diff --git a/.jupyter/api_authentication/models/database_dto.py b/.jupyter/api_authentication/models/database_dto.py
index 9974642be9b7daba87c73e2e70f0af2d961ef7b9..baeaf0e46fa9a534e439e687533e6e6e86300d83 100644
--- a/.jupyter/api_authentication/models/database_dto.py
+++ b/.jupyter/api_authentication/models/database_dto.py
@@ -117,8 +117,7 @@ class DatabaseDto(object):
         if deleted is not None:
             self.deleted = deleted
         self.internal_name = internal_name
-        if publication_year is not None:
-            self.publication_year = publication_year
+        self.publication_year = publication_year
         if is_public is not None:
             self.is_public = is_public
 
@@ -492,6 +491,8 @@ class DatabaseDto(object):
         :param publication_year: The publication_year of this DatabaseDto.  # noqa: E501
         :type: int
         """
+        if publication_year is None:
+            raise ValueError("Invalid value for `publication_year`, must not be `None`")  # noqa: E501
 
         self._publication_year = publication_year
 
diff --git a/.jupyter/api_container/models/database_dto.py b/.jupyter/api_container/models/database_dto.py
index ef38b6a7d5a6a992f54b8e51d8f0455f45dd5ec4..0aa1b92b3db1bf2fd768ccff07f61361a4a56f21 100644
--- a/.jupyter/api_container/models/database_dto.py
+++ b/.jupyter/api_container/models/database_dto.py
@@ -117,8 +117,7 @@ class DatabaseDto(object):
         if deleted is not None:
             self.deleted = deleted
         self.internal_name = internal_name
-        if publication_year is not None:
-            self.publication_year = publication_year
+        self.publication_year = publication_year
         if is_public is not None:
             self.is_public = is_public
 
@@ -492,6 +491,8 @@ class DatabaseDto(object):
         :param publication_year: The publication_year of this DatabaseDto.  # noqa: E501
         :type: int
         """
+        if publication_year is None:
+            raise ValueError("Invalid value for `publication_year`, must not be `None`")  # noqa: E501
 
         self._publication_year = publication_year
 
diff --git a/.jupyter/api_database/models/database_dto.py b/.jupyter/api_database/models/database_dto.py
index 6e485faa9dc4f0dea3b7c3bae4063ab1be1135c7..52e21473a2256ae38d006e121c8080abecc2b7ad 100644
--- a/.jupyter/api_database/models/database_dto.py
+++ b/.jupyter/api_database/models/database_dto.py
@@ -117,8 +117,7 @@ class DatabaseDto(object):
         if deleted is not None:
             self.deleted = deleted
         self.internal_name = internal_name
-        if publication_year is not None:
-            self.publication_year = publication_year
+        self.publication_year = publication_year
         if is_public is not None:
             self.is_public = is_public
 
@@ -492,6 +491,8 @@ class DatabaseDto(object):
         :param publication_year: The publication_year of this DatabaseDto.  # noqa: E501
         :type: int
         """
+        if publication_year is None:
+            raise ValueError("Invalid value for `publication_year`, must not be `None`")  # noqa: E501
 
         self._publication_year = publication_year
 
diff --git a/.jupyter/api_query/api/table_data_endpoint_api.py b/.jupyter/api_query/api/table_data_endpoint_api.py
index 8f34b37dacac4db3543dd2def4951d0d24501b87..632bf0023c0c979119e43647dec551cf4bc744ad 100644
--- a/.jupyter/api_query/api/table_data_endpoint_api.py
+++ b/.jupyter/api_query/api/table_data_endpoint_api.py
@@ -259,7 +259,7 @@ class TableDataEndpointApi(object):
         auth_settings = ['bearerAuth']  # noqa: E501
 
         return self.api_client.call_api(
-            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET',
+            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD',
             path_params,
             query_params,
             header_params,
@@ -380,7 +380,7 @@ class TableDataEndpointApi(object):
         auth_settings = ['bearerAuth']  # noqa: E501
 
         return self.api_client.call_api(
-            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'HEAD',
+            '/api/container/{id}/database/{databaseId}/table/{tableId}/data', 'GET',
             path_params,
             query_params,
             header_params,
diff --git a/.jupyter/api_query/models/database_dto.py b/.jupyter/api_query/models/database_dto.py
index 008562a718b764a529bfdfbc6d14c04d0d3f9d7b..a6cbe93ef828694fc41e70f0dc370ee8fdd900f0 100644
--- a/.jupyter/api_query/models/database_dto.py
+++ b/.jupyter/api_query/models/database_dto.py
@@ -117,8 +117,7 @@ class DatabaseDto(object):
         if deleted is not None:
             self.deleted = deleted
         self.internal_name = internal_name
-        if publication_year is not None:
-            self.publication_year = publication_year
+        self.publication_year = publication_year
         if is_public is not None:
             self.is_public = is_public
 
@@ -492,6 +491,8 @@ class DatabaseDto(object):
         :param publication_year: The publication_year of this DatabaseDto.  # noqa: E501
         :type: int
         """
+        if publication_year is None:
+            raise ValueError("Invalid value for `publication_year`, must not be `None`")  # noqa: E501
 
         self._publication_year = publication_year
 
diff --git a/.jupyter/api_units/__init__.py b/.jupyter/api_units/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c957b741e1db37d91b16cf96b692225e94af901
--- /dev/null
+++ b/.jupyter/api_units/__init__.py
@@ -0,0 +1,25 @@
+# coding: utf-8
+
+# flake8: noqa
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+# import apis into sdk package
+from api_units.api.default_api import DefaultApi
+# import ApiClient
+from api_units.api_client import ApiClient
+from api_units.configuration import Configuration
+# import models into sdk package
+from api_units.models.units_savecolumnsconcept_body import UnitsSavecolumnsconceptBody
+from api_units.models.units_saveconcept_body import UnitsSaveconceptBody
+from api_units.models.units_suggest_body import UnitsSuggestBody
diff --git a/.jupyter/api_units/api/__init__.py b/.jupyter/api_units/api/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e0a0fa250b70cb3f7dea9bcc5941dea5a85d763f
--- /dev/null
+++ b/.jupyter/api_units/api/__init__.py
@@ -0,0 +1,6 @@
+from __future__ import absolute_import
+
+# flake8: noqa
+
+# import apis into api package
+from api_units.api.default_api import DefaultApi
diff --git a/.jupyter/api_units/api/default_api.py b/.jupyter/api_units/api/default_api.py
new file mode 100644
index 0000000000000000000000000000000000000000..9de20b4fd5c4600ed24a84f4255b683d99b77536
--- /dev/null
+++ b/.jupyter/api_units/api/default_api.py
@@ -0,0 +1,500 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+import re  # noqa: F401
+
+# python 2 and python 3 compatibility library
+import six
+
+from api_units.api_client import ApiClient
+
+
+class DefaultApi(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    Ref: https://github.com/swagger-api/swagger-codegen
+    """
+
+    def __init__(self, api_client=None):
+        if api_client is None:
+            api_client = ApiClient()
+        self.api_client = api_client
+
+    def api_units_savecolumnsconcept_post(self, body, **kwargs):  # noqa: E501
+        """Save concepts to MDB  # noqa: E501
+
+        This is a simple API for saving units and concepts.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_savecolumnsconcept_post(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSavecolumnsconceptBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.api_units_savecolumnsconcept_post_with_http_info(body, **kwargs)  # noqa: E501
+        else:
+            (data) = self.api_units_savecolumnsconcept_post_with_http_info(body, **kwargs)  # noqa: E501
+            return data
+
+    def api_units_savecolumnsconcept_post_with_http_info(self, body, **kwargs):  # noqa: E501
+        """Save concepts to MDB  # noqa: E501
+
+        This is a simple API for saving units and concepts.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_savecolumnsconcept_post_with_http_info(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSavecolumnsconceptBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['body']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method api_units_savecolumnsconcept_post" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'body' is set
+        if ('body' not in params or
+                params['body'] is None):
+            raise ValueError("Missing the required parameter `body` when calling `api_units_savecolumnsconcept_post`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        if 'body' in params:
+            body_params = params['body']
+        # HTTP header `Content-Type`
+        header_params['Content-Type'] = self.api_client.select_header_content_type(  # noqa: E501
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/api/units/savecolumnsconcept', 'POST',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def api_units_saveconcept_post(self, body, **kwargs):  # noqa: E501
+        """Save concepts to MDB  # noqa: E501
+
+        This is a simple API for saving units and concepts.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_saveconcept_post(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSaveconceptBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.api_units_saveconcept_post_with_http_info(body, **kwargs)  # noqa: E501
+        else:
+            (data) = self.api_units_saveconcept_post_with_http_info(body, **kwargs)  # noqa: E501
+            return data
+
+    def api_units_saveconcept_post_with_http_info(self, body, **kwargs):  # noqa: E501
+        """Save concepts to MDB  # noqa: E501
+
+        This is a simple API for saving units and concepts.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_saveconcept_post_with_http_info(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSaveconceptBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['body']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method api_units_saveconcept_post" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'body' is set
+        if ('body' not in params or
+                params['body'] is None):
+            raise ValueError("Missing the required parameter `body` when calling `api_units_saveconcept_post`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        if 'body' in params:
+            body_params = params['body']
+        # HTTP header `Content-Type`
+        header_params['Content-Type'] = self.api_client.select_header_content_type(  # noqa: E501
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/api/units/saveconcept', 'POST',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def api_units_suggest_post(self, body, **kwargs):  # noqa: E501
+        """Autosuggest units  # noqa: E501
+
+        This is a simple API which returns a list of suggested units.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_suggest_post(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSuggestBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.api_units_suggest_post_with_http_info(body, **kwargs)  # noqa: E501
+        else:
+            (data) = self.api_units_suggest_post_with_http_info(body, **kwargs)  # noqa: E501
+            return data
+
+    def api_units_suggest_post_with_http_info(self, body, **kwargs):  # noqa: E501
+        """Autosuggest units  # noqa: E501
+
+        This is a simple API which returns a list of suggested units.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_suggest_post_with_http_info(body, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param UnitsSuggestBody body: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['body']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method api_units_suggest_post" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'body' is set
+        if ('body' not in params or
+                params['body'] is None):
+            raise ValueError("Missing the required parameter `body` when calling `api_units_suggest_post`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        if 'body' in params:
+            body_params = params['body']
+        # HTTP header `Content-Type`
+        header_params['Content-Type'] = self.api_client.select_header_content_type(  # noqa: E501
+            ['application/json'])  # noqa: E501
+
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/api/units/suggest', 'POST',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def api_units_uri_uname_get(self, uname, **kwargs):  # noqa: E501
+        """Get URI of units  # noqa: E501
+
+        This is a simple API for getting the URI of a certain unit in OM.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_uri_uname_get(uname, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str uname: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.api_units_uri_uname_get_with_http_info(uname, **kwargs)  # noqa: E501
+        else:
+            (data) = self.api_units_uri_uname_get_with_http_info(uname, **kwargs)  # noqa: E501
+            return data
+
+    def api_units_uri_uname_get_with_http_info(self, uname, **kwargs):  # noqa: E501
+        """Get URI of units  # noqa: E501
+
+        This is a simple API for getting the URI of a certain unit in OM.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_uri_uname_get_with_http_info(uname, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str uname: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['uname']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method api_units_uri_uname_get" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'uname' is set
+        if ('uname' not in params or
+                params['uname'] is None):
+            raise ValueError("Missing the required parameter `uname` when calling `api_units_uri_uname_get`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+        if 'uname' in params:
+            path_params['uname'] = params['uname']  # noqa: E501
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/api/units/uri/{uname}', 'GET',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
+
+    def api_units_validate_unit_get(self, unit, **kwargs):  # noqa: E501
+        """Validate units  # noqa: E501
+
+        This is a simple API for validating units.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_validate_unit_get(unit, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str unit: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+        kwargs['_return_http_data_only'] = True
+        if kwargs.get('async_req'):
+            return self.api_units_validate_unit_get_with_http_info(unit, **kwargs)  # noqa: E501
+        else:
+            (data) = self.api_units_validate_unit_get_with_http_info(unit, **kwargs)  # noqa: E501
+            return data
+
+    def api_units_validate_unit_get_with_http_info(self, unit, **kwargs):  # noqa: E501
+        """Validate units  # noqa: E501
+
+        This is a simple API for validating units.  # noqa: E501
+        This method makes a synchronous HTTP request by default. To make an
+        asynchronous HTTP request, please pass async_req=True
+        >>> thread = api.api_units_validate_unit_get_with_http_info(unit, async_req=True)
+        >>> result = thread.get()
+
+        :param async_req bool
+        :param str unit: to-do description (required)
+        :return: None
+                 If the method is called asynchronously,
+                 returns the request thread.
+        """
+
+        all_params = ['unit']  # noqa: E501
+        all_params.append('async_req')
+        all_params.append('_return_http_data_only')
+        all_params.append('_preload_content')
+        all_params.append('_request_timeout')
+
+        params = locals()
+        for key, val in six.iteritems(params['kwargs']):
+            if key not in all_params:
+                raise TypeError(
+                    "Got an unexpected keyword argument '%s'"
+                    " to method api_units_validate_unit_get" % key
+                )
+            params[key] = val
+        del params['kwargs']
+        # verify the required parameter 'unit' is set
+        if ('unit' not in params or
+                params['unit'] is None):
+            raise ValueError("Missing the required parameter `unit` when calling `api_units_validate_unit_get`")  # noqa: E501
+
+        collection_formats = {}
+
+        path_params = {}
+        if 'unit' in params:
+            path_params['unit'] = params['unit']  # noqa: E501
+
+        query_params = []
+
+        header_params = {}
+
+        form_params = []
+        local_var_files = {}
+
+        body_params = None
+        # Authentication setting
+        auth_settings = []  # noqa: E501
+
+        return self.api_client.call_api(
+            '/api/units/validate/{unit}', 'GET',
+            path_params,
+            query_params,
+            header_params,
+            body=body_params,
+            post_params=form_params,
+            files=local_var_files,
+            response_type=None,  # noqa: E501
+            auth_settings=auth_settings,
+            async_req=params.get('async_req'),
+            _return_http_data_only=params.get('_return_http_data_only'),
+            _preload_content=params.get('_preload_content', True),
+            _request_timeout=params.get('_request_timeout'),
+            collection_formats=collection_formats)
diff --git a/.jupyter/api_units/api_client.py b/.jupyter/api_units/api_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..36201d73283cdae2ea1e5cfb656c63a6de6f74d8
--- /dev/null
+++ b/.jupyter/api_units/api_client.py
@@ -0,0 +1,632 @@
+# coding: utf-8
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+from __future__ import absolute_import
+
+import datetime
+import json
+import mimetypes
+from multiprocessing.pool import ThreadPool
+import os
+import re
+import tempfile
+
+# python 2 and python 3 compatibility library
+import six
+from six.moves.urllib.parse import quote
+
+from api_units.configuration import Configuration
+import api_units.models
+from api_units import rest
+
+
+class ApiClient(object):
+    """Generic API client for Swagger client library builds.
+
+    Swagger generic API client. This client handles the client-
+    server communication, and is invariant across implementations. Specifics of
+    the methods and models for each application are generated from the Swagger
+    templates.
+
+    NOTE: This class is auto generated by the swagger code generator program.
+    Ref: https://github.com/swagger-api/swagger-codegen
+    Do not edit the class manually.
+
+    :param configuration: .Configuration object for this client
+    :param header_name: a header to pass when making calls to the API.
+    :param header_value: a header value to pass when making calls to
+        the API.
+    :param cookie: a cookie to include in the header when making calls
+        to the API
+    """
+
+    PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types
+    NATIVE_TYPES_MAPPING = {
+        'int': int,
+        'long': int if six.PY3 else long,  # noqa: F821
+        'float': float,
+        'str': str,
+        'bool': bool,
+        'date': datetime.date,
+        'datetime': datetime.datetime,
+        'object': object,
+    }
+
+    def __init__(self, configuration=None, header_name=None, header_value=None,
+                 cookie=None):
+        if configuration is None:
+            configuration = Configuration()
+        self.configuration = configuration
+
+        self.pool = ThreadPool()
+        self.rest_client = rest.RESTClientObject(configuration)
+        self.default_headers = {}
+        if header_name is not None:
+            self.default_headers[header_name] = header_value
+        self.cookie = cookie
+        # Set default User-Agent.
+        self.user_agent = 'Swagger-Codegen/1.0.0/python'
+
+    def __del__(self):
+        self.pool.close()
+        self.pool.join()
+
+    @property
+    def user_agent(self):
+        """User agent for this API client"""
+        return self.default_headers['User-Agent']
+
+    @user_agent.setter
+    def user_agent(self, value):
+        self.default_headers['User-Agent'] = value
+
+    def set_default_header(self, header_name, header_value):
+        self.default_headers[header_name] = header_value
+
+    def __call_api(
+            self, resource_path, method, path_params=None,
+            query_params=None, header_params=None, body=None, post_params=None,
+            files=None, response_type=None, auth_settings=None,
+            _return_http_data_only=None, collection_formats=None,
+            _preload_content=True, _request_timeout=None):
+
+        config = self.configuration
+
+        # header parameters
+        header_params = header_params or {}
+        header_params.update(self.default_headers)
+        if self.cookie:
+            header_params['Cookie'] = self.cookie
+        if header_params:
+            header_params = self.sanitize_for_serialization(header_params)
+            header_params = dict(self.parameters_to_tuples(header_params,
+                                                           collection_formats))
+
+        # path parameters
+        if path_params:
+            path_params = self.sanitize_for_serialization(path_params)
+            path_params = self.parameters_to_tuples(path_params,
+                                                    collection_formats)
+            for k, v in path_params:
+                # specified safe chars, encode everything
+                resource_path = resource_path.replace(
+                    '{%s}' % k,
+                    quote(str(v), safe=config.safe_chars_for_path_param)
+                )
+
+        # query parameters
+        if query_params:
+            query_params = self.sanitize_for_serialization(query_params)
+            query_params = self.parameters_to_tuples(query_params,
+                                                     collection_formats)
+
+        # post parameters
+        if post_params or files:
+            post_params = self.prepare_post_parameters(post_params, files)
+            post_params = self.sanitize_for_serialization(post_params)
+            post_params = self.parameters_to_tuples(post_params,
+                                                    collection_formats)
+
+        # auth setting
+        self.update_params_for_auth(header_params, query_params, auth_settings)
+
+        # body
+        if body:
+            body = self.sanitize_for_serialization(body)
+
+        # request url
+        url = self.configuration.host + resource_path
+
+        # perform request and return response
+        response_data = self.request(
+            method, url, query_params=query_params, headers=header_params,
+            post_params=post_params, body=body,
+            _preload_content=_preload_content,
+            _request_timeout=_request_timeout)
+
+        self.last_response = response_data
+
+        return_data = response_data
+        if _preload_content:
+            # deserialize response data
+            if response_type:
+                return_data = self.deserialize(response_data, response_type)
+            else:
+                return_data = None
+
+        if _return_http_data_only:
+            return (return_data)
+        else:
+            return (return_data, response_data.status,
+                    response_data.getheaders())
+
+    def sanitize_for_serialization(self, obj):
+        """Builds a JSON POST object.
+
+        If obj is None, return None.
+        If obj is str, int, long, float, bool, return directly.
+        If obj is datetime.datetime, datetime.date
+            convert to string in iso8601 format.
+        If obj is list, sanitize each element in the list.
+        If obj is dict, return the dict.
+        If obj is swagger model, return the properties dict.
+
+        :param obj: The data to serialize.
+        :return: The serialized form of data.
+        """
+        if obj is None:
+            return None
+        elif isinstance(obj, self.PRIMITIVE_TYPES):
+            return obj
+        elif isinstance(obj, list):
+            return [self.sanitize_for_serialization(sub_obj)
+                    for sub_obj in obj]
+        elif isinstance(obj, tuple):
+            return tuple(self.sanitize_for_serialization(sub_obj)
+                         for sub_obj in obj)
+        elif isinstance(obj, (datetime.datetime, datetime.date)):
+            return obj.isoformat()
+
+        if isinstance(obj, dict):
+            obj_dict = obj
+        else:
+            # Convert model obj to dict except
+            # attributes `swagger_types`, `attribute_map`
+            # and attributes which value is not None.
+            # Convert attribute name to json key in
+            # model definition for request.
+            obj_dict = {obj.attribute_map[attr]: getattr(obj, attr)
+                        for attr, _ in six.iteritems(obj.swagger_types)
+                        if getattr(obj, attr) is not None}
+
+        return {key: self.sanitize_for_serialization(val)
+                for key, val in six.iteritems(obj_dict)}
+
+    def deserialize(self, response, response_type):
+        """Deserializes response into an object.
+
+        :param response: RESTResponse object to be deserialized.
+        :param response_type: class literal for
+            deserialized object, or string of class name.
+
+        :return: deserialized object.
+        """
+        # handle file downloading
+        # save response body into a tmp file and return the instance
+        if response_type == "file":
+            return self.__deserialize_file(response)
+
+        # fetch data from response object
+        try:
+            data = json.loads(response.data)
+        except ValueError:
+            data = response.data
+
+        return self.__deserialize(data, response_type)
+
+    def __deserialize(self, data, klass):
+        """Deserializes dict, list, str into an object.
+
+        :param data: dict, list or str.
+        :param klass: class literal, or string of class name.
+
+        :return: object.
+        """
+        if data is None:
+            return None
+
+        if type(klass) == str:
+            if klass.startswith('list['):
+                sub_kls = re.match(r'list\[(.*)\]', klass).group(1)
+                return [self.__deserialize(sub_data, sub_kls)
+                        for sub_data in data]
+
+            if klass.startswith('dict('):
+                sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2)
+                return {k: self.__deserialize(v, sub_kls)
+                        for k, v in six.iteritems(data)}
+
+            # convert str to class
+            if klass in self.NATIVE_TYPES_MAPPING:
+                klass = self.NATIVE_TYPES_MAPPING[klass]
+            else:
+                klass = getattr(api_units.models, klass)
+
+        if klass in self.PRIMITIVE_TYPES:
+            return self.__deserialize_primitive(data, klass)
+        elif klass == object:
+            return self.__deserialize_object(data)
+        elif klass == datetime.date:
+            return self.__deserialize_date(data)
+        elif klass == datetime.datetime:
+            return self.__deserialize_datatime(data)
+        else:
+            return self.__deserialize_model(data, klass)
+
+    def call_api(self, resource_path, method,
+                 path_params=None, query_params=None, header_params=None,
+                 body=None, post_params=None, files=None,
+                 response_type=None, auth_settings=None, async_req=None,
+                 _return_http_data_only=None, collection_formats=None,
+                 _preload_content=True, _request_timeout=None):
+        """Makes the HTTP request (synchronous) and returns deserialized data.
+
+        To make an async request, set the async_req parameter.
+
+        :param resource_path: Path to method endpoint.
+        :param method: Method to call.
+        :param path_params: Path parameters in the url.
+        :param query_params: Query parameters in the url.
+        :param header_params: Header parameters to be
+            placed in the request header.
+        :param body: Request body.
+        :param post_params dict: Request post form parameters,
+            for `application/x-www-form-urlencoded`, `multipart/form-data`.
+        :param auth_settings list: Auth Settings names for the request.
+        :param response: Response data type.
+        :param files dict: key -> filename, value -> filepath,
+            for `multipart/form-data`.
+        :param async_req bool: execute request asynchronously
+        :param _return_http_data_only: response data without head status code
+                                       and headers
+        :param collection_formats: dict of collection formats for path, query,
+            header, and post parameters.
+        :param _preload_content: if False, the urllib3.HTTPResponse object will
+                                 be returned without reading/decoding response
+                                 data. Default is True.
+        :param _request_timeout: timeout setting for this request. If one
+                                 number provided, it will be total request
+                                 timeout. It can also be a pair (tuple) of
+                                 (connection, read) timeouts.
+        :return:
+            If async_req parameter is True,
+            the request will be called asynchronously.
+            The method will return the request thread.
+            If parameter async_req is False or missing,
+            then the method will return the response directly.
+        """
+        if not async_req:
+            return self.__call_api(resource_path, method,
+                                   path_params, query_params, header_params,
+                                   body, post_params, files,
+                                   response_type, auth_settings,
+                                   _return_http_data_only, collection_formats,
+                                   _preload_content, _request_timeout)
+        else:
+            thread = self.pool.apply_async(self.__call_api, (resource_path,
+                                           method, path_params, query_params,
+                                           header_params, body,
+                                           post_params, files,
+                                           response_type, auth_settings,
+                                           _return_http_data_only,
+                                           collection_formats,
+                                           _preload_content, _request_timeout))
+        return thread
+
+    def request(self, method, url, query_params=None, headers=None,
+                post_params=None, body=None, _preload_content=True,
+                _request_timeout=None):
+        """Makes the HTTP request using RESTClient."""
+        if method == "GET":
+            return self.rest_client.GET(url,
+                                        query_params=query_params,
+                                        _preload_content=_preload_content,
+                                        _request_timeout=_request_timeout,
+                                        headers=headers)
+        elif method == "HEAD":
+            return self.rest_client.HEAD(url,
+                                         query_params=query_params,
+                                         _preload_content=_preload_content,
+                                         _request_timeout=_request_timeout,
+                                         headers=headers)
+        elif method == "OPTIONS":
+            return self.rest_client.OPTIONS(url,
+                                            query_params=query_params,
+                                            headers=headers,
+                                            post_params=post_params,
+                                            _preload_content=_preload_content,
+                                            _request_timeout=_request_timeout,
+                                            body=body)
+        elif method == "POST":
+            return self.rest_client.POST(url,
+                                         query_params=query_params,
+                                         headers=headers,
+                                         post_params=post_params,
+                                         _preload_content=_preload_content,
+                                         _request_timeout=_request_timeout,
+                                         body=body)
+        elif method == "PUT":
+            return self.rest_client.PUT(url,
+                                        query_params=query_params,
+                                        headers=headers,
+                                        post_params=post_params,
+                                        _preload_content=_preload_content,
+                                        _request_timeout=_request_timeout,
+                                        body=body)
+        elif method == "PATCH":
+            return self.rest_client.PATCH(url,
+                                          query_params=query_params,
+                                          headers=headers,
+                                          post_params=post_params,
+                                          _preload_content=_preload_content,
+                                          _request_timeout=_request_timeout,
+                                          body=body)
+        elif method == "DELETE":
+            return self.rest_client.DELETE(url,
+                                           query_params=query_params,
+                                           headers=headers,
+                                           _preload_content=_preload_content,
+                                           _request_timeout=_request_timeout,
+                                           body=body)
+        else:
+            raise ValueError(
+                "http method must be `GET`, `HEAD`, `OPTIONS`,"
+                " `POST`, `PATCH`, `PUT` or `DELETE`."
+            )
+
+    def parameters_to_tuples(self, params, collection_formats):
+        """Get parameters as list of tuples, formatting collections.
+
+        :param params: Parameters as dict or list of two-tuples
+        :param dict collection_formats: Parameter collection formats
+        :return: Parameters as list of tuples, collections formatted
+        """
+        new_params = []
+        if collection_formats is None:
+            collection_formats = {}
+        for k, v in six.iteritems(params) if isinstance(params, dict) else params:  # noqa: E501
+            if k in collection_formats:
+                collection_format = collection_formats[k]
+                if collection_format == 'multi':
+                    new_params.extend((k, value) for value in v)
+                else:
+                    if collection_format == 'ssv':
+                        delimiter = ' '
+                    elif collection_format == 'tsv':
+                        delimiter = '\t'
+                    elif collection_format == 'pipes':
+                        delimiter = '|'
+                    else:  # csv is the default
+                        delimiter = ','
+                    new_params.append(
+                        (k, delimiter.join(str(value) for value in v)))
+            else:
+                new_params.append((k, v))
+        return new_params
+
+    def prepare_post_parameters(self, post_params=None, files=None):
+        """Builds form parameters.
+
+        :param post_params: Normal form parameters.
+        :param files: File parameters.
+        :return: Form parameters with files.
+        """
+        params = []
+
+        if post_params:
+            params = post_params
+
+        if files:
+            for k, v in six.iteritems(files):
+                if not v:
+                    continue
+                file_names = v if type(v) is list else [v]
+                for n in file_names:
+                    with open(n, 'rb') as f:
+                        filename = os.path.basename(f.name)
+                        filedata = f.read()
+                        mimetype = (mimetypes.guess_type(filename)[0] or
+                                    'application/octet-stream')
+                        params.append(
+                            tuple([k, tuple([filename, filedata, mimetype])]))
+
+        return params
+
+    def select_header_accept(self, accepts):
+        """Returns `Accept` based on an array of accepts provided.
+
+        :param accepts: List of headers.
+        :return: Accept (e.g. application/json).
+        """
+        if not accepts:
+            return
+
+        accepts = [x.lower() for x in accepts]
+
+        if 'application/json' in accepts:
+            return 'application/json'
+        else:
+            return ', '.join(accepts)
+
+    def select_header_content_type(self, content_types):
+        """Returns `Content-Type` based on an array of content_types provided.
+
+        :param content_types: List of content-types.
+        :return: Content-Type (e.g. application/json).
+        """
+        if not content_types:
+            return 'application/json'
+
+        content_types = [x.lower() for x in content_types]
+
+        if 'application/json' in content_types or '*/*' in content_types:
+            return 'application/json'
+        else:
+            return content_types[0]
+
+    def update_params_for_auth(self, headers, querys, auth_settings):
+        """Updates header and query params based on authentication setting.
+
+        :param headers: Header parameters dict to be updated.
+        :param querys: Query parameters tuple list to be updated.
+        :param auth_settings: Authentication setting identifiers list.
+        """
+        if not auth_settings:
+            return
+
+        for auth in auth_settings:
+            auth_setting = self.configuration.auth_settings().get(auth)
+            if auth_setting:
+                if not auth_setting['value']:
+                    continue
+                elif auth_setting['in'] == 'header':
+                    headers[auth_setting['key']] = auth_setting['value']
+                elif auth_setting['in'] == 'query':
+                    querys.append((auth_setting['key'], auth_setting['value']))
+                else:
+                    raise ValueError(
+                        'Authentication token must be in `query` or `header`'
+                    )
+
+    def __deserialize_file(self, response):
+        """Deserializes body to file
+
+        Saves response body into a file in a temporary folder,
+        using the filename from the `Content-Disposition` header if provided.
+
+        :param response:  RESTResponse.
+        :return: file path.
+        """
+        fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path)
+        os.close(fd)
+        os.remove(path)
+
+        content_disposition = response.getheader("Content-Disposition")
+        if content_disposition:
+            filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?',
+                                 content_disposition).group(1)
+            path = os.path.join(os.path.dirname(path), filename)
+            response_data = response.data
+            with open(path, "wb") as f:
+                if isinstance(response_data, str):
+                    # change str to bytes so we can write it
+                    response_data = response_data.encode('utf-8')
+                    f.write(response_data)
+                else:
+                    f.write(response_data)
+        return path
+
+    def __deserialize_primitive(self, data, klass):
+        """Deserializes string to primitive type.
+
+        :param data: str.
+        :param klass: class literal.
+
+        :return: int, long, float, str, bool.
+        """
+        try:
+            return klass(data)
+        except UnicodeEncodeError:
+            return six.text_type(data)
+        except TypeError:
+            return data
+
+    def __deserialize_object(self, value):
+        """Return a original value.
+
+        :return: object.
+        """
+        return value
+
+    def __deserialize_date(self, string):
+        """Deserializes string to date.
+
+        :param string: str.
+        :return: date.
+        """
+        try:
+            from dateutil.parser import parse
+            return parse(string).date()
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0,
+                reason="Failed to parse `{0}` as date object".format(string)
+            )
+
+    def __deserialize_datatime(self, string):
+        """Deserializes string to datetime.
+
+        The string should be in iso8601 datetime format.
+
+        :param string: str.
+        :return: datetime.
+        """
+        try:
+            from dateutil.parser import parse
+            return parse(string)
+        except ImportError:
+            return string
+        except ValueError:
+            raise rest.ApiException(
+                status=0,
+                reason=(
+                    "Failed to parse `{0}` as datetime object"
+                    .format(string)
+                )
+            )
+
+    def __hasattr(self, object, name):
+            return name in object.__class__.__dict__
+
+    def __deserialize_model(self, data, klass):
+        """Deserializes list or dict to model.
+
+        :param data: dict, list.
+        :param klass: class literal.
+        :return: model object.
+        """
+
+        if not klass.swagger_types and not self.__hasattr(klass, 'get_real_child_model'):
+            return data
+
+        kwargs = {}
+        if klass.swagger_types is not None:
+            for attr, attr_type in six.iteritems(klass.swagger_types):
+                if (data is not None and
+                        klass.attribute_map[attr] in data and
+                        isinstance(data, (list, dict))):
+                    value = data[klass.attribute_map[attr]]
+                    kwargs[attr] = self.__deserialize(value, attr_type)
+
+        instance = klass(**kwargs)
+
+        if (isinstance(instance, dict) and
+                klass.swagger_types is not None and
+                isinstance(data, dict)):
+            for key, value in data.items():
+                if key not in klass.swagger_types:
+                    instance[key] = value
+        if self.__hasattr(instance, 'get_real_child_model'):
+            klass_name = instance.get_real_child_model(data)
+            if klass_name:
+                instance = self.__deserialize(data, klass_name)
+        return instance
diff --git a/.jupyter/api_units/configuration.py b/.jupyter/api_units/configuration.py
new file mode 100644
index 0000000000000000000000000000000000000000..d9746a635357a967d7864586c7e7f480262dba9b
--- /dev/null
+++ b/.jupyter/api_units/configuration.py
@@ -0,0 +1,244 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+import copy
+import logging
+import multiprocessing
+import sys
+import urllib3
+
+import six
+from six.moves import http_client as httplib
+
+
+class TypeWithDefault(type):
+    def __init__(cls, name, bases, dct):
+        super(TypeWithDefault, cls).__init__(name, bases, dct)
+        cls._default = None
+
+    def __call__(cls):
+        if cls._default is None:
+            cls._default = type.__call__(cls)
+        return copy.copy(cls._default)
+
+    def set_default(cls, default):
+        cls._default = copy.copy(default)
+
+
+class Configuration(six.with_metaclass(TypeWithDefault, object)):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Ref: https://github.com/swagger-api/swagger-codegen
+    Do not edit the class manually.
+    """
+
+    def __init__(self):
+        """Constructor"""
+        # Default Base url
+        self.host = "http://localhost:9095"
+        # Temp file folder for downloading files
+        self.temp_folder_path = None
+
+        # Authentication Settings
+        # dict to store API key(s)
+        self.api_key = {}
+        # dict to store API prefix (e.g. Bearer)
+        self.api_key_prefix = {}
+        # function to refresh API key if expired
+        self.refresh_api_key_hook = None
+        # Username for HTTP basic authentication
+        self.username = ""
+        # Password for HTTP basic authentication
+        self.password = ""
+        # Logging Settings
+        self.logger = {}
+        self.logger["package_logger"] = logging.getLogger("api_units")
+        self.logger["urllib3_logger"] = logging.getLogger("urllib3")
+        # Log format
+        self.logger_format = '%(asctime)s %(levelname)s %(message)s'
+        # Log stream handler
+        self.logger_stream_handler = None
+        # Log file handler
+        self.logger_file_handler = None
+        # Debug file location
+        self.logger_file = None
+        # Debug switch
+        self.debug = False
+
+        # SSL/TLS verification
+        # Set this to false to skip verifying SSL certificate when calling API
+        # from https server.
+        self.verify_ssl = True
+        # Set this to customize the certificate file to verify the peer.
+        self.ssl_ca_cert = None
+        # client certificate file
+        self.cert_file = None
+        # client key file
+        self.key_file = None
+        # Set this to True/False to enable/disable SSL hostname verification.
+        self.assert_hostname = None
+
+        # urllib3 connection pool's maximum number of connections saved
+        # per pool. urllib3 uses 1 connection as default value, but this is
+        # not the best value when you are making a lot of possibly parallel
+        # requests to the same host, which is often the case here.
+        # cpu_count * 5 is used as default value to increase performance.
+        self.connection_pool_maxsize = multiprocessing.cpu_count() * 5
+
+        # Proxy URL
+        self.proxy = None
+        # Safe chars for path_param
+        self.safe_chars_for_path_param = ''
+
+    @property
+    def logger_file(self):
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        return self.__logger_file
+
+    @logger_file.setter
+    def logger_file(self, value):
+        """The logger file.
+
+        If the logger_file is None, then add stream handler and remove file
+        handler. Otherwise, add file handler and remove stream handler.
+
+        :param value: The logger_file path.
+        :type: str
+        """
+        self.__logger_file = value
+        if self.__logger_file:
+            # If set logging file,
+            # then add file handler and remove stream handler.
+            self.logger_file_handler = logging.FileHandler(self.__logger_file)
+            self.logger_file_handler.setFormatter(self.logger_formatter)
+            for _, logger in six.iteritems(self.logger):
+                logger.addHandler(self.logger_file_handler)
+                if self.logger_stream_handler:
+                    logger.removeHandler(self.logger_stream_handler)
+        else:
+            # If not set logging file,
+            # then add stream handler and remove file handler.
+            self.logger_stream_handler = logging.StreamHandler()
+            self.logger_stream_handler.setFormatter(self.logger_formatter)
+            for _, logger in six.iteritems(self.logger):
+                logger.addHandler(self.logger_stream_handler)
+                if self.logger_file_handler:
+                    logger.removeHandler(self.logger_file_handler)
+
+    @property
+    def debug(self):
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        return self.__debug
+
+    @debug.setter
+    def debug(self, value):
+        """Debug status
+
+        :param value: The debug status, True or False.
+        :type: bool
+        """
+        self.__debug = value
+        if self.__debug:
+            # if debug status is True, turn on debug logging
+            for _, logger in six.iteritems(self.logger):
+                logger.setLevel(logging.DEBUG)
+            # turn on httplib debug
+            httplib.HTTPConnection.debuglevel = 1
+        else:
+            # if debug status is False, turn off debug logging,
+            # setting log level to default `logging.WARNING`
+            for _, logger in six.iteritems(self.logger):
+                logger.setLevel(logging.WARNING)
+            # turn off httplib debug
+            httplib.HTTPConnection.debuglevel = 0
+
+    @property
+    def logger_format(self):
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        return self.__logger_format
+
+    @logger_format.setter
+    def logger_format(self, value):
+        """The logger format.
+
+        The logger_formatter will be updated when sets logger_format.
+
+        :param value: The format string.
+        :type: str
+        """
+        self.__logger_format = value
+        self.logger_formatter = logging.Formatter(self.__logger_format)
+
+    def get_api_key_with_prefix(self, identifier):
+        """Gets API key (with prefix if set).
+
+        :param identifier: The identifier of apiKey.
+        :return: The token for api key authentication.
+        """
+        if self.refresh_api_key_hook:
+            self.refresh_api_key_hook(self)
+
+        key = self.api_key.get(identifier)
+        if key:
+            prefix = self.api_key_prefix.get(identifier)
+            if prefix:
+                return "%s %s" % (prefix, key)
+            else:
+                return key
+
+    def get_basic_auth_token(self):
+        """Gets HTTP basic authentication header (string).
+
+        :return: The token for basic HTTP authentication.
+        """
+        return urllib3.util.make_headers(
+            basic_auth=self.username + ':' + self.password
+        ).get('authorization')
+
+    def auth_settings(self):
+        """Gets Auth Settings dict for api client.
+
+        :return: The Auth Settings information dict.
+        """
+        return {
+        }
+
+    def to_debug_report(self):
+        """Gets the essential information for debugging.
+
+        :return: The report for debugging.
+        """
+        return "Python SDK Debug Report:\n"\
+               "OS: {env}\n"\
+               "Python Version: {pyversion}\n"\
+               "Version of the API: 0.0.1\n"\
+               "SDK Package Version: 1.0.0".\
+               format(env=sys.platform, pyversion=sys.version)
diff --git a/.jupyter/api_units/models/__init__.py b/.jupyter/api_units/models/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..08e7322d4595851ab810ec897cd98917b07fdeb2
--- /dev/null
+++ b/.jupyter/api_units/models/__init__.py
@@ -0,0 +1,19 @@
+# coding: utf-8
+
+# flake8: noqa
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+# import models into model package
+from api_units.models.units_savecolumnsconcept_body import UnitsSavecolumnsconceptBody
+from api_units.models.units_saveconcept_body import UnitsSaveconceptBody
+from api_units.models.units_suggest_body import UnitsSuggestBody
diff --git a/.jupyter/api_units/models/units_savecolumnsconcept_body.py b/.jupyter/api_units/models/units_savecolumnsconcept_body.py
new file mode 100644
index 0000000000000000000000000000000000000000..1237b414feffa530b7b014493c40e6daf6ae40da
--- /dev/null
+++ b/.jupyter/api_units/models/units_savecolumnsconcept_body.py
@@ -0,0 +1,188 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+class UnitsSavecolumnsconceptBody(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'cdbid': 'int',
+        'cid': 'int',
+        'tid': 'int',
+        'uri': 'str'
+    }
+
+    attribute_map = {
+        'cdbid': 'cdbid',
+        'cid': 'cid',
+        'tid': 'tid',
+        'uri': 'uri'
+    }
+
+    def __init__(self, cdbid=None, cid=None, tid=None, uri=None):  # noqa: E501
+        """UnitsSavecolumnsconceptBody - a model defined in Swagger"""  # noqa: E501
+        self._cdbid = None
+        self._cid = None
+        self._tid = None
+        self._uri = None
+        self.discriminator = None
+        if cdbid is not None:
+            self.cdbid = cdbid
+        if cid is not None:
+            self.cid = cid
+        if tid is not None:
+            self.tid = tid
+        if uri is not None:
+            self.uri = uri
+
+    @property
+    def cdbid(self):
+        """Gets the cdbid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+
+
+        :return: The cdbid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :rtype: int
+        """
+        return self._cdbid
+
+    @cdbid.setter
+    def cdbid(self, cdbid):
+        """Sets the cdbid of this UnitsSavecolumnsconceptBody.
+
+
+        :param cdbid: The cdbid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :type: int
+        """
+
+        self._cdbid = cdbid
+
+    @property
+    def cid(self):
+        """Gets the cid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+
+
+        :return: The cid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :rtype: int
+        """
+        return self._cid
+
+    @cid.setter
+    def cid(self, cid):
+        """Sets the cid of this UnitsSavecolumnsconceptBody.
+
+
+        :param cid: The cid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :type: int
+        """
+
+        self._cid = cid
+
+    @property
+    def tid(self):
+        """Gets the tid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+
+
+        :return: The tid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :rtype: int
+        """
+        return self._tid
+
+    @tid.setter
+    def tid(self, tid):
+        """Sets the tid of this UnitsSavecolumnsconceptBody.
+
+
+        :param tid: The tid of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :type: int
+        """
+
+        self._tid = tid
+
+    @property
+    def uri(self):
+        """Gets the uri of this UnitsSavecolumnsconceptBody.  # noqa: E501
+
+
+        :return: The uri of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :rtype: str
+        """
+        return self._uri
+
+    @uri.setter
+    def uri(self, uri):
+        """Sets the uri of this UnitsSavecolumnsconceptBody.
+
+
+        :param uri: The uri of this UnitsSavecolumnsconceptBody.  # noqa: E501
+        :type: str
+        """
+
+        self._uri = uri
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(UnitsSavecolumnsconceptBody, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, UnitsSavecolumnsconceptBody):
+            return False
+
+        return self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        return not self == other
diff --git a/.jupyter/api_units/models/units_saveconcept_body.py b/.jupyter/api_units/models/units_saveconcept_body.py
new file mode 100644
index 0000000000000000000000000000000000000000..16fcdacc063f5f608a6e65034ada792420a0961e
--- /dev/null
+++ b/.jupyter/api_units/models/units_saveconcept_body.py
@@ -0,0 +1,136 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+class UnitsSaveconceptBody(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'name': 'str',
+        'uri': 'str'
+    }
+
+    attribute_map = {
+        'name': 'name',
+        'uri': 'uri'
+    }
+
+    def __init__(self, name=None, uri=None):  # noqa: E501
+        """UnitsSaveconceptBody - a model defined in Swagger"""  # noqa: E501
+        self._name = None
+        self._uri = None
+        self.discriminator = None
+        if name is not None:
+            self.name = name
+        if uri is not None:
+            self.uri = uri
+
+    @property
+    def name(self):
+        """Gets the name of this UnitsSaveconceptBody.  # noqa: E501
+
+
+        :return: The name of this UnitsSaveconceptBody.  # noqa: E501
+        :rtype: str
+        """
+        return self._name
+
+    @name.setter
+    def name(self, name):
+        """Sets the name of this UnitsSaveconceptBody.
+
+
+        :param name: The name of this UnitsSaveconceptBody.  # noqa: E501
+        :type: str
+        """
+
+        self._name = name
+
+    @property
+    def uri(self):
+        """Gets the uri of this UnitsSaveconceptBody.  # noqa: E501
+
+
+        :return: The uri of this UnitsSaveconceptBody.  # noqa: E501
+        :rtype: str
+        """
+        return self._uri
+
+    @uri.setter
+    def uri(self, uri):
+        """Sets the uri of this UnitsSaveconceptBody.
+
+
+        :param uri: The uri of this UnitsSaveconceptBody.  # noqa: E501
+        :type: str
+        """
+
+        self._uri = uri
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(UnitsSaveconceptBody, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, UnitsSaveconceptBody):
+            return False
+
+        return self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        return not self == other
diff --git a/.jupyter/api_units/models/units_suggest_body.py b/.jupyter/api_units/models/units_suggest_body.py
new file mode 100644
index 0000000000000000000000000000000000000000..7aaa2366f8bed8b81c00f6db2871d11670c663a5
--- /dev/null
+++ b/.jupyter/api_units/models/units_suggest_body.py
@@ -0,0 +1,136 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+import pprint
+import re  # noqa: F401
+
+import six
+
+class UnitsSuggestBody(object):
+    """NOTE: This class is auto generated by the swagger code generator program.
+
+    Do not edit the class manually.
+    """
+    """
+    Attributes:
+      swagger_types (dict): The key is attribute name
+                            and the value is attribute type.
+      attribute_map (dict): The key is attribute name
+                            and the value is json key in definition.
+    """
+    swagger_types = {
+        'offset': 'int',
+        'ustring': 'str'
+    }
+
+    attribute_map = {
+        'offset': 'offset',
+        'ustring': 'ustring'
+    }
+
+    def __init__(self, offset=None, ustring=None):  # noqa: E501
+        """UnitsSuggestBody - a model defined in Swagger"""  # noqa: E501
+        self._offset = None
+        self._ustring = None
+        self.discriminator = None
+        if offset is not None:
+            self.offset = offset
+        if ustring is not None:
+            self.ustring = ustring
+
+    @property
+    def offset(self):
+        """Gets the offset of this UnitsSuggestBody.  # noqa: E501
+
+
+        :return: The offset of this UnitsSuggestBody.  # noqa: E501
+        :rtype: int
+        """
+        return self._offset
+
+    @offset.setter
+    def offset(self, offset):
+        """Sets the offset of this UnitsSuggestBody.
+
+
+        :param offset: The offset of this UnitsSuggestBody.  # noqa: E501
+        :type: int
+        """
+
+        self._offset = offset
+
+    @property
+    def ustring(self):
+        """Gets the ustring of this UnitsSuggestBody.  # noqa: E501
+
+
+        :return: The ustring of this UnitsSuggestBody.  # noqa: E501
+        :rtype: str
+        """
+        return self._ustring
+
+    @ustring.setter
+    def ustring(self, ustring):
+        """Sets the ustring of this UnitsSuggestBody.
+
+
+        :param ustring: The ustring of this UnitsSuggestBody.  # noqa: E501
+        :type: str
+        """
+
+        self._ustring = ustring
+
+    def to_dict(self):
+        """Returns the model properties as a dict"""
+        result = {}
+
+        for attr, _ in six.iteritems(self.swagger_types):
+            value = getattr(self, attr)
+            if isinstance(value, list):
+                result[attr] = list(map(
+                    lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
+                    value
+                ))
+            elif hasattr(value, "to_dict"):
+                result[attr] = value.to_dict()
+            elif isinstance(value, dict):
+                result[attr] = dict(map(
+                    lambda item: (item[0], item[1].to_dict())
+                    if hasattr(item[1], "to_dict") else item,
+                    value.items()
+                ))
+            else:
+                result[attr] = value
+        if issubclass(UnitsSuggestBody, dict):
+            for key, value in self.items():
+                result[key] = value
+
+        return result
+
+    def to_str(self):
+        """Returns the string representation of the model"""
+        return pprint.pformat(self.to_dict())
+
+    def __repr__(self):
+        """For `print` and `pprint`"""
+        return self.to_str()
+
+    def __eq__(self, other):
+        """Returns true if both objects are equal"""
+        if not isinstance(other, UnitsSuggestBody):
+            return False
+
+        return self.__dict__ == other.__dict__
+
+    def __ne__(self, other):
+        """Returns true if both objects are not equal"""
+        return not self == other
diff --git a/.jupyter/api_units/rest.py b/.jupyter/api_units/rest.py
new file mode 100644
index 0000000000000000000000000000000000000000..a4b96071cbd53eb501a9fc5eac1909569705d449
--- /dev/null
+++ b/.jupyter/api_units/rest.py
@@ -0,0 +1,317 @@
+# coding: utf-8
+
+"""
+    units
+
+    powered by Flasgger  # noqa: E501
+
+    OpenAPI spec version: 0.0.1
+    
+    Generated by: https://github.com/swagger-api/swagger-codegen.git
+"""
+
+from __future__ import absolute_import
+
+import io
+import json
+import logging
+import re
+import ssl
+
+import certifi
+# python 2 and python 3 compatibility library
+import six
+from six.moves.urllib.parse import urlencode
+
+try:
+    import urllib3
+except ImportError:
+    raise ImportError('Swagger python client requires urllib3.')
+
+
+logger = logging.getLogger(__name__)
+
+
+class RESTResponse(io.IOBase):
+
+    def __init__(self, resp):
+        self.urllib3_response = resp
+        self.status = resp.status
+        self.reason = resp.reason
+        self.data = resp.data
+
+    def getheaders(self):
+        """Returns a dictionary of the response headers."""
+        return self.urllib3_response.getheaders()
+
+    def getheader(self, name, default=None):
+        """Returns a given response header."""
+        return self.urllib3_response.getheader(name, default)
+
+
+class RESTClientObject(object):
+
+    def __init__(self, configuration, pools_size=4, maxsize=None):
+        # urllib3.PoolManager will pass all kw parameters to connectionpool
+        # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75  # noqa: E501
+        # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680  # noqa: E501
+        # maxsize is the number of requests to host that are allowed in parallel  # noqa: E501
+        # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html  # noqa: E501
+
+        # cert_reqs
+        if configuration.verify_ssl:
+            cert_reqs = ssl.CERT_REQUIRED
+        else:
+            cert_reqs = ssl.CERT_NONE
+
+        # ca_certs
+        if configuration.ssl_ca_cert:
+            ca_certs = configuration.ssl_ca_cert
+        else:
+            # if not set certificate file, use Mozilla's root certificates.
+            ca_certs = certifi.where()
+
+        addition_pool_args = {}
+        if configuration.assert_hostname is not None:
+            addition_pool_args['assert_hostname'] = configuration.assert_hostname  # noqa: E501
+
+        if maxsize is None:
+            if configuration.connection_pool_maxsize is not None:
+                maxsize = configuration.connection_pool_maxsize
+            else:
+                maxsize = 4
+
+        # https pool manager
+        if configuration.proxy:
+            self.pool_manager = urllib3.ProxyManager(
+                num_pools=pools_size,
+                maxsize=maxsize,
+                cert_reqs=cert_reqs,
+                ca_certs=ca_certs,
+                cert_file=configuration.cert_file,
+                key_file=configuration.key_file,
+                proxy_url=configuration.proxy,
+                **addition_pool_args
+            )
+        else:
+            self.pool_manager = urllib3.PoolManager(
+                num_pools=pools_size,
+                maxsize=maxsize,
+                cert_reqs=cert_reqs,
+                ca_certs=ca_certs,
+                cert_file=configuration.cert_file,
+                key_file=configuration.key_file,
+                **addition_pool_args
+            )
+
+    def request(self, method, url, query_params=None, headers=None,
+                body=None, post_params=None, _preload_content=True,
+                _request_timeout=None):
+        """Perform requests.
+
+        :param method: http request method
+        :param url: http request url
+        :param query_params: query parameters in the url
+        :param headers: http request headers
+        :param body: request json body, for `application/json`
+        :param post_params: request post parameters,
+                            `application/x-www-form-urlencoded`
+                            and `multipart/form-data`
+        :param _preload_content: if False, the urllib3.HTTPResponse object will
+                                 be returned without reading/decoding response
+                                 data. Default is True.
+        :param _request_timeout: timeout setting for this request. If one
+                                 number provided, it will be total request
+                                 timeout. It can also be a pair (tuple) of
+                                 (connection, read) timeouts.
+        """
+        method = method.upper()
+        assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT',
+                          'PATCH', 'OPTIONS']
+
+        if post_params and body:
+            raise ValueError(
+                "body parameter cannot be used with post_params parameter."
+            )
+
+        post_params = post_params or {}
+        headers = headers or {}
+
+        timeout = None
+        if _request_timeout:
+            if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)):  # noqa: E501,F821
+                timeout = urllib3.Timeout(total=_request_timeout)
+            elif (isinstance(_request_timeout, tuple) and
+                  len(_request_timeout) == 2):
+                timeout = urllib3.Timeout(
+                    connect=_request_timeout[0], read=_request_timeout[1])
+
+        if 'Content-Type' not in headers:
+            headers['Content-Type'] = 'application/json'
+
+        try:
+            # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
+            if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
+                if query_params:
+                    url += '?' + urlencode(query_params)
+                if re.search('json', headers['Content-Type'], re.IGNORECASE):
+                    request_body = '{}'
+                    if body is not None:
+                        request_body = json.dumps(body)
+                    r = self.pool_manager.request(
+                        method, url,
+                        body=request_body,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                elif headers['Content-Type'] == 'application/x-www-form-urlencoded':  # noqa: E501
+                    r = self.pool_manager.request(
+                        method, url,
+                        fields=post_params,
+                        encode_multipart=False,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                elif headers['Content-Type'] == 'multipart/form-data':
+                    # must del headers['Content-Type'], or the correct
+                    # Content-Type which generated by urllib3 will be
+                    # overwritten.
+                    del headers['Content-Type']
+                    r = self.pool_manager.request(
+                        method, url,
+                        fields=post_params,
+                        encode_multipart=True,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                # Pass a `string` parameter directly in the body to support
+                # other content types than Json when `body` argument is
+                # provided in serialized form
+                elif isinstance(body, str):
+                    request_body = body
+                    r = self.pool_manager.request(
+                        method, url,
+                        body=request_body,
+                        preload_content=_preload_content,
+                        timeout=timeout,
+                        headers=headers)
+                else:
+                    # Cannot generate the request from given parameters
+                    msg = """Cannot prepare a request message for provided
+                             arguments. Please check that your arguments match
+                             declared content type."""
+                    raise ApiException(status=0, reason=msg)
+            # For `GET`, `HEAD`
+            else:
+                r = self.pool_manager.request(method, url,
+                                              fields=query_params,
+                                              preload_content=_preload_content,
+                                              timeout=timeout,
+                                              headers=headers)
+        except urllib3.exceptions.SSLError as e:
+            msg = "{0}\n{1}".format(type(e).__name__, str(e))
+            raise ApiException(status=0, reason=msg)
+
+        if _preload_content:
+            r = RESTResponse(r)
+
+            # log response body
+            logger.debug("response body: %s", r.data)
+
+        if not 200 <= r.status <= 299:
+            raise ApiException(http_resp=r)
+
+        return r
+
+    def GET(self, url, headers=None, query_params=None, _preload_content=True,
+            _request_timeout=None):
+        return self.request("GET", url,
+                            headers=headers,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            query_params=query_params)
+
+    def HEAD(self, url, headers=None, query_params=None, _preload_content=True,
+             _request_timeout=None):
+        return self.request("HEAD", url,
+                            headers=headers,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            query_params=query_params)
+
+    def OPTIONS(self, url, headers=None, query_params=None, post_params=None,
+                body=None, _preload_content=True, _request_timeout=None):
+        return self.request("OPTIONS", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def DELETE(self, url, headers=None, query_params=None, body=None,
+               _preload_content=True, _request_timeout=None):
+        return self.request("DELETE", url,
+                            headers=headers,
+                            query_params=query_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def POST(self, url, headers=None, query_params=None, post_params=None,
+             body=None, _preload_content=True, _request_timeout=None):
+        return self.request("POST", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def PUT(self, url, headers=None, query_params=None, post_params=None,
+            body=None, _preload_content=True, _request_timeout=None):
+        return self.request("PUT", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+    def PATCH(self, url, headers=None, query_params=None, post_params=None,
+              body=None, _preload_content=True, _request_timeout=None):
+        return self.request("PATCH", url,
+                            headers=headers,
+                            query_params=query_params,
+                            post_params=post_params,
+                            _preload_content=_preload_content,
+                            _request_timeout=_request_timeout,
+                            body=body)
+
+
+class ApiException(Exception):
+
+    def __init__(self, status=None, reason=None, http_resp=None):
+        if http_resp:
+            self.status = http_resp.status
+            self.reason = http_resp.reason
+            self.body = http_resp.data
+            self.headers = http_resp.getheaders()
+        else:
+            self.status = status
+            self.reason = reason
+            self.body = None
+            self.headers = None
+
+    def __str__(self):
+        """Custom error messages for exception"""
+        error_message = "({0})\n"\
+                        "Reason: {1}\n".format(self.status, self.reason)
+        if self.headers:
+            error_message += "HTTP response headers: {0}\n".format(
+                self.headers)
+
+        if self.body:
+            error_message += "HTTP response body: {0}\n".format(self.body)
+
+        return error_message
diff --git a/.jupyter/load_test.py b/.jupyter/load_test.py
index 55ce49c3b66b281463654f18bd34fd83d8963270..7a6ef465509a58a4ee2d018b9e33abe0390ad3cf 100644
--- a/.jupyter/load_test.py
+++ b/.jupyter/load_test.py
@@ -4,8 +4,8 @@ import time
 import os
 import shutil
 import uuid
+import requests as rq
 from postgres import Postgres
-from datetime import date
 
 import api_query.rest
 from api_authentication.api.authentication_endpoint_api import AuthenticationEndpointApi
@@ -17,6 +17,7 @@ from api_query.api.table_data_endpoint_api import TableDataEndpointApi
 from api_query.api.query_endpoint_api import QueryEndpointApi
 from api_identifier.api.identifier_endpoint_api import IdentifierEndpointApi
 from api_identifier.api.persistence_endpoint_api import PersistenceEndpointApi
+from api_units.api.default_api import DefaultApi
 
 authentication = AuthenticationEndpointApi()
 user = UserEndpointApi()
@@ -27,6 +28,7 @@ query = QueryEndpointApi()
 data = TableDataEndpointApi()
 identifier = IdentifierEndpointApi()
 persistence = PersistenceEndpointApi()
+unit = DefaultApi()
 
 token = ""
 
@@ -99,7 +101,7 @@ def update_database(container_id, database_id, is_public=True):
         },
         "language": "en",
         "is_public": is_public,
-        "publication_year": date.year
+        "publication_year": 2022
     }, container_id, database_id)
     print("updated database with id %d" % response.id)
     return response
@@ -204,9 +206,9 @@ def create_identifier(container_id, database_id, query_id, visibility="everyone"
             "affiliation": "TU Wien",
             "orcid": "0000-0002-9272-6225"
         }],
-        "publication_day": date.day,
-        "publication_month": date.month,
-        "publication_year": date.year,
+        "publication_day": 2,
+        "publication_month": 8,
+        "publication_year": 2022,
         "related_identifiers": [{
             "value": "http://localhost:3000/container/" + str(container_id) + "/database/" + str(database_id),
             "type": "URL",
@@ -240,10 +242,38 @@ def update_theme(user_id):
     }, user_id)
     print("updated theme user with id %d" % user_id)
 
+
 def verify_user(user_id):
     db = Postgres("dbname=fda user=postgres password=postgres")
     token = db.one("SELECT ")
 
+
+def find_concept(concept):
+    response = rq.get("http://localhost:9095/api/units/uri/" + concept)
+    print("found concept for name %s" % concept)
+    return response.json()
+
+
+def create_concept(name, uri):
+    response = rq.post("http://localhost:9095/api/units/saveconcept", {
+        "name": name,
+        "uri": uri
+    })
+    print("created concept for name %s" % name)
+    return response.json()
+
+
+def assign_concept(database_id, table_id, column_id, uri):
+    response = rq.post("http://localhost:9095/api/units/savecolumnsconcept", {
+        "cdbid": database_id,
+        "cid": column_id,
+        "tid": table_id,
+        "uri": uri
+    })
+    print("assigned concept to column with id %d" % column_id)
+    return response.json()
+
+
 if __name__ == '__main__':
     #
     # create 1 user and 3 containers (public, private, public)
@@ -256,6 +286,9 @@ if __name__ == '__main__':
     dbid = create_database(cid).id
     update_database(cid, dbid)
     tid = create_table(cid, dbid).id
+    curi = find_concept("time")["URI"]
+    create_concept("time", curi)
+    assign_concept(dbid, tid, 2, curi)
     tname = find_table(cid, dbid, tid).internal_name
     fill_table(cid, dbid, tid)
     create_query(cid, dbid, "select `id` from `" + tname + "`")
diff --git a/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
index 4b6fc8d4c40a3b8d506099d15bb436afa9764eac..8a9136f0670dd6b56ff90031b51f8b86ccd9ee90 100644
--- a/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
+++ b/fda-database-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -104,7 +104,7 @@ public abstract class BaseUnitTest {
     public final static String DATABASE_1_NAME = "Weather";
     public final static String DATABASE_1_DESCRIPTION = "Weather somewhere in the world";
     public final static String DATABASE_1_PUBLISHER = "TU Wien";
-    public final static Short DATABASE_1_PUBLICATION_YEAR = 2022;
+    public final static Integer DATABASE_1_PUBLICATION_YEAR = 2022;
     public final static Boolean DATABASE_1_PUBLIC = false;
     public final static String DATABASE_1_INTERNALNAME = "weather";
     public final static String DATABASE_1_EXCHANGE = "fda." + DATABASE_1_INTERNALNAME;
diff --git a/fda-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java b/fda-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
index 62daeb5dd8c97282bc7951343e8704957cdd3c52..003e106dc80793a62b9358196d56b054e9858deb 100644
--- a/fda-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
+++ b/fda-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java
@@ -28,11 +28,10 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.persistence.PersistenceException;
 import java.security.Principal;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import java.sql.*;
 import java.time.Instant;
+import java.time.temporal.ChronoField;
+import java.util.Calendar;
 import java.util.List;
 import java.util.Optional;
 
@@ -152,6 +151,7 @@ public class MariaDbServiceImpl extends HibernateConnector implements DatabaseSe
         database.setName(createDto.getName());
         database.setInternalName(databaseMapper.nameToInternalName(database.getName()));
         database.setContainer(container);
+        database.setPublicationYear(Calendar.getInstance().get(Calendar.YEAR));
         final ComboPooledDataSource dataSource = getDataSource(container.getImage(), container);
         try {
             /* create database */
diff --git a/fda-identifier-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-identifier-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
index 3d73541ada4d1faf1f64b0b2009dcced171a20da..c5937971671d0f445c02df17c3a5cfd99781f3f8 100644
--- a/fda-identifier-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
+++ b/fda-identifier-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -246,7 +246,7 @@ public abstract class BaseUnitTest {
     public final static Instant IDENTIFIER_1_CREATED = Instant.ofEpochSecond(1641588352);
     public final static Instant IDENTIFIER_1_MODIFIED = Instant.ofEpochSecond(1541588352);
     public final static Instant IDENTIFIER_1_EXECUTION = Instant.ofEpochSecond(1541588352);
-    public final static Short IDENTIFIER_1_PUBLICATION_YEAR = 2022;
+    public final static Integer IDENTIFIER_1_PUBLICATION_YEAR = 2022;
     public final static String IDENTIFIER_1_QUERY_HASH = "abc";
     public final static String IDENTIFIER_1_RESULT_HASH = "def";
     public final static String IDENTIFIER_1_QUERY = "SELECT `id` FROM `foobar`";
@@ -264,9 +264,9 @@ public abstract class BaseUnitTest {
     public final static Instant IDENTIFIER_2_CREATED = Instant.ofEpochSecond(1641588352);
     public final static Instant IDENTIFIER_2_MODIFIED = Instant.ofEpochSecond(1541588352);
     public final static Instant IDENTIFIER_2_EXECUTION = Instant.ofEpochSecond(1541588352);
-    public final static Short IDENTIFIER_2_PUBLICATION_DAY = 14;
-    public final static Short IDENTIFIER_2_PUBLICATION_MONTH = 7;
-    public final static Short IDENTIFIER_2_PUBLICATION_YEAR = 2022;
+    public final static Integer IDENTIFIER_2_PUBLICATION_DAY = 14;
+    public final static Integer IDENTIFIER_2_PUBLICATION_MONTH = 7;
+    public final static Integer IDENTIFIER_2_PUBLICATION_YEAR = 2022;
     public final static String IDENTIFIER_2_QUERY_HASH = "abc";
     public final static String IDENTIFIER_2_RESULT_HASH = "def";
     public final static String IDENTIFIER_2_QUERY = "SELECT `id` FROM `foobar`";
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java
index 152d2e4feb030da0c211947233ed4c4e9db4fc76..c7b97e3af0e7553a59ffc1138e5083b9851fc640 100644
--- a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/DocumentMapper.java
@@ -90,7 +90,7 @@ public interface DocumentMapper {
                         }
                         if (related.getRelation() != null) {
                             builder.append(" relationType=\"")
-                                    .append(related.getRelation())
+                                    .append(related.getRelation().name())
                                     .append("\"");
                         }
                         builder.append(">")
@@ -112,10 +112,7 @@ public interface DocumentMapper {
                     .append(data.getDescription())
                     .append("</description></descriptions>");
         }
-        builder.append("<version>1.0</version><descriptions>")
-                .append("<description xml:lang=\"en\" descriptionType=\"Abstract\">")
-                .append(data.getDescription())
-                .append("</description></descriptions>")
+        builder.append("<version>1.0</version>")
                 .append("</resource>");
         log.trace("mapped identifier to xml {}", builder);
         return new InputStreamResource(IOUtils.toInputStream(builder.toString(), Charset.defaultCharset()));
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
index a9c1223a3f87133252c16f6d52e0e5af46033ef3..513b7e9458e604df91f96b144a7676c9453b79da 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
@@ -64,9 +64,10 @@ public class DatabaseDto {
     @Parameter(name = "database contact person")
     private UserDto contact;
 
+    @NotNull
     @JsonProperty("publication_year")
     @Parameter(name = "database publication year")
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @Parameter(name = "tables")
     private List<TableBriefDto> tables;
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseModifyDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseModifyDto.java
index ba5804fa7213d955af9ccaa36150a5c919645f2c..ec8696bef5ede35b3b79909413529d971e839d7c 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseModifyDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseModifyDto.java
@@ -31,10 +31,10 @@ public class DatabaseModifyDto {
     @Parameter(name = "database publisher", example = "TU Wien")
     private String publisher;
 
-    @NotBlank
+    @NotNull
     @JsonProperty("publication_year")
     @Parameter(name = "database publication year")
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @Parameter(name = "database license")
     private LicenseDto license;
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java
index 90b176d4db1c589c92e0dded17766f0de85c15dc..a35fc8b47abbe504c0806179541afacdacd18149 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierCreateDto.java
@@ -41,16 +41,16 @@ public class IdentifierCreateDto {
 
     @JsonProperty("publication_day")
     @Parameter(name = "publication day")
-    private Short publicationDay;
+    private Integer publicationDay;
 
     @JsonProperty("publication_month")
     @Parameter(name = "publication month")
-    private Short publicationMonth;
+    private Integer publicationMonth;
 
     @NotNull
     @JsonProperty("publication_year")
     @Parameter(name = "publication year")
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @NotNull
     @Parameter(name = "creators")
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java
index e5e3d33c55fc270e9568efc5af11c516b6432c3f..42763f8c31387a81466b732792a3c1ef30a6f269 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierDto.java
@@ -88,16 +88,16 @@ public class IdentifierDto {
 
     @JsonProperty("publication_day")
     @Parameter(name = "publication day")
-    private Short publicationDay;
+    private Integer publicationDay;
 
     @JsonProperty("publication_month")
     @Parameter(name = "publication month")
-    private Short publicationMonth;
+    private Integer publicationMonth;
 
     @NotNull
     @JsonProperty("publication_year")
     @Parameter(name = "publication year")
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @NotNull
     @Parameter(name = "creators")
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java
index 68e952263dedb4c5152013df3cd3b7e85cfd2d8c..60f95dcc6ce8b92c4a34620fbd241e9cc714a735 100644
--- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java
@@ -76,7 +76,7 @@ public class Database {
     private String publisher;
 
     @Column
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
     @JoinColumns({
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
index a6ec125f5dece091fa881f3374b3e0c029f35588..375b9e4a5639b467e627fe6ce22dba30e400a53e 100644
--- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
@@ -79,13 +79,13 @@ public class Identifier {
     private Long resultNumber;
 
     @Column(nullable = false)
-    private Short publicationYear;
+    private Integer publicationYear;
 
     @Column
-    private Short publicationMonth;
+    private Integer publicationMonth;
 
     @Column
-    private Short publicationDay;
+    private Integer publicationDay;
 
     @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     @JoinColumns({
diff --git a/fda-metadata-db/setup-schema.sql b/fda-metadata-db/setup-schema.sql
index d6f20c96bb009030800352b5c9d9cf2e1f8e87bf..f5dd40b1369e28b12f1d14a399f0a6d4c6eea14b 100644
--- a/fda-metadata-db/setup-schema.sql
+++ b/fda-metadata-db/setup-schema.sql
@@ -278,7 +278,7 @@ CREATE TABLE IF NOT EXISTS mdb_databases
     internal_name    character varying(255)      NOT NULL,
     exchange         character varying(255)      NOT NULL,
     subject          character varying(255),
-    publication_year smallint,
+    publication_year INTEGER,
     ResourceType     TEXT,
     Description      TEXT,
     Engine           VARCHAR(20)                          DEFAULT 'Postgres',
@@ -458,9 +458,9 @@ CREATE TABLE IF NOT EXISTS mdb_identifiers
     title             VARCHAR(255)                NOT NULL,
     description       TEXT                        NOT NULL,
     visibility        VARCHAR(10)                 NOT NULL DEFAULT 'SELF',
-    publication_year  smallint                    NOT NULL,
-    publication_month smallint,
-    publication_day   smallint,
+    publication_year  INTEGER                     NOT NULL,
+    publication_month INTEGER,
+    publication_day   INTEGER,
     query             TEXT                        NOT NULL,
     query_normalized  TEXT                        NOT NULL,
     query_hash        VARCHAR(255)                NOT NULL,
diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/AbstractEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/AbstractEndpoint.java
index 56125529d8d94da58eb35125aebc18f8b0edd2c1..10cd45680a456d90aeedd3a6f47e5ccd0c6a871a 100644
--- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/AbstractEndpoint.java
+++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/AbstractEndpoint.java
@@ -37,7 +37,7 @@ public abstract class AbstractEndpoint {
             return false;
         }
         /* view-only operations are allowed on public databases */
-        if (database.getIsPublic() && List.of("TABLE_EXPORT", "DATA_VIEW", "DATA_HISTORY", "QUERY_VIEW_ALL").contains(permissionCode)) {
+        if (database.getIsPublic() && List.of("TABLE_EXPORT", "DATA_VIEW", "DATA_HISTORY", "QUERY_VIEW_ALL", "QUERY_EXECUTE").contains(permissionCode)) {
             log.debug("grant permission {} because database is public", permissionCode);
             return true;
         }
diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
index f1bc79f8191c512c2ba38a221853ea3292b03367..c39ade7008a6a118ac5403da1b8164df39023538 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
@@ -652,17 +652,6 @@ public interface QueryMapper {
         }
     }
 
-    default Long resultSetToLong(ResultSet data) {
-        try {
-            if (data.next()) {
-                return data.getLong(1);
-            }
-        } catch (SQLException e) {
-            return null;
-        }
-        return null;
-    }
-
     default PreparedStatement tableToRawFindAllQuery(Connection connection, Table table, Instant timestamp, Long size, Long page)
             throws ImageNotSupportedException, QueryMalformedException {
         /* param check */
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
index 0ff0e3fc64e7123c1acb80cfb2aa9a2314b28339..b88f806e14590475d314e897004c4a56cc44fd34 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
@@ -23,8 +23,6 @@ import net.sf.jsqlparser.statement.Statement;
 import net.sf.jsqlparser.statement.select.*;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.RandomStringUtils;
-import org.hibernate.Session;
-import org.hibernate.query.NativeQuery;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.stereotype.Service;
diff --git a/fda-ui/components/DBToolbar.vue b/fda-ui/components/DBToolbar.vue
index e20d3034dcea84c74c9edd2965604ea028acac44..229c09bfd25ed4f0a0c728864328e1aefb538a2b 100644
--- a/fda-ui/components/DBToolbar.vue
+++ b/fda-ui/components/DBToolbar.vue
@@ -20,7 +20,7 @@
       </v-toolbar-title>
       <template v-slot:extension>
         <v-tabs v-model="tab" color="primary">
-          <v-tab :to="`/container/${$route.params.container_id}/database/${databaseId}`">
+          <v-tab :to="`/container/${$route.params.container_id}/database/${databaseId}/info`">
             Info
           </v-tab>
           <v-tab :to="`/container/${$route.params.container_id}/database/${databaseId}/table`">
diff --git a/fda-ui/components/TableList.vue b/fda-ui/components/TableList.vue
index a5149bccf7fe396516727933c1af88a46459c398..1ec27ab34debc7dcaf421b32abfa83e0f85454d7 100644
--- a/fda-ui/components/TableList.vue
+++ b/fda-ui/components/TableList.vue
@@ -1,6 +1,6 @@
 <template>
   <div>
-    <v-progress-linear v-if="loading" :color="loadingColor" />
+    <v-progress-linear v-if="loading" :color="loadingColor" indeterminate />
     <v-card v-if="!loading && tables.length === 0" flat>
       <v-card-title>
         (no tables)
@@ -80,12 +80,15 @@
           </v-row>
           <v-row dense>
             <v-col>
-              <v-btn :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`">
+              <v-btn color="secondary" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}`">
                 View Data
               </v-btn>
               <v-btn color="secondary" class="ml-2" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/query/create?tid=${item.id}`">
                 Create Subset
               </v-btn>
+              <v-btn class="ml-2" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${item.id}/import`">
+                Import csv
+              </v-btn>
             </v-col>
             <v-col class="align-right">
               <v-btn v-if="false" outlined color="error" @click="showDeleteTableDialog(item.id)">
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/index.vue
index d7b586ac145832845219a90836569c0fc7377282..e39d3d7b62049773de5edcbde3dabf7d92e6c7c6 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/index.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/index.vue
@@ -1,210 +1,13 @@
 <template>
-  <div>
-    <DBToolbar />
-    <v-progress-linear v-if="loading" />
-    <v-tabs-items v-model="tab">
-      <v-tab-item>
-        <v-card flat>
-          <v-card-text>
-            <v-list dense>
-              <v-list-item>
-                <v-list-item-content>
-                  <v-list-item-title>
-                    Database Visibility
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ database.is_public ? 'Public' : 'Private' }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Database Publisher
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ publisher }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Database Internal Name
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ internal_name }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Database Description
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="paragraph" width="50%" />
-                    <span v-if="!loading">{{ description }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Database Creator
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">
-                      {{ creator }}
-                      <sup>
-                        <v-icon v-if="database.creator.email_verified" small color="primary">mdi-check-decagram</v-icon>
-                      </sup>
-                    </span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Created
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ createdUTC }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Language
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ language }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    Publication Date
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <span v-if="!loading">{{ publication }}</span>
-                  </v-list-item-content>
-                  <v-list-item-title class="mt-2">
-                    License
-                  </v-list-item-title>
-                  <v-list-item-content>
-                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
-                    <a v-if="database.license" target="_blank" :href="database.license.uri">{{ database.license.identifier }}</a>
-                    <span v-if="!database.license">(none)</span>
-                  </v-list-item-content>
-                </v-list-item-content>
-              </v-list-item>
-            </v-list>
-            <v-btn color="secondary" @click="editDbDialog = true">Edit</v-btn>
-            <v-dialog
-              v-model="editDbDialog"
-              persistent
-              max-width="640">
-              <EditDB :database="database" @close-dialog="closeDialog" />
-            </v-dialog>
-          </v-card-text>
-        </v-card>
-      </v-tab-item>
-    </v-tabs-items>
-    <v-breadcrumbs :items="items" class="pa-0 mt-2" />
-  </div>
+  <div />
 </template>
 
 <script>
-import DBToolbar from '@/components/DBToolbar'
-import EditDB from '@/components/dialogs/EditDB'
-import { formatTimestampUTCLabel, formatUser } from '@/utils'
-
 export default {
-  components: {
-    DBToolbar,
-    EditDB
-  },
-  data () {
-    return {
-      loading: false,
-      editDbDialog: false,
-      database: {
-        id: null,
-        name: null,
-        description: null,
-        is_public: null,
-        publisher: null,
-        created: null,
-        subject: [],
-        language: null,
-        license: {
-          uri: null,
-          identifier: null
-        },
-        creator: {
-          titles_before: null,
-          firstname: null,
-          lastname: null,
-          username: null,
-          titles_after: null
-        }
-      },
-      items: [
-        { text: 'Databases', to: '/container', activeClass: '' },
-        {
-          text: `${this.$route.params.database_id}`,
-          to: `/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/info`,
-          activeClass: ''
-        }
-      ]
-    }
-  },
-  computed: {
-    tab () {
-      return 0
-    },
-    description () {
-      return this.database.description === null ? '(no description)' : this.database.description
-    },
-    publisher () {
-      return this.database.publisher === null ? '(none)' : this.database.publisher
-    },
-    token () {
-      return this.$store.state.token
-    },
-    config () {
-      if (this.token === null) {
-        return {}
-      }
-      return {
-        headers: { Authorization: `Bearer ${this.token}` }
-      }
-    },
-    createdUTC () {
-      return formatTimestampUTCLabel(this.database.created)
-    },
-    language () {
-      return this.database.language === null ? '(none)' : this.database.language
-    },
-    internal_name () {
-      return this.database.internal_name
-    },
-    publication () {
-      return this.database.publication === null ? '(none)' : this.database.publication
-    },
-    creator () {
-      return formatUser(this.database.creator)
-    }
-  },
   mounted () {
-    this.loadDatabase()
-  },
-  methods: {
-    async loadDatabase () {
-      this.loading = true
-      try {
-        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.config)
-        this.database = res.data
-        console.debug('database', res.data)
-      } catch (err) {
-        this.$toast.error('Could not load database.')
-      }
-      this.loading = false
-    },
-    closeDialog () {
-      this.loadDatabase()
-      this.editDbDialog = false
-    }
+    this.$router.push(`/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/info`)
   }
 }
 </script>
 <style>
-.v-card__text {
-  font-size: initial;
-}
-.skeleton-small .v-skeleton-loader__text {
-  width: 100px;
-}
 </style>
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/info.vue b/fda-ui/pages/container/_container_id/database/_database_id/info.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d7b586ac145832845219a90836569c0fc7377282
--- /dev/null
+++ b/fda-ui/pages/container/_container_id/database/_database_id/info.vue
@@ -0,0 +1,210 @@
+<template>
+  <div>
+    <DBToolbar />
+    <v-progress-linear v-if="loading" />
+    <v-tabs-items v-model="tab">
+      <v-tab-item>
+        <v-card flat>
+          <v-card-text>
+            <v-list dense>
+              <v-list-item>
+                <v-list-item-content>
+                  <v-list-item-title>
+                    Database Visibility
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ database.is_public ? 'Public' : 'Private' }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Database Publisher
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ publisher }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Database Internal Name
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ internal_name }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Database Description
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="paragraph" width="50%" />
+                    <span v-if="!loading">{{ description }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Database Creator
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">
+                      {{ creator }}
+                      <sup>
+                        <v-icon v-if="database.creator.email_verified" small color="primary">mdi-check-decagram</v-icon>
+                      </sup>
+                    </span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Created
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ createdUTC }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Language
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ language }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    Publication Date
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <span v-if="!loading">{{ publication }}</span>
+                  </v-list-item-content>
+                  <v-list-item-title class="mt-2">
+                    License
+                  </v-list-item-title>
+                  <v-list-item-content>
+                    <v-skeleton-loader v-if="loading" type="text" class="skeleton-small" />
+                    <a v-if="database.license" target="_blank" :href="database.license.uri">{{ database.license.identifier }}</a>
+                    <span v-if="!database.license">(none)</span>
+                  </v-list-item-content>
+                </v-list-item-content>
+              </v-list-item>
+            </v-list>
+            <v-btn color="secondary" @click="editDbDialog = true">Edit</v-btn>
+            <v-dialog
+              v-model="editDbDialog"
+              persistent
+              max-width="640">
+              <EditDB :database="database" @close-dialog="closeDialog" />
+            </v-dialog>
+          </v-card-text>
+        </v-card>
+      </v-tab-item>
+    </v-tabs-items>
+    <v-breadcrumbs :items="items" class="pa-0 mt-2" />
+  </div>
+</template>
+
+<script>
+import DBToolbar from '@/components/DBToolbar'
+import EditDB from '@/components/dialogs/EditDB'
+import { formatTimestampUTCLabel, formatUser } from '@/utils'
+
+export default {
+  components: {
+    DBToolbar,
+    EditDB
+  },
+  data () {
+    return {
+      loading: false,
+      editDbDialog: false,
+      database: {
+        id: null,
+        name: null,
+        description: null,
+        is_public: null,
+        publisher: null,
+        created: null,
+        subject: [],
+        language: null,
+        license: {
+          uri: null,
+          identifier: null
+        },
+        creator: {
+          titles_before: null,
+          firstname: null,
+          lastname: null,
+          username: null,
+          titles_after: null
+        }
+      },
+      items: [
+        { text: 'Databases', to: '/container', activeClass: '' },
+        {
+          text: `${this.$route.params.database_id}`,
+          to: `/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/info`,
+          activeClass: ''
+        }
+      ]
+    }
+  },
+  computed: {
+    tab () {
+      return 0
+    },
+    description () {
+      return this.database.description === null ? '(no description)' : this.database.description
+    },
+    publisher () {
+      return this.database.publisher === null ? '(none)' : this.database.publisher
+    },
+    token () {
+      return this.$store.state.token
+    },
+    config () {
+      if (this.token === null) {
+        return {}
+      }
+      return {
+        headers: { Authorization: `Bearer ${this.token}` }
+      }
+    },
+    createdUTC () {
+      return formatTimestampUTCLabel(this.database.created)
+    },
+    language () {
+      return this.database.language === null ? '(none)' : this.database.language
+    },
+    internal_name () {
+      return this.database.internal_name
+    },
+    publication () {
+      return this.database.publication === null ? '(none)' : this.database.publication
+    },
+    creator () {
+      return formatUser(this.database.creator)
+    }
+  },
+  mounted () {
+    this.loadDatabase()
+  },
+  methods: {
+    async loadDatabase () {
+      this.loading = true
+      try {
+        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.config)
+        this.database = res.data
+        console.debug('database', res.data)
+      } catch (err) {
+        this.$toast.error('Could not load database.')
+      }
+      this.loading = false
+    },
+    closeDialog () {
+      this.loadDatabase()
+      this.editDbDialog = false
+    }
+  }
+}
+</script>
+<style>
+.v-card__text {
+  font-size: initial;
+}
+.skeleton-small .v-skeleton-loader__text {
+  width: 100px;
+}
+</style>
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
index 7623073dbdca02119ad8e8f5a4cd310ed55fad23..e2c628149809449cdd710e260d424f282c4cc5ed 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/query/_query_id/index.vue
@@ -311,9 +311,6 @@ export default {
     }
   },
   computed: {
-    token () {
-      return this.$store.state.token
-    },
     result_icon () {
       return this.erroneous && !this.loadingQuery ? 'mdi-flash' : 'mdi-table'
     },
@@ -323,6 +320,9 @@ export default {
     loadingColor () {
       return this.error ? 'red' : 'primary'
     },
+    token () {
+      return this.$store.state.token
+    },
     config () {
       if (this.token === null) {
         return {}
@@ -404,10 +404,7 @@ export default {
     async metadata () {
       this.metadataLoading = true
       try {
-        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/identifier/${this.identifier.id}`, {
-          headers: { Authorization: `Bearer ${this.token}` },
-          responseType: 'text'
-        })
+        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/identifier/${this.identifier.id}`, this.config)
         console.debug('identifier result', res)
         const url = window.URL.createObjectURL(new Blob([res.data]))
         const link = document.createElement('a')
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/import.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/import.vue
index bb6c37509f8b82761c867b3b73a282b5d48ed324..ccc79ac9df1a6a08cd00065cb8987ec2ea73531b 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/import.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/import.vue
@@ -1,97 +1,101 @@
 <template>
   <div>
     <v-toolbar flat>
-      <v-toolbar-title>Import Data</v-toolbar-title>
-      <v-spacer />
       <v-toolbar-title>
-        <v-btn :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}`">
-          <v-icon left>mdi-table</v-icon>
-          View Table
+        <v-btn id="back-btn" class="mr-2" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table`">
+          <v-icon left>mdi-arrow-left</v-icon>
         </v-btn>
       </v-toolbar-title>
-    </v-toolbar>
-    <v-card>
-      <v-card-title v-if="!loading">
+      <v-toolbar-title>
         {{ table.name }}
-      </v-card-title>
-      <v-card-subtitle>{{ table.internal_name }}</v-card-subtitle>
-      <v-card-text>
-        <v-row dense>
-          <v-col cols="8">
-            <v-select
-              v-model="tableImport.separator"
-              :items="separators"
-              item-text="key"
-              item-value="value"
-              required
-              hint="Character separating the values"
-              label="Separator *" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-text-field
-              v-model.number="tableImport.skip_lines"
-              :rules="[v => isNonNegativeInteger(v) || $t('Greater or equal to zero')]"
-              type="number"
-              required
-              hint="Skip n lines from the top. These may include comments or the header of column names."
-              label="Number of lines to skip *"
-              placeholder="e.g. 0" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-select
-              v-model="tableImport.quote"
-              :items="quotes"
-              item-text="key"
-              item-value="value"
-              hint="Character quoting the values"
-              label="Value quotes" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-text-field
-              v-model="tableImport.null_element"
-              hint="Representation of 'no value present'"
-              placeholder="e.g. NA"
-              label="NULL Element" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-text-field
-              v-model="tableImport.true_element"
-              label="True Element"
-              hint="Representation of boolean 'true'"
-              placeholder="e.g. 1, true, YES" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-text-field
-              v-model="tableImport.false_element"
-              label="False Element"
-              hint="Representation of boolean 'false'"
-              placeholder="e.g. 0, false, NO" />
-          </v-col>
-        </v-row>
-        <v-row dense>
-          <v-col cols="8">
-            <v-file-input
-              v-model="file"
-              accept=".csv,.tsv"
-              show-size
-              label="CSV/TSV File" />
-          </v-col>
-        </v-row>
-      </v-card-text>
-      <v-card-actions>
-        <v-btn :disabled="!file" :loading="loading" color="primary" @click="upload">Upload</v-btn>
-      </v-card-actions>
-    </v-card>
+      </v-toolbar-title>
+    </v-toolbar>
+    <v-stepper v-model="step" vertical flat>
+      <v-stepper-step :complete="step > 1" step="1">
+        Import Data
+      </v-stepper-step>
+
+      <v-stepper-content step="1">
+        <v-form ref="form" v-model="validStep1" @submit.prevent="submit">
+          <v-row dense>
+            <v-col cols="8">
+              <v-select
+                v-model="tableImport.separator"
+                :items="separators"
+                item-text="key"
+                item-value="value"
+                required
+                hint="Character separating the values"
+                label="Separator *" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-text-field
+                v-model.number="tableImport.skip_lines"
+                :rules="[v => isNonNegativeInteger(v) || $t('Greater or equal to zero')]"
+                type="number"
+                required
+                hint="Skip n lines from the top. These may include comments or the header of column names."
+                label="Number of lines to skip *"
+                placeholder="e.g. 0" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-select
+                v-model="tableImport.quote"
+                :items="quotes"
+                item-text="key"
+                item-value="value"
+                hint="Character quoting the values"
+                label="Value quotes" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-text-field
+                v-model="tableImport.null_element"
+                hint="Representation of 'no value present'"
+                placeholder="e.g. NA"
+                label="NULL Element" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-text-field
+                v-model="tableImport.true_element"
+                label="True Element"
+                hint="Representation of boolean 'true'"
+                placeholder="e.g. 1, true, YES" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-text-field
+                v-model="tableImport.false_element"
+                label="False Element"
+                hint="Representation of boolean 'false'"
+                placeholder="e.g. 0, false, NO" />
+            </v-col>
+          </v-row>
+          <v-row dense>
+            <v-col cols="8">
+              <v-file-input
+                v-model="file"
+                accept=".csv,.tsv"
+                show-size
+                label="CSV/TSV File" />
+            </v-col>
+          </v-row>
+          <v-row>
+            <v-col cols="8">
+              <v-btn :disabled="!file" :loading="loading" color="primary" @click="upload">Upload</v-btn>
+            </v-col>
+          </v-row>
+        </v-form>
+      </v-stepper-content>
+    </v-stepper>
     <v-breadcrumbs :items="items" class="pa-0 mt-2" />
   </div>
 </template>
@@ -104,6 +108,8 @@ export default {
   data () {
     return {
       loading: false,
+      step: 1,
+      validStep1: false,
       separators: [
         { key: ',', value: ',' },
         { key: ';', value: ';' },
@@ -155,6 +161,9 @@ export default {
   },
   methods: {
     isNonNegativeInteger,
+    submit () {
+      this.$refs.form.validate()
+    },
     async info () {
       this.loading = true
       const infoUrl = `/api/container/${this.$route.params.container_id}/database/${this.databaseId}/table/${this.tableId}`
@@ -210,6 +219,14 @@ export default {
   }
 }
 </script>
-
 <style>
+#back-btn {
+  min-width: auto;
+  padding: 0 0 0 12px;
+  background: none !important;
+  box-shadow: none;
+}
+#back-btn::before {
+  opacity: 0;
+}
 </style>
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue
index 269887ef5277bbf3b4ffd5ce062badc352e78420..b40ce18cb6c382b26d7dbf2c35d8af02347fff63 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/_table_id/index.vue
@@ -83,7 +83,7 @@
 <script>
 import EditTuple from '@/components/dialogs/EditTuple'
 import TimeTravel from '@/components/dialogs/TimeTravel'
-import { formatTimestampUTCLabel, formatDateUTC } from '@/utils'
+import { formatTimestampUTCLabel, formatDateUTC, formatTimestamp } from '@/utils'
 
 export default {
   components: {
@@ -226,9 +226,11 @@ export default {
       this.pickVersionDialog = true
     },
     pickVersion (event) {
+      const date = new Date(event.time)
+      date.setSeconds(date.getSeconds() + 1)
       console.debug('closed', event)
       if (event.time) {
-        this.version = event.time
+        this.version = formatTimestamp(date)
       }
       this.pickVersionDialog = false
     },