diff --git a/.gitignore b/.gitignore
index 1f6580a7e7ebe22e5d7259ef49dfb33ad0fe338e..2bcbcdda3dd15b98c8f1fadc3bcf844f86cf7dad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,3 +41,12 @@ coverage.xml
 # Sphinx documentation
 docs/_build/
 .vscode/settings.json
+
+# VS Code
+.vscode/
+
+# symlink to env
+env
+
+# nose
+.noseids
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3e20b46d5b2c9e7b7153e2af6c9bcad183335306
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# ckanext-odsh
+Diese CKAN-Extension enthält die wichtigsten Features und das Layout für das Tranzparenzportal Schleswig-Holstein.
+Sie ist eine Weiterentwicklung der gleichnamigen Extension, die im Zuge der Entwicklung des Open Data Portals Schleswig-Holstein entwickelt wurde.
+
+## Branches
+### master
+Dieser Branch enthält den aktuell auf den Stage- bzw. Prod-Servern laufenden Code.
+
+### dev
+Dieser Branch enthält den aktuellsten Stand mit allen fertig entwickelten Features.
+
+### andere Branches
+Für die Entwicklung neuer Features soll jeweils ein eigener Branch vom dev-Branch abgezweigt werden. Für den Branch soll ein sprechender Name gewählt werden.
+
+## Deployment auf Produktivsystem
+Das Deployment auf das Produktivsystem geschieht über Ansible. Die dafür benötigten Skripte befinden sich im Repository `tpsh_deploy`. 
+
+## Manuelle Installation
+
+
+## Konfiguration
+Die Extension benötigt Konfigurationsparameter in der CKAN-Konfigurationsdatei (z.B. `production.ini`). Die korrekten Parameter für das Produktivsystem befinden sich im Repository `tpsh_deploy` unter `resources/production.ini`. Folgende Parameter sollten für Enwicklungssysteme geändert werden:
+
+| Parameter                             | Erläuterung                                                   | Wert für Entwicklungssysteme              |
+|---------------------------------------|---------------------------------------------------------------|-------------------------------------------|
+| ckanext.odsh.use_matomo               | `true` schaltet das matomo-Tracking ein.                      | `false`                                   |
+| ckanext.odsh.skip_icap_virus_check    | `false` schaltet den Virus-Check ein.                         | `true`                                    |
+| ckanext.odsh.showtestbanner           | `true` schaltet das Banner "Testsystem" ein, Muss `false` für Production-Server sein. | -                 |
\ No newline at end of file
diff --git a/ckanext/odsh/collection/__init__.py b/ckanext/odsh/collection/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ckanext/odsh/collection/controller.py b/ckanext/odsh/collection/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..5b049563195ed12b5a1b4f008b38fd95fc3af612
--- /dev/null
+++ b/ckanext/odsh/collection/controller.py
@@ -0,0 +1,38 @@
+from ckan.lib.helpers import is_url, url_for
+import ckan.plugins.toolkit as toolkit
+from ckan.controllers.package import PackageController
+from helpers import get_latest_resources_for_type, get_latest_dataset
+
+
+
+class LatestDatasetController(PackageController):
+    
+    def latest_dataset(self, id):
+        latest_dataset= get_latest_dataset(id)
+        toolkit.redirect_to(controller='package', action='read', id=latest_dataset)
+
+class LatestRecourcesController(PackageController):
+    
+    def latest_resource(self, id, type):
+        latest_resources = get_latest_resources_for_type(id, type)
+        if latest_resources is None:
+            abort(404)
+        url_type = latest_resources.get('url_type')
+        if url_type is None:
+            resource_url = latest_resources.get('url')
+            toolkit.redirect_to(resource_url)
+        if url_type == 'upload':
+            download_package_id = latest_resources.get('package_id')
+            download_resource_id = latest_resources.get('id')
+            pre_resource_url = latest_resources.get('url')
+            if is_url(pre_resource_url):
+                url_resource = pre_resource_url
+            else:
+                url_resource = url_for(controller='package',
+                                    action='resource_download',
+                                    id=download_package_id,
+                                    resource_id=download_resource_id,
+                                    filename=pre_resource_url,
+                                    qualified = True)
+            toolkit.redirect_to(url_resource)
+        abort(404)
\ No newline at end of file
diff --git a/ckanext/odsh/collection/helpers.py b/ckanext/odsh/collection/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec0f7dcbf05e7c37afa5491501e9d54f071f11d8
--- /dev/null
+++ b/ckanext/odsh/collection/helpers.py
@@ -0,0 +1,161 @@
+from string import lower
+
+import ckan.lib.helpers as helpers
+import ckan.model as model
+import ckan.plugins.toolkit as toolkit
+
+
+
+#routine functions
+
+def get_package_dict(name):
+    return model.Package.get(name).as_dict()
+
+def get_relationships(name):
+    collection_dict = get_package_dict(name)
+    return collection_dict.get('relationships')
+
+def get_all_datasets_belonging_to_collection(collection_name):
+    list_rel_collection = get_relationships(collection_name)
+    name_list = list()
+    for item in list_rel_collection:
+        item_object = item.get('object') 
+        name_list.append(item_object)
+    return name_list
+
+#for mapping latest resources and latest dataset
+
+def get_latest_dataset(collection_name):
+    collection_list_relationships = get_all_datasets_belonging_to_collection(collection_name)
+    latest_issued = latest_name = None
+    for item in collection_list_relationships:
+        item_pkt_dict =  get_package_dict(item)
+        if helpers.check_access('package_show', item_pkt_dict):
+            item_issued = item_pkt_dict.get('extras').get('issued')
+            if latest_issued < item_issued or (latest_issued == item_issued and latest_name < item):
+                latest_name=item
+                latest_issued=item_issued
+    return latest_name
+
+
+def is_latest_resources(resource_format, type, resource_created,latest_created, resource_id, latest_id):
+    if lower(resource_format) == lower(type):
+        return (resource_created > latest_created or (resource_created == latest_created and resource_id > latest_id))
+    else:
+        return False
+
+def get_latest_resources_for_type(collection_name, type):
+    latest_dataset_name = get_latest_dataset(collection_name)
+    latest_dataset = get_package_dict(latest_dataset_name)
+    resource_list = latest_dataset.get('resources')
+    latest_resource = latest_created = latest_id = None
+    for resource in resource_list:
+        resource_format = resource.get('format')
+        resource_created = resource.get('created')
+        resource_id = resource.get('id')
+        if is_latest_resources(resource_format, type, resource_created, latest_created, resource_id, latest_id):
+            latest_id=resource_id
+            latest_created=resource_created
+            latest_resource=resource
+    return latest_resource
+
+#for predecessor and successor
+
+
+
+def get_collection_name_by_dataset(dataset_name):
+    list_rel_dataset = get_relationships(dataset_name)
+    if len(list_rel_dataset):        
+        return list_rel_dataset[0]['object']
+
+def get_collection_title_by_dataset(pkg_dict_dataset):
+    dataset_name = pkg_dict_dataset.get('name')
+    collection_name = get_collection_name_by_dataset(dataset_name)
+    if not collection_name:
+        return None
+    context = None
+    pkg_dict_collection = toolkit.get_action('package_show')(context, {'id': collection_name})
+    if not pkg_dict_collection:
+        return None
+    title_collection = pkg_dict_collection.get('title')
+    return title_collection
+
+def get_all_datasets_belonging_to_collection_by_dataset(dataset_name):
+    collection_name = get_collection_name_by_dataset(dataset_name)
+    if collection_name: 
+        return get_all_datasets_belonging_to_collection(collection_name)
+    return []
+
+def _get_siblings_dicts_with_access(pkg_dict):
+    dataset_name = pkg_dict.get('name')
+    list_of_siblings = get_all_datasets_belonging_to_collection_by_dataset(dataset_name)
+    n_siblings = len(list_of_siblings)
+    if n_siblings>0:
+        siblings_dicts = [get_package_dict(name) for name in list_of_siblings]
+        user_has_access = lambda pkg_dict:helpers.check_access('package_show', pkg_dict)
+        siblings_dicts_with_access = filter(user_has_access, siblings_dicts)
+        return siblings_dicts_with_access
+    return None
+
+def _sort_siblings_by_name_and_date(siblings_dicts):
+    '''
+    sort by name first and then by date to have a fallback if dates are the same
+    '''
+    _get_name = lambda pkg_dict:pkg_dict.get('name')
+    _get_issued = lambda pkg_dict:pkg_dict.get('extras').get('issued')
+    siblings_dicts_sorted_by_name = sorted(siblings_dicts, key=_get_name)
+    siblings_dicts_sorted_by_date_issued = sorted(siblings_dicts_sorted_by_name, key=_get_issued)
+    return siblings_dicts_sorted_by_date_issued
+
+def get_successor_and_predecessor_dataset(pkg_dict):
+    dataset_name = pkg_dict.get('name')
+    siblings_dicts_with_access = _get_siblings_dicts_with_access(pkg_dict)
+    if siblings_dicts_with_access:
+        n_siblings = len(siblings_dicts_with_access)
+        siblings_dicts_sorted_by_date_issued = _sort_siblings_by_name_and_date(siblings_dicts_with_access)
+        siblings_names_sorted_by_date_issued = [d['name'] for d in siblings_dicts_sorted_by_date_issued]
+        id_current_dataset = siblings_names_sorted_by_date_issued.index(dataset_name)
+        predecessor_name = (
+            siblings_names_sorted_by_date_issued[id_current_dataset-1] if (id_current_dataset > 0) 
+            else None
+        )
+        successor_name = (
+            siblings_names_sorted_by_date_issued[id_current_dataset+1] if (id_current_dataset < n_siblings-1) 
+            else None
+        )
+    else:
+        predecessor_name, successor_name = None, None
+    return successor_name, predecessor_name
+
+def get_successor_and_predecessor_urls(pkg_dict):
+    successor_name, predecessor_name = get_successor_and_predecessor_dataset(pkg_dict)
+    successor_url, predecessor_url = (
+        helpers.url_for(controller='package', action='read', id=name)
+        if name is not None
+        else None
+        for name in (successor_name, predecessor_name)
+    )
+    return successor_url, predecessor_url
+
+def get_successor(pkg_dict):
+    successor_and_predecessor = get_successor_and_predecessor_urls(pkg_dict)
+    return successor_and_predecessor[0]
+    
+def get_predecessor(pkg_dict):
+    successor_and_predecessor = get_successor_and_predecessor_urls(pkg_dict)
+    return successor_and_predecessor[1]
+
+#link to latest collection member
+def latest_collection_member_persistent_link(pkg_dict):
+    dataset_name = pkg_dict.get('name')
+    collection_name = get_collection_name_by_dataset(
+        dataset_name=dataset_name
+    )
+    if not collection_name:
+        return None
+    url = helpers.url_for(
+        controller='ckanext.odsh.collection.controller:LatestDatasetController', 
+        action='latest',
+        id=collection_name
+    )
+    return url
\ No newline at end of file
diff --git a/ckanext/odsh/collection/plugin.py b/ckanext/odsh/collection/plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ebcefc1af2c164045af7e861856858644885df9
--- /dev/null
+++ b/ckanext/odsh/collection/plugin.py
@@ -0,0 +1,60 @@
+
+from ckan.lib.plugins import DefaultTranslation, DefaultDatasetForm
+import ckan.plugins as plugins 
+import helpers as collection_helpers
+from routes.mapper import SubMapper
+
+class CollectionsPlugin(plugins.SingletonPlugin, DefaultDatasetForm):
+    plugins.implements(plugins.IDatasetForm, inherit=True)
+    plugins.implements(plugins.IRoutes, inherit=True)
+    plugins.implements(plugins.ITemplateHelpers)
+
+
+    # IDataSetForm
+    def package_types(self):
+        return ('collection', )
+    
+    def is_fallback(self):
+        return False
+
+    
+    # IRoutes    
+    def before_map(self, map):
+
+        map.connect(
+            '/collection/{id}/aktuell',
+            controller='ckanext.odsh.collection.controller:LatestDatasetController',
+            action='latest_dataset'
+        )
+
+        map.connect(
+            '/collection/{id}/aktuell.{type}',
+            controller='ckanext.odsh.collection.controller:LatestRecourcesController',
+            action='latest_resource'
+        )
+
+        with SubMapper(
+            map, 
+            controller='ckanext.odsh.collection.controller:LatestDatasetController', 
+            path_prefix='/collection/'
+        ) as m:
+            m.connect('latest', '{id}/aktuell', action='latest')
+            m.connect('latest_resource', '{id}/aktuell.{type}', action='latest_resource')  
+        return map
+
+    def after_map(self, map):
+        return map
+
+    
+    # ITemplateHelpers
+    def get_helpers(self):
+        # Template helper function names should begin with the name of the
+        # extension they belong to, to avoid clashing with functions from
+        # other extensions.
+
+        return {
+            'collection_get_successor': collection_helpers.get_successor,
+            'collection_get_predecessor': collection_helpers.get_predecessor,
+            'collection_get_latest_member':collection_helpers.latest_collection_member_persistent_link,
+            'collection_get_title': collection_helpers.get_collection_title_by_dataset,
+        }
diff --git a/ckanext/odsh/fanstatic/datepicker.css b/ckanext/odsh/fanstatic/datepicker.css
index c2a0a0a74d66a307be8fea00105c8f66079454d2..408f3afa97f78e22ce09b9173ca376589209f20d 100644
--- a/ckanext/odsh/fanstatic/datepicker.css
+++ b/ckanext/odsh/fanstatic/datepicker.css
@@ -3,308 +3,5 @@
  *
  * Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
  */
- .datepicker{
-    padding:4px;
-    -webkit-border-radius:4px;
-    -moz-border-radius:4px;
-    border-radius:4px;
-    direction:ltr
-}
-.datepicker-inline{
-    width:220px
-}
-.datepicker-rtl{
-    direction:rtl
-}
-.datepicker-rtl.dropdown-menu{
-    left:auto
-}
-.datepicker-rtl table tr td span{
-    float:right
-}
-.datepicker-dropdown{
-    top:0;
-    left:0
-}
-.datepicker-dropdown:before{
-    content:'';
-    display:inline-block;
-    border-left:7px solid transparent;
-    border-right:7px solid transparent;
-    border-bottom:7px solid #999;
-    border-top:0;
-    border-bottom-color:rgba(0,0,0,.2);
-    position:absolute
-}
-.datepicker-dropdown:after{
-    content:'';
-    display:inline-block;
-    border-left:6px solid transparent;
-    border-right:6px solid transparent;
-    border-bottom:6px solid #fff;
-    border-top:0;
-    position:absolute
-}
-.datepicker-dropdown.datepicker-orient-left:before{
-    left:6px
-}
-.datepicker-dropdown.datepicker-orient-left:after{
-    left:7px
-}
-.datepicker-dropdown.datepicker-orient-right:before{
-    right:6px
-}
-.datepicker-dropdown.datepicker-orient-right:after{
-    right:7px
-}
-.datepicker-dropdown.datepicker-orient-bottom:before{
-    top:-7px
-}
-.datepicker-dropdown.datepicker-orient-bottom:after{
-    top:-6px
-}
-.datepicker-dropdown.datepicker-orient-top:before{
-    bottom:-7px;
-    border-bottom:0;
-    border-top:7px solid #999
-}
-.datepicker-dropdown.datepicker-orient-top:after{
-    bottom:-6px;
-    border-bottom:0;
-    border-top:6px solid #fff
-}
-.datepicker table{
-    margin:0;
-    -webkit-touch-callout:none;
-    -webkit-user-select:none;
-    -khtml-user-select:none;
-    -moz-user-select:none;
-    -ms-user-select:none;
-    user-select:none
-}
-.datepicker td,.datepicker th{
-    text-align:center;
-    width:20px;
-    height:20px;
-    -webkit-border-radius:4px;
-    -moz-border-radius:4px;
-    border-radius:4px;
-    border:none
-}
-.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{
-    background-color:transparent
-}
-.datepicker table tr td.day.focused,.datepicker table tr td.day:hover{
-    background:#eee;
-    cursor:pointer
-}
-.datepicker table tr td.new,.datepicker table tr td.old{
-    color:#999
-}
-.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{
-    background:0 0;
-    color:#999;
-    cursor:default
-}
-.datepicker table tr td.highlighted{
-    background:#d9edf7;
-    border-radius:0
-}
-.datepicker table tr td.today,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today:hover{
-    background-color:#fde19a;
-    background-image:-moz-linear-gradient(to bottom,#fdd49a,#fdf59a);
-    background-image:-ms-linear-gradient(to bottom,#fdd49a,#fdf59a);
-    background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));
-    background-image:-webkit-linear-gradient(to bottom,#fdd49a,#fdf59a);
-    background-image:-o-linear-gradient(to bottom,#fdd49a,#fdf59a);
-    background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);
-    background-repeat:repeat-x;
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
-    border-color:#fdf59a #fdf59a #fbed50;
-    border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
-    filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
-    color:#000
-}
-.datepicker table tr td.today.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today.disabled:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today:active,.datepicker table tr td.today:hover,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today:hover:active,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today[disabled]{
-    background-color:#fdf59a
-}
-.datepicker table tr td.today.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today:active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover:active{
-    background-color:#fbf069\9
-}
-.datepicker table tr td.today:hover:hover{
-    color:#000
-}
-.datepicker table tr td.today.active:hover{
-    color:#fff
-}
-.datepicker table tr td.range,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover,.datepicker table tr td.range:hover{
-    background:#eee;
-    -webkit-border-radius:0;
-    -moz-border-radius:0;
-    border-radius:0
-}
-.datepicker table tr td.range.today,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today:hover{
-    background-color:#f3d17a;
-    background-image:-moz-linear-gradient(to bottom,#f3c17a,#f3e97a);
-    background-image:-ms-linear-gradient(to bottom,#f3c17a,#f3e97a);
-    background-image:-webkit-gradient(linear,0 0,0 100%,from(#f3c17a),to(#f3e97a));
-    background-image:-webkit-linear-gradient(to bottom,#f3c17a,#f3e97a);
-    background-image:-o-linear-gradient(to bottom,#f3c17a,#f3e97a);
-    background-image:linear-gradient(to bottom,#f3c17a,#f3e97a);
-    background-repeat:repeat-x;
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
-    border-color:#f3e97a #f3e97a #edde34;
-    border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
-    filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
-    -webkit-border-radius:0;
-    -moz-border-radius:0;
-    border-radius:0
-}
-.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today.disabled:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today[disabled]{
-    background-color:#f3e97a
-}
-.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover:active{
-    background-color:#efe24b\9
-}
-.datepicker table tr td.selected,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected:hover{
-    background-color:#9e9e9e;
-    background-image:-moz-linear-gradient(to bottom,#b3b3b3,grey);
-    background-image:-ms-linear-gradient(to bottom,#b3b3b3,grey);
-    background-image:-webkit-gradient(linear,0 0,0 100%,from(#b3b3b3),to(grey));
-    background-image:-webkit-linear-gradient(to bottom,#b3b3b3,grey);
-    background-image:-o-linear-gradient(to bottom,#b3b3b3,grey);
-    background-image:linear-gradient(to bottom,#b3b3b3,grey);
-    background-repeat:repeat-x;
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
-    border-color:grey grey #595959;
-    border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
-    filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
-    color:#fff;
-    text-shadow:0 -1px 0 rgba(0,0,0,.25)
-}
-.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected.disabled:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected[disabled]{
-    background-color:grey
-}
-.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover:active{
-    background-color:#666\9
-}
-.datepicker table tr td.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active:hover{
-    background-color:#006dcc;
-    background-image:-moz-linear-gradient(to bottom,#08c,#04c);
-    background-image:-ms-linear-gradient(to bottom,#08c,#04c);
-    background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));
-    background-image:-webkit-linear-gradient(to bottom,#08c,#04c);
-    background-image:-o-linear-gradient(to bottom,#08c,#04c);
-    background-image:linear-gradient(to bottom,#08c,#04c);
-    background-repeat:repeat-x;
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);
-    border-color:#04c #04c #002a80;
-    border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
-    filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
-    color:#fff;
-    text-shadow:0 -1px 0 rgba(0,0,0,.25)
-}
-.datepicker table tr td.active.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active.disabled:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active:active,.datepicker table tr td.active:hover,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active:hover:active,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active[disabled]{
-    background-color:#04c
-}
-.datepicker table tr td.active.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active:active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover:active{
-    background-color:#039\9
-}
-.datepicker table tr td span{
-    display:block;
-    width:23%;
-    height:54px;
-    line-height:54px;
-    float:left;
-    margin:1%;
-    cursor:pointer;
-    -webkit-border-radius:4px;
-    -moz-border-radius:4px;
-    border-radius:4px
-}
-.datepicker table tr td span.focused,.datepicker table tr td span:hover{
-    background:#eee
-}
-.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{
-    background:0 0;
-    color:#999;
-    cursor:default
-}
-.datepicker table tr td span.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active:hover{
-    background-color:#006dcc;
-    background-image:-moz-linear-gradient(to bottom,#08c,#04c);
-    background-image:-ms-linear-gradient(to bottom,#08c,#04c);
-    background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));
-    background-image:-webkit-linear-gradient(to bottom,#08c,#04c);
-    background-image:-o-linear-gradient(to bottom,#08c,#04c);
-    background-image:linear-gradient(to bottom,#08c,#04c);
-    background-repeat:repeat-x;
-    filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);
-    border-color:#04c #04c #002a80;
-    border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
-    filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);
-    color:#fff;
-    text-shadow:0 -1px 0 rgba(0,0,0,.25)
-}
-.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active.disabled:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active[disabled]{
-    background-color:#04c
-}
-.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover:active{
-    background-color:#039\9
-}
-.datepicker table tr td span.new,.datepicker table tr td span.old{
-    color:#999
-}
-.datepicker .datepicker-switch{
-    width:145px
-}
-.datepicker .datepicker-switch,.datepicker .next,.datepicker .prev,.datepicker tfoot tr th{
-    cursor:pointer
-}
-.datepicker .datepicker-switch:hover,.datepicker .next:hover,.datepicker .prev:hover,.datepicker tfoot tr th:hover{
-    background:#eee
-}
-.datepicker .next.disabled,.datepicker .prev.disabled{
-    visibility:hidden
-}
-.datepicker .cw{
-    font-size:10px;
-    width:12px;
-    padding:0 2px 0 5px;
-    vertical-align:middle
-}
-.input-append.date .add-on,.input-prepend.date .add-on{
-    cursor:pointer
-}
-.input-append.date .add-on i,.input-prepend.date .add-on i{
-    margin-top:3px
-}
-.input-daterange input{
-    text-align:center
-}
-.input-daterange input:first-child{
-    -webkit-border-radius:3px 0 0 3px;
-    -moz-border-radius:3px 0 0 3px;
-    border-radius:3px 0 0 3px
-}
-.input-daterange input:last-child{
-    -webkit-border-radius:0 3px 3px 0;
-    -moz-border-radius:0 3px 3px 0;
-    border-radius:0 3px 3px 0
-}
-.input-daterange .add-on{
-    display:inline-block;
-    width:auto;
-    min-width:16px;
-    height:18px;
-    padding:4px 5px;
-    font-weight:400;
-    line-height:18px;
-    text-align:center;
-    text-shadow:0 1px 0 #fff;
-    vertical-align:middle;
-    background-color:#eee;
-    border:1px solid #ccc;
-    margin-left:-5px;
-    margin-right:-5px
-}
\ No newline at end of file
+
+.datepicker{padding:4px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;direction:ltr}.datepicker-inline{width:220px}.datepicker-rtl{direction:rtl}.datepicker-rtl.dropdown-menu{left:auto}.datepicker-rtl table tr td span{float:right}.datepicker-dropdown{top:0;left:0}.datepicker-dropdown:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #999;border-top:0;border-bottom-color:rgba(0,0,0,.2);position:absolute}.datepicker-dropdown:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;border-top:0;position:absolute}.datepicker-dropdown.datepicker-orient-left:before{left:6px}.datepicker-dropdown.datepicker-orient-left:after{left:7px}.datepicker-dropdown.datepicker-orient-right:before{right:6px}.datepicker-dropdown.datepicker-orient-right:after{right:7px}.datepicker-dropdown.datepicker-orient-bottom:before{top:-7px}.datepicker-dropdown.datepicker-orient-bottom:after{top:-6px}.datepicker-dropdown.datepicker-orient-top:before{bottom:-7px;border-bottom:0;border-top:7px solid #999}.datepicker-dropdown.datepicker-orient-top:after{bottom:-6px;border-bottom:0;border-top:6px solid #fff}.datepicker table{margin:0;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker td,.datepicker th{text-align:center;width:20px;height:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:none}.table-striped .datepicker table tr td,.table-striped .datepicker table tr th{background-color:transparent}.datepicker table tr td.day.focused,.datepicker table tr td.day:hover{background:#eee;cursor:pointer}.datepicker table tr td.new,.datepicker table tr td.old{color:#999}.datepicker table tr td.disabled,.datepicker table tr td.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td.highlighted{background:#d9edf7;border-radius:0}.datepicker table tr td.today,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today:hover{background-color:#fde19a;background-image:-moz-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-ms-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fdd49a),to(#fdf59a));background-image:-webkit-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:-o-linear-gradient(to bottom,#fdd49a,#fdf59a);background-image:linear-gradient(to bottom,#fdd49a,#fdf59a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color:#fdf59a #fdf59a #fbed50;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#000}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled.disabled,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover.disabled,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today.disabled:hover:hover,.datepicker table tr td.today.disabled:hover[disabled],.datepicker table tr td.today.disabled[disabled],.datepicker table tr td.today:active,.datepicker table tr td.today:hover,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover.disabled,.datepicker table tr td.today:hover:active,.datepicker table tr td.today:hover:hover,.datepicker table tr td.today:hover[disabled],.datepicker table tr td.today[disabled]{background-color:#fdf59a}.datepicker table tr td.today.active,.datepicker table tr td.today.disabled.active,.datepicker table tr td.today.disabled:active,.datepicker table tr td.today.disabled:hover.active,.datepicker table tr td.today.disabled:hover:active,.datepicker table tr td.today:active,.datepicker table tr td.today:hover.active,.datepicker table tr td.today:hover:active{background-color:#fbf069\9}.datepicker table tr td.today:hover:hover{color:#000}.datepicker table tr td.today.active:hover{color:#fff}.datepicker table tr td.range,.datepicker table tr td.range.disabled,.datepicker table tr td.range.disabled:hover,.datepicker table tr td.range:hover{background:#eee;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today:hover{background-color:#f3d17a;background-image:-moz-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-ms-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f3c17a),to(#f3e97a));background-image:-webkit-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:-o-linear-gradient(to bottom,#f3c17a,#f3e97a);background-image:linear-gradient(to bottom,#f3c17a,#f3e97a);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);border-color:#f3e97a #f3e97a #edde34;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled.disabled,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover.disabled,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today.disabled:hover:hover,.datepicker table tr td.range.today.disabled:hover[disabled],.datepicker table tr td.range.today.disabled[disabled],.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover.disabled,.datepicker table tr td.range.today:hover:active,.datepicker table tr td.range.today:hover:hover,.datepicker table tr td.range.today:hover[disabled],.datepicker table tr td.range.today[disabled]{background-color:#f3e97a}.datepicker table tr td.range.today.active,.datepicker table tr td.range.today.disabled.active,.datepicker table tr td.range.today.disabled:active,.datepicker table tr td.range.today.disabled:hover.active,.datepicker table tr td.range.today.disabled:hover:active,.datepicker table tr td.range.today:active,.datepicker table tr td.range.today:hover.active,.datepicker table tr td.range.today:hover:active{background-color:#efe24b\9}.datepicker table tr td.selected,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected:hover{background-color:#9e9e9e;background-image:-moz-linear-gradient(to bottom,#b3b3b3,grey);background-image:-ms-linear-gradient(to bottom,#b3b3b3,grey);background-image:-webkit-gradient(linear,0 0,0 100%,from(#b3b3b3),to(grey));background-image:-webkit-linear-gradient(to bottom,#b3b3b3,grey);background-image:-o-linear-gradient(to bottom,#b3b3b3,grey);background-image:linear-gradient(to bottom,#b3b3b3,grey);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);border-color:grey grey #595959;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled.disabled,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover.disabled,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected.disabled:hover:hover,.datepicker table tr td.selected.disabled:hover[disabled],.datepicker table tr td.selected.disabled[disabled],.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover.disabled,.datepicker table tr td.selected:hover:active,.datepicker table tr td.selected:hover:hover,.datepicker table tr td.selected:hover[disabled],.datepicker table tr td.selected[disabled]{background-color:grey}.datepicker table tr td.selected.active,.datepicker table tr td.selected.disabled.active,.datepicker table tr td.selected.disabled:active,.datepicker table tr td.selected.disabled:hover.active,.datepicker table tr td.selected.disabled:hover:active,.datepicker table tr td.selected:active,.datepicker table tr td.selected:hover.active,.datepicker table tr td.selected:hover:active{background-color:#666\9}.datepicker table tr td.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active:hover{background-color:#006dcc;background-image:-moz-linear-gradient(to bottom,#08c,#04c);background-image:-ms-linear-gradient(to bottom,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(to bottom,#08c,#04c);background-image:-o-linear-gradient(to bottom,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled.disabled,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover.disabled,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active.disabled:hover:hover,.datepicker table tr td.active.disabled:hover[disabled],.datepicker table tr td.active.disabled[disabled],.datepicker table tr td.active:active,.datepicker table tr td.active:hover,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover.disabled,.datepicker table tr td.active:hover:active,.datepicker table tr td.active:hover:hover,.datepicker table tr td.active:hover[disabled],.datepicker table tr td.active[disabled]{background-color:#04c}.datepicker table tr td.active.active,.datepicker table tr td.active.disabled.active,.datepicker table tr td.active.disabled:active,.datepicker table tr td.active.disabled:hover.active,.datepicker table tr td.active.disabled:hover:active,.datepicker table tr td.active:active,.datepicker table tr td.active:hover.active,.datepicker table tr td.active:hover:active{background-color:#039\9}.datepicker table tr td span{display:block;width:23%;height:54px;line-height:54px;float:left;margin:1%;cursor:pointer;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.datepicker table tr td span.focused,.datepicker table tr td span:hover{background:#eee}.datepicker table tr td span.disabled,.datepicker table tr td span.disabled:hover{background:0 0;color:#999;cursor:default}.datepicker table tr td span.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active:hover{background-color:#006dcc;background-image:-moz-linear-gradient(to bottom,#08c,#04c);background-image:-ms-linear-gradient(to bottom,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(to bottom,#08c,#04c);background-image:-o-linear-gradient(to bottom,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#08c', endColorstr='#0044cc', GradientType=0);border-color:#04c #04c #002a80;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,.25)}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled.disabled,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover.disabled,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active.disabled:hover:hover,.datepicker table tr td span.active.disabled:hover[disabled],.datepicker table tr td span.active.disabled[disabled],.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover.disabled,.datepicker table tr td span.active:hover:active,.datepicker table tr td span.active:hover:hover,.datepicker table tr td span.active:hover[disabled],.datepicker table tr td span.active[disabled]{background-color:#04c}.datepicker table tr td span.active.active,.datepicker table tr td span.active.disabled.active,.datepicker table tr td span.active.disabled:active,.datepicker table tr td span.active.disabled:hover.active,.datepicker table tr td span.active.disabled:hover:active,.datepicker table tr td span.active:active,.datepicker table tr td span.active:hover.active,.datepicker table tr td span.active:hover:active{background-color:#039\9}.datepicker table tr td span.new,.datepicker table tr td span.old{color:#999}.datepicker .datepicker-switch{width:145px}.datepicker .datepicker-switch,.datepicker .next,.datepicker .prev,.datepicker tfoot tr th{cursor:pointer}.datepicker .datepicker-switch:hover,.datepicker .next:hover,.datepicker .prev:hover,.datepicker tfoot tr th:hover{background:#eee}.datepicker .next.disabled,.datepicker .prev.disabled{visibility:hidden}.datepicker .cw{font-size:10px;width:12px;padding:0 2px 0 5px;vertical-align:middle}.input-append.date .add-on,.input-prepend.date .add-on{cursor:pointer}.input-append.date .add-on i,.input-prepend.date .add-on i{margin-top:3px}.input-daterange input{text-align:center}.input-daterange input:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px}.input-daterange input:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0}.input-daterange .add-on{display:inline-block;width:auto;min-width:16px;height:18px;padding:4px 5px;font-weight:400;line-height:18px;text-align:center;text-shadow:0 1px 0 #fff;vertical-align:middle;background-color:#eee;border:1px solid #ccc;margin-left:-5px;margin-right:-5px}
\ No newline at end of file
diff --git a/ckanext/odsh/fanstatic/odsh.js b/ckanext/odsh/fanstatic/odsh.js
index b3081447568642b2391fd02b4bdd1713ce456f31..97cd432650dbdf5926c53649449d47eab09ced7b 100644
--- a/ckanext/odsh/fanstatic/odsh.js
+++ b/ckanext/odsh/fanstatic/odsh.js
@@ -2,7 +2,7 @@ $(document).ready(function ()
 {
     $('.mylabel').click(function ()
     {
-        window.location = $(this).siblings('a').attr('href');
+        window.location = $(this).siblings('label').children('a').attr('href');
     });
 
     let search = function (score)
diff --git a/ckanext/odsh/fanstatic/tpsh_toggle_menu.js b/ckanext/odsh/fanstatic/tpsh_toggle_menu.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a8a8c82d0f4849ca49b8bf525247cca7cdbf755
--- /dev/null
+++ b/ckanext/odsh/fanstatic/tpsh_toggle_menu.js
@@ -0,0 +1,21 @@
+"use strict";
+
+ckan.module('tpsh_toggle_menu', function ($) {
+    return {
+        initialize: function () {
+            $.proxyAll(this, /_on/);
+            this.el.on('click', this._onClick);
+        },
+        
+        _onClick: function(event) {
+            var element = $("body");
+            var className = "menu-modal"
+            if (element.hasClass(className)){
+                element.removeClass(className)
+            }
+            else {
+                element.addClass(className);
+            }
+        }
+    };
+});
\ No newline at end of file
diff --git a/ckanext/odsh/fanstatic/tpsh_validate_password.js b/ckanext/odsh/fanstatic/tpsh_validate_password.js
new file mode 100644
index 0000000000000000000000000000000000000000..f0f8f71b55e4f6a2cd9e52c6a39b09ab302d2dab
--- /dev/null
+++ b/ckanext/odsh/fanstatic/tpsh_validate_password.js
@@ -0,0 +1,71 @@
+"use strict";
+
+function isPasswordValid(password) {
+    if (password.length == 0) return true;
+    var minimumLength = 8;
+    var isValid = 
+        (password.length >= minimumLength) &&
+        (atLeastOneUpperCaseLetter(password)) &&
+        (atLeastOneLowerCaseLetter(password)) &&
+        (atLeastOneNoneLetter(password));
+    return isValid
+
+    function atLeastOneUpperCaseLetter(password) {
+        return (password !== password.toLowerCase())
+    }
+
+    function atLeastOneLowerCaseLetter(password) {
+        return (password !== password.toUpperCase())
+    }
+
+    function atLeastOneNoneLetter(password) {
+        return /[\W\d_]/.test(password)
+    }
+}
+
+
+function showPasswordStatus(isValid, inputElement) {
+    if (isValid) {
+        messageText = '';
+    } else {
+        messageText = 'Passwörter müssen länger als 8 Zeichen sein und Großbuchstaben, Kleinbuchstaben und andere Zeichen enthalten.'
+    }
+    get_error_element(inputElement).innerHTML = messageText;
+
+    function get_error_element(inputElement) {
+        // assumes that there is an element after input_element's parent that
+        // contains a class "inline-error"
+        var currentNode = inputElement.parentNode
+        do {
+            currentNode = currentNode.nextElementSibling;
+        } while (
+            (currentNode !== null) &&
+            !(currentNode.classList.contains('inline-error'))
+        )
+        return currentNode
+    }
+}
+
+
+function setSubmitButtonState(isPasswordValid) {
+    var submitButton = document.getElementsByName('save')[0];
+    submitButton.disabled = !isPasswordValid;
+}
+
+
+ckan.module('tpsh_validate_password', function ($) {
+    return {
+        initialize: function () {
+            $.proxyAll(this, /_on/);
+            this.el.on('input', this._onChange);
+        },
+        
+        _onChange: function(event) {
+            var inputElement = event.target;
+            var newPassword = inputElement.value;
+            var isValid = isPasswordValid(newPassword);
+            showPasswordStatus(isValid, inputElement);
+            setSubmitButtonState(isValid);
+        }
+    };
+});
\ No newline at end of file
diff --git a/ckanext/odsh/harvesters/kielharvester.py b/ckanext/odsh/harvesters/kielharvester.py
index 55a7317e8bd51ddbb5b411545ee111fe1f9d1694..c1dfb652a9a2703b4dbd579cb38413298fad5298 100755
--- a/ckanext/odsh/harvesters/kielharvester.py
+++ b/ckanext/odsh/harvesters/kielharvester.py
@@ -112,7 +112,7 @@ class KielHarvester(ODSHBaseHarvester):
                 context.copy(), {'id': harvest_object.source.id})
             package_dict['owner_org'] = source_dataset.get('owner_org')
 
-            if package_dict['type'] == 'datensatz':
+            if package_dict['type'] in ('datensatz', 'dokument', 'document'):
                 package_dict['type'] = 'dataset'
             package_dict['id'] = harvest_object.guid
 
diff --git a/ckanext/odsh/harvesters/number_dcat_de_hamburg.json b/ckanext/odsh/harvesters/number_dcat_de_hamburg.json
index 8ccefed472c2594f5ef89cf4d0e639712b4ed8be..51c0efe1abd42364f81a7ce47dfdb6ad1e13d947 100644
--- a/ckanext/odsh/harvesters/number_dcat_de_hamburg.json
+++ b/ckanext/odsh/harvesters/number_dcat_de_hamburg.json
@@ -28,7 +28,7 @@
 "32" : ["soci"],
 "33" : ["soci"],
 "34" : ["soci"],
-"35" : ["regi"],
+"35" : ["econ","regi","agri"],
 "36" : ["educ"],
 "37" : ["educ"],
 "38" : ["educ"],
@@ -64,16 +64,16 @@
 "68" : ["econ"],
 "69" : ["econ"],
 "70" : ["econ"],
-"71" : ["educ"],
+"71" : ["econ"],
 "72" : ["econ"],
 "73" : ["econ"],
-"74" : ["econ"],
+"74" : ["econ","intr"],
 "75" : ["econ"],
 "76" : ["econ"],
 "77" : ["econ"],
 "78" : ["econ"],
 "79" : ["gove"],
-"80" : ["gove"],
+"80" : ["gove","econ"],
 "81" : ["gove"],
 "82" : ["gove"],
 "83" : ["envi"],
@@ -91,7 +91,9 @@
 "95" : ["educ"],
 "97" : ["gove"],
 "98" : ["gove"],
-"104" : ["agri"],
+"100" : ["gove","intr"],
+"101" : ["gove"],
+"104" : ["gove","regi"],
 "105" : ["regi"],
 "106" : ["regi"],
 "108" : ["econ"],
@@ -101,7 +103,7 @@
 "115" : ["agri"],
 "116" : ["soci"],
 "117" : ["econ"],
-"122" : ["econ"],
+"122" : ["gove","intr"],
 "124" : ["econ"],
 "127" : ["agri"],
 "128" : ["agri"],
diff --git a/ckanext/odsh/harvesters/statistikamtnordharvester.py b/ckanext/odsh/harvesters/statistikamtnordharvester.py
index 50a082a66b9796a6d3c5c93f89644d851b93d486..64ffbc985f33282bca88dce18e7310e539576df8 100755
--- a/ckanext/odsh/harvesters/statistikamtnordharvester.py
+++ b/ckanext/odsh/harvesters/statistikamtnordharvester.py
@@ -225,7 +225,7 @@ class StatistikamtNordHarvester(ODSHBaseHarvester):
                 resource_file = urllib2.urlopen(resource['url'])
                 resource_dict['file_size'] = resource_file['Content-Length']
             else:
-                file_size = int(round(float(resource['Dateigroesse']) * 1000000000))
+                file_size = int(round(float(resource['Dateigroesse']) * 1048576 ))
                 resource_dict['size'] = file_size
             package_dict['resources'].append(resource_dict)
 
diff --git a/ckanext/odsh/helper_pkg_dict.py b/ckanext/odsh/helper_pkg_dict.py
new file mode 100644
index 0000000000000000000000000000000000000000..912b0b83db873b0ed58b98e64ef21b83c3a59e4b
--- /dev/null
+++ b/ckanext/odsh/helper_pkg_dict.py
@@ -0,0 +1,197 @@
+import re
+
+import ckanext.odsh.helpers as helpers_odsh
+import datetime
+
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
+import ckanext.odsh.collection.helpers as helpers_collection
+
+import ckanext.odsh.uri_store as uri_store
+
+from ckanext.odsh.pretty_daterange.date_range_formatter import DateRangeFormatter
+
+import logging
+log = logging.getLogger(__name__)
+
+
+class HelperPgkDict(object):
+    '''
+    a convenience class for all operations related to pkg_dict
+    aka dataset_dict, dict_pkg ...
+    '''
+    def __init__(self, pkg_dict):
+        self.pkg_dict = pkg_dict
+    
+    def is_collection(self):
+        '''
+        return True if self.pkg_dict['type'] is collection,
+        false otherwise
+        '''
+        dataset_type = self.pkg_dict.get(u'type')
+        return dataset_type == 'collection'
+    
+    def shall_be_part_of_collection(self):
+        '''
+        return the flag 'add_to_collection',
+        this one is set by ODSHDCATdeProfile._mark_for_adding_to_ckan_collection
+        '''
+        shall_be_part_of_collection = self.pkg_dict.get('add_to_collection')
+        return shall_be_part_of_collection
+    
+    def update_relations_to_collection_members(self):
+        '''
+        update a collection's relationships to its members
+
+        '''
+
+        id_collection = self.pkg_dict.get('id')
+        uris_collection_members = self.get_uris_collection_members()
+        ckan_ids_collection_members = [self.get_id_from_store(uri) for uri in uris_collection_members]
+        for id_pkg in ckan_ids_collection_members:
+            helpers_tpsh.add_pkg_to_collection(id_pkg, id_collection)
+            log.info('Added package with id {} to collection with id {}'.format(id_pkg, id_collection))
+    
+    def get_uris_collection_members(self):
+        '''
+        get the uris of a collection's members
+        
+        Returns:
+            list of uris taken from the 'has_version' in in self.pkg_dict['extras']
+        '''
+        extras = self.pkg_dict.get('extras')
+        uris_collection_members_as_string = helpers_odsh.odsh_extract_value_from_extras(
+            extras, 'has_version'
+        )
+        uris_collection_members_as_string_cleaned = re.sub(
+            r'[\"\[\] ]',
+            '',
+            uris_collection_members_as_string,
+            0, 0,
+        )
+        uris_collection_members = uris_collection_members_as_string_cleaned.split(',')
+        return uris_collection_members
+
+    
+    def update_relation_to_collection(self):
+        '''
+        update a package's relation to its collection
+        '''
+        id_pkg = self.pkg_dict.get('id')
+        uri_collection = self.get_collection_uri()
+        id_collection = uri_store.get_id_from_uri(uri_collection)
+        helpers_tpsh.add_pkg_to_collection(id_pkg, id_collection)
+        log.info('Added package with id {} to collection with id {}'.format(id_pkg, id_collection))
+    
+
+    def get_collection_uri(self):
+        '''
+        return the collection uri stored in 'extras
+        '''
+        extras = self.pkg_dict.get('extras')
+        uri_collection = helpers_odsh.odsh_extract_value_from_extras(
+            extras, 'is_version_of'
+        )
+        if uri_collection:
+            uri_collection_cleaned = re.sub(
+                r'[\"\[\] ]',
+                '',
+                uri_collection,
+                0, 0,
+            )
+            return uri_collection_cleaned
+        return None
+    
+
+    def get_collection_id(self):
+        '''
+        construct a collection uri from the id of 
+        the containing collection
+        '''
+        package_name = self.pkg_dict.get('name')
+        collection_name = helpers_collection.get_collection_name_by_dataset(package_name)
+        collection_dict = helpers_collection.get_package_dict(collection_name)
+        collection_id = collection_dict.get('id')
+        return collection_id
+
+    
+    def add_uri_to_store(self):
+        '''
+        store pair of uri and id for subsequent use
+        '''
+        uri_store.add_uri(self.pkg_dict)
+    
+    @staticmethod
+    def get_id_from_store(uri):
+        '''
+        get id from known uri
+        '''
+        id = uri_store.get_id_from_uri(uri)
+        return id
+
+    def is_package_new(self):
+        date_package_created_as_str = self._get_date_of_package_creation_from_pkg_dict()
+        if date_package_created_as_str == None:
+            is_new = False
+        else:
+            date_package_created = self._get_date_from_string(date_package_created_as_str)
+            if date_package_created == None:
+                is_new = False
+            else:
+                is_new = helpers_odsh.is_within_last_month(date_package_created)
+        return is_new
+    
+    def _get_date_of_package_creation_from_pkg_dict(self):
+        if 'extras' in self.pkg_dict:
+            extras = self.pkg_dict['extras']
+            issued = helpers_odsh.odsh_extract_value_from_extras(extras=extras, key='issued') # is None if issued not in extras
+            return issued
+        else:
+            return None
+        
+    @staticmethod
+    def _get_date_from_string(date_time_str):
+        date_time_format = '%Y-%m-%dT%H:%M:%S' #e.g. u'2019-06-12T11:56:25'
+        try:
+            date_time = datetime.datetime.strptime(date_time_str, date_time_format)
+            date = date_time.date()
+        except (ValueError, TypeError):
+            # if date cannot be converted from string return None
+            date = None
+        return date
+
+    def get_prettified_daterange(self):
+        date_start, date_end = self._get_date_start_and_end_from_pkg_dict()
+        prettified_daterange = self._construct_prettified_daterange(date_start, date_end)
+        return prettified_daterange
+    
+    @staticmethod
+    def _construct_prettified_daterange(date_start, date_end):
+        try:
+            prettified_daterange = DateRangeFormatter(date_start, date_end).get_formatted_str()
+        except ValueError as err:
+            log.warning(err.message)
+            return '-'
+        return prettified_daterange
+    
+    def _get_date_start_and_end_from_pkg_dict(self):
+        if 'extras' in self.pkg_dict:
+            extras = self.pkg_dict['extras']
+            date_start_as_str, date_end_as_str = (
+                helpers_odsh.odsh_extract_value_from_extras(
+                    extras=extras, key=key)
+                for key in ('temporal_start', 'temporal_end')
+            )
+            date_start = self._get_date_from_string(date_start_as_str)
+            date_end = self._get_date_from_string(date_end_as_str)
+        else:
+            date_start = None
+            date_end = None
+        return date_start, date_end
+
+
+def get_daterange_prettified(pkg_dict):
+    '''
+    wrapper function to use as a template helper
+    '''
+    daterange_prettified = HelperPgkDict(pkg_dict).get_prettified_daterange()
+    return daterange_prettified
\ No newline at end of file
diff --git a/ckanext/odsh/helpers.py b/ckanext/odsh/helpers.py
index 4acbb1902493fdb026ab908bb670cc49d8d62932..672ff8208dbd99c17da4e17dcb0ed01bc36cbc40 100644
--- a/ckanext/odsh/helpers.py
+++ b/ckanext/odsh/helpers.py
@@ -1,9 +1,13 @@
+# encoding: utf-8
+
 import logging
 import traceback
 import ast
 import ckan.plugins.toolkit as toolkit
 import ckan.logic as logic
 import ckan.model as model
+import ckan.logic.action as action
+import ckan.lib.helpers as helpers
 import json
 from ckan.common import c
 import datetime
@@ -18,6 +22,7 @@ from ckan.common import request
 import pdb
 from urlparse import urlsplit, urlunsplit
 import subprocess
+import ckan.lib.helpers as helpers
 
 get_action = logic.get_action
 log = logging.getLogger(__name__)
@@ -116,7 +121,7 @@ def extend_search_convert_local_to_utc_timestamp(str_timestamp):
         return None 
 
     if not re.match(r'\d\d\d\d-\d\d-\d\d', str_timestamp):
-        raise 'wrong format'
+        raise ValueError('wrong format')
     
     dt = parser.parse(str_timestamp, dayfirst=False).isoformat()
 
@@ -268,6 +273,59 @@ def odsh_is_slave():
     return 1 if c == 'True' else 0
 
 
+def odsh_get_facet_items_dict(name, limit=None):
+    '''
+    Gets all facets like 'get_facet_items_dict' but sorted alphabetically
+    instead by count.
+    '''
+    if name == 'groups':
+        limit = 20
+    facets = helpers.get_facet_items_dict(name, limit)
+    facets.sort(key=lambda it: (it['display_name'].lower(), -it['count']))
+    return facets
+
+
+def odsh_main_groups():
+    '''Return a list of the groups to be shown on the start page.'''
+
+    # Get a list of all the site's groups from CKAN, sorted by number of
+    # datasets.
+    groups = toolkit.get_action('group_list')(
+        data_dict={'all_fields': True})
+
+    return groups
+
+
+def odsh_now():
+    return helpers.render_datetime(datetime.datetime.now(), "%Y-%m-%d")
+
+
+def odsh_group_id_selected(selected, group_id):
+    if type(selected) is not list:
+        selected = [selected]
+    for g in selected:
+        if (isinstance(g, basestring) and group_id == g) or (type(g) is dict and group_id == g['id']):
+            return True
+
+    return False
+
+
+def odsh_remove_route(map, routename):
+    route = None
+    for i, r in enumerate(map.matchlist):
+
+        if r.name == routename:
+            route = r
+            break
+    if route is not None:
+        map.matchlist.remove(route)
+        for key in map.maxkeys:
+            if key == route.maxkeys:
+                map.maxkeys.pop(key)
+                map._routenames.pop(route.name)
+                break
+
+
 def is_within_last_month(date, date_ref=None):
     '''
     date is a datetime.date object containing the date to be checked
@@ -293,3 +351,105 @@ def is_within_last_month(date, date_ref=None):
     if date > one_month_ago:
         return True
     return False
+
+def tpsh_get_all_datasets_belonging_to_collection(context, collection_name):
+    rel_collection_dict = dict({"id": collection_name})
+    name_list = list()
+    try:
+        list_rel_collection = get_action('package_relationships_list')(context, rel_collection_dict)
+    except AssertionError:
+        #if there does not exist an relationship, returns an empty list
+        return name_list 
+    for item in list_rel_collection:
+        item_object = item.get('object') 
+        name_list.append(item_object)
+    return name_list
+
+def tpsh_get_all_datasets_belonging_to_collection_by_dataset(context, dataset_name):
+    collection_name = tpsh_get_collection_name_by_dataset(context, dataset_name)
+    if collection_name:
+        name_list = tpsh_get_all_datasets_belonging_to_collection(context, collection_name)
+        return name_list
+    return list()
+
+def tpsh_get_collection_name_by_dataset(context, dataset_name):
+    rel_dataset_dict = dict({"id" : dataset_name})
+    list_rel_dataset = toolkit.get_action('package_relationships_list')(context, rel_dataset_dict)
+    if not len(list_rel_dataset):
+        return None    
+    collection_name = list_rel_dataset[0]['object']
+    return collection_name
+
+def tpsh_get_successor_and_predecessor_dataset(context, pkg_dict):
+    dataset_name = pkg_dict.get('name')
+    siblings_dicts_with_access = _get_siblings_dicts_with_access(context, pkg_dict)
+    if siblings_dicts_with_access:
+        n_siblings = len(siblings_dicts_with_access)
+        siblings_dicts_sorted_by_date_issued = _sort_siblings_by_name_and_date(siblings_dicts_with_access)
+        siblings_names_sorted_by_date_issued = [d['name'] for d in siblings_dicts_sorted_by_date_issued]
+        id_current_dataset = siblings_names_sorted_by_date_issued.index(dataset_name)
+        predecessor_name = (
+            siblings_names_sorted_by_date_issued[id_current_dataset-1] if (id_current_dataset > 0) 
+            else None
+        )
+        successor_name = (
+            siblings_names_sorted_by_date_issued[id_current_dataset+1] if (id_current_dataset < n_siblings-1) 
+            else None
+        )
+    else:
+        predecessor_name, successor_name = None, None
+    return successor_name, predecessor_name
+
+def _get_siblings_dicts_with_access(context, pkg_dict):
+    dataset_name = pkg_dict.get('name')
+    list_of_siblings = tpsh_get_all_datasets_belonging_to_collection_by_dataset(context, dataset_name)
+    n_siblings = len(list_of_siblings)
+    if n_siblings>0:
+        siblings_dicts = [get_package_dict(name) for name in list_of_siblings]
+        user_has_access = lambda pkg_dict:helpers.check_access('package_show', pkg_dict)
+        siblings_dicts_with_access = filter(user_has_access, siblings_dicts)
+        return siblings_dicts_with_access
+    return None
+
+    
+def _sort_siblings_by_name_and_date(siblings_dicts):
+    '''
+    sort by name first and then by date to have a fallback if dates are the same
+    '''
+    _get_name = lambda pkg_dict:pkg_dict.get('name')
+    _get_issued = lambda pkg_dict:odsh_extract_value_from_extras(pkg_dict.get('extras'), 'issued')
+    siblings_dicts_sorted_by_name = sorted(siblings_dicts, key=_get_name)
+    siblings_dicts_sorted_by_date_issued = sorted(siblings_dicts_sorted_by_name, key=_get_issued)
+    return siblings_dicts_sorted_by_date_issued
+
+
+def get_package_dict(name):
+    return model.Package.get(name).as_dict()
+
+def tpsh_get_successor_and_predecessor_urls(context, pkg_dict):
+    successor_name, predecessor_name = tpsh_get_successor_and_predecessor_dataset(context, pkg_dict)
+    successor_url, predecessor_url = (
+        helpers.url_for(controller='package', action='read', id=name)
+        if name is not None
+        else None
+        for name in (successor_name, predecessor_name)
+    )
+    return successor_url, predecessor_url
+
+def short_name_for_category(category_name):
+    translations = {
+        'soci': u'Bevölkerung',
+        'educ': u'Bildung',
+        'ener': u'Energie',
+        'heal': u'Gesundheit',
+        'intr': u'Internationales',
+        'just': u'Justiz',
+        'agri': u'Landwirtschaft',
+        'gove': u'Regierung',
+        'regi': u'Regionales',
+        'envi': u'Umwelt',
+        'tran': u'Verkehr',
+        'econ': u'Wirtschaft',
+        'tech': u'Wissenschaft',
+    }
+    return translations.get(category_name)
diff --git a/ckanext/odsh/helpers_tpsh.py b/ckanext/odsh/helpers_tpsh.py
new file mode 100644
index 0000000000000000000000000000000000000000..608c91016c353ca9de29934c3b06a0c52dd1c4d8
--- /dev/null
+++ b/ckanext/odsh/helpers_tpsh.py
@@ -0,0 +1,211 @@
+# encoding: utf-8
+
+import csv
+import datetime
+import logging
+from string import lower
+import json
+import re
+import urllib2
+from collections import OrderedDict
+
+from ckan.common import config
+import ckan.lib.helpers as helpers
+import ckan.logic.action.create as create
+import ckan.model as model
+import ckan.plugins.toolkit as toolkit
+
+
+import ckanext.odsh.helpers as odsh_helpers
+
+log = logging.getLogger(__name__)
+
+CKAN_TYPES = {'http://dcat-ap.de/def/datasetTypes/collection': 'collection'}
+
+
+def map_dct_type_to_ckan_type(dct_type):
+    '''
+    matches the field dct:type from a harvested rdf file 
+    to the corresponding ckan package type
+    '''
+    ckan_type = CKAN_TYPES.get(dct_type)
+    return ckan_type
+
+def map_ckan_type_to_dct_type(ckan_type):
+    DCT_TYPES = _revert_dict(CKAN_TYPES)
+    dct_type = DCT_TYPES.get(ckan_type)
+    return dct_type
+
+def _revert_dict(d):
+    d_inverse = {v: k for k, v in d.iteritems()}
+    return d_inverse
+
+def add_pkg_to_collection(id_pkg, id_collection):
+    if id_pkg and id_collection:
+        relationship_dict = {
+            'subject': id_pkg,
+            'object': id_collection,
+            'type': 'child_of',
+        }
+        toolkit.get_action('package_relationship_create')(None, relationship_dict)
+
+def use_matomo():
+    '''Return the value of the use_matomo config setting.
+
+    To enable using matomo, add this line to the
+    [app:main] section of your CKAN config file::
+
+      ckanext.odsh.use_matomo = True
+
+    Returns ``False`` by default, if the setting is not in the config file.
+
+    :rtype: bool
+
+    '''
+    value = config.get('ckanext.odsh.use_matomo', False)
+    value = toolkit.asbool(value)
+    return value
+
+def correct_missing_relationship(pkg_dict, pkg_relationships_from_model):
+    '''
+    This function corrects missing relationship in show package.
+    Note this fix is only good with one or non relationship. 
+    This error is well known but was not fixed. https://github.com/ckan/ckan/issues/3114
+    The error causes the deletation of relationships, because package_show is
+    used in resource_create to get the package. 
+    '''
+    if pkg_relationships_from_model:
+        relationship_from_model = pkg_relationships_from_model[0]
+        relationship_list_from_dict = pkg_dict.get('relationships_as_subject')
+        type_pkg = pkg_dict.get('type')
+        needs_update = type_pkg == 'dataset' and not relationship_list_from_dict
+        if needs_update:
+            relationship_for_package = {
+                '__extras': {
+                    'object_package_id': relationship_from_model.object_package_id,
+                    'revision_id': relationship_from_model.revision_id,
+                    'subject_package_id': relationship_from_model.subject_package_id,
+                },
+                'comment': relationship_from_model.subject_package_id,
+                'id': relationship_from_model.id,
+                'type': relationship_from_model.type,
+            }
+            pkg_dict['relationships_as_subject'].append(relationship_for_package) 
+    return pkg_dict
+
+def get_pkg_relationships_from_model(pkg_dict):
+    pkg_id = pkg_dict.get('id')
+    return model.Package.get(pkg_id).get_relationships()
+
+def load_language_mapping():
+    with open(config.get('ckanext.odsh.language_mapping')) as language_mapping_json:
+        LANGUAGE_MAPPING = json.loads(language_mapping_json.read())
+    return LANGUAGE_MAPPING
+
+def load_json_to_ordered_dict(json_str):
+    return json.loads(json_str, object_pairs_hook=OrderedDict)
+
+def load_subject_mapping():
+    with open(config.get('ckanext.odsh.subject_mapping')) as subject_mapping_json:
+        SUBJECT_MAPPING = load_json_to_ordered_dict(subject_mapping_json.read())
+    return SUBJECT_MAPPING
+
+def get_language_of_package(pkg_dict):
+    LANGUAGE_MAPPING = load_language_mapping()
+    language_id = _get_language_id(pkg_dict)
+    if not language_id:
+        return None
+    language = LANGUAGE_MAPPING.get(language_id)
+    return language
+
+def get_language_icon(pkg_dict):
+    ICONS = {
+        "http://publications.europa.eu/resource/authority/language/DAN": '/base/images/icon_lang_danish.png',
+        "http://publications.europa.eu/resource/authority/language/ENG": '/base/images/icon_lang_english.png',
+    }
+    language_id = _get_language_id(pkg_dict)
+    if not language_id:
+        return None
+    return ICONS.get(language_id) 
+
+def _get_language_id(pkg_dict):
+    language_id = odsh_helpers.odsh_extract_value_from_extras(pkg_dict.get('extras'), 'language')
+    language_id = pkg_dict.get('language')
+    if not language_id:
+        language_id = odsh_helpers.odsh_extract_value_from_extras(
+            pkg_dict.get('extras'), 'language'
+        )
+    if not language_id:
+        return None
+    language_id_cleaned = re.sub('[\[\]\"]', '', language_id)
+    return language_id_cleaned
+
+def get_spatial_for_selection():
+    mapping_path = config.get('ckanext.odsh.spatial.mapping')
+    try:
+        mapping_file = urllib2.urlopen(mapping_path)
+    except urllib2.URLError:
+        log.error('Could not load spatial mapping file')
+        raise
+    cr = csv.reader(mapping_file, delimiter="\t")
+    spatial_mapping = list()
+    for row in cr:
+        key  = row[0].decode('UTF-8')
+        value = row[1].decode('UTF-8')
+        spatial_mapping.append({'key':key, 'value':value}) 
+    spatial_mapping.append({'key':'', 'value':''})   
+    return spatial_mapping
+
+def get_subject_for_selection():
+    SUBJECT_MAPPING = load_subject_mapping()
+    dict_for_select_box = [{'key': 'empty', 'value':' '}, ]
+    dict_for_select_box.extend(
+        [{'key': key, 'value': SUBJECT_MAPPING[key]} for key in SUBJECT_MAPPING]
+    )
+    return dict_for_select_box
+
+def get_language_for_selection():
+    LANGUAGE_MAPPING = load_language_mapping()
+    dict_for_select_box = [{'key': key, 'value': LANGUAGE_MAPPING[key]} for key in LANGUAGE_MAPPING]
+    return dict_for_select_box
+
+def get_package_dict(name):
+    return model.Package.get(name).as_dict()
+
+def size_of_fmt(num, suffix='B'):
+    for unit in ['',' k',' M',' G',' T',' P',' E',' Z']:
+        if abs(num) < 1000.0:
+            return "%3.1f%s%s" % (num, unit, suffix)
+        num /= 1000.0
+    return "%.1f%s%s" % (num, 'Y', suffix)
+
+def get_resource_size(resource):
+    resource_size = resource.get('size')
+    if resource_size:
+        return size_of_fmt(resource_size)    
+
+
+def get_address_org(organization):
+    list_extras = organization.get('extras')
+    address = dict()
+    if not list_extras:
+        return address
+    for extra in list_extras:
+            address.update({extra.get('key'):extra.get('value')})
+    web = address.get('web')
+    if web and not web.startswith('http'):
+         web = 'http://' + web
+         address.update({'web':web})    
+    return address
+
+
+def get_body_mail(organization, package):
+    package_name = package.get('name')
+    url = helpers.url_for(controller='package', action='read', id=package_name, qualified = True)
+    title = package.get('title')
+    anrede = "Sehr geehrte Damen und Herren," + "%0D%0A" +  "%0D%0A" + "zu folgendem Eintrag habe ich eine Anmerkung/Frage:" + "%0D%0A" + "%0D%0A" 
+    mail_titel = "Titel: " + title + "%0D%0A"    
+    mail_document = "Dokument-ID: " +  package_name + "%0D%0A"
+    mail_url = "URL: " +  url + "%0D%0A"  +  "%0D%0A" 
+    message =  mail_titel + mail_document  +  mail_url + "Mein Kommentar:" +  "%0D%0A"    +  "%0D%0A"  +  "%0D%0A"  +  "%0D%0A" 
+    return anrede + message
\ No newline at end of file
diff --git a/ckanext/odsh/i18n/ckanext-odsh.pot b/ckanext/odsh/i18n/ckanext-odsh.pot
index 1885142a55a7226b363bb5704dd72d4f2b18ed22..32e57994a11c31e0a7e4d6ffb4bd0a9ab4536676 100644
--- a/ckanext/odsh/i18n/ckanext-odsh.pot
+++ b/ckanext/odsh/i18n/ckanext-odsh.pot
@@ -1,14 +1,14 @@
 # Translations template for ckanext-odsh.
-# Copyright (C) 2018 ORGANIZATION
+# Copyright (C) 2019 ORGANIZATION
 # This file is distributed under the same license as the ckanext-odsh project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2018.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2019.
 #
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: ckanext-odsh 0.0.1\n"
 "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2018-09-28 13:50+0000\n"
+"POT-Creation-Date: 2019-10-08 12:09+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,151 +17,1154 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 2.3.4\n"
 
-#: ckanext/odsh/plugin.py:52
-msgid "Groups"
+#: ckanext/odsh/plugin.py:158 ckanext/odsh/plugin.py:165 ckanext/odsh/plugin.py:171
+msgid "Herausgeber"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:43
-msgid "Search Datasets"
+#: ckanext/odsh/plugin.py:159 ckanext/odsh/plugin.py:168 ckanext/odsh/plugin.py:174
+msgid "Kategorie"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:46
-msgid "Search"
+#: ckanext/odsh/plugin.py:160
+msgid "Informationsgegenstand"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:65
+#: ckanext/odsh/plugin.py:161
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:223
+msgid "Tags"
+msgstr ""
+
+#: ckanext/odsh/plugin.py:166 ckanext/odsh/plugin.py:172
+msgid "Dateiformat"
+msgstr ""
+
+#: ckanext/odsh/plugin.py:167 ckanext/odsh/plugin.py:173
+msgid "Lizenz"
+msgstr ""
+
+#: ckanext/odsh/validation.py:261
+#, python-format
+msgid "Tag \"%s\" must be alphanumeric characters or symbols: -_.:()"
+msgstr ""
+
+#: ckanext/odsh/validation.py:312
+msgid "Subject must be a known URI."
+msgstr ""
+
+#: ckanext/odsh/validation.py:334
+msgid "Subject must not be empty."
+msgstr ""
+
+#: ckanext/odsh/fanstatic/moment.js:6
+msgid "Weeks"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:63
+msgid "Link"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:64
+msgid "Link to a URL on the internet (you can also link to an API)"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:71
+#: ckanext/odsh/templates/header.html:56
+msgid "Upload"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:75
+#: ckanext/odsh/templates/macros/form.html:342
+msgid "Remove"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:83
+#: ckanext/odsh/templates/macros/form.html:528
+msgid "Image"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:90
+msgid "Upload a file on your computer"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:115
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:186
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:18
+#: ckanext/odsh/templates/package/snippets/resource_form.html:33
+msgid "URL"
+msgstr ""
+
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:125
+#: ckanext/odsh/fanstatic/odsh_image-upload.js:221
+msgid "File"
+msgstr ""
+
+#: ckanext/odsh/templates/error_document_template.html:3
+#, python-format
+msgid "Error %(error_code)s"
+msgstr ""
+
+#: ckanext/odsh/templates/header.html:47 ckanext/odsh/templates/home/index.html:7
 msgid "Start"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:66
-msgid "Datasets"
+#: ckanext/odsh/templates/header.html:48
+msgid "Dokumente"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:67
-#: ckanext/odsh/templates/snippets/package_item.html:82
-msgid "Organizations"
+#: ckanext/odsh/templates/header.html:49
+msgid "Infos"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/base.html:12
+#: ckanext/odsh/templates/datarequests/close.html:6
+#: ckanext/odsh/templates/datarequests/edit.html:6
+#: ckanext/odsh/templates/datarequests/new.html:6
+msgid "Data Proposal"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/close.html:3
+#: ckanext/odsh/templates/datarequests/close.html:8
+#: ckanext/odsh/templates/datarequests/close.html:12
+msgid "Close Data Proposal"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:18
+#: ckanext/odsh/templates/datarequests/show.html:15
+#: ckanext/odsh/templates/organization/read_base.html:18
+#: ckanext/odsh/templates/package/resource_read.html:31
+msgid "Manage"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:22
+#: ckanext/odsh/templates/datarequests/show.html:19
+msgid "Close"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:37
+#: ckanext/odsh/templates/datarequests/snippets/comment_form.html:25
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_item.html:38
+msgid "Add New Comment"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:53
+msgid "Released"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:54
+msgid "Suggester"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:54
+msgid "None"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:56
+msgid "Status"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:60
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_item.html:13
+msgid "Done"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/comment.html:64
+#: ckanext/odsh/templates/datarequests/show.html:40
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_item.html:17
+msgid "Open"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/edit.html:3
+#: ckanext/odsh/templates/datarequests/edit.html:8
+#: ckanext/odsh/templates/datarequests/edit.html:12
+msgid "Edit Data Proposal"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/index.html:8
+msgid "Search Data Requests..."
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/index.html:12
+msgid "Add Request"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/new.html:3
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:33
+msgid "Create Data Request"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/new.html:7
+msgid "Create Data Proposal"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/new.html:11
+msgid "Create New Data Request"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/show.html:3
+#: ckanext/odsh/templates/datarequests/show.html:25
+msgid "Data Request"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/show.html:8
+msgid "Data Requests"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/show.html:35
+msgid "Closed"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/show.html:64
+#: ckanext/odsh/templates/datarequests/snippets/comments.html:11
+msgid "This data request has not been commented yet"
 msgstr ""
 
-#: ckanext/odsh/templates/header.html:68
-msgid "Info"
+#: ckanext/odsh/templates/datarequests/snippets/comment_form.html:17
+msgid "Add a new Comment"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:5
+#: ckanext/odsh/templates/datarequests/snippets/comment_form.html:22
+msgid "Cancel"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/comment_form.html:23
+msgid "Update Comment"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/comments.html:3
+msgid "Comments"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:17
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:9
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:13
 msgid "Title"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:17
-msgid "URL"
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:17
+msgid "eg. Data Request Name"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:23
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:21
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:20
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:27
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:32
 msgid "Description"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:33
-#: ckanext/odsh/templates/package/snippets/package_metadata_fields.html:18
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:21
+msgid "eg. Data Request description"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:29
+msgid "Are you sure you want to delete this data request?"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_form.html:30
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:60
+#: ckanext/odsh/templates/package/edit_view.html:19
+#: ckanext/odsh/templates/package/snippets/package_form.html:32
+#: ckanext/odsh/templates/package/snippets/resource_form.html:96
+msgid "Delete"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_list.html:11
+msgid "No Data Requests found with the given criteria"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/datarequest_list.html:13
+#: ckanext/odsh/templates/organization/index.html:50
+msgid "How about creating one?"
+msgstr ""
+
+#: ckanext/odsh/templates/datarequests/snippets/new_datarequest_form.html:7
+msgid "Suggest New Data Request"
+msgstr ""
+
+#: ckanext/odsh/templates/home/index.html:4
+msgid "Welcome"
+msgstr ""
+
+#: ckanext/odsh/templates/macros/form.html:374
+msgid "Custom"
+msgstr ""
+
+#: ckanext/odsh/templates/macros/form.html:374
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:59
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:94
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:249
 msgid "This field is required"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:34
-#: ckanext/odsh/templates/snippets/package_item.html:83
-msgid "License"
+#: ckanext/odsh/templates/macros/form.html:510
+msgid "Required field"
+msgstr ""
+
+#: ckanext/odsh/templates/macros/form.html:526
+msgid "http://example.com/my-image.jpg"
+msgstr ""
+
+#: ckanext/odsh/templates/macros/form.html:527
+msgid "Image URL"
+msgstr ""
+
+#: ckanext/odsh/templates/macros/form.html:544
+msgid "Clear Upload"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/index.html:3
+#: ckanext/odsh/templates/organization/index.html:6
+#: ckanext/odsh/templates/organization/index.html:33
+#: ckanext/odsh/templates/organization/read_base.html:3
+#: ckanext/odsh/templates/organization/read_base.html:6
+#: ckanext/odsh/templates/package/base.html:14
+msgid "Organizations"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/index.html:17
+msgid "Search organizations"
 msgstr ""
 
+#: ckanext/odsh/templates/organization/index.html:30
+msgid "Add Organization"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/index.html:37
+msgid "Search organizations..."
+msgstr ""
+
+#: ckanext/odsh/templates/organization/index.html:48
+msgid "There are currently no organizations for this site"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:5
+msgid "Add Dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:27
+#: ckanext/odsh/templates/snippets/search_form.html:11
+msgid "Relevance"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:28
+#: ckanext/odsh/templates/snippets/search_form.html:6
+#: ckanext/odsh/templates/snippets/search_form.html:12
+msgid "Name Ascending"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:29
+#: ckanext/odsh/templates/snippets/search_form.html:6
+#: ckanext/odsh/templates/snippets/search_form.html:13
+msgid "Name Descending"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:30
+#: ckanext/odsh/templates/snippets/search_form.html:14
+msgid "Issued Ascending"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:31
+#: ckanext/odsh/templates/snippets/search_form.html:15
+msgid "Issued Descending"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:32
+#: ckanext/odsh/templates/snippets/package_item.html:90
+#: ckanext/odsh/templates/snippets/search_form.html:20
+msgid "Popular"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:36
+#: ckanext/odsh/templates/snippets/search_form.html:3
+msgid "Search datasets..."
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read.html:37
+#: ckanext/odsh/templates/package/base.html:7
+#: ckanext/odsh/templates/package/base.html:17
+#: ckanext/odsh/templates/package/read.html:17
+#: ckanext/odsh/templates/package/read.html:22
+#: ckanext/odsh/templates/package/search.html:5
+#: ckanext/odsh/templates/snippets/organization.html:59
+msgid "Documents"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/read_base.html:29
+#: ckanext/odsh/templates/snippets/organization.html:47
+msgid "There is no description for this organization"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:10
+#: ckanext/odsh/templates/package/snippets/resource_form.html:39
+msgid "Name"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:10
+msgid "My Organization"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:18
+msgid "my-organization"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:20
+msgid "A little information about my organization..."
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:35
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:48
+msgid "Custom Field"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:60
+msgid ""
+"Are you sure you want to delete this Organization? This will delete all the "
+"public and private datasets belonging to this organization."
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_form.html:63
+msgid "Save Organization"
+msgstr ""
+
+#: ckanext/odsh/templates/organization/snippets/organization_item.html:15
+#: ckanext/odsh/templates/snippets/package_item.html:75
+msgid "View {organization_name}"
+msgstr ""
+
+#: ckanext/odsh/templates/package/base.html:22
+msgid "Dokuments"
+msgstr ""
+
+#: ckanext/odsh/templates/package/base.html:23
+#: ckanext/odsh/templates/package/read.html:23
+msgid "Create Dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_base.html:10
+#: ckanext/odsh/templates/package/resource_edit.html:3
+#: ckanext/odsh/templates/package/resource_edit_base.html:12
+msgid "Edit"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_base.html:12
+#: ckanext/odsh/templates/package/new_package_form.html:8
+#: ckanext/odsh/templates/package/snippets/resource_form.html:14
+msgid "odsh Create Dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_base.html:26
+#: ckanext/odsh/templates/package/resource_edit_base.html:28
+#: ckanext/odsh/templates/package/snippets/resource_form.html:86
+msgid "back"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_view.html:3
+#: ckanext/odsh/templates/package/edit_view.html:4
+#: ckanext/odsh/templates/package/edit_view.html:8
+#: ckanext/odsh/templates/package/edit_view.html:12
+msgid "Edit view"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_view.html:21
+#: ckanext/odsh/templates/package/new_view.html:31
+#: ckanext/odsh/templates/package/read.html:81
+msgid "Preview"
+msgstr ""
+
+#: ckanext/odsh/templates/package/edit_view.html:22
+msgid "Update"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_package_form.html:18
+msgid "next"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_package_form.html:20
+msgid "Update Dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_resource.html:5
+msgid "Add data to the dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_resource.html:11
+#: ckanext/odsh/templates/package/new_resource_not_draft.html:8
+msgid "Add New Resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_resource_not_draft.html:3
+#: ckanext/odsh/templates/package/new_resource_not_draft.html:4
+msgid "Add resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_view.html:3
+#: ckanext/odsh/templates/package/new_view.html:4
+#: ckanext/odsh/templates/package/new_view.html:8
+#: ckanext/odsh/templates/package/new_view.html:12
+msgid "Add view"
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_view.html:19
+msgid ""
+" Data Explorer views may be slow and unreliable unless the DataStore "
+"extension is enabled. For more information, please see the <a "
+"href='http://docs.ckan.org/en/latest/maintaining/data-viewer.html#viewing-"
+"structured-data-the-data-explorer'         target='_blank'>Data Explorer "
+"documentation</a>. "
+msgstr ""
+
+#: ckanext/odsh/templates/package/new_view.html:32
+#: ckanext/odsh/templates/package/snippets/resource_form.html:111
+msgid "Add"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:35
+#: ckanext/odsh/templates/snippets/package_item.html:79
+msgid "Draft"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:38
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:279
+#: ckanext/odsh/templates/snippets/organization.html:25
+#: ckanext/odsh/templates/snippets/package_item.html:81
+msgid "Deleted"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:44
+msgid "Manage Dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:51
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:255
+#: ckanext/odsh/templates/snippets/package_item.html:70
+msgid "Private"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:62
+msgid "Publisher"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:101
+msgid "latest collection member"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:106
+#: ckanext/odsh/templates/package/read.html:111
+msgid "predecessor"
+msgstr ""
+
+#: ckanext/odsh/templates/package/read.html:116
+#: ckanext/odsh/templates/package/read.html:121
+msgid "successor"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_edit_base.html:32
+msgid "Edit resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:37
+msgid "View"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:39
+msgid "API Endpoint"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:41
+msgid "Go to resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:43
+msgid "Download"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:56
+#: ckanext/odsh/templates/package/resource_read.html:58
+msgid "URL:"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:66
+msgid "From the dataset abstract"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:68
+#, python-format
+msgid "Source: <a href=\"%(url)s\">%(dataset)s</a>"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:109
+msgid "There are no views created for this resource yet."
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:113
+msgid "Not seeing the views you were expecting?"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:115
+msgid "Click here for more information."
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:118
+msgid "Here are some reasons you may not be seeing expected views:"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:120
+msgid "No view has been created that is suitable for this resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:121
+msgid "The site administrators may not have enabled the relevant view plugins"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:122
+msgid ""
+"If a view requires the DataStore, the DataStore plugin may not be enabled, or"
+" the data may not have been pushed to the DataStore, or the DataStore hasn't "
+"finished processing the data yet"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:144
+msgid "Additional Information"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:148
+msgid "Field"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:149
+msgid "Value"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:154
+msgid "Data last updated"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:155
+#: ckanext/odsh/templates/package/resource_read.html:159
+#: ckanext/odsh/templates/package/resource_read.html:163
+#: ckanext/odsh/templates/package/resource_read.html:167
+msgid "unknown"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:158
+msgid "Metadata last updated"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:162
+msgid "Created"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:166
+#: ckanext/odsh/templates/package/snippets/resource_form.html:75
+#: ckanext/odsh/templates/package/snippets/resource_info.html:26
+msgid "Format"
+msgstr ""
+
+#: ckanext/odsh/templates/package/resource_read.html:170
+#: ckanext/odsh/templates/package/snippets/info.html:94
 #: ckanext/odsh/templates/package/snippets/package_basic_fields.html:93
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:99
+msgid "License"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:63
+#: ckanext/odsh/templates/package/snippets/info.html:72
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:142
+msgid "timerange"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:78
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:160
+#: ckanext/odsh/templates/snippets/search_form.html:117
+msgid "from"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:81
+msgid "date start"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:85
+#: ckanext/odsh/templates/package/search.html:100
+msgid "Date"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:89
+#: ckanext/odsh/templates/snippets/search_form.html:130
+msgid "wrong_start_date_for_search"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:93
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:174
+#: ckanext/odsh/templates/snippets/search_form.html:144
+msgid "to"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:96
+msgid "date end"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:104
+#: ckanext/odsh/templates/snippets/search_form.html:157
+msgid "wrong_end_date_for_search"
+msgstr ""
+
+#: ckanext/odsh/templates/package/search.html:107
+msgid "submit date search"
+msgstr ""
+
+#: ckanext/odsh/templates/package/view_edit_base.html:9
+msgid "All views"
+msgstr ""
+
+#: ckanext/odsh/templates/package/view_edit_base.html:12
+msgid "View view"
+msgstr ""
+
+#: ckanext/odsh/templates/package/view_edit_base.html:37
+msgid "View preview"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:27
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:85
+#: ckanext/odsh/templates/snippets/package_item.html:114
+msgid "subject"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:38
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:237
+msgid "language"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:50
+#: ckanext/odsh/templates/snippets/package_item.html:97
+msgid " category: "
+msgid_plural " categories: "
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:82
+#: ckanext/odsh/templates/snippets/package_item.html:115
+msgid "issued"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:87
+msgid "modified"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:110
+msgid "share this dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/info.html:125
+msgid "send an email"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:19
+msgid "Enter title"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:36
+msgid "Enter description"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:58
 msgid "Organization"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:97
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:66
 msgid "No organization"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:113
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:119
+#: ckanext/odsh/templates/user/snippets/login_form.html:23
+msgid "enter name"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:229
+msgid "odsh tags placeholder"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:243
+msgid "Spatial uri"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:248
+msgid "Visibility"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:255
+msgid "Public"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:269
 msgid "State"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:117
+#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:276
 msgid "Active"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_basic_fields.html:119
-#: ckanext/odsh/templates/snippets/package_item.html:49
-msgid "Deleted"
+#: ckanext/odsh/templates/package/snippets/package_form.html:31
+msgid "Are you sure you want to delete this dataset?"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_metadata_fields.html:47
-msgid "Visibility"
+#: ckanext/odsh/templates/package/snippets/package_form.html:38
+msgid "Next: Add Data"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_metadata_fields.html:50
-#: ckanext/odsh/templates/snippets/package_item.html:37
-msgid "Private"
+#: ckanext/odsh/templates/package/snippets/resource_form.html:30
+msgid "odsh_resource_upload_error_label"
 msgstr ""
 
-#: ckanext/odsh/templates/package/snippets/package_metadata_fields.html:50
-msgid "Public"
+#: ckanext/odsh/templates/package/snippets/resource_form.html:33
+msgid "Data-Upload"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:33
+msgid "http://example.com/external-data.csv"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:38
+msgid "odsh_resource_name_error_label"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:39
+msgid "Enter name of the dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:54
+msgid "Last Modified"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:54
+msgid "eg. 2012-06-05"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:57
+msgid "File Size"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:57
+msgid "eg. 1024"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:60
+#: ckanext/odsh/templates/package/snippets/resource_form.html:63
+msgid "MIME Type"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:60
+#: ckanext/odsh/templates/package/snippets/resource_form.html:63
+msgid "eg. application/json"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:73
+msgid "odsh_resource_format_error_label"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:75
+msgid "eg. CSV, XML or JSON"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:95
+msgid "Are you sure you want to delete this resource?"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_form.html:106
+msgid "Upload dataset"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_info.html:14
+msgid "document"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_info.html:18
+msgid "Name Resource"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_info.html:22
+msgid "Resource count"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resource_item.html:24
+#: ckanext/odsh/templates/package/snippets/resource_item.html:41
+msgid "download file"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resources_list.html:13
+msgid "Dateien"
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resources_list.html:26
+#, python-format
+msgid ""
+" <p class=\"empty\">This dataset has no data, <a href=\"%(url)s\">why not add"
+" some?</a></p> "
+msgstr ""
+
+#: ckanext/odsh/templates/package/snippets/resources_list.html:30
+msgid "This dataset has no data"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/facet_list.html:26
-msgid "Show More {facet_type}"
+#: ckanext/odsh/templates/package/snippets/stages.html:23
+#: ckanext/odsh/templates/package/snippets/stages.html:25
+msgid "Enter data"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/facet_list.html:30
-msgid "Show Only Popular {facet_type}"
+#: ckanext/odsh/templates/package/snippets/stages.html:30
+#: ckanext/odsh/templates/package/snippets/stages.html:34
+#: ckanext/odsh/templates/package/snippets/stages.html:36
+msgid "Add dataset"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/facet_list.html:34
+#: ckanext/odsh/templates/snippets/custom_search_form.html:6
+msgid "{number} data request found for \"{query}\""
+msgid_plural "{number} data requests found for \"{query}\""
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/custom_search_form.html:7
+msgid "No data requests found for \"{query}\""
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/custom_search_form.html:8
+msgid "{number} data proposal found"
+msgid_plural "{number} data proposals found"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/custom_search_form.html:9
+msgid "No data proposal found"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/facet_list.html:65
+msgid "Show More"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/facet_list.html:69
+msgid "Show Less"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/facet_list.html:75
 msgid "There are no {facet_type} that match this search"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/language_selector.html:13
-#: ckanext/odsh/templates/snippets/search_form.html:34
-msgid "Go"
+#: ckanext/odsh/templates/snippets/follow_button.html:9
+msgid "Unfollow"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/package_item.html:47
-msgid "Draft"
+#: ckanext/odsh/templates/snippets/follow_button.html:14
+msgid "Follow"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/package_item.html:58
-msgid "Popular"
+#: ckanext/odsh/templates/snippets/home_breadcrumb_item.html:5
+msgid "Home"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/map.html:4
+msgid "map"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/organization.html:44
+msgid "read more"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/organization.html:55
+msgid "Followers"
 msgstr ""
 
 #: ckanext/odsh/templates/snippets/package_item.html:65
-msgid "This dataset has no description"
+msgid "NEW"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:3
-msgid "Search datasets..."
+#: ckanext/odsh/templates/snippets/search_box.html:5
+msgid "enter search query for datasets"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_box.html:11
+#: ckanext/odsh/templates/snippets/search_box.html:13
+msgid "Search dataset"
 msgstr ""
 
 #: ckanext/odsh/templates/snippets/search_form.html:4
 msgid "Order by"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:5
-msgid "Name Ascending"
+#: ckanext/odsh/templates/snippets/search_form.html:8
+msgid "Date Ascending"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:5
-msgid "Name Descending"
+#: ckanext/odsh/templates/snippets/search_form.html:8
+msgid "Date Descending"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:60
-msgid "Remove"
+#: ckanext/odsh/templates/snippets/search_form.html:16
+msgid "Start Date Descending"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:17
+msgid "Start Date Ascending"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:65
+#: ckanext/odsh/templates/snippets/search_form.html:18
+msgid "End Date Descending"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:19
+msgid "End Date Ascending"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:45
+msgid "rss feeds"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:67
+msgid "Go"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:93
+#: ckanext/odsh/templates/snippets/search_form.html:94
+#: ckanext/odsh/templates/snippets/search_form.html:121
+#: ckanext/odsh/templates/snippets/search_form.html:122
+#: ckanext/odsh/templates/snippets/search_form.html:134
+#: ckanext/odsh/templates/snippets/search_form.html:135
+#: ckanext/odsh/templates/snippets/search_form.html:148
+#: ckanext/odsh/templates/snippets/search_form.html:149
+#: ckanext/odsh/templates/snippets/search_form.html:161
+#: ckanext/odsh/templates/snippets/search_form.html:162
+#: ckanext/odsh/templates/snippets/search_form.html:182
+#: ckanext/odsh/templates/snippets/search_form.html:183
+msgid "Remove filters"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:102
 msgid "Filter Results"
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:72
+#: ckanext/odsh/templates/snippets/search_form.html:117
+#: ckanext/odsh/templates/snippets/search_form.html:130
+#: ckanext/odsh/templates/snippets/search_form.html:144
+#: ckanext/odsh/templates/snippets/search_form.html:157
+msgid "daterange"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:178
+msgid "map search active"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_form.html:196
 msgid " <p class=\"extra\">Please try another search.</p> "
 msgstr ""
 
-#: ckanext/odsh/templates/snippets/search_form.html:78
+#: ckanext/odsh/templates/snippets/search_form.html:202
 msgid ""
 " <p id=\"search-error\"><strong>There was an error while searching.</strong> "
 "Please try again.</p> "
 msgstr ""
 
+#: ckanext/odsh/templates/snippets/search_result_text.html:15
+msgid "{number} dataset found for \"{query}\""
+msgid_plural "{number} datasets found for \"{query}\""
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:17
+msgid "No datasets found for \"{query}\""
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:18
+msgid "{number} dataset found"
+msgid_plural "{number} datasets found"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:19
+msgid "No datasets found"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:22
+msgid "{number} group found for \"{query}\""
+msgid_plural "{number} groups found for \"{query}\""
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:23
+msgid "No groups found for \"{query}\""
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:24
+msgid "{number} group found"
+msgid_plural "{number} groups found"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:25
+msgid "No groups found"
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:28
+msgid "{number} organization found for \"{query}\""
+msgid_plural "{number} organizations found for \"{query}\""
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:30
+msgid "No organizations found for \"{query}\""
+msgstr ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:31
+msgid "{number} organization found"
+msgid_plural "{number} organizations found"
+msgstr[0] ""
+msgstr[1] ""
+
+#: ckanext/odsh/templates/snippets/search_result_text.html:32
+msgid "No organizations found"
+msgstr ""
+
+#: ckanext/odsh/templates/user/login.html:3
+#: ckanext/odsh/templates/user/login.html:6
+#: ckanext/odsh/templates/user/login.html:12
+msgid "Login"
+msgstr ""
+
+#: ckanext/odsh/templates/user/login.html:25
+msgid "Forgotten your password?"
+msgstr ""
+
+#: ckanext/odsh/templates/user/login.html:28
+msgid "change password"
+msgstr ""
+
+#: ckanext/odsh/templates/user/logout.html:4
+msgid "Logout"
+msgstr ""
+
+#: ckanext/odsh/templates/user/logout.html:7
+#: ckanext/odsh/templates/user/logout.html:14
+msgid "Logged Out"
+msgstr ""
+
+#: ckanext/odsh/templates/user/logout.html:16
+msgid "You are now logged out."
+msgstr ""
+
+#: ckanext/odsh/templates/user/snippets/login_form.html:22
+msgid "Username"
+msgstr ""
+
+#: ckanext/odsh/templates/user/snippets/login_form.html:29
+msgid "Password"
+msgstr ""
+
+#: ckanext/odsh/templates/user/snippets/login_form.html:30
+msgid "enter password"
+msgstr ""
+
+#: ckanext/odsh/templates/user/snippets/login_form.html:34
+msgid "Remember me"
+msgstr ""
+
+#: ckanext/odsh/templates/user/snippets/login_form.html:40
+msgid "do Login"
+msgstr ""
+
diff --git a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-datarequest.po b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-datarequest.po
index fd21f87655c476ef50e6cff6dd164628a3ee79e0..bee83c54a7a62620fb761664ca9ef2dbb311abde 100644
--- a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-datarequest.po
+++ b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-datarequest.po
@@ -4,4 +4,4 @@
 #: ckanext/datarequests/templates/datarequests/snippets/datarequest_form.html:47
 #: ckanext/datarequests/templates/datarequests/snippets/new_datarequest_form.html:7
 msgid "Create Data Request"
-msgstr "Datenanfrage "
+msgstr "Dokumentanfrage "
diff --git a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.1.po b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.1.po
index aa5b97f3ba5f2e3045614f6a71261353a1271a00..a749e5df932a6c2c92a64805d8ba3be4d8033ec0 100644
--- a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.1.po
+++ b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.1.po
@@ -27,7 +27,7 @@ msgid "Start"
 msgstr "Start"
 
 msgid "Datasets"
-msgstr "Daten"
+msgstr "Dokumente"
 
 #: ckanext/odsh/templates/header.html:12
 msgid "Organizations"
diff --git a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.mo b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.mo
index 8be79d9fd27fdd19815a279d577a8af7bd65b6ed..e5231b5c445d99ba368944a4870058a2d41ed820 100644
Binary files a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.mo and b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.mo differ
diff --git a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.po b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.po
index 43b3fa3427fa45fda80caa70fad17077ee4f9521..63e6dee0ae0ba2803ce21295de817c91331f6462 100644
--- a/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.po
+++ b/ckanext/odsh/i18n/de/LC_MESSAGES/ckanext-odsh.po
@@ -24,8 +24,17 @@ msgid "Start typing…"
 msgstr "Bitte Schlagwort eingeben"
 
 
+
+msgid "datasets"
+msgstr "Datenästze"
+
+
+msgid "dataset"
+msgstr "Datensatz"
+
+
 msgid "Search dataset"
-msgstr "Nach Datensatz suchen"
+msgstr "Nach Datensätzen suchen"
 
 msgid "Search organizations"
 msgstr "Nach Herausgeber suchen"
@@ -115,7 +124,7 @@ msgid "to"
 msgstr "bis"
 
 msgid "Data-Upload"
-msgstr "Daten-Upload"
+msgstr "Datensatz-Upload"
 
 msgid "Enter name of the dataset"
 msgstr "Namen der Distribution eingeben"
@@ -339,10 +348,10 @@ msgid "Score"
 msgstr "Open-Data-Eigenschaften"
 
 msgid "Issued Ascending"
-msgstr "Veröffentlichungsdatum aufsteigend"
+msgstr "Veröffentlichungsdatum: Älteste zuerst"
 
 msgid "Issued Descending"
-msgstr "Veröffentlichungsdatum absteigend"
+msgstr "Veröffentlichungsdatum: Neueste zuerst"
 
 msgid "Name Resource"
 msgstr "Name Ressource"
@@ -407,7 +416,7 @@ msgid "tran"
 msgstr "Verkehr"
 
 msgid "Datarequest"
-msgstr "Datenvorschlag"
+msgstr "Datensatz"
 
 msgid "Add Request"
 msgstr "Datensatz vorschlagen"
@@ -461,3 +470,75 @@ msgstr "Datum absteigend"
 
 msgid "Date Ascending"
 msgstr "Datum aufsteigend"
+
+msgid "subject"
+msgstr "Informationsgegenstand"
+
+msgid "Subject must not be empty."
+msgstr "Bitte geben Sie einen Informationsgegenstand ein."
+
+msgid "type subject"
+msgstr "Informationsgegenstand eingeben"
+
+msgid "date start"
+msgstr "Startdatum"
+
+msgid "date end"
+msgstr "Enddatum"
+
+msgid "main nav menu"
+msgstr "Navigations-Hauptmenü"
+
+msgid "Start Date Descending"
+msgstr "Startdatum: Neueste zuerst"
+
+msgid "Start Date Ascending"
+msgstr "Startdatum: Älteste zuerst"
+
+msgid "End Date Descending"
+msgstr "Enddatum: Neueste zuerst"
+
+msgid "End Date Ascending"
+msgstr "Enddatum: Älteste zuerst"
+
+msgid "send an email"
+msgstr "E-Mail senden"
+
+msgid "enter search query for datasets"
+msgstr "Suchanfrage für Datensätze eingeben"
+
+msgid "Remove filters"
+msgstr "Filter deaktivieren"
+
+msgid "successor"
+msgstr "Nachfolger"
+
+msgid "predecessor"
+msgstr "Vorgänger"
+
+msgid "latest collection member"
+msgstr "Neuester Datensatz"
+
+msgid "language"
+msgstr "Sprache"
+
+
+msgid "Subject must be a known URI."
+msgstr "Bitte geben Sie einen Informationsgegenstand an"
+
+msgid "Documents"
+msgstr "Dokumente"
+
+msgid " category: "
+msgid_plural " categories: "
+msgstr[0] "Kategorie:"
+msgstr[1] "Kategorien:"
+
+msgid "Publisher"
+msgstr "Herausgeber"
+
+msgid "Name Ascending"
+msgstr "Name: A – Z"
+
+msgid "Name Descending"
+msgstr "Name: Z – A"
diff --git a/ckanext/odsh/lib/odsh_icap_client.cfg b/ckanext/odsh/lib/odsh_icap_client.cfg
deleted file mode 100644
index 654b57a83fc705ebff6769c89035df98f583432a..0000000000000000000000000000000000000000
--- a/ckanext/odsh/lib/odsh_icap_client.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-# the IP of the ICAP-Server
-host = 10.61.127.77
-
-# The port of the ICAP-Server
-port = 1344
-
-# the IP of the client-machine
-clientip = 127.0.0.1
diff --git a/ckanext/odsh/lib/odsh_icap_client.py b/ckanext/odsh/lib/odsh_icap_client.py
index fe8101eb25237f0a3ffb410f17821703e2e0f029..df3df673829d5ae31c74c860da45ff0f01ffb68f 100644
--- a/ckanext/odsh/lib/odsh_icap_client.py
+++ b/ckanext/odsh/lib/odsh_icap_client.py
@@ -1,37 +1,48 @@
 import socket
 import sys
 import time
-#from ckan.common import config
-#import logging
+import logging
+from ckan.common import config
+import ckan.plugins.toolkit as toolkit
 
-#log = logging.getLogger(__name__)
+log = logging.getLogger(__name__)
+
+def _read_from_config(key):
+    value = config.get(key, None)
+    if value is None:
+        _raise_KeyError_if_not_in_config(key)
+    return value
+
+def _raise_KeyError_if_not_in_config(key):
+    raise KeyError('key {} is not defined in ckan config file.'.format(key))
 
 
 class ODSHICAPRequest(object):
 
     def __init__(self, FILENAME, FILEBUFF):
-        config = []
-        self.HOST =  "10.61.127.77"  #'10.61.127.77'
-        self.PORT =  1344
-
-        self.CLIENTIP = '127.0.0.1'
+        try:
+            self.HOST = _read_from_config('ckanext.odsh.icap.host')
+            self.PORT = toolkit.asint(_read_from_config('ckanext.odsh.icap.port'))
+            self.CLIENTIP = _read_from_config('ckanext.odsh.icap.clientip')
+        except KeyError, e:
+            log.error(e)
         self.FILENAME = FILENAME
         self.FILEBUFF = FILEBUFF
-
+    
     def send(self):
-        #log.info("----- Starting ICAP-Request via RESPMOD -----")
+        print("----- Starting ICAP-Request via RESPMOD -----")
 
         # socket connect
         try:
             sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         except socket.error as msg:
-            #log.error(msg[1])
+            sys.stderr.write("[ERROR] %s\n" % msg[1])
             sys.exit(1)
 
         try:
             sock.connect((self.HOST, self.PORT))
         except socket.error as msg:
-            #log.error(msg[1])
+            sys.stderr.write("[ERROR] %s\n" % msg[1])
             sys.exit(2)
 
         # create and send header
@@ -46,7 +57,7 @@ class ODSHICAPRequest(object):
         data_response = self._recvall(sock)
         response_object = self._parse_response(data_response)
 
-        #log.info("----- Finished ICAP-Request via RESPMOD -----")
+        print("----- Finished ICAP-Request via RESPMOD -----")
 
         return response_object
 
@@ -74,36 +85,20 @@ class ODSHICAPRequest(object):
         return icapRequest
 
     def _sendfile(self, fileBuffer, sock):
-        #log.info('Start sending file.')
+        print('start sending file')
         PACK_SIZE = 1024 # in bytes
 
         l = fileBuffer.read(PACK_SIZE)
         while(l):
-            #log.info('Sending {} bytes of data...'.format(len(l)))
+            print('sending %d bytes of data...' % len(l))
             sock.send('{:02X}'.format(len(l)).encode())
             sock.send("\r\n".encode())
             sock.send(l)
             sock.send("\r\n".encode())
             l = fileBuffer.read(PACK_SIZE)
-
-    def _sendfile_old(self, fileName, sock):
-        #log.info('OLD: Start sending file.')
-        PACK_SIZE = 1024 # in bytes
-    
-        with open(fileName) as f:
-            l = f.read(PACK_SIZE)
-            while(l):
-                #log.info('Sending {} bytes of data...'.format(len(l)))
-                sock.send('{:02X}'.format(len(l)).encode())
-                sock.send("\r\n".encode())
-                sock.send(l)
-                sock.send("\r\n".encode())
-                l = f.read(PACK_SIZE)
-        #log.info('Done sending.')
-
     
     def _recvall(self, sock):
-        #log.info('Receiving response from icap server...')
+        print('receiving response from icap server')
         BUFF_SIZE = 4096 # 4 KiB
         data = b''
         while True:
@@ -115,7 +110,7 @@ class ODSHICAPRequest(object):
         return data
 
     def _parse_response(self, data_response):
-        #log.info('Parsing response...')
+        print('parsing response')
         lines = data_response.split('\r\n')
         http_status_code = self._parse_response_http_statuscode(lines)
         http_block = self._parse_block(lines, 'HTTP/1.1')
@@ -164,9 +159,7 @@ class ODSHParsedICAPResponse(object):
 
     def virus_found(self):
         if (self.http_status_code != 200) and (self.http_status_code != 403):
-            msg = 'Received an unknown http response code: {}'.format(self.http_status_code)
-            #log.warning(msg)
-            raise UnknownResponseException(msg)
+            raise UnknownResponseException('Received an unknown http response code: %d' % self.http_status_code)
         return self.http_status_code != 200
 
 
diff --git a/ckanext/odsh/lib/uploader.py b/ckanext/odsh/lib/uploader.py
index 93452f933405aec491cf34ffdff2881284c92618..ab89260a54cada77b3de43f81834e2ab600bd67f 100644
--- a/ckanext/odsh/lib/uploader.py
+++ b/ckanext/odsh/lib/uploader.py
@@ -1,23 +1,77 @@
 import ckan.logic as logic
-from ckan.lib.uploader import ResourceUpload
+from ckan.lib.uploader import ResourceUpload, Upload
+import ckan.plugins.toolkit as toolkit
+from pylons import config
+
 from odsh_icap_client import ODSHICAPRequest
+import logging
+import hashlib
+
+log = logging.getLogger(__name__)
+
+
+def _icap_virus_found(filename, upload_file):
+    # the flag skip_icap_virus_check in can be used during development
+    skip_icap_virus_check = toolkit.asbool(
+        config.get('ckanext.odsh.skip_icap_virus_check', 'False')
+    )
+    if skip_icap_virus_check:
+        log.debug("WARNING: icap virus check skipped, remove parameter ckanext.odsh.skip_icap_virus_check from ckan's ini file")
+        return False
+    if filename and upload_file:
+        response_object = ODSHICAPRequest(filename, upload_file).send()
+        return response_object.virus_found()
+
 
-#import logging
+def _raise_validation_error_if_virus_found(filename, upload_file):
+    if _icap_virus_found(filename, upload_file):
+        raise logic.ValidationError({'upload': ['Virus gefunden']})
 
-#log = logging.getLogger(__name__)
 
+def calculate_hash(upload_file):
+    upload_file.seek(0)
+    hash_md5 = hashlib.md5()
+    for chunk in iter(lambda: upload_file.read(4096), b""):
+            hash_md5.update(chunk)
+    return hash_md5.hexdigest()
+    #return hashlib.md5(upload_file.read()).hexdigest() 
+
+
+def _raise_validation_error_if_hash_values_differ(upload_file, resource):
+    hash_from_resource = resource.get('hash') 
+    if hash_from_resource:
+        hash_from_calculation = calculate_hash(upload_file)
+        if not hash_from_calculation == hash_from_resource:
+            log.debug('hash from calculation: {}'.format(hash_from_calculation))
+            log.debug('hash from resource: {}'.format(hash_from_resource))
+            raise logic.ValidationError({'upload': ['Berechneter Hash und mitgelieferter Hash sind unterschiedlich']})
+            
 
 class ODSHResourceUpload(ResourceUpload):
 
     def __init__(self, resource):
-        #log.info("Resource({}) uploaded.".format(resource))
+        log.debug("Resource({}) uploaded.".format(resource))
         super(ODSHResourceUpload, self).__init__(resource)
-        if self._icap_virus_found():
-            #log.info("Found Virus!")
-            raise logic.ValidationError({'upload': ['Virus gefunden']})
-        
-    def _icap_virus_found(self):
-        if self.filename and self.upload_file:
-            response_object = ODSHICAPRequest(self.filename, self.upload_file).send()
-            return response_object.virus_found()
-        
+        if hasattr(self, 'filename') and hasattr(self, 'upload_file'):
+            _raise_validation_error_if_virus_found(self.filename, self.upload_file)
+            _raise_validation_error_if_hash_values_differ(self.upload_file, resource)
+
+
+class ODSHUpload(Upload):
+    '''
+    custom uploader to upload resources and group images
+    see https://docs.ckan.org/en/ckan-2.7.3/extensions/plugin-interfaces.html?highlight=iuploader#ckan.plugins.interfaces.IUploader
+    this uploader object hooks into the upload method in order to 
+    scan for viruses within the uploaded content
+    '''
+
+    def __init__(self, upload_to, old_filename=None):
+        super(ODSHUpload, self).__init__(upload_to, old_filename)
+    
+    def update_data_dict(self, data_dict, url_field, file_field, clear_field):
+        super(ODSHUpload, self).update_data_dict(data_dict, url_field, file_field, clear_field)
+    
+    def upload(self, max_size=2):
+        if hasattr(self, 'filename') and hasattr(self, 'upload_file'):
+            _raise_validation_error_if_virus_found(self.filename, self.upload_file)
+        super(ODSHUpload, self).upload(max_size)
\ No newline at end of file
diff --git a/ckanext/odsh/logic/action.py b/ckanext/odsh/logic/action.py
index 6b952764c6422b470c93eb1103c3f3fecc1a6396..481a72ac130bf8447c89be96dcc27f6ddde28832 100644
--- a/ckanext/odsh/logic/action.py
+++ b/ckanext/odsh/logic/action.py
@@ -1,7 +1,10 @@
 import logging
+import ckan.logic as logic
+from ckan.logic.action.update import user_update
 from ckan.logic.action.create import package_create, user_create, group_member_create
 import ckan.model as model
 import ckan.lib.dictization.model_dictize as model_dictize
+from ckan.lib.munge import munge_title_to_name
 import ckan.plugins.toolkit as toolkit
 from ckan.lib.search.common import (
     make_connection, SearchError, SearchQueryError
@@ -13,8 +16,11 @@ log = logging.getLogger(__name__)
 
 
 def odsh_package_create(context, data_dict):
+    pkg_type = data_dict.get('type', None)
+    if pkg_type == 'collection':
+        return package_create(context, data_dict)
     munge_increment_name(data_dict)
-    if data_dict.get('type', None) != 'dataset':
+    if pkg_type != 'dataset':
         return package_create(context, data_dict)
     issued = False
     for extra in data_dict.get('extras'):
@@ -27,26 +33,51 @@ def odsh_package_create(context, data_dict):
 
 
 def munge_increment_name(data_dict):
-    from ckan.lib.munge import munge_title_to_name
-
-    name_base = name = munge_title_to_name(data_dict['title'])
-    pkg = model.Package.get(name)
-    i = 0
-    while pkg:
-        i += 1
-        name = name_base + str(i)
+    title_from_dict = data_dict.get('title')
+    if title_from_dict:
+        name_base = name = munge_title_to_name(title_from_dict)
         pkg = model.Package.get(name)
-    log.debug('name: %s' % name)
-    data_dict['name'] = name
+        i = 0
+        while pkg:
+            i += 1
+            name = name_base + str(i)
+            pkg = model.Package.get(name)
+        log.debug('name: %s' % name)
+        data_dict['name'] = name
+
 
+def check_password(password):
+    return (len(password) >= 8 and
+            any(c.islower() for c in password) and
+            any(c.isupper() for c in password) and
+            any((c.isalpha()==False) for c in password)) #Number or Special character
+
+PASSWORD_ERROR_MESSAGE =  {'security': ['Passwort muss mindestens acht Zeichen, einen Gross-, einen Kleinbuchstaben und entweder eine Zahl oder ein Sondernzeichen enthalten!']}       
 
 def odsh_user_create(context, data_dict):
     model = context['model']
-    user = user_create(context, data_dict)
-    groups = toolkit.get_action('group_list')(data_dict={'all_fields': False})
-    for group in groups:
-        group_member_create(context, {'id': group, 'username': user.get('name'), 'role': 'member'})
-    return model_dictize.user_dictize(model.User.get(user.get('name')), context)
+    password = data_dict.get('password')
+    if not password:
+        password = data_dict.get('password1')
+    if check_password(password):
+        user = user_create(context, data_dict)
+        groups = toolkit.get_action('group_list')(data_dict={'all_fields': False})
+    
+        for group in groups:
+            group_member_create(context, {'id': group, 'username': user.get('name'), 'role': 'member'})
+        return model_dictize.user_dictize(model.User.get(user.get('name')), context)
+    else:
+        raise logic.ValidationError(PASSWORD_ERROR_MESSAGE)          
+  
+def tpsh_user_update(context, data_dict):
+      password = data_dict.get('password')
+      if not password:
+        password = data_dict.get('password1')
+      if password and not check_password(password):
+          raise logic.ValidationError(PASSWORD_ERROR_MESSAGE)      
+      return user_update(context, data_dict)
+
+
 
 
 @toolkit.side_effect_free
diff --git a/ckanext/odsh/matomo.py b/ckanext/odsh/matomo.py
index a3fd6fc1ae16564f5ad5eeed7de94e04f5d2c5a3..15ac1b5c7c70e3413fab7051a14bb6f13e4b0c93 100644
--- a/ckanext/odsh/matomo.py
+++ b/ckanext/odsh/matomo.py
@@ -4,7 +4,16 @@ from ckan.common import c, request
 from pylons import config
 import logging
 from ckan.plugins.toolkit import enqueue_job
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
 
+def do_if_use_matomo(func):
+    def wrapper(*args, **kwargs):
+        use_matomo = helpers_tpsh.use_matomo()
+        if use_matomo:
+            return func(*args, **kwargs)
+    return wrapper
+
+@do_if_use_matomo
 def create_matomo_request(userId=None):
     headers = {
         'HTTP_USER_AGENT': request.headers.get('User-Agent'),
diff --git a/ckanext/odsh/odsh_logger.py b/ckanext/odsh/odsh_logger.py
new file mode 100644
index 0000000000000000000000000000000000000000..54eea1b0bd88889c57c8b9d761580e83f654ff34
--- /dev/null
+++ b/ckanext/odsh/odsh_logger.py
@@ -0,0 +1,53 @@
+from multiline_formatter.formatter import MultilineMessagesFormatter
+import ckan.plugins as plugins
+import ckan.plugins.toolkit as toolkit
+
+
+class OdshLogger(MultilineMessagesFormatter):
+    multiline_marker = '...'
+    multiline_fmt = multiline_marker + ' : %(message)s'
+
+    def format(self, record):
+        """
+        This is mostly the same as logging.Formatter.format except for the splitlines() thing.
+        This is done so (copied the code) to not make logging a bottleneck. It's not lots of code
+        after all, and it's pretty straightforward.
+        """
+        endl_marker = '\n... : ";'
+        record.message = record.getMessage()
+        if self.usesTime():
+            record.asctime = self.formatTime(record, self.datefmt)
+        if '\n' in record.message:
+            splitted = record.message.splitlines()
+            output = self._fmt % dict(record.__dict__, message=splitted.pop(0))
+            output += ' ' + self.multiline_marker % record.__dict__ + '\n'
+            output += '\n'.join(
+                self.multiline_fmt % dict(record.__dict__, message=line)
+                for line in splitted
+            )
+            output = output.replace('"', '\\"')
+            output += endl_marker
+        else:
+            output = self._fmt % record.__dict__
+
+        if record.exc_info:
+            # Cache the traceback text to avoid converting it multiple times
+            # (it's constant anyway)
+            if not record.exc_text:
+                record.exc_text = self.formatException(record.exc_info)
+        if record.exc_text:
+            output += ' ' + self.multiline_marker % record.__dict__ + '\n'
+            try:
+                output += '\n'.join(
+                    self.multiline_fmt % dict(record.__dict__, message=line)
+                    for index, line in enumerate(record.exc_text.splitlines())
+                )
+                output = output.replace('"', '\\"')
+                output += endl_marker
+            except UnicodeError:
+                output += '\n'.join(
+                    self.multiline_fmt % dict(record.__dict__, message=line)
+                    for index, line
+                    in enumerate(record.exc_text.decode(sys.getfilesystemencoding(), 'replace').splitlines())
+                )
+        return output
\ No newline at end of file
diff --git a/ckanext/odsh/pdf_to_thumbnail/__init__.py b/ckanext/odsh/pdf_to_thumbnail/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ckanext/odsh/pdf_to_thumbnail/action.py b/ckanext/odsh/pdf_to_thumbnail/action.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd5d713086311721f593ba276ea9d650f1e77f87
--- /dev/null
+++ b/ckanext/odsh/pdf_to_thumbnail/action.py
@@ -0,0 +1,30 @@
+# ckan
+import ckan.plugins.toolkit as toolkit
+import ckan.lib.helpers as helpers
+from ckan.logic.action.update import package_update
+from ckan.logic.action.delete import package_delete
+
+#from thumbnail
+import thumbnail as thumbnail
+
+
+def before_package_delete(context, package_id_dict):
+    pkg_dict = toolkit.get_action('package_show')(context, package_id_dict)
+    if helpers.check_access('package_delete', pkg_dict):
+        thumbnail.remove_thumbnail(context)
+    return package_delete(context, package_id_dict)
+    
+def before_package_update(context, pkg_dict):
+    if helpers.check_access('package_update', pkg_dict):
+        package_id =pkg_dict.get('id') 
+        package = toolkit.get_action('package_show')(context, {'id': package_id})
+        old_private = package.get('private')
+        new_private = pkg_dict.get('private')
+        old_filename = package.get('thumbnail')
+        if old_filename:
+            if str(old_private) != str(new_private):
+                new_filename = thumbnail.change_filepath(old_filename)
+                pkg_dict['extras'].append({'key': 'thumbnail', 'value': new_filename})
+            elif not pkg_dict.get('thumbnail'): 
+                pkg_dict['extras'].append({'key': 'thumbnail', 'value': old_filename})
+    return package_update(context, pkg_dict)
\ No newline at end of file
diff --git a/ckanext/odsh/pdf_to_thumbnail/helpers.py b/ckanext/odsh/pdf_to_thumbnail/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..faddfaa0691b19f158df50b13b352e9ff2a642c5
--- /dev/null
+++ b/ckanext/odsh/pdf_to_thumbnail/helpers.py
@@ -0,0 +1,27 @@
+
+from ckan.lib.helpers import is_url, url_for
+
+def thumbnail_namespace(filename):
+    return "/" + filename
+
+def get_download_link_for_thumbnail(package):
+    resources = package.get('resources')
+    for resource in resources[::-1]:
+        url_type =resource.get('url_type')
+        mimetype = resource.get('mimetype')
+        if url_type == 'upload' and mimetype == 'application/pdf':
+            package_id = resource.get('package_id')
+            resource_id = resource.get('id')
+            pre_resource_url = resource.get('url')
+            if is_url(pre_resource_url):
+                url_resource = pre_resource_url
+            else:
+                url_resource = url_for(controller='package',
+                                    action='resource_download',
+                                    id=package_id,
+                                    resource_id=resource_id,
+                                    filename=pre_resource_url,
+                                    qualified = True)
+            
+            
+            return url_resource
diff --git a/ckanext/odsh/pdf_to_thumbnail/plugin.py b/ckanext/odsh/pdf_to_thumbnail/plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..715235990b6515a9b9d86a2a4f063c8da5e2bf7e
--- /dev/null
+++ b/ckanext/odsh/pdf_to_thumbnail/plugin.py
@@ -0,0 +1,58 @@
+import os 
+
+
+#from ckan
+import ckan.plugins as plugins
+
+#pdf_to_thumbnail 
+import thumbnail 
+import action as thumbnail_action
+import helpers as thumbnail_helpers
+
+import logging
+log = logging.getLogger(__name__)
+
+
+class ThumbnailPlugin(plugins.SingletonPlugin):
+    plugins.implements(plugins.IResourceController, inherit=True)
+    plugins.implements(plugins.IConfigurer, inherit=True)
+    plugins.implements(plugins.IActions, inherit=True)
+    plugins.implements(plugins.ITemplateHelpers)
+
+
+#IResourceController
+    def after_create(self, context, resource):        
+        _, filename = thumbnail.create_thumbnail(context, resource)
+        thumbnail.write_thumbnail_into_package(context, resource, filename)
+        
+    def after_update(self, context, resource):
+        thumbnail.check_and_create_thumbnail_after_update(context, resource)
+                
+    def after_delete(self, context, resources):
+        thumbnail.create_thumbnail_for_last_resource(context, resources)
+            
+#IConfigurer 
+
+    def update_config(self, config_):
+        storage_path = config_.get('ckan.storage_path')
+        public_dir = os.path.join(storage_path, 'thumbnail')
+        if config_.get('extra_public_paths'):
+            config_['extra_public_paths'] += ',' + public_dir
+        else:
+            config_['extra_public_paths'] = public_dir
+
+#IActions
+
+    def get_actions(self):
+        return {'package_delete': thumbnail_action.before_package_delete,
+                'package_update': thumbnail_action.before_package_update 
+                }
+
+#ITemplateHelpers
+
+    def get_helpers(self):
+        
+        return {
+                'thumbnail_namespace':thumbnail_helpers.thumbnail_namespace,
+                'thumbail_get_download_link':thumbnail_helpers.get_download_link_for_thumbnail
+                }
diff --git a/ckanext/odsh/pdf_to_thumbnail/thumbnail.py b/ckanext/odsh/pdf_to_thumbnail/thumbnail.py
new file mode 100644
index 0000000000000000000000000000000000000000..768cfdbfcfedc0a9b8e84fb6bea8c71472fd4524
--- /dev/null
+++ b/ckanext/odsh/pdf_to_thumbnail/thumbnail.py
@@ -0,0 +1,170 @@
+import os
+import tempfile
+import magic
+from pdf2image import convert_from_bytes
+import logging
+from ckan.common import config 
+import urllib2
+import requests
+
+import binascii
+import ckan.plugins.toolkit as toolkit
+import ckan.logic as logic
+#from extension
+#from ckanext.odsh.lib.uploader import raise_validation_error_if_virus_found
+
+log = logging.getLogger(__name__)
+ 
+
+def get_filename_from_context(context):
+    package = context.get('package')
+    package_id = package.id
+    package= toolkit.get_action('package_show')(context, {'id': package_id})
+    thumbnail = package.get('thumbnail') 
+    return  thumbnail
+
+def get_filepath_for_thumbnail(filename):
+    if filename:
+        return config.get('ckan.storage_path') + "/thumbnail/" + filename
+    return config.get('ckan.storage_path') + "/thumbnail/"
+
+def concatenate_filename(filename):
+    return filename + ".jpg"
+
+def get_filepath_to_resource(resource):
+    resource_id = resource.get('id')
+    directory = config.get('ckan.storage_path') + '/resources/'
+    #looked up how resources are saved, by locating the keyword resources in the OS 
+    path = directory + resource_id[0:3] + '/' + resource_id[3:6] + '/' +  resource_id[6:]
+    return path
+
+def random_filename():
+    number = binascii.b2a_hex(os.urandom(15))
+    filename = 'thumbnail_picture_' + str(number)    
+    full_filename = concatenate_filename(filename)
+    filepath = get_filepath_for_thumbnail(full_filename)
+    if os.path.exists(filepath):
+        filename = random_filename()
+    return filename
+
+def change_filepath(old_filename):    
+    old_filepath = get_filepath_for_thumbnail(old_filename)
+    new_filename = concatenate_filename(random_filename())
+    new_filepath = get_filepath_for_thumbnail(new_filename)
+    try:
+        os.renames(old_filepath, new_filepath)
+        return new_filename
+    except OSError:
+        log.warning('The file path "{}"  of package was not found.'.format(old_filepath))
+     
+
+def create_thumbnail_from_file(file, old_filename):
+    width = config.get('ckan.thumbnail.size.width', 410)
+    filename = random_filename()
+    file.seek(0)
+    file_read = file.read()
+    directory = get_filepath_for_thumbnail('')
+    if old_filename:
+        old_filepath = get_filepath_for_thumbnail(concatenate_filename(old_filename))
+        if os.path.exists(old_filepath):
+            os.remove(old_filepath)
+    convert_from_bytes(file_read,
+                       size=(width, None),
+                       output_folder=directory,
+                       output_file=filename,
+                       single_file=True,
+                       first_page=0,
+                       last_page=0,
+                       fmt='jpg'
+                       )
+    return concatenate_filename(filename)
+
+
+def create_thumbnail_from_url(resource, old_filename):
+    resource_url = resource.get('url')
+    request = urllib2.Request(resource_url)
+    response = urllib2.urlopen(request, timeout = 100000) 
+    
+    
+    if response.code == 200:
+        filetowrite = response.read()
+        # function is set to private in ckanext.odsh.lib.uploader
+        # raise_validation_error_if_virus_found(filetowrite, response.read())
+        file_type = magic.from_buffer(response.read(), mime = True)
+        header = response.headers
+        resource_size = header.get('Content-Length')
+        
+            
+        max_available_memory = config.get('ckan.max_available_memory', 250000000)  #In Bytes ca. 250 MB
+        with tempfile.SpooledTemporaryFile(max_size=max_available_memory) as file:
+            file.write(filetowrite)
+            
+            new_filename = create_thumbnail_from_file(file, old_filename)        
+            return True, new_filename
+
+def create_thumbnail_from_memory(resource, old_filename):
+    path = get_filepath_to_resource(resource)
+    file_type = magic.from_file(path, mime = True)
+    if file_type == 'application/pdf':
+        with open(path, 'rb') as file:
+            new_filename = create_thumbnail_from_file(file, old_filename)
+        is_PDF = True
+        return is_PDF, new_filename
+    else:
+        is_PDF = False
+        return is_PDF,  None
+
+def remove_thumbnail(context):
+    old_filename = get_filename_from_context(context)
+    if old_filename:
+        old_filepath = get_filepath_for_thumbnail(old_filename)
+        if os.path.exists(old_filepath):
+            os.remove(old_filepath)
+
+def create_thumbnail(context, resource):
+    log.debug('create_thumbnail')
+    old_filename = get_filename_from_context(context)
+    url_type = resource.get('url_type')
+    if url_type == 'upload':
+        is_PDF,  filename = create_thumbnail_from_memory(resource, old_filename)
+    else:
+        is_PDF,  filename = create_thumbnail_from_url(resource, old_filename)
+    return is_PDF,  filename   
+
+def check_and_create_thumbnail_after_update(context, resource):
+    log.debug('check_and_create_thumbnail_after_update')
+    package_id = resource.get('package_id')
+    package = toolkit.get_action('package_show')(context, {'id': package_id})
+    resources = package.get('resources')
+    if len(resources) > 0:
+        last_resource = resources.pop()
+        last_resource_id = last_resource.get('id')
+        resource_id = resource.get('id')
+    if last_resource_id == resource_id and resource.get('url_type') != 'upload':
+        is_PDF,  filename = create_thumbnail(context, resource)
+        if is_PDF:
+            write_thumbnail_into_package(context, resource, filename)  
+        
+
+def create_thumbnail_for_last_resource(context, resources):
+    if len(resources) > 0:
+        last_resource = resources.pop()
+        is_PDF, filename = create_thumbnail(context, last_resource)
+        if not is_PDF:
+            create_thumbnail_for_last_resource(context, resources)
+        else:
+            write_thumbnail_into_package(context, last_resource, filename)
+    else:
+        remove_thumbnail(context)
+        package = context.get('package')
+        package_id = package.id
+        package= toolkit.get_action('package_show')(context, {'id': package_id})
+        package.update({'thumbnail': None})
+        toolkit.get_action('package_update')(context, package)
+
+def write_thumbnail_into_package(context, resource, filename):
+        package_id = resource.get('package_id')
+        package = toolkit.get_action('package_show')(context, {'id': package_id})
+        if filename:
+            package.update({'thumbnail': filename})
+        toolkit.get_action('package_update')(context, package)
diff --git a/ckanext/odsh/plugin.py b/ckanext/odsh/plugin.py
index add7226bd682d4e49eaff5ff131bf3975f875378..ea003f69bb8abac9affd2421dd9e33613f81c3f3 100644
--- a/ckanext/odsh/plugin.py
+++ b/ckanext/odsh/plugin.py
@@ -1,341 +1,266 @@
-from multiline_formatter.formatter import MultilineMessagesFormatter
-import datetime
-import json
-import ckan.plugins as plugins
-import ckan.plugins.toolkit as toolkit
-from ckan.lib.plugins import DefaultTranslation
-from ckan.lib.plugins import DefaultDatasetForm
-from ckan.logic.validators import tag_string_convert
-from ckan.logic.schema import default_extras_schema
-from ckan.common import OrderedDict
-from ckanext.odsh.lib.uploader import ODSHResourceUpload
-import ckan.lib.helpers as helpers
-import helpers as odsh_helpers
-import ckanext.odsh.logic.action as action
-from ckanext.dcat.interfaces import IDCATRDFHarvester
-from ckanext.dcatde.extras import Extras
-
-from routes.mapper import SubMapper
-from pylons import config
+# import from third parties
 from dateutil.parser import parse
-from ckan import model
-
-import ckan.plugins as p
-
+import json
 import logging
-import validation
-import precondition
-
+from multiline_formatter.formatter import MultilineMessagesFormatter
+import os
+from pylons import config
+from routes.mapper import SubMapper
 import sys
 
-log = logging.getLogger(__name__)
-
-# from functools import wraps
-# from flask import Flask, redirect, jsonify
-# app = Flask(__name__)
-
-# def get_http_exception_handler(app):
-#     """Overrides the default http exception handler to return JSON."""
-#     handle_http_exception = app.handle_http_exception
-#     @wraps(handle_http_exception)
-#     def ret_val(exception):
-#         print("HEHREHR")
-#         exc = handle_http_exception(exception)
-#         return jsonify({'code':exc.code, 'message':exc.description}), exc.code
-#     return ret_val
+# imports from ckan
+from ckan.common import OrderedDict
+import ckan.lib.helpers as helpers
+from ckan.lib.plugins import DefaultTranslation, DefaultDatasetForm
+from ckan.logic.validators import tag_string_convert
+import ckan.plugins as plugins
+import ckan.plugins.toolkit as toolkit
+import ckan.model as model
 
-# # Override the HTTP exception handler.
-# app.handle_http_exception = get_http_exception_handler(app)
+# imports from this extension
+import ckanext.odsh.helpers as odsh_helpers
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
+import ckanext.odsh.helper_pkg_dict as helper_pkg_dict
+from helper_pkg_dict import HelperPgkDict
+import ckanext.odsh.logic.action as action
+import ckanext.odsh.validation as validation
+import ckanext.odsh.search as search
+from ckanext.odsh.odsh_logger import OdshLogger
+import ckanext.odsh.tools as tools
 
 
-# def my_except_hook(exctype, value, traceback):
-#     print('GOT excepton')
-#     log.exception(value)
-#     sys.__excepthook__(exctype, value, traceback)
-# print('INSTALL EX')
-# sys.excepthook = my_except_hook
+log = logging.getLogger(__name__)
 
 _ = toolkit._
 
-
-class OdshLogger(MultilineMessagesFormatter):
-    multiline_marker = '...'
-    multiline_fmt = multiline_marker + ' : %(message)s'
-
-    def format(self, record):
-        """
-        This is mostly the same as logging.Formatter.format except for the splitlines() thing.
-        This is done so (copied the code) to not make logging a bottleneck. It's not lots of code
-        after all, and it's pretty straightforward.
-        """
-        endl_marker = '\n... : ";'
-        record.message = record.getMessage()
-        if self.usesTime():
-            record.asctime = self.formatTime(record, self.datefmt)
-        if '\n' in record.message:
-            splitted = record.message.splitlines()
-            output = self._fmt % dict(record.__dict__, message=splitted.pop(0))
-            output += ' ' + self.multiline_marker % record.__dict__ + '\n'
-            output += '\n'.join(
-                self.multiline_fmt % dict(record.__dict__, message=line)
-                for line in splitted
-            )
-            output = output.replace('"', '\\"')
-            output += endl_marker
-        else:
-            output = self._fmt % record.__dict__
-
-        if record.exc_info:
-            # Cache the traceback text to avoid converting it multiple times
-            # (it's constant anyway)
-            if not record.exc_text:
-                record.exc_text = self.formatException(record.exc_info)
-        if record.exc_text:
-            output += ' ' + self.multiline_marker % record.__dict__ + '\n'
-            try:
-                output += '\n'.join(
-                    self.multiline_fmt % dict(record.__dict__, message=line)
-                    for index, line in enumerate(record.exc_text.splitlines())
-                )
-                output = output.replace('"', '\\"')
-                output += endl_marker
-            except UnicodeError:
-                output += '\n'.join(
-                    self.multiline_fmt % dict(record.__dict__, message=line)
-                    for index, line
-                    in enumerate(record.exc_text.decode(sys.getfilesystemencoding(), 'replace').splitlines())
-                )
-        return output
-
-
-def odsh_get_facet_items_dict(name, limit=None):
-    '''
-    Gets all facets like 'get_facet_items_dict' but sorted alphabetically
-    instead by count.
-    '''
-    facets = helpers.get_facet_items_dict(name, limit)
-    facets.sort(key=lambda it: (it['display_name'].lower(), -it['count']))
-    return facets
-
-
-def odsh_main_groups():
-    '''Return a list of the groups to be shown on the start page.'''
-
-    # Get a list of all the site's groups from CKAN, sorted by number of
-    # datasets.
-    groups = toolkit.get_action('group_list')(
-        data_dict={'all_fields': True})
-
-    return groups
-
-
-def odsh_now():
-    return helpers.render_datetime(datetime.datetime.now(), "%Y-%m-%d")
-
-
-def odsh_group_id_selected(selected, group_id):
-    if type(selected) is not list:
-        selected = [selected]
-    for g in selected:
-        if (isinstance(g, basestring) and group_id == g) or (type(g) is dict and group_id == g['id']):
-            return True
-
-    return False
-
-
-def remove_route(map, routename):
-    route = None
-    for i, r in enumerate(map.matchlist):
-
-        if r.name == routename:
-            route = r
-            break
-    if route is not None:
-        map.matchlist.remove(route)
-        for key in map.maxkeys:
-            if key == route.maxkeys:
-                map.maxkeys.pop(key)
-                map._routenames.pop(route.name)
-                break
-
-
-class OdshIcapPlugin(plugins.SingletonPlugin):
-    plugins.implements(plugins.IUploader, inherit=True)
-
-    def get_resource_uploader(self, data_dict):
-        return ODSHResourceUpload(data_dict)
-
-
-class OdshAutocompletePlugin(plugins.SingletonPlugin):
+class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm):
     plugins.implements(plugins.IActions)
+    plugins.implements(plugins.IConfigurer)
+    plugins.implements(plugins.IDatasetForm)
+    plugins.implements(plugins.IFacets)
+    plugins.implements(plugins.IPackageController, inherit=True)
+    plugins.implements(plugins.IRoutes, inherit=True)
+    plugins.implements(plugins.ITemplateHelpers)
+    plugins.implements(plugins.ITranslation)
+    plugins.implements(plugins.IValidators)
+    plugins.implements(plugins.IResourceController, inherit=True)
 
-    def get_actions(self):
-        return {'autocomplete': action.autocomplete}
+    
+    # IActions
 
+    def get_actions(self):
+        return {'package_create': action.odsh_package_create,
+                'user_update':action.tpsh_user_update,
+                'user_create': action.odsh_user_create}
 
-class OdshHarvestPlugin(plugins.SingletonPlugin):
-    plugins.implements(plugins.IRoutes, inherit=True)
-    plugins.implements(plugins.IConfigurer)
+    
+    # IConfigurer
 
     def update_config(self, config_):
-        toolkit.add_template_directory(config_, 'harvest_templates')
-    plugins.implements(plugins.IRoutes, inherit=True)
+        toolkit.add_template_directory(config_, 'templates')
+        toolkit.add_public_directory(config_, 'public')
+        toolkit.add_resource('fanstatic', 'odsh')
 
-    def before_map(self, map):
-        DATASET_TYPE_NAME = 'harvest'
-        controller = 'ckanext.odsh.controller:OdshHarvestController'
-
-        map.connect('{0}_delete'.format(DATASET_TYPE_NAME), '/' +
-                    DATASET_TYPE_NAME + '/delete/:id', controller=controller, action='delete')
-        map.connect('{0}_refresh'.format(DATASET_TYPE_NAME), '/' + DATASET_TYPE_NAME + '/refresh/:id', controller=controller,
-                    action='refresh')
-        map.connect('{0}_admin'.format(DATASET_TYPE_NAME), '/' +
-                    DATASET_TYPE_NAME + '/admin/:id', controller=controller, action='admin')
-        map.connect('{0}_about'.format(DATASET_TYPE_NAME), '/' +
-                    DATASET_TYPE_NAME + '/about/:id', controller=controller, action='about')
-        map.connect('{0}_clear'.format(DATASET_TYPE_NAME), '/' +
-                    DATASET_TYPE_NAME + '/clear/:id', controller=controller, action='clear')
-
-        map.connect('harvest_job_list', '/' + DATASET_TYPE_NAME +
-                    '/{source}/job', controller=controller, action='list_jobs')
-        map.connect('harvest_job_show_last', '/' + DATASET_TYPE_NAME +
-                    '/{source}/job/last', controller=controller, action='show_last_job')
-        map.connect('harvest_job_show', '/' + DATASET_TYPE_NAME +
-                    '/{source}/job/{id}', controller=controller, action='show_job')
-        map.connect('harvest_job_abort', '/' + DATASET_TYPE_NAME +
-                    '/{source}/job/{id}/abort', controller=controller, action='abort_job')
-
-        map.connect('harvest_object_show', '/' + DATASET_TYPE_NAME +
-                    '/object/:id', controller=controller, action='show_object')
-        map.connect('harvest_object_for_dataset_show', '/dataset/harvest_object/:id',
-                    controller=controller, action='show_object', ref_type='dataset')
-
-        org_controller = 'ckanext.harvest.controllers.organization:OrganizationController'
-        map.connect('{0}_org_list'.format(DATASET_TYPE_NAME), '/organization/' +
-                    DATASET_TYPE_NAME + '/' + '{id}', controller=org_controller, action='source_list')
-        return map
 
-    def after_map(self, map):
-        return map
+    # IDatasetForm
 
+    def package_types(self):
+        # This plugin doesn't handle any special package types, it just
+        # registers itself as the default (above).
+        return []
 
-class OdshDCATHarvestPlugin(plugins.SingletonPlugin):
-    plugins.implements(IDCATRDFHarvester, inherit=True)
+    def is_fallback(self):
+        # Return True to register this plugin as the default handler for
+        # package types not handled by any other IDatasetForm plugin.
+        return True
+    
+    def create_package_schema(self):
+        schema = super(OdshPlugin, self).create_package_schema()
+        self._update_schema(schema)
+        self._tpsh_update_create_or_update_package_schema(schema)
+        return schema
 
-    def before_update(self, harvest_object, dataset_dict, temp_dict):
+    def update_package_schema(self):
+        schema = super(OdshPlugin, self).update_package_schema()
+        self._update_schema(schema)
+        self._tpsh_update_create_or_update_package_schema(schema)
+        return schema
 
-        existing_package_dict = self._get_existing_dataset(harvest_object.guid)
-        new_dataset_extras = Extras(dataset_dict['extras'])
-        if new_dataset_extras.key('modified') and \
-                new_dataset_extras.value('modified') < existing_package_dict.get('metadata_modified'):
-            log.info("Modified date of new dataset is not newer than "
-                     + "the already exisiting dataset, ignoring new one.")
-            dataset_dict.clear()
+    def show_package_schema(self):
+        schema = super(OdshPlugin, self).show_package_schema()
+        self._tpsh_update_show_package_schema(schema)
+        return schema
 
-    def _get_existing_dataset(self, guid):
-        '''
-        Checks if a dataset with a certain guid extra already exists
+    def _update_schema(self, schema):
+        for field in ['title', 'license_id']:
+            schema.update({field: [toolkit.get_converter('not_empty')]})
+        
+        for i, item in enumerate(schema['tags']['name']):
+            if item == toolkit.get_validator('tag_name_validator'):
+                schema['tags']['name'][i] = toolkit.get_validator(
+                    'odsh_tag_name_validator')
+        for i, item in enumerate(schema['tag_string']):
+            if item == tag_string_convert:
+                schema['tag_string'][i] = validation.tag_string_convert
 
-        Returns a dict as the ones returned by package_show
-        '''
+        schema['resources'].update({
+            'url': [toolkit.get_converter('not_empty')],
+            'format': [toolkit.get_converter('not_empty')],
+        })
 
-        datasets = model.Session.query(model.Package.id) \
-                                .join(model.PackageExtra) \
-                                .filter(model.PackageExtra.key == 'guid') \
-                                .filter(model.PackageExtra.value == guid) \
-                                .filter(model.Package.state == 'active') \
-                                .all()
+        schema['extras'].update({
+            'key': [
+                toolkit.get_converter('known_spatial_uri'),
+                toolkit.get_converter('validate_licenseAttributionByText'),
+            ]
+        })
+        schema.update(
+            {'__extras':  [toolkit.get_converter('odsh_validate_extras')]})
 
-        if not datasets:
-            return None
-        elif len(datasets) > 1:
-            log.error('Found more than one dataset with the same guid: {0}'
-                      .format(guid))
+    def _tpsh_update_create_or_update_package_schema(self, schema):
+        schema.update({
+            'language': [
+                toolkit.get_validator('ignore_missing'),
+                toolkit.get_converter('convert_to_extras')
+            ],
+            'thumbnail': [
+                toolkit.get_validator('ignore_missing'),
+                toolkit.get_converter('convert_to_extras')
+            ],
 
-        return p.toolkit.get_action('package_show')({}, {'id': datasets[0][0]})
+        })
+        return schema
+    
+    def _tpsh_update_show_package_schema(self, schema):
+        schema.update({
+            'language': [
+                toolkit.get_converter('convert_from_extras'),
+                toolkit.get_validator('ignore_missing')
+            ],
+            'thumbnail': [
+                toolkit.get_converter('convert_from_extras'),
+                toolkit.get_validator('ignore_missing')
+            ],
+        })
+        return schema
 
 
-class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm):
-    plugins.implements(plugins.IConfigurer)
-    plugins.implements(plugins.ITemplateHelpers)
-    plugins.implements(plugins.IRoutes, inherit=True)
-    plugins.implements(plugins.ITranslation)
-    plugins.implements(plugins.IFacets)
-    plugins.implements(plugins.IDatasetForm)
-    plugins.implements(plugins.IValidators)
-    plugins.implements(plugins.IPackageController, inherit=True)
-    plugins.implements(plugins.IActions)
+    # IFacets
+    
+    def dataset_facets(self, facets_dict, package_type):
+        return OrderedDict({'organization': _('Herausgeber'),
+                            'groups': _('Kategorie'),
+                            'res_format': _('Dateiformat'),
+                            'license_title': _('Lizenz'),
+                            'tags': _('Tags'),
+                            'openness': _('Open-Data-Eigenschaften')
+                            })
 
-    # IActions
+    def group_facets(self, facets_dict, group_type, package_type):
+        return OrderedDict({'organization': _('Herausgeber'),
+                            'res_format': _('Dateiformat'),
+                            'license_title': _('Lizenz'),
+                            'groups': _('Kategorie')})
 
-    def get_actions(self):
-        return {'package_create': action.odsh_package_create,
-                'user_create': action.odsh_user_create}
+    def organization_facets(self, facets_dict, organization_type, package_type):
+        return OrderedDict({'organization': _('Herausgeber'),
+                            'res_format': _('Dateiformat'),
+                            'license_title': _('Lizenz'),
+                            'groups': _('Kategorie')})
+    
 
-    # IConfigurer
+    # IPackageController
 
-    def update_config(self, config_):
-        toolkit.add_template_directory(config_, 'templates')
-        toolkit.add_public_directory(config_, 'public')
-        toolkit.add_resource('fanstatic', 'odsh')
+    def after_show(self, context, pkg_dict):
+        '''
+        corrects missing relationships in pkg dict
+        adds the following key-value-pairs to pkg_dict:
+        # key: 'is_new', value: True if the dataset has been created within the last month
+        '''
+        pkg_dict = helpers_tpsh.correct_missing_relationship(
+            pkg_dict,
+            helpers_tpsh.get_pkg_relationships_from_model(pkg_dict)
+        )
+        self._update_is_new_in_pkg_dict(pkg_dict)
+        
+        return pkg_dict
 
-    def get_helpers(self):
-        # Template helper function names should begin with the name of the
-        # extension they belong to, to avoid clashing with functions from
-        # other extensions.
-        return {'odsh_main_groups': odsh_main_groups,
-                'odsh_now': odsh_now,
-                'odsh_group_id_selected': odsh_group_id_selected,
-                'odsh_get_facet_items_dict': odsh_get_facet_items_dict,
-                'odsh_openness_score_dataset_html': odsh_helpers.odsh_openness_score_dataset_html,
-                'odsh_get_resource_details': odsh_helpers.odsh_get_resource_details,
-                'odsh_get_resource_views': odsh_helpers.odsh_get_resource_views,
-                'odsh_get_bounding_box': odsh_helpers.odsh_get_bounding_box,
-                'odsh_get_spatial_text': odsh_helpers.odsh_get_spatial_text,
-                'odsh_render_datetime': odsh_helpers.odsh_render_datetime,
-                'odsh_upload_known_formats': odsh_helpers.odsh_upload_known_formats,
-                'odsh_encodeurl': odsh_helpers.odsh_encodeurl,
-                'odsh_extract_error': odsh_helpers.odsh_extract_error,
-                'odsh_extract_error_new': odsh_helpers.odsh_extract_error_new,
-                'odsh_extract_value_from_extras': odsh_helpers.odsh_extract_value_from_extras,
-                'odsh_create_checksum': odsh_helpers.odsh_create_checksum,
-                'presorted_license_options': odsh_helpers.presorted_license_options,
-                'odsh_tracking_id': odsh_helpers.odsh_tracking_id,
-                'odsh_tracking_url': odsh_helpers.odsh_tracking_url,
-                'odsh_has_more_facets': odsh_helpers.odsh_has_more_facets,
-                'odsh_public_url': odsh_helpers.odsh_public_url,
-                'odsh_spatial_extends_available': odsh_helpers.spatial_extends_available,
-                'odsh_public_resource_url': odsh_helpers.odsh_public_resource_url,
-                'odsh_get_version_id': odsh_helpers.odsh_get_version_id,
-                'odsh_show_testbanner': odsh_helpers.odsh_show_testbanner,
-                'odsh_is_slave': odsh_helpers.odsh_is_slave
-                }
+    def before_view(self, pkg_dict):
+        '''
+        adds the following key-value-pairs to pkg_dict:
+        # key: 'is_new', value: True if the dataset has been created within the last month
+        '''
+        self._update_is_new_in_pkg_dict(pkg_dict)
+        return pkg_dict
+    
+    def after_create(self, context, resource):
+        if resource.get('package_id'):
+            tools.add_attributes_resources(context, resource)
 
-    def after_map(self, map):
-        return map
+    def after_update(self, context, resource):
+        if resource.get('package_id'):
+            tools.add_attributes_resources(context, resource)
 
-    def before_map(self, map):
-        map.connect('info_page', '/info_page',
-                    controller='ckanext.odsh.controller:OdshRouteController', action='info_page')
-        map.connect('home', '/',
-                    controller='ckanext.odsh.controller:OdshRouteController', action='start')
+    @staticmethod
+    def _update_is_new_in_pkg_dict(pkg_dict):
+        is_new = HelperPgkDict(pkg_dict).is_package_new()
+        pkg_dict.update({'is_new': is_new})
+
+    
+    def before_index(self, dict_pkg):
+        # make special date fields solr conform
+        fields = ["issued", "temporal_start", "temporal_end"]
+        for field in fields:
+            field = 'extras_' + field
+            if field in dict_pkg and dict_pkg[field]:
+                d = parse(dict_pkg[field])
+                dict_pkg[field] = '{0.year:04d}-{0.month:02d}-{0.day:02d}T00:00:00Z'.format(
+                    d)
 
-        map.redirect('/dataset/{id}/resource/{resource_id}', '/dataset/{id}')
+        self.map_qa_score(dict_pkg)
 
-        if p.toolkit.asbool(config.get('ckanext.dcat.enable_rdf_endpoints', True)):
-            remove_route(map, 'dcat_catalog')
-            map.connect('dcat_catalog',
-                        config.get('ckanext.dcat.catalog_endpoint',
-                                   '/catalog.{_format}'),
-                        controller='ckanext.odsh.controller:OdshDCATController', action='read_catalog',
-                        requirements={'_format': 'xml|rdf|n3|ttl|jsonld'})
+        return dict_pkg
+    
 
-        # with SubMapper(map, controller='ckanext.odsh.controller:OdshApiController') as m:
-        #     m.connect('/catalog2', action='read_catalog')
+    # IRoutes
+    
+    def before_map(self, map):
+        map.connect(
+            'info_page', 
+            '/info_page',
+            controller='ckanext.odsh.controller:OdshRouteController', 
+            action='info_page'
+        )
+        map.connect(
+            'home', 
+            '/',
+            controller='ckanext.odsh.controller:OdshRouteController', 
+            action='start'
+        )
+
+        map.redirect('/dataset/{id}/resource/{resource_id}', '/dataset/{id}')         
+
+        if plugins.toolkit.asbool(config.get('ckanext.dcat.enable_rdf_endpoints', True)):
+            odsh_helpers.odsh_remove_route(map, 'dcat_catalog')
+            map.connect(
+                'dcat_catalog',
+                config.get(
+                    'ckanext.dcat.catalog_endpoint',
+                    '/catalog.{_format}'
+                ),
+                controller='ckanext.odsh.controller:OdshDCATController', 
+                action='read_catalog',
+                requirements={'_format': 'xml|rdf|n3|ttl|jsonld'}
+            )
 
         # /api ver 3 or none with matomo
         GET_POST = dict(method=['GET', 'POST'])
-        with SubMapper(map, controller='ckanext.odsh.controller:OdshApiController', path_prefix='/api{ver:/3|}', ver='/3') as m:
+        with SubMapper(
+            map, 
+            controller='ckanext.odsh.controller:OdshApiController', 
+            path_prefix='/api{ver:/3|}', 
+            ver='/3'
+        ) as m:
             m.connect('/action/{logic_function}',
                       action='action', conditions=GET_POST)
 
@@ -364,89 +289,79 @@ class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm
             m.connect('/user/logged_in', action='logged_in')
             m.connect('/user/logged_out', action='logged_out')
             m.connect('/user/logged_out_redirect', action='logged_out_page')
-            m.connect('user_datasets', '/user/{id:.*}', action='read',
+            m.connect('user_datasets', '/user/{id:(?!(generate_key|activity)).*}', action='read',
                       ckan_icon='sitemap')
 
-        map.connect('comment_datarequest', '/datarequest/new',
-                    controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
-                    action='new', conditions=dict(method=['GET', 'POST']), ckan_icon='comment')
-        map.connect('comment_datarequest', '/datarequest/{id}',
-                    controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
-                    action='comment', conditions=dict(method=['GET', 'POST']), ckan_icon='comment')
+        map.connect(
+            'comment_datarequest', 
+            '/datarequest/new',
+            controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
+            action='new', 
+            conditions=dict(method=['GET', 'POST']), 
+            ckan_icon='comment'
+        )
+        map.connect(
+            'comment_datarequest', 
+            '/datarequest/{id}',
+            controller='ckanext.datarequests.controllers.ui_controller:DataRequestsUI',
+            action='comment', 
+            conditions=dict(method=['GET', 'POST']), 
+            ckan_icon='comment'
+        )
+        return map
+    
+    def after_map(self, map):
         return map
 
-    def dataset_facets(self, facets_dict, package_type):
-        return OrderedDict({'organization': _('Herausgeber'),
-                            'res_format': _('Dateiformat'),
-                            'license_title': _('Lizenz'),
-                            'groups': _('Kategorie'),
-                            'openness': _('Open-Data-Eigenschaften')})
-
-    def organization_facets(self, facets_dict, organization_type, package_type):
-        return OrderedDict({'organization': _('Herausgeber'),
-                            'res_format': _('Dateiformat'),
-                            'license_title': _('Lizenz'),
-                            'groups': _('Kategorie')})
-
-    def group_facets(self, facets_dict, group_type, package_type):
-        return OrderedDict({'organization': _('Herausgeber'),
-                            'res_format': _('Dateiformat'),
-                            'license_title': _('Lizenz'),
-                            'groups': _('Kategorie')})
-
-    def _update_schema(self, schema):
-        for field in ['title', 'notes', 'license_id']:
-            schema.update({field: [toolkit.get_converter('not_empty')]})
-
-        for i, item in enumerate(schema['tags']['name']):
-            if item == toolkit.get_validator('tag_name_validator'):
-                schema['tags']['name'][i] = toolkit.get_validator(
-                    'odsh_tag_name_validator')
-        for i, item in enumerate(schema['tag_string']):
-            if item == tag_string_convert:
-                schema['tag_string'][i] = validation.tag_string_convert
-
-        schema['resources'].update({
-            'url': [toolkit.get_converter('not_empty')],
-            'format': [toolkit.get_converter('not_empty')],
-        })
-
-        schema['extras'].update({
-            'key': [
-                toolkit.get_converter('known_spatial_uri'),
-                toolkit.get_converter('validate_licenseAttributionByText'),
-            ]
-        })
-        schema.update(
-            {'__extras':  [toolkit.get_converter('odsh_validate_extras')]})
-
-        # only to make sure the spatial field is there for validation
-        # schema.update({'spatial':  [toolkit.get_converter('convert_from_extras')]})
-
-    def create_package_schema(self):
-        schema = super(OdshPlugin, self).create_package_schema()
-        self._update_schema(schema)
-        return schema
-
-    def update_package_schema(self):
-        schema = super(OdshPlugin, self).update_package_schema()
-        self._update_schema(schema)
-        return schema
-
-    def show_package_schema(self):
-        schema = super(OdshPlugin, self).show_package_schema()
-        return schema
 
-    def is_fallback(self):
-        # Return True to register this plugin as the default handler for
-        # package types not handled by any other IDatasetForm plugin.
-        return True
-
-    def package_types(self):
-        # This plugin doesn't handle any special package types, it just
-        # registers itself as the default (above).
-        return []
+    # ITemplateHelpers
+    
+    def get_helpers(self):
+        # Template helper function names should begin with the name of the
+        # extension they belong to, to avoid clashing with functions from
+        # other extensions.
+        return {'odsh_main_groups': odsh_helpers.odsh_main_groups,
+                'odsh_now': odsh_helpers.odsh_now,
+                'odsh_group_id_selected': odsh_helpers.odsh_group_id_selected,
+                'odsh_get_facet_items_dict': odsh_helpers.odsh_get_facet_items_dict,
+                'odsh_openness_score_dataset_html': odsh_helpers.odsh_openness_score_dataset_html,
+                'odsh_get_resource_details': odsh_helpers.odsh_get_resource_details,
+                'odsh_get_resource_views': odsh_helpers.odsh_get_resource_views,
+                'odsh_get_bounding_box': odsh_helpers.odsh_get_bounding_box,
+                'odsh_get_spatial_text': odsh_helpers.odsh_get_spatial_text,
+                'odsh_render_datetime': odsh_helpers.odsh_render_datetime,
+                'odsh_upload_known_formats': odsh_helpers.odsh_upload_known_formats,
+                'odsh_encodeurl': odsh_helpers.odsh_encodeurl,
+                'odsh_extract_error': odsh_helpers.odsh_extract_error,
+                'odsh_extract_error_new': odsh_helpers.odsh_extract_error_new,
+                'odsh_extract_value_from_extras': odsh_helpers.odsh_extract_value_from_extras,
+                'odsh_create_checksum': odsh_helpers.odsh_create_checksum,
+                'presorted_license_options': odsh_helpers.presorted_license_options,
+                'odsh_tracking_id': odsh_helpers.odsh_tracking_id,
+                'odsh_tracking_url': odsh_helpers.odsh_tracking_url,
+                'odsh_has_more_facets': odsh_helpers.odsh_has_more_facets,
+                'odsh_public_url': odsh_helpers.odsh_public_url,
+                'odsh_spatial_extends_available': odsh_helpers.spatial_extends_available,
+                'odsh_public_resource_url': odsh_helpers.odsh_public_resource_url,
+                'odsh_get_version_id': odsh_helpers.odsh_get_version_id,
+                'odsh_show_testbanner': odsh_helpers.odsh_show_testbanner,
+                'odsh_is_slave': odsh_helpers.odsh_is_slave,
+                'odsh_use_matomo': helpers_tpsh.use_matomo,
+                'tpsh_get_daterange_prettified': helper_pkg_dict.get_daterange_prettified,
+                'tpsh_get_language_of_package': helpers_tpsh.get_language_of_package,
+                'get_language_icon': helpers_tpsh.get_language_icon,
+                'short_name_for_category': odsh_helpers.short_name_for_category,
+                'get_spatial_for_selection': helpers_tpsh.get_spatial_for_selection,
+                'get_subject_for_selection': helpers_tpsh.get_subject_for_selection,
+                'get_language_for_selection': helpers_tpsh.get_language_for_selection,
+                'tpsh_get_resource_size': helpers_tpsh.get_resource_size,
+                'tpsh_get_address_org':helpers_tpsh.get_address_org,
+                'tpsh_get_body_mail':helpers_tpsh.get_body_mail,
+                }
 
+    
+    # IValidators
+    
     def get_validators(self):
         return validation.get_validators()
 
@@ -454,67 +369,7 @@ class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm
     # use several daterange queries agains temporal_start and temporal_end field
     # TODO: use field of type date_range in solr index instead
     def before_search(self, search_params):
-        search_params['facet.mincount'] = 0
-        extras = search_params.get('extras')
-        print(search_params)
-        if not extras:
-            # There are no extras in the search params, so do nothing.
-            return search_params
-
-        fq = search_params['fq']
-
-        start_date = None
-        end_date = None
-        try:
-            start_date = odsh_helpers.extend_search_convert_local_to_utc_timestamp(
-                extras.get('ext_startdate'))
-            end_date = odsh_helpers.extend_search_convert_local_to_utc_timestamp(
-                extras.get('ext_enddate'))
-        except:
-            return search_params
-
-        empty_range = start_date and end_date and start_date > end_date
-
-        if not start_date and not end_date:
-            return search_params
-
-        do_enclosing_query = True
-        if not start_date:
-            do_enclosing_query = False
-            start_date = '*'
-        if not end_date:
-            do_enclosing_query = False
-            end_date = '*'
-
-        start_query = '+extras_temporal_start:[{start_date} TO {end_date}]'.format(
-            start_date=start_date, end_date=end_date)
-
-        end_query = '+extras_temporal_end:[{start_date} TO {end_date}]'.format(
-            start_date=start_date, end_date=end_date)
-
-        enclosing_query = ''
-        if do_enclosing_query and not empty_range:
-            enclosing_query_start = 'extras_temporal_start:[* TO {start_date}]'.format(
-                start_date=start_date)
-
-            enclosing_query_end = 'extras_temporal_end:[{end_date} TO *]'.format(
-                end_date=end_date)
-
-            enclosing_query = ' OR ({enclosing_query_start} AND {enclosing_query_end})'.format(
-                enclosing_query_start=enclosing_query_start, enclosing_query_end=enclosing_query_end)
-
-        if end_date is '*':
-            open_end_query = '(*:* NOT extras_temporal_end:[* TO *])'
-        else:
-            open_end_query = '((*:* NOT extras_temporal_end:[* TO *]) AND extras_temporal_start:[* TO {end_date}])'.format(
-                end_date=end_date)
-
-        fq = u'{fq} ({start_query} OR {end_query} {enclosing_query} OR {open_end_query})'.format(
-            fq=fq, start_query=start_query, end_query=end_query, enclosing_query=enclosing_query, open_end_query=open_end_query)
-
-        search_params['fq'] = fq
-
-        return search_params
+        return search.before_search(search_params)
 
     scores = [['0OL'], ['0OL', '1RE'], ['0OL', '1RE', '2OF'], [
         '0OL', '1RE', '2OF', '3URI'], ['0OL', '1RE', '2OF', '3URI', '4LD']]
@@ -532,64 +387,6 @@ class OdshPlugin(plugins.SingletonPlugin, DefaultTranslation, DefaultDatasetForm
             if score > 0:
                 dict_pkg['openness'] = OdshPlugin.scores[score-1]
 
-    # @precondition.not_on_slave
 
-    def before_index(self, dict_pkg):
-        # make special date fields solr conform
-        fields = ["issued", "temporal_start", "temporal_end"]
-        for field in fields:
-            field = 'extras_' + field
-            if field in dict_pkg and dict_pkg[field]:
-                d = parse(dict_pkg[field])
-                dict_pkg[field] = '{0.year:04d}-{0.month:02d}-{0.day:02d}T00:00:00Z'.format(
-                    d)
-        # if 'res_format' in dict_pkg:
-        #     dict_pkg['res_format']=[e.lower() for e in dict_pkg['res_format']]
-
-        self.map_qa_score(dict_pkg)
-
-        return dict_pkg
-    
-
-    # IPackageController
 
-    def before_view(self, pkg_dict):
-        '''
-        add a key 'is_new' to pkg_dict
-        the value for this key is True if the dataset has been created within the last month
-        the value is used in the snippet package_item.html
-        '''
-        is_new = self._is_package_new(pkg_dict)
-        pkg_dict.update({'is_new':is_new})
-        return pkg_dict
-    
-    def _is_package_new(self, pkg_dict):
-        date_package_created_as_str = self._get_date_of_package_creation_from_pkg_dict(pkg_dict)
-        if date_package_created_as_str == None:
-            is_new = False
-        else:
-            date_package_created = self._get_date_from_string(date_package_created_as_str)
-            if date_package_created == None:
-                is_new = False
-            else:
-                is_new = odsh_helpers.is_within_last_month(date_package_created)
-        return is_new
-    
-    def _get_date_of_package_creation_from_pkg_dict(self, pkg_dict):
-        if 'extras' in pkg_dict:
-            extras = pkg_dict['extras']
-            issued = odsh_helpers.odsh_extract_value_from_extras(extras=extras, key='issued') # is None if issued not in extras
-            return issued
-        else:
-            return None
-    
-    def _get_date_from_string(self, date_time_str):
-        date_time_format = '%Y-%m-%dT%H:%M:%S' #e.g. u'2019-06-12T11:56:25'
-        try:
-            date_time = datetime.datetime.strptime(date_time_str, date_time_format)
-            date = date_time.date()
-        except ValueError:
-            # if date cannot be converted from string return None
-            date = None
-        return date
 
diff --git a/ckanext/odsh/plugin_odsh_autocomplete.py b/ckanext/odsh/plugin_odsh_autocomplete.py
new file mode 100644
index 0000000000000000000000000000000000000000..e34d7f0ee54ea0572f52db38eda72bdaee4a334d
--- /dev/null
+++ b/ckanext/odsh/plugin_odsh_autocomplete.py
@@ -0,0 +1,8 @@
+import ckan.plugins as plugins
+import ckanext.odsh.logic.action as action
+
+class OdshAutocompletePlugin(plugins.SingletonPlugin):
+    plugins.implements(plugins.IActions)
+
+    def get_actions(self):
+        return {'autocomplete': action.autocomplete}
\ No newline at end of file
diff --git a/ckanext/odsh/plugin_odsh_dcat_harvest.py b/ckanext/odsh/plugin_odsh_dcat_harvest.py
new file mode 100644
index 0000000000000000000000000000000000000000..3b03b6e7b66f2084911ae20378833453dc9e18ce
--- /dev/null
+++ b/ckanext/odsh/plugin_odsh_dcat_harvest.py
@@ -0,0 +1,65 @@
+import ckan.plugins as plugins
+import ckan.plugins.toolkit as toolkit
+from ckanext.dcat.interfaces import IDCATRDFHarvester
+from ckanext.dcatde.extras import Extras
+
+from ckanext.odsh.helper_pkg_dict import HelperPgkDict
+
+from ckan import model
+
+import ckan.plugins as p
+
+_ = toolkit._
+
+import logging
+log = logging.getLogger(__name__)
+
+
+class OdshDCATHarvestPlugin(plugins.SingletonPlugin):
+    plugins.implements(IDCATRDFHarvester, inherit=True)
+    
+    def before_update(self, harvest_object, dataset_dict, temp_dict):
+        existing_package_dict = self._get_existing_dataset(harvest_object.guid)
+        new_dataset_extras = Extras(dataset_dict['extras'])
+        if new_dataset_extras.key('modified') and \
+                new_dataset_extras.value('modified') < existing_package_dict.get('metadata_modified'):
+            log.info("Modified date of new dataset is not newer than "
+                     + "the already exisiting dataset, ignoring new one.")
+            dataset_dict.clear()
+
+    def _get_existing_dataset(self, guid):
+        '''
+        Checks if a dataset with a certain guid extra already exists
+        Returns a dict as the ones returned by package_show
+        '''
+        datasets = model.Session.query(model.Package.id) \
+                                .join(model.PackageExtra) \
+                                .filter(model.PackageExtra.key == 'guid') \
+                                .filter(model.PackageExtra.value == guid) \
+                                .filter(model.Package.state == 'active') \
+                                .all()
+
+        if not datasets:
+            return None
+        elif len(datasets) > 1:
+            log.error('Found more than one dataset with the same guid: {0}'
+                      .format(guid))
+        return p.toolkit.get_action('package_show')({}, {'id': datasets[0][0]})
+
+
+    def after_create(self, harvest_object, dataset_dict, temp_dict):
+        '''
+        Called just after a successful ``package_create`` action has been
+        performed.
+
+        This method sets relationships between packages and collections.
+        '''
+        dd = HelperPgkDict(dataset_dict)
+        if dd.is_collection():
+            dd.update_relations_to_collection_members()
+            dd.add_uri_to_store()
+        if dd.shall_be_part_of_collection():
+            dd.update_relation_to_collection()
+            dd.add_uri_to_store()
+    
+    
diff --git a/ckanext/odsh/plugin_odsh_harvest.py b/ckanext/odsh/plugin_odsh_harvest.py
new file mode 100644
index 0000000000000000000000000000000000000000..6c7d326da317cd8c88254457b5adf380bd62bb81
--- /dev/null
+++ b/ckanext/odsh/plugin_odsh_harvest.py
@@ -0,0 +1,48 @@
+import ckan.plugins as plugins
+import ckan.plugins.toolkit as toolkit
+import ckanext.odsh.logic.action as action
+
+
+class OdshHarvestPlugin(plugins.SingletonPlugin):
+    plugins.implements(plugins.IRoutes, inherit=True)
+    plugins.implements(plugins.IConfigurer)
+
+    def update_config(self, config_):
+        toolkit.add_template_directory(config_, 'harvest_templates')
+
+    def before_map(self, map):
+        DATASET_TYPE_NAME = 'harvest'
+        controller = 'ckanext.odsh.controller:OdshHarvestController'
+        
+        map.connect('{0}_delete'.format(DATASET_TYPE_NAME), '/' +
+                    DATASET_TYPE_NAME + '/delete/:id', controller=controller, action='delete')
+        map.connect('{0}_refresh'.format(DATASET_TYPE_NAME), '/' + DATASET_TYPE_NAME + '/refresh/:id', controller=controller,
+                    action='refresh')
+        map.connect('{0}_admin'.format(DATASET_TYPE_NAME), '/' +
+                    DATASET_TYPE_NAME + '/admin/:id', controller=controller, action='admin')
+        map.connect('{0}_about'.format(DATASET_TYPE_NAME), '/' +
+                    DATASET_TYPE_NAME + '/about/:id', controller=controller, action='about')
+        map.connect('{0}_clear'.format(DATASET_TYPE_NAME), '/' +
+                    DATASET_TYPE_NAME + '/clear/:id', controller=controller, action='clear')
+
+        map.connect('harvest_job_list', '/' + DATASET_TYPE_NAME +
+                    '/{source}/job', controller=controller, action='list_jobs')
+        map.connect('harvest_job_show_last', '/' + DATASET_TYPE_NAME +
+                    '/{source}/job/last', controller=controller, action='show_last_job')
+        map.connect('harvest_job_show', '/' + DATASET_TYPE_NAME +
+                    '/{source}/job/{id}', controller=controller, action='show_job')
+        map.connect('harvest_job_abort', '/' + DATASET_TYPE_NAME +
+                    '/{source}/job/{id}/abort', controller=controller, action='abort_job')
+
+        map.connect('harvest_object_show', '/' + DATASET_TYPE_NAME +
+                    '/object/:id', controller=controller, action='show_object')
+        map.connect('harvest_object_for_dataset_show', '/dataset/harvest_object/:id',
+                    controller=controller, action='show_object', ref_type='dataset')
+
+        org_controller = 'ckanext.harvest.controllers.organization:OrganizationController'
+        map.connect('{0}_org_list'.format(DATASET_TYPE_NAME), '/organization/' +
+                    DATASET_TYPE_NAME + '/' + '{id}', controller=org_controller, action='source_list')
+        return map
+
+    def after_map(self, map):
+        return map
\ No newline at end of file
diff --git a/ckanext/odsh/plugin_odsh_icap.py b/ckanext/odsh/plugin_odsh_icap.py
new file mode 100644
index 0000000000000000000000000000000000000000..d6462db4af0e09a46a2ac900a91dc923cb59728b
--- /dev/null
+++ b/ckanext/odsh/plugin_odsh_icap.py
@@ -0,0 +1,11 @@
+import ckan.plugins as plugins
+from ckanext.odsh.lib.uploader import ODSHResourceUpload, ODSHUpload
+
+class OdshIcapPlugin(plugins.SingletonPlugin):
+    plugins.implements(plugins.IUploader, inherit=True)
+
+    def get_resource_uploader(self, data_dict):
+        return ODSHResourceUpload(data_dict)
+    
+    def get_uploader(self, upload_to, old_filename):
+        return ODSHUpload(upload_to, old_filename)
\ No newline at end of file
diff --git a/ckanext/odsh/pretty_daterange/README.md b/ckanext/odsh/pretty_daterange/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6fc2eaac24fcf80d9f3c271fe4c235d3fc5736fd
--- /dev/null
+++ b/ckanext/odsh/pretty_daterange/README.md
@@ -0,0 +1,62 @@
+# pretty_daterange package
+Dieses Package erlaubt die "hübsche" Darstellung von Datumsbereichen. 
+
+## Beispiel
+```
+from datetime import date
+from pretty_daterange.date_range_formatter import DateRangeFormatter
+
+drf = DateRangeFormatter(
+    date_start = date(2019, 1, 1),
+    date_end = date(2019, 3, 31)
+)
+print(drf.get_formatted_str())
+```
+prints
+```
+1. Quartal 2019
+```
+
+# Spezifikation
+Viele Datumsangaben lassen sich eleganter als TT.MM.JJJJ-TT.MM.JJJJ darstellen. Bei der Anzeige auf der Suchergebnisseite und der Datensatzdetailsseite sollen Datumsangaben nach den folgenden Regeln umgeformt werden.
+
+## Regel zum Kürzen von Datumsangaben
+### Jahr ist gleich
+Startdatum = a.b.n und Enddatum = a.b.n -> a.b.n
+
+Starddatum = 01.01.n und Enddatum = 31.12.n -> n
+
+Startdatum = 01.01.n und Enddatum = 31.01.n -> Januar n
+
+Startdatum = 01.02.n und ( Enddatum = 28.02.n oder Enddatum = 28.02.n ) -> Februar n
+
+Startdatum = 01.03.n und Enddatum = 31.03.n -> März n
+
+[...]
+
+Startdatum = 01.12.n und Enddatum = 31.12.n -> Dezember n
+
+Startdatum = 01.01.n und Enddatum = 31.03.n -> 1. Quartal n
+
+Startdatum = 01.04.n und Enddatum = 30.06.n -> 2. Quartal n
+
+Startdatum = 01.07.n und Enddatum = 30.09.n -> 3. Quartal n
+
+Startdatum = 01.10.n und Enddatum = 31.12.n -> 4. Quartal n
+
+Startdatum = 01.01.n und Enddatum = 30.06.n -> 1. Halbjahr n
+
+Startdatum = 01.07.n und Enddatum = 31.12.n -> 2. Halbjahr n
+
+Startdatum = 01.01.n und ( Enddatum = 28.02.n oder Enddatum = 28.02.n ) -> Januar bis Februar n
+
+Startdatum = 01.01.n und Enddatum = 31.03.n -> Januar bis März n
+
+[...]
+
+Startdatum = 01.01.n und Enddatum = 30.11.n -> Januar bis November n
+
+### Jahr ist unterschiedlich
+Startdatum = 01.01.n und Enddatum = 31.12.m -> n-m
+
+Stardatum = 01.a.n und Enddatum ist letzer des Monats b im Jahr m -> [Text für a] n bis [Text für b] m
diff --git a/ckanext/odsh/pretty_daterange/__init__.py b/ckanext/odsh/pretty_daterange/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ckanext/odsh/pretty_daterange/date_range.py b/ckanext/odsh/pretty_daterange/date_range.py
new file mode 100644
index 0000000000000000000000000000000000000000..d43d7e28c0bf7e4b4845be549e30c1aa061deb2b
--- /dev/null
+++ b/ckanext/odsh/pretty_daterange/date_range.py
@@ -0,0 +1,181 @@
+ # -*- coding: utf-8 -*-
+
+import datetime
+
+class DateRange(object):
+    def __init__(self, date_start, date_end):
+        if date_end < date_start:
+            raise ValueError('date_end may not be before date_start')
+        self.date_start = date_start
+        self.date_end = date_end
+    
+    
+    def is_one_year(self):
+        is_one_year = (
+            self._are_start_and_end_in_same_year() and 
+            self._is_first_of_year(self.date_start) and 
+            self._is_last_of_year(self.date_end)
+        )
+        return is_one_year
+
+    
+    def _are_start_and_end_in_same_year(self):
+        in_same_year = self.date_start.year==self.date_end.year
+        return in_same_year
+    
+    
+    @staticmethod
+    def _is_first_of_year(date):
+        return date.day==1 and date.month==1
+    
+    
+    @staticmethod
+    def _is_last_of_year(date):
+        return date.day==31 and date.month==12
+
+    
+    def is_range_of_multiple_years(self):
+        is_range_of_multiple_years = (
+            not self._are_start_and_end_in_same_year() and 
+            self._is_first_of_year(self.date_start) and 
+            self._is_last_of_year(self.date_end)
+        )
+        return is_range_of_multiple_years
+    
+    def is_one_half_of_year(self):
+        is_one_half_year = (
+            self._are_start_and_end_in_same_half_year() and
+            self._is_first_of_half_year(self.date_start) and
+            self._is_last_of_half_year(self.date_end)
+        )
+        return is_one_half_year
+    
+    
+    def _are_start_and_end_in_same_half_year(self):
+        in_same_half_year = (
+            self._are_start_and_end_in_same_year() and
+            self.get_half_year(self.date_start) == self.get_half_year(self.date_end)
+        )
+        return in_same_half_year
+    
+    
+    @staticmethod
+    def get_half_year(date):
+        year = date.year
+        if date < datetime.date(year, 7, 1):
+            return 1
+        return 2
+    
+    
+    @staticmethod
+    def _is_first_of_half_year(date):
+        year = date.year
+        return date in (
+            datetime.date(year, 1, 1),
+            datetime.date(year, 7, 1),
+        )
+    
+    
+    @staticmethod
+    def _is_last_of_half_year(date):
+        year = date.year
+        return date in (
+            datetime.date(year, 6, 30),
+            datetime.date(year, 12, 31),
+        )
+    
+    
+    def is_one_quarter_of_year(self):
+        is_one_quarter_of_year = (
+            self._are_start_and_end_in_same_quarter() and
+            self._is_first_of_quarter(self.date_start) and
+            self._is_last_of_quarter(self.date_end)
+        )
+        return is_one_quarter_of_year
+    
+    
+    def _are_start_and_end_in_same_quarter(self):
+        in_same_quarter = (
+            self._are_start_and_end_in_same_year() and
+            self.get_quarter(self.date_start) == self.get_quarter(self.date_end)
+        )
+        return in_same_quarter
+
+    
+    @staticmethod
+    def get_quarter(date):
+        year = date.year
+        if date < datetime.date(year, 4, 1):
+            return 1
+        if date < datetime.date(year, 7, 1):
+            return 2
+        if date < datetime.date(year, 10, 1):
+            return 3
+        return 4
+    
+    
+    @staticmethod
+    def _is_first_of_quarter(date):
+        year = date.year
+        return date in (
+            datetime.date(year, 1, 1),
+            datetime.date(year, 4, 1),
+            datetime.date(year, 7, 1),
+            datetime.date(year, 10, 1),
+        )
+    
+    
+    @staticmethod
+    def _is_last_of_quarter(date):
+        year = date.year
+        return date in (
+            datetime.date(year, 3, 31),
+            datetime.date(year, 6, 30),
+            datetime.date(year, 9, 30),
+            datetime.date(year, 12, 31),
+        )
+    
+    
+    def is_one_month(self):
+        is_one_month = (
+            self._are_start_and_end_in_same_year() and
+            self._are_start_and_end_in_same_month() and
+            self._is_first_of_month(self.date_start) and 
+            self._is_last_of_month(self.date_end)
+        )
+        return is_one_month
+    
+    
+    def _are_start_and_end_in_same_month(self):
+        is_in_same_month = self.date_start.month == self.date_end.month
+        return is_in_same_month
+
+    
+    @staticmethod
+    def _is_first_of_month(date):
+        return date.day==1
+    
+    
+    @staticmethod
+    def _is_last_of_month(date):
+        day_after_date = date + datetime.timedelta(days=1)
+        is_last_of_month = day_after_date.day==1
+        return is_last_of_month
+    
+    def is_range_of_multiple_months(self):
+        is_range_of_multiple_months = (
+            self._is_first_of_month(self.date_start) and 
+            self._is_last_of_month(self.date_end) and
+            not self._are_start_and_end_in_same_month()
+        )
+        return is_range_of_multiple_months
+    
+    def is_range_of_multiple_months_in_same_year(self):
+        is_range_of_multiple_months_in_same_year = (
+            self._is_first_of_month(self.date_start) and 
+            self._is_last_of_month(self.date_end) and
+            not self._are_start_and_end_in_same_month() and
+            self._are_start_and_end_in_same_year()
+        )
+        return is_range_of_multiple_months_in_same_year
+    
diff --git a/ckanext/odsh/pretty_daterange/date_range_formatter.py b/ckanext/odsh/pretty_daterange/date_range_formatter.py
new file mode 100644
index 0000000000000000000000000000000000000000..dcd513f32257bb5e339a89470fae64b5389d5c86
--- /dev/null
+++ b/ckanext/odsh/pretty_daterange/date_range_formatter.py
@@ -0,0 +1,99 @@
+ # -*- coding: utf-8 -*-
+
+import datetime
+from babel.dates import format_date
+
+from .date_range import DateRange
+
+class DateRangeFormatter(object):
+    def __init__(self, date_start, date_end):
+        if all((date_start, date_end)):
+            self._date_range = DateRange(date_start, date_end)
+        self.locale_for_date_strings = 'de_DE.UTF-8'
+        self.date_start = date_start
+        self.date_end = date_end
+        self._format_full_date = 'dd.MM.yyyy'
+        self._format_only_year = 'yyyy'
+        self._format_month_year = 'MMMM yyyy'
+        self._format_only_month = 'MMMM'
+    
+    
+    def get_formatted_str(self):
+        if not any((self.date_start, self.date_end, )):
+            return self._construct_empty_date_string()
+        
+        if not self.date_end:
+            return self._construct_open_end_date_string()
+        
+        if not self.date_start:
+            return self._construct_open_start_date_string()
+        
+        if self.date_start == self.date_end:
+            return self._construct_single_date_string(self.date_start, self._format_full_date)
+        
+        if self._date_range.is_range_of_multiple_years():
+            return self._construct_date_range_string(self._format_only_year, self._format_only_year)
+        
+        if self._date_range.is_one_year():
+            return self._construct_single_date_string(self.date_start, self._format_only_year)
+        
+        if self._date_range.is_one_half_of_year():
+            return self._construct_half_of_year_date_string()
+        
+        if self._date_range.is_one_quarter_of_year():
+            return self._construct_quarter_of_year_date_string()
+
+        if self._date_range.is_range_of_multiple_months_in_same_year():
+            return self._construct_date_range_string(self._format_only_month, self._format_month_year)
+        
+        if self._date_range.is_range_of_multiple_months():
+            return self._construct_date_range_string(self._format_month_year, self._format_month_year)
+
+        if self._date_range.is_one_month():
+            return self._construct_single_date_string(self.date_start, self._format_month_year)
+        
+        format_date_start = self._format_full_date
+        format_date_end = self._format_full_date
+        formatted_date_range = self._construct_date_range_string(format_date_start, format_date_end)
+        return formatted_date_range
+    
+    
+    @staticmethod
+    def _construct_empty_date_string():
+        return ""
+    
+    def _construct_open_end_date_string(self):
+        date_start_formatted = self._construct_single_date_string(self.date_start, self._format_full_date)
+        return "ab {}".format(date_start_formatted)
+    
+    def _construct_open_start_date_string(self):
+        date_end_formatted = self._construct_single_date_string(self.date_end, self._format_full_date)
+        return "bis {}".format(date_end_formatted)
+    
+    def _construct_single_date_string(self, date, format):
+        return format_date(date, format=format, locale=self.locale_for_date_strings)
+
+    @staticmethod
+    def _as_utf_8(s):
+        return u'' + s.decode('utf-8')
+    
+    
+    def _construct_half_of_year_date_string(self):
+        year = self.date_start.year
+        half = self._date_range.get_half_year(self.date_start)
+        half_of_year_date_string = u'{}. Halbjahr {}'.format(half, year)
+        return DateRangeFormatter._as_utf_8(half_of_year_date_string)
+    
+    
+    def _construct_quarter_of_year_date_string(self):
+        year = self.date_start.year
+        quarter = self._date_range.get_quarter(self.date_start)
+        quarter_of_year_date_string = u'{}. Quartal {}'.format(quarter, year)
+        return DateRangeFormatter._as_utf_8(quarter_of_year_date_string)
+
+    
+    def _construct_date_range_string(self, format_date_start, format_date_end):
+        formatted_date_range = u'{} - {}'.format(
+            self._construct_single_date_string(self.date_start, format_date_start), 
+            self._construct_single_date_string(self.date_end, format_date_end))
+        return formatted_date_range
diff --git a/ckanext/odsh/profiles/__init__.py b/ckanext/odsh/profiles/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..f87530b7c8b2c3d7eb8dc717ef414fad44ba1a55
--- /dev/null
+++ b/ckanext/odsh/profiles/__init__.py
@@ -0,0 +1,2 @@
+from odsh_dcat_de_profile import ODSHDCATdeProfile
+from odsh_european_dcatap_profile import ODSHEuropeanDCATAPProfile
\ No newline at end of file
diff --git a/ckanext/odsh/profiles/odsh_dcat_de_profile.py b/ckanext/odsh/profiles/odsh_dcat_de_profile.py
new file mode 100644
index 0000000000000000000000000000000000000000..c475ac6a823c6bac61712051a89fecae077cdcd3
--- /dev/null
+++ b/ckanext/odsh/profiles/odsh_dcat_de_profile.py
@@ -0,0 +1,169 @@
+import rdflib
+
+from ckan.common import config
+import ckan.lib.helpers as helpers
+import ckan.model as model
+from ckanext.dcat.profiles import DCT
+from ckanext.dcat.utils import resource_uri
+import ckanext.dcatde.dataset_utils as ds_utils
+from ckanext.dcatde.profiles import DCATdeProfile, DCATDE, DCAT, DCATDE_1_0
+
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
+import ckanext.odsh.collection.helpers as helpers_collection
+from ckanext.odsh.helper_pkg_dict import HelperPgkDict
+
+
+DCT = rdflib.namespace.Namespace("http://purl.org/dc/terms/")
+DCAT = rdflib.namespace.Namespace("http://www.w3.org/ns/dcat#")
+
+
+class ODSHDCATdeProfile(DCATdeProfile):
+
+    # from RDF
+
+    def parse_dataset(self, dataset_dict, dataset_ref):
+        dataset_dict = super(ODSHDCATdeProfile, self).parse_dataset(
+            dataset_dict, dataset_ref
+        )
+        self._parse_distributions(dataset_dict, dataset_ref)
+        self._parse_type(dataset_dict, dataset_ref)
+        if self._belongs_to_collection(dataset_dict, dataset_ref):
+            self._mark_for_adding_to_ckan_collection(dataset_dict, dataset_ref)
+        return dataset_dict
+    
+    def _parse_distributions(self, dataset_dict, dataset_ref):
+        for distribution in self.g.objects(dataset_ref, DCAT.distribution):
+            for resource_dict in dataset_dict.get('resources', []):
+                # Match distribution in graph and distribution in ckan-dict
+                if unicode(distribution) == resource_uri(resource_dict):
+                    for namespace in [DCATDE, DCATDE_1_0]:
+                        value = self._object_value(
+                            distribution, namespace.licenseAttributionByText)
+                        if value:
+                            ds_utils.insert_new_extras_field(
+                                dataset_dict, 'licenseAttributionByText', value)
+                            return
+    
+    def _parse_type(self, dataset_dict, dataset_ref):
+        dct_type = self._object(dataset_ref, DCT.type)
+        if dct_type:
+            ckan_type = helpers_tpsh.map_dct_type_to_ckan_type(str(dct_type))
+            dataset_dict.update({'type': ckan_type})
+    
+    def _belongs_to_collection(self, dataset_dict, dataset_ref):
+        dct_is_version_of = self._object(dataset_ref, DCT.isVersionOf)
+        belongs_to_collection = True if dct_is_version_of else False
+        return belongs_to_collection
+    
+    def _mark_for_adding_to_ckan_collection(self, dataset_dict, dataset_ref):
+        dataset_dict.update({'add_to_collection': True})
+
+    
+    # to RDF    
+    
+    def graph_from_dataset(self, dataset_dict, dataset_ref):
+        '''
+        this class inherits from ODSHDCATdeProfile
+        it has been extended to add information to
+        the rdf export
+
+        '''
+        super(ODSHDCATdeProfile, self).graph_from_dataset(
+            dataset_dict, dataset_ref)
+        self._add_contributor_id(dataset_dict, dataset_ref)
+        self._add_license_attribution_by_text(dataset_dict, dataset_ref)
+        self._add_type(dataset_dict, dataset_ref)
+        if self._is_dataset_collection(dataset_dict):
+            self._remove_predefined_collection_members()
+            self._add_collection_members(dataset_dict, dataset_ref)
+        if self._dataset_belongs_to_collection(dataset_dict):
+            self._add_collection(dataset_dict, dataset_ref)
+    
+    def _add_contributor_id(self, dataset_dict, dataset_ref):
+        contributorID = 'http://dcat-ap.de/def/contributors/schleswigHolstein'
+        self.g.add(
+            (dataset_ref, DCATDE.contributorID, 
+                rdflib.URIRef(contributorID)
+            )
+        )
+    
+    def _add_license_attribution_by_text(self, dataset_dict, dataset_ref):
+        licenseAttributionByText = self._get_dataset_value(dataset_dict, 'licenseAttributionByText')
+        if licenseAttributionByText:
+            self.g.set(
+                (dataset_ref, DCATDE.licenseAttributionByText, rdflib.Literal(licenseAttributionByText))
+            )
+            for distribution in self.g.objects(dataset_ref, DCAT.distribution):
+                self.g.set(
+                    (distribution, DCATDE.licenseAttributionByText, rdflib.Literal(licenseAttributionByText))
+                )
+    
+    def _add_type(self, dataset_dict, dataset_ref):
+        '''
+        adds the type if there is a known mapping from ckan type to
+        dct:type
+        '''
+        ckan_type = self._get_ckan_type(dataset_dict)
+        dct_type = helpers_tpsh.map_ckan_type_to_dct_type(ckan_type)
+        if dct_type:
+            self.g.set(
+                (dataset_ref, DCT.type, 
+                    rdflib.URIRef(dct_type)
+                )
+            )
+    
+    def _get_ckan_type(self, dataset_dict):
+        ckan_type = self._get_dataset_value(dataset_dict, 'type')
+        return ckan_type
+    
+    def _remove_predefined_collection_members(self):
+        for s, p, o in self.g:
+            if p==DCT.hasVersion:
+                self.g.remove((s, p, o))
+    
+    def _add_collection_members(self, dataset_dict, dataset_ref):
+        dataset_refs_belonging_to_collection = self._get_dataset_refs_belonging_to_collection(dataset_dict)
+        for ref in dataset_refs_belonging_to_collection:
+            self.g.add(
+                (dataset_ref, DCT.hasVersion, rdflib.URIRef(ref))
+            )
+    
+    def _is_dataset_collection(self, dataset_dict):
+        ckan_type = self._get_ckan_type(dataset_dict)
+        is_collection = ckan_type=='collection'
+        return is_collection
+    
+    def _get_dataset_refs_belonging_to_collection(self, dataset_dict):
+        dataset_names = helpers_collection.get_all_datasets_belonging_to_collection(
+            collection_name = dataset_dict.get('id')
+        )
+        dataset_dicts = [model.Package.get(name).as_dict() for name in dataset_names]
+        dataset_ids = [dataset_dict.get('id') for dataset_dict in dataset_dicts]
+        dataset_refs = [self._construct_refs(id) for id in dataset_ids]
+        return dataset_refs
+    
+    @staticmethod
+    def _construct_refs(id):
+        public_url = config.get('ckan.site_url')
+        url_to_id = helpers.url_for(controller='package', action ='read', id=id)
+        ref = public_url + url_to_id
+        return ref
+    
+    def _dataset_belongs_to_collection(self, dataset_dict):
+        '''
+        returns True if a containing collection is found
+        '''
+        if dataset_dict.get('type')=='collection':
+            return False
+        id_dataset = dataset_dict.get('id')
+        collection_name = helpers_collection.get_collection_name_by_dataset(id_dataset)
+        return collection_name is not None
+
+    def _add_collection(self, dataset_dict, dataset_ref):
+        collection_id = HelperPgkDict(dataset_dict).get_collection_id()
+        collection_uri = self._construct_refs(collection_id)
+        self.g.set(
+            (dataset_ref, DCT.isVersionOf, 
+                rdflib.URIRef(collection_uri)
+            )
+        )
diff --git a/ckanext/odsh/profiles.py b/ckanext/odsh/profiles/odsh_european_dcatap_profile.py
similarity index 70%
rename from ckanext/odsh/profiles.py
rename to ckanext/odsh/profiles/odsh_european_dcatap_profile.py
index d9532758d517c39d9a995a3cad70b24df7bf2390..544323bd1d9b32db11f84e78b93f4a5fb364f92d 100644
--- a/ckanext/odsh/profiles.py
+++ b/ckanext/odsh/profiles/odsh_european_dcatap_profile.py
@@ -1,20 +1,10 @@
-from ckanext.dcatde.profiles import DCATdeProfile, DCATDE, DCAT, VCARD, dcat_theme_prefix, DCATDE_1_0
-from ckanext.dcat.utils import resource_uri
-from ckanext.dcat.profiles import EuropeanDCATAPProfile, DCT, URIRefOrLiteral
-from ckan.model.license import LicenseRegister
-import rdflib
-import ckanext.dcatde.dataset_utils as ds_utils
 import logging
-from ckan.plugins import toolkit
-from ckan.common import config, json
-from ckanext.dcat.interfaces import IDCATRDFHarvester
-import pdb
+import rdflib
 
-import sys
-if sys.version_info[0] == 2:
-    import urllib2
-elif sys.version_info[0] == 3:  # >=Python3.1
-    import urllib
+from ckan.common import config, json
+from ckan.model.license import LicenseRegister
+from ckanext.dcat.profiles import EuropeanDCATAPProfile, DCT, URIRefOrLiteral
+from ckanext.dcatde.profiles import DCAT
 
 log = logging.getLogger(__name__)
 DCT = rdflib.namespace.Namespace("http://purl.org/dc/terms/")
@@ -75,51 +65,10 @@ class ODSHEuropeanDCATAPProfile(EuropeanDCATAPProfile):
             for dist in self.g.objects(dataset_ref, DCAT.distribution):
                 self.g.add((dist, DCT.license, rdflib.URIRef(license)))
 
-class ODSHDCATdeProfile(DCATdeProfile):
-    def parse_dataset(self, dataset_dict, dataset_ref):
-        dataset_dict = super(ODSHDCATdeProfile, self).parse_dataset(
-            dataset_dict, dataset_ref)
-        # Enhance Distributions
-        for distribution in self.g.objects(dataset_ref, DCAT.distribution):
-            for resource_dict in dataset_dict.get('resources', []):
-                # Match distribution in graph and distribution in ckan-dict
-                if unicode(distribution) == resource_uri(resource_dict):
-                    for namespace in [DCATDE, DCATDE_1_0]:
-                        value = self._object_value(
-                            distribution, namespace.licenseAttributionByText)
-                        if value:
-                            ds_utils.insert_new_extras_field(
-                                dataset_dict, 'licenseAttributionByText', value)
-                            return dataset_dict
-        return dataset_dict
-
-    def graph_from_dataset(self, dataset_dict, dataset_ref):
-        super(ODSHDCATdeProfile, self).graph_from_dataset(
-            dataset_dict, dataset_ref)
-        # Enhance Distributions
-        # <dcatde:contributorID rdf:resource="http://dcat-ap.de/def/contributors/schleswigHolstein"/>
-        self.g.add((dataset_ref, DCATDE.contributorID, rdflib.URIRef(
-            "http://dcat-ap.de/def/contributors/schleswigHolstein")))
-
-        extras = dataset_dict.get('extras', None)
-        if extras:
-            attr = None
-            for d in extras:
-                if d['key'] == 'licenseAttributionByText':
-                    attr = d['value']
-                    break
-            if attr:
-                self.g.set(
-                    (dataset_ref, DCATDE.licenseAttributionByText, rdflib.Literal(attr)))
-                for dist in self.g.objects(dataset_ref, DCAT.distribution):
-                    self.g.set(
-                        (dist, DCATDE.licenseAttributionByText, rdflib.Literal(attr)))
-
 
 _RESOURCE_FORMATS_IMPORT = None
 _RESOURCE_FORMATS_EXPORT = None
 
-
 def resource_formats():
     global _RESOURCE_FORMATS_IMPORT
     global _RESOURCE_FORMATS_EXPORT
@@ -142,14 +91,12 @@ def resource_formats():
             _RESOURCE_FORMATS_EXPORT[elem.split('/')[-1]] = elem
             _RESOURCE_FORMATS_IMPORT[elem] = elem.split('/')[-1]
 
-
 def resource_formats_export():
     global _RESOURCE_FORMATS_EXPORT
     if not _RESOURCE_FORMATS_EXPORT:
         resource_formats()
     return _RESOURCE_FORMATS_EXPORT
 
-
 def resource_formats_import():
     global _RESOURCE_FORMATS_IMPORT
     if not _RESOURCE_FORMATS_IMPORT:
@@ -159,7 +106,6 @@ def resource_formats_import():
 
 _LANGUAGES = None
 
-
 def get_language():
     ''' When datasets are exported in rdf-format, their language-tag
     should be given as
@@ -190,4 +136,4 @@ def get_language():
             for language_line in language_mapping_table:
                 _LANGUAGES[language_line[0]] = language_line[1]
 
-    return _LANGUAGES
+    return _LANGUAGES
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_arrow_left.svg b/ckanext/odsh/public/base/images/icon_arrow_left.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b6444d840d6a95b0d9bb9086315e5950762ae8e8
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_arrow_left.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="19.692" viewBox="0 0 16 19.692"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M23,8.923v9.846H16.846v4.923L7,13.846,16.846,4V8.923Z" transform="translate(-7 -4)"/></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_arrow_right.svg b/ckanext/odsh/public/base/images/icon_arrow_right.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8100a08444b09bac12d5e37715d8cd9218e5e6ee
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_arrow_right.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="19.692" viewBox="0 0 16 19.692"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M13.154,8.923V4L23,13.846l-9.846,9.846V18.769H7V8.923Z" transform="translate(-7 -4)"/></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_close.svg b/ckanext/odsh/public/base/images/icon_close.svg
new file mode 100644
index 0000000000000000000000000000000000000000..37a57bf148cc3a6b5cf1372e663be7a0bef2f700
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_close.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="17.999" viewBox="0 0 18 17.999"><defs><style>.a{fill:#444;}</style></defs><g transform="translate(-3910 -11)"><path class="a" d="M101.5,172.4l-.885-.885-3.553,3.552-3.706-3.706-.9.9,3.7,3.709L92.6,179.524l.447.449.438.436,3.558-3.556,3.549,3.551.9-.9-3.553-3.551Z" transform="translate(3821.947 -156.081)"/><path class="a" d="M96.6,167.766a7.877,7.877,0,1,0,7.877,7.876,7.888,7.888,0,0,0-7.877-7.876m0,16.875a9,9,0,1,1,9-9,9.009,9.009,0,0,1-9,9" transform="translate(3822.398 -155.642)"/></g></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_close_white.svg b/ckanext/odsh/public/base/images/icon_close_white.svg
new file mode 100644
index 0000000000000000000000000000000000000000..aebfd442e542ff008eb891eba0b6a4a5729277f5
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_close_white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="17.999" viewBox="0 0 18 17.999"><defs><style>.a{fill:#fff;}</style></defs><g transform="translate(-87.602 -166.642)"><path class="a" d="M101.5,172.4l-.885-.885-3.553,3.552-3.706-3.706-.9.9,3.7,3.709L92.6,179.524l.447.449.438.436,3.558-3.556,3.549,3.551.9-.9-3.553-3.551Z" transform="translate(-0.451 -0.439)"/><path class="a" d="M96.6,167.766a7.877,7.877,0,1,0,7.877,7.876,7.888,7.888,0,0,0-7.877-7.876m0,16.875a9,9,0,1,1,9-9,9.009,9.009,0,0,1-9,9" transform="translate(0 0)"/></g></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_funnel.svg b/ckanext/odsh/public/base/images/icon_funnel.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f5ae5fc47cceaf6e8cba427dfbcf0e00614047f5
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_funnel.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="19.528" height="18" viewBox="0 0 19.528 18"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M19.471,10.022a.592.592,0,0,0-.535-.339H.591a.592.592,0,0,0-.457.968L7.187,19.2v7.887a.592.592,0,0,0,.855.53L12,25.658a.592.592,0,0,0,.329-.53L12.34,19.2l7.052-8.553A.592.592,0,0,0,19.471,10.022Zm-8.179,8.593a.592.592,0,0,0-.135.376l-.008,5.769L8.37,26.137V18.992a.592.592,0,0,0-.135-.377L1.847,10.867H17.681Z" transform="translate(0 -9.683)"/></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_info.svg b/ckanext/odsh/public/base/images/icon_info.svg
new file mode 100644
index 0000000000000000000000000000000000000000..61cfea800270ee0698df56ad8371b0ff6fc51046
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_info.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M12,2A10,10,0,1,1,2,12,10.011,10.011,0,0,1,12,2Zm0-2A12,12,0,1,0,24,12,12,12,0,0,0,12,0Zm0,5.75A1.25,1.25,0,1,1,10.75,7,1.251,1.251,0,0,1,12,5.75ZM14,18H10V17c.484-.179,1-.2,1-.735V11.8c0-.534-.516-.618-1-.8V10h3v6.265c0,.535.517.558,1,.735Z"/></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_lang_danish.png b/ckanext/odsh/public/base/images/icon_lang_danish.png
new file mode 100644
index 0000000000000000000000000000000000000000..8a6a9f60bfaa2ab1e7f448063810e93b6a427d1f
Binary files /dev/null and b/ckanext/odsh/public/base/images/icon_lang_danish.png differ
diff --git a/ckanext/odsh/public/base/images/icon_lang_english.png b/ckanext/odsh/public/base/images/icon_lang_english.png
new file mode 100644
index 0000000000000000000000000000000000000000..5999e319634f3a4c68006c44c828ddcc441bafb6
Binary files /dev/null and b/ckanext/odsh/public/base/images/icon_lang_english.png differ
diff --git a/ckanext/odsh/public/base/images/icon_latest.svg b/ckanext/odsh/public/base/images/icon_latest.svg
new file mode 100644
index 0000000000000000000000000000000000000000..a2741441aec25f95904483f7f44ea6324e51bc74
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_latest.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="17.999" height="18" viewBox="0 0 17.999 18"><defs><style>.a{fill:#fff;}</style></defs><path class="a" d="M21,10.12H14.22L16.96,7.3a7.039,7.039,0,0,0-9.88-.1,6.875,6.875,0,0,0,0,9.79,7.02,7.02,0,0,0,9.88,0A6.513,6.513,0,0,0,19,12.1h2a9.341,9.341,0,0,1-2.64,6.29,9.054,9.054,0,0,1-12.72,0A8.84,8.84,0,0,1,5.62,5.81a8.987,8.987,0,0,1,12.65,0L21,3ZM12.5,8v4.25L16,14.33l-.72,1.21L11,13V8Z" transform="translate(-3.001 -3)"/></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/icon_phone.svg b/ckanext/odsh/public/base/images/icon_phone.svg
new file mode 100644
index 0000000000000000000000000000000000000000..3f8189d6c89ee21adb6af5d2a895600fd0204756
--- /dev/null
+++ b/ckanext/odsh/public/base/images/icon_phone.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 52.5 (67469) - http://www.bohemiancoding.com/sketch -->
+    <title>local_phone</title>
+    <desc>Created with Sketch.</desc>
+    <g id="Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="Rounded" transform="translate(-341.000000, -3213.000000)">
+            <g id="Maps" transform="translate(100.000000, 3068.000000)">
+                <g id="-Round-/-Maps-/-local_phone" transform="translate(238.000000, 142.000000)">
+                    <g>
+                        <polygon id="Path" points="0 0 24 0 24 24 0 24"></polygon>
+                        <path d="M19.23,15.26 L16.69,14.97 C16.08,14.9 15.48,15.11 15.05,15.54 L13.21,17.38 C10.38,15.94 8.06,13.63 6.62,10.79 L8.47,8.94 C8.9,8.51 9.11,7.91 9.04,7.3 L8.75,4.78 C8.63,3.77 7.78,3.01 6.76,3.01 L5.03,3.01 C3.9,3.01 2.96,3.95 3.03,5.08 C3.56,13.62 10.39,20.44 18.92,20.97 C20.05,21.04 20.99,20.1 20.99,18.97 L20.99,17.24 C21,16.23 20.24,15.38 19.23,15.26 Z" id="🔹-Icon-Color" fill="#003064"></path>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/base/images/logo-quer.png b/ckanext/odsh/public/base/images/logo-quer.png
new file mode 100644
index 0000000000000000000000000000000000000000..a3baa7b1f60ef757a92924772fe7bd160c68dcc2
Binary files /dev/null and b/ckanext/odsh/public/base/images/logo-quer.png differ
diff --git a/ckanext/odsh/public/base/images/logo-quer@2x.png b/ckanext/odsh/public/base/images/logo-quer@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..7a77936ab8710e3a940e9f93d859a3992525d719
Binary files /dev/null and b/ckanext/odsh/public/base/images/logo-quer@2x.png differ
diff --git a/ckanext/odsh/public/base/images/platzhalter.svg b/ckanext/odsh/public/base/images/platzhalter.svg
new file mode 100644
index 0000000000000000000000000000000000000000..746fb2026e686850a5b0c295612f98768f866e28
--- /dev/null
+++ b/ckanext/odsh/public/base/images/platzhalter.svg
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="svg10"
+   xml:space="preserve"
+   width="793.70074"
+   height="1122.5197"
+   viewBox="0 0 793.70074 1122.5197"
+   sodipodi:docname="platzhalter.svg"
+   inkscape:version="0.92.4 (unknown)"><metadata
+     id="metadata16"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+     id="defs14" /><sodipodi:namedview
+     pagecolor="#f1f1f1;"
+     bordercolor="#f1f1f1;"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1855"
+     inkscape:window-height="1056"
+     id="namedview12"
+     showgrid="false"
+     inkscape:zoom="0.81423964"
+     inkscape:cx="205.87465"
+     inkscape:cy="561.25983"
+     inkscape:window-x="65"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g18" /><g
+     id="g18"
+     inkscape:groupmode="layer"
+     inkscape:label="plazthalter"
+     transform="matrix(1.3333333,0,0,-1.3333333,0,1122.5197)"><g
+       id="g20"><g
+         id="g22"
+         transform="matrix(1,0,0,-1,0,841.88977)"><path
+           d="M 2.145,1.891 H 597.856 V 844.032 H 2.145 Z"
+           style="fill:#f1f1f1;fill-opacity:1;fill-rule:nonzero;stroke:#c8b7b7;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+           id="path24"
+           inkscape:connector-curvature="0" /></g></g></g></svg>
\ No newline at end of file
diff --git a/ckanext/odsh/public/odsh.css b/ckanext/odsh/public/odsh.css
index de9f959d270ec810ef6e65d121615a208d3a2ce6..cb3f12fa070bae5751abb1c24ac28242f10eac05 100644
--- a/ckanext/odsh/public/odsh.css
+++ b/ckanext/odsh/public/odsh.css
@@ -1,11 +1,5 @@
 /* FONTS */
 
-@media (max-width: 767px){
-.span9 {
-    width: 100%;
-}
-}
-
 @font-face{
     font-family:"MuseoSans";
     src:url("/base/fonts/Fonts/905300/fd479df2-01b0-4e3a-a411-915c477f1352.eot?#iefix");
@@ -29,6 +23,17 @@ html,body {
     height: 100%;
 }
 
+@media (max-width: 767px) {
+    body {
+        padding-left: 0px;
+        padding-right: 0px;
+    } 
+
+    .hide-on-mobile {
+        display: none;
+    }
+}
+
 /* FROM: https://stackoverflow.com/questions/2610497/change-an-html5-inputs-placeholder-color-with-css */
 /* do not group these rules */
 *::-webkit-input-placeholder {
@@ -64,7 +69,8 @@ input, button, select, textarea {
 
 h1{
     color:#003064;
-    font-weight: normal ;
+    font-size: 38px;
+    font-weight: 500;
 }
 
 h3{
@@ -73,6 +79,18 @@ h3{
     font-size:20px;
 }
 
+.skip-link {
+    position: fixed;
+    top: -200px;
+    text-decoration: none;
+    padding: 10px;
+    display: inline-block;
+  }
+
+.skip-link:focus {
+    top: 0;
+}
+
 .secondary h1.heading {
     color:black;
     font-weight: normal ;
@@ -83,19 +101,74 @@ h3{
 
 /* same width as schleswig-holstein.de */
 .container {
-    width: 960px;
+    max-width: 960px;
 }
-@media (max-width: 767px){
-.container {
-    width: 100%;
+
+
+@media (max-width: 1023px){
+    .container,
+    .masthead .container
+    {
+        padding-right: 80px;
+        padding-left: 80px;
+        box-sizing: border-box;
+        max-width: 100%;
+        width: auto;
+    }
 }
+
+@media (max-width: 767px) {
+    .container
+    {
+        padding-right: 15px;
+        padding-left: 15px;
+    }
+    .masthead .container
+    {
+        padding-right: 0;
+        padding-left: 0;
+    }
 }
 
 .search-form, .odsh-dataset-heading {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
     border-bottom: 4px solid #dbdbdb;
-    padding-bottom: 5px;
+    padding-bottom: 26px;
+    margin-bottom: 0px;
 }
 
+@media (min-width: 1024px){
+    .search-form, .odsh-dataset-heading {
+        border-bottom: none;
+        margin-bottom: 0px;
+        margin-left: -15px;
+        margin-right: -15px;
+        padding-bottom: 0;
+    }
+
+    .search-form:after {
+        content: ""; 
+        display: block; 
+        margin: 0 auto; 
+        width: calc(100% - 30px); 
+        padding-top: 25px; 
+        border-bottom: 4px solid #dbdbdb; 
+        order: 100;
+    }
+
+    .search-form h2 {
+        margin-left: 15px;
+    }
+    
+    .form-select.control-group.control-order-by {
+        margin-left: 15px;
+        margin-right: 15px;
+    }
+}
+
+
 
 .organizaion-full-description{
     padding-bottom: 50px;
@@ -112,6 +185,9 @@ h3{
     margin-bottom: 10px;
 }
 
+.control-order-by {
+    margin: 0;
+}
 
 .search-form .control-order-by select {
     width: 225px;
@@ -121,14 +197,109 @@ h3{
     color: #003064;
 }
 
-.search-form h2, 
+.search-form h2,
 .odsh-dataset-heading h2,
 .odsh-dataset-heading .title 
  {
     margin-top: 0px;
-    font-size: 25px;
+    margin-bottom: 10px;
+    margin-right: 22px;
+    font-size: 24px;
+    letter-spacing: 0.01em;
     color: #003064;
     font-weight: 300;
+    line-height: 28px;
+}
+
+
+.odsh-dataset-heading > h2 {
+    margin: 0px;
+}
+
+.resources h3 {
+    font-size: 18px;
+    letter-spacing: 0.01em;
+    color: #000000;
+}
+
+section#dataset-preview {
+    margin-top: 26px;
+}
+
+@media (max-width: 767px) {
+    section#dataset-preview {
+        display: none;
+    }
+}
+
+section#dataset-preview p {
+    color: black;
+    font-size: 14px;
+    letter-spacing: 0.01em;
+}
+
+.container-preview-large {
+    padding-top: 10px;
+    padding-bottom: 10px;
+    height: 287px;
+    background-color: #F2F2F2;
+    display: flex;
+}
+
+.container-preview-large a {
+    margin-left: auto;
+}
+
+.container-preview-large img {
+    height: 100%;
+    margin-left: auto;
+    margin-right: auto;
+    border: 1px solid #666666;
+}
+
+section#dataset-collection {
+    padding-top: 17px;
+    border-top: 5px solid #DBDBDB;
+    margin-top: 38px;
+    color: black;
+}
+
+section#dataset-collection .button-container {
+    margin-top: 20px;
+    display: flex;
+}
+
+section#dataset-collection .button-container a {
+    margin-right: 24px;
+    padding-left: 12px;
+    padding-right: 12px;
+}
+
+section#dataset-collection .button-container a:nth-child(2) {
+    /* second a */
+    margin-left: auto;
+}
+
+section#dataset-collection .button-container a:last-child {
+    /* second a */
+    margin-right: 0;
+}
+
+section#dataset-collection .button-container img {
+    width: 18px;
+    height: auto;
+    margin-right: 5px;
+    margin-left: 5px;
+}
+
+@media (max-width: 767px) {
+    .search-form h2, 
+    .odsh-dataset-heading h2,
+    .odsh-dataset-heading .title 
+    {
+        width: 100%;
+        margin-bottom: 8px;
+    }
 }
 
 .odsh-dataset-heading .title
@@ -145,11 +316,50 @@ h3{
     padding: 0;
 }
 
+#section-org.module-content {
+    padding-bottom: 87px;
+    border-bottom: solid 3px #DBDBDB;
+}
+
+.information-organisation {
+    margin-top: 20px;
+    font-size: 12px;
+    text-align: left;
+    letter-spacing: 0.12px;
+    color: #000000;
+}
+
+.information-organisation p {
+    margin-bottom: 0;
+}
+
+.information-organisation a {
+    color: inherit;
+}
+
+.information-organisation .phone::before{
+    content: "";
+    display: inline-block;
+    background-image: url(/base/images/icon_phone.svg);
+    background-repeat: no-repeat;
+    background-size: .7rem .7rem;
+    background-position: 50% 50%;
+    width: 0.8rem;
+    height: 0.8rem;
+    vertical-align: middle;
+}
+
+
 .module-narrow .module-footer {
     padding: 0;
     border: none;
     font-size: 12px;
 }
+@media (max-width: 767px) {
+    .js [role="main"] .secondary .filters > div .module-footer {
+        display: block;
+    }
+}
 
 .module .read-more{
     font-weight: normal;
@@ -186,10 +396,11 @@ input[type=radio], input[type=checkbox] {
     background-color: #f2f2f2;
 }
 
-.is-table-row .secondary.span3 {
-    width: 191px;
-    max-width: 1970px;
-    padding: 20px 16px 0px;
+.secondary.span3 {
+    box-sizing: border-box;
+    min-width: 300px;
+    max-width: 300px;
+    padding: 40.66px 16px 0px;
 }
 .secondary .module-narrow .module-content{
     padding-left: 0px;
@@ -197,16 +408,15 @@ input[type=radio], input[type=checkbox] {
 }
 
 .primary {
-    padding-left: 20px;
+    padding-left: 31px;
 }
 
 .primary.organization {
     padding-left: 0px;
 }
 
-.is-table-row .primary.span9 {
-    width: 717px;
-    float: right;
+.primary.span9 {
+    max-width: 640px;
 }
 
 .primary.logout {
@@ -214,8 +424,8 @@ input[type=radio], input[type=checkbox] {
     padding-left: 0px;
 }
 
-@media (max-width: 767px){
-.is-table-row .primary.span9 {
+@media (max-width: 1023px){
+.primary{
     padding-left: 0px;
     width: 100%;
     margin-left: 0;
@@ -223,9 +433,6 @@ input[type=radio], input[type=checkbox] {
 .primary.span9{
     width: 100%;
 }
-.primary{
-    padding: 0px;
-}
 }
 
 .wrapper {
@@ -235,6 +442,12 @@ input[type=radio], input[type=checkbox] {
     border: none;
 }
 
+@media (max-width: 1023px){
+    .wrapper {
+        width: 100%;
+    }
+}
+
 .karte_inner {
     background-color: lightgrey;
     height: 220px;
@@ -243,20 +456,25 @@ input[type=radio], input[type=checkbox] {
 
 .filter-reset {
     padding: 0px 0px 10px 0px;
+    margin-top: 18px;
 }
 
 .filter-reset-label {
     float: left;
+    font-size: 14px;
+    letter-spacing: 0.14px;
+    color: black;
 }
 
 .filter-reset-box {
     float: right;
     background-color: white;
-    padding: 0px 10px 0px 10px;
+    padding: 1px 10px 4px 10px;
 }
 
 .filter-reset-box a {
     font-size: 12px;
+    color: #003064;
 }
 
 .filters section nav {
@@ -271,28 +489,74 @@ input[type=radio], input[type=checkbox] {
 
 .nav-simple>li {
     border-bottom: 0px;
-    padding: 15px 0px 0px 0px;
-    width: 193px;
+    padding: 10px 0px 0px 0px;
+    width: 100%;
     white-space: nowrap;
     display: flex;
     justify-content: space-between;
+    align-items: center;
 }
 
 .nav-item .facet_label {
-    flex:1;
     white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
+    max-width: 240px;
 }
 
-.nav-item .facet_label a{
+.nav-item .facet_label label.odsh-visible-label{
+    display: inline;
+    font-size: inherit;
+}
+
+.nav-item .facet_label label a{
     color: black;
+    display: inline;
 }
 
 .nav-item .facet_count {
     display: inline-block;
     background-color: white;
-    padding: 0px 2px 0px 2px;
+    padding: 1px 2px;
+}
+
+.package-info-category {
+    margin: 0;
+}
+
+.category-with-icon {
+    display: inline-block;
+    /* padding-bottom: 0.5rem; */
+    vertical-align: middle;
+}
+
+.group-icon-container {
+    display: inline-block;
+    width: 16px;
+    height: 16px;
+    margin-right: 8px;
+    margin-left: 3px;
+}
+
+.group-icon-container img {
+    vertical-align: top;
+}
+
+.category-header {
+    display: inline-block;
+    padding-right: 6px;
+    vertical-align: top;
+}
+
+.category-icon-container {
+    display: inline-block;
+    width: 16px;
+    height: 16px;
+    margin-right: 3px;
+}
+
+.category-name {
+    padding-right: 15px;
 }
 
 
@@ -304,7 +568,7 @@ input[type=radio], input[type=checkbox] {
 
 label.label-score,
 label.rangesearch,
-input[type=checkbox] + label.mylabel {
+input[type=checkbox] + span.mylabel {
     background: #fff;
     border: 1px solid black;
     height: 8px;
@@ -317,7 +581,7 @@ input[type=checkbox] + label.mylabel {
 
 input[type=checkbox]:checked + label.label-score,
 label.rangesearch.checked,
-input[type=checkbox]:checked + label.mylabel {
+input[type=checkbox]:checked + span.mylabel {
     background: url(/base/images/checked.png);
     background-color: #fff;
     background-size: 8px 8px;
@@ -330,28 +594,6 @@ input[type=checkbox]:checked + label.mylabel {
     margin-bottom: 0px;
 }
 
-
-@media (max-width: 768px)
-{
-input[type=checkbox] + label.mylabel,
-input[type=checkbox]:checked + label.mylabel {
-    height: 20px;
-    width: 20px;
-    background-size: 20px 20px;
-    vertical-align: text-bottom;
-}
-.facet_label {
-    font-size: 18px;
-    vertical-align: text-bottom;
-}
-.nav-simple>li{
-    width: 100%;
-}
-.js [role=main] .secondary .filters {
-    background-color: white;
-}
-}
-
 .checklabel input[type="checkbox"]
 {
     float: inherit;
@@ -359,7 +601,7 @@ input[type=checkbox]:checked + label.mylabel {
 
 label.label-score,
 label.rangesearch,
-label.mylabel  {
+span.mylabel  {
     margin-right: 3px;
     margin-bottom: 0px;
     -webkit-user-select: none; /* Safari */        
@@ -369,7 +611,7 @@ label.mylabel  {
 }
 
 label.rangesearch::after,
-label.mylabel::after {
+span.mylabel::after {
     content: "";
 }
 
@@ -386,6 +628,10 @@ label.rangesearch.disabled {
     display: inline-block;
 }
 
+.controls.rangesearch label {
+    display: block;
+}
+
 .search-score
 {
     color:black;
@@ -399,13 +645,15 @@ label.rangesearch.disabled {
 
 .rangesearch a{
     color:black;
-    font-size:14px;
+    font-size:12px;
 }
 
 .controls input.rangesearch{
-    font-style: normal;
-    width:187px;
+    box-sizing: border-box;
+    width: 100%;
+    height: 1.5rem;
     padding: 2px;
+    font-style: normal;
     font-size: 12px;
     line-height: 1.16666667em;
 }
@@ -446,20 +694,45 @@ label.rangesearch.disabled {
     font-size: 10px;
     position: relative;
     top: -8px;
-    right: -8px;    
+    right: -8px;
+    margin-right: 0; 
 }
 .pill.error .remove .fa.fa-times{
     background-color: #d4004b;
 }
 
-.container-fluid.odsh-dataset-item {
-    padding: 20px 0px 20px 0px;
+.odsh-dataset-item {
+    display: flex;
+    padding: 27px 0px;
     border-bottom: 2px solid #DBDBDB;
-    display: table;
+    width: 100%;
 }
-.container-fluid.odsh-dataset-item:hover {
+.odsh-dataset-item:hover {
     background-color: rgb(246,247,249);
 }
+.odsh-dataset-item:last-child {
+    border-bottom: none;
+}
+
+.preview-image-container {
+    display: flex;
+    flex-direction: column;
+    margin-right: 25px;
+    width: auto;
+}
+
+@media (max-width: 767px) {
+    .preview-image-container {
+        display: none;
+    }
+}
+
+.preview-image-container img {
+    margin-top: auto;
+    height: auto;
+    max-width: 102px;
+    border: 1px solid #666666;
+}
 
 .organization-item{
     padding: 5px 0px 5px 0px;
@@ -490,29 +763,28 @@ a:hover.organization-item ,a:focus.organization-item
     width: 705px;
 }
 
-.dataset-content {
-    width: 470px;
-    display: table-cell;
-    position: relative;
-}
-
 .dataset-heading {
-    margin-right: 30px;
     font-weight: normal;
     font-size: 20px;
     word-wrap: break-word;
-    max-width: 310px;
+    width: 100%;
+    margin-bottom: 12px;
+}
+.dataset-content {
+    flex-grow: 1;
 }
 .dataset-content p{
     font-size: 12px;
-    margin: 0 0 5px; 
+    /* margin: 0 0 5px;  */
 }
 .dataset-heading a{
+    color: black;
     text-decoration: none;
+    padding-right: 30px;
+    letter-spacing: 0.18px;
 }
 
 .dataset-spacer{
-    display: table-cell;
     width: 25px;
 }
 
@@ -522,9 +794,14 @@ a:hover.organization-item ,a:focus.organization-item
 }
 
 .dataset-meta {
-    width: 225px;
-    height: 100%;
-    display: table-cell;
+    position: relative;
+}
+
+.package-info-pill img {
+    padding-right: 5px;
+    height: auto;
+    width: 18px;
+    bottom: 1.5px;
     position: relative;
 }
 
@@ -555,8 +832,6 @@ ul.dataset-resources {
 }
 
 
-element.style {
-}
 .dataformat-label:hover {
     background-color: #d4004b!important;
 }
@@ -564,13 +839,10 @@ element.style {
 
 
 .dataset-stars {
+    width: 190px;
     margin-bottom: 10px;
 }
 
-
-.popover-content{
-
-}
 .popover{
     width: unset;
     display:inline-table!important;
@@ -671,6 +943,11 @@ label:after {
     font-style: normal;
 } 
 
+input#field-username {
+    margin-bottom: 30px;
+    vertical-align: super;
+}
+
 .control-group.error input,
 .control-group.error select,
 .control-group.error .select2-choices,
@@ -965,15 +1242,10 @@ label:after {
 .footer a{
     color:white;
 }
-@media (max-width: 767px){
-.footer{
-    border-top:0px;
-    width: 100%;
-}
 body {
     background-color: white;
 }
-}
+
 .footer .container{
     width: 100%;
     max-width: 1000px;
@@ -1015,6 +1287,50 @@ body {
     margin-top: 10px;
 }
 
+@media (max-width: 1023px){
+    .footer{
+        border-top-width: 30px;
+        width: 100%;
+    }
+    .footer-line{
+        border-top: 1px solid white;
+    }
+}
+
+@media (max-width: 767px){
+    .footer{
+        border-top-width: 20px;
+    }
+    .footer .container {
+        padding-bottom: 0;
+    }
+    .footer-line{
+        border-top: none;
+        margin-top: 0;
+        margin-bottom: 0;
+    }
+    .footer-content{
+        box-sizing: border-box;
+        padding-bottom: 15px;
+        background-image: none;
+        height: 139px;
+        display: flex;
+        flex-direction: column-reverse;
+    }
+    .footer-first-row{
+        padding-top: 0;
+        height: 0;
+    }
+    .footer-right{
+        display: flex;
+        justify-content: space-between;
+        padding-bottom: 15px;
+    }
+    .footer-icon a{
+        padding: 15px 0;
+    }
+}
+
 .toolbar .breadcrumb li:after {
     background-image: url(/base/images/arrow-right.png);
     background-repeat: no-repeat;
@@ -1079,6 +1395,12 @@ body {
     border: none;
 }
 
+@media(maxwidth: 767px) {
+    .page-header .nav-tabs {
+        margin: 0;
+    }
+}
+
 .module .module-content {
     margin: 0px;
 }
@@ -1086,8 +1408,9 @@ body {
 .info-detail {
     margin-bottom: 20px;
     font-size: 12px;
+    letter-spacing: 0.01em;
     color: black;
-    max-width: 193px;
+    max-width: 100%;
     word-break: break-word;
 }
 .info-detail p{
@@ -1097,9 +1420,22 @@ body {
     margin-top: 5px;
     margin-bottom: 5px;
 }
+.info-detail img {
+    margin-right: 5px;
+}
+
+.info-detail.groups-detail > div {
+    margin-bottom: 5px;
+}
+
 .odsh-dataset-heading {
     word-wrap: break-word;
-    margin-bottom: 30px;
+    padding-bottom: 16px;
+    margin-bottom: 18px;
+}
+
+.odsh-dataset-edit-button {
+    margin-top: 10px;
 }
 
 .odsh-dataset-heading .dataset-stars {
@@ -1110,11 +1446,18 @@ body {
     margin-bottom: 30px;
 }
 
+.notes > p {
+    font-size: 16px;
+    letter-spacing: 0.01em;
+    color: #000000;
+}
+
 .resource-list {
     margin: 0px;
 }
 
 .resource-item {
+    display: flex;
     background: #f2f2f2;
     margin-top: 10px;
     padding: 15px 15px 15px 15px;
@@ -1135,14 +1478,10 @@ body {
     text-align: center;
 }
 
-element.style {
-}
 .dataformat-label:hover {
     background-color: #d4004b!important;
 }
 
-
-
 .resource-title {
     float: left;
     margin-left: 5px;
@@ -1153,18 +1492,34 @@ element.style {
     cursor: pointer;
     text-decoration: none;
     min-height: 1em;
+    color: black;
 }
 
 .resource-title a{
     color: black;
+    letter-spacing: 0.16px;
 }
 
 .resource-title a:hover{
     text-decoration: none
 }
 
+.resource-title p:first-of-type{
+    font-size: 12px;
+    letter-spacing: 0.12px;
+    padding-top: 12px;
+    margin-bottom: 0;
+}
+.resource-title p{
+    font-size: 12px;
+    letter-spacing: 0.12px;
+    padding-top: 0;
+}
+
 .resource-title-container{
     display: flex;
+    justify-content: space-between;
+    width: 100%;
 }
 .resource-title-container .dataformat-label:hover{
     background-color: #003064 !important;
@@ -1185,15 +1540,6 @@ element.style {
     float:left;
 }
 
-@media (max-width: 767px)
-{
-.is-table-row .resource-details-left {
-    /* padding-right: 0px; */
-    width: 100%;
-    /* float:none; */
-}
-}
-
 .resource-icons {
     font-size: 24px;
     margin-left: 5px;
@@ -1230,6 +1576,12 @@ element.style {
     vertical-align: 0px;
 }
 
+@media (max-width: 767px) {
+    .toolbar .breadcrumb .home {
+        display: inline-block;
+    }
+}
+
 
 .resource-icons a {
     color: #003064;
@@ -1246,19 +1598,31 @@ element.style {
 }
 
 .search-box-container{
-    width:100%;
-    max-width: 430px;
+    box-sizing: border-box;
+    width: auto;
+    height: 40px;
+    max-width: 470px;
     margin-bottom: 60px;
-    margin-left: 250px;
+    margin-left:330px;
+}
+
+.search-field {
+    display: flex;
+    align-items: center;
 }
 
 #field-sitewide-search {
-    font-size: 87%;
+    flex: 1;
+    font-size: 14px;
     font-weight: 300;
-    padding: 0px;
+    padding-top: 0px;
+    padding-bottom: 0px;
     padding-right: 35px;
-    padding-left: 5px;
-    width: 100%;
+    padding-left: 14.24px;
+    margin: 0px;
+    margin-left: 0px;
+    width: inherit;
+    min-width: 210px;
     line-height: 1.1;
     border: 1px solid #003064!important;
     color:#003064;
@@ -1266,30 +1630,57 @@ element.style {
     box-shadow: none !important;
     height: 40px;
     border-radius: 0px;
+    box-sizing: border-box;
 }
 
 .simple-input .field .btn-search {
-    height: 25px;
-    width: 25px;
+    height: 36px;
+    width: 36px;
     background: url(/base/images/Icon-Suche.png);
-    background-size: 25px 25px;
-    right: -28px;
-    top: -25px;
-    position: relative;
-    float: right;
+    background-size: 36px 36px;
+    top: 3px;
+    margin: 0px 5px;
+}
+
+.simple-input .field .btn-search:focus {
+    border-color: #003064;
+    border-width: 1px;
+    border-style: dotted;
 }
 
-.search-box-container .field{
+/* .search-box-container .field{
     width: 100%;
     max-width: 465px;
+} */
+
+@media (max-width: 1023px){
+    .search-box-container {
+        flex: 1;    
+        box-sizing: border-box;
+        margin-left: auto;
+        margin-bottom: 20px;
+        padding: 0px;
+        display: inline-block;
+        height: 40px;
+        width: 100%;
+        min-width: 210px;
+    }
+
+    .filter-search-row {
+        display: flex;
+        flex-wrap: wrap;
+    }
 }
 
 @media (max-width: 767px){
-.search-box-container{
-    margin-bottom: 20px;
-    padding: 0px;
-    margin-left: 0px;
-}
+    .search-box-container:focus-within {
+        position: absolute;
+        margin-right: auto;
+        margin-left: auto;
+        padding: 0;
+        width: 80%;
+        min-width: 95%;
+    }
 }
 
 
@@ -1501,22 +1892,6 @@ element.style {
     margin-bottom: 0px;
 }
 
-#dataset-map .module-heading [class^="icon-"],
-#dataset-map .module-heading [class*=" icon-"] {
-  font-size: 14px;
-  line-height: 1;
-  width: 14px;
-  text-align: left;
-  display: inherit;
-}
-@media (max-width: 767px){
-#dataset-map {
-display: none;
-}
-#dataset-map {
-display: none;
-}
-}
 
 @media (min-width: 768px){
 .span9 div.module-content {
@@ -1524,7 +1899,9 @@ display: none;
 }
 }
 
-.field-organization .select2-container .select2-choice {
+.field-organization .select2-container .select2-choice,
+.field-spatial_uri .select2-container .select2-choice 
+{
     background-color: #F6F7F9;
     background-image: none;
     background-image: none;
@@ -1537,36 +1914,110 @@ display: none;
 
 .logo{
     margin-left: -7px;
-    height: 70px; 
+    height: auto;
+    box-sizing: border-box;
+    width: 155px;
+    display: block;
 }
-.logo img{
-    height: 65px; 
-    width:auto;
-    padding: 6px;
+.img-logo-large {
+    display: initial;
+}
+.img-logo-small {
+    display: none;
 }
 
-.site-title{
-    color:black;
-    font-size: 2.5rem; 
-    margin-top: 30px; 
-    color: #333; 
-    text-align: center; 
+@media (max-width: 1023px){
+    .logo {
+        width: 121.1px;
+        height: auto;
+        display: block;
+    }
+}
+
+@media (max-width: 767px){
+    .logo {
+        display: initial;
+    }
+    .img-logo-large {
+        display: none;
+    }
+    .img-logo-small {
+        display: initial;
+    }
+}
+
+.topline {
+    margin-bottom: 25px;
+}
+@media (max-width: 767px){
+    .topline {
+        margin-bottom: 0px;
+    }
+}
+
+.site-title {
+    color:#003064;
+    font-size: 38px; 
+    position: absolute;
+    left: 340px;
+    text-align: left; 
     line-height: 1.47; 
-    font-weight: 100; 
+    font-weight: 500;
+    letter-spacing: 0.38px;
+    padding-top: 24px;
+}
+
+@media (max-width: 1023px){
+    .site-title{
+        font-size: 24px;
+        line-height: 1.0;
+        display: inline-block;
+        left: initial;
+        margin-left: 33px;
+    }
+}
+
+#dataset-search-box-form{
+    margin-bottom: 0;
 }
 
 @media (max-width: 767px){
-.logo img{
-    height: 25px; 
-    width:auto;
-    padding: 6px;
+    .site-title{
+        display: none;
+    }
+}
+
+#menu-button-and-title {
+    display: none;
+}
+@media (max-width: 767px){
+    #menu-button-and-title {
+        display: flex;
+        align-items: center;
+        padding-left: 15px;
+        padding-right: 15px;
+        background-color: #f2f2f2;
+    }
 }
-.site-title{
-    font-size: 1.5rem; 
-    margin-top: 15px; 
-    color: #333; 
-    line-height: 1.0; 
+#menu-button-and-title span {
+    display: inline-block;
+    color: #003064;
+    padding-right: 20px;
 }
+#menu-button-and-title h1 {
+    display: inline-block;
+}
+
+
+.site-title-mobile{
+    font-size: 18px;
+    line-height: 1.0;
+    position: relative;
+    margin-left: 0;
+}
+
+.search-form .filter-list {
+    width: 100%
 }
 
 .filter-list .filtered.pill,
@@ -1574,6 +2025,14 @@ display: none;
     background-color: #003064;
     color:white;
 }
+
+@media (min-width: 1024px){
+    .search-form .filter-list {
+        margin-left: 15px;
+        margin-right: 15px;
+    }
+}
+
 .filtered.pill.error{
     background-color: #d4004b;
 }
@@ -1582,6 +2041,7 @@ display: none;
 .share-links {
     display: flex;
     justify-content: space-between;
+    margin-top: 10px;
 }
 
 .share-links a{
@@ -1591,7 +2051,7 @@ display: none;
 }
 
 .share-links img {
-    width: 20px;
+    width: 23px;
 }
 
 .home-title{
@@ -1774,11 +2234,9 @@ a:hover.tooltips_cls span {
 #testsystem p { margin:0 }
 
 .tag-container {
-    border-top: 1px solid #DBDBDB;
     padding-top:10px;
     margin-top:20px;
     display: flex;
-    width: 720px;
     flex-wrap: wrap;
     flex-direction: row;
     justify-content: start;
@@ -1859,15 +2317,23 @@ span.clear {
 .package-info-pill
 {
     display: inline-block;
+    box-sizing: border-box;
+    height: 20px;
     padding: 3px 10px;
     background-color: #dbdbdb;
-    border-radius: 5px;
+    border-radius: 3px;
     font-size: 12px;
+    margin-right: 10px;
+    margin-bottom: 17.84px;
 }
 
-p.package-info-categorie 
+p.package-info-subject 
 {
-    margin-top: 15px;
+    margin-top: 12px;
+    margin-bottom: 0px;
+}
+
+p.package-info-issued {
     margin-bottom: 0px;
 }
 
@@ -2001,9 +2467,34 @@ p.package-info-categorie
     font-size: 20px;
     cursor: pointer;
 }
+
 .search-form a 
 {
     color: #003064;
+    margin-left: auto;
+    margin-right: 22px;
+}
+@media (max-width: 767px) {
+    .search-form a
+    {
+        order: 4;
+        margin-right: 0;
+    }
+
+    .search-form .filter-list {
+        order: 5;
+        break-before: always;
+    }
+
+    .search-form #datesearch-filter {
+        order: 6;
+    }
+}
+
+.search-form a:focus i {
+    border-color: #003064;
+    border-width: 1px;
+    border-style: dotted;
 }
 
 .error-title
@@ -2075,6 +2566,7 @@ p.package-info-categorie
     padding: 3px 3px 1px 3px;
     font-size: 14px;
     margin-right: 4px;
+    text-shadow: none;
 }
 
 .comments-heading{
@@ -2167,96 +2659,113 @@ p.package-info-categorie
     width: 715px;
 }
 
-@media (max-width: 767px)
-{
-[role=main] .secondary.span3 {
-    display: block;
-    width: 100%;
-    margin-left: 0;
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    box-sizing: border-box;
-    padding: 0;
-    order: 2;
-}
-#testsystem 
-{
-    display: none;
-}
-.simple-input .field .btn-search
-{
-    display: none;
-}
-#field-sitewide-search {
-    padding: 0px;
-    width: 100%;
-    margin: 0px;
-}
-}
+@media (max-width: 1023px) {
+    [role=main] .secondary.span3 {
+        max-width: 300px;
+        margin-left: 0;
+        -webkit-box-sizing: border-box;
+        -moz-box-sizing: border-box;
+        box-sizing: border-box;
+        position: fixed;
+        top: 0;
+        left: 0;
+        display: none;
+        z-index: 3;
+        height: 100%;
+        overflow: scroll;
+        filter: blur(0) brightness(100%);
+    }
 
-@media (max-width: 767px)
-{
-    .masthead .container,
-    body {
-    padding-left: 0px;
-    padding-right: 0px;
-}
-#content
-{
-    margin-left: 0px;
-    padding-right: 0px;
-}
-.dataset-heading {
-    max-width: unset;
-    width: 100%;
-    margin: 0px;
-}
-/* .dataset-heading a {
-    max-width: unset;
-    width: 100%;
-    margin: 0px;
-} */
-.js body.filters-modal .secondary .filters .hide-filters i {
-    font-size: 32px;
-}
-.container-fluid.odsh-dataset-item {
-    width: 100%;
-    padding: 20px 15px 20px 15px;
-    box-sizing: border-box;
-}
-.row.wrapper.is-table-row
-{
-    width: 100%;
-    display: flex;
-    flex-direction: column;
-}
-.dataset-info.issued
-{
-    position: relative;
-}
-ul.dataset-resources
-{
-    margin: 5px 0px 5px 0px;
-}
-.stages li .highlight {
-     text-indent: unset; 
-}
-.tag-container
-{
-    width: 100%;
-}
-}
-.module-content.page-header
-{
-    background-color: unset;
+    [role=main] .secondary.span3 > .filters {
+        position: initial;
+        background-color: inherit;
+        padding: 0px;
+    }
+
+    .js [role=main] .secondary > .filters > div {
+        background-color: inherit;
+    }
+
+    div.hide-filters-style > a.hide-filters {
+        display: block;
+        position: absolute;
+        top: 18px;
+        right: 18px;
+    }
+    @media (max-width: 767px) {
+        .js body.filters-modal .secondary .filters > .hide-filters-style > a.hide-filters {
+            display: block;
+            position: absolute;
+            top: 18px;
+            right: 18px;
+            opacity: 1;
+        }
+    }
+
+    body.menu-modal {
+        overflow: hidden;
+    }
+    
+    body.filters-modal div.primary,
+    body.filters-modal header,
+    body.filters-modal .search-box-container,
+    body.filters-modal .toolbar,
+    body.menu-modal div.primary,
+    body.menu-modal .search-box-container,
+    body.menu-modal .toolbar
+    {
+        filter: blur(3px);
+        -webkit-backdrop-filter: blur(3px);
+    }
+
+    body.filters-modal div.blur-layer,
+    body.menu-modal div.blur-layer
+    {
+        position: absolute;
+        width: 100vw;
+        height: 100vh;
+        background-color: #000000;
+        opacity: 0.6;
+        z-index: 2;
+    }
+    body.filters-modal div.blur-layer
+    {
+        top: 0;
+    }
 }
 
-@media (max-width: 768px)
-{
-.wrapper {
-    margin: 0;
+body.filters-modal div.row > aside.secondary.span3 {
+    display: block;
 }
-.dataset-edit-form .span6 {
-    width: 100%;
+
+
+@media (max-width: 1023px)
+{
+    .js .show-filters.btn {
+        box-sizing: border-box;
+        display: inline-block;
+        background-image: url("/base/images/icon_funnel.svg");
+        background-size: 18px 18px;
+        background-repeat: no-repeat;
+        background-position: 15px center;
+        padding-left: 49px;
+        margin-right: 28px;
+        display: inline-block;
+        height: 40px;
+        background-color: #0089CA;
+        color: white;
+        font-size: 18px;
+        margin-bottom: 12px;
+    }
+
+    .js .module-content > .show-filters.btn {
+        background-image: none;
+        padding-left: 15px;
+    }
+
+    .js .module-content > .show-filters.btn > img {
+        width: 24px;
+        height: auto;
+        margin-right: 6px;
+    }
 }
-}
\ No newline at end of file
diff --git a/ckanext/odsh/public/odsh_header.css b/ckanext/odsh/public/odsh_header.css
index 13406da5d0baef850855331ea4dc2a51513ed0ad..31822582d5b095bb524b579579b44830b182786a 100644
--- a/ckanext/odsh/public/odsh_header.css
+++ b/ckanext/odsh/public/odsh_header.css
@@ -10,6 +10,13 @@
     max-width: 1280px;
 }
 
+@media (max-width: 767px) {
+    .navbar-static-top .container.navigation-container {
+        padding-left: 15px;
+        padding-right: 15px;
+    }
+}
+
 [class*="span"] {
     margin-left: 0px;
 }
@@ -31,9 +38,15 @@
     padding-right: 0;
     position: relative;
     top: 0;
+    left: 18px;
     padding: 1em 0;
 }
 
+/* @media (max-width: 767px){
+    .header-image {
+        display: block;
+    } */
+
 .language-switch {
     float: right;
     background-color: #f2f2f2;
@@ -100,6 +113,13 @@
     background: white;
 }
 
+@media (max-width: 1023px) {
+    .masthead {
+        margin-left: 0;
+        margin-right: 0;
+    }
+}
+
 
 .navigation-container {
     background: #f2f2f2;
@@ -107,8 +127,21 @@
     border-bottom: 15px solid #003064;
 }
 
+@media (max-width: 1023px) {
+    .navigation-container {
+        border-bottom: 10px solid #003064;
+    }
+}
+
+@media (max-width: 767px) {
+    .navigation-container {
+        border-bottom: 8px solid #003064;
+    }
+}
+
 .navigation-row {
     width: 960px;
+    max-width: 100%;
     padding-left: 0px;
     margin-left: auto;
     margin-right: auto;
@@ -128,6 +161,75 @@
     margin: 0px;
 }
 
+.header-menu-mobile {
+    display: none;
+}
+@media (max-width: 767px) {
+    .menu-modal .navbar.masthead .nav > li.header-menu-mobile,
+    .menu-modal .navbar.masthead .nav > li.header-menu-mobile:hover {
+        display: initial;
+        background-color: #003064;
+        border-top-width: 0;
+        position: relative;
+    }
+    .menu-modal .navbar.masthead .navigation ul.nav-pills > li.header-menu-mobile > a {
+        color: white;
+        font-size: 18px;
+    }
+    .menu-modal .navbar.masthead .navigation ul.nav-pills > li.header-menu-mobile > img {
+        display: inline-block;
+        position: absolute;
+        margin-top: -10px;
+        top: 50%;
+        right: 17px;
+    }
+}
+
+@media (max-width: 767px) {
+    .navbar .nav {
+        display: none;
+    }
+
+    .menu-modal .navbar nav {
+        max-width: 250px;
+        background-color: white;
+    }
+
+    .menu-modal .navbar .nav {
+        display: block;
+    }
+
+    .menu-modal .navbar.masthead .navigation {
+        position: absolute;
+        top: 8px;
+        left: 0;
+        z-index: 3;
+    }
+
+    .menu-modal .navbar.masthead .navigation ul.nav-pills > li {
+        box-sizing: border-box;
+        min-width: 100%;
+        padding-left: 21px;
+        margin-left: 0;
+    }
+    
+    .menu-modal .navbar.masthead .navigation ul.nav-pills > li.active {
+        border-top: 2px solid #f2f2f2;
+    }
+
+    .menu-modal .navbar.masthead .navigation .nav-pills > li > a,
+    .menu-modal .navbar.masthead .navigation .nav-pills > li.active > a {
+        color: #003064;
+        font-size: 14px;
+        font-weight: 500;
+    }
+    .menu-modal .navbar.masthead .navigation .nav-pills > li:hover > a {
+        color: #ffffff;
+        font-size: 14px;
+        font-weight: 500;
+    }
+}
+
 .navbar.masthead .navigation .nav-pills,
 .navbar.masthead .navigation  {
     width: 100%;
@@ -139,8 +241,10 @@
     background-color: #003064 !important;
 }
 
-.navbar.masthead .navigation .nav-pills li:not(:first-child) {
-    margin-left: 22px;
+@media (min-width: 768px) {
+    .navbar.masthead .navigation .nav-pills li:not(:first-child) {
+        margin-left: 22px;
+    }
 }
 
 /* Default border to align font vertically to active navigation tab */
@@ -251,34 +355,12 @@
     float: right;
 }
 
-@media (max-width: 767px)
-{
-.navbar.masthead .navigation .nav-pills li.dropdown
-{
-    float: none;
-}
-.nav-pills li a:hover, .nav-pills li:hover {
-    background-color: rgb(242, 242, 242)!important;
-}
-.dropdown-backdrop
-{
-    display: none;
-}
-.navigation-row {
-    width: 100%;
-    padding-left: 0px;
-    margin-left: auto;
-    margin-right: auto;
-}
-}
-
 .navbar.masthead .navigation .nav-pills li.dropdown > .dropdown-toggle
 {
     padding-bottom: 12px;
     padding-top: 12px;
 }
 
-
 .user-icon
 {
     fill:#003064;
@@ -308,19 +390,3 @@
 {
     fill:white;
 }
-
-@media (max-width: 767px)
-{
-.navbar-fixed-top, .navbar-fixed-bottom, .navbar-static-top {
-     margin-left: 0px; 
-     margin-right: 0px; 
-}
-
-.navbar.masthead .nav>li:hover a,
-.navbar.masthead .navigation .nav-pills li.open .user-icon, .navbar.masthead .navigation .nav-pills li a:hover .user-icon,
-.navbar.masthead .navigation .nav-pills li.dropdown.open > a.dropdown-toggle:hover, .navbar .nav li.dropdown.open > .dropdown-toggle 
-{
-    color: #003064;
-    fill: #003064;
-}
-}
\ No newline at end of file
diff --git a/ckanext/odsh/search.py b/ckanext/odsh/search.py
new file mode 100644
index 0000000000000000000000000000000000000000..bc68443ccb0fab2453156e65712d2c293fc9bdd5
--- /dev/null
+++ b/ckanext/odsh/search.py
@@ -0,0 +1,80 @@
+import ckanext.odsh.helpers as odsh_helpers
+
+def before_search(search_params):
+    _update_facet_mincount(search_params)
+    _update_daterange_query(search_params)
+    return search_params
+
+def _update_facet_mincount(search_params):
+    search_params.update({'facet.mincount': 0})
+
+def _update_daterange_query(search_params):
+    start_date, end_date = _get_start_and_end_date(search_params)
+    is_no_range = not start_date and not end_date
+    if is_no_range:
+        return search_params
+    start_date_or_star = start_date or '*'
+    end_date_or_star = end_date or '*'
+    start_query, end_query = _get_start_and_end_query(start_date_or_star, end_date_or_star)
+    is_enclosing_range = start_date and end_date and start_date < end_date
+    if is_enclosing_range:
+        enclosing_query = _get_enclosing_query(start_date_or_star, end_date_or_star)
+    else:
+        enclosing_query = ''
+    open_end_query = _get_open_end_query(end_date_or_star)
+    fq_preset = search_params.get('fq')
+    fq = _combine_query(fq_preset, start_query, end_query, enclosing_query, open_end_query)
+    search_params.update({'fq': fq})
+
+def _get_start_and_end_date(search_params):
+    extras = search_params.get('extras')
+    start_date_local, end_date_local = (
+        extras.get(key)
+        for key in ('ext_startdate', 'ext_enddate')
+    )
+    try:
+        start_date, end_date = (
+            odsh_helpers.extend_search_convert_local_to_utc_timestamp(date)
+            for date in (start_date_local, end_date_local)
+        )
+    except ValueError:
+        start_date = end_date = None
+    return start_date, end_date
+
+def _get_start_and_end_query(start_date, end_date):
+    start_query, end_query = (
+        '+extras_temporal_{start_or_end}:[{start_date} TO {end_date}]'.format(
+            start_or_end=__,
+            start_date=start_date,
+            end_date=end_date
+        )
+        for __ in ('start', 'end')
+    )
+    return start_query, end_query
+
+def _get_open_end_query(end_date):
+    if end_date is '*':
+        open_end_query = '(*:* NOT extras_temporal_end:[* TO *])'
+    else:
+        open_end_query = '((*:* NOT extras_temporal_end:[* TO *]) AND extras_temporal_start:[* TO {end_date}])'.format(
+            end_date=end_date)
+    return open_end_query
+
+def _get_enclosing_query(start_date, end_date):
+    enclosing_query_start = 'extras_temporal_start:[* TO {start_date}]'.format(
+        start_date=start_date)
+    enclosing_query_end = 'extras_temporal_end:[{end_date} TO *]'.format(
+        end_date=end_date)
+    enclosing_query = ' OR ({enclosing_query_start} AND {enclosing_query_end})'.format(
+        enclosing_query_start=enclosing_query_start, enclosing_query_end=enclosing_query_end)
+    return enclosing_query
+
+def _combine_query(fq_preset, start_query, end_query, enclosing_query, open_end_query):
+    combined_query = u'{fq_preset} ({start_query} OR {end_query} {enclosing_query} OR {open_end_query})'.format(
+        fq_preset=fq_preset, 
+        start_query=start_query, 
+        end_query=end_query, 
+        enclosing_query=enclosing_query, 
+        open_end_query=open_end_query
+    )
+    return combined_query
\ No newline at end of file
diff --git a/ckanext/odsh/templates/base.html b/ckanext/odsh/templates/base.html
index debf3e341031fb6cf5bdfd328b4accc3fa23eb20..8191f4ce7851b544041bd209461165c8e8ab0fed 100644
--- a/ckanext/odsh/templates/base.html
+++ b/ckanext/odsh/templates/base.html
@@ -11,10 +11,13 @@
 
 {% block head_extras %}
 {{ super() }}
+{% if h.odsh_use_matomo() %}
 {% set matomo_url = h.odsh_tracking_url()%}
 {% set matomo_id = h.odsh_tracking_id()%}
+{% endif %}
 <meta data-name="type" content="{{h.odsh_is_slave()}}">
 
+{% if h.odsh_use_matomo() %}
 <!-- Matomo -->
 <script type="text/javascript">
   var _paq = _paq || [];
@@ -29,6 +32,7 @@
   })();
 </script>
 <!-- End Matomo Code -->
+{% endif %}
 {% endblock %}
 {% block bodytag %} data-site-root="{{ h.odsh_public_url() }}" data-locale-root="{{ h.odsh_public_url() }}" {% endblock %}
 {% block page %}
diff --git a/ckanext/odsh/templates/footer.html b/ckanext/odsh/templates/footer.html
index 5aad688f3330a8af36d0c7f481684f30f531fb80..03764a7c7b58782fb85faee0af0af365732205df 100644
--- a/ckanext/odsh/templates/footer.html
+++ b/ckanext/odsh/templates/footer.html
@@ -1,4 +1,4 @@
-<div class="footer">
+<footer class="footer">
     <div class="container">
         <div class="footer-content">
             <div class='footer-first-row'>
@@ -8,12 +8,12 @@
             <div class='footer-line'></div>
             <div class="footer-left">
                 <div class="footer-icon">&copy; {{g.site_title}}</div>
-                <div class="footer-right">
-                    <div class='footer-icon'><a href='http://www.schleswig-holstein.de/odpkontakt'>Kontakt</a></div>
-                    <div class='footer-icon'><a href='http://www.schleswig-holstein.de/odpimpressum'>Impressum</a></div>
-                    <div class='footer-icon last'><a href='http://www.schleswig-holstein.de/odpdatenschutz'>Datenschutz</a></div>
-                </div>
+            </div>
+            <div class="footer-right">
+                <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpkontakt'>Kontakt</a></div>
+                <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpimpressum'>Impressum</a></div>
+                <div class='footer-icon last'><a href='http://www.schleswig-holstein.de/tpdatenschutz'>Datenschutz</a></div>
             </div>
         </div>
     </div>
-</div>
\ No newline at end of file
+</footer>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/header.html b/ckanext/odsh/templates/header.html
index 1c06ef6108440d9f462939575fd0cc7c29bbc8df..afc0250f21f7591cf03625c0fe9dd7e305bd033c 100644
--- a/ckanext/odsh/templates/header.html
+++ b/ckanext/odsh/templates/header.html
@@ -1,112 +1,117 @@
+{% resource 'odsh/tpsh_toggle_menu.js' %}
+
 {% block header_wrapper %}
 {% block header_account %}
 <header class="navbar navbar-static-top masthead">
-  {% block header_debug %}
-  {% if g.debug and not g.debug_supress_header %}
-  <div class="debug">Controller : {{ c.controller }}<br />Action : {{ c.action }}</div>
-  {% endif %}
-  {% endblock %}
-  <div class="container">
-    {# The .header-image class hides the main text and uses image replacement for the title #}
-    <div class='row'>
-
-      <div class='span3 span-navigation'>
-        <hgroup class="{{ g.header_class }} pull-left">
+    {% block header_debug %}
+    {% if g.debug and not g.debug_supress_header %}
+    <div class="debug">Controller : {{ c.controller }}<br />Action : {{ c.action }}</div>
+    {% endif %}
+    {% endblock %}
+    <div class="container">
+        {# The .header-image class hides the main text and uses image replacement for the title #}
+        <div class='row topline'>
 
-          {% block header_logo %}
-          <a class="logo" href="{{ h.url_for('home') }}"><img src="{{ h.url_for_static_or_external(g.site_logo) }}" alt="{{ g.site_title }}"
-              title="{{ g.site_title }}" /></a>
-          {% endblock %}
-        </hgroup>
-      </div>
-      <button data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar" type="button">
-        <span class="fa fa-bars"></span>
-      </button>
+            <div class='span3 span-navigation'>
+                <hgroup class="{{ g.header_class }} pull-left">
 
-      <div class='site-title'> {{ g.site_title }} </div>
+                    {% block header_logo %}
+                    <a class="logo" href="{{ h.url_for('home') }}">
+                        <img class="img-logo-large" src="{{ h.url_for_static_or_external(g.site_logo) }}" alt="Logo Schleswig Holstein"
+                            title="{{ g.site_title }}" />
+                        <img class="img-logo-small" src="/base/images/logo-quer.png" alt="Logo Schleswig Holstein"
+                            title="{{ g.site_title }}" />
+                    </a>
+                    {% endblock %}
+                </hgroup>
+            </div>
+            <h1 class='site-title'> {{ g.site_title }} </h1>
+        </div>
+        <div id="menu-button-and-title" data-module="tpsh_toggle_menu">
+            <span class="fa fa-bars"></span>
+            <h1 class='site-title-mobile'> {{ g.site_title }} </h1>
+        </div>
     </div>
-  </div>
 
-  <div class="container navigation-container">
-    <div class='row navigation-row'>
-      <div class="nav-collapse collapse">
-        <nav class="section navigation">
-          <ul class="nav nav-pills">
-            {% block header_site_navigation_tabs %}
-            {{ h.build_nav_main(
-            ('home', _('Start')),
-            ('search', _('Daten')))}}
-            {% if c.userobj %}
-            <li >
-                    <a href="{{ h.url_for('/datarequest/') }}" >{{_('Datarequest')}}</a>
-            </li>
-            {% endif %}
-            {{ h.build_nav_main(
-            ('organizations_index', _('Herausgeber')),
-            ('info_page', _('Infos'))
-            ) }}
-            {% endblock %}
-            {% set clazz='active' if c.action=='login' else ''%}
-            {% if h.check_access('package_create') %}
-            <li class='{{clazz}}'>
-              {% link_for _('Upload'), controller='package', action='new', group=c.group_dict.id, class_='text' %}
-            </li>
-            {% endif %}
-            {% if c.userobj %}
-            <li class='{{clazz}} dropdown navbar-right'>
-              {% set name = c.userobj.fullname if c.userobj.fullname else c.userobj.email%}
-                <a class="dropdown-toggle" data-toggle="dropdown" href="#">
-                  <svg class='user-icon'  viewBox="0 0 54 54">
-                  <circle class='user-icon' cx="27" cy="17" r="7.5"/>
-                  <path class='user-icon' d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z"/>
-                  </svg>
-                 {{name}}</a>
-                <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
-                  <li>
-                  <svg class='user-icon-small'  viewBox="0 0 54 54">
-                  <circle  cx="27" cy="17" r="7.5"/>
-                  <path  d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z"/>
-                  </svg>
-                    <a href="{{ h.url_for('/user/') }}" title="logout">
-                      <span class="text">
-                       Mein Profil einsehen
-                      </span>
-                    </a>
-                  </li>
-                  <li>
-                    <a href="{{ h.url_for('/user/edit') }}" title="logout">
-                    <i class='fa fa-edit'></i>
-                      <span class="text">
-                        Mein Profil bearbeiten
-                      </span>
-                    </a>
-                  </li>
-                  <li>
-                    <a href="{{ h.url_for('/user/_logout') }}" title="logout">
-                    <i class='fa fa-sign-out'></i>
-                      <span class="text">Logout</span>
-                    </a>
-                  </li>
+    <div class="container navigation-container">
+        <div class='row navigation-row'>
+            <nav class="section navigation">
+                <ul class="nav nav-pills">
+                    <li class="header-menu-mobile" data-module="tpsh_toggle_menu">
+                        <a>Menü</a>
+                        <img src="/base/images/icon_close_white.svg" alt="Menü schließen" aria-label="Menü schließen">
+                    </li>
+                    {% block header_site_navigation_tabs %}
+                    {{ 
+                    h.build_nav_main(
+                        ('home', _('Start')),
+                        ('search', _('Datensätze')),
+                        ('organizations_index', _('Herausgeber')),
+                        ('info_page', _('Infos'))
+                    )
+                    }}
+                    {% endblock %}
+                    {% set clazz='active' if c.action=='login' else ''%}
+                    {% if h.check_access('package_create') %}
+                    <li class='{{clazz}}'>
+                        {% link_for _('Upload'), controller='package', action='new', group=c.group_dict.id, class_='text' %}
+                    </li>
+                    {% endif %}
+                    {% if c.userobj %}
+                    <li class='{{clazz}} dropdown navbar-right'>
+                        {% set name = c.userobj.fullname if c.userobj.fullname else c.userobj.email%}
+                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">
+                            <svg class='user-icon' viewBox="0 0 54 54">
+                                <circle class='user-icon' cx="27" cy="17" r="7.5" />
+                                <path class='user-icon'
+                                    d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z" />
+                            </svg>
+                            {{name}}</a>
+                        <ul class="dropdown-menu" role="menu">
+                            <li>
+                                <svg class='user-icon-small' viewBox="0 0 54 54">
+                                    <circle cx="27" cy="17" r="7.5" />
+                                    <path
+                                        d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z" />
+                                </svg>
+                                <a href="{{ h.url_for('/user/') }}" title="logout" role="menuitem">
+                                    <span class="text">
+                                        Mein Profil einsehen
+                                    </span>
+                                </a>
+                            </li>
+                            <li>
+                                <a href="{{ h.url_for('/user/edit') }}" title="logout" role="menuitem">
+                                    <i class='fa fa-edit'></i>
+                                    <span class="text">
+                                        Mein Profil bearbeiten
+                                    </span>
+                                </a>
+                            </li>
+                            <li>
+                                <a href="{{ h.url_for('/user/_logout') }}" title="logout" role="menuitem">
+                                    <i class='fa fa-sign-out'></i>
+                                    <span class="text">Logout</span>
+                                </a>
+                            </li>
+                        </ul>
+                        </a>
+                    </li>
+                    {% else %}
+                    <li class='{{clazz}}'>
+                        <a href="{{ h.url_for('/user/login') }}" title="login">
+                            <span class="text">Login</span>
+                        </a>
+                    </li>
+                    {% endif %}
                 </ul>
-              </a>
-            </li>
-            {% else %}
-            <li class='{{clazz}}'>
-              <a href="{{ h.url_for('/user/login') }}" title="login">
-                <span class="text">Login</span>
-              </a>
-            </li>
-            {% endif %}
-          </ul>
-        </nav>
-        <nav class="section navigation">
-          <ul class="nav nav-pills">
-          </ul>
-        </nav>
-        {% endblock %}
-      </div>
+            </nav>
+            <nav class="section navigation">
+                <ul class="nav nav-pills">
+                </ul>
+            </nav>
+            {% endblock %}
+        </div>
     </div>
-  </div>
-  </div>
 </header>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/ckanext/odsh/templates/macros/form.html b/ckanext/odsh/templates/macros/form.html
index cc01867dab57de4dc4fd41785ab9df68579b6791..862c69eee75b6e20effeb981da4e4287fec103c3 100644
--- a/ckanext/odsh/templates/macros/form.html
+++ b/ckanext/odsh/templates/macros/form.html
@@ -95,6 +95,21 @@ is_required=false) %}
 </div>
 {% endmacro %}
 
+
+{% macro select(name, id='', label='', options='', selected='', error='', classes=[], attrs={'class': 'form-control'}, is_required=false) %}
+{% set classes = (classes|list) %}
+{% do classes.append('control-select') %}
+
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required) %}
+<select id="{{ id or name }}" name="{{ name }}" {{ attributes(attrs) }}>
+  {% for option in options %}
+<option value="{{ option.value }}"{% if option.value == selected %} selected{% endif %}>{{ option.text or option.value }}</option>
+{% endfor %}
+</select>
+{% endcall %}
+{% endmacro %}
+
 {#
 Creates all the markup required for an select element. Handles matching labels to
 inputs and error messages.
@@ -107,401 +122,461 @@ name - The name of the form parameter.
 id - The id to use on the input and label. Convention is to prefix with 'field-'.
 label - The human readable label.
 options - A list/tuple of fields to be used as <options>.
-    selected - The value of the selected <option>.
-        error - A list of error strings for the field or just true to highlight the field.
-        classes - An array of classes to apply to the control-group.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Examples:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.select('year', label=_('Year'), options=[{'name':2010, 'value': 2010},{'name': 2011, 'value': 2011}],
-        selected=2011, error=errors.year) }}
-
-        #}
-        {% macro select(name, id='', label='', options='', selected='', error='', classes=[], attrs={},
-        is_required=false) %}
-        {% set classes = (classes|list) %}
-        {% do classes.append('control-select') %}
-
-        {%- set extra_html = caller() if caller -%}
-        {% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required)
-        %}
+selected - The value of the selected <option>.
+error - A list of error strings for the field or just true to highlight the field.
+classes - An array of classes to apply to the control-group.
+is_required - Boolean of whether this input is requred for the form to validate
+
+Examples:
+
+{% import 'macros/form.html' as form %}
+{{ form.select('year', label=_('Year'), options=[{'name':2010, 'value': 2010},{'name': 2011, 'value': 2011}],
+selected=2011, error=errors.year) }}
+
+#}
+{% macro tpsh_select(name, id='', label='', options='', selected='', error='', classes=[], attrs={},
+is_required=false) %}
+{% set classes = (classes|list) %}
+{% do classes.append('control-select') %}
+
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required)
+%}
+<div class="row-fluid">
+    <div class="span6">
         <select id="{{ id or name }}" name="{{ name }}" {{ attributes(attrs) }}>
             {% for option in options %}
-            <option value="{{ option.value }}" {% if option.value==selected %} selected{% endif %}>{{ option.text or
+            <option value="{{ option.key }}" {% if option.key==selected %} selected{% endif %}>{{ option.text or
                 option.value }}</option>
             {% endfor %}
         </select>
-        {% endcall %}
-        {% endmacro %}
-
-        {#
-        Creates all the markup required for a Markdown textarea element. Handles
-        matching labels to inputs, selected item and error messages.
-
-        name - The name of the form parameter.
-        id - The id to use on the input and label. Convention is to prefix with 'field-'.
-        label - The human readable label.
-        value - The value of the input.
-        placeholder - Some placeholder text.
-        error - A list of error strings for the field or just true to highlight the field.
-        classes - An array of classes to apply to the control-group.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Examples:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.markdown('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}
-
-        #}
-        {% macro markdown(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={},
-        is_required=false, cols=20, rows=5) %}
-        {% set classes = (classes|list) %}
-        {% do classes.append('control-full') %}
-        {% set markdown_tooltip = "
-        <pre><p>__Bold text__ or _italic text_</p><p># title<br>## secondary title<br>### etc</p><p>* list<br>* of<br>* items</p><p>http://auto.link.ed/</p></pre>
-        <p><b><a href='http://daringfireball.net/projects/markdown/syntax' target='_blank'>Full markdown syntax</a></b></p>
-        <p class='muted'><b>Please note:</b> HTML tags are stripped out for security reasons</p>" %}
-
-        {%- set extra_html = caller() if caller -%}
-        {% call input_block(id or name, label or name, error, classes, control_classes=["editor"],
-        extra_html=extra_html, is_required=is_required) %}
-        <div class="row-fluid">
-            <div class="span6">
-                <textarea id="{{ id or name }}" name="{{ name }}" cols="{{cols}}" rows="{{rows}}" placeholder="{{ placeholder }}"
-                    {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
-            </div>
-            <div class="span6 inline-error">
-                {{error}}
-            </div>
-        </div>
-        {% endcall %}
-        {% endmacro %}
-
-        {#
-        Creates all the markup required for a plain textarea element. Handles
-        matching labels to inputs, selected item and error messages.
-
-        name - The name of the form parameter.
-        id - The id to use on the input and label. Convention is to prefix with 'field-'.
-        label - The human readable label.
-        value - The value of the input.
-        placeholder - Some placeholder text.
-        error - A list of error strings for the field or just true to highlight the field.
-        classes - An array of classes to apply to the control-group.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Examples:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.textarea('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}
-
-        #}
-        {% macro textarea(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={},
-        is_required=false, rows=5, cols=20) %}
-        {% set classes = (classes|list) %}
-        {% do classes.append('control-full') %}
-
-        {%- set extra_html = caller() if caller -%}
-        {% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required)
-        %}
-        <textarea id="{{ id or name }}" name="{{ name }}" cols="{{ cols }}" rows="{{ rows }}" placeholder="{{ placeholder }}"
-            {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
-        {% endcall %}
-        {% endmacro %}
-
-        {#
-        Creates all the markup required for an input element with a prefixed segment.
-        These are useful for showing url slugs and other fields where the input
-        information forms only part of the saved data.
-
-        name - The name of the form parameter.
-        id - The id to use on the input and label. Convention is to prefix with 'field-'.
-        label - The human readable label.
-        prepend - The text that will be prepended before the input.
-        value - The value of the input.
-        which will use the name key as the value.
-        placeholder - Some placeholder text.
-        error - A list of error strings for the field or just true to highlight the field.
-        classes - An array of classes to apply to the control-group.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Examples:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.prepend('slug', id='field-slug', prepend='/dataset/', label=_('Slug'), value=data.slug,
-        error=errors.slug) }}
-
-        #}
-        {% macro prepend(name, id='', label='', prepend='', value='', placeholder='', type='text', error="",
-        classes=[], attrs={}, is_required=false) %}
-        {# We manually append the error here as it needs to be inside the .input-prepend block #}
-        {% set classes = (classes|list) %}
-        {% do classes.append('error') if error %}
-        {%- set extra_html = caller() if caller -%}
-        {% call input_block(id or name, label or name, error='', classes=classes, extra_html=extra_html,
-        is_required=is_required) %}
-        <div class="input-prepend">
-            {% if prepend %}<span class="add-on">{{ prepend }}</span>{%- endif -%}
-            <input id="{{ id or name }}" type="{{ type }}" name="{{ name }}" value="{{ value | empty_and_escape }}"
-                placeholder="{{ placeholder }}" {{ attributes(attrs) }} />
-        </div>
-        {% endcall %}
-        {% endmacro %}
-
-        {#
-        Creates all the markup required for an custom key/value input. These are usually
-        used to let the user provide custom meta data. Each "field" has three inputs
-        one for the key, one for the value and a checkbox to remove it. So the arguments
-        for this macro are nearly all tuples containing values for the
-        (key, value, delete) fields respectively.
-
-        name - A tuple of names for the three fields.
-        id - An id string to be used for each input.
-        label - The human readable label for the main label.
-        values - A tuple of values for the (key, value, delete) fields. If delete
-        is truthy the checkbox will be checked.
-        placeholder - A tuple of placeholder text for the (key, value) fields.
-        error - A list of error strings for the field or just true to highlight the field.
-        classes - An array of classes to apply to the control-group.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Examples:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.custom(
-        names=('custom_key', 'custom_value', 'custom_deleted'),
-        id='field-custom',
-        label=_('Custom Field'),
-        values=(extra.key, extra.value, extra.deleted),
-        error=''
-        ) }}
-        #}
-        {% macro custom(names=(), id="", label="", values=(), placeholders=(), error="", classes=[], attrs={},
-        is_required=false, key_values=()) %}
-        {%- set classes = (classes|list) -%}
-        {%- set label_id = (id or names[0]) ~ "-key" -%}
-        {%- set extra_html = caller() if caller -%}
-        {%- do classes.append('control-custom') -%}
-
-        {% call input_block(label_id, label or name, error, classes, control_classes=["editor"], extra_html=extra_html,
-        is_required=is_required) %}
-        <div class="input-prepend" {{ attributes(attrs) }}>
-            <label for="{{ label_id }}" class="add-on">Key</label><input id="{{ id or names[0] }}-key" type="text" name="{{ names[0] }}"
-                value="{{ values[0] | empty_and_escape }}" placeholder="{{ placeholders[0] }}" />
-            <label for="{{ id or names[1] }}-value" class="add-on">Value</label><input id="{{ id or names[1] }}-value"
-                type="text" name="{{ names[1] }}" value="{{ values[1] | empty_and_escape }}" placeholder="{{ placeholders[1] }}" />
-            {% if values[0] or values[1] or error %}
-            <label class="checkbox" for="{{ id or names[2] }}-remove">
-                <input type="checkbox" id="{{ id or names[2] }}-remove" name="{{ names[2] }}" {% if values[2] %}
-                    checked{% endif %} /> <span>{{ _('Remove') }}</span>
-            </label>
-            {% endif %}
-        </div>
-        {% endcall %}
-        {% endmacro %}
-
-        {#
-        A generic input_block for providing the default markup for CKAN form elements.
-        It is expected to be called using a {% call %} block, the contents of which
-        will be inserted into the .controls element.
-
-        for - The id for the input that the label should match.
-        label - A human readable label.
-        error - A list of error strings for the field or just true.
-        classes - An array of custom classes for the outer element.
-        control_classes - An array of custom classes for the .control wrapper.
-        extra_html - An html string to be inserted after the errors eg. info text.
-        is_required - Boolean of whether this input is requred for the form to validate
-
-        Example:
-
-        {% import 'macros/form.html' as form %}
-        {% call form.input_block("field", "My Field") %}
-        <input id="field" type="text" name="{{ name }}" value="{{ value | empty_and_escape }}" />
-        {% endcall %}
-
-        #}
-        {% macro input_block(for, label, error="", classes=[], control_classes=[], extra_html="", is_required=false)
-        %}
-        <div class="control-group{{ " error" if error }}{{ " " ~ classes | join(' ') }}">
-            {%if label%}
-            <label class="control-label" for="{{ for }}">{{ label or _('Custom') }}: {% if is_required %}<span title="{{ _("This field is required") }}"
-                    class="control-required">*</span> {% endif %}</label>
-            {%endif%}
-            <div class="controls{{ " " ~ control_classes | join(' ') }}">
-                {{ caller() }}
-                {{ extra_html }}
-            </div>
-        </div>
-        {% endmacro %}
-
-        {#
-        Builds a list of errors for the current form.
-
-        errors - A dict of field/message pairs.
-        type - The alert-* class that should be applied (default: "error")
-        classes - A list of classes to apply to the wrapper (default: [])
-
-        Example:
-
-        {% import 'macros/form.html' as form %}
-        {{ form.errors(error_summary, type="warning") }}
-
-        #}
-        {% macro errors(errors={}, type="error", classes=[]) %}
-        {% if errors %}
-        <div class="error-explanation alert alert-{{ type }}{{ " " ~ classes | join(' ') }}">
-            <ul>
-                {% for key, error in errors.items() %}
-                {%if key %}
-                <li data-field-label="{{ key }}">
-                    {{_(key+': '+error)}}
-                </li>
-                {%else%}
-                <li data-field-label="{{ key }}"> {{error}} </li>
-                {%endif%}
-                {% endfor %}
-            </ul>
-        </div>
+    </div>
+    <div class="span6 inline-error">
+        {% if error is iterable and error is not string %}
+        {{error|first}}
+        {% elif error is string %}
+        {{error}}
         {% endif %}
-        {% endmacro %}
+    </div>
+</div>
+{% endcall %}
+{% endmacro %}
 
-        {#
-        Renders an info box with a description. This will usually be used with in a
-        call block when creating an input element.
 
-        text - The text to include in the box.
-        inline - If true displays the info box inline with the input.
-        classes - A list of classes to add to the info box.
+{# 
+Creates a select with an input field for autocomplete #}
+{% macro select_autocomplete(name, id='', label='', options='', selected='', error='', classes=[],  attrs={},
+    is_required=false) %}
+{% set classes = (classes|list) %}
+{% do classes.append('control-select') %}
 
-        Example
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required)
+%}
 
-        {% import 'macros/form.html' as form %}
-        {% call form.input('name') %}
-        {{ form.info(_('My useful help text')) }}
-        {% endcall %}
+<div class="row-fluid">
+    <div class="span6">
+        <select id="{{ id or name }}" name="{{ name }}" {{ attributes(attrs) }} data-module="autocomplete">
+            {% for option in options %}
+                <option value="{{ option.key }}" {% if option.key==selected %} selected {% endif %}>{{ option.text or
+                option.value }} </option>
+            {% endfor %}
+        </select>
+    </div>
+    <div class="span6 inline-error">
+        {% if error is iterable and error is not string %}
+        {{error|first}}
+        {% elif error is string %}
+        {{error}}
+        {% endif %}
+    </div>
+</div>
+{% endcall %}
+{% endmacro %}
 
-        #}
-        {% macro info(text='', inline=false, classes=[]) %}
-        {%- if text -%}
-        <div class="info-block{{ ' info-inline' if inline }}{{ " " ~ classes | join(' ') }}">
-            <i class="fa fa-info-circle"></i>
-            {{ text }}
-        </div>
-        {%- endif -%}
-        {% endmacro %}
 
-        {#
-        Builds a single hidden input.
+{#
+Creates all the markup required for a Markdown textarea element. Handles
+matching labels to inputs, selected item and error messages.
 
-        name - name of the hidden input
-        value - value of the hidden input
+name - The name of the form parameter.
+id - The id to use on the input and label. Convention is to prefix with 'field-'.
+label - The human readable label.
+value - The value of the input.
+placeholder - Some placeholder text.
+error - A list of error strings for the field or just true to highlight the field.
+classes - An array of classes to apply to the control-group.
+is_required - Boolean of whether this input is requred for the form to validate
 
-        Example
-        {% import 'macros/form.html' as form %}
-        {{ form.hidden('name', 'value') }}
+Examples:
 
-        #}
-        {% macro hidden(name, value) %}
-        <input type="hidden" name="{{ name }}" value="{{ value }}" />
-        {% endmacro %}
+{% import 'macros/form.html' as form %}
+{{ form.markdown('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}
 
-        {#
-        Contructs hidden inputs for each name-value pair.
+#}
+{% macro markdown(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={},
+is_required=false, cols=20, rows=5) %}
+{% set classes = (classes|list) %}
+{% do classes.append('control-full') %}
+{% set markdown_tooltip = "
+<pre><p>__Bold text__ or _italic text_</p><p># title<br>## secondary title<br>### etc</p><p>* list<br>* of<br>* items</p><p>http://auto.link.ed/</p></pre>
+<p><b><a href='http://daringfireball.net/projects/markdown/syntax' target='_blank'>Full markdown syntax</a></b></p>
+<p class='muted'><b>Please note:</b> HTML tags are stripped out for security reasons</p>" %}
 
-        fields - [('name1', 'value1'), ('name2', 'value2'), ...]
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error, classes, control_classes=["editor"],
+extra_html=extra_html, is_required=is_required) %}
+<div class="row-fluid">
+    <div class="span6">
+        <textarea id="{{ id or name }}" name="{{ name }}" cols="{{cols}}" rows="{{rows}}" placeholder="{{ placeholder }}"
+            {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
+    </div>
+    <div class="span6 inline-error">
+        {{error}}
+    </div>
+</div>
+{% endcall %}
+{% endmacro %}
 
-        Two parameter for excluding several names or name-value pairs.
+{#
+Creates all the markup required for a plain textarea element. Handles
+matching labels to inputs, selected item and error messages.
 
-        except_names - list of names to be excluded
-        except - list of name-value pairs to be excluded
+name - The name of the form parameter.
+id - The id to use on the input and label. Convention is to prefix with 'field-'.
+label - The human readable label.
+value - The value of the input.
+placeholder - Some placeholder text.
+error - A list of error strings for the field or just true to highlight the field.
+classes - An array of classes to apply to the control-group.
+is_required - Boolean of whether this input is requred for the form to validate
 
+Examples:
 
-        Example:
-        {% import 'macros/form.html' as form %}
-        {% form.hidden_from_list(fields=c.fields, except=[('topic', 'xyz')]) %}
-        {% form.hidden_from_list(fields=c.fields, except_names=['time_min', 'time_max']) %}
-        #}
-        {% macro hidden_from_list(fields, except_names=None, except=None) %}
-        {% set except_names = except_names or [] %}
-        {% set except = except or [] %}
+{% import 'macros/form.html' as form %}
+{{ form.textarea('desc', id='field-description', label=_('Description'), value=data.desc, error=errors.desc) }}
 
-        {% for name, value in fields %}
-        {% if name and value and name not in except_names and (name, value) not in except %}
-        {{ hidden(name, value) }}
-        {% endif %}
+#}
+{% macro textarea(name, id='', label='', value='', placeholder='', error="", classes=[], attrs={},
+is_required=false, rows=5, cols=20) %}
+{% set classes = (classes|list) %}
+{% do classes.append('control-full') %}
+
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error, classes, extra_html=extra_html, is_required=is_required)
+%}
+<textarea id="{{ id or name }}" name="{{ name }}" cols="{{ cols }}" rows="{{ rows }}" placeholder="{{ placeholder }}"
+    {{ attributes(attrs) }}>{{ value | empty_and_escape }}</textarea>
+{% endcall %}
+{% endmacro %}
+
+{#
+Creates all the markup required for an input element with a prefixed segment.
+These are useful for showing url slugs and other fields where the input
+information forms only part of the saved data.
+
+name - The name of the form parameter.
+id - The id to use on the input and label. Convention is to prefix with 'field-'.
+label - The human readable label.
+prepend - The text that will be prepended before the input.
+value - The value of the input.
+which will use the name key as the value.
+placeholder - Some placeholder text.
+error - A list of error strings for the field or just true to highlight the field.
+classes - An array of classes to apply to the control-group.
+is_required - Boolean of whether this input is requred for the form to validate
+
+Examples:
+
+{% import 'macros/form.html' as form %}
+{{ form.prepend('slug', id='field-slug', prepend='/dataset/', label=_('Slug'), value=data.slug,
+error=errors.slug) }}
+
+#}
+{% macro prepend(name, id='', label='', prepend='', value='', placeholder='', type='text', error="",
+classes=[], attrs={}, is_required=false) %}
+{# We manually append the error here as it needs to be inside the .input-prepend block #}
+{% set classes = (classes|list) %}
+{% do classes.append('error') if error %}
+{%- set extra_html = caller() if caller -%}
+{% call input_block(id or name, label or name, error='', classes=classes, extra_html=extra_html,
+is_required=is_required) %}
+<div class="input-prepend">
+    {% if prepend %}<span class="add-on">{{ prepend }}</span>{%- endif -%}
+    <input id="{{ id or name }}" type="{{ type }}" name="{{ name }}" value="{{ value | empty_and_escape }}"
+        placeholder="{{ placeholder }}" {{ attributes(attrs) }} />
+</div>
+{% endcall %}
+{% endmacro %}
+
+{#
+Creates all the markup required for an custom key/value input. These are usually
+used to let the user provide custom meta data. Each "field" has three inputs
+one for the key, one for the value and a checkbox to remove it. So the arguments
+for this macro are nearly all tuples containing values for the
+(key, value, delete) fields respectively.
+
+name - A tuple of names for the three fields.
+id - An id string to be used for each input.
+label - The human readable label for the main label.
+values - A tuple of values for the (key, value, delete) fields. If delete
+is truthy the checkbox will be checked.
+placeholder - A tuple of placeholder text for the (key, value) fields.
+error - A list of error strings for the field or just true to highlight the field.
+classes - An array of classes to apply to the control-group.
+is_required - Boolean of whether this input is requred for the form to validate
+
+Examples:
+
+{% import 'macros/form.html' as form %}
+{{ form.custom(
+names=('custom_key', 'custom_value', 'custom_deleted'),
+id='field-custom',
+label=_('Custom Field'),
+values=(extra.key, extra.value, extra.deleted),
+error=''
+) }}
+#}
+{% macro custom(names=(), id="", label="", values=(), placeholders=(), error="", classes=[], attrs={},
+is_required=false, key_values=()) %}
+{%- set classes = (classes|list) -%}
+{%- set label_id = (id or names[0]) ~ "-key" -%}
+{%- set extra_html = caller() if caller -%}
+{%- do classes.append('control-custom') -%}
+
+{% call input_block(label_id, label or name, error, classes, control_classes=["editor"], extra_html=extra_html,
+is_required=is_required) %}
+<div class="input-prepend" {{ attributes(attrs) }}>
+    <label for="{{ label_id }}" class="add-on">Key</label><input id="{{ id or names[0] }}-key" type="text" name="{{ names[0] }}"
+        value="{{ values[0] | empty_and_escape }}" placeholder="{{ placeholders[0] }}" />
+    <label for="{{ id or names[1] }}-value" class="add-on">Value</label><input id="{{ id or names[1] }}-value"
+        type="text" name="{{ names[1] }}" value="{{ values[1] | empty_and_escape }}" placeholder="{{ placeholders[1] }}" />
+    {% if values[0] or values[1] or error %}
+    <label class="checkbox" for="{{ id or names[2] }}-remove">
+        <input type="checkbox" id="{{ id or names[2] }}-remove" name="{{ names[2] }}" {% if values[2] %}
+            checked{% endif %} /> <span>{{ _('Remove') }}</span>
+    </label>
+    {% endif %}
+</div>
+{% endcall %}
+{% endmacro %}
+
+
+
+{% macro input_address(field, label, value='', index='', placeholder='', type='text', attrs={}) %}
+{%- set _type = 'text' if type=='date' and not value else type -%}
+{%- set onFocus = 'onfocus=(this.type=\'date\')' if type=='date' and not value else '' -%}
+<div class="row-fluid">
+    <div class="span6">
+    <label class="address-label"> {{ label }} </label>
+    <input id="field-{{field}}-key" type="hidden" name="extras__{{index}}__key" value="{{field}}"  />
+    <input id="field-{{field}}-value" type="{{_type}}" name="extras__{{index}}__value" value="{{value | empty_and_escape }}" placeholder="{{ placeholder }}" {{ onFocus }} {{ attributes(attrs) }}/>
+</div>
+</div>
+{% endmacro %}
+
+
+
+{#
+A generic input_block for providing the default markup for CKAN form elements.
+It is expected to be called using a {% call %} block, the contents of which
+will be inserted into the .controls element.
+
+for - The id for the input that the label should match.
+label - A human readable label.
+error - A list of error strings for the field or just true.
+classes - An array of custom classes for the outer element.
+control_classes - An array of custom classes for the .control wrapper.
+extra_html - An html string to be inserted after the errors eg. info text.
+is_required - Boolean of whether this input is requred for the form to validate
+
+Example:
+
+{% import 'macros/form.html' as form %}
+{% call form.input_block("field", "My Field") %}
+<input id="field" type="text" name="{{ name }}" value="{{ value | empty_and_escape }}" />
+{% endcall %}
+
+#}
+{% macro input_block(for, label, error="", classes=[], control_classes=[], extra_html="", is_required=false)
+%}
+<div class="control-group{{ " error" if error }}{{ " " ~ classes | join(' ') }}">
+    {%if label%}
+    <label class="control-label" for="{{ for }}">{{ label or _('Custom') }}: {% if is_required %}<span title="{{ _("This field is required") }}"
+            class="control-required">*</span> {% endif %}</label>
+    {%endif%}
+    <div class="controls{{ " " ~ control_classes | join(' ') }}">
+        {{ caller() }}
+        {{ extra_html }}
+    </div>
+</div>
+{% endmacro %}
+
+{#
+Builds a list of errors for the current form.
+
+errors - A dict of field/message pairs.
+type - The alert-* class that should be applied (default: "error")
+classes - A list of classes to apply to the wrapper (default: [])
+
+Example:
+
+{% import 'macros/form.html' as form %}
+{{ form.errors(error_summary, type="warning") }}
+
+#}
+{% macro errors(errors={}, type="error", classes=[]) %}
+{% if errors %}
+<div class="error-explanation alert alert-{{ type }}{{ " " ~ classes | join(' ') }}">
+    <ul>
+        {% for key, error in errors.items() %}
+        {%if key %}
+        <li data-field-label="{{ key }}">
+            {{_(key+': '+error)}}
+        </li>
+        {%else%}
+        <li data-field-label="{{ key }}"> {{error}} </li>
+        {%endif%}
         {% endfor %}
-        {% endmacro %}
-
-        {#
-        Builds a space seperated list of html attributes from a dict of key/value pairs.
-        Generally only used internally by macros.
-
-        attrs - A dict of attribute/value pairs
-
-        Example
-
-        {% import 'macros/form.html' as form %}
-        {{ form.attributes({}) }}
-
-        #}
-        {%- macro attributes(attrs={}) -%}
-        {%- for key, value in attrs.items() -%}
-        {{ " " }}{{ key }}{% if value != "" %}="{{ value }}"{% endif %}
-        {%- endfor -%}
-        {%- endmacro -%}
-
-        {#
-        Outputs the "* Required field" message for the bottom of formss
-
-        Example
-        {% import 'macros/form.html' as form %}
-        {{ form.required_message() }}
-
-        #}
-        {% macro required_message() %}
-        <p class="control-required-message">
-            <span class="control-required">*</span> {{ _("Required field") }}
-        </p>
-        {% endmacro %}
-
-        {#
-        Builds a file upload for input
-
-        Example
-        {% import 'macros/form.html' as form %}
-        {{ form.image_upload(data, errors, is_upload_enabled=true) }}
-
-        #}
-        {% macro image_upload(data, errors, field_url='image_url', field_upload='image_upload',
-        field_clear='clear_upload',
-        is_url=false, is_upload=false, is_upload_enabled=false, placeholder=false,
-        url_label='', upload_label='', field_name='image_url') %}
-        {% set placeholder = placeholder if placeholder else _('http://example.com/my-image.jpg') %}
-        {% set url_label = url_label or _('Image URL') %}
-        {% set upload_label = upload_label or _('Image') %}
-
-        {% if is_upload_enabled %}
-        <div class="image-upload" data-module="odsh_image-upload" data-module-is_url="{{ 'true' if is_url else 'false' }}"
-            data-module-is_upload="{{ 'true' if is_upload else 'false' }}" data-module-field_url="{{ field_url }}"
-            data-module-field_upload="{{ field_upload }}" data-module-field_clear="{{ field_clear }}"
-            data-module-upload_label="{{ upload_label }}" data-module-field_name="{{ field_name }}">
-            {% endif %}
-
-            {{ input(field_url, label=url_label, id='field-image-url', placeholder=placeholder,
-            value=data.get(field_url), error='', classes=['control-full']) }}
-
-            {% if is_upload_enabled %}
-            {{ input(field_upload, label=upload_label, id='field-image-upload', type='file', placeholder='', value='',
-            error=errors, classes=['control-full'], is_required=true) }}
-            {% if is_upload %}
-            {{ checkbox(field_clear, label=_('Clear Upload'), id='field-clear-upload', value='true', error='',
-            classes=['control-full']) }}
-            {% endif %}
-            {% endif %}
-
-            {% if is_upload_enabled %}</div>{% endif %}
-
-        {% endmacro %}
+    </ul>
+</div>
+{% endif %}
+{% endmacro %}
+
+{#
+Renders an info box with a description. This will usually be used with in a
+call block when creating an input element.
+
+text - The text to include in the box.
+inline - If true displays the info box inline with the input.
+classes - A list of classes to add to the info box.
+
+Example
+
+{% import 'macros/form.html' as form %}
+{% call form.input('name') %}
+{{ form.info(_('My useful help text')) }}
+{% endcall %}
+
+#}
+{% macro info(text='', inline=false, classes=[]) %}
+{%- if text -%}
+<div class="info-block{{ ' info-inline' if inline }}{{ " " ~ classes | join(' ') }}">
+    <i class="fa fa-info-circle"></i>
+    {{ text }}
+</div>
+{%- endif -%}
+{% endmacro %}
+
+{#
+Builds a single hidden input.
+
+name - name of the hidden input
+value - value of the hidden input
+
+Example
+{% import 'macros/form.html' as form %}
+{{ form.hidden('name', 'value') }}
+
+#}
+{% macro hidden(name, value) %}
+<input type="hidden" name="{{ name }}" value="{{ value }}" />
+{% endmacro %}
+
+{#
+Contructs hidden inputs for each name-value pair.
+
+fields - [('name1', 'value1'), ('name2', 'value2'), ...]
+
+Two parameter for excluding several names or name-value pairs.
+
+except_names - list of names to be excluded
+except - list of name-value pairs to be excluded
+
+
+Example:
+{% import 'macros/form.html' as form %}
+{% form.hidden_from_list(fields=c.fields, except=[('topic', 'xyz')]) %}
+{% form.hidden_from_list(fields=c.fields, except_names=['time_min', 'time_max']) %}
+#}
+{% macro hidden_from_list(fields, except_names=None, except=None) %}
+{% set except_names = except_names or [] %}
+{% set except = except or [] %}
+
+{% for name, value in fields %}
+{% if name and value and name not in except_names and (name, value) not in except %}
+{{ hidden(name, value) }}
+{% endif %}
+{% endfor %}
+{% endmacro %}
+
+{#
+Builds a space seperated list of html attributes from a dict of key/value pairs.
+Generally only used internally by macros.
+
+attrs - A dict of attribute/value pairs
+
+Example
+
+{% import 'macros/form.html' as form %}
+{{ form.attributes({}) }}
+
+#}
+{%- macro attributes(attrs={}) -%}
+{%- for key, value in attrs.items() -%}
+{{ " " }}{{ key }}{% if value != "" %}="{{ value }}"{% endif %}
+{%- endfor -%}
+{%- endmacro -%}
+
+{#
+Outputs the "* Required field" message for the bottom of formss
+
+Example
+{% import 'macros/form.html' as form %}
+{{ form.required_message() }}
+
+#}
+{% macro required_message() %}
+<p class="control-required-message">
+    <span class="control-required">*</span> {{ _("Required field") }}
+</p>
+{% endmacro %}
+
+{#
+Builds a file upload for input
+
+Example
+{% import 'macros/form.html' as form %}
+{{ form.image_upload(data, errors, is_upload_enabled=true) }}
+
+#}
+{% macro image_upload(data, errors, field_url='image_url', field_upload='image_upload',
+field_clear='clear_upload',
+is_url=false, is_upload=false, is_upload_enabled=false, placeholder=false,
+url_label='', upload_label='', field_name='image_url') %}
+{% set placeholder = placeholder if placeholder else _('http://example.com/my-image.jpg') %}
+{% set url_label = url_label or _('Image URL') %}
+{% set upload_label = upload_label or _('Image') %}
+
+{% if is_upload_enabled %}
+<div class="image-upload" data-module="odsh_image-upload" data-module-is_url="{{ 'true' if is_url else 'false' }}"
+    data-module-is_upload="{{ 'true' if is_upload else 'false' }}" data-module-field_url="{{ field_url }}"
+    data-module-field_upload="{{ field_upload }}" data-module-field_clear="{{ field_clear }}"
+    data-module-upload_label="{{ upload_label }}" data-module-field_name="{{ field_name }}">
+    {% endif %}
+
+    {{ input(field_url, label=url_label, id='field-image-url', placeholder=placeholder,
+    value=data.get(field_url), error='', classes=['control-full']) }}
+
+    {% if is_upload_enabled %}
+    {{ input(field_upload, label=upload_label, id='field-image-upload', type='file', placeholder='', value='',
+    error=errors, classes=['control-full'], is_required=true) }}
+    {% if is_upload %}
+    {{ checkbox(field_clear, label=_('Clear Upload'), id='field-clear-upload', value='true', error='',
+    classes=['control-full']) }}
+    {% endif %}
+    {% endif %}
+
+    {% if is_upload_enabled %}</div>{% endif %}
+
+{% endmacro %}
diff --git a/ckanext/odsh/templates/organization/snippets/organization_form.html b/ckanext/odsh/templates/organization/snippets/organization_form.html
index 4028d04852a5a92661fad71deaa3ed069504c2fd..364433fb5a1841e363507669c15fecdaf52598dc 100644
--- a/ckanext/odsh/templates/organization/snippets/organization_form.html
+++ b/ckanext/odsh/templates/organization/snippets/organization_form.html
@@ -25,32 +25,23 @@
     {{ form.image_upload(data, errors, is_upload_enabled=h.uploads_enabled(), is_url=is_url, is_upload=is_upload) }}
 
   {% endblock %}
-
-  {% block custom_fields %}
-    {% for extra in data.extras %}
-      {% set prefix = 'extras__%d__' % loop.index0 %}
-      {{ form.custom(
-        names=(prefix ~ 'key', prefix ~ 'value', prefix ~ 'deleted'),
-        id='field-extras-%d' % loop.index,
-        label=_('Custom Field'),
-        values=(extra.key, extra.value, extra.deleted),
-        error=errors[prefix ~ 'key'] or errors[prefix ~ 'value']
-      ) }}
-    {% endfor %}
-
-    {# Add a max if 3 empty columns #}
-    {% for extra in range(data.extras|count, 3) %}
-      {% set index = (loop.index0 + data.extras|count) %}
-      {% set prefix = 'extras__%d__' % index %}
-      {{ form.custom(
-        names=(prefix ~ 'key', prefix ~ 'value', prefix ~ 'deleted'),
-        id='field-extras-%d' % index,
-        label=_('Custom Field'),
-        values=(extra.key, extra.value, extra.deleted),
-        error=errors[prefix ~ 'key'] or errors[prefix ~ 'value']
-      ) }}
-    {% endfor %}
-  {% endblock %}
+  
+  
+
+ 
+  {% set extras = h.tpsh_get_address_org(data) %}
+
+  {{ form.input_address('person','Ansprechpartner', value= extras.person , index=0, placeholder='', type='text', attrs={}) }}
+ 
+  {{ form.input_address('street','Straße', value= extras.street, index=1, placeholder='', type='text', attrs={}) }}
+  
+  {{ form.input_address('location','Stadt', value=extras.location, index=2, placeholder='', type='text', attrs={}) }}
+  
+  {{ form.input_address('telephone','Tel.-Nr.:', value=extras.telephone, index=3, placeholder='', type='text', attrs={}) }}
+
+  {{ form.input_address('mail','e-mail', value=extras.mail, index=4, placeholder='', type='text', attrs={}) }}
+ 
+  {{ form.input_address('web','Website', value=extras.web, index=5, placeholder='', type='text', attrs={}) }}
 
   {{ form.required_message() }}
 
diff --git a/ckanext/odsh/templates/package/read.html b/ckanext/odsh/templates/package/read.html
index 097f993db901aef9d5a1aaac8dd66a5a240c4d83..068b60870df00513f3c63b30f848ad3724c0b7f6 100644
--- a/ckanext/odsh/templates/package/read.html
+++ b/ckanext/odsh/templates/package/read.html
@@ -1,8 +1,10 @@
 {% extends "package/read_base.html" %}
 
 {% set pkg = c.pkg_dict %}
-
-
+{% set collection_title = h.collection_get_title(pkg) %}
+{% set successor_url = h.collection_get_successor(pkg) %}
+{% set predecessor_url = h.collection_get_predecessor(pkg) %}
+{% set latest_collection_member = h.collection_get_latest_member(pkg) %}
 {% set stars = h.odsh_openness_score_dataset_html(pkg) %}
 
 {% block breadcrumb_content %}
@@ -25,7 +27,7 @@
 {% block primary_content_inner %}
 {{ super() }}
 {% block package_description %}
-<div class="odsh-dataset-heading row-fluid">
+<div class="odsh-dataset-heading">
   <h2>
     {% block page_heading %}
     {{ h.dataset_display_name(pkg) }}
@@ -36,7 +38,7 @@
     [{{ _('Deleted') }}]
     {% endif %}
     {% endblock %}
-    <div class="pull-right">
+    <div class="odsh-dataset-edit-button">
       {% if h.check_access('package_update', {'id':pkg.id }) %}
       <div>
         {% link_for _('Manage Dataset'), controller='package', action='edit', id=pkg.name, class_='btn btn-primary btn-add-dataset',
@@ -60,16 +62,19 @@
   {% endif %}
 </div>
 {# {{ pkg.resources }} #}
+
 {% block package_notes %}
+<div class="btn btn-primary btn-lg show-filters" role="button">
+    <img src="/base/images/icon_info.svg" aria-hidden="true"></img>
+    {{ _('Detailinformationen') }}
+</div>
 {% if pkg.notes %}
 <div class="notes embedded-content">
   {{ h.render_markdown(h.get_translated(pkg, 'notes')) }}
 </div>
 {% endif %}
-{% endblock %}
-{# FIXME why is this here? seems wrong #}
-<span class="insert-comment-thread"></span>
-{% endblock %}
+{% endblock package_notes %}
+{% endblock package_description %}
 
 {% block package_resources %}
 {% snippet "package/snippets/resources_list.html", pkg=pkg, resources=pkg.resources %}
@@ -80,6 +85,48 @@
   {% endif %}
 {% endblock %}
 
+{% block collection %}
+{% if latest_collection_member %}
+<section id="dataset-collection">
+    {% if collection_title %}
+    <p>
+        Dieser Datensatz ist Bestandteil der Datenreihe "{{ collection_title }}". 
+        Sie können zu älteren und neueren Datensätzen blättern.
+    </p>
+    {% endif %} {# collection_title #}
+    <div class="button-container">
+        <a href="{{ latest_collection_member }}" class="btn btn-primary btn-lg" role="button">
+            <img src="/base/images/icon_latest.svg" aria-hidden="true"></img>
+            <span class="hide-on-mobile">{{ _('latest collection member') }}</span>
+        </a>
+        {% if predecessor_url %} 
+        <a href="{{ predecessor_url }}" class="btn btn-primary btn-lg" role="button">
+            <img src="/base/images/icon_arrow_left.svg" aria-hidden="true"></img>
+            <span class="hide-on-mobile">{{ _('predecessor') }}</span>
+        </a>
+        {% else %}
+        <a href="#" class="btn btn-primary btn-lg disabled" role="button">
+            <img src="/base/images/icon_arrow_left.svg" aria-hidden="true"></img>
+            <span class="hide-on-mobile">{{ _('predecessor') }}</span>
+        </a>
+        {% endif %}  
+        {% if successor_url %}
+        <a href="{{ successor_url }}" class="btn btn-primary btn-lg" role="button">
+            <span class="hide-on-mobile">{{ _('successor') }}</span>
+            <img src="/base/images/icon_arrow_right.svg" aria-hidden="true"></img>
+        </a>
+        {% else %}
+        <a href="#" class="btn btn-primary btn-lg disabled" role="button">
+            <span class="hide-on-mobile">{{ _('successor') }}</span>
+            <img src="/base/images/icon_arrow_right.svg" aria-hidden="true"></img>
+        </a>
+        {% endif %}
+    </div>
+</section>
+{% endif %} {# latest_collection_member #}
+{% endblock collection %}
+
+
 <div class='tag-container'>
 {% for tag in pkg.tags %}
     <div class='tag-pill'>
@@ -88,4 +135,5 @@
 {% endfor %}
 </div>
 
-{% endblock %}
\ No newline at end of file
+{% endblock %}
+
diff --git a/ckanext/odsh/templates/package/read_base.html b/ckanext/odsh/templates/package/read_base.html
index 9597da673921613a4a8c9f15e2c7269c33e2943b..99cb65fdda0f56337edb14a2135016b73955fbd5 100644
--- a/ckanext/odsh/templates/package/read_base.html
+++ b/ckanext/odsh/templates/package/read_base.html
@@ -9,9 +9,10 @@
 {% block secondary_content %}
 
 {% block package_organization %}
+{% snippet "package/snippets/close_mobile_sidebar_button.html" %}
 {% if pkg.organization %}
 {% set org = h.get_organization(pkg.organization.name) %}
-{% snippet "snippets/organization.html", organization=org, has_context_title=true, hide_description=true %}
+{% snippet "snippets/organization.html", package=pkg, organization=org, has_context_title=true, hide_description=true %}
 {% endif %}
 {% endblock %}
 
diff --git a/ckanext/odsh/templates/package/search.html b/ckanext/odsh/templates/package/search.html
index 75ce5e4e537d2d1edecf4eed5d6987f71f8e2f30..b08b1f55b8059262e0300d2d75153f0b94abb5e4 100644
--- a/ckanext/odsh/templates/package/search.html
+++ b/ckanext/odsh/templates/package/search.html
@@ -1,12 +1,18 @@
 {% ckan_extends %}
 
 
+{% block breadcrumb_content %}
+  <li class="active">{{ h.nav_link(_('Documents'), controller='package', action='search', highlight_actions = 'new index') }}</li>
+{% endblock %}
 
 {% block toolbar %}
 {{ super() }}
 <form id='dataset-search-box-form' class="section site-search simple-input" action="{% url_for controller='package', action='search' %}"
-    method="get" data-module="select-switch">
-{% snippet "snippets/search_box.html"%}
+method="get" data-module="select-switch">
+    <div class="row filter-search-row">
+        <div class='btn show-filters'>Filter</div>
+        {% snippet "snippets/search_box.html"%}
+    </div>
 {% endblock %}
 
 {% block primary_content %}
@@ -31,22 +37,23 @@
   {% endblock %}
 {% endblock %}
 
-
 {% block secondary_content %}
 <div class="filters">
-  <div class="container-fluid filter-reset">
-    <div class="filter-reset-label"><span>Filter:</span></div>
-    <div class="filter-reset-box"><a href="{{h.url_for(controller='package', action='search')}}">zurücksetzen</a></button></div>
-  </div>
+    {% snippet "package/snippets/close_mobile_sidebar_button.html" %}
+    <div class="container-fluid filter-reset">
+        <div class="filter-reset-label"><span>Filter:</span></div>
+        <div class="filter-reset-box">
+            <a href="{{h.url_for(controller='package', action='search')}}">zurücksetzen</a>
+        </div>
+    </div>
 </div>
-{% snippet "snippets/map.html",
-default_extent="{ \"type\": \"Polygon\", \"coordinates\": [[[7.6574,53.1632],[11.8322,53.1632],[11.8322,55.1066],
-[7.6574,55.1066],[7.6574,53.1632]]] }"%}
+
 <div class="filters">
   <div>
     {% for facet in c.facet_titles %}
     {{ h.snippet('snippets/facet_list.html', title=c.facet_titles[facet], name=facet) }}
     {% endfor %}
+  </div>
 
   {% block datereange_search %}
   {% set has_range_filter = request.params.get('ext_startdate') or request.params.get('ext_enddate') %}
@@ -66,27 +73,41 @@ default_extent="{ \"type\": \"Polygon\", \"coordinates\": [[[7.6574,53.1632],[11
             {%- set end_error = h.odsh_render_datetime(end, False) == '' and end -%}
             {%- set typeStart = 'text' if (start_error or not start) else 'date' -%}
             {%- set typeEnd = 'text' if (end_error or not end) else 'date' -%}
+            
             <label for="ext_startdate">{{_('from')|title}}</label>
-	          {% snippet 'snippets/datepicker.html', id='ext_startdate', value=start, class='rangesearch', placeholder=_('Date') %}
-              {%if start_error %}
-                <div class="error-reange-search">
-                    {{_('wrong_start_date_for_search')}}
-                </div>
-              {%endif%}
+            {% 
+              snippet 'snippets/datepicker.html', 
+              aria_label=_('date start'), 
+              id='ext_startdate', 
+              value=start, 
+              class='rangesearch', 
+              placeholder=_('Date') 
+            %}
+            {%if start_error %}
+              <div class="error-reange-search">
+                  {{_('wrong_start_date_for_search')}}
+              </div>
+            {%endif%}
+            
             <label for="ext_enddate">{{_('to')|title}}</label>
-	          {% snippet 'snippets/datepicker.html', id='ext_enddate', value=end, class='rangesearch', placeholder=_('Date') %}
-              {%if end_error %}
-                <div class="error-reange-search">
-                    {{_('wrong_end_date_for_search')}}
-                </div>
-              {%endif%}
+            {% 
+              snippet 'snippets/datepicker.html', 
+              aria_label=_('date end'),
+              id='ext_enddate', 
+              value=end, 
+              class='rangesearch', 
+              placeholder=_('Date') 
+            %}
+            {%if end_error %}
+              <div class="error-reange-search">
+                  {{_('wrong_end_date_for_search')}}
+              </div>
+            {%endif%}
             <a class='pull-right' href="javascript:{}" onclick="$('#dataset-search-box-form').submit();" class="action">{{_('submit date search') }}</a>
           </div>
       </div>
     </nav>
   </section>
-  </div>
- <a class="close no-text hide-filters"><i class="fa fa-times-circle"></i><span class="text">close</span></a>
   {% endblock %}
 
 </div>
@@ -94,4 +115,4 @@ default_extent="{ \"type\": \"Polygon\", \"coordinates\": [[[7.6574,53.1632],[11
 
 {% block pre_wrap %}
 </form>
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/ckanext/odsh/templates/package/search.html_neu b/ckanext/odsh/templates/package/search.html_neu
new file mode 100644
index 0000000000000000000000000000000000000000..cadf27f07acc15663e13424255d3e6da720fa87b
--- /dev/null
+++ b/ckanext/odsh/templates/package/search.html_neu
@@ -0,0 +1,123 @@
+{% ckan_extends %}
+
+
+{% block breadcrumb_content %}
+  <li class="active">{{ h.nav_link(_('Documents'), controller='package', action='search', highlight_actions = 'new index') }}</li>
+{% endblock %}
+
+{% block toolbar %}
+{{ super() }}
+<form id='dataset-search-box-form' class="section site-search simple-input" action="{% url_for controller='package', action='search' %}"
+method="get" data-module="select-switch">
+    <div class="row filter-search-row">
+        <div class='btn show-filters'>Filter</div>
+        {% snippet "snippets/search_box.html"%}
+    </div>
+{% endblock %}
+
+{% block primary_content %}
+  <section class="module">
+    <div class="module-content">
+      {% block page_primary_action %}
+      {% endblock %}
+      {% block form %}
+        {{ super() }}
+      {% endblock %}
+      {% block package_search_results_list %}
+        {{ h.snippet('snippets/package_list.html', packages=c.page.items) }}
+      {% endblock %}
+    </div>
+
+    {% block page_pagination %}
+    {{ c.page.pager(q=c.q,symbol_next='>') }}
+    {% endblock %}
+  </section>
+
+  {% block package_search_results_api %}
+  {% endblock %}
+{% endblock %}
+
+
+{% block secondary_content %}
+<div class="filters">
+    {% snippet "package/snippets/close_mobile_sidebar_button.html" %}
+    <div class="container-fluid filter-reset">
+        <div class="filter-reset-label"><span>Filter:</span></div>
+        <div class="filter-reset-box">
+            <a href="{{h.url_for(controller='package', action='search')}}">zurücksetzen</a>
+        </div>
+    </div>
+</div>
+{% snippet "snippets/map.html",
+default_extent="{ \"type\": \"Polygon\", \"coordinates\": [[[7.6574,53.1632],[11.8322,53.1632],[11.8322,55.1066],
+[7.6574,55.1066],[7.6574,53.1632]]] }"%}
+<div class="filters">
+  <div>
+    {% for facet in c.facet_titles %}
+    {{ h.snippet('snippets/facet_list.html', title=c.facet_titles[facet], name=facet) }}
+    {% endfor %}
+  </div>
+
+  {% block datereange_search %}
+  {% set has_range_filter = request.params.get('ext_startdate') or request.params.get('ext_enddate') %}
+  <section class="module module-narrow module-shallow">
+    <nav>
+      <div class="nav-title">{{_('timerange')}}</div>
+      <div class="rangesearch-controls">
+          {% import 'macros/form.html' as form %}
+          {% resource 'odsh/moment.js' %}
+          {% resource 'odsh/datepicker.css' %}
+          {% resource 'odsh/bootstrap-datepicker.js' %}
+          {% resource 'odsh/odsh_datepicker.js' %}
+          <div class='controls rangesearch' >
+            {%- set start = request.params['ext_startdate'] -%}
+            {%- set start_error = h.odsh_render_datetime(start, False) == '' and start -%}
+            {%- set end = request.params['ext_enddate'] -%}
+            {%- set end_error = h.odsh_render_datetime(end, False) == '' and end -%}
+            {%- set typeStart = 'text' if (start_error or not start) else 'date' -%}
+            {%- set typeEnd = 'text' if (end_error or not end) else 'date' -%}
+            
+            <label for="ext_startdate">{{_('from')|title}}</label>
+            {% 
+              snippet 'snippets/datepicker.html', 
+              aria_label=_('date start'), 
+              id='ext_startdate', 
+              value=start, 
+              class='rangesearch', 
+              placeholder=_('Date') 
+            %}
+            {%if start_error %}
+              <div class="error-reange-search">
+                  {{_('wrong_start_date_for_search')}}
+              </div>
+            {%endif%}
+            
+            <label for="ext_enddate">{{_('to')|title}}</label>
+            {% 
+              snippet 'snippets/datepicker.html', 
+              aria_label=_('date end'),
+              id='ext_enddate', 
+              value=end, 
+              class='rangesearch', 
+              placeholder=_('Date') 
+            %}
+            {%if end_error %}
+              <div class="error-reange-search">
+                  {{_('wrong_end_date_for_search')}}
+              </div>
+            {%endif%}
+            <a class='pull-right' href="javascript:{}" onclick="$('#dataset-search-box-form').submit();" class="action">{{_('submit date search') }}</a>
+          </div>
+      </div>
+    </nav>
+  </section>
+  </div>
+ <a class="close no-text hide-filters"><i class="fa fa-times-circle"></i><span class="text">close</span></a>
+  {% endblock %}
+
+</div>
+{% endblock %}
+
+{% block pre_wrap %}
+</form>
+{% endblock %}
diff --git a/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html b/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html
new file mode 100644
index 0000000000000000000000000000000000000000..5e30ade9262d6db85bd7ed8792b3f92091950b7a
--- /dev/null
+++ b/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html
@@ -0,0 +1,3 @@
+<div class="container-fluid hide-filters-style">
+    <a class="no-text hide-filters"><img src="/base/images/icon_close.svg" alt="Filterdialog schließen"><span class="text">close</span></a>
+</div>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/package/snippets/info.html b/ckanext/odsh/templates/package/snippets/info.html
index cff6830c16011422f3f1a62ed512c8e0d4773219..167ec74d8efccd2624e126e827508a1d86a0de34 100644
--- a/ckanext/odsh/templates/package/snippets/info.html
+++ b/ckanext/odsh/templates/package/snippets/info.html
@@ -8,6 +8,11 @@ Example:
 {% snippet "package/snippets/info.html", pkg=pkg %}
 
 #}
+
+{% set daterange = h.tpsh_get_daterange_prettified(pkg) %}
+{% set language_icon = h.get_language_icon(pkg) %}
+{% set license_attribution_by_text = h.odsh_extract_value_from_extras(pkg.extras, 'licenseAttributionByText') %}
+
 {% block package_info %}
 {% if pkg %}
 <section class="module module-narrow">
@@ -15,40 +20,43 @@ Example:
         <div class="module-content">
             {% block package_info_inner %}
             {% block heading %}
-            {% endblock %}
+            {% endblock heading %}
 
-            {% block groups %}
-            <div class="groups-detail info-detail">
-                <div>{{ _('Kategorie') }}:</div>
-                {{ pkg.groups|map(attribute='display_name')|join('; ') }}
+            {% block groups %} {# aka categories #}
+            {% if pkg.groups|length %}
+            <div class="info-detail groups-detail">
+                <div>
+                    {% trans category_count=pkg.groups|length %}
+                    category:
+                    {% pluralize %}
+                    categories:
+                    {% endtrans %}
+                </div>
+                {% for category in pkg.groups %}
+                <span class='category-with-icon'>
+                    <span class='category-icon-container'>
+                        <img src="/base/images/icon_kat_{{category.name}}.svg" />
+                    </span>
+                    <span class="category-name">
+                        {{ category.display_name }}
+                    </span>
+                </span>
+                {% endfor %}
             </div>
-            {% endblock %}
-
-            {% block nums %}
-            {% endblock %}
-
+            {% endif %}
+            {% endblock groups %}
 
-            {% block license %}
-            <div class="license-detail info-detail">
-                <div>{{ _('License') }}:</div>
-                {%set lic=pkg.license_title if pkg.license_title else '-'%}
-                {%set licenseAttributionByText = h.odsh_extract_value_from_extras(pkg.extras,'licenseAttributionByText') %}
-                {%set name=' (' + licenseAttributionByText +')' if licenseAttributionByText else ''%}
-                <a href='{{pkg.license_url}}'>{{ lic }}</a>{{ name }}
-            </div>
-            {% endblock %}
 
             {% block timerange %}
+            {% if daterange %}
             <div class="timerange-detail info-detail">
                 <div>{{ _('timerange') }}:</div>
-                {% set temporal_start = h.odsh_extract_value_from_extras(pkg.extras,'temporal_start') %}
-                {% set temporal_end = h.odsh_extract_value_from_extras(pkg.extras,'temporal_end') %}
-                {%set start=h.odsh_render_datetime(temporal_start) if temporal_start else ''%}
-                {%set end=h.odsh_render_datetime(temporal_end) if temporal_end else ''%}
-                <p>{{ start }} - {{ end }}</p>
+                <p>{{ daterange }}</p>
             </div>
-            {% endblock %}
+            {% endif %}
+            {% endblock timerange %}
 
+            
             {% block last_change %}
             <div class="last-change-detail info-detail">
                 {% set value = h.odsh_extract_value_from_extras(pkg.extras,'issued')%}
@@ -61,9 +69,19 @@ Example:
                 <div>{{ _('modified') }}:</div>
                 {{modified}}
             </div>
-            {% endblock %}
+            {% endblock last_change %}
+
+            {% block license %}
+            <div class="license-detail info-detail">
+                <div>{{ _('License') }}:</div>
+                {%set lic=pkg.license_title if pkg.license_title else '-'%}
+                {%set licenseAttributionByText = h.odsh_extract_value_from_extras(pkg.extras,'licenseAttributionByText') %}
+                {%set name=' (' + licenseAttributionByText +')' if licenseAttributionByText else ''%}
+                <a href='{{pkg.license_url}}'>{{ lic }}</a>{{ name }}
+            </div>
+            {% endblock license %}
 
-            {% endblock %}
+            {% endblock package_info_inner %}
         </div>
         {% set map_text = h.odsh_get_spatial_text(pkg) %}
         <div class="spatial-detail info-detail">
@@ -95,15 +113,27 @@ Example:
             {% set current_url = h.odsh_encodeurl(h.full_current_url()) %}
             <p>{{ _('share this dataset')}}:</p>
             <div class="share-links">
-                <a href="https://www.linkedin.com/shareArticle?mini=true&url={{current_url}}" target="_blank"><img class='' src="/base/images/Icon-linkedin.png"/></a>
-                <a href="https://www.xing.com/app/user?op=share&url={{ current_url }}" target="_blank"><img class='' src="/base/images/Icon-xing.png"/></a>
-                <a href="https://www.facebook.com/sharer.php?href={{ current_url }}" target="_blank"><img class='' src="/base/images/Icon-facebook.png"/></a>
-                <a href="https://twitter.com/share?url={{ current_url }}" target="_blank"><img class='' src="/base/images/Icon-twitter.png"/></a>
-                <a href="mailto:?body={{ current_url }}" target="_blank"><img class='' src="/base/images/Icon-mail.png"/></a>
+                <a href="https://www.linkedin.com/shareArticle?mini=true&url={{current_url}}" target="_blank">
+                    <img class='' src="/base/images/Icon-linkedin.png" alt="Linked In"/>
+                </a>
+                <a href="https://www.xing.com/app/user?op=share&url={{ current_url }}" target="_blank">
+                    <img class='' src="/base/images/Icon-xing.png" alt="XING"/>
+                </a>
+                <a href="https://www.facebook.com/sharer.php?href={{ current_url }}" target="_blank">
+                    <img class='' src="/base/images/Icon-facebook.png" alt="facebook"/>
+                </a>
+                <a href="https://twitter.com/share?url={{ current_url }}" target="_blank">
+                    <img class='' src="/base/images/Icon-twitter.png" alt="twitter"/>
+                </a>
+                <a href="mailto:?body={{ current_url }}" target="_blank">
+                    <img class='' src="/base/images/Icon-mail.png" alt="{{ _('send an email') }}"/>
+                </a>
             </div>
         </div>
-        {% endblock %}
+        {% endblock social_nav %}
         {% endif %}
+
+        
 </section>
 {% endif %}
-{% endblock %}
\ No newline at end of file
+{% endblock package_info %}
diff --git a/ckanext/odsh/templates/package/snippets/package_basic_fields.html b/ckanext/odsh/templates/package/snippets/package_basic_fields.html
index 5bed804b41f9cc894ef9381a496e24c22c738daa..ada4778f2c438600cabce8295223a229ed2e87b6 100644
--- a/ckanext/odsh/templates/package/snippets/package_basic_fields.html
+++ b/ckanext/odsh/templates/package/snippets/package_basic_fields.html
@@ -3,315 +3,320 @@
 {% resource 'odsh/bootstrap-multiselect.js' %}
 {% set dataset_is_draft = data.get('state', 'draft').startswith('draft') or data.get('state', 'none') == 'none' %}
 
-<!-- field title -->
+
+{# field title #}
 {% block package_basic_fields_title %}
 {% set error_string = _(_('Title') + ': '+errors.title[0]) if errors.title %}
-{{ form.input('title', id='field-title', label=_('Title'), value=data.title,
-error=error_string, classes=['control-full'], attrs={'data-module': 'slug-preview-target'},
-is_required=true,placeholder=_('Enter title')) }}
-{% endblock %}
+{{ 
+    form.input(
+        'title', id='field-title', 
+        label=_('Title'), 
+        value=data.title,
+        error=error_string, 
+        classes=['control-full'], 
+        attrs={'data-module': 'slug-preview-target'},
+        is_required=true,
+        placeholder=_('Enter title')
+    ) 
+}}
+{% endblock package_basic_fields_title %}
 
 
-    <!-- field notes -->
-    {% block package_basic_fields_description %}
-    {% set error_string = _(_('Description') + ': '+errors.notes[0]) if errors.notes %}
-    {{ form.markdown('notes', id='field-notes', label=_('Description'), value=data.notes,
-    error=error_string, is_required=true, placeholder=_('Enter description')) }}
-    {% endblock %}
+{# field note #}
+{% block package_basic_fields_description %}
+{% set error_string = _(_('Description') + ': '+errors.notes[0]) if errors.notes %}
+{{ 
+    form.markdown(
+        'notes', 
+        id='field-notes', 
+        label=_('Description'), 
+        value=data.notes,
+        error=error_string, 
+        is_required=false, 
+        placeholder=_('Enter description')
+    ) 
+}}
+{% endblock package_basic_fields_description %}
 
-    {% block package_basic_fields_org %}
-    {% if data.group_id %}
-    <input type="hidden" name="groups__0__id" value="{{ data.group_id }}" />
-    {% endif %}
 
-    {% set dataset_has_organization = data.owner_org or data.group_id %}
-    {% set organizations_available = h.organizations_available('create_dataset') %}
-    {% set user_is_sysadmin = h.check_access('sysadmin') %}
-    {% set show_organizations_selector = organizations_available %}
-    {% set show_visibility_selector = dataset_has_organization or (organizations_available and (user_is_sysadmin or
-    dataset_is_draft)) %}
-    {% set existing_org = data.owner_org or data.group_id %}
+{# field Organization #}
+{% block package_basic_fields_org %}
+{% if data.group_id %}
+<input type="hidden" name="groups__0__id" value="{{ data.group_id }}" />
+{% endif %}
 
-    <div class="control-group field-organization">
-        <label for="field-organizations" class="control-label">{{ _('Organization') }}
-            <span title="{{ _("This field is required") }}" class="control-required">*</span>
-        </label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    <select id="field-organizations" name="owner_org" data-module="autocomplete">
-                        {% if h.check_config_permission('create_unowned_dataset') %}
-                        <option value="" {% if not selected_org and data.id %} selected="selected" {% endif %}>{{ _('No
-                            organization') }}</option>
-                        {% endif %}
-                        {% for organization in organizations_available %}
-                        {# get out first org from users list only if there is not an existing org #}
-                        {% set selected_org = (existing_org and existing_org == organization.id) or (not existing_org and not data.id and organization.id == organizations_available[0].id) %}
-                        <option value="{{ organization.id }}" {% if selected_org %} selected="selected" {% endif %}>{{
-                            organization.display_name }}</option>
-                        {% endfor %}
-                    </select>
-                </div>
+{% set dataset_has_organization = data.owner_org or data.group_id %}
+{% set organizations_available = h.organizations_available('create_dataset') %}
+{% set user_is_sysadmin = h.check_access('sysadmin') %}
+{% set show_organizations_selector = organizations_available %}
+{% set show_visibility_selector = dataset_has_organization or (organizations_available and (user_is_sysadmin or
+dataset_is_draft)) %}
+{% set existing_org = data.owner_org or data.group_id %}
+
+<div class="control-group field-organization">
+    <label for="field-organizations" class="control-label">
+        {{ _('Organization') }}
+        <span title="{{ _("This field is required") }}" class="control-required">*</span>
+    </label>
+    <div class="controls">
+        <div class="row-fluid">
+            <div class="span6">
+                <select id="field-organizations" name="owner_org" data-module="autocomplete">
+                    {% if h.check_config_permission('create_unowned_dataset') %}
+                    <option value="" {% if not selected_org and data.id %} selected="selected" {% endif %}>{{ _('No
+                        organization') }}</option>
+                    {% endif %}
+                    {% for organization in organizations_available %}
+                    {# get out first org from users list only if there is not an existing org #}
+                    {% set selected_org = (existing_org and existing_org == organization.id) or (not existing_org and not data.id and organization.id == organizations_available[0].id) %}
+                    <option value="{{ organization.id }}" {% if selected_org %} selected="selected" {% endif %}>{{
+                        organization.display_name }}</option>
+                    {% endfor %}
+                </select>
             </div>
         </div>
     </div>
-    {% endblock %}
+</div>
+{% endblock package_basic_fields_org %}
 
 
-    <!-- field license -->
-    {% set error_missing_attr = h.odsh_extract_error('licenseAttributionByText', errors) %}
-    <label class="control-label" for="field-license">
-        {{ _("License") }}:
-        <span title="{{ _("This field is required") }}" class="control-required">*</span>
-    </label>
-    <div class='row-fluid'>
-        <div class='span3'>
-            {% block package_basic_fields_license %}
-                {% set error = errors.license_id %}
-                {% set error_license_id = _(_("License") + ': '+errors.license_id[0] ) if errors.license_id %}
-            <div class="control-group {{ " error" if error_license_id }}">
-                <div class="controls">
-                    <select id="field-license" name="license_id">
-                        {% set existing_license_id = data.get('license_id') %}
-                        {% for license_id, license_desc in h.presorted_license_options(existing_license_id) %}
-                        <option value="{{ license_id }}" {% if existing_license_id==license_id %}selected="selected" {%
-                            endif %}>{{ license_desc }}</option>
-                        {% endfor %}
-                    </select>
-                </div>
+{# field license #}
+{% block package_basic_fields_license %}
+
+{% set error_missing_attr = h.odsh_extract_error('licenseAttributionByText', errors) %}
+<label class="control-label" for="field-license">
+    {{ _("License") }}:
+    <span title="{{ _("This field is required") }}" class="control-required">*</span>
+</label>
+<div class='row-fluid'>
+    <div class='span3'>
+            {% set error = errors.license_id %}
+            {% set error_license_id = _(_("License") + ': '+errors.license_id[0] ) if errors.license_id %}
+        <div class="control-group {{ " error" if error_license_id }}">
+            <div class="controls">
+                <select id="field-license" name="license_id">
+                    {% set existing_license_id = data.get('license_id') %}
+                    {% for license_id, license_desc in h.presorted_license_options(existing_license_id) %}
+                    <option value="{{ license_id }}" {% if existing_license_id==license_id %}selected="selected" {%
+                        endif %}>{{ license_desc }}</option>
+                    {% endfor %}
+                </select>
             </div>
         </div>
-        <div class='span3'>
-            <!-- field Namensnennung -->
-            {% set field = 'licenseAttributionByText' %}
-            {% set value = h.odsh_extract_value_from_extras(data.extras,field) %}
-            <div class="control-group {{ " error" if error_missing_attr }} control-full">
-                <div class="controls">
-                            {{ form.input_extra(field, value=value, index=h.odsh_create_checksum(field), type='text', attrs={'disabled':true,
-            'data-module':"odsh_form", 'data-module-licensetoggle':'true', 'data-module-autofill':'true'}, placeholder=_('enter name')) }}
-                </div>
+    </div>
+    <div class='span3'>
+        {# field Namensnennung #}
+        {% set field = 'licenseAttributionByText' %}
+        {% set value = h.odsh_extract_value_from_extras(data.extras,field) %}
+        <div class="control-group {{ " error" if error_missing_attr }} control-full">
+            <div class="controls">
+                        {{ form.input_extra(field, value=value, index=h.odsh_create_checksum(field), type='text', attrs={'disabled':true,
+        'data-module':"odsh_form", 'data-module-licensetoggle':'true', 'data-module-autofill':'true'}, placeholder=_('enter name')) }}
             </div>
         </div>
-        {% if error_license_id %} 
-            <div class="span6 inline-error">
-                {{_(error_license_id)}}
-            </div>
-        {% endif %}
-        {% if error_missing_attr%} 
-            <div class="span6 inline-error">
-                {{_(error_missing_attr)}}
-            </div>
-        {% endif %}
     </div>
+    {% if error_license_id %} 
+        <div class="span6 inline-error">
+            {{_(error_license_id)}}
+        </div>
+    {% endif %}
+    {% if error_missing_attr%} 
+        <div class="span6 inline-error">
+            {{_(error_missing_attr)}}
+        </div>
+    {% endif %}
+</div>
 
-    {% endblock %}
+{% endblock package_basic_fields_license%}
 
-    <!-- timerange -->
-    {% set error_start = h.odsh_extract_error_new('temporal_start', errors) %}
-    {% set error_end = h.odsh_extract_error_new('temporal_end', errors) %}
-    {% set error_string = 'odsh_temporal_error_label' if error_start and error_end else (error_start if error_start else (error_end if error_end))%}
-    <label for="start-end" class="control-label">{{ _('timerange') }}:
-        <span title="{{ _("This field is required") }}" class="control-required">*</span>
-    </label>
-    <div class='row-fluid'>
-          {% resource 'odsh/moment.js' %}
-          {% resource 'odsh/datepicker.css' %}
-          {% resource 'odsh/bootstrap-datepicker.js' %}
-          {% resource 'odsh/odsh_datepicker.js' %}
-        <div id='start-end' class='span3'>
-            <!-- field temporal_start -->
-            {% set field = 'temporal_start' %}
-            {% set data_temporal_start = h.odsh_extract_value_from_extras(data.extras,field) %}
-            {% set value = data_temporal_start.split('T')[0] if data_temporal_start else None %}
-            {% set index = h.odsh_create_checksum(field) %}
-            <div class="control-group {{ " error" if error_start }} control-full">
-                <div class="controls">
-                            {{ form.input_extra(field, value=value, index=index, type='hidden') }}
-                            <input pattern="\d{2}\.\d{2}\.\d{4}" autocomplete="off" id="datepicker_start" type="text" 
-                                value="{{h.odsh_render_datetime(value, False)}}" placeholder="{{ _('from') }}"
-                                data-module="odsh_datepicker" data-module-target='field-temporal_start-value'/>
-                </div>
+
+{# timerange #}
+{% set error_start = h.odsh_extract_error_new('temporal_start', errors) %}
+{% set error_end = h.odsh_extract_error_new('temporal_end', errors) %}
+{% set error_string = 'odsh_temporal_error_label' if error_start and error_end else (error_start if error_start else (error_end if error_end))%}
+<label for="start-end" class="control-label">{{ _('timerange') }}:
+    {# <span title="{{ _("This field is required") }}" class="control-required">*</span> #}
+</label>
+<div class='row-fluid'>
+        {% resource 'odsh/moment.js' %}
+        {% resource 'odsh/datepicker.css' %}
+        {% resource 'odsh/bootstrap-datepicker.js' %}
+        {% resource 'odsh/odsh_datepicker.js' %}
+    <div id='start-end' class='span3'>
+        {# field temporal_start #}
+        {% set field = 'temporal_start' %}
+        {% set data_temporal_start = h.odsh_extract_value_from_extras(data.extras,field) %}
+        {% set value = data_temporal_start.split('T')[0] if data_temporal_start else None %}
+        {% set index = h.odsh_create_checksum(field) %}
+        <div class="control-group {{ " error" if error_start }} control-full">
+            <div class="controls">
+                        {{ form.input_extra(field, value=value, index=index, type='hidden') }}
+                        <input pattern="\d{2}\.\d{2}\.\d{4}" autocomplete="off" id="datepicker_start" type="text" 
+                            value="{{h.odsh_render_datetime(value, False)}}" placeholder="{{ _('from') }}"
+                            data-module="odsh_datepicker" data-module-target='field-temporal_start-value'/>
             </div>
         </div>
-        <div class='span3'>
-            <!-- field temporal_end -->
-            {% set field = 'temporal_end' %}
-            {% set data_temporal_end = h.odsh_extract_value_from_extras(data.extras,field) %}
-            {% set value = data_temporal_end.split('T')[0] if data_temporal_end else None %}
-            <div class="control-group {{ " error" if error_end }} control-full">
-                <div class="controls">
-                            {{ form.input_extra(field, value=value, index=h.odsh_create_checksum(field), type='hidden') }}
-                            <input pattern="\d{2}\.\d{2}\.\d{4}"  autocomplete="off" id="datepicker_end" type="text" 
-                                value="{{h.odsh_render_datetime(value, False)}}" placeholder="{{ _('to') }}"
-                                data-module="odsh_datepicker" data-module-target='field-temporal_end-value'/>
-                </div>
+    </div>
+    <div class='span3'>
+        {# field temporal_end #}
+        {% set field = 'temporal_end' %}
+        {% set data_temporal_end = h.odsh_extract_value_from_extras(data.extras,field) %}
+        {% set value = data_temporal_end.split('T')[0] if data_temporal_end else None %}
+        <div class="control-group {{ " error" if error_end }} control-full">
+            <div class="controls">
+                        {{ form.input_extra(field, value=value, index=h.odsh_create_checksum(field), type='hidden') }}
+                        <input pattern="\d{2}\.\d{2}\.\d{4}"  autocomplete="off" id="datepicker_end" type="text" 
+                            value="{{h.odsh_render_datetime(value, False)}}" placeholder="{{ _('to') }}"
+                            data-module="odsh_datepicker" data-module-target='field-temporal_end-value'/>
             </div>
         </div>
-        {% if error_string %} 
-            <div class="span6 inline-error">
-                {{_(error_string)}}
-            </div>
-        {% endif %}
     </div>
+    {% if error_string %} 
+        <div class="span6 inline-error">
+            {{_(error_string)}}
+        </div>
+    {% endif %}
+</div>
 
-    <!-- field issued -->
 
-    {% set field = 'issued' %}
-    {% set data_issued = h.odsh_extract_value_from_extras(data.extras,field) %}
-    {% set error = h.odsh_extract_error_new(field, errors) %}
-    {% set value = data_issued.split('T')[0] if data_issued else (h.odsh_now() if not error else '')%}
-    <div class="control-group {{ " error" if error }} control-full">
-        <label class="control-label" for="field-{{field}}">Veröffentlichungsdatum: <span title="Dieses Feld ist erforderlich" class="control-required">*</span> </label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    {{ form.input_extra(field, value=value , index=h.odsh_create_checksum(field), type='hidden') }}
-                    <input  pattern="\d{2}\.\d{2}\.\d{4}" autocomplete="off" type="text" 
-                        value="{{h.odsh_render_datetime(value, False)}}" 
-                        data-module="odsh_datepicker" data-module-target='field-issued-value'/>
-                </div>
-                <div class="span6 inline-error">
-                    {% if error %} 
-                    {{_(error)}}
-                    {% endif %}
-                </div>
+{# field issued #}
+{% set field = 'issued' %}
+{% set data_issued = h.odsh_extract_value_from_extras(data.extras,field) %}
+{% set error = h.odsh_extract_error_new(field, errors) %}
+{% set value = data_issued.split('T')[0] if data_issued else (h.odsh_now() if not error else '')%}
+<div class="control-group {{ " error" if error }} control-full">
+    <label class="control-label" for="field-{{field}}">Veröffentlichungsdatum: <span title="Dieses Feld ist erforderlich" class="control-required">*</span> </label>
+    <div class="controls">
+        <div class="row-fluid">
+            <div class="span6">
+                {{ form.input_extra(field, value=value , index=h.odsh_create_checksum(field), type='hidden') }}
+                <input  pattern="\d{2}\.\d{2}\.\d{4}" autocomplete="off" type="text" 
+                    value="{{h.odsh_render_datetime(value, False)}}" 
+                    data-module="odsh_datepicker" data-module-target='field-issued-value'/>
+            </div>
+            <div class="span6 inline-error">
+                {% if error %} 
+                {{_(error)}}
+                {% endif %}
             </div>
         </div>
     </div>
+</div>
 
 
-    <!-- field tags -->
-    {% block package_basic_fields_tags %}
-    {% set tag_attrs = {'data-module': 'autocomplete', 'data-module-tags': '', 'data-module-source':
-    '/api/2/util/tag/autocomplete?incomplete=?'} %}
-    {{ form.input('tag_string', id='field-tags', label=_('Tags'), value=data.tag_string, error=errors.tag_string,
-    classes=['control-full'], attrs=tag_attrs,
-    is_required=false, placeholder=_('odsh tags placeholder')) }}
-    {% endblock %}
+{# field tags #}
+{% block package_basic_fields_tags %}
+{% set tag_attrs = {
+    'data-module': 'autocomplete', 
+    'data-module-tags': '', 
+    'data-module-source': '/api/2/util/tag/autocomplete?incomplete=?'
+} %}
+{{ 
+    form.input(
+        'tag_string', 
+        id='field-tags', 
+        label=_('Tags'), 
+        value=data.tag_string, 
+        error=errors.tag_string,
+        classes=['control-full'], 
+        attrs=tag_attrs,
+        is_required=false, 
+        placeholder=_('odsh tags placeholder')
+    ) 
+}}
+{% endblock %}
 
 
-    <!-- field spatial_uri -->
-    {% set field = 'spatial_uri' %}
-    {% set value = h.odsh_extract_value_from_extras(data.extras,field) %}
-    {% set error = h.odsh_extract_error(field, errors) %}
-    <div class="control-group {{ " error" if error }} control-full">
-        <label class="control-label" for="field-{{field}}">{{_('Spatial uri')}}: <span title="Dieses Feld ist erforderlich" class="control-required">*</span> </label>
-        <div class="controls">
-            <div class="row-fluid">
-            {% if not value and not error and data.state == 'active'%}
-                <div class="span6">
-                    <input  type='text' value="{{h.truncate(h.odsh_extract_value_from_extras(data.extras,'spatial'),20)}}" readonly  />
-                </div>
-            {% else %}
-                <div class="span6">
-                    {{ form.input_extra(field, value=value, index=h.odsh_create_checksum(field), type='text', placeholder=_('Enter spatial uri')) }}
-                </div>
-                <div class="span6 inline-error">
-                    {% if error %} 
-                    {{_(error)}}
-                    {% endif %}
-                </div>
-                {% endif %}
-            </div>
-        </div>
-    </div>
+{# field language #}
+{% set before_selected = data.get('language') or h.odsh_extract_value_from_extras(data.extras, 'language') or 'http://publications.europa.eu/resource/authority/language/DEU' %}
+{{ form.tpsh_select('language', label=_('language'), options=h.get_language_for_selection(), selected=before_selected , error=errors.language, is_required=False, classes=['control-full']) }}
 
-    {#
-    {% set spatial_extends_available = h.odsh_spatial_extends_available() %}
-    <div class="control-group">
-        <label class="control-label" for="field-{{field}}">{{_('Spatial uri')}}: <span title="Dieses Feld ist erforderlich" class="control-required">*</span> </label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    <select id="field-{{field}}" data-module="autocomplete" data-module-items="10">
-                        {% for extend in spatial_extends_available%}
-                        <option value="{{ extend }}" {% if selected_extend %} selected="selected" {% endif %}>{{extend}}</option> 
-                        {% endfor %}
-                    </select>
-                </div>
-            </div>
-        </div>
-    </div>
-    #}
 
-    <!-- field private -->
-    <div class="control-group">
-        <label for="field-private" class="control-label">{{ _('Visibility') }}:
-            <span title="{{ _("This field is required") }}" class="control-required">*</span>
-        </label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    <select id="field-private" name="private">
-                        {% for option in [('True', _('Private')), ('False', _('Public'))] %}
-                        <option value="{{ option[0] }}" {% if option[0]==data.private|trim %}selected="selected" {%
-                            endif %}>{{
-                            option[1] }}</option>
-                        {% endfor %}
-                    </select>
-                </div>
+{# field spatial_uri #}
+{% set spatial_uri_from_extras =  h.odsh_extract_value_from_extras(data.extras, 'spatial_uri') %}
+{% set spatial_uri = data.spatial_uri_temp or spatial_uri_from_extras or '' %}
+{{ form.select_autocomplete('spatial_uri_temp', label=_('Spatial uri'), selected=spatial_uri, options=h.get_spatial_for_selection(), is_required=False, classes=['control-full', 'field-spatial_uri'])}}
+
+
+{# field private #}
+<div class="control-group">
+    <label for="field-private" class="control-label">{{ _('Visibility') }}:
+        <span title="{{ _("This field is required") }}" class="control-required">*</span>
+    </label>
+    <div class="controls">
+        <div class="row-fluid">
+            <div class="span6">
+                <select id="field-private" name="private">
+                    {% for option in [('True', _('Private')), ('False', _('Public'))] %}
+                    <option value="{{ option[0] }}" {% if option[0]==data.private|trim %}selected="selected" {%
+                        endif %}>{{
+                        option[1] }}</option>
+                    {% endfor %}
+                </select>
             </div>
         </div>
     </div>
+</div>
 
 
-    {% if data.id and h.check_access('package_delete', {'id': data.id}) and data.state != 'active' %}
-    <div class="control-group">
-        <label for="field-state" class="control-label">{{ _('State') }}</label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    <select id="field-state" name="state">
-                        <option value="active" {% if data.get('state', 'none' )=='active' %} selected="selected" {%
-                            endif %}>{{
-                            _('Active') }}</option>
-                        <option value="deleted" {% if data.get('state', 'none' )=='deleted' %} selected="selected" {%
-                            endif %}>{{
-                            _('Deleted') }}</option>
-                    </select>
-                </div>
+{% if data.id and h.check_access('package_delete', {'id': data.id}) and data.state != 'active' %}
+<div class="control-group">
+    <label for="field-state" class="control-label">{{ _('State') }}</label>
+    <div class="controls">
+        <div class="row-fluid">
+            <div class="span6">
+                <select id="field-state" name="state">
+                    <option value="active" {% if data.get('state', 'none' )=='active' %} selected="selected" {%
+                        endif %}>{{
+                        _('Active') }}</option>
+                    <option value="deleted" {% if data.get('state', 'none' )=='deleted' %} selected="selected" {%
+                        endif %}>{{
+                        _('Deleted') }}</option>
+                </select>
             </div>
         </div>
     </div>
-    {% endif %}
+</div>
+{% endif %}
 
-    <!-- field groups -->
-    {% set error_groups = h.odsh_extract_error_new('groups', errors) %}
-    <div class="control-group {{ " error" if error_groups }}">
-        {% set groups_label='Kategorien'%}
-        {% set multiselect_nonSelectedText='keine' %}
-        {% set multiselect_allSelectedText='alle' %}
-        {% set multiselect_nSelectedText='gewählt' %}
-        <label for="field-groups" class="control-label">{{ groups_label }}
-            <span title="{{ _("This field is required") }}" class="control-required">*</span>
-        </label>
-        <div class="controls">
-            <div class="row-fluid">
-                <div class="span6">
-                    {% set existing_groups = data.get('groups') %}
-                    {% if existing_groups %}
-                    {% set existing_groups_string = existing_groups|map(attribute='id')|join(',') %}
-                    {% else %}
-                    {% set existing_groups_string = h.odsh_extract_value_from_extras(data.extras,'groups') %}
-                    {% endif %}
-                    <select id='field-groups' multiple="multiple" data-module="odsh_form" data-module-multiselect='true'
-                        data-module-nonSelectedText="{{multiselect_nonSelectedText}}" data-module-allSelectedText="{{multiselect_allSelectedText}}"
-                        data-module-nSelectedText="{{multiselect_nSelectedText}}" data-module-update='{{data.id != None}}'>
-                        {% for option in h.groups_available()%}
-                        <option value={{option.id}} {% if existing_groups_string!=None and option['id'] in existing_groups_string %}selected="selected"
-                            {% endif %}>
-                            {{ option['display_name'] }}</option>
-                        {% endfor %}
-                    </select>
-                    <div id='selected-groups'>
-                        {{ form.input_extra('groups', value=existing_groups_string, index=h.odsh_create_checksum('groups'), type='hidden')}}
-                    </div>
-                </div>
-                <div class="span6 inline-error">
-                    {% if error_groups %} 
-                    {{_(error_groups)}}
-                    {% endif %}
+
+{# field groups #}
+{% set error_groups = h.odsh_extract_error_new('groups', errors) %}
+<div class="control-group {{ " error" if error_groups }}">
+    {% set groups_label='Kategorien'%}
+    {% set multiselect_nonSelectedText='keine' %}
+    {% set multiselect_allSelectedText='alle' %}
+    {% set multiselect_nSelectedText='gewählt' %}
+    <label for="field-groups" class="control-label">
+        {{ groups_label }}
+    </label>
+    <div class="controls">
+        <div class="row-fluid">
+            <div class="span6">
+                {% set existing_groups = data.get('groups') %}
+                {% if existing_groups %}
+                {% set existing_groups_string = existing_groups|map(attribute='id')|join(',') %}
+                {% else %}
+                {% set existing_groups_string = h.odsh_extract_value_from_extras(data.extras,'groups') %}
+                {% endif %}
+                <select id='field-groups' multiple="multiple" data-module="odsh_form" data-module-multiselect='true'
+                    data-module-nonSelectedText="{{multiselect_nonSelectedText}}" data-module-allSelectedText="{{multiselect_allSelectedText}}"
+                    data-module-nSelectedText="{{multiselect_nSelectedText}}" data-module-update='{{data.id != None}}'>
+                    {% for option in h.groups_available()%}
+                    <option value={{option.id}} {% if existing_groups_string!=None and option['id'] in existing_groups_string %}selected="selected"
+                        {% endif %}>
+                        {{ option['display_name'] }}</option>
+                    {% endfor %}
+                </select>
+                <div id='selected-groups'>
+                    {{ form.input_extra('groups', value=existing_groups_string, index=h.odsh_create_checksum('groups'), type='hidden')}}
                 </div>
             </div>
+            <div class="span6 inline-error">
+                {% if error_groups %} 
+                {{_(error_groups)}}
+                {% endif %}
+            </div>
         </div>
-    </div>
\ No newline at end of file
+    </div>
+</div>
diff --git a/ckanext/odsh/templates/package/snippets/resource_item.html b/ckanext/odsh/templates/package/snippets/resource_item.html
index cf63b5a7ba30932a882c494c31c6b0c7c29d556b..457eb4d8fca6dabff1ec8849816cf23a09270e64 100644
--- a/ckanext/odsh/templates/package/snippets/resource_item.html
+++ b/ckanext/odsh/templates/package/snippets/resource_item.html
@@ -2,44 +2,66 @@
 {% set url = h.url_for(controller='package', action=url_action, id=pkg.name, resource_id=res.id) %}
 
 {# hack for correcting slave url if resource was uploaded #}
-{% set download = h.odsh_public_resource_url(res) or ulr%}
+{% set download = h.odsh_public_resource_url(res) or url %}
 
-<li class="resource-item" data-id="{{ res.id }}">
+{% set rtitle=h.resource_display_name(res) if res.name else ' '%}
+{% set resource_size = h.tpsh_get_resource_size(res) %}
 
-  <div class="container-fluid">
-    <div class="row">
-      <div class="span8 resource-details-left">
-        <div class="row resource-title-container">
-        {% set rtitle=h.resource_display_name(res) if res.name else ' '%}
-          <div class="resource-title" title="{{ rtitle }}">
-        {% if res.name %}
-        <a href="{{ download }}">
-            {{ h.resource_display_name(res) }}
-        </a>
-        {% endif %}
-          </div>
+<li class="resource-item" data-id="{{ res.id }}">
+    <div class="resource-title-container">
+        <div class="resource-title" title="{{ rtitle }}">
+            {% if res.name %}
+            <a href="{{ download }}">
+                {{ h.resource_display_name(res) }}
+            </a>
+            {% endif %}
+            {% if resource_size %}
+            <p>Dateigröße: {{ resource_size }}</p>  
+            {% endif %}
+            {% set number_of_pages = res.get('number_of_pages') %}
+            {% if number_of_pages%}
+            <p>Seitenanzahl: {{ number_of_pages }}</p>   
+            {% endif %}
         </div>
+        <div class="resource-icons">
+            {% block resource_item_explore_links %}
+            <a href="{{ download }}" aria-label="{{ _('download file') }}">
+                <div aria-hidden="true" class="icon icon-download"></div>
+            </a>
+            {% if can_edit %}
+            <a href="{{ h.url_for(controller='package', action='resource_edit', id=pkg.name, resource_id=res.id) }}">
+                <div class="icon icon-edit"></div>
+            </a>
+            {% endif %}
+            {% endblock %}
+        </div>
+            {% if res.format %}
+            <a href="{{ download }}" >
+               <div class="dataformat-label resource-dataformat-label label" style='font-size:{{150/(res.format|length)}}px'>{{res.format}}</div>
+            </a>
+            {% endif %}
+    </div>
+</li>
+    
+        <!-- </div>
         <div class="row resource-description-container">
         </div>
       <div class="resource-icons">
-        {% block resource_item_explore_links %}
-        <a href="{{ download }}">
-          <div class="icon icon-download"></div>
+        <a href="{{ download }}" aria-label="{{ _('download file') }}">
+          <div aria-hidden="true" class="icon icon-download"></div>
         </a>
         {% if can_edit %}
         <a href="{{ h.url_for(controller='package', action='resource_edit', id=pkg.name, resource_id=res.id) }}">
           <div class="icon icon-edit"></div>
         </a>
         {% endif %}
-        {% endblock %}
+      </div>
+      <div>
+        
+        
       </div>
       </div>
-      {% if(res.format) %}
-        <a href="{{ download }}">
-          <div class="dataformat-label resource-dataformat-label label" style='font-size:{{150/(res.format|length)}}px'>{{res.format}}</div>
-        </a>
-      {% endif %}
     </div>
   </div>
 
-</li>
\ No newline at end of file
+</li> -->
diff --git a/ckanext/odsh/templates/page.html b/ckanext/odsh/templates/page.html
index 3cd01dece9eb8d86bdd41a8a5bb86f31af21909d..134079dd6ced8e52b3e01a7eec0fcef0a3db1a22 100644
--- a/ckanext/odsh/templates/page.html
+++ b/ckanext/odsh/templates/page.html
@@ -1,11 +1,21 @@
 {% ckan_extends %}
 
+{% block skip %}
+    <a class="skip-link" href="#content">
+        Zum Inhalt springen.
+    </a>
+{% endblock skip %}
 
 {%- block content %}
+<div class="blur-layer"></div>
 {% block maintag %}<div role="main">{% endblock %}
+
+{% if h.odsh_use_matomo() %}
 {% set matomo_url = h.odsh_tracking_url()%}
 {% set matomo_id = h.odsh_tracking_id()%}
 <noscript><p><img src="{{matomo_url}}?idsite={{matomo_id}}&rec=1" style="border:0;" alt="" /></p></noscript>
+{% endif %}
+
   <div id="content" class="container">
   {% if h.odsh_show_testbanner() %}
 <div id="testsystem">
diff --git a/ckanext/odsh/templates/snippets/datepicker.html b/ckanext/odsh/templates/snippets/datepicker.html
index 18ff3039faa64807512896b5e1977099c162b66c..1119e4e4882883ee6760984109351f31eb30e2f2 100644
--- a/ckanext/odsh/templates/snippets/datepicker.html
+++ b/ckanext/odsh/templates/snippets/datepicker.html
@@ -1,6 +1,17 @@
 
 {% set class = class or '' %}
 {% set placeholder = placeholder or '' %}
+{% set aria_label = aria_label or '' %}
 <input id="{{id}}" name="{{id}}" type="hidden" value="{{value}}" />
-<input pattern="\d{2}\.\d{2}\.\d{4}" autocomplete="off" id="datepicker_{{id}}" type="text" value="{{h.odsh_render_datetime(value, False)}}" placeholder="{{ placeholder }}"
-    class='{{class}}' data-module="odsh_datepicker" data-module-target='{{id}}'/>
\ No newline at end of file
+<input
+    aria-label="{{ aria_label }}" 
+    pattern="\d{2}\.\d{2}\.\d{4}" 
+    autocomplete="off" 
+    id="datepicker_{{ id }}" 
+    type="text" 
+    value="{{h.odsh_render_datetime(value, False)}}" 
+    placeholder="{{ placeholder }}"
+    class='{{ class }}' 
+    data-module="odsh_datepicker" 
+    data-module-target='{{ id }}'
+/>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/snippets/facet_list.html b/ckanext/odsh/templates/snippets/facet_list.html
index 9741ee167dcdeb210b0c8013c6c8bf5668eabc25..17531a4884925b89173a02aebf0c20109933daba 100644
--- a/ckanext/odsh/templates/snippets/facet_list.html
+++ b/ckanext/odsh/templates/snippets/facet_list.html
@@ -12,44 +12,66 @@
 <nav>
   {% set title = title or h.get_facet_title(name) %}
   <div class="nav-title">{{ title }}</div>
-    <ul class="{{ nav_class or 'unstyled nav nav-simple nav-facet' }}">
-        {% for item in items %}
-        {% set href = h.remove_url_param(name, item.name, extras=extras, alternative_url=alternative_url) if
-        item.active else h.add_url_param(new_params={name: item.name}, extras=extras, alternative_url=alternative_url)
-        %}
-        {% set label = label_function(item) if label_function else item.display_name %}
-        {% if title=='Open-Data-Eigenschaften'%}
-        {% set label = _(label)%}
-        {% endif%}
-        {% set count = count_label(item['count']) if count_label else ('%d' % item['count']) %}
-        {% set label_truncated = h.truncate(label, 25) if not label_function else label %}
-        <li class="{{ nav_item_class or 'nav-item' }}">
-	  <div class="facet_label">
-	    {# TODO: checkbox-id vereinheitlichen (code-duplikation) und sicher gegen Titel mit Leerzeichen machen! #}
-	    <input type="checkbox" alt="Checkbox" {% if item.active %} checked {% endif %} class="filter-checkbox" id="check-{{ title.lower() }}-{{ loop.index }}"/>
-	    <label class="mylabel" for="check-{{ title.lower() }}-{{ loop.index }}"></label>
-	    <a href="{{ href }}" title="{{ label if label != label_truncated else '' }}">
-                <span>{{ label}}</span>
+  <ul class="{{ nav_class or 'unstyled nav nav-simple nav-facet' }}">
+    {% for item in items %}
+      {% set href = h.remove_url_param(name, item.name, extras=extras, alternative_url=alternative_url) if
+          item.active else h.add_url_param(new_params={name: item.name}, extras=extras, alternative_url=alternative_url)
+      %}
+      {% set label = label_function(item) if label_function else item.display_name %}
+      {% if title=='Open-Data-Eigenschaften'%}
+      {% set label = _(label)%}
+      {% endif%}
+      {% set count = count_label(item['count']) if count_label else ('%d' % item['count']) %}
+      {% set label_truncated = h.truncate(label, 25) if not label_function else label %}
+      <li class="{{ nav_item_class or 'nav-item' }}">
+        <div class="facet_label">
+          {# TODO: checkbox-id vereinheitlichen (code-duplikation) und sicher gegen Titel mit Leerzeichen machen! #}
+          <input type="checkbox" 
+            {% if item.active %} checked {% endif %} 
+            class="filter-checkbox"
+            id="check-{{ title.lower() }}-{{ loop.index }}"
+            aria-hidden="true"
+          />
+          <span 
+            role="checkbox"
+            class="mylabel" 
+            for="check-{{ title.lower() }}-{{ loop.index }}" 
+            aria-labelledby="description-{{ title.lower() }}-{{ loop.index }}"
+            aria-checked={% if item.active %}"true"{% else %}"false"{% endif %}
+          >
+          </span>
+          {% if name=='groups' %}
+          <span class="group-icon-container" aria-hidden="true">
+            <img src="/base/images/icon_kat_{{item.name}}.svg" alt=""/>
+          </span>
+          {% endif %}
+          
+          <label class="odsh-visible-label" for="check-{{ title.lower() }}-{{ loop.index }}">
+            <a href="{{ href }}" title="{{ label if label != label_truncated else '' }}">
+              <span id="description-{{ title.lower() }}-{{ loop.index }}">{{ label }}</span>
             </a>
-	  </div>
-	  <div class="facet_count">
-            <span class="facet_count">{{ count }}</span>
-	  </div>
-        </li>
-        {% endfor %}
-    </ul>
+          </label>
+        </div>
+        <div class="facet_count">
+          <span class="facet_count">{{ count }}</span>
+        </div>
+      </li>
+    {% endfor %}
+  </ul>
 </nav>
 
 <div class="module-footer">
+    {% if not name=='groups' %}
     {% if h.get_param_int('_%s_limit' % name) %}
     {% if h.odsh_has_more_facets(name) %}
     <a href="{{ h.remove_url_param('_%s_limit' % name, replace=0, extras=extras, alternative_url=alternative_url) }}"
-        class="read-more">> {{ _('Show More') }}</a>
+    class="read-more">> {{ _('Show More') }}</a>
     {% endif %}
     {% else %}
     <a href="{{ h.remove_url_param('_%s_limit' % name, extras=extras, alternative_url=alternative_url) }}" class="read-more">> {{
         _('Show Less')}}</a>
     {% endif %}
+    {% endif %}
 </div>
 
 {% else %}
diff --git a/ckanext/odsh/templates/snippets/home_breadcrumb_item.html b/ckanext/odsh/templates/snippets/home_breadcrumb_item.html
index a14dcb74445f0a35d201232203c641343a0d676b..7631991a8f5af79049b34ee308827ade14c6a421 100644
--- a/ckanext/odsh/templates/snippets/home_breadcrumb_item.html
+++ b/ckanext/odsh/templates/snippets/home_breadcrumb_item.html
@@ -1,9 +1,7 @@
 {# Used to insert the home icon into a breadcrumb #}
 <li class="home">
     <a href="{{ h.url_for('home') }}">
-        <img class='icon-home' src='/base/images/Icon-Home.png' alt='Ikon Home' />
-        <span> 
-            {{_('Home') }}
-        </span>
+        <img class='icon-home' src='/base/images/Icon-Home.png' alt='home icon' />
+        <span> {{_('Home') }}</span>
     </a>
 </li>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/snippets/organization.html b/ckanext/odsh/templates/snippets/organization.html
index bbd506d3b94d35b1cbe17f2c40452801a0a77755..df7bda0041df1b7cc4f988683ee0d9dd98ae4bc7 100644
--- a/ckanext/odsh/templates/snippets/organization.html
+++ b/ckanext/odsh/templates/snippets/organization.html
@@ -15,7 +15,6 @@ Example:
 #}
 
 {% set truncate = truncate or 0 %}
-{% set url = h.url_for(controller='organization', action='read', id=organization.name) %}
 
 {% block info %}
 <div class="module module-narrow module-shallow context-info">
@@ -25,17 +24,61 @@ Example:
         [{{ _('Deleted') }}]
         {% endif %}
     </h1>
-    {% endblock %}
-    <section class="module-content">
+    {% endblock heading%}
+    <section id="section-org" class="module-content">
         {% block inner %}
         {% block image %}
         <div class="image">
-            <a href="{{ url }}">
-                <img src="{{ organization.image_display_url or h.url_for_static('/base/images/placeholder-organization.png') }}"
-                    width="200" alt="{{ organization.name }}" />
-            </a>
+            <img src="{{ organization.image_display_url or h.url_for_static('/base/images/placeholder-organization.png') }}"
+                width="200" alt="{{ organization.name }}" />
         </div>
-        {% endblock %}
+        
+        <div class="information-organisation">
+            {% set address = h.tpsh_get_address_org(organization) %}
+            {% set street = address.get('street') %}
+            {% set location = address.get('location') %}
+            {% set mail = address.get('mail') %}
+            {% set telephone = address.get('telephone') %}
+            {% set web = address.get('web') %}
+            
+            {% if person %}
+            <p>   
+                {{ person }}  
+            </p>
+            {% endif %} {# person #}
+
+            {% if street and location %}
+            <p>{{ street }}</p>
+            <p>{{ location }}</p>
+            {% endif %} {# street and location #}
+                
+            {% if mail %}
+            {% if package %}
+            {% set package_name = package.get('name') %}
+            {% set betreff = "Transparenzportal Dokument: "+ package_name%}
+            {% set body_mail = h.tpsh_get_body_mail(organization, package)   %}
+            {% else %}
+            {% set betreff = "Transparenzportal" %}
+            {% endif %} {# package #}
+            <p>
+                <a href="mailto:{{ mail }}?subject={{betreff}}&body={{body_mail}}Viele Grüße">{{ mail }}</a>
+            </p>
+            {% endif %} {# mail #}
+
+            {% if telephone %}
+            <p class="phone">
+                {{ telephone }}
+            </p>
+            {% endif %} {# telephone #}
+            
+            {% if web %}
+            <p>
+                <a href="{{address.web}}">{{ address.web }}</a>
+            </p>
+            {% endif %} {# web #}
+        </div>
+        {% endblock image%}
+
         {% if not hide_description %}
         {% block description %}
         {% if organization.description %}
@@ -46,7 +89,7 @@ Example:
         {% else %}
         <p class="empty">{{ _('There is no description for this organization') }}</p>
         {% endif %}
-        {% endblock %}
+        {% endblock description %}
         {% endif %}
         {% if show_nums %}
         {% block nums %}
@@ -56,18 +99,18 @@ Example:
                 <dd>{{ h.SI_number_span(organization.num_followers) }}</dd>
             </dl>
             <dl>
-                <dt>{{ _('Datasets') }}</dt>
+                <dt>{{ _('Documents') }}</dt>
                 <dd>{{ h.SI_number_span(organization.package_count) }}</dd>
             </dl>
         </div>
-        {% endblock %}
+        {% endblock nums%}
         {% block follow %}
         <div class="follow_button">
             {{ h.follow_button('group', organization.id) }}
         </div>
-        {% endblock %}
+        {% endblock follow %}
         {% endif %}
-        {% endblock %}
+        {% endblock inner %}
     </section>
 </div>
 {% endblock %}
\ No newline at end of file
diff --git a/ckanext/odsh/templates/snippets/package_item.html b/ckanext/odsh/templates/snippets/package_item.html
index d1a84c3e442076b49baef7108d0a385d6f9e613c..b0918d3e68682688b5e93514aa556d969b320f13 100644
--- a/ckanext/odsh/templates/snippets/package_item.html
+++ b/ckanext/odsh/templates/snippets/package_item.html
@@ -14,82 +14,104 @@ Example:
 
 #}
 {% set truncate = truncate or 180 %}
-{% set truncate_title = truncate_title or 80 %}
+{% set truncate_title = truncate_title or 180 %}
 {% set title = package.title or package.name %}
 {% set notes = h.markdown_extract(package.notes, extract_length=truncate) %}
 {% set license_title =package.license_title if package.license_title else '-'%}
 {% set licenseAttributionByText = h.odsh_extract_value_from_extras(package.extras,'licenseAttributionByText')%}
 {% set license_name=' ('+licenseAttributionByText +')' if licenseAttributionByText else ''%}
 {% set license = license_title + license_name %}
-{% set temporal_start = h.odsh_extract_value_from_extras(package.extras,'temporal_start') %}
-{% set start=h.odsh_render_datetime(temporal_start) if temporal_start else ''%}
-{% set temporal_end = h.odsh_extract_value_from_extras(package.extras,'temporal_end') %}
-{% set end=h.odsh_render_datetime(temporal_end) if temporal_end else ''%}
-{% set timerange = start + '-' + end%}
 {% set org = package.organization.title or package.organization.name or '-' %}
 {% set stars = h.odsh_openness_score_dataset_html(package) %}
 {% set access_count=(package.tracking_summary.total if package.tracking_summary) or '-' %}
-{% set timerange_label ='Zeitraum' %}
-{% set access_count_label ='Aufrufe' %}
 {% set issued_extra = h.odsh_extract_value_from_extras(package.extras,'issued') %}
-{% set issued = h.odsh_render_datetime(issued_extra) if issued_extra else h.odsh_render_datetime(package.metadata_created)%} 
-{% set categories = package.groups|map(attribute='display_name')|join(', ') if package.groups else '-' %}
+{% set issued = h.odsh_render_datetime(issued_extra) if issued_extra else h.odsh_render_datetime(package.metadata_created)%}
+{% set daterange = h.tpsh_get_daterange_prettified(package) %}
+{% set language_of_package = h.tpsh_get_language_of_package(package) %}
+{% set language_icon = h.get_language_icon(package) %}
+{% set thumbnail = package.get('thumbnail') %}
 
 {% block package_item %}
-<div class="container-fluid odsh-dataset-item">
-  {% block content %}
-  <div class="dataset-content">
-    {% block heading %}
-    <p>{{org}}</p>
-    <h3 class="dataset-heading">
-      {% block heading_private %}
-      {% if package.is_new %}
-        <span class='label new-dataset-label'>{{ _('NEW') }}</span>
-      {% endif %}
-      {% if package.private %}
-      <span class="dataset-private label label-inverse">
-        <i class="fa fa-lock"></i>
-        {{ _('Private') }}
-      </span>
-      {% endif %}
-      {% endblock %}
-      {% block heading_title %}
-      {{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name),title=_('View {organization_name}').format(organization_name=title))
-      }}
-      {% endblock %}
-      {% block heading_meta %}
-      {% if package.get('state', '').startswith('draft') %}
-      <span class="label label-info">{{ _('Draft') }}</span>
-      {% elif package.get('state', '').startswith('deleted') %}
-      <span class="label label-important">{{ _('Deleted') }}</span>
-      {% endif %}
-      {{ h.popular('recent views', package.tracking_summary.recent, min=10) if package.tracking_summary }}
-      </span>
-      {% endblock %}
-    </h3>
-    {% endblock %}
-    {% block banner %}
-    {% if banner %}
-    <span class="banner">{{ _('Popular') }}</span>
-    {% endif %}
-    {% endblock %}
-    {% block notes %}
+<div class="odsh-dataset-item">
+    {% block content %}
+    <div class="dataset-content">
+        {% block heading %}
+        {%if daterange %}
+        <div class='package-info-pill'>
+            {{ daterange }}
+        </div>
+        {% endif %}
+        {% set spatial_text=h.odsh_get_spatial_text(package)%}
+        {% if spatial_text %}
+        <div class='package-info-pill'>
+            {{ spatial_text }}
+        </div>
+        {% endif %}
+        {% if language_of_package != 'Deutsch' and language_of_package %}
+        <div class='package-info-pill'>
+            <img src={{ language_icon }} />
+            {{ language_of_package }}
+        </div>
+        {% endif %}
+        <p>{{ org }}</p>
+        <h3 class="dataset-heading">
+            {% block heading_private %}
+            {% if package.is_new %}
+            <span class='label new-dataset-label'>{{ _('NEW') }}</span>
+            {% endif %}
+            {% if package.private %}
+            <span class="dataset-private label label-inverse">
+                <i class="fa fa-lock"></i>
+                {{ _('Private') }}
+            </span>
+            {% endif %}
+            {% endblock heading_private %}
+            {% block heading_title %}
+            {{ h.link_to(h.truncate(title, truncate_title), h.url_for(controller='package', action='read', id=package.name),title=_('View {organization_name}').format(organization_name=title))}}
+            {% endblock heading_title %}
+            {% block heading_meta %}
+            {% if package.get('state', '').startswith('draft') %}
+            <span class="label label-info">{{ _('Draft') }}</span>
+            {% elif package.get('state', '').startswith('deleted') %}
+            <span class="label label-important">{{ _('Deleted') }}</span>
+            {% endif %}
+            {{ h.popular('recent views', package.tracking_summary.recent, min=10) if package.tracking_summary }}
+            {% endblock heading_meta %}
+        </h3>
+        {% endblock heading%}
+        {% block banner %}
+        {% if banner %}
+        <span class="banner">{{ _('Popular') }}</span>
+        {% endif %}
+        {% endblock banner%}
 
-    {%if start or end %}
-    <div class='package-info-pill'>
-        {{timerange}}
-    </div>
-    {% endif %}
-    {% set spatial_text=h.odsh_get_spatial_text(package)%}
-    {%if spatial_text %}
-    <div class='package-info-pill'>
-        {{ spatial_text }}
+        {% block notes %}
+        {% if package.groups|length %}   
+        <p class='package-info-category'>
+            <span class='category-header'>
+                {% trans category_count=package.groups|length %}
+                category:
+                {% pluralize %}
+                categories:
+                {% endtrans %}
+            </span>
+            {% for category in package.groups %}
+            <span class='category-with-icon'>
+                <span class='category-icon-container' aria-hidden='true'>
+                    <img src="/base/images/icon_kat_{{category.name}}.svg" alt=""/>
+                </span>
+                <span class="category-name">
+                    {{ category.display_name }}
+                </span>
+            </span>
+            {% endfor %}
+        </p>
+        {% endif %}
+        {% endblock notes %}
     </div>
-    {% endif %}
-    <p class='package-info-categorie'>{{ _('Kategorie') }}: {{ categories}} </p>
-    {% endblock %}
-  </div>
-  <div class='dataset-spacer'></div>
+
+    <div class='dataset-spacer'></div>
+
   <div class="dataset-meta">
     {% block resources %}
     {% block resources_outer %}
@@ -118,6 +140,7 @@ Example:
     {% endblock %}
     {% endblock %}
   </div>
-  {% endblock %}
+
+    {% endblock content %}
 </div>
-{% endblock %}
+{% endblock package_item %}
diff --git a/ckanext/odsh/templates/snippets/search_box.html b/ckanext/odsh/templates/snippets/search_box.html
index 7599b722123d70f198501106356c5fdb49722c51..e5831c99d0e756541209e5fe61aa331bc961020e 100644
--- a/ckanext/odsh/templates/snippets/search_box.html
+++ b/ckanext/odsh/templates/snippets/search_box.html
@@ -1,8 +1,16 @@
 <div class='search-box-container'>
     <div class='search-box'>
-            <div class="field">
-                <input id="field-sitewide-search" class="search" type="text" value="{{c.q}}" name="q" placeholder="{{ _('Search dataset') }}" />
-                <button class="btn-search" type="submit">
+            <div class="field search-field">
+                <input 
+                    aria-label="{{ _('enter search query for datasets') }}"
+                    id="field-sitewide-search" 
+                    class="search" 
+                    type="text" 
+                    value="{{c.q}}" 
+                    name="q" 
+                    placeholder="{{ _('Search dataset') }}" 
+                />
+                <button class="btn-search" type="submit" aria-label="{{ _('Search dataset') }}"></button>
             </div>
     </div>
 </div>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/snippets/search_form.html b/ckanext/odsh/templates/snippets/search_form.html
index 52b85f3da7aa1625a11f32654bb1b700afe82f93..9e1ea9ed0bb4d3b4941c5f72d83dcbeca6e9521a 100644
--- a/ckanext/odsh/templates/snippets/search_form.html
+++ b/ckanext/odsh/templates/snippets/search_form.html
@@ -12,7 +12,11 @@
           (_('Name Ascending'), 'title_string asc'),
           (_('Name Descending'), 'title_string desc'),
           (_('Issued Ascending'), 'extras_issued asc'),
-          (_('Issued Descending'), 'extras_issued desc'),
+          (_('Issued Descending'), 'extras_issued desc'),          
+          (_('Start Date Ascending'), 'temporal_start asc'),
+          (_('Start Date Descending'), 'temporal_start desc'),
+          (_('End Date Ascending'), 'temporal_end asc'),
+          (_('End Date Descending'), 'temporal_end desc'),
           (_('Popular'), 'views_recent desc') if g.tracking_enabled else (false, false) ]
         %}
 {% endif %}
@@ -31,10 +35,27 @@
     {%- endif %}
     {% endblock %}
 
+    {% block search_title %}
+    {% if not error %}
+    {% if force_title %}
+    <h2>{{force_title }}</h2>
+    {% else %}
+    <h2>{% snippet 'snippets/search_result_text.html', query=query, count=count, type=type %}</h2>
+    {% if type == 'dataset' %}
+    <a aria-label="{{ _('rss feeds') }}" href={{h.remove_url_param([''], controller='feed', action='custom') }}> 
+        <i aria-hidden="true" class="fa fa-medium fa-rss"></i>
+    </a>
+    {%- endif -%}
+    {% endif %}
+    {% else %}
+    <h2>Error</h2>
+    {% endif %}
+    {% endblock %}
+
     {% block search_sortby %}
     {% if sorting %}
     <div class="form-select control-group control-order-by">
-        <select id="field-order-by" name="sort">
+        <select id="field-order-by" name="sort" aria-label="{{sorting_label_prefix}}&nbsp;&hellip;">
             {% for label, value in sorting %}
             {% if label and value %}
             <option value="{{ value }}" {% if sorting_selected==value %} selected="selected" {% endif %}>
@@ -49,18 +70,6 @@
     {% endif %}
     {% endblock %}
 
-    {% block search_title %}
-    {% if not error %}
-    {% if force_title %}
-    <h2>{{force_title }}</h2>
-    {% else %}
-    <h2>{% snippet 'snippets/search_result_text.html', query=query, count=count, type=type %}</h2>
-    {% endif %}
-    {% else %}
-    <h2>Error</h2>
-    {% endif %}
-    {% endblock %}
-
     {% block search_facets %}
     {% if facets %}
     <p class="filter-list">
@@ -78,12 +87,19 @@
                 {#{{_(value)}}#}
                 {%- endif %}
              {%- endif %}
-                <a href="{{ facets.remove_field(field, value) }}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ facets.remove_field(field, value) }}" 
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                    <i class="fa fa-times" aria-hidden="true"></i>
+                </a>
         </span>
         {% endfor %}
         {% endfor %}
     </p>
-    <a class="show-filters btn">{{ _('Filter Results') }}</a>
+    <!-- <a class="show-filters btn">{{ _('Filter Results') }}</a> -->
     {% else%}
     {% if always_show_filter_list%}
     <p class="filter-list"></p>
@@ -99,26 +115,54 @@
             {% if start_date and not start_error%}
             <span class="filtered pill">
                 {{_('daterange')}}: {{_('from')}} {{ start_date}}
-                <a href="{{ h.remove_url_param('ext_startdate') }}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ h.remove_url_param('ext_startdate') }}" 
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                <i class="fa fa-times" aria-hidden="true"></i>
+            </a>
             </span>
             {% endif %}
             {% if start_error %}
             <span class="filtered pill error">
                 {{_('daterange')}}: {{_('wrong_start_date_for_search')}}
-                <a href="{{ h.remove_url_param('ext_startdate') }}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ h.remove_url_param('ext_startdate') }}"
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                    <i class="fa fa-times" aria-hidden="true"></i>
+                </a>
             </span>
             {% endif %}
 
             {% if end_date and not end_error%}
             <span class="filtered pill">
                 {{_('daterange')}}: {{_('to')}} {{ end_date}}
-                <a href="{{ h.remove_url_param('ext_enddate') }}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ h.remove_url_param('ext_enddate') }}" 
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                <i class="fa fa-times" aria-hidden="true"></i>
+            </a>
             </span>
             {% endif %}
             {% if end_error %}
             <span class="filtered pill error">
                 {{_('daterange')}}: {{_('wrong_end_date_for_search')}}
-                <a href="{{ h.remove_url_param('ext_enddate') }}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ h.remove_url_param('ext_enddate') }}" 
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                    <i class="fa fa-times" aria-hidden="true"></i>
+                </a>
             </span>
             {% endif %}
         </p>
@@ -132,7 +176,14 @@
         <p class="filter-list">
             <span class="filtered pill">
                 {{_('map search active')}}
-                <a href="{{ h.remove_url_param(['ext_bbox','ext_prev_extent', 'ext_location'])}}" class="remove" title="{{ _('Remove') }}"><i class="fa fa-times"></i></a>
+                <a 
+                    href="{{ h.remove_url_param(['ext_bbox','ext_prev_extent', 'ext_location'])}}" 
+                    class="remove"
+                    aria-label="{{ _('Remove filters') }}" 
+                    title="{{ _('Remove filters') }}"
+                >
+                <i class="fa fa-times" aria-hidden="true"></i>
+            </a>
             </span>
         </p>
         {% endif %}
diff --git a/ckanext/odsh/templates/snippets/search_result_text.html b/ckanext/odsh/templates/snippets/search_result_text.html
index 56cf8470d4d6db7b993132f30f3fa32ebdff231d..cd44abe63cd5f3be1caa86928cedc31bbb0dd5e1 100644
--- a/ckanext/odsh/templates/snippets/search_result_text.html
+++ b/ckanext/odsh/templates/snippets/search_result_text.html
@@ -45,7 +45,4 @@ Example:
 {%- else -%}
 {{ text_no_query_none }}
 {%- endif -%}
-{%- endif -%}
-{% if type == 'dataset' %}
-<a href={{h.remove_url_param([''], controller='feed', action='custom' )}}> <i class="fa fa-medium fa-rss"></i></a>
 {%- endif -%}
\ No newline at end of file
diff --git a/ckanext/odsh/templates/user/edit_user_form.html b/ckanext/odsh/templates/user/edit_user_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..9ceda7c7afc8e093149537317040f080d943afef
--- /dev/null
+++ b/ckanext/odsh/templates/user/edit_user_form.html
@@ -0,0 +1,59 @@
+{% import 'macros/form.html' as form %}
+{% resource 'odsh/tpsh_validate_password.js' %}
+
+
+<form id="user-edit-form" class="dataset-form form-horizontal" method="post" action="{{ action }}">
+  {{ form.errors(error_summary) }}
+
+  <fieldset>
+    <legend>{{ _('Change details') }}</legend>
+    {{ form.input('name', label=_('Username'), id='field-username', value=data.name, error=errors.name, classes=['control-medium'], is_required=true) }}
+
+    {{ form.input('fullname', label=_('Full name'), id='field-fullname', value=data.fullname, error=errors.fullname, placeholder=_('eg. Joe Bloggs'), classes=['control-medium']) }}
+
+    {{ form.input('email', label=_('Email'), id='field-email', type='email', value=data.email, error=errors.email, placeholder=_('eg. joe@example.com'), classes=['control-medium'], is_required=true) }}
+
+    {{ form.markdown('about', label=_('About'), id='field-about', value=data.about, error=errors.about, placeholder=_('A little information about yourself')) }}
+
+    {% if c.show_email_notifications %}
+      {% call form.checkbox('activity_streams_email_notifications', label=_('Subscribe to notification emails'), id='field-activity-streams-email-notifications', value=True, checked=c.userobj.activity_streams_email_notifications) %}
+      {% set helper_text = _("You will receive notification emails from {site_title}, e.g. when you have new activities on your dashboard."|string) %}
+      {{ form.info(helper_text.format(site_title=g.site_title), classes=['info-help-tight']) }}
+      {% endcall %}
+    {% endif %}
+
+  </fieldset>
+
+  <fieldset>
+    <legend>{{ _('Change password') }}</legend>
+    {{ form.input('old_password',
+                  type='password',
+                  label=_('Sysadmin Password') if c.is_sysadmin else _('Old Password'),
+                  id='field-password',
+                  value=data.oldpassword,
+                  error=errors.oldpassword,
+                  classes=['control-medium'],
+                  attrs={'autocomplete': 'off'}
+                  ) }}
+
+    {{ form.input(
+        'password1', type='password', label=_('Password'), id='field-password', value=data.password1, error=errors.password1, classes=['control-medium'], attrs={'autocomplete': 'off', 'data-module': 'tpsh_validate_password'} ) }}
+
+    {{ form.input('password2', type='password', label=_('Confirm Password'), id='field-password-confirm', value=data.password2, error=errors.password2, classes=['control-medium'], attrs={'autocomplete': 'off'}) }}
+  </fieldset>
+
+  <div class="form-actions">
+    {% block delete_button %}
+      {% if h.check_access('user_delete', {'id': data.id})  %}
+        <a class="btn btn-danger pull-left" href="{% url_for controller='user', action='delete', id=data.id %}" data-module="confirm-action" data-module-content="{{ _('Are you sure you want to delete this User?') }}">{% block delete_button_text %}{{ _('Delete') }}{% endblock %}</a>
+      {% endif %}
+    {% endblock %}
+    {% block generate_button %}
+      {% if h.check_access('user_generate_apikey', {'id': data.id})  %}
+        <a class="btn btn-warning" href="{% url_for controller='user', action='generate_apikey', id=data.id %}" data-module="confirm-action" data-module-content="{{ _('Are you sure you want to regenerate the API key?') }}">{% block generate_button_text %}{{ _('Regenerate API Key') }}{% endblock %}</a>
+      {% endif %}
+    {% endblock %}
+    {{ form.required_message() }}
+    <button class="btn btn-primary" type="submit" name="save">{{ _('Update Profile') }}</button>
+  </div>
+</form>
\ No newline at end of file
diff --git a/ckanext/odsh/tests/test_validation.py b/ckanext/odsh/tests/test_validation.py
index d631545ab34a2a0cd10094ab55ff22f7904970f6..b2edc40b15f6f2e6446a709c34706bb63ac3a3a2 100644
--- a/ckanext/odsh/tests/test_validation.py
+++ b/ckanext/odsh/tests/test_validation.py
@@ -110,3 +110,25 @@ def test_validate_licenseAttributionByText():
             ('extras', 0, 'key'): 'licenseAttributionByText',
             ('extras', 0, 'value'): ''}
     validate_licenseAttributionByText('key', data, {}, None)
+
+
+def test_convert_subjectID_to_subjectText():
+    # arrange
+    data = {('extras', 0, 'subject'): 'subject',
+            ('extras', 0, 'subject'): 'Test_id'}
+    # act
+    convert_subjectID_to_subjectText('key', data, {}, None):
+    # assert
+    assert data[('extras', 1, 'key')] == 'subject_text'
+    assert data[('extras', 1, 'value')] == 'Test_subject'
+
+
+def test_exception_convert_subjectID_to_subjectText():
+    # arrange
+    data = {('extras', 0, 'subject'): 'subject',
+            ('extras', 0, 'subject'): 'Nicht_Vorhanden'}
+    # act
+    convert_subjectID_to_subjectText('key', data, {}, None):
+    #assert
+    assert data[('extras', 1, 'key')] == 'subject_text'
+    assert data[('extras', 1, 'value')] == ''
diff --git a/ckanext/odsh/tests_tpsh/__init__.py b/ckanext/odsh/tests_tpsh/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ckanext/odsh/tests_tpsh/resources/__init__.py b/ckanext/odsh/tests_tpsh/resources/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ckanext/odsh/tests_tpsh/resources/collection1.rdf b/ckanext/odsh/tests_tpsh/resources/collection1.rdf
new file mode 100644
index 0000000000000000000000000000000000000000..8ffd258536049afa2bd76a6a10196bf05b992386
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/resources/collection1.rdf
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rdf:RDF xmlns:dcatde="http://dcat-ap.de/def/dcatde/1_0/" xmlns:dcat="http://www.w3.org/ns/dcat#"
+xmlns:dct="http://purl.org/dc/terms/" xmlns:foaf="http://xmlns.com/foaf/0.1/"
+xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:schema="http://schema.org/">
+  <dcat:Catalog rdf:about="https://data.some.org/catalog">
+
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte">
+        <dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+	<dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201704" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201703" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201702" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201701" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201612" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2017" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2016" />
+        <dct:hasVersion rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2015" />
+      </dcat:Dataset>
+    </dcat:dataset>
+    
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201704">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201704/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201704.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-03-20</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-04-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-04-30</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201703">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201703/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201703.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-02-20</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-03-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-03-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201702">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201702/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201702.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-01-16</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-02-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-02-28</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201701">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201701/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201701.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-12-12</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-01-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-01-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201612">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201612/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201612.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-11-21</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2017">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2017/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_Antrag_Jahr_2017.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-12-31</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-01-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-12-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2016">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2016/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_Antrag_Jahr_2016.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-31</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-01-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2015">
+        <dct:isVersionOf rdf:resource="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte" />
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2015/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_Antrag_Jahr_2015.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-01-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+    <dcat:dataset>
+      <dcat:Dataset rdf:about="http://opendata.schleswig-holstein.de/dataset/Test_nicht_in_Collection">
+        <dct:title>SER Statistik anerkannte Versorgungsberechtigte</dct:title>
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_Antrag_Jahr_2015/resource">
+            <dcat:accessURL rdf:resource="http://185.223.104.6/data/lasd/LAsDSH_SER_Statistik_Antrag_Jahr_2015.pdf" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+            <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+            <dct:format rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/SOCI" />
+        <dct:description>Statistik der Versorgung von rentenberechtigten Kriegsopfern und gleichgestellten Personen nach
+        Personenkreis und MdE innerhalb Schleswig-Holsteins</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</dct:issued>
+        <dct:license rdf:resource="http://dcat-ap.de/def/licenses/dl-by-de/2.0" />
+        <dcatde:licenseAttributionByText>Landesamt für soziale Dienste Schleswig-Holstein</dcatde:licenseAttributionByText>
+        <dct:publisher>
+          <foaf:Organization rdf:about="http://opendata.schleswig-holstein.de/lasd" />
+        </dct:publisher>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-01-01</schema:startDate>
+            <schema:endDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</schema:endDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+        <dcat:keyword>Soziales Entschädigungsrecht</dcat:keyword>
+        <dcat:keyword>Kriegsopfer</dcat:keyword>
+        <dcat:keyword>Beschädigte</dcat:keyword>
+        <dcat:keyword>Witwen</dcat:keyword>
+        <dcat:keyword>Waisen</dcat:keyword>
+        <dcat:keyword>BVG</dcat:keyword>
+        <dcat:keyword>SVG</dcat:keyword>
+        <dcat:keyword>ZDG</dcat:keyword>
+        <dcat:keyword>OEG</dcat:keyword>
+        <dcat:keyword>IfSG</dcat:keyword>
+        <dcat:keyword>HHG</dcat:keyword>
+        <dcat:keyword>SER</dcat:keyword>
+        <dcat:keyword>Statistik</dcat:keyword>
+        <dcat:keyword>Versorgungsberechtigte</dcat:keyword>
+      </dcat:Dataset>
+    </dcat:dataset>
+  </dcat:Catalog>
+</rdf:RDF>
diff --git a/ckanext/odsh/tests_tpsh/resources/org_dicts.py b/ckanext/odsh/tests_tpsh/resources/org_dicts.py
new file mode 100644
index 0000000000000000000000000000000000000000..5948d7658b0e626459a3cef62392c124f8b3f723
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/resources/org_dicts.py
@@ -0,0 +1,87 @@
+# encoding: utf-8
+
+organization_with_address = {
+            'approval_status': u'approved',
+            'created': '2019-07-29T08:11:32.697127',
+            'description': u'',
+            'display_name': u'Test-Organisation',
+            'extras': [
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'b31c1b27-8c4e-46d7-b533-30bc4cc93d0e',
+                    'key': u'location',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'Müllerdorf'
+                },
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'7302c660-871e-44f0-92f4-18bc5b8953ec',
+                    'key': u'mail',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'mueller@mueller.de'
+                },
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'6d3e02ba-b721-4362-92f3-985ed50f6c42',
+                    'key': u'person',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'Michael Müller'
+                },
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'baf92ac2-21e2-49f5-96f8-e48c7fd50cf0',
+                    'key': u'street',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'Müllergasse 10'
+                },
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'd5ce2972-487e-444b-95ba-c6a8db238c67',
+                    'key': u'telephone',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'040 123456'
+                },
+                {
+                    'group_id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+                    'id': u'00d1d308-6718-4d90-81ae-25ee3f0b76f7',
+                    'key': u'web',
+                    'revision_id': u'5e9677a3-ddab-4306-850f-cfd4fad3d676',
+                    'state': u'active',
+                    'value': u'mueller.de'
+                }
+            ],
+            'groups': [],
+            'id': u'63c87e74-60a9-4a4a-a980-d7983c47f92b',
+            'image_display_url': u'',
+            'image_url': u'',
+            'is_organization': True,
+            'name': u'test-organisation',
+            'num_followers': 0L,
+            'package_count': 51,
+            'revision_id': u'3040af6c-d3f6-462d-b48a-329d63e17a28',
+            'state': u'active',
+            'tags': [],
+            'title': u'Test-Organisation',
+            'type': u'organization',
+            'users': [{
+                'about': u'',
+                'activity_streams_email_notifications': False,
+                'capacity': u'admin',
+                'created': '2019-06-05T06:19:17.576291',
+                'display_name': u'ckanuser',
+                'email_hash': 'b28744113bd1ae8dc4f6e17aefe3bd9b',
+                'fullname': u'',
+                'id': u'ff8d002d-3908-45e5-ba7b-445381860957',
+                'name': u'ckanuser',
+                'number_created_packages': 13L,
+                'number_of_edits': 456L,
+                'openid': None,
+                'state': u'active',
+                'sysadmin': True
+            }]
+        }
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/resources/subject_mapping_for_tests.json b/ckanext/odsh/tests_tpsh/resources/subject_mapping_for_tests.json
new file mode 100644
index 0000000000000000000000000000000000000000..2e8bd946d9237ed177f8d3759defc4732d2f8ddf
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/resources/subject_mapping_for_tests.json
@@ -0,0 +1,26 @@
+{
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Verwaltungsvorschrift" : "Verwaltungsvorschrift",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Organisationsplan" : "Organisationsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Geschaeftsverteilungsplan" : "Geschäftsverteilungsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Aktenplan" : "Aktenplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Richtlinie" : "Richtlinie und Runderlass",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Statistik" : "amtliche Statistik",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Taetigkeitsbericht" : "Tätigkeitsbericht",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Broschuere" : "Broschüre",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Gutachten" : "Gutachten",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Studie" : "Studie",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Haushaltsplan" : "Haushaltsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Stellenplan" : "Stellenplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Wirtschaftsplan" : "Wirtschaftsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#ZuwendungAnPerson" : "Übersicht über Zuwendungen an juristische Personen des Privatrechts",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#ZuwendungAnLand" : "Übersicht über Zuwendungen an das Land Schleswig-Holstein",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#IZGAntwort" : "IZG/GvgV-Auskunft",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Gerichtsurteil" : "Gerichtsurteil",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#GesetzvorlageLandtag" : "Gesetzesvorlage an den Landtag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#MitteilungLandtag" : "Mitteilung an den Landtag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Unternehmensdaten" : "wesentliche Unternehmensdaten von Beteiligungen des Landes",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#VergütungsOG" : "jährliche Vergütungen nach dem VergütungsOG",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Vertrag" : "Vertrag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#sonstiges" : "sonstiges"
+}
+    
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/resources/test.pdf b/ckanext/odsh/tests_tpsh/resources/test.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..10451cf0fba2fea7ac87ae52cc9b350b48c67198
Binary files /dev/null and b/ckanext/odsh/tests_tpsh/resources/test.pdf differ
diff --git a/ckanext/odsh/tests_tpsh/resources/transparenz.rdf b/ckanext/odsh/tests_tpsh/resources/transparenz.rdf
new file mode 100644
index 0000000000000000000000000000000000000000..ea4fb5e3c229d3e01feb3e4bb562f644cb8017da
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/resources/transparenz.rdf
@@ -0,0 +1,1145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rdf:RDF xmlns:dcatde="http://dcat-ap.de/def/dcatde/1_0/" xmlns:dcat="http://www.w3.org/ns/dcat#" xmlns:dct="http://purl.org/dc/terms/"
+xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:schema="http://schema.org/">
+  <dcat:Catalog rdf:about="https://transparenz.schleswig-holstein.de/catalog">
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/9f9ae60bb0d8985e10e9ab8aa6a7ca34">
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2017)</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/af_blano_fortschritt2017.pdf?__blob=publicationFile&amp;v=5">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/af_blano_fortschritt2017.pdf?__blob=publicationFile&amp;v=5" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2017)</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-05-02</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-05-02</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/ff612d0f165d46f3091f58e1ef56a2ec">
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2016)</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ae_blano_fortschritt2016.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ae_blano_fortschritt2016.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2016)</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-04-10</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-04-10</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/3a0d0674120fbf06b5cb8737124e3fd0">
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2015)</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ad_blano_fortschritt2015.pdf?__blob=publicationFile&amp;v=8">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ad_blano_fortschritt2015.pdf?__blob=publicationFile&amp;v=8" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2015)</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-07-10</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-07-10</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/b5cd3f303f594ecde96e1017e953b688">
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2014)</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ad_blano_fortschritt2014.pdf?__blob=publicationFile&amp;v=4">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ad_blano_fortschritt2014.pdf?__blob=publicationFile&amp;v=4" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2014)</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-07-17</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-07-17</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/cd606b042789723a2b6d61cb31c46c39">
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2013)</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ac_blano_fortschritt2013.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/UXO/Berichte/PDF/Berichte/ac_blano_fortschritt2013.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt (Jahr 2013)</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2014-07-26</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2014-07-26</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/04640ac19a21450984d2af7c402d6aa0">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2006 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2006.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2006.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2006 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/86fe10eb6578e940d7df8e3d6da6520d">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2007 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2007.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2007.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2007 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/b0024265f96b9de5a590541f5e0aec91">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2008 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2008.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2008.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2008 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/ccb65ee5047e3c9cc67384b513400246">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2009 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2009.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2009.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2009 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/ae2a3cffda84388365bc87711ed4af47">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2010 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2010.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2010.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2010 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/91a479991245f208dd6f8ba82411a570">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2011 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2011.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2011.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2011 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/1ee93d311ae6078dc11655c2ca8865b5">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2012 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2012.pdf?__blob=publicationFile&amp;v=6">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2012.pdf?__blob=publicationFile&amp;v=6" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2012 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f5123967a8d0d80ff135342ce41a09bb">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2013 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2013.pdf?__blob=publicationFile&amp;v=5">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2013.pdf?__blob=publicationFile&amp;v=5" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2013 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-28</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/05199f38b6234e794f79ad3726957a3e">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2014/15 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2015.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2015.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2014/15 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-07-14</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-07-14</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/ffef477b7ebb1447d869b33c79cac8e2">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2016/17 - Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2017.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2017.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2016/17 - Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-08-01</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-08-01</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/a1fea922aa7d9f7a924784615301da83">
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein 2015/16 – Bericht</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2016.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/VIII/Service/Broschueren/Broschueren_VIII/Gesundheit/schuleinguntber2016.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein 2015/16 – Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-11-27</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-11-27</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/423e1ea7e98b492aebc0ca5108c7b36d">
+        <dct:title>Jahresbericht 2017 zur biologischen Vielfalt - Jagd und Artenschutz</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/7ee94f73beb43faf4099208b4e55734b" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/Jahresbericht_Zur_biologischen_Vielfalt_2017.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/Jahresbericht_Zur_biologischen_Vielfalt_2017.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Jahresbericht 2017 zur biologischen Vielfalt - Jagd und Artenschutz</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-01-16</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-01-16</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/6ea87d1f4a92efb288ed53e2bf901880">
+        <dct:title>Jahresbericht 2018 zur biologischen Vielfalt - Jagd und Artenschutz</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/7ee94f73beb43faf4099208b4e55734b" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/Jahresbericht_zur_biologischen_Vielfalt_2018.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/Jahresbericht_zur_biologischen_Vielfalt_2018.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Jahresbericht 2018 zur biologischen Vielfalt - Jagd und Artenschutz</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-12-16</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-12-16</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/7f6ef434153bdbfff9ed42c8d9ee1381">
+        <dct:title>Jahresbericht 2016 zur biologischen Vielfalt – Jagd- und Artenschutz</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/7ee94f73beb43faf4099208b4e55734b" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/biodiversitaetsbericht2016.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Landesregierung/V/Service/Broschueren/Broschueren_V/Umwelt/pdf/biodiversitaetsbericht2016.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Jahresbericht 2016 zur biologischen Vielfalt – Jagd- und Artenschutz</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-21</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-21</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f681f52201dcf1b1ea467aeed683c8a2">
+        <dct:title>Waldzustandsbericht 2018</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2018.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2018.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2018</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-11-29</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2018-11-29</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/225ebaffe8e7a30483ac43935e91e1f4">
+        <dct:title>Waldzustandsbericht 2017</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht_2017.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht_2017.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2017</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-12-27</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2017-12-27</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/9f48b6c643a139a0b4e7eac2ab4cfbb0">
+        <dct:title>Waldzustandsbericht 2016</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2016.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2016.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2016</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-15</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2016-12-15</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/904ef47daad01d2979ab20dda18b2ae7">
+        <dct:title>Waldzustandsbericht 2015</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2015.pdf?__blob=publicationFile&amp;v=3">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2015.pdf?__blob=publicationFile&amp;v=3" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2015</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2015-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/2147dcaa148ff19a89fa99c989dd648e">
+        <dct:title>Waldzustandsbericht 2014</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2014.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2014.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2014</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2014-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2014-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f201ecaf859f8e713cd030615bd3f5cb">
+        <dct:title>Waldzustandsbericht 2013</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2013.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2013.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2013</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2013-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2013-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/9bbeaf7b503dbd2c667786db08c4512d">
+        <dct:title>Waldzustandsbericht 2012</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2012.pdf?__blob=publicationFile&amp;v=2">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2012.pdf?__blob=publicationFile&amp;v=2" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2012</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2012-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2012-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f6de9c145fe28effe99fc163b92d657e">
+        <dct:title>Waldzustandsbericht 2011</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2011.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2011.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2011</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2011-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2011-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/5d794a0f4064ba53b5047dbe36eef3ef">
+        <dct:title>Waldzustandsbericht 2010</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2010.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2010.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2010</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2010-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/0ac0c2ceb265a7c0ca18385c95ec6e3a">
+        <dct:title>Waldzustandsbericht 2009</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2009.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2009.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2009</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2009-12-31</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2009-12-31</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/2f21507e1dc4e9106e348a65bb9e5cfa">
+        <dct:title>Waldzustandsbericht 2008</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2008.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2008.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2008</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2009-01-06</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2009-01-06</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/1e4b51fbab78072693617fcc2458824e">
+        <dct:title>Waldzustandsbericht 2006/2007</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2006_2007.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2006_2007.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldzustandsbericht 2006/2007</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2008-02-18</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2008-02-18</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/ac543132dfecddfdaa9ef8385034323f">
+        <dct:title>Waldschadensbericht 2005</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2005.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2005.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldschadensbericht 2005</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2006-03-22</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2006-03-22</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+   <dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f9727d9cfb4ad6f923a800e0f116b6e3">
+        <dct:title>Waldschadensbericht 2004</dct:title>
+
+   <dct:isVersionOf rdf:resource="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63" />
+        <dcat:distribution>
+          <dcat:Distribution rdf:about="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2004.pdf?__blob=publicationFile&amp;v=1">
+            <dct:title></dct:title>
+            <dcat:accessURL rdf:resource="https://www.schleswig-holstein.de/DE/Fachinhalte/W/wald/Downloads/Waldzustandsbericht2004.pdf?__blob=publicationFile&amp;v=1" />
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+            <dct:format  rdf:resource="http://publications.europa.eu/resource/authority/file-type/PDF" />
+            <dcat:mediaType>application/pdf</dcat:mediaType>
+          </dcat:Distribution>
+        </dcat:distribution>
+        <dct:subject rdf:resource="http://d-nb.info/gnd/4128022-2"/>
+        <dcat:theme rdf:resource="http://publications.europa.eu/resource/authority/data-theme/GOVE" />
+        <dct:description>Waldschadensbericht 2004</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU"/>
+        <dct:issued rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2004-11-30</dct:issued>
+            <dct:license rdf:resource="http://dcat-ap.de/def/licenses/cc-zero" />
+        <dct:modified rdf:datatype="http://www.w3.org/2001/XMLSchema#dateTime">2019-07-15T14:55:00.00000</dct:modified>
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+        <dct:temporal>
+          <dct:PeriodOfTime>
+            <schema:startDate rdf:datatype="http://www.w3.org/2001/XMLSchema#date">2004-11-30</schema:startDate>
+          </dct:PeriodOfTime>
+        </dct:temporal>
+      </dcat:Dataset>
+    </dcat:dataset>
+
+<dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/5768d5cdbc58abd45c8620e44e017f01">
+        <dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection" />
+        <dct:title>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt</dct:title>
+        <dct:description>Munitionsbelastung der deutschen Meeresgewässer – Entwicklungen und Fortschritt</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/b5cd3f303f594ecde96e1017e953b688" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/9f9ae60bb0d8985e10e9ab8aa6a7ca34" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/ff612d0f165d46f3091f58e1ef56a2ec" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/3a0d0674120fbf06b5cb8737124e3fd0" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/cd606b042789723a2b6d61cb31c46c39" />
+
+      </dcat:Dataset>
+    </dcat:dataset>
+<dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/f1f2513c3899ecf6f15691e0e4412822">
+        <dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection" />
+        <dct:title>Schuleingangsuntersuchungen in Schleswig-Holstein – Bericht</dct:title>
+        <dct:description>Schuleingangsuntersuchungen in Schleswig-Holstein – Bericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/ae2a3cffda84388365bc87711ed4af47" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/1ee93d311ae6078dc11655c2ca8865b5" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/91a479991245f208dd6f8ba82411a570" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/b0024265f96b9de5a590541f5e0aec91" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/04640ac19a21450984d2af7c402d6aa0" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/ffef477b7ebb1447d869b33c79cac8e2" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/a1fea922aa7d9f7a924784615301da83" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/86fe10eb6578e940d7df8e3d6da6520d" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/ccb65ee5047e3c9cc67384b513400246" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/f5123967a8d0d80ff135342ce41a09bb" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/05199f38b6234e794f79ad3726957a3e" />
+
+      </dcat:Dataset>
+    </dcat:dataset>
+<dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63">
+        <dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection" />
+        <dct:title>Waldzustandsbericht</dct:title>
+        <dct:description>Waldzustandsbericht</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/1e4b51fbab78072693617fcc2458824e" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/0ac0c2ceb265a7c0ca18385c95ec6e3a" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/f9727d9cfb4ad6f923a800e0f116b6e3" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/904ef47daad01d2979ab20dda18b2ae7" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/5d794a0f4064ba53b5047dbe36eef3ef" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/2147dcaa148ff19a89fa99c989dd648e" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/f201ecaf859f8e713cd030615bd3f5cb" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/9bbeaf7b503dbd2c667786db08c4512d" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/ac543132dfecddfdaa9ef8385034323f" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/f6de9c145fe28effe99fc163b92d657e" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/f681f52201dcf1b1ea467aeed683c8a2" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/9f48b6c643a139a0b4e7eac2ab4cfbb0" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/225ebaffe8e7a30483ac43935e91e1f4" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/2f21507e1dc4e9106e348a65bb9e5cfa" />
+
+      </dcat:Dataset>
+    </dcat:dataset>
+<dcat:dataset>
+      <dcat:Dataset rdf:about="http://transparenz.schleswig-holstein.de/7ee94f73beb43faf4099208b4e55734b">
+        <dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection" />
+        <dct:title>Jahresbericht zur biologischen Vielfalt</dct:title>
+        <dct:description>Jahresbericht zur biologischen Vielfalt</dct:description>
+        <dct:language rdf:resource="http://publications.europa.eu/resource/authority/language/DEU" />
+        <dct:spatial>
+          <dct:Location rdf:about="http://dcat-ap.de/def/politicalGeocoding/stateKey/01" />
+        </dct:spatial>
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/423e1ea7e98b492aebc0ca5108c7b36d" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/6ea87d1f4a92efb288ed53e2bf901880" />
+
+        <dct:hasVersion rdf:resource="http://transparenz.schleswig-holstein.de/7f6ef434153bdbfff9ed42c8d9ee1381" />
+
+      </dcat:Dataset>
+    </dcat:dataset>
+</dcat:Catalog>
+</rdf:RDF>
+
diff --git a/ckanext/odsh/tests_tpsh/test_checksum.py b/ckanext/odsh/tests_tpsh/test_checksum.py
new file mode 100644
index 0000000000000000000000000000000000000000..6bff5d4fe469025e396c8b7e291e0d99106aad36
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_checksum.py
@@ -0,0 +1,59 @@
+from mock import patch, mock_open
+import nose.tools as nt
+from ckanext.odsh.lib.uploader import _raise_validation_error_if_hash_values_differ, calculate_hash
+import ckantoolkit as ct
+import ckan.logic as logic
+import hashlib
+
+import os
+path = os.path.abspath(__file__)
+dir_path = os.path.dirname(path)
+
+class testHashException(object):     
+     text = 'Transparenz SH'
+     # hash produced by following command in bash:
+     # echo -n "Transparenz SH" | md5sum
+     hash_for_text = '791759e98a3ec4cc9c03141a3293292b'
+
+     def test_without_hash(self):
+          resource = {'package_id':'Test_id',}
+          with patch("__builtin__.open", mock_open(read_data=self.text)) as mock_file:
+               with open('some/file') as f:
+                    assert _raise_validation_error_if_hash_values_differ(f, resource) == None
+
+     def test_with_correct_hash(self):
+          resource = {'package_id':'Test_id', 'hash':self.hash_for_text}
+          with patch("__builtin__.open", mock_open(read_data=self.text)) as mock_file:
+               with open('some/file') as f:
+                    assert _raise_validation_error_if_hash_values_differ(f, resource) == None
+
+     def test_with_wrong_hash(self):
+          resource = {'package_id':'Test_id', 'hash':'incorrect_hash'}
+          with patch("__builtin__.open", mock_open(read_data=self.text)) as mock_file:
+               with open('some/file') as f:
+                    with nt.assert_raises(logic.ValidationError) as e:
+                         _raise_validation_error_if_hash_values_differ(f, resource)
+          exception_upload = e.exception.error_dict.get('upload')
+          assert exception_upload[0] == 'Berechneter Hash und mitgelieferter Hash sind unterschiedlich'
+     
+     def test_mock_file(self):
+          with patch("__builtin__.open", mock_open(read_data=self.text)) as mock_file:
+               with open('some/file') as f:
+                    file_content = f.read()
+          nt.assert_equal(file_content, self.text)
+     
+     def test_hash_of_empty_string(self):
+          hash_empty_string = 'd41d8cd98f00b204e9800998ecf8427e'
+          nt.assert_equal(hash_empty_string, hashlib.md5('').hexdigest())
+     
+     def test_pdf(self):
+          # expected_hash_pdf produced by following command in bash:
+          # md5sum test.pdf
+          expected_hash_pdf = '66123edf64fabf1c073fc45478bf4a57'
+          with open(dir_path + '/resources/test.pdf') as f:
+               hash = calculate_hash(f)
+          nt.assert_equal(hash, expected_hash_pdf)
+
+               
+               
+               
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_date_range.py b/ckanext/odsh/tests_tpsh/test_date_range.py
new file mode 100644
index 0000000000000000000000000000000000000000..e9b7121db7b7285b13ae6690a763af9028c901cd
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_date_range.py
@@ -0,0 +1,158 @@
+ # -*- coding: utf-8 -*-
+
+import nose.tools as nt
+
+import datetime
+
+from ckanext.odsh.pretty_daterange.date_range import DateRange
+
+class TestDateRange(object):
+    def test_is_one_year_returns_true(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_year()
+    
+    def test_is_one_year_returns_false_for_less_than_one_year(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 12, 30)
+        )
+        assert dr.is_one_year()==False
+    
+    def test_is_one_year_returns_false_for_more_than_one_year(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2001, 1, 15)
+        )
+        assert dr.is_one_year()==False
+    
+    def test_is_one_year_returns_false_for_two_years(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2001, 12, 31)
+        )
+        assert dr.is_one_year()==False
+    
+    def test_is_one_half_of_year_returns_true_for_first_half(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 6, 30)
+        )
+        assert dr.is_one_half_of_year()
+    
+    def test_is_one_half_of_year_returns_true_for_second_half(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 7, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_half_of_year()
+    
+    def test_is_one_half_of_year_returns_false_for_full_year(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_half_of_year()==False
+    
+    def test_get_half_year_returns_1_for_first_half_of_year(self):
+        half_year = DateRange.get_half_year(datetime.date(2000, 6, 30))
+        nt.assert_equal(half_year, 1)
+    
+    def test_get_half_year_returns_2_for_second_half_of_year(self):
+        half_year = DateRange.get_half_year(datetime.date(2000, 7, 1))
+        nt.assert_equal(half_year, 2)
+    
+    def test_is_one_quarter_of_year_returns_true_for_first_quarter(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 3, 31)
+        )
+        assert dr.is_one_quarter_of_year()
+    
+    def test_is_one_quarter_of_year_returns_true_for_second_quarter(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 4, 1),
+            date_end = datetime.date(2000, 6, 30)
+        )
+        assert dr.is_one_quarter_of_year()
+
+    def test_is_one_quarter_of_year_returns_true_for_third_quarter(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 7, 1),
+            date_end = datetime.date(2000, 9, 30)
+        )
+        assert dr.is_one_quarter_of_year()
+    
+    def test_is_one_quarter_of_year_returns_true_for_fourth_quarter(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 10, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_quarter_of_year()
+    
+    def test_get_quarter_returns_1_for_first_quarter(self):
+        quarter = DateRange.get_quarter(datetime.date(2000, 2, 1))
+        nt.assert_equal(quarter, 1)
+    
+    def test_get_quarter_returns_2_for_second_quarter(self):
+        quarter = DateRange.get_quarter(datetime.date(2000, 5, 1))
+        nt.assert_equal(quarter, 2)
+
+    def test_get_quarter_returns_3_for_third_quarter(self):
+        quarter = DateRange.get_quarter(datetime.date(2000, 8, 1))
+        nt.assert_equal(quarter, 3)
+    
+    def test_get_quarter_returns_4_for_fourth_quarter(self):
+        quarter = DateRange.get_quarter(datetime.date(1981, 11, 21))
+        nt.assert_equal(quarter, 4)
+
+    def test_is_one_month_returns_true(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 12, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_month()
+
+    def test_is_one_month_returns_false_for_two_months(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 11, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_one_month()==False
+    
+    def test_is_range_of_multiple_months_returns_false_for_single_month(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 11, 1),
+            date_end = datetime.date(2000, 11, 30)
+        )
+        assert dr.is_range_of_multiple_months()==False
+    
+    def test_is_range_of_multiple_months_returns_true_for_multiple_months(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 11, 1),
+            date_end = datetime.date(2021, 12, 31)
+        )
+        assert dr.is_range_of_multiple_months()
+    
+    def test_is_range_of_multiple_months_in_same_year_returns_false_for_differing_years(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 11, 1),
+            date_end = datetime.date(2021, 12, 31)
+        )
+        assert dr.is_range_of_multiple_months_in_same_year()==False
+
+    def test_is_range_of_multiple_months_in_same_year_returns_true_for_same_year(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 11, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_range_of_multiple_months_in_same_year()
+
+    def test_is_range_of_multiple_years_returns_false_for_single_year(self):
+        dr = DateRange(
+            date_start = datetime.date(2000, 1, 1),
+            date_end = datetime.date(2000, 12, 31)
+        )
+        assert dr.is_range_of_multiple_years() == False
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_date_range_formatter.py b/ckanext/odsh/tests_tpsh/test_date_range_formatter.py
new file mode 100644
index 0000000000000000000000000000000000000000..d2c8e77bf148fe8ef67b6a973033ba759caa3e9e
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_date_range_formatter.py
@@ -0,0 +1,145 @@
+ # -*- coding: utf-8 -*-
+
+import nose.tools as nt
+
+import datetime
+
+from ckanext.odsh.pretty_daterange.date_range_formatter import DateRangeFormatter
+
+class TestDateRangeFormatter(object):
+    def test_it_raises_value_error_if_date_end_before_date_start(self):
+        date_start = datetime.date(2019,1,1)
+        date_end = datetime.date(2018,1,1)
+        with nt.assert_raises(ValueError):
+            drf = DateRangeFormatter(date_start, date_end)
+    
+    def test_it_stores_date_start_and_date_end(self):
+        date_start = datetime.date(2019,1,1)
+        date_end = datetime.date(2019,2,1)
+        drf = DateRangeFormatter(date_start, date_end)
+        assert drf.date_start==date_start and drf.date_end==date_end
+    
+    def test_it_returns_date_in_correct_format(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019,1,2), 
+            date_end = datetime.date(2020, 2, 4), 
+            expected_str = u'02.01.2019 - 04.02.2020')
+    
+    def _assert_output_string_equals(self, date_start, date_end, expected_str):
+        drf = DateRangeFormatter(date_start, date_end)
+        formatted_date_range = drf.get_formatted_str()
+        nt.assert_equal(formatted_date_range, expected_str)
+    
+    def test_it_returns_single_date_if_start_equals_end(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 1, 2), 
+            date_end = datetime.date(2019, 1, 2), 
+            expected_str = u'02.01.2019')
+
+    def test_it_returns_only_year_for_full_year(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 1, 1), 
+            date_end = datetime.date(2019, 12, 31), 
+            expected_str = u'2019')
+    
+    def test_it_returns_only_year_for_multiple_full_years(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 1, 1), 
+            date_end = datetime.date(2020, 12, 31), 
+            expected_str = u'2019 - 2020')
+    
+    def test_it_returns_month_for_full_month(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 2, 1), 
+            date_end = datetime.date(2019, 2, 28), 
+            expected_str = u'Februar 2019')
+    
+    def test_it_returns_months_for_range_of_months(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 2, 1), 
+            date_end = datetime.date(2020, 3, 31), 
+            expected_str = u'Februar 2019 - März 2020')
+    
+    def test_it_returns_months_for_range_of_months_in_same_year(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 2, 1), 
+            date_end = datetime.date(2019, 3, 31), 
+            expected_str = u'Februar - März 2019')
+    
+    def test_it_returns_first_quarter(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 1, 1), 
+            date_end = datetime.date(2019, 3, 31), 
+            expected_str = u'1. Quartal 2019')
+    
+    def test_it_returns_second_quarter(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 4, 1), 
+            date_end = datetime.date(2019, 6, 30), 
+            expected_str = u'2. Quartal 2019')
+    
+    def test_it_returns_third_quarter(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 7, 1), 
+            date_end = datetime.date(2019, 9, 30), 
+            expected_str = u'3. Quartal 2019')
+    
+    def test_it_returns_fourth_quarter(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 10, 1), 
+            date_end = datetime.date(2019, 12, 31), 
+            expected_str = u'4. Quartal 2019')
+    
+    def test_it_returns_first_half_year(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 1, 1), 
+            date_end = datetime.date(2019, 6, 30), 
+            expected_str = u'1. Halbjahr 2019')
+
+    def test_it_returns_second_half_year(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 7, 1), 
+            date_end = datetime.date(2019, 12, 31), 
+            expected_str = u'2. Halbjahr 2019')
+    
+    def test_it_returns_date_start_if_date_end_is_none(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 7, 1), 
+            date_end = None, 
+            expected_str = u'ab 01.07.2019'
+        )
+    
+    def test_it_returns_date_end_if_date_start_is_none(self):
+        self._assert_output_string_equals(
+            date_start = None, 
+            date_end = datetime.date(2019, 7, 1), 
+            expected_str = u'bis 01.07.2019'
+        )
+
+    def test_it_returns_empty_string_if_date_start_and_end_are_none(self):
+        self._assert_output_string_equals(
+            date_start = None, 
+            date_end = None, 
+            expected_str = u''
+        )
+
+    def test_it_returns_date_start_if_date_end_is_empty(self):
+        self._assert_output_string_equals(
+            date_start = datetime.date(2019, 7, 1), 
+            date_end = '', 
+            expected_str = u'ab 01.07.2019'
+        )
+    
+    def test_it_returns_date_end_if_date_start_is_empty(self):
+        self._assert_output_string_equals(
+            date_start = '', 
+            date_end = datetime.date(2019, 7, 1), 
+            expected_str = u'bis 01.07.2019'
+        )
+
+    def test_it_returns_empty_string_if_date_start_and_end_are_empty(self):
+        self._assert_output_string_equals(
+            date_start = '', 
+            date_end = '', 
+            expected_str = u''
+        )
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_helper_pkg_dict.py b/ckanext/odsh/tests_tpsh/test_helper_pkg_dict.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b5af7be0bade0d18299473ba0052fa9118047f0
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_helper_pkg_dict.py
@@ -0,0 +1,200 @@
+import datetime
+import nose.tools as nt
+from mock import patch, call
+
+from ckanext.odsh.helper_pkg_dict import HelperPgkDict
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
+import ckanext.odsh.uri_store as uri_store
+
+class TestHelperPkgDict(object):
+    def test_is_collection_returns_true(self):
+        dataset_dict = {
+            u'type': u'collection',
+        }
+        h = HelperPgkDict(dataset_dict)
+        is_collection = h.is_collection()
+        nt.assert_true(is_collection)
+    
+    def test_is_collection_returns_false_if_no_type(self):
+        dataset_dict = {}
+        h = HelperPgkDict(dataset_dict)
+        is_collection = h.is_collection()
+        nt.assert_false(is_collection)
+    
+    def test_is_collection_returns_false_if_type_dataset(self):
+        dataset_dict = {u'type': u'dataset'}
+        h = HelperPgkDict(dataset_dict)
+        is_collection = h.is_collection()
+        nt.assert_false(is_collection)
+    
+    def test_shall_be_part_of_collection_returns_true_if_flag_add_to_collection_is_True(self):
+        dataset_dict = {'add_to_collection': True}
+        h = HelperPgkDict(dataset_dict)
+        shall_be_part_of_collection = h.shall_be_part_of_collection()
+        nt.assert_true(shall_be_part_of_collection)
+    
+    def test_shall_be_part_of_collection_returns_false_if_flag_add_to_collection_is_False(self):
+        dataset_dict = {'add_to_collection': False}
+        h = HelperPgkDict(dataset_dict)
+        shall_be_part_of_collection = h.shall_be_part_of_collection()
+        nt.assert_false(shall_be_part_of_collection)
+    
+    def test_shall_be_part_of_collection_returns_false_if_flag_add_to_collection_not_in_dict(self):
+        dataset_dict = {}
+        h = HelperPgkDict(dataset_dict)
+        shall_be_part_of_collection = h.shall_be_part_of_collection()
+        nt.assert_false(shall_be_part_of_collection)
+    
+    def test_update_relations_to_collection_members_leads_to_correct_call_of_add_to_collection(self):
+        with patch.object(helpers_tpsh, 'add_pkg_to_collection') as patch_add_package_to_collection:
+            # arange
+            # taken from debugging _update_relations_to_collection_members:
+            dataset_dict_collection = {
+                'id': u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d',
+                u'extras': [
+                    {u'key': u'has_version', u'value': u'["http://transparenz.schleswig-holstein.de/9f9ae60bb0d8985e10e9ab8aa6a7ca34", "http://transparenz.schleswig-holstein.de/3a0d0674120fbf06b5cb8737124e3fd0", "http://transparenz.schleswig-holstein.de/b5cd3f303f594ecde96e1017e953b688", "http://transparenz.schleswig-holstein.de/ff612d0f165d46f3091f58e1ef56a2ec", "http://transparenz.schleswig-holstein.de/cd606b042789723a2b6d61cb31c46c39"]'},
+                ]
+            }
+            id_collection = u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d'
+            uri_collection_member = 'http://transparenz.schleswig-holstein.de/b5cd3f303f594ecde96e1017e953b688'
+            id_collection_member = 'fake_id_collection_member'
+            uri_store._set_uri_to_id({uri_collection_member: id_collection_member})
+
+            # act
+            h = HelperPgkDict(dataset_dict_collection)
+            h.update_relations_to_collection_members()
+
+            # assert
+            calls = [call(id_collection_member,id_collection), ]
+            patch_add_package_to_collection.assert_has_calls(calls)
+
+            # teardown
+            uri_store._set_uri_to_id({})
+    
+    def test_update_relation_to_collection_leads_to_correct_call_of_add_to_collection(self):
+        with patch.object(helpers_tpsh, 'add_pkg_to_collection') as patch_add_package_to_collection:
+            # arange
+            # taken from debugging _update_relations_to_collection_members:
+            dataset_dict_collection_member = {
+                u'add_to_collection': True,
+                u'extras': [
+                    {u'key': u'is_version_of', u'value': u'["http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63"]'},
+                ],
+                'id': u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d',
+            }
+            id_collection_member = u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d'
+            uri_collection = 'http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63'
+            id_collection = 'fake_id_collection'
+            uri_store._set_uri_to_id({uri_collection: id_collection})
+
+            # act
+            h = HelperPgkDict(dataset_dict_collection_member)
+            h.update_relation_to_collection()
+
+            # assert
+            calls = [call(id_collection_member,id_collection), ]
+            patch_add_package_to_collection.assert_has_calls(calls)
+
+            # teardown
+            uri_store._set_uri_to_id({})
+    
+    def test_get_collection_uri(self):
+        dataset_dict_collection_member = {
+            u'add_to_collection': True,
+            u'extras': [
+                {u'key': u'is_version_of', u'value': u'["http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63"]'},
+            ],
+            'id': u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d',
+        }
+        h = HelperPgkDict(dataset_dict_collection_member)
+        collection = h.get_collection_uri()
+        nt.assert_equal(collection, u'http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63')
+    
+    def test_get_collection_uri_if_not_in_extras(self):
+        dataset_dict_collection_member = {
+            u'id': u'248ceefd-2fb8-4a3c-ab3c-d2c873b24e4d',
+        }
+        h = HelperPgkDict(dataset_dict_collection_member)
+        collection = h.get_collection_uri()
+        nt.assert_equal(collection, None)
+    
+    def test_get_uris_collection_members(self):
+        collection_members_as_string = u'["http://transparenz.schleswig-holstein.de/cd606b042789723a2b6d61cb31c46c39", "http://transparenz.schleswig-holstein.de/3a0d0674120fbf06b5cb8737124e3fd0", "http://transparenz.schleswig-holstein.de/b5cd3f303f594ecde96e1017e953b688", "http://transparenz.schleswig-holstein.de/9f9ae60bb0d8985e10e9ab8aa6a7ca34", "http://transparenz.schleswig-holstein.de/ff612d0f165d46f3091f58e1ef56a2ec"]'
+        dataset_dict = {
+            u'extras': [
+                {u'key': u'has_version', u'value': collection_members_as_string},
+            ]
+        }
+        h = HelperPgkDict(dataset_dict)
+        uris = h.get_uris_collection_members()
+        nt.assert_equal(uris[0], 'http://transparenz.schleswig-holstein.de/cd606b042789723a2b6d61cb31c46c39')
+        nt.assert_equal(uris[1], 'http://transparenz.schleswig-holstein.de/3a0d0674120fbf06b5cb8737124e3fd0')
+        nt.assert_equal(uris[-1], 'http://transparenz.schleswig-holstein.de/ff612d0f165d46f3091f58e1ef56a2ec')
+
+
+
+class Test_get_date_start_and_end_from_pkg_dict(object):
+
+    def setUp(self):
+        self.dict_with_start_and_end_date = {
+            u'extras': [
+                {u'key': u'groups', u'value': u''}, 
+                {u'key': u'issued', u'value': u'2019-07-06T00:00:00'}, 
+                {u'key': u'licenseAttributionByText', u'value': u''}, 
+                {u'key': u'subject_text', u'value': u''}, 
+                {u'key': u'temporal_end', u'value': u'2019-08-31T00:00:00'}, 
+                {u'key': u'temporal_start', u'value': u'2019-08-01T00:00:00'}
+            ],
+        }
+        self.dict_with_empty_start_date = {
+            u'extras': [
+                {u'key': u'groups', u'value': u''}, 
+                {u'key': u'issued', u'value': u'2019-07-06T00:00:00'}, 
+                {u'key': u'licenseAttributionByText', u'value': u''}, 
+                {u'key': u'subject_text', u'value': u''}, 
+                {u'key': u'temporal_end', u'value': u'2019-08-31T00:00:00'}, 
+                {u'key': u'temporal_start', u'value': u''}
+            ],
+        }
+        self.dict_with_empty_end_date = {
+            u'extras': [
+                {u'key': u'groups', u'value': u''}, 
+                {u'key': u'issued', u'value': u'2019-07-06T00:00:00'}, 
+                {u'key': u'licenseAttributionByText', u'value': u''}, 
+                {u'key': u'subject_text', u'value': u''}, 
+                {u'key': u'temporal_end', u'value': u''}, 
+                {u'key': u'temporal_start', u'value': u'2019-08-01T00:00:00'}
+            ],
+        }
+        self.date_start_expected = datetime.date(2019, 8, 1)
+        self.date_end_expected = datetime.date(2019, 8, 31)
+
+    def test_it_returns_correct_start_date(self):
+        h = HelperPgkDict(self.dict_with_start_and_end_date)
+        date_start, _ = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_start, self.date_start_expected)
+    
+    def test_it_returns_correct_end_date(self):
+        h = HelperPgkDict(self.dict_with_start_and_end_date)
+        _, date_end = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_end, self.date_end_expected)
+    
+    def test_it_return_none_if_date_start_empty(self):
+        h = HelperPgkDict(self.dict_with_empty_start_date)
+        date_start, _ = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_start, None)
+    
+    def test_it_return_none_if_date_end_empty(self):
+        h = HelperPgkDict(self.dict_with_empty_end_date)
+        _, date_end = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_end, None)
+    
+    def test_it_returns_date_start_if_date_end_empty(self):
+        h = HelperPgkDict(self.dict_with_empty_end_date)
+        date_start, _ = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_start, self.date_start_expected)
+    
+    def test_it_returns_date_end_if_date_start_empty(self):
+        h = HelperPgkDict(self.dict_with_empty_start_date)
+        _, date_end = h._get_date_start_and_end_from_pkg_dict()
+        nt.assert_equal(date_end, self.date_end_expected)    
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_helpers_tpsh.py b/ckanext/odsh/tests_tpsh/test_helpers_tpsh.py
new file mode 100644
index 0000000000000000000000000000000000000000..78c106081ea654955449b41e79412f5c7563e33a
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_helpers_tpsh.py
@@ -0,0 +1,281 @@
+# encoding: utf-8
+
+import os
+from collections import namedtuple, OrderedDict
+import datetime
+import nose.tools as nt
+from mock import patch
+from ckan.common import config
+import ckan.logic.action.create as create
+from ckanext.odsh.tests_tpsh.resources import org_dicts
+
+
+from ckanext.odsh.helpers_tpsh import (
+    map_dct_type_to_ckan_type,
+    map_ckan_type_to_dct_type,
+    add_pkg_to_collection,
+    correct_missing_relationship,
+    get_language_of_package,
+    get_address_org,
+    load_json_to_ordered_dict,
+    load_subject_mapping,
+    get_subject_for_selection
+)
+
+
+class TestMatchDctTypeToCkanType(object):
+    
+    def test_it_returns_collection(self):
+        dct_type = 'http://dcat-ap.de/def/datasetTypes/collection'
+        ckan_type = map_dct_type_to_ckan_type(dct_type)
+        expected_ckan_type = 'collection'
+        nt.assert_equal(ckan_type, expected_ckan_type)
+    
+    def test_it_returns_none_for_unknown_type(self):
+        nt.assert_equal(
+            map_dct_type_to_ckan_type('some unknown type'), 
+            None
+        )
+
+
+class TestMatchCkanTypeToDctType(object):
+    
+    def test_it_returns_url_for_collection(self):
+        ckan_type = 'collection'
+        dct_type = map_ckan_type_to_dct_type(ckan_type)
+        expected_dct_type = 'http://dcat-ap.de/def/datasetTypes/collection'
+        nt.assert_equal(
+            dct_type, expected_dct_type
+        )
+
+
+FakePackageRelationship = namedtuple(
+    'FakePackageRelationship',
+    '''
+    object_package_id
+    revision_id
+    subject_package_id
+    id
+    type
+    '''
+)
+
+class Test_correct_missing_relationship(object):
+    def setUp(self):
+        self.relationships_from_model = [
+            FakePackageRelationship(
+                object_package_id=u'object package id',
+                revision_id=u'revision id',
+                subject_package_id=u'subject package id',
+                id=u'id',
+                type=u'type'
+            )
+        ]
+
+    def test_it_does_not_modify_pkg_dict_if_no_model_relationships(self):
+        relationships_from_model = []
+        original_pkg_dict = {'id': 'some_id'}
+        pkg_dict = dict(original_pkg_dict)
+        correct_missing_relationship(
+            pkg_dict, relationships_from_model
+        )
+        nt.assert_equal(pkg_dict, original_pkg_dict)
+    
+    def test_it_does_not_modify_pkg_dict_if_relationships_already_in_dict(self):
+        original_pkg_dict = {
+            u'type': u'dataset',
+            u'relationships_as_subject': [
+                {
+                    u'__extras': {
+                        u'object_package_id': u'original object package id', 
+                        u'revision_id': u'original revision id', 
+                        u'subject_package_id': u'original subject package id'
+                    }, 
+                    u'comment': u'', 
+                    u'id': u'original id', 
+                    u'type': u'original type'
+                }
+            ]
+        }
+        pkg_dict = dict(original_pkg_dict)
+        correct_missing_relationship(
+            pkg_dict, self.relationships_from_model
+        )
+        nt.assert_equal(pkg_dict, original_pkg_dict)
+    
+    def test_it_does_not_modify_pkg_dict_if_type_collection(self):
+        original_pkg_dict = {
+            u'type': u'collection',
+            u'relationships_as_subject': [
+                {
+                    u'__extras': {
+                        u'object_package_id': u'original object package id', 
+                        u'revision_id': u'original revision id', 
+                        u'subject_package_id': u'original subject package id'
+                    }, 
+                    u'comment': u'', 
+                    u'id': u'original id', 
+                    u'type': u'original type'
+                }
+            ]
+        }
+        pkg_dict = dict(original_pkg_dict)
+        correct_missing_relationship(
+            pkg_dict, self.relationships_from_model
+        )
+        nt.assert_equal(pkg_dict, original_pkg_dict)
+    
+    def test_it_adds_relationships_if_not_already_in_dict(self):
+        pkg_dict = {
+            u'type': u'dataset',
+            u'relationships_as_subject': []
+        }
+        correct_missing_relationship(
+            pkg_dict, self.relationships_from_model
+        )
+        expected_pkg_dict = {
+            u'type': u'dataset',
+            u'relationships_as_subject': [
+                {
+                    u'__extras': {
+                        u'object_package_id': u'object package id', 
+                        u'revision_id': u'revision id', 
+                        u'subject_package_id': u'subject package id'
+                    }, 
+                    u'comment': u'', 
+                    u'id': u'id', 
+                    u'type': u'type'
+                }
+            ]
+        }
+
+        from_relationships = lambda d, key: d.get('relationships_as_subject')[0].get(key)
+        from_extras = lambda d, key: d.get('relationships_as_subject')[0].get('__extras').get(key)
+        
+        # assert
+        nt.assert_equal(pkg_dict.get('type'), 'dataset')
+        
+        for key in ('id', 'type'):
+            nt.assert_true(from_relationships(pkg_dict, key) is not None)
+            nt.assert_equal(
+                from_relationships(pkg_dict, key), 
+                from_relationships(expected_pkg_dict, key)
+            )
+
+        for key in ('object_package_id', 'revision_id', 'subject_package_id'):
+            nt.assert_true(
+                pkg_dict is not None)
+            nt.assert_equal(
+                from_extras(pkg_dict, key),
+                from_extras(expected_pkg_dict, key)
+            )
+
+    
+class Test_get_language_of_package(object):
+    def setUp(self):
+        config.update({'ckanext.odsh.language_mapping': '/usr/lib/ckan/default/src/ckanext-odsh/language_mapping.json'})
+    
+    def tearDown(self):
+        config.clear()
+
+    def test_it_returns_Englisch(self):
+        test_package = {
+                'id': u'language_test',
+                u'extras': [
+                    {u'key': u'language', u'value': u'http://publications.europa.eu/resource/authority/language/ENG'},
+                ]
+            }
+        nt.assert_equal(get_language_of_package(test_package),'Englisch')
+    
+    def test_it_returns_None_if_language_id_not_in_dict(self):
+        test_package = {
+                'id': u'language_test',
+                u'extras': [
+                    {u'key': u'language', u'value': u'tlhIngan Hol'},
+                ]
+            }
+        nt.assert_equal(get_language_of_package(test_package), None)
+    
+    def test_it_returns_None_if_language_not_in_pkg_dict(self):
+        test_package = {}
+        nt.assert_equal(get_language_of_package(test_package), None)
+    
+
+class Test_get_address_org(object):
+    def test_it_returns_address_for_org_with_address(self):
+        organization = org_dicts.organization_with_address
+        address = get_address_org(organization)
+        nt.assert_equal(address.get('location'), u'Müllerdorf')
+        nt.assert_equal(address.get('person'), u'Michael Müller')
+        nt.assert_equal(address.get('mail'), u'mueller@mueller.de')
+        nt.assert_equal(address.get('street'), u'Müllergasse 10')
+        nt.assert_equal(address.get('telephone'), u'040 123456')
+        nt.assert_equal(address.get('web'), u'http://mueller.de')
+
+    def test_it_returns_empty_dict_if_called_via_organization_new(self):
+        organization = dict()
+        address = get_address_org(organization)
+        assert type(address) is dict
+        nt.assert_equal(len(address), 0)
+
+
+def _add_subject_mapping_file_to_config():
+    path_current_file = os.path.dirname(os.path.abspath(__file__))
+    path_to_subject_mapping_file = path_current_file + '/resources/subject_mapping_for_tests.json'
+    config.update({'ckanext.odsh.subject_mapping': path_to_subject_mapping_file})
+
+class Test_load_json_to_ordered_dict(object):
+    def setUp(self):
+        json_str = '{"A": 1, "B": 2, "D": 3, "C":4, "E": 0}'
+        self.result = load_json_to_ordered_dict(json_str)
+    
+    def test_it_does_not_crash(self):
+        pass
+
+    def test_it_returns_ordered_dict(self):
+        nt.assert_is(type(self.result), OrderedDict)
+    
+    def test_it_preserves_order_of_keys(self):
+        keys = self.result.keys()
+        nt.assert_equal(keys, [u'A', u'B', u'D', u'C', u'E'])
+    
+    def test_it_preserves_order_of_values(self):
+        values = self.result.values()
+        nt.assert_equal(values, [1, 2, 3, 4, 0])
+
+class Test_load_subject_mapping(object):
+    def setUp(self):
+        _add_subject_mapping_file_to_config()
+        self.SUBJECT_MAPPING = load_subject_mapping()
+    
+    def tearDown(self):
+        config.clear()
+    
+    def test_it_returns_an_ordered_dictionary(self):
+        nt.assert_is(type(self.SUBJECT_MAPPING), OrderedDict)
+    
+    def test_it_preserves_order_of_json_file(self):
+        keys = self.SUBJECT_MAPPING.keys()
+        nt.assert_equal(keys[0], u'http://transparenz.schleswig-holstein.de/informationsgegenstand#Verwaltungsvorschrift')
+        nt.assert_equal(keys[1], u'http://transparenz.schleswig-holstein.de/informationsgegenstand#Organisationsplan')
+        nt.assert_equal(keys[2], u'http://transparenz.schleswig-holstein.de/informationsgegenstand#Geschaeftsverteilungsplan')
+        nt.assert_equal(keys[3], u'http://transparenz.schleswig-holstein.de/informationsgegenstand#Aktenplan')
+
+class Test_get_subject_for_selection(object):
+    def setUp(self):
+        _add_subject_mapping_file_to_config()
+        self.result = get_subject_for_selection()
+    
+    def tearDown(self):
+        config.clear()
+
+    def test_it_returns_a_list(self):
+        assert type(self.result) is list
+    
+    def test_first_element_is_empty(self):
+        nt.assert_equal(self.result[0], {'key': 'empty', 'value': ' '})
+    
+    def test_it_contains_more_than_one_element(self):
+        nt.assert_greater(len(self.result), 1)
+
+        
diff --git a/ckanext/odsh/tests_tpsh/test_icap.py b/ckanext/odsh/tests_tpsh/test_icap.py
new file mode 100644
index 0000000000000000000000000000000000000000..f97bbc74249eadeeb2e36ebdf07aae53191d0d82
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_icap.py
@@ -0,0 +1,67 @@
+import nose.tools as nt
+from testfixtures import log_capture
+
+from ckan.common import config
+from ckanext.odsh.lib.odsh_icap_client import ODSHICAPRequest, _read_from_config
+
+class Test_ODSHICAPRequest(object):
+    def setUp(self):
+        config.update({
+            'ckanext.odsh.icap.host': 'some_host',
+            'ckanext.odsh.icap.port': '123',
+            'ckanext.odsh.icap.clientip': 'some_ip',
+        })
+    
+    def tearDown(self):
+        config.clear()
+
+    def test_it_initializes_with_parameters_set_in_config(self):
+        request = ODSHICAPRequest('some_filename', 'some_filebuffer')
+        nt.assert_equal(request.HOST, 'some_host')
+        nt.assert_equal(request.PORT, 123)
+        nt.assert_equal(request.CLIENTIP, 'some_ip')
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_host_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.host']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.host is not defined in ckan config file.'"
+        ))
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_port_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.port']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.port is not defined in ckan config file.'"
+        ))
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_clientip_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.clientip']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.clientip is not defined in ckan config file.'"
+        ))
+    
+    def test_read_from_config_raises_KeyError_if_host_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.host']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.host')
+    
+    def test_read_from_config_raises_KeyError_if_port_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.port']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.port')
+    
+    def test_read_from_config_raises_KeyError_if_clientip_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.clientip']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.clientip')
diff --git a/ckanext/odsh/tests_tpsh/test_matomo.py b/ckanext/odsh/tests_tpsh/test_matomo.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c20d6853e746ad866e7c30f25db91a2d6e7c5ab
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_matomo.py
@@ -0,0 +1,53 @@
+import nose.tools as nt
+from mock import patch
+from ckan.common import config
+
+from ckanext.odsh.plugin import OdshPlugin
+import ckanext.odsh.helpers_tpsh as helpers_tpsh
+import ckanext.odsh.matomo as matomo
+
+class Test_helper_odsh_use_matomo(object):
+    def setUp(self):
+        self.plugin = OdshPlugin()
+    
+    def test_use_matomo_returns_False_if_not_in_config(self):
+        use_matomo = self.plugin.get_helpers()['odsh_use_matomo']()
+        nt.assert_false(use_matomo)
+    
+    def test_use_matomo_returns_False_if_set_False_in_config(self):
+        config.update({'ckanext.odsh.use_matomo': 'False'})
+        use_matomo = self.plugin.get_helpers()['odsh_use_matomo']()
+        nt.assert_false(use_matomo)
+        config.clear()
+    
+    def test_use_matomo_returns_True_if_set_True_in_config(self):
+        config.update({'ckanext.odsh.use_matomo': 'True'})
+        use_matomo = self.plugin.get_helpers()['odsh_use_matomo']()
+        nt.assert_true(use_matomo)
+        config.clear()
+    
+
+class Test_decorator_do_if_use_matomo(object):
+    def test_it_does_not_if_use_matomo_set_False_in_config(self):
+        
+        @matomo.do_if_use_matomo
+        def set_to_true(_):
+            return True
+        
+        config.update({'ckanext.odsh.use_matomo': 'False'})
+        did_run = False
+        did_run = set_to_true(did_run)
+        nt.assert_false(did_run)
+        config.clear()
+    
+    def test_it_does_if_use_matomo_set_True_in_config(self):
+        
+        @matomo.do_if_use_matomo
+        def set_to_true(_):
+            return True
+
+        config.update({'ckanext.odsh.use_matomo': 'True'})
+        did_run = False
+        did_run = set_to_true(did_run)
+        nt.assert_true(did_run)
+        config.clear()
diff --git a/ckanext/odsh/tests_tpsh/test_odsh_helpers.py b/ckanext/odsh/tests_tpsh/test_odsh_helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4c488230d254139ec4b3c7da1df93dd762a41dc
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_odsh_helpers.py
@@ -0,0 +1,161 @@
+import datetime
+import nose.tools as nt
+from mock import patch
+
+import ckan.lib.helpers as helpers
+
+import ckanext.odsh.helpers as odsh_helpers
+from ckanext.odsh.helpers import is_within_last_month
+import ckanext.odsh.collection.helpers as helpers_collection
+import ckan.model as model
+
+
+class Test_tpsh_get_successor_and_predecessor_dataset(object):
+    
+    def setUp(self):
+        
+        # construct datasets that shall be in following order:
+        # name      date
+        # public2   2014-07-01
+        # public3   2014-07-01
+        # public4   2014-07-02
+        # public1   2014-07-03
+
+        self.names_collection_members = [
+            u'public3', u'public2', u'public1', u'public4', 
+            u'private3', u'private2', u'private1']
+        self.dates_collection_members = [
+            u'2014-07-01T00:00:00', #public3
+            u'2014-07-01T00:00:00', #public2
+            u'2014-07-03T00:00:00', #public1
+            u'2014-07-02T00:00:00', #public4
+            u'2014-07-05T00:00:00', #private3
+            u'2014-07-06T00:00:00', #private2
+            u'2014-07-07T00:00:00', #private1
+        ]
+        self.pkg_dicts_collection_members = [
+            {
+                u'name': name,
+                u'extras': {u'issued': date}
+            }
+            for (name, date) in zip(self.names_collection_members, self.dates_collection_members)
+        ]
+
+        def fake_access_checker(access_type, pkg_dict):
+            pkg_name = pkg_dict.get('name')
+            if 'public' in pkg_name:
+                return True
+            return False
+        
+        def fake_get_package_dict(name):
+            package_list = filter(lambda pkg_dict:pkg_dict.get('name')==name, self.pkg_dicts_collection_members)
+            return package_list[0]
+
+        self.patch_get_datasets_belonging_to_collection_by_dataset = patch.object(
+            helpers_collection,
+            'get_all_datasets_belonging_to_collection_by_dataset',
+            return_value = self.names_collection_members)
+        self.patch_get_datasets_belonging_to_collection_by_dataset.start()
+
+        self.patch_check_access = patch.object(
+            helpers,
+            'check_access',
+            new=fake_access_checker, 
+        )
+        self.patch_check_access.start()
+
+        self.patch_get_package_dict = patch.object(
+            helpers_collection,
+            'get_package_dict',
+            new=fake_get_package_dict,
+        )
+        self.patch_get_package_dict.start()
+    
+    def tearDown(self):
+        self.patch_get_datasets_belonging_to_collection_by_dataset.stop()
+        self.patch_check_access.stop()
+        self.patch_get_package_dict.stop()
+
+    def test_patch_get_datasets_belonging_to_collection_by_dataset(self):
+        return_value = helpers_collection.get_all_datasets_belonging_to_collection_by_dataset()
+        nt.assert_equal(return_value, self.names_collection_members)
+    
+    def test_patch_access_checker_returns_True(self):
+        pkg_dict = {u'name': u'public1'}
+        has_access = helpers.check_access('package_show', pkg_dict)
+        nt.assert_true(has_access)
+    
+    def test_patch_access_checker_returns_False(self):
+        pkg_dict = {u'name': u'private1'}
+        has_access = helpers.check_access('package_show', pkg_dict)
+        nt.assert_false(has_access)
+    
+    def test_patch_package_get(self):
+        pkg_dict = helpers_collection.get_package_dict('public1')
+        nt.assert_equal(pkg_dict.get('name'), 'public1')
+    
+    def test_it_returns_correct_for_public2(self):
+        pkg_dict = {u'name': u'public2'}
+        successor, predecessor = helpers_collection.get_successor_and_predecessor_dataset(pkg_dict)
+        nt.assert_equal(successor, 'public3')
+        nt.assert_equal(predecessor, None)
+    
+    def test_it_returns_correct_for_public3(self):
+        pkg_dict = {u'name': u'public3'}
+        successor, predecessor = helpers_collection.get_successor_and_predecessor_dataset(pkg_dict)
+        nt.assert_equal(successor, 'public4')
+        nt.assert_equal(predecessor, 'public2')
+
+    def test_it_returns_correct_for_public4(self):
+        pkg_dict = {u'name': u'public4'}
+        successor, predecessor = helpers_collection.get_successor_and_predecessor_dataset(pkg_dict)
+        nt.assert_equal(successor, 'public1')
+        nt.assert_equal(predecessor, 'public3')
+
+    def test_it_returns_correct_for_public1(self):
+        pkg_dict = {u'name': u'public1'}
+        successor, predecessor = helpers_collection.get_successor_and_predecessor_dataset(pkg_dict)
+        nt.assert_equal(successor, None)
+        nt.assert_equal(predecessor, 'public4')
+    
+    def test_it_returns_None_if_no_siblings(self):
+        with patch.object(
+            helpers_collection,
+            'get_all_datasets_belonging_to_collection_by_dataset',
+            return_value = list()
+        ):
+            pkg_dict = {u'name': u'some_name'}
+            successor, predecessor = helpers_collection.get_successor_and_predecessor_dataset(pkg_dict)
+            nt.assert_equal(successor, None)
+            nt.assert_equal(predecessor, None)
+
+
+class Test_is_within_last_month(object):
+    def test_it_returns_true_for_simple_query(self):
+        date = datetime.date(2019, 4, 15)
+        date_ref = datetime.date(2019, 4, 29)
+        assert is_within_last_month(date, date_ref)
+    
+    def test_it_uses_today_if_date_ref_missing(self):
+        date = datetime.date.today() - datetime.timedelta(days=20)
+        assert is_within_last_month(date)
+    
+    def test_it_returns_true_for_dates_in_different_years(self):
+        date = datetime.date(2018, 12, 16)
+        date_ref = datetime.date(2019, 1, 15)
+        assert is_within_last_month(date, date_ref)
+    
+    def test_it_returns_false_for_dates_in_different_years(self):
+        date = datetime.date(2018, 12, 15)
+        date_ref = datetime.date(2019, 1, 15)
+        assert is_within_last_month(date, date_ref)==False
+    
+    def test_it_returns_true_for_dates_in_differen_months(self):
+        date = datetime.date(2018, 6, 16)
+        date_ref = datetime.date(2018, 7, 10)
+        assert is_within_last_month(date, date_ref)
+    
+    def test_it_return_false_for_date_in_different_months(self):
+        date = datetime.date(2018, 6, 8)
+        date_ref = datetime.date(2018, 7, 10)
+        assert is_within_last_month(date, date_ref)==False
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_password_validation.py b/ckanext/odsh/tests_tpsh/test_password_validation.py
new file mode 100644
index 0000000000000000000000000000000000000000..c999b3974784df07d2da8c3d40ac1d9e11e8026d
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_password_validation.py
@@ -0,0 +1,35 @@
+# encoding: utf-8
+
+import nose.tools as nt
+from ckanext.odsh.logic.action import check_password
+
+class Test_PasswordValidation(object):
+
+    @staticmethod
+    def assert_password_invalid(password):
+        assert not check_password(password)
+    
+    @staticmethod
+    def assert_password_valid(password):
+        assert check_password(password)
+    
+    def test_valid_password(self):
+        self.assert_password_valid('Passwort1 :) :P :D')
+    
+    def test_umlaute(self):
+        self.assert_password_valid('Pässword')
+    
+    def test_no_uppercase(self):
+        self.assert_password_invalid('passwort1')
+    
+    def test_no_lowercase(self):
+        self.assert_password_invalid('PASSWORT1')
+    
+    def test_no_letters(self):
+        self.assert_password_invalid('37459073245!!?===))/=$§äüöÄÜÖ')
+    
+    def test_only_letters(self):
+        self.assert_password_invalid('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')
+    
+    def test_to_short(self):
+        self.assert_password_invalid('Pw123')
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_plugin.py b/ckanext/odsh/tests_tpsh/test_plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..e5084a4518c3639bba1956d4dac29f0606ad3c28
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_plugin.py
@@ -0,0 +1,52 @@
+import datetime
+
+import ckanext.odsh.plugin as plugin
+
+class TestMethodBeforeView(object):
+    date_time_format = '%Y-%m-%dT%H:%M:%S'
+
+    def test_before_view_adds_false_for_old_dataset(self):
+        plugin_object = plugin.OdshPlugin()
+        today = datetime.date.today()
+        hundred_days_ago = today - datetime.timedelta(days=100)
+        hundred_days_ago_as_ckan_str = self._date_as_ckan_str(hundred_days_ago)
+        dict_for_template = plugin_object.before_view(
+            {
+                u'extras': [
+                    {u'key': 'issued', u'value': hundred_days_ago_as_ckan_str}
+                ]
+            }
+        )
+        assert dict_for_template['is_new']==False
+
+    def _date_as_ckan_str(self, date):
+        return date.strftime(self.date_time_format)
+
+    def test_before_view_adds_true_for_new_dataset(self):
+        plugin_object = plugin.OdshPlugin()
+        today = datetime.date.today()
+        ten_days_ago = today - datetime.timedelta(days=10)
+        ten_days_ago_as_ckan_str = self._date_as_ckan_str(ten_days_ago)
+        dict_for_template = plugin_object.before_view(
+            {
+                u'extras': [
+                    {u'key': 'issued', u'value': ten_days_ago_as_ckan_str}
+                ]
+            }
+        )
+        assert dict_for_template['is_new']==True
+    
+    def test_before_view_does_not_modify_unconcerned_dict_values(self):
+        plugin_object = plugin.OdshPlugin()
+        today = datetime.date.today()
+        ten_days_ago = today - datetime.timedelta(days=10)
+        ten_days_ago_as_ckan_str = self._date_as_ckan_str(ten_days_ago)
+        dict_for_template = plugin_object.before_view(
+            {
+                u'extras': [
+                    {u'key': 'issued', u'value': ten_days_ago_as_ckan_str}
+                ],
+                'some_other_key': 'some_other_value', 
+            }
+        )
+        assert dict_for_template['some_other_key']=='some_other_value'
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_profiles.py b/ckanext/odsh/tests_tpsh/test_profiles.py
new file mode 100644
index 0000000000000000000000000000000000000000..0d6e859b98e3dcf8ec557ee0df1d2bd0160a9690
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_profiles.py
@@ -0,0 +1,184 @@
+import nose.tools as nt
+import rdflib
+from rdflib import Graph
+from mock import patch
+
+from ckanext.dcat.profiles import URIRefOrLiteral
+
+import ckanext.odsh.profiles as profiles
+import ckanext.odsh.helper_pkg_dict as helper_pkg_dict
+
+DCT = rdflib.namespace.Namespace("http://purl.org/dc/terms/")
+
+
+class TestODSHDCATdeProfileParseDatasetWithCollection(object):
+    '''
+    Tests for ODSHDCATdeProfile.parse_dataset with an rdf file 
+    containing a collection
+    '''
+    def setUp(self):
+        rdf_graph = Graph()
+        rdf_graph.parse('ckanext/odsh/tests_tpsh/resources/collection1.rdf')
+        self.profile = profiles.ODSHDCATdeProfile(rdf_graph)
+        self.dataset_ref_with_collection = URIRefOrLiteral(
+            'http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte'
+        )
+        self.dataset_ref_with_collection_member = URIRefOrLiteral(
+            'http://opendata.schleswig-holstein.de/dataset/LAsDSH_SER_Statistik_anerkannte_Versorgungsberechtigte_Monat_201704'
+        )
+        self.dataset_ref_with_member_not_in_collection = URIRefOrLiteral(
+            'http://opendata.schleswig-holstein.de/dataset/Test_nicht_in_Collection'
+        )
+    
+    def test_parse_dataset_adds_type_collection_to_dataset_dict(self):
+        dataset_dict = {}
+        self.profile.parse_dataset(dataset_dict, self.dataset_ref_with_collection)
+        nt.assert_equal('collection', dataset_dict['type'])
+    
+    def test_parse_dataset_adds_flag_for_collection_member(self):
+        dataset_dict = {}
+        self.profile.parse_dataset(dataset_dict, self.dataset_ref_with_collection_member)
+        nt.assert_equal(True, dataset_dict.get('add_to_collection'))
+    
+    def test_parse_type_adds_type_collection_to_dataset_dict(self):
+        dataset_dict = {}
+        self.profile._parse_type(dataset_dict, self.dataset_ref_with_collection)
+        nt.assert_equal('collection', dataset_dict['type'])
+
+    def test_parse_type_does_not_add_collection_to_dataset_dict(self):
+        dataset_dict = {}
+        self.profile._parse_type(dataset_dict, self.dataset_ref_with_collection_member)
+        nt.assert_not_in('type', dataset_dict)
+
+    def test_belongs_to_collection_returns_true(self):
+        dataset_dict = {}
+        assert self.profile._belongs_to_collection(dataset_dict, self.dataset_ref_with_collection_member)
+
+    def test_belongs_to_collection_returns_false(self):
+        dataset_dict = {}
+        belongs_to_collection = self.profile._belongs_to_collection(
+            dataset_dict, self.dataset_ref_with_member_not_in_collection)
+        nt.assert_false(belongs_to_collection)
+    
+
+class TestODSHDCATdeProfileParseDatasetWithSubject(object):
+    '''
+    Tests for ODSHDCATdeProfile.parse_dataset with an rdf file 
+    containing datasets with subjects
+    '''
+    def setUp(self):
+        rdf_graph = Graph()
+        rdf_graph.parse('ckanext/odsh/tests_tpsh/resources/transparenz.rdf')
+        self.profile = profiles.ODSHDCATdeProfile(rdf_graph)
+        self.dataset_ref_with_subject = URIRefOrLiteral(
+            'http://transparenz.schleswig-holstein.de/ae2a3cffda84388365bc87711ed4af47'
+        )
+
+    def test_parse_subject_returns_subject(self):
+        dataset_dict = {}
+        self.profile._parse_subject(dataset_dict, self.dataset_ref_with_subject)
+        nt.assert_equal('http://d-nb.info/gnd/4128022-2', dataset_dict['subject'])
+    
+    def test_parse_dataset_returns_subject(self):
+        dataset_dict = {}
+        self.profile.parse_dataset(dataset_dict, self.dataset_ref_with_subject)
+        nt.assert_equal('http://d-nb.info/gnd/4128022-2', dataset_dict['subject'])
+
+
+class TestODSHDCATdeProfileGraphFromDataset(object):
+    '''
+    Tests for ODSHDCATdeProfile.graph_from_dataset
+    '''
+    def setUp(self):
+        rdf_graph = Graph()
+        self.profile = profiles.ODSHDCATdeProfile(rdf_graph)
+        self.dummy_dataset_ref = URIRefOrLiteral('http://some_ref')
+    
+    def get_graph_and_assert_in(self, dataset_dict, dataset_ref, expected_node):
+        self.profile.graph_from_dataset(dataset_dict, dataset_ref)
+        graph_serialized = self.profile.g.serialize()
+        print(self.profile.g.serialize(format='pretty-xml'))
+        nt.assert_in(expected_node, graph_serialized)
+    
+    
+    patch_collection_member = patch.object(
+        profiles.ODSHDCATdeProfile, 
+        '_dataset_belongs_to_collection', 
+        return_value=True
+    )
+    
+    patch_no_collection_member = patch.object(
+        profiles.ODSHDCATdeProfile, 
+        '_dataset_belongs_to_collection', 
+        return_value=False
+    )
+
+    
+    @patch_no_collection_member
+    def test_it_adds_dct_subject(self, __):
+        dataset_dict = {
+            'subject': 'http://some_subject',
+            'type': 'dataset',
+            'groups': [],
+        }        
+        expected_node = '<dct:subject rdf:resource="http://some_subject"/>'
+        self.get_graph_and_assert_in(dataset_dict, self.dummy_dataset_ref, expected_node)
+    
+    
+    @patch_no_collection_member
+    def test_it_adds_dct_type_collection(self, __):
+        dataset_dict = {
+            'groups': [],
+            'type': 'collection',
+        }
+        expected_node = (
+            '<dct:type rdf:resource="http://dcat-ap.de/def/datasetTypes/collection"/>'
+        )
+        with patch.object(
+            profiles.ODSHDCATdeProfile, 
+            '_get_dataset_refs_belonging_to_collection', 
+            return_value=[]
+        ):
+            self.get_graph_and_assert_in(dataset_dict, self.dummy_dataset_ref, expected_node)
+    
+    
+    @patch_no_collection_member
+    def test_it_adds_members_of_collection(self, __):
+        '''
+        tests if rdf export of a collection  contains the members of that collection.
+        The members are read from the package relationships.
+        '''
+        dataset_dict = {
+            'groups': [],
+            'type': 'collection',
+        }
+        expected_nodes = (
+            '<dct:hasVersion rdf:resource="http://id_1"/>',
+            '<dct:hasVersion rdf:resource="http://id_2"/>',
+        )
+        # mock get_dataset_refs_belonging_to_collection(context, collection_name)
+        dataset_refs_belonging_to_collection = ['http://id_1', 'http://id_2']
+        with patch.object(
+            profiles.ODSHDCATdeProfile, 
+            '_get_dataset_refs_belonging_to_collection', 
+            return_value=dataset_refs_belonging_to_collection
+        ):
+            for expected_node in expected_nodes:
+                self.get_graph_and_assert_in(dataset_dict, self.dummy_dataset_ref, expected_node)
+    
+    def test_remove_predefined_collection_members(self):
+        rdf_graph = Graph()
+        self.profile = profiles.ODSHDCATdeProfile(rdf_graph)
+        dummy_ref = rdflib.URIRef('http://transparenz.schleswig-holstein.de/5ffd27c528f7ab6936318da90d5cdd63')
+        refs = (
+            'http://transparenz.schleswig-holstein.de/9bbeaf7b503dbd2c667786db08c4512d',
+            'http://transparenz.schleswig-holstein.de/f6de9c145fe28effe99fc163b92d657e'
+        )
+        for ref in refs:
+            self.profile.g.add(
+                (dummy_ref, DCT.hasVersion, rdflib.URIRef(ref))
+            )
+        self.profile._remove_predefined_collection_members()
+        graph_serialized = self.profile.g.serialize()
+        for ref in refs:
+            nt.assert_not_in(ref, graph_serialized)
\ No newline at end of file
diff --git a/ckanext/odsh/tests_tpsh/test_search.py b/ckanext/odsh/tests_tpsh/test_search.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e5008f9bf5dc88ecf3c0df5f224824319e9118a
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_search.py
@@ -0,0 +1,133 @@
+import nose.tools as nt
+import ckanext.odsh.search as search
+
+class Test_before_search(object):
+    def setUp(self):
+        self.search_params_before_test = {
+            'extras': {}, 
+            'facet.field': ['organization', 'subject_text', 'groups'], 
+            'fq': u'organization:"test-organisation" groups:"gove" subject_text:"T\xe4tigkeitsbericht" +dataset_type:dataset', 
+            'include_private': True, 
+            'q': u'', 
+            'rows': 20, 
+            'sort': u'score desc, metadata_modified desc', 
+            'start': 0
+        }
+        self.search_params_with_facet_mincount = self.search_params_before_test.copy()
+        self.search_params_with_facet_mincount.update({'facet.mincount': 0})
+    
+    def test_it_solely_adds_facet_mincount_to_dict_if_no_extras(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        # act
+        search.before_search(search_params)
+        # assert
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        nt.assert_equal(search_params, search_params_expected)
+
+    def test_it_adds_fq_if_empty_range(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        extras = {'ext_enddate': u'2019-08-01', 'ext_startdate': u'2019-08-02'}
+        search_params.update({'extras': extras})
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        search_params_expected.update({'extras': extras})
+        search_params_expected.update({
+            'fq': (
+                u'organization:"test-organisation" groups:"gove" subject_text:"T\xe4tigkeitsbericht" '
+                u'+dataset_type:dataset (+extras_temporal_start:[2019-08-02T00:00:00Z TO 2019-08-01T00:00:00Z] '
+                u'OR +extras_temporal_end:[2019-08-02T00:00:00Z TO 2019-08-01T00:00:00Z]  OR '
+                u'((*:* NOT extras_temporal_end:[* TO *]) AND extras_temporal_start:[* TO 2019-08-01T00:00:00Z]))'
+            )
+        })
+        # act
+        search.before_search(search_params)
+        # assert
+        nt.assert_equal(search_params, search_params_expected)
+    
+    def test_it_solely_adds_facet_mincount_to_dict_if_wrong_date_format_in_extras(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        extras = {'ext_enddate': u'some_date', 'ext_startdate': u'some_date'}
+        search_params.update({'extras': extras})
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        search_params_expected.update({'extras': extras})
+        # act
+        search.before_search(search_params)
+        # assert
+        nt.assert_equal(search_params, search_params_expected)
+    
+    def test_it_adds_fq_if_enclosing_range(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        extras = {'ext_enddate': u'2019-08-02', 'ext_startdate': u'2019-08-01'}
+        search_params.update({'extras': extras})
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        search_params_expected.update({'extras': extras})
+        search_params_expected.update({
+            'fq': (
+                u'organization:"test-organisation" groups:"gove" '
+                u'subject_text:"T\xe4tigkeitsbericht" +dataset_type:dataset '
+                u'(+extras_temporal_start:[2019-08-01T00:00:00Z TO 2019-08-02T00:00:00Z] '
+                u'OR +extras_temporal_end:[2019-08-01T00:00:00Z TO 2019-08-02T00:00:00Z]  '
+                u'OR (extras_temporal_start:[* TO 2019-08-01T00:00:00Z] AND '
+                u'extras_temporal_end:[2019-08-02T00:00:00Z TO *]) OR '
+                u'((*:* NOT extras_temporal_end:[* TO *]) AND '
+                u'extras_temporal_start:[* TO 2019-08-02T00:00:00Z]))'
+            )
+        })
+        # act
+        search.before_search(search_params)
+        # assert
+        nt.assert_equal(search_params, search_params_expected)
+
+    def test_it_adds_fq_if_start_only(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        extras = {'ext_startdate': u'2019-08-01'}
+        search_params.update({'extras': extras})
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        search_params_expected.update({'extras': extras})
+        search_params_expected.update({
+            'fq': (
+                u'organization:"test-organisation" groups:"gove" '
+                u'subject_text:"T\xe4tigkeitsbericht" +dataset_type:dataset '
+                u'(+extras_temporal_start:[2019-08-01T00:00:00Z TO *] '
+                u'OR +extras_temporal_end:[2019-08-01T00:00:00Z TO *]  '
+                u'OR (*:* NOT extras_temporal_end:[* TO *]))'
+            )
+        })
+        # act
+        search.before_search(search_params)
+        # assert
+        nt.assert_equal(search_params, search_params_expected)
+    
+    def test_it_adds_fq_if_end_only(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        extras = {'ext_enddate': u'2019-08-02'}
+        search_params.update({'extras': extras})
+        search_params_expected = self.search_params_with_facet_mincount.copy()
+        search_params_expected.update({'extras': extras})
+        search_params_expected.update({
+            'fq': (
+                u'organization:"test-organisation" groups:"gove" '
+                u'subject_text:"T\xe4tigkeitsbericht" +dataset_type:dataset '
+                u'(+extras_temporal_start:[* TO 2019-08-02T00:00:00Z] OR '
+                u'+extras_temporal_end:[* TO 2019-08-02T00:00:00Z]  '
+                u'OR ((*:* NOT extras_temporal_end:[* TO *]) '
+                u'AND extras_temporal_start:[* TO 2019-08-02T00:00:00Z]))'
+            )
+        })
+        # act
+        search.before_search(search_params)
+        # assert
+        nt.assert_equal(search_params, search_params_expected)
+    
+    def test_it_returns_search_params(self):
+        # arange
+        search_params = self.search_params_before_test.copy()
+        # act
+        return_value = search.before_search(search_params)
+        # assert
+        nt.assert_equal(return_value, search_params)
diff --git a/ckanext/odsh/tests_tpsh/test_uri_store.py b/ckanext/odsh/tests_tpsh/test_uri_store.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fc92f09df43419cc3375dcd3188c0697e6d9e69
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_uri_store.py
@@ -0,0 +1,38 @@
+import nose.tools as nt
+from ckanext.odsh.uri_store import add_uri, get_id_from_uri, _set_uri_to_id, _get_uri_to_id
+
+class Test_uri_store(object):
+    def test_add_uri_adds_values_to_dict(self):
+        _set_uri_to_id({u'http://some_uri': u'some_id'})
+        dataset_dict = {
+            'id': u'some_new_id',
+            u'extras': [
+                {u'key': u'uri', u'value': u'http://some_new_uri'},
+            ]
+        }
+        add_uri(dataset_dict)
+        nt.assert_equal(
+            _get_uri_to_id().get('http://some_uri'),
+            u'some_id'
+        )
+        nt.assert_equal(
+            _get_uri_to_id().get('http://some_new_uri'),
+            u'some_new_id'
+        )
+    
+    def test_get_id_returns_id(self):
+        _set_uri_to_id({u'http://some_uri': u'some_id'})
+        uri = 'http://some_uri'
+        id = get_id_from_uri(uri)
+        id_expected = u'some_id'
+        nt.assert_equal(id, id_expected)
+    
+    def test_get_id_from_uri_returns_None_if_dict_empty(self):
+        _set_uri_to_id({})
+        id = get_id_from_uri('some_uri')
+        nt.assert_equal(id, None)
+    
+    def test_get_id_from_uri_returns_None_if_id_unknown(self):
+        _set_uri_to_id({'uri_to_id': {u'http://some_uri': u'some_id'}})
+        id = get_id_from_uri('some_unknown_id')
+        nt.assert_equal(id, None)
\ No newline at end of file
diff --git a/ckanext/odsh/tools.py b/ckanext/odsh/tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab7c1ba60885d1a4589b1bc533f9d22e4d74d27b
--- /dev/null
+++ b/ckanext/odsh/tools.py
@@ -0,0 +1,45 @@
+import os
+from ckanext.odsh.pdf_to_thumbnail.thumbnail import get_filepath_to_resource
+from ckanext.odsh.lib.uploader import calculate_hash
+import ckan.plugins.toolkit as toolkit
+import magic
+import pdftotext
+
+def add_attributes_resources(context, resource):
+    package_id = resource.get('package_id')
+    package = toolkit.get_action('package_show')(context, {'id': package_id})
+    resources = package.get('resources')
+    i = 0
+    for item in resources:    
+        if item.get('id') == resource.get('id'):
+            path = get_filepath_to_resource(resource)
+            if os.path.exists(path):
+                with open(path, 'rb') as file:                  
+                    
+                    #size
+                    if not item.get('size'):
+                        resource_size = os.path.getsize(path)
+                        item.update({'size': resource_size})
+                    
+                    #hash
+                    file.seek(0)
+                    hash = calculate_hash(file)
+                    item.update({'hash':hash})
+                    
+                    #hash algorithm
+                    item.update({'hash_algorithm': 'http://dcat-ap.de/def/hashAlgorithms/md/5'})
+                    
+            
+                    #number of pages
+                    file_type = magic.from_file(path, mime = True)                    
+                    if file_type == 'application/pdf':
+                        file.seek(0)            
+                        pdf = pdftotext.PDF(file)
+                        number_of_pages = len(pdf)
+                        item.update({'number_of_pages':number_of_pages})
+
+                    resources[i] = item 
+            break                         
+        i = i + 1  
+    package.update({'resources':resources})
+    toolkit.get_action('package_update')(context, package)
diff --git a/ckanext/odsh/uri_store/__init__.py b/ckanext/odsh/uri_store/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..8f72f0e2a35f457b004d2a60703ca917a2fb864e
--- /dev/null
+++ b/ckanext/odsh/uri_store/__init__.py
@@ -0,0 +1 @@
+from modifiers import add_uri, get_id_from_uri, _set_uri_to_id, _get_uri_to_id
\ No newline at end of file
diff --git a/ckanext/odsh/uri_store/modifiers.py b/ckanext/odsh/uri_store/modifiers.py
new file mode 100644
index 0000000000000000000000000000000000000000..4fc1175b1bf10d870aca353edb6b5eddc38b0f34
--- /dev/null
+++ b/ckanext/odsh/uri_store/modifiers.py
@@ -0,0 +1,20 @@
+import store 
+
+import ckanext.odsh.helpers as odsh_helpers
+
+def add_uri(dataset_dict):
+    uri = odsh_helpers.odsh_extract_value_from_extras(
+        dataset_dict.get('extras'), 'uri'
+    )
+    id = dataset_dict.get('id')
+    store.uri_to_id.update({uri: id})
+
+def get_id_from_uri(uri):
+    id = store.uri_to_id.get(uri)
+    return id
+
+def _set_uri_to_id(new_uri_to_id):
+    store.uri_to_id = new_uri_to_id
+
+def _get_uri_to_id():
+    return store.uri_to_id
\ No newline at end of file
diff --git a/ckanext/odsh/uri_store/store.py b/ckanext/odsh/uri_store/store.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d152d8eee425ee7af34e5f6e618d7a9fb668ea0
--- /dev/null
+++ b/ckanext/odsh/uri_store/store.py
@@ -0,0 +1 @@
+uri_to_id = {}
\ No newline at end of file
diff --git a/ckanext/odsh/validation.py b/ckanext/odsh/validation.py
index e50cbb4394ddbcc447a7fe87d200e738ba6019e6..a1e5338ec9e15795c7cab51ccf728c4fc38e0246 100644
--- a/ckanext/odsh/validation.py
+++ b/ckanext/odsh/validation.py
@@ -1,6 +1,6 @@
 # This Python file uses the following encoding: utf-8
 import logging
-import csv
+import unicodecsv as csv
 import re
 import urllib2
 import json
@@ -33,12 +33,13 @@ def _extract_value(data, field):
 
 def validate_extra_groups(data, requireAtLeastOne, errors):
     value = _extract_value(data, 'groups')
+    error_message_no_group = 'at least one group needed'
     if value != None:
         # 'value != None' means the extra key 'groups' was found,
         # so the dataset came from manual editing via the web-frontend.
         if not value:
             if requireAtLeastOne:
-                errors['groups'] = 'at least one group needed'
+                errors['groups'] = error_message_no_group
             data[('groups', 0, 'id')] = ''
             return
 
@@ -49,7 +50,7 @@ def validate_extra_groups(data, requireAtLeastOne, errors):
                 # del data[k]
         if len(groups) == 0:
             if requireAtLeastOne:
-                errors['groups'] = 'at least one group needed'
+                errors['groups'] = error_message_no_group
             return
 
         for num, group in zip(range(len(groups)), groups):
@@ -58,22 +59,59 @@ def validate_extra_groups(data, requireAtLeastOne, errors):
         # dataset might come from a harvest process
         if not data.get(('groups', 0, 'id'), False) and \
            not data.get(('groups', 0, 'name'), False):
-            errors['groups'] = 'at least one group needed'
+            errors['groups'] = error_message_no_group
 
 
 def validate_extras(key, data, errors, context):
     extra_errors = {}
+    
     isStaNord = ('id',) in data and data[('id',)][:7] == 'StaNord'
-
-    validate_extra_groups(data, True, extra_errors)
-    validate_extra_date_new(key, 'issued', data, isStaNord, extra_errors)
-    validate_extra_date_new(key, 'temporal_start',
-                            data, isStaNord, extra_errors)
-    validate_extra_date_new(key, 'temporal_end', data, True, extra_errors)
+    is_optional_temporal_start = toolkit.asbool(
+        config.get('ckanext.odsh.is_optional_temporal_start', False)
+    ) or isStaNord
+
+    require_at_least_one_category = toolkit.asbool(
+        config.get('ckanext.odsh.require_at_least_one_category', False)
+    )
+    validate_extra_groups(
+        data=data, 
+        requireAtLeastOne=require_at_least_one_category, 
+        errors=extra_errors
+    )
+    
+    is_date_start_before_date_end(data, extra_errors)
+    
+    validate_extra_date_new(
+        key=key,
+        field='issued',
+        data=data,
+        optional=isStaNord,
+        errors=extra_errors
+    )
+    validate_extra_date_new(
+        key=key,
+        field='temporal_start',
+        data=data,
+        optional=is_optional_temporal_start, 
+        errors=extra_errors
+    )
+    validate_extra_date_new(
+        key=key,
+        field='temporal_end',
+        data=data,
+        optional=True,
+        errors=extra_errors
+    )
 
     if len(extra_errors.values()):
         raise toolkit.Invalid(extra_errors)
 
+def is_date_start_before_date_end(data, extra_errors):
+    start_date = _extract_value(data, 'temporal_start')
+    end_date = _extract_value(data, 'temporal_end')
+    if start_date and end_date:
+        if start_date > end_date:
+            extra_errors['temporal_start'] = extra_errors['temporal_end'] = 'Please enter a valid period of time.'
 
 def _set_value(data, field, value):
     key = None
@@ -141,7 +179,13 @@ def validate_licenseAttributionByText(key, data, errors, context):
 
 
 def known_spatial_uri(key, data, errors, context):
+    if data.get(('__extras',)) and 'spatial_uri_temp' in data.get(('__extras',)):
+        _copy_spatial_uri_temp_to_extras(data)
     value = _extract_value(data, 'spatial_uri')
+    require_spatial_uri = toolkit.asbool(
+        config.get('ckanext.odsh.require_spatial_uri', False)
+    )
+    error_message_spatial_uri_empty = 'spatial_uri: empty not allowed'
 
     if not value:
         poly = None
@@ -157,8 +201,10 @@ def known_spatial_uri(key, data, errors, context):
             has_old_uri = old_uri != None and len(old_uri) > 0
             if not poly:
                 poly = pkg.extras.get('spatial', None)
-        if not poly or has_old_uri:
-            raise toolkit.Invalid('spatial_uri: empty not allowed')
+        if (not poly) and require_spatial_uri:
+            raise toolkit.Invalid(error_message_spatial_uri_empty)
+        if has_old_uri and require_spatial_uri:
+            raise toolkit.Invalid(error_message_spatial_uri_empty)
         else:
             if poly:
                 new_index = next_extra_index(data)
@@ -175,9 +221,9 @@ def known_spatial_uri(key, data, errors, context):
     not_found = True
     spatial_text = str()
     spatial = str()
-    cr = csv.reader(mapping_file, delimiter="\t")
+    cr = csv.reader(mapping_file, delimiter="\t", encoding='utf-8')
     for row in cr:
-        if row[0].encode('UTF-8') == value:
+        if row[0] == value:
             not_found = False
             spatial_text = row[1]
             loaded = json.loads(row[2])
@@ -195,6 +241,21 @@ def known_spatial_uri(key, data, errors, context):
     data[('extras', new_index+1, 'value')] = spatial
 
 
+def _copy_spatial_uri_temp_to_extras(data):
+    '''
+    copy the field spatial_uri_temp originating 
+    from the user interface to extras
+    '''
+    spatial_uri = data.get(('__extras',)).get('spatial_uri_temp')
+    is_spatial_uri_in_extras = _extract_value(data, 'spatial_uri') is not None
+    if not is_spatial_uri_in_extras:
+        next_index = next_extra_index(data)
+        data[('extras', next_index, 'key')] = 'spatial_uri'
+        data[('extras', next_index, 'value')] = spatial_uri
+    else:
+        _set_value(data, 'spatial_uri', spatial_uri)
+    
+
 def next_extra_index(data):
     current_indexes = [k[1] for k in data.keys()
                        if len(k) > 1 and k[0] == 'extras']
@@ -232,10 +293,65 @@ def tag_string_convert(key, data, errors, context):
         tag_name_validator(tag, context)
 
 
+def _convert_subjectID_to_subjectText(subject_id, flattened_data):
+
+    if not subject_id:
+        return flattened_data
+
+    default_subject_mapping_file_path = '/usr/lib/ckan/default/src/ckanext-odsh/subject_mapping.json'
+    subject_mapping_file_path = config.get(
+        'ckanext.odsh.subject_mapping_file_path', default_subject_mapping_file_path)
+    
+    try:
+        with open(subject_mapping_file_path) as mapping_json:
+             subject_mapping = json.loads(mapping_json.read())
+    except IOError as err:
+        log.error(
+            'Could not load subject mapping file from {}'
+            .format(subject_mapping_file_path)
+        )
+        raise
+    except ValueError as err:
+        log.error(
+            'Could not convert subject mapping file from json. \nSubject mapping file: {}'
+            .format(subject_mapping_file_path)
+        )
+        raise
+    
+    try: 
+        subject_text = subject_mapping[subject_id]
+    except:
+        raise toolkit.Invalid(_('Subject must be a known URI.'))
+        log.warning(
+            'Subject_id "{}" not found in subject mapping dictionary.\nSubject mapping file: {}'
+            .format(subject_id, subject_mapping_file_path)
+        )
+        
+
+    new_index = next_extra_index(flattened_data)
+    flattened_data[('extras', new_index, 'key')] = 'subject_text'
+    flattened_data[('extras', new_index, 'value')] = subject_text
+    return flattened_data
+
+
+def validate_subject(key, flattened_data, errors, context):
+    subject_id = flattened_data[key]
+    require_subject = toolkit.asbool(
+        config.get('ckanext.odsh.require_subject', True)
+    )
+    if not require_subject:
+        flattened_data = _convert_subjectID_to_subjectText(subject_id, flattened_data)
+        return
+    if not subject_id:
+        raise toolkit.Invalid(_('Subject must not be empty.'))
+    flattened_data = _convert_subjectID_to_subjectText(subject_id, flattened_data)
+
+
 def get_validators():
     return {
         'known_spatial_uri': known_spatial_uri,
         'odsh_tag_name_validator': tag_name_validator,
         'odsh_validate_extras': validate_extras,
-        'validate_licenseAttributionByText': validate_licenseAttributionByText
+        'validate_licenseAttributionByText': validate_licenseAttributionByText,
+        'tpsh_validate_subject': validate_subject,
     }
diff --git a/dev-requirements.txt b/dev-requirements.txt
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c574e4eaf013c487e6c63e0048eb9132b71c2627 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -0,0 +1,185 @@
+alabaster==0.7.11
+amqp==1.4.9
+anyjson==0.3.3
+arrow==0.13.1
+asn1crypto==0.24.0
+astroid==1.6.6
+atomicwrites==1.3.0
+attrs==19.3.0
+Babel==2.3.4
+backports.functools-lru-cache==1.5
+Beaker==1.8.1
+beautifulsoup4==4.5.1
+billiard==3.3.0.23
+bleach==1.5.0
+blinker==1.4
+celery==3.1.25
+certifi==2018.8.13
+cffi==1.11.5
+chardet==3.0.4
+click==6.7
+configparser==3.7.4
+contextlib2==0.6.0.post1
+cookies==2.2.1
+coverage==4.5.1
+coveralls==1.3.0
+cryptography==2.3
+decorator==4.0.6
+defusedxml==0.6.0
+dnspython==1.16.0
+docopt==0.6.2
+docutils==0.12
+entrypoints==0.3
+enum34==1.1.6
+eventlet==0.24.1
+extras==1.0.0
+factory-boy==2.1.1
+fanstatic==0.12
+filehash==0.1.dev3
+first==2.0.1
+fixtures==3.0.0
+flake8==3.7.8
+Flask==0.11.1
+Flask-DebugToolbar==0.10.0
+FormEncode==1.3.0
+funcsigs==1.0.2
+functools32==3.2.3.post2
+futures==3.3.0
+GeoAlchemy==0.7.2
+GeoAlchemy2==0.4.2
+geolinks==0.2.0
+geomet==0.2.0.post2
+greenlet==0.4.15
+html5lib==0.9999999
+httpretty==0.8.3
+hupper==1.6.1
+idna==2.7
+imagesize==1.0.0
+importlib-metadata==0.23
+ipaddress==1.0.22
+isodate==0.6.0
+isort==4.3.21
+itsdangerous==0.24
+Jinja2==2.8
+json-table-schema==0.2.1
+kombu==3.0.37
+lazy-object-proxy==1.4.1
+linecache2==1.0.0
+lxml==3.6.2
+Mako==1.0.4
+Markdown==2.6.7
+MarkupSafe==0.23
+mccabe==0.6.1
+messytables==0.15.2
+mock==2.0.0
+monotonic==1.5
+more-itertools==5.0.0
+mox3==0.26.0
+multiline-log-formatter==0.1.8
+nose==1.3.7
+ofs==0.4.2
+ordereddict==1.1
+OWSLib==0.16.0
+packaging==17.1
+Pairtree===0.7.1-T
+passlib==1.6.5
+Paste==1.7.5.1
+PasteDeploy==2.0.1
+PasteScript==2.0.2
+pathlib==1.0.1
+pathlib2==2.3.5
+pbr==1.10.0
+pdf2image==1.9.0
+pdftotext==2.1.2
+pika==0.12.0
+Pillow==6.1.0
+pip-tools==1.7.0
+piwikapi==0.3
+pkg-resources==0.0.0
+plaster==1.0
+plaster-pastedeploy==0.7
+pluggy==0.13.0
+polib==1.0.7
+progressbar==2.3
+psycopg2==2.7.3.2
+py==1.8.0
+pyasn1==0.4.8
+pycodestyle==2.5.0
+pycountry==18.5.26
+pycparser==2.18
+pycrypto==2.6.1
+pycryptodome==3.9.0
+pycsw==2.2.0
+pyfakefs==2.9
+pyflakes==2.1.1
+Pygments==2.1.3
+pylint==1.9.5
+Pylons==0.9.7
+pymongo==3.9.0
+pyOpenSSL==18.0.0
+pyparsing==2.2.0
+pyproj==1.9.5.1
+pyramid==1.10.4
+pyramid-exclog==0.1
+-e git+https://github.com/IdentityPython/pysaml2.git@247e2f642b37de90a61c4f5ca49d8403840b6ea2#egg=pysaml2
+pysolr==3.6.0
+pytest==4.6.6
+pytest-cov==2.8.1
+python-dateutil==2.8.0
+python-json-logger==0.1.11
+python-magic==0.4.12
+python-memcached==1.48
+python-mimeparse==1.6.0
+pytz==2016.7
+pyutilib.component.core==4.6.4
+rdflib==4.2.1
+rdflib-jsonld==0.4.0
+redis==2.10.1
+repoze.lru==0.6
+repoze.who==2.3
+repoze.who-friendlyform==1.0.8
+requests==2.11.1
+responses==0.10.6
+rope==0.14.0
+Routes==1.13
+rq==0.6.0
+rq-dashboard==0.4.0
+scandir==1.10.0
+selenium==3.141.0
+Shapely==1.5.17
+simplejson==3.10.0
+singledispatch==3.4.0.3
+six==1.10.0
+snowballstemmer==1.2.1
+SPARQLWrapper==1.8.2
+Sphinx==1.7.1
+sphinx-rtd-theme==0.3.1
+sphinxcontrib-websupport==1.1.0
+SQLAlchemy==0.9.6
+sqlalchemy-migrate==0.10.0
+sqlparse==0.2.2
+Tempita==0.5.2
+testfixtures==6.10.3
+testtools==2.3.0
+traceback2==1.4.0
+translationstring==1.3
+typing==3.6.4
+tzlocal==1.3
+unicodecsv==0.14.1
+unittest2==1.1.0
+urllib3==1.23
+vdm==0.13
+venusian==1.2.0
+vine==1.1.4
+wcwidth==0.1.7
+WebError==0.13.1
+WebHelpers==1.3
+WebOb==1.0.8
+WebTest==1.4.3
+Werkzeug==0.11.10
+wrapt==1.11.2
+xlrd==1.0.0
+xmltodict==0.10.2
+zipp==0.6.0
+zope.deprecation==4.4.0
+zope.interface==4.3.2
diff --git a/language_mapping.json b/language_mapping.json
new file mode 100644
index 0000000000000000000000000000000000000000..808122e6d854b0e9ea1bd006e474830017ef1dc2
--- /dev/null
+++ b/language_mapping.json
@@ -0,0 +1,5 @@
+{
+    "http://publications.europa.eu/resource/authority/language/DAN":"Dänisch",
+    "http://publications.europa.eu/resource/authority/language/DEU":"Deutsch",
+    "http://publications.europa.eu/resource/authority/language/ENG":"Englisch"
+}
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 83c9faa80e481fef6c586113897a26bc7bc9b949..524de62fd1f8a0134be3fbf616914c1e64692ac9 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,4 +3,8 @@ ckanext-harvest
 ckanext-spatial
 lxml
 piwikapi
-multiline-log-formatter
\ No newline at end of file
+multiline-log-formatter
+filehash==0.1.dev3
+pdf2image==1.9.0
+pathlib
+pdftotext
diff --git a/setup.py b/setup.py
index e1a98ffc15ae06b7b6a0972f7d34a726114984a2..56287f08b92df2409200a83f764ab61a294c50df 100755
--- a/setup.py
+++ b/setup.py
@@ -81,13 +81,14 @@ setup(
     entry_points='''
         [ckan.plugins]
         odsh=ckanext.odsh.plugin:OdshPlugin
-        odsh_icap=ckanext.odsh.plugin:OdshIcapPlugin
+        odsh_icap=ckanext.odsh.plugin_odsh_icap:OdshIcapPlugin
         statistikamtnord_harvester=ckanext.odsh.harvesters:StatistikamtNordHarvester
         kiel_harvester=ckanext.odsh.harvesters:KielHarvester
-        odsh_autocomplete=ckanext.odsh.plugin:OdshAutocompletePlugin
-        odsh_harvest=ckanext.odsh.plugin:OdshHarvestPlugin
-        odsh_dcat_harvest=ckanext.odsh.plugin:OdshDCATHarvestPlugin
-
+        odsh_autocomplete=ckanext.odsh.plugin_odsh_autocomplete:OdshAutocompletePlugin
+        odsh_harvest=ckanext.odsh.plugin_odsh_harvest:OdshHarvestPlugin
+        odsh_dcat_harvest=ckanext.odsh.plugin_odsh_dcat_harvest:OdshDCATHarvestPlugin
+        tpsh_collections=ckanext.odsh.collection.plugin:CollectionsPlugin
+        thumbnail=ckanext.odsh.pdf_to_thumbnail.plugin:ThumbnailPlugin
         [paste.paster_command]
         odsh_initialization = ckanext.odsh.commands.initialization:Initialization
 
diff --git a/subject_mapping.json b/subject_mapping.json
new file mode 100644
index 0000000000000000000000000000000000000000..97ebe1718d106fb679478595aff84c4acab1c26d
--- /dev/null
+++ b/subject_mapping.json
@@ -0,0 +1,25 @@
+{
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Verwaltungsvorschrift": "Verwaltungsvorschrift",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Organisationsplan": "Organisationsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Geschaeftsverteilungsplan": "Geschäftsverteilungsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Aktenplan": "Aktenplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Richtlinie": "Richtlinie und Runderlass",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Statistik": "amtliche Statistik",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Taetigkeitsbericht": "Tätigkeitsbericht",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Broschuere": "Broschüre",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Gutachten": "Gutachten",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Studie": "Studie",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Haushaltsplan": "Haushaltsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Stellenplan": "Stellenplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Wirtschaftsplan": "Wirtschaftsplan",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#ZuwendungAnPerson": "Übersicht über Zuwendungen an juristische Personen des Privatrechts",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#ZuwendungAnLand": "Übersicht über Zuwendungen an das Land Schleswig-Holstein",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#IZGAntwort": "IZG/GvgV-Auskunft",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Gerichtsurteil": "Gerichtsurteil",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#GesetzvorlageLandtag": "Gesetzesvorlage an den Landtag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#MitteilungLandtag": "Mitteilung an den Landtag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Unternehmensdaten": "wesentliche Unternehmensdaten von Beteiligungen des Landes",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#VergütungsOG": "jährliche Vergütungen nach dem VergütungsOG",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#Vertrag": "Vertrag",
+    "http://transparenz.schleswig-holstein.de/informationsgegenstand#sonstiges": "zusätzliche freiwillige Information"
+}