{"action":"created","comment":{"url":"https://api.github.com/repos/lizardsystem/freq/pulls/comments/48947559","id":48947559,"diff_hunk":"@@ -1,283 +1,913 @@\n # (c) Nelen & Schuurmans.  GPL licensed, see LICENSE.rst.\n # -*- coding: utf-8 -*-\n-import datetime\n+import copy\n+import datetime as dt\n import json\n+from pprint import pprint  # left here for debugging purposes\n+from statistics import mean\n \n-from django.utils.encoding import uri_to_iri\n-from django.core.urlresolvers import reverse\n-from django.http import HttpResponseRedirect\n+from django.utils.functional import cached_property\n from django.utils.translation import ugettext as _\n from django.views.generic.base import TemplateView\n-import pytz\n+\n+import numpy as np\n+import pandas as pd\n from rest_framework.response import Response as RestResponse\n from rest_framework.views import APIView\n \n-from freq import models\n-from freq.lizard_api_connector import GroundwaterLocations\n-from freq.lizard_api_connector import TimeSeries\n+from freq.buttons import *\n+import freq.freq_calculator as calculator\n from freq.lizard_api_connector import ApiError\n-\n-\n-class BaseView(TemplateView):\n+from freq.lizard_api_connector import GroundwaterLocations\n+from freq.lizard_api_connector import GroundwaterTimeSeries\n+\n+\n+def today():\n+    return dt.datetime.now().strftime('%d-%m-%Y')\n+\n+\n+TIMESERIES_MEASUREMENT_FREQUENCY = 'M'\n+DEFAULT_STATE = {\n+    'map_': {\n+        'center': [45.0, 0.0],\n+        'zoom': 3\n+    },\n+    'startpage': {\n+        'chart': 'hidden',\n+        'datepicker': {'start': '1-1-1900', 'end': today()},\n+        'end_js': 1000000000000,\n+        'graph': {'x': 0, 'y': 0, 'series': 0},\n+        'measurement_point': 'No Time Series Selected',\n+        'selected_coords': [],\n+        'start_js': 0,\n+        'timeseries_length': -9999,\n+        'uuid': 'EMPTY',\n+    },\n+    'trend_detection': {\n+        'active': False,\n+        'datepicker': {'start': '1-1-1900', 'end': today()},\n+        'dropdown_0': {'value': '... (choose type)'},\n+        'graph': {'x': 0, 'y': 0, 'series': 0},\n+        'spinner_0': {'value': 0.05},\n+    },\n+    'periodic_fluctuations': {\n+        'spinner_0': {'value': 10},\n+        'spinner_1': {'value': 0},\n+        'graph': {'x': 0, 'y': 0, 'series': 0},\n+    },\n+    'autoregressive': {\n+        'spinner_0': {'value': 1},\n+        'graph': {'x': 0, 'y': 0, 'series': 0},\n+    },\n+    'disabled': {\n+            'startpage': 'enabled',\n+            'trend_detection': 'disabled',\n+            'periodic_fluctuations': 'disabled',\n+            'autoregressive': 'disabled',\n+    },\n+}\n+\n+\n+class BaseViewMixin(object):\n     \"\"\"Base view.\"\"\"\n     template_name = 'freq/base.html'\n-    title = _('FREQ - frequency analysis of groundwater measurements')\n-    page_title = _('FREQ - frequency analysis groundwater measurements')\n+    title = _('GGMN - Global Groundwater Network')\n+    page_title = _('GGMN - Global Groundwater Network')\n     menu_items = [\n-        ('Map', 'Full page map', 'map_'),\n         ('Startpage', 'Back to Homepage', 'startpage'),\n         ('Detection of Trends', 'Step trend or flat trend detection',\n             'trend_detection'),\n         ('Periodic Fluctuations', 'Estimate periodic fluctuations by harmonic '\n-            'analysis', 'periodic_fluctuation'),\n+            'analysis', 'periodic_fluctuations'),\n         ('Autoregressive Model', 'Analyse the resulting, now stationary, time '\n             'series with an autoregressive model (ARM)', 'autoregressive'),\n-        ('Sampling Frequency', 'Analysis and design of sampling frequency',\n-            'sampling'),\n+        # ('Sampling Frequency', 'Analysis and design of sampling frequency',\n+        #     'sampling'),\n     ]\n     active = ''\n-    tab_order = ['startpage', 'trend_detection', 'periodic_fluctuation',\n-                 'autoregressive', 'sampling']\n-\n-    @property\n-    def default(self):\n-        return {\n-            'startpage': {\n-                'measurement_point': 'No Time Series Selected',\n-                'chart': 'hidden',\n-                'data': []\n-            },\n-            'trend_detection': {},\n-            'periodic_fluctuation': {},\n-            'autoregressive': {},\n-            'sampling': {},\n-        }\n+    tab_order = ['startpage', 'trend_detection', 'periodic_fluctuations',\n+                 'autoregressive']\n+    spinners = []\n+\n+    # ------------------------------------------------------------------------ #\n+    ### Session handling\n+\n+    ## Use for debugging:\n+    # def dispatch(self, *args, **kwargs):\n+    #     print('\\n\\n\\nIN {}'.format(type(self).__name__))\n+    #     pprint(dict(self.request.session))\n+    #     return super().dispatch(*args, **kwargs)\n+\n+    def instantiate_session(self):\n+        self.request.session['session_is_set'] = True\n+        default = copy.deepcopy(DEFAULT_STATE)\n+        self.request.session.update(default)\n+\n+    def set_session_value(self, state, key, value):\n+        if self.is_default_type(state, key, value):\n+            old_value = self.request.session[state].get(key)\n+            if old_value != value:\n+                self.request.session[state][key] = value\n+                self.request.session.modified = True\n+                print('\\nupdated {} with old value {} with new value {'\n+                      '}'.format(\n+                    key, old_value, value))\n+        else:\n+            print('NOT MY TYPE!:', state, key, value)\n+            print('default:', type(DEFAULT_STATE[state][key]).__name__)\n+            print('new:', type(value).__name__)\n \n-    def disabled(self, request):\n+    def is_default_type(self, state, key, value):\n         try:\n-            return request.session['disabled']\n+            return isinstance(value, type(DEFAULT_STATE[state][key]))\n         except KeyError:\n-            request.session['disabled'] = {\n-                'map_': '',\n-                'startpage': '',\n-                'trend_detection': 'disabled',\n-                'periodic_fluctuation': 'disabled',\n-                'autoregressive': 'disabled',\n-                'sampling': 'disabled'\n-            }\n-            return request.session['disabled']\n+            return True\n \n-    def last(self, request):\n-        request.session['redo'] = request.session.get(\n+    def undo(self):\n+        remove = self.tab_order[self.last - 1]\n+        self.request.session['redo'][remove] = self.request.session[remove]\n+        if remove != 'startpage':\n+            self.request.session['disabled'][remove] = 'disabled'\n+        default = copy.deepcopy(DEFAULT_STATE)\n+        self.request.session[remove] = default[remove]\n+        self.request.session.modified = True\n+\n+    def redo(self):\n+        redo = self.tab_order[self.last]\n+        new_redo = self.request.session['redo'][redo]\n+        if new_redo:\n+            self.request.session['disabled'][redo] = ''\n+            self.request.session[redo] = new_redo\n+            self.request.session.modified = True\n+\n+    @cached_property\n+    def last(self):\n+        self.request.session['redo'] = self.request.session.get(\n             'redo',\n-            {key: request.session.get(key, value) for key, value in\n-             self.default.items()}\n+            {key: self.request.session.get(key, value) for key, value in\n+             DEFAULT_STATE.items()}\n         )\n         for i, status in enumerate(self.tab_order):\n-            if request.session['disabled'][status] == 'disabled':\n+            if self.request.session['disabled'][status] == 'disabled':\n                 break\n         return i\n \n-    def undo(self, request):\n-        remove = self.tab_order[self.last(request) - 1]\n-        request.session['redo'][remove] = request.session[remove]\n-        if remove != 'startpage':\n-            request.session['disabled'][remove] = 'disabled'\n-        request.session[remove] = {}\n+    # ------------------------------------------------------------------------ #\n+    ### Page properties\n+    @cached_property\n+    def menu(self):\n+        return [\n+            (i + 1, title, description, link,\n+             self.request.session['disabled'][link] if link != self.active else 'active')\n+            for i, (title, description, link) in enumerate(self.menu_items)\n+        ]\n \n-    def redo(self, request):\n-        redo = self.tab_order[self.last(request)]\n-        new_redo = request.session['redo'][redo]\n-        if new_redo:\n-            request.session['disabled'][redo] = ''\n-            request.session[redo] = new_redo\n+    @cached_property\n+    def show_error(self):\n+        if not 'error_message' in self.kwargs:\n+            self.error_message = ''\n+            return 'hidden'\n+        return ''\n+\n+    @cached_property\n+    def measurement_point(self):\n+        return self.request.session['startpage'].get(\n+            'measurement_point', 'No Time Series Selected')\n+\n+    # ------------------------------------------------------------------------ #\n+    ### Map properties\n+    @cached_property\n+    def selected_coords(self):\n+        return json.dumps([float(x) for x in self.request.session['startpage'].get(\n+            'selected_coords', [])])\n+\n+    @property\n+    def center(self):\n+        return [float(x) for x in self.request.session['map_'].get('center',\n+                                                                       [45, 0])]\n+\n+    @property\n+    def zoom(self):\n+        if self.request.session['startpage']['selected_coords']:\n+            return 10\n+        return self.request.session['map_'].get('zoom', 3)\n+\n+    @property\n+    def freq_icon_size(self):\n+        if self.active == 'map_':\n+            return \"glyphicon-sm\"\n+        else:\n+            return \"\"\n+\n+    @property\n+    def map_icon_size(self):\n+        if self.active != 'map_':\n+            return \"glyphicon-sm\"\n+        else:\n+            return \"\"\n+\n+    # ------------------------------------------------------------------------ #\n+    ### Data handling\n+\n+    @cached_property\n+    def timeseries(self):\n+        ts = GroundwaterTimeSeries()\n+        ts.uuid(self.request.session['startpage']['uuid'], **self.time_window)\n+        if len(ts.results) != 0:\n+            data = [{'y': x['max'], 'x': x['timestamp']}\n+                             for x in ts.results[0]['events']]\n+        else:\n+            data = []\n+\n+        self.data = {\n+            'values': data,\n+            'key': 'Groundwaterlevels (m)',\n+            'color': '#1abc9c'\n+        }\n+\n+        self.request.session['startpage']['timeseries_length'] = len(data)\n+        self.request.session.modified = True\n+\n+        return self.data\n \n-    def flush(self, request):\n-        request.session.update(self.default)\n-        del(request.session['disabled'])\n-        request.session['disabled'] = self.disabled(request)\n+\n+    @cached_property\n+    def error_message(self):\n+        if len(self.timeseries['values']) == 0:\n+            return 'No time series found for this location, please select ' \\\n+                   'another.'\n+        return ''\n+\n+    # ------------------------------------------------------------------------ #\n+    ### Date handling\n+    JS_EPOCH = dt.datetime(1970, 1, 1)\n+\n+    def datetime_to_js(self, date_time):\n+        if date_time is not None:\n+            return int((date_time - self.JS_EPOCH).total_seconds() * 1000)\n+\n+    def js_to_datetime(self, date_time):\n+        if date_time is not None:\n+            return self.JS_EPOCH + dt.timedelta(seconds=date_time/1000)\n+\n+    @cached_property\n+    def today(self):\n+        return today()\n+\n+    # TODO: 'old' code once written for the map part, probably obsolete.\n+    # @cached_property\n+    # def current(self):\n+    #     return self.active if self.active else 'map_'\n+    #\n+    # @cached_property\n+    # def start(self):\n+    #     start_old = self.request.session[self.current].get('start', self.today)\n+    #     return self.request.GET.get('start', start_old)\n+    #\n+    # @cached_property\n+    # def end(self):\n+    #     start_old = self.request.session[self.current].get('end', self.today)\n+    #     return self.request.GET.get('end', start_old)\n+\n+    @property\n+    def time_window(self):\n+        start = self.datetime_to_js(dt.datetime.strptime(\n+            self.request.session['startpage']['datepicker']['start'], '%d-%m-%Y'\n+        ))\n+        end = self.datetime_to_js(dt.datetime.strptime(\n+            self.request.session['startpage']['datepicker']['end'], '%d-%m-%Y'\n+        ))\n+        return {\n+            'start': start,\n+            'end': end\n+        }\n+\n+    # ------------------------------------------------------------------------ #\n+    ### Button handling:\n+\n+    @cached_property\n+    def length(self):\n+        length = self.request.session['startpage']['timeseries_length']\n+        if length < 0:\n+            return len(self.timeseries['values'])\n+        return length\n+\n+    @cached_property\n+    def spinner_value(self):\n+        return self.request.session[self.active]['spinner_0']['value']\n+\n+    @cached_property\n+    def dropdown_selected(self):\n+        return self.request.session[self.active]['dropdown_0']['value']\n+\n+    @cached_property\n+    def dropdown_unselected(self):\n+        return [x for x in self.dropdown_options if x != self.dropdown_selected]\n+\n+    @cached_property\n+    def datepicker_start(self):\n+        return [int(x) for x in self.request.session['startpage']['datepicker']['start'].split('-')]\n+\n+    @cached_property\n+    def datepicker_end(self):\n+        return [int(x) for x in self.request.session['startpage']['datepicker']['end'].split('-')]\n+\n+\n+class FreqTemplateView(TemplateView):\n \n     def get(self, request, *args, **kwargs):\n         if request.GET.get('undo', False):\n-            self.undo(request)\n+            self.undo()\n         elif request.GET.get('redo', False):\n-            self.redo(request)\n-        disabled = self.disabled(request)\n-        context = self.get_context_data(**kwargs)\n-        context['show_error'] = ''\n-        context['measurement_point'] = request.session['startpage'].get(\n-            'measurement_point', 'No Time Series Selected')\n-        context['menu'] = [\n-            (title, description, link, disabled[link] if link != self.active\n-            else 'active') for title, description,\n-            link in self.menu_items\n-        ]\n-        if not 'error_message' in kwargs:\n-            context['error_message'] = ''\n-            context['show_error']='hidden'\n-        context['selected_coords'] = json.dumps([float(x) for x\n-                                                 in request.session[\n-                                                     'startpage'].get(\n-            'selected_coords', [])])\n-        return self.render_to_response(context)\n+            self.redo()\n+        return super().get(request, *args, **kwargs)\n \n-    def set_session(self, request):\n-        request.session[self.active] = request.session.get(self.active, {})\n+\n+class BaseView(BaseViewMixin, FreqTemplateView):\n+    pass\n \n \n class MapView(BaseView):\n     active = 'map_'\n     template_name = 'freq/map.html'\n+    menu_items = []\n+    map_active = 'active'\n+    # statistic_options = ('min', 'max', 'mean')\n+    #\n+    # @property\n+    # def active_statistic(self):\n+    #     return self.request.session['map_'].get('active_statistic', 'mean')\n+    #\n+    # @property\n+    # def statistics(self):\n+    #     return [s for s in self.statistic_options if s != self.active_statistic]\n+    # TODO: update to spinners and other buttons\n \n \n-class StartPageView(BaseView):\n+class StartPageBaseView(BaseView):\n     active = 'startpage'\n+    freq_active = 'active'\n     template_name = 'freq/startpage.html'\n \n-    def get(self, request, *args, **kwargs):\n-        self.set_session(request)\n-        return super().get(request, *args, **kwargs)\n+\n+class StartPageView(StartPageBaseView):\n+    active = 'startpage'\n+    freq_active = 'active'\n+    template_name = 'freq/startpage.html'\n+\n+    def dispatch(self, *args, **kwargs):  # TODO: PUT IN ALL VIEWS\n+        if not self.request.session.get('session_is_set', False):\n+            self.instantiate_session()\n+        return super().dispatch(*args, **kwargs)\n \n \n class ReStartPageView(StartPageView):\n \n     def get(self, request, *args, **kwargs):\n-        self.flush(request)\n-        self.set_session(request)\n+        self.instantiate_session()\n         return super().get(request, *args, **kwargs)\n \n \n-class TimeSeriesQueryView(StartPageView):\n-\n-    def get(self, request, x_coord, y_coord, *args, **kwargs):\n-        kwargs['multiple_timeseries'] = False\n-        ts = TimeSeries()\n-        ts.location_uuid(kwargs['uuid'])\n-        request.session['startpage']['selected_coords'] = [x_coord, y_coord]\n-        if len(ts.results) == 0:\n-            kwargs['error_message'] = 'No time series found for this ' \\\n-                                      'location, please select another.'\n-        elif len(ts.results) == 1:\n-            request.session['startpage']['measurement_point'] = \\\n-                \"Meetpunt: \" + ts.results[0]['name']\n-            request.session['disabled']['trend_detection'] = ''\n-            request.session['trend_detection'] = {'active':True}\n-        else:\n-            kwargs['error_message'] = 'Multiple time series found for ' \\\n-                                      'this location, please select one ' \\\n-                                      'below.'\n-            kwargs['multiple_timeseries'] = True\n-            kwargs['timeseries'] = [\n+class TimeSeriesByLocationUUIDView(StartPageBaseView):\n+    error_message = ''\n+\n+    @cached_property\n+    def timeseries(self):\n+        ts = GroundwaterTimeSeries()\n+        ts.location_uuid(self.uuid)\n+        return ts.results\n+\n+    @cached_property\n+    def multiple_timeseries(self):\n+        return len(self.timeseries) > 1\n+\n+    @cached_property\n+    def error_message(self):\n+        if self.multiple_timeseries:\n+            return 'Multiple time series found for this location, please ' \\\n+                   'select one below.'\n+        elif len(self.timeseries) == 1:\n+            return 'No time series found for this location, please select ' \\\n+                   'another.'\n+        return ''\n+\n+    @property\n+    def timeseries_selection(self):\n+        if self.multiple_timeseries:\n+            return [\n                 (\n                     x['location']['name'] + ' - ' + x['name'],\n                     x['uuid'],\n                     x['first_value_timestamp'],\n                     x['last_value_timestamp']\n                 )\n-                for x in ts.results]\n+                for x in self.timeseries\n+            ]\n+        elif len(self.timeseries) == 1:\n+            result = self.timeseries[0]\n+            self.set_session_value('startpage', 'measurement_point',\n+                \"Meetpunt: \" + result['name'])\n+            self.set_session_value('disabled', 'trend_detection', 'enabled')\n+            self.request.session.modified = True\n+            self.set_session_value('trend_detection', 'active', True)\n+            self.set_session_value('periodic_fluctuations', 'active', True)\n+            self.set_session_value('startpage', 'start_js', result['first_value_timestamp'])\n+            self.set_session_value('startpage', 'end_js', result['last_value_timestamp'])\n+            self.set_session_value('startpage', 'uuid', result['uuid'])\n+        return []\n+\n+    @cached_property\n+    def uuid(self):\n+        return self.request.GET['uuid']\n+\n+    @cached_property\n+    def coordinates(self):\n+        return [self.request.GET['x_coord'], self.request.GET['y_coord']]\n+\n+    def get(self, request, *args, **kwargs):\n+        self.request.session['startpage']['selected_coords'] = self.coordinates\n+        self.request.session['map_']['center'] = self.coordinates\n+        self.request.session.modified = True\n         return super().get(request, *args, **kwargs)\n \n \n-class TimeSeriesStartPageView(StartPageView):\n+class TimeSeriesByUUIDView(StartPageBaseView):\n \n-    def get(self, request, uuid, start, end, *args, **kwargs):\n-        ts = TimeSeries()\n-        ts.uuid(uuid, start, end)\n+    def to_date(self, date_extreme):\n+        return self.js_to_datetime(int(self.request.GET[date_extreme])\n+                                   ).strftime('%d-%m-%Y')\n \n-        if len(ts.results) == 0:\n-            kwargs['error_message'] = 'No time series found for this ' \\\n-                                      'location, please select another.'\n-        else:\n-            data = [{'y': x['max'], 'x': x['timestamp']}\n-                             for x in ts.results[0]['events']]\n-            data = [{\n-                'values': data,\n-                'key': 'Groundwaterlevels (m)',\n-                'color': '#1abc9c'\n-            }]\n-            request.session['startpage']['measurement_point'] = \\\n-                \"Meetpunt: \" + ts.results[0]['location']['name']\n-            request.session['disabled']['trend_detection'] = ''\n-            request.session['trend_detection'] = {'active':True}\n-            request.session['startpage'].update(\n-                {\n-                    'start': start,\n-                    'end': end,\n-                    'uuid': uuid,\n-                    'data': data\n-                }\n-            )\n-            kwargs['data'] = data\n-            kwargs['chart'] = ''\n+    @property\n+    def startdate(self):\n+        return self.to_date('start')\n+\n+    @property\n+    def enddate(self):\n+        return self.to_date('end')\n+\n+    def get(self, request, uuid, *args, **kwargs):\n+        self.set_session_value('startpage', 'measurement_point',\n+                               \"Meetpunt: \" + self.request.GET['name'])\n+        self.set_session_value('startpage', 'datepicker',\n+                               {\n+                                    'start': self.startdate,\n+                                    'end': self.enddate\n+                               })\n+        self.set_session_value('startpage', 'start_js', request.GET['start'])\n+        self.set_session_value('startpage', 'end_js', request.GET['end'])\n+        self.set_session_value('startpage', 'uuid', uuid)\n+        self.request.session['disabled']['trend_detection'] = 'enabled'\n+        self.request.session.modified = True\n+        self.set_session_value('trend_detection', 'active', True)\n+        self.chart = ''\n         return super().get(request, *args, **kwargs)\n \n \n class TrendDetectionView(BaseView):\n+    freq_active = 'active'\n     active = 'trend_detection'\n     template_name = 'freq/trend_detection.html'\n+    spinners = Spinner(\n+        heading='Alpha (significance)',\n+        title=\"alpha (significance of the t-test for changes in the \" \\\n+                    \"mean (0-1))\",\n+        min_=0.01,\n+        step=0.01,\n+        precision=2\n+    )\n+\n+    dropdowns = DropDown(\n+        heading= \"Trend type\",\n+    )\n+    spinner_max = 0.99\n+    dropdown_options= [\n+        \"Both trends\",\n+        \"Linear trend\",\n+        \"Step trend\"\n+    ]\n \n \n class PeriodicFluctuationsView(BaseView):\n-    active = 'periodic_fluctuation'\n+    freq_active = 'active'\n+    active = 'periodic_fluctuations'\n     template_name = 'freq/periodic_fluctuations.html'\n+    spinners = [","path":"freq/views.py","position":639,"original_position":639,"commit_id":"8786134de546541b1dfe9cebbed9c4a523b28154","original_commit_id":"8786134de546541b1dfe9cebbed9c4a523b28154","user":{"login":"reinout","id":121433,"avatar_url":"https://avatars.githubusercontent.com/u/121433?v=3","gravatar_id":"","url":"https://api.github.com/users/reinout","html_url":"https://github.com/reinout","followers_url":"https://api.github.com/users/reinout/followers","following_url":"https://api.github.com/users/reinout/following{/other_user}","gists_url":"https://api.github.com/users/reinout/gists{/gist_id}","starred_url":"https://api.github.com/users/reinout/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reinout/subscriptions","organizations_url":"https://api.github.com/users/reinout/orgs","repos_url":"https://api.github.com/users/reinout/repos","events_url":"https://api.github.com/users/reinout/events{/privacy}","received_events_url":"https://api.github.com/users/reinout/received_events","type":"User","site_admin":false},"body":"Hier heeft spinners wel netjes een meervoud-waarde.","created_at":"2016-01-06T11:15:21Z","updated_at":"2016-01-06T11:15:21Z","html_url":"https://github.com/lizardsystem/freq/pull/1#discussion_r48947559","pull_request_url":"https://api.github.com/repos/lizardsystem/freq/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/comments/48947559"},"html":{"href":"https://github.com/lizardsystem/freq/pull/1#discussion_r48947559"},"pull_request":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/lizardsystem/freq/pulls/1","id":54685650,"html_url":"https://github.com/lizardsystem/freq/pull/1","diff_url":"https://github.com/lizardsystem/freq/pull/1.diff","patch_url":"https://github.com/lizardsystem/freq/pull/1.patch","issue_url":"https://api.github.com/repos/lizardsystem/freq/issues/1","number":1,"state":"open","locked":false,"title":"Roel refactor views","user":{"login":"RoelvandenBerg","id":10162961,"avatar_url":"https://avatars.githubusercontent.com/u/10162961?v=3","gravatar_id":"","url":"https://api.github.com/users/RoelvandenBerg","html_url":"https://github.com/RoelvandenBerg","followers_url":"https://api.github.com/users/RoelvandenBerg/followers","following_url":"https://api.github.com/users/RoelvandenBerg/following{/other_user}","gists_url":"https://api.github.com/users/RoelvandenBerg/gists{/gist_id}","starred_url":"https://api.github.com/users/RoelvandenBerg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RoelvandenBerg/subscriptions","organizations_url":"https://api.github.com/users/RoelvandenBerg/orgs","repos_url":"https://api.github.com/users/RoelvandenBerg/repos","events_url":"https://api.github.com/users/RoelvandenBerg/events{/privacy}","received_events_url":"https://api.github.com/users/RoelvandenBerg/received_events","type":"User","site_admin":false},"body":"Reinout,\r\n\r\nAllereerst nogmaals gefeliciteerd!\r\nSorry, vorige week vrijdag werd ik er iets eerder dan verwacht (20 over 5) door de schoonmaakster het gebouw uit gebonjourd ivm kerstnacht (haar goed recht i guess, welke idioot werkt er dan nog ;-)). Aangezien mijn code toen nog niet werkend was (ik was halverwege het omschrijven naar buttons) wilde ik die nog niet committen. Nu heb ik dat wel al gedaan zodat jij er naar kan kijken a.s. week. Mocht je daar zin in hebben. Ik ben helaas nog zeer spaarzaam met comments en docstrings. Sinds de crash alweer twee maanden geleden heb ik ook flake8 niet meer geinstalleerd (I know: Foei!). Maar hou met Pycharm zoveel mogelijk Flake 8 aan. Als daar toch nog veels te veel van niet goed zit hoor ik het graag, dan loop ik daar nog een keer door. \r\n\r\nGroet,\r\n\r\nRoel","created_at":"2015-12-28T21:37:55Z","updated_at":"2016-01-06T11:15:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c3b43d4fa74fb693151fea4c4431941e5bbc4636","assignee":{"login":"reinout","id":121433,"avatar_url":"https://avatars.githubusercontent.com/u/121433?v=3","gravatar_id":"","url":"https://api.github.com/users/reinout","html_url":"https://github.com/reinout","followers_url":"https://api.github.com/users/reinout/followers","following_url":"https://api.github.com/users/reinout/following{/other_user}","gists_url":"https://api.github.com/users/reinout/gists{/gist_id}","starred_url":"https://api.github.com/users/reinout/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reinout/subscriptions","organizations_url":"https://api.github.com/users/reinout/orgs","repos_url":"https://api.github.com/users/reinout/repos","events_url":"https://api.github.com/users/reinout/events{/privacy}","received_events_url":"https://api.github.com/users/reinout/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/lizardsystem/freq/pulls/1/commits","review_comments_url":"https://api.github.com/repos/lizardsystem/freq/pulls/1/comments","review_comment_url":"https://api.github.com/repos/lizardsystem/freq/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lizardsystem/freq/issues/1/comments","statuses_url":"https://api.github.com/repos/lizardsystem/freq/statuses/8786134de546541b1dfe9cebbed9c4a523b28154","head":{"label":"lizardsystem:roel-refactor_views","ref":"roel-refactor_views","sha":"8786134de546541b1dfe9cebbed9c4a523b28154","user":{"login":"lizardsystem","id":1029862,"avatar_url":"https://avatars.githubusercontent.com/u/1029862?v=3","gravatar_id":"","url":"https://api.github.com/users/lizardsystem","html_url":"https://github.com/lizardsystem","followers_url":"https://api.github.com/users/lizardsystem/followers","following_url":"https://api.github.com/users/lizardsystem/following{/other_user}","gists_url":"https://api.github.com/users/lizardsystem/gists{/gist_id}","starred_url":"https://api.github.com/users/lizardsystem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lizardsystem/subscriptions","organizations_url":"https://api.github.com/users/lizardsystem/orgs","repos_url":"https://api.github.com/users/lizardsystem/repos","events_url":"https://api.github.com/users/lizardsystem/events{/privacy}","received_events_url":"https://api.github.com/users/lizardsystem/received_events","type":"Organization","site_admin":false},"repo":{"id":44813583,"name":"freq","full_name":"lizardsystem/freq","owner":{"login":"lizardsystem","id":1029862,"avatar_url":"https://avatars.githubusercontent.com/u/1029862?v=3","gravatar_id":"","url":"https://api.github.com/users/lizardsystem","html_url":"https://github.com/lizardsystem","followers_url":"https://api.github.com/users/lizardsystem/followers","following_url":"https://api.github.com/users/lizardsystem/following{/other_user}","gists_url":"https://api.github.com/users/lizardsystem/gists{/gist_id}","starred_url":"https://api.github.com/users/lizardsystem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lizardsystem/subscriptions","organizations_url":"https://api.github.com/users/lizardsystem/orgs","repos_url":"https://api.github.com/users/lizardsystem/repos","events_url":"https://api.github.com/users/lizardsystem/events{/privacy}","received_events_url":"https://api.github.com/users/lizardsystem/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lizardsystem/freq","description":"FREQ groundwater analysis app","fork":false,"url":"https://api.github.com/repos/lizardsystem/freq","forks_url":"https://api.github.com/repos/lizardsystem/freq/forks","keys_url":"https://api.github.com/repos/lizardsystem/freq/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lizardsystem/freq/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lizardsystem/freq/teams","hooks_url":"https://api.github.com/repos/lizardsystem/freq/hooks","issue_events_url":"https://api.github.com/repos/lizardsystem/freq/issues/events{/number}","events_url":"https://api.github.com/repos/lizardsystem/freq/events","assignees_url":"https://api.github.com/repos/lizardsystem/freq/assignees{/user}","branches_url":"https://api.github.com/repos/lizardsystem/freq/branches{/branch}","tags_url":"https://api.github.com/repos/lizardsystem/freq/tags","blobs_url":"https://api.github.com/repos/lizardsystem/freq/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lizardsystem/freq/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lizardsystem/freq/git/refs{/sha}","trees_url":"https://api.github.com/repos/lizardsystem/freq/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lizardsystem/freq/statuses/{sha}","languages_url":"https://api.github.com/repos/lizardsystem/freq/languages","stargazers_url":"https://api.github.com/repos/lizardsystem/freq/stargazers","contributors_url":"https://api.github.com/repos/lizardsystem/freq/contributors","subscribers_url":"https://api.github.com/repos/lizardsystem/freq/subscribers","subscription_url":"https://api.github.com/repos/lizardsystem/freq/subscription","commits_url":"https://api.github.com/repos/lizardsystem/freq/commits{/sha}","git_commits_url":"https://api.github.com/repos/lizardsystem/freq/git/commits{/sha}","comments_url":"https://api.github.com/repos/lizardsystem/freq/comments{/number}","issue_comment_url":"https://api.github.com/repos/lizardsystem/freq/issues/comments{/number}","contents_url":"https://api.github.com/repos/lizardsystem/freq/contents/{+path}","compare_url":"https://api.github.com/repos/lizardsystem/freq/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lizardsystem/freq/merges","archive_url":"https://api.github.com/repos/lizardsystem/freq/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lizardsystem/freq/downloads","issues_url":"https://api.github.com/repos/lizardsystem/freq/issues{/number}","pulls_url":"https://api.github.com/repos/lizardsystem/freq/pulls{/number}","milestones_url":"https://api.github.com/repos/lizardsystem/freq/milestones{/number}","notifications_url":"https://api.github.com/repos/lizardsystem/freq/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lizardsystem/freq/labels{/name}","releases_url":"https://api.github.com/repos/lizardsystem/freq/releases{/id}","created_at":"2015-10-23T13:05:41Z","updated_at":"2015-10-23T13:57:34Z","pushed_at":"2016-01-04T17:28:30Z","git_url":"git://github.com/lizardsystem/freq.git","ssh_url":"git@github.com:lizardsystem/freq.git","clone_url":"https://github.com/lizardsystem/freq.git","svn_url":"https://github.com/lizardsystem/freq","homepage":null,"size":715,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"lizardsystem:master","ref":"master","sha":"f64c564318757e90406eb763c12108904ba6a05c","user":{"login":"lizardsystem","id":1029862,"avatar_url":"https://avatars.githubusercontent.com/u/1029862?v=3","gravatar_id":"","url":"https://api.github.com/users/lizardsystem","html_url":"https://github.com/lizardsystem","followers_url":"https://api.github.com/users/lizardsystem/followers","following_url":"https://api.github.com/users/lizardsystem/following{/other_user}","gists_url":"https://api.github.com/users/lizardsystem/gists{/gist_id}","starred_url":"https://api.github.com/users/lizardsystem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lizardsystem/subscriptions","organizations_url":"https://api.github.com/users/lizardsystem/orgs","repos_url":"https://api.github.com/users/lizardsystem/repos","events_url":"https://api.github.com/users/lizardsystem/events{/privacy}","received_events_url":"https://api.github.com/users/lizardsystem/received_events","type":"Organization","site_admin":false},"repo":{"id":44813583,"name":"freq","full_name":"lizardsystem/freq","owner":{"login":"lizardsystem","id":1029862,"avatar_url":"https://avatars.githubusercontent.com/u/1029862?v=3","gravatar_id":"","url":"https://api.github.com/users/lizardsystem","html_url":"https://github.com/lizardsystem","followers_url":"https://api.github.com/users/lizardsystem/followers","following_url":"https://api.github.com/users/lizardsystem/following{/other_user}","gists_url":"https://api.github.com/users/lizardsystem/gists{/gist_id}","starred_url":"https://api.github.com/users/lizardsystem/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lizardsystem/subscriptions","organizations_url":"https://api.github.com/users/lizardsystem/orgs","repos_url":"https://api.github.com/users/lizardsystem/repos","events_url":"https://api.github.com/users/lizardsystem/events{/privacy}","received_events_url":"https://api.github.com/users/lizardsystem/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lizardsystem/freq","description":"FREQ groundwater analysis app","fork":false,"url":"https://api.github.com/repos/lizardsystem/freq","forks_url":"https://api.github.com/repos/lizardsystem/freq/forks","keys_url":"https://api.github.com/repos/lizardsystem/freq/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lizardsystem/freq/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lizardsystem/freq/teams","hooks_url":"https://api.github.com/repos/lizardsystem/freq/hooks","issue_events_url":"https://api.github.com/repos/lizardsystem/freq/issues/events{/number}","events_url":"https://api.github.com/repos/lizardsystem/freq/events","assignees_url":"https://api.github.com/repos/lizardsystem/freq/assignees{/user}","branches_url":"https://api.github.com/repos/lizardsystem/freq/branches{/branch}","tags_url":"https://api.github.com/repos/lizardsystem/freq/tags","blobs_url":"https://api.github.com/repos/lizardsystem/freq/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lizardsystem/freq/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lizardsystem/freq/git/refs{/sha}","trees_url":"https://api.github.com/repos/lizardsystem/freq/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lizardsystem/freq/statuses/{sha}","languages_url":"https://api.github.com/repos/lizardsystem/freq/languages","stargazers_url":"https://api.github.com/repos/lizardsystem/freq/stargazers","contributors_url":"https://api.github.com/repos/lizardsystem/freq/contributors","subscribers_url":"https://api.github.com/repos/lizardsystem/freq/subscribers","subscription_url":"https://api.github.com/repos/lizardsystem/freq/subscription","commits_url":"https://api.github.com/repos/lizardsystem/freq/commits{/sha}","git_commits_url":"https://api.github.com/repos/lizardsystem/freq/git/commits{/sha}","comments_url":"https://api.github.com/repos/lizardsystem/freq/comments{/number}","issue_comment_url":"https://api.github.com/repos/lizardsystem/freq/issues/comments{/number}","contents_url":"https://api.github.com/repos/lizardsystem/freq/contents/{+path}","compare_url":"https://api.github.com/repos/lizardsystem/freq/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lizardsystem/freq/merges","archive_url":"https://api.github.com/repos/lizardsystem/freq/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lizardsystem/freq/downloads","issues_url":"https://api.github.com/repos/lizardsystem/freq/issues{/number}","pulls_url":"https://api.github.com/repos/lizardsystem/freq/pulls{/number}","milestones_url":"https://api.github.com/repos/lizardsystem/freq/milestones{/number}","notifications_url":"https://api.github.com/repos/lizardsystem/freq/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lizardsystem/freq/labels{/name}","releases_url":"https://api.github.com/repos/lizardsystem/freq/releases{/id}","created_at":"2015-10-23T13:05:41Z","updated_at":"2015-10-23T13:57:34Z","pushed_at":"2016-01-04T17:28:30Z","git_url":"git://github.com/lizardsystem/freq.git","ssh_url":"git@github.com:lizardsystem/freq.git","clone_url":"https://github.com/lizardsystem/freq.git","svn_url":"https://github.com/lizardsystem/freq","homepage":null,"size":715,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/1"},"html":{"href":"https://github.com/lizardsystem/freq/pull/1"},"issue":{"href":"https://api.github.com/repos/lizardsystem/freq/issues/1"},"comments":{"href":"https://api.github.com/repos/lizardsystem/freq/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lizardsystem/freq/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/lizardsystem/freq/statuses/8786134de546541b1dfe9cebbed9c4a523b28154"}}}}