diff --git a/gulpfile.js b/gulpfile.js
index 85ed64030c0677b9e398a21198814269fb194643..c25abcae7119a05d57cf7b17697f43ccd392ed72 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -266,10 +266,10 @@ gulp.task('watch:app', function watch (callback) {
 gulp.task('watch', gulp.parallel('watch:css', 'watch:lint:sass', 'watch:js', 'watch:lint:js', 'watch:images', 'watch:fonts', 'watch:static'));
 
 // Build everything.
-gulp.task('build', gulp.series(gulp.parallel('styles:production', 'scripts:production', 'app:production', 'images', 'fonts', 'lint'), 'collectstatic'));
+gulp.task('build', gulp.series(gulp.parallel(gulp.series('styles:production', 'scripts:production', 'app:production'), 'images', 'fonts', 'lint'), 'collectstatic'));
 
 // Deploy everything.
-gulp.task('deploy', gulp.parallel('styles:production', 'scripts:production', 'app:production', 'images', 'fonts'));
+gulp.task('deploy', gulp.parallel(gulp.series('styles:production', 'scripts:production', 'app:production'), 'images', 'fonts'));
 
 // The default task.
 gulp.task('default', gulp.series('build'));
diff --git a/opentech/api/__init__.py b/opentech/api/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/api/pagination.py b/opentech/api/pagination.py
new file mode 100644
index 0000000000000000000000000000000000000000..1382e50358d993cb6629244709a19261b0616df7
--- /dev/null
+++ b/opentech/api/pagination.py
@@ -0,0 +1,6 @@
+from rest_framework import pagination
+
+
+class StandardResultsSetPagination(pagination.PageNumberPagination):
+    page_size_query_param = 'page_size'
+    max_page_size = 1000
diff --git a/opentech/apply/activity/messaging.py b/opentech/apply/activity/messaging.py
index 29c0ad9d865174320b45a13d5f8f5c2f5f73aa4a..a7cb75e0afddeb0094c57b55fb515547cb29ac91 100644
--- a/opentech/apply/activity/messaging.py
+++ b/opentech/apply/activity/messaging.py
@@ -1,3 +1,4 @@
+import json
 import requests
 
 from django.db import models
@@ -5,6 +6,7 @@ from django.conf import settings
 from django.contrib import messages
 from django.template.loader import render_to_string
 
+from .models import INTERNAL, PUBLIC
 from .options import MESSAGES
 from .tasks import send_mail
 
@@ -21,6 +23,7 @@ neat_related = {
     MESSAGES.APPLICANT_EDIT: 'revision',
     MESSAGES.EDIT: 'revision',
     MESSAGES.COMMENT: 'comment',
+    MESSAGES.SCREENING: 'old_status',
 }
 
 
@@ -117,7 +120,7 @@ class ActivityAdapter(AdapterBase):
     adapter_type = "Activity Feed"
     always_send = True
     messages = {
-        MESSAGES.TRANSITION: 'Progressed from {old_phase.display_name} to {submission.phase}',
+        MESSAGES.TRANSITION: 'handle_transition',
         MESSAGES.NEW_SUBMISSION: 'Submitted {submission.title} for {submission.page.title}',
         MESSAGES.EDIT: 'Edited',
         MESSAGES.APPLICANT_EDIT: 'Edited',
@@ -127,14 +130,18 @@ class ActivityAdapter(AdapterBase):
         MESSAGES.REVIEWERS_UPDATED: 'reviewers_updated',
         MESSAGES.NEW_REVIEW: 'Submitted a review',
         MESSAGES.OPENED_SEALED: 'Opened the submission while still sealed',
+        MESSAGES.SCREENING: 'Screening status from {old_status} to {submission.screening_status}'
     }
 
     def recipients(self, message_type, **kwargs):
         return [None]
 
-    def extra_kwargs(self, message_type, **kwargs):
-        if message_type in [MESSAGES.OPENED_SEALED, MESSAGES.REVIEWERS_UPDATED]:
-            from .models import INTERNAL
+    def extra_kwargs(self, message_type, submission, **kwargs):
+        from .models import INTERNAL
+        if message_type in [MESSAGES.OPENED_SEALED, MESSAGES.REVIEWERS_UPDATED, MESSAGES.SCREENING]:
+            return {'visibility': INTERNAL}
+        if message_type == MESSAGES.TRANSITION and not submission.phase.permissions.can_view(submission.user):
+            # User's shouldn't see status activity changes for stages that aren't visible to the them
             return {'visibility': INTERNAL}
         return {}
 
@@ -150,12 +157,40 @@ class ActivityAdapter(AdapterBase):
 
         return ' '.join(message)
 
+    def handle_transition(self, old_phase, submission, **kwargs):
+        base_message = 'Progressed from {old_display} to {new_display}'
+
+        new_phase = submission.phase
+
+        staff_message = base_message.format(
+            old_display=old_phase.display_name,
+            new_display=new_phase.display_name,
+        )
+
+        if new_phase.permissions.can_view(submission.user):
+            # we need to provide a different message to the applicant
+            if not old_phase.permissions.can_view(submission.user):
+                old_phase = submission.workflow.previous_visible(old_phase, submission.user)
+
+            applicant_message = base_message.format(
+                old_display=old_phase.public_name,
+                new_display=new_phase.public_name,
+            )
+
+            return json.dumps({
+                INTERNAL: staff_message,
+                PUBLIC: applicant_message,
+            })
+
+        return staff_message
+
     def send_message(self, message, user, submission, **kwargs):
         from .models import Activity, PUBLIC
         visibility = kwargs.get('visibility', PUBLIC)
 
         related = kwargs['related']
-        if isinstance(related, models.Model):
+        has_correct_fields = all(hasattr(related, attr) for attr in ['author', 'submission', 'get_absolute_url'])
+        if has_correct_fields and isinstance(related, models.Model):
             related_object = related
         else:
             related_object = None
@@ -300,6 +335,11 @@ class EmailAdapter(AdapterBase):
     def recipients(self, message_type, submission, **kwargs):
         if message_type == MESSAGES.READY_FOR_REVIEW:
             return self.reviewers(submission)
+
+        if message_type == MESSAGES.TRANSITION:
+            # Only notify the applicant if the new phase can be seen within the workflow
+            if not submission.phase.permissions.can_view(submission.user):
+                return []
         return [submission.user.email]
 
     def reviewers(self, submission):
diff --git a/opentech/apply/activity/migrations/0013_add_new_event_type_screening.py b/opentech/apply/activity/migrations/0013_add_new_event_type_screening.py
new file mode 100644
index 0000000000000000000000000000000000000000..065b7afa51b2253c7411086c11f82d114c81c1e4
--- /dev/null
+++ b/opentech/apply/activity/migrations/0013_add_new_event_type_screening.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.0.10 on 2019-01-09 16:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('activity', '0012_add_generic_relation_to_activity'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='event',
+            name='type',
+            field=models.CharField(choices=[('UPDATE_LEAD', 'Update Lead'), ('EDIT', 'Edit'), ('APPLICANT_EDIT', 'Applicant Edit'), ('NEW_SUBMISSION', 'New Submission'), ('SCREENING', 'Screening'), ('TRANSITION', 'Transition'), ('DETERMINATION_OUTCOME', 'Determination Outcome'), ('INVITED_TO_PROPOSAL', 'Invited To Proposal'), ('REVIEWERS_UPDATED', 'Reviewers Updated'), ('READY_FOR_REVIEW', 'Ready For Review'), ('NEW_REVIEW', 'New Review'), ('COMMENT', 'Comment'), ('PROPOSAL_SUBMITTED', 'Proposal Submitted'), ('OPENED_SEALED', 'Opened Sealed Submission')], max_length=50),
+        ),
+    ]
diff --git a/opentech/apply/activity/options.py b/opentech/apply/activity/options.py
index ca9a78cb0baafbf87323780ab7f3b20e1971317f..46d744e035fa0af24a76b6c63996edf6e3523e6e 100644
--- a/opentech/apply/activity/options.py
+++ b/opentech/apply/activity/options.py
@@ -6,6 +6,7 @@ class MESSAGES(Enum):
     EDIT = 'Edit'
     APPLICANT_EDIT = "Applicant Edit"
     NEW_SUBMISSION = 'New Submission'
+    SCREENING = 'Screening'
     TRANSITION = 'Transition'
     DETERMINATION_OUTCOME = 'Determination Outcome'
     INVITED_TO_PROPOSAL = 'Invited To Proposal'
diff --git a/opentech/apply/activity/templates/activity/include/listing_base.html b/opentech/apply/activity/templates/activity/include/listing_base.html
index 23056f2fcd17b5d104676122e098172af5611f71..f999f30d48506338aea55ecea8cafb49b56a566a 100644
--- a/opentech/apply/activity/templates/activity/include/listing_base.html
+++ b/opentech/apply/activity/templates/activity/include/listing_base.html
@@ -19,7 +19,7 @@
                 updated <a href="{{ activity.submission.get_absolute_url }}">{{ activity.submission.title }}</a>
             {% endif %}
 
-            {{ activity.message|submission_links|markdown|bleach }}
+            {{ activity|display_for:request.user|submission_links|markdown|bleach }}
 
             {% if not submission_title and activity|user_can_see_related:request.user %}
                 {% with url=activity.related_object.get_absolute_url %}
diff --git a/opentech/apply/activity/templatetags/activity_tags.py b/opentech/apply/activity/templatetags/activity_tags.py
index 6f8c87ba50afb7cdca21112a8517701ebf75636f..1f43a872e263ae8585d4b1a0c4cf39cb1626868e 100644
--- a/opentech/apply/activity/templatetags/activity_tags.py
+++ b/opentech/apply/activity/templatetags/activity_tags.py
@@ -1,8 +1,12 @@
+import json
+
 from django import template
 
 from opentech.apply.determinations.models import Determination
 from opentech.apply.review.models import Review
 
+from ..models import INTERNAL, PUBLIC, REVIEWER
+
 register = template.Library()
 
 
@@ -25,3 +29,18 @@ def user_can_see_related(activity, user):
         return True
 
     return False
+
+
+@register.filter
+def display_for(activity, user):
+    try:
+        message_data = json.loads(activity.message)
+    except json.JSONDecodeError:
+        return activity.message
+
+    visibile_for_user = activity.visibility_for(user)
+
+    if set(visibile_for_user) & set([INTERNAL, REVIEWER]):
+        return message_data[INTERNAL]
+
+    return message_data[PUBLIC]
diff --git a/opentech/apply/activity/tests/test_messaging.py b/opentech/apply/activity/tests/test_messaging.py
index ec782ecf9cbf2f567b2e96db42c0b513dc17271d..d804f3c4f52f815e9b8376e62ea926cd269b3574 100644
--- a/opentech/apply/activity/tests/test_messaging.py
+++ b/opentech/apply/activity/tests/test_messaging.py
@@ -11,9 +11,10 @@ from django.contrib.messages import get_messages
 
 from opentech.apply.utils.testing import make_request
 from opentech.apply.funds.tests.factories import ApplicationSubmissionFactory
-from opentech.apply.users.tests.factories import UserFactory, ReviewerFactory
+from opentech.apply.review.tests.factories import ReviewFactory
+from opentech.apply.users.tests.factories import ReviewerFactory, UserFactory
 
-from ..models import Activity, Event, Message
+from ..models import Activity, Event, Message, INTERNAL, PUBLIC
 from ..messaging import (
     AdapterBase,
     ActivityAdapter,
@@ -222,6 +223,66 @@ class TestActivityAdapter(TestCase):
         self.assertTrue('1' in message)
         self.assertTrue('2' in message)
 
+    def test_internal_transition_kwarg_for_invisible_transition(self):
+        submission = ApplicationSubmissionFactory(status='post_review_discussion')
+        kwargs = self.adapter.extra_kwargs(MESSAGES.TRANSITION, submission=submission)
+
+        self.assertEqual(kwargs['visibility'], INTERNAL)
+
+    def test_public_transition_kwargs(self):
+        submission = ApplicationSubmissionFactory()
+        kwargs = self.adapter.extra_kwargs(MESSAGES.TRANSITION, submission=submission)
+
+        self.assertNotIn('visibility', kwargs)
+
+    def test_handle_transition_public_to_public(self):
+        submission = ApplicationSubmissionFactory(status='more_info')
+        old_phase = submission.workflow.phases_for()[0]
+
+        message = self.adapter.handle_transition(old_phase, submission)
+        message = json.loads(message)
+
+        self.assertIn(submission.phase.display_name, message[INTERNAL])
+        self.assertIn(old_phase.display_name, message[INTERNAL])
+        self.assertIn(submission.phase.public_name, message[PUBLIC])
+        self.assertIn(old_phase.public_name, message[PUBLIC])
+
+    def test_handle_transition_to_private_to_public(self):
+        submission = ApplicationSubmissionFactory(status='more_info')
+        old_phase = submission.workflow.phases_for()[1]
+
+        message = self.adapter.handle_transition(old_phase, submission)
+        message = json.loads(message)
+
+        self.assertIn(submission.phase.display_name, message[INTERNAL])
+        self.assertIn(old_phase.display_name, message[INTERNAL])
+        self.assertIn(submission.phase.public_name, message[PUBLIC])
+        self.assertIn(old_phase.public_name, message[PUBLIC])
+
+    def test_handle_transition_to_public_to_private(self):
+        submission = ApplicationSubmissionFactory(status='internal_review')
+        old_phase = submission.workflow.phases_for()[0]
+
+        message = self.adapter.handle_transition(old_phase, submission)
+
+        self.assertIn(submission.phase.display_name, message)
+        self.assertIn(old_phase.display_name, message)
+
+    def test_lead_not_saved_on_activity(self):
+        submission = ApplicationSubmissionFactory()
+        user = UserFactory()
+        self.adapter.send_message('a message', user=user, submission=submission, related=user)
+        activity = Activity.objects.first()
+        self.assertEqual(activity.related_object, None)
+
+    def test_review_saved_on_activtiy(self):
+        submission = ApplicationSubmissionFactory()
+        user = UserFactory()
+        review = ReviewFactory(submission=submission)
+        self.adapter.send_message('a message', user=user, submission=submission, related=review)
+        activity = Activity.objects.first()
+        self.assertEqual(activity.related_object, review)
+
 
 class TestSlackAdapter(AdapterMixin, TestCase):
     target_url = 'https://my-slack-backend.com/incoming/my-very-secret-key'
diff --git a/opentech/apply/activity/views.py b/opentech/apply/activity/views.py
index 07ba2d1dcb64df46393c08315b44aaf410260ad0..12600a8bd8033929a4513bcc34f4511fd1a92289 100644
--- a/opentech/apply/activity/views.py
+++ b/opentech/apply/activity/views.py
@@ -35,12 +35,14 @@ class ActivityContextMixin:
             'actions': Activity.actions.filter(submission=self.object).select_related(
                 'user',
             ).prefetch_related(
-                'related_object',
+                'related_object__author',
+                'related_object__submission',
             ).visible_to(self.request.user),
             'comments': Activity.comments.filter(submission=self.object).select_related(
                 'user',
             ).prefetch_related(
-                'related_object',
+                'related_object__author',
+                'related_object__submission',
             ).visible_to(self.request.user),
         }
 
diff --git a/opentech/apply/categories/blocks.py b/opentech/apply/categories/blocks.py
index 02359dc54c454236183c6407d962f59fc8e4c687..b8bf9a67c1180cd53a62490fae49aa46930fe6e9 100644
--- a/opentech/apply/categories/blocks.py
+++ b/opentech/apply/categories/blocks.py
@@ -74,12 +74,11 @@ class CategoryQuestionBlock(OptionalFormFieldBlock):
         else:
             return forms.RadioSelect
 
-    def render(self, value, context):
-        data = context['data']
+    def prepare_data(self, value, data, serialize):
         category = value['category']
         if data:
-            context['data'] = category.options.filter(id__in=data).values_list('value', flat=True)
-        return super().render(value, context)
+            data = category.options.filter(id__in=data).values_list('value', flat=True)
+        return data
 
     def get_searchable_content(self, value, data):
         return None
diff --git a/opentech/apply/dashboard/templates/dashboard/applicant_dashboard.html b/opentech/apply/dashboard/templates/dashboard/applicant_dashboard.html
index fa7d3b774881004160cebd2b9dcb3ea31da5aa4d..122386a8bcd37d53a6cae7b7de0609c86dbdc0ee 100644
--- a/opentech/apply/dashboard/templates/dashboard/applicant_dashboard.html
+++ b/opentech/apply/dashboard/templates/dashboard/applicant_dashboard.html
@@ -1,6 +1,6 @@
 {% extends "base-apply.html" %}
 {% load render_table from django_tables2 %}
-{% load static wagtailcore_tags workflow_tags %}
+{% load static wagtailcore_tags workflow_tags statusbar_tags %}
 
 {% block title %}Submission Dashboard{% endblock %}
 
@@ -27,7 +27,7 @@
                     <h5 class="heading heading--no-margin"><a class="link link--underlined" href="{% url 'funds:submissions:detail' submission.id %}">{{ submission.title }}</a></h5>
                     <h6 class="heading heading--no-margin heading--submission-meta"><span>Submitted:</span> {{ submission.submit_time.date }} by {{ submission.user.get_full_name }}</h6>
                 </div>
-                {% include "funds/includes/status_bar.html" with phases=submission.workflow current_phase=submission.phase class="status-bar--small" %}
+                {% status_bar submission.workflow submission.phase request.user css_class="status-bar--small" %}
             </div>
             {% if request.user|has_edit_perm:submission %}
                 <a class="button button--primary" href="{% url 'funds:submissions:edit' submission.id %}">
diff --git a/opentech/apply/dashboard/templates/dashboard/dashboard.html b/opentech/apply/dashboard/templates/dashboard/dashboard.html
index 1f355a82e7656ae982adc85d3280d10c078ae040..de14c3caef48d98e96c5c102aa8cdbd8362a1118 100644
--- a/opentech/apply/dashboard/templates/dashboard/dashboard.html
+++ b/opentech/apply/dashboard/templates/dashboard/dashboard.html
@@ -26,17 +26,6 @@
             {% endif %}
         </div>
 </div>
-
-<div class="wrapper wrapper--large wrapper--inner-space-medium">
-    <div class="wrapper wrapper--large wrapper--inner-space-medium">
-        <h3>Applications awaiting determination</h3>
-        {% if awaiting_determination.data %}
-            {% render_table awaiting_determination %}
-        {% else %}
-            No applications awaiting determination
-        {% endif %}
-    </div>
-</div>
 {% endblock %}
 
 {% block extra_js %}
diff --git a/opentech/apply/dashboard/tests/test_views.py b/opentech/apply/dashboard/tests/test_views.py
index df5a41eaa3227dd9a9b27ffe49ab4323717cd8fd..795fcf11f404596c3f6e6eeb885cfef8a8fc3a87 100644
--- a/opentech/apply/dashboard/tests/test_views.py
+++ b/opentech/apply/dashboard/tests/test_views.py
@@ -57,12 +57,6 @@ class TestStaffDashboard(BaseViewTestCase):
     url_name = 'dashboard:{}'
     base_view_name = 'dashboard'
 
-    def test_can_see_need_determinations(self):
-        ApplicationSubmissionFactory(status='concept_review_discussion', workflow_stages=2, lead=self.user,
-                                     form_data__title='Internet of things')
-        response = self.get_page()
-        self.assertContains(response, 'Internet of things')
-
     def test_cannot_see_submission_in_determination_when_not_lead(self):
         ApplicationSubmissionFactory(status='concept_review_discussion', workflow_stages=2, form_data__title='Reviewr')
         response = self.get_page()
diff --git a/opentech/apply/dashboard/views.py b/opentech/apply/dashboard/views.py
index 0592593f845e14cfb446e985017e690067def5e2..b8703e77d2457cd107d877c81bd101f44ad90d3f 100644
--- a/opentech/apply/dashboard/views.py
+++ b/opentech/apply/dashboard/views.py
@@ -16,15 +16,8 @@ class AdminDashboardView(TemplateView):
         in_review = SubmissionsTable(qs.in_review_for(request.user), prefix='in-review-')
         RequestConfig(request, paginate={'per_page': 10}).configure(in_review)
 
-        awaiting_determination = AdminSubmissionsTable(
-            qs.awaiting_determination_for(request.user),
-            prefix='pending-determination-'
-        )
-        RequestConfig(request, paginate={'per_page': 10}).configure(awaiting_determination)
-
         return render(request, 'dashboard/dashboard.html', {
             'in_review': in_review,
-            'awaiting_determination': awaiting_determination,
         })
 
 
diff --git a/opentech/apply/funds/admin.py b/opentech/apply/funds/admin.py
index 559a76bf512d52c8f94da44f33c9761a8374f645..689f73027216344b55a4b82eed731de5b7b55dfb 100644
--- a/opentech/apply/funds/admin.py
+++ b/opentech/apply/funds/admin.py
@@ -1,6 +1,7 @@
 from wagtail.contrib.modeladmin.helpers import PermissionHelper
 from wagtail.contrib.modeladmin.options import ModelAdmin, ModelAdminGroup
 
+from opentech.apply.funds.models import ScreeningStatus
 from opentech.apply.review.admin import ReviewFormAdmin
 from opentech.apply.utils.admin import ListRelatedMixin
 from .admin_helpers import (
@@ -27,6 +28,28 @@ class RoundAdmin(BaseRoundAdmin):
     menu_icon = 'repeat'
 
 
+class ScreeningStatusPermissionHelper(PermissionHelper):
+    def user_can_edit_obj(self, user, obj):
+        """
+        Return a boolean to indicate whether `user` is permitted to 'change'
+        a specific `self.model` instance.
+        """
+        return user.is_superuser
+
+    def user_can_delete_obj(self, user, obj):
+        """
+        Return a boolean to indicate whether `user` is permitted to 'delete'
+        a specific `self.model` instance.
+        """
+        return user.is_superuser
+
+
+class ScreeningStatusAdmin(ModelAdmin):
+    model = ScreeningStatus
+    menu_icon = 'tag'
+    permission_helper_class = ScreeningStatusPermissionHelper
+
+
 class SealedRoundAdmin(BaseRoundAdmin):
     model = SealedRound
     menu_icon = 'locked'
@@ -82,4 +105,5 @@ class ApplyAdminGroup(ModelAdminGroup):
         ApplicationFormAdmin,
         ReviewFormAdmin,
         CategoryAdmin,
+        ScreeningStatusAdmin,
     )
diff --git a/opentech/apply/funds/api_views.py b/opentech/apply/funds/api_views.py
new file mode 100644
index 0000000000000000000000000000000000000000..4e294f673bb74547106e2521eff91bb93be5fc8a
--- /dev/null
+++ b/opentech/apply/funds/api_views.py
@@ -0,0 +1,47 @@
+from django.db.models import Q
+from rest_framework import generics
+from rest_framework import permissions
+from django_filters import rest_framework as filters
+
+from wagtail.core.models import Page
+
+from opentech.api.pagination import StandardResultsSetPagination
+from .models import ApplicationSubmission
+from .serializers import SubmissionListSerializer, SubmissionDetailSerializer
+from .permissions import IsApplyStaffUser
+
+
+class RoundLabFilter(filters.ModelChoiceFilter):
+    def filter(self, qs, value):
+        if not value:
+            return qs
+
+        return qs.filter(Q(round=value) | Q(page=value))
+
+
+class SubmissionsFilter(filters.FilterSet):
+    # TODO replace with better call to Round and Lab base class
+    round = RoundLabFilter(queryset=Page.objects.all())
+
+    class Meta:
+        model = ApplicationSubmission
+        fields = ('status', 'round')
+
+
+class SubmissionList(generics.ListAPIView):
+    queryset = ApplicationSubmission.objects.current()
+    serializer_class = SubmissionListSerializer
+    permission_classes = (
+        permissions.IsAuthenticated, IsApplyStaffUser,
+    )
+    filter_backends = (filters.DjangoFilterBackend,)
+    filter_class = SubmissionsFilter
+    pagination_class = StandardResultsSetPagination
+
+
+class SubmissionDetail(generics.RetrieveAPIView):
+    queryset = ApplicationSubmission.objects.all()
+    serializer_class = SubmissionDetailSerializer
+    permission_classes = (
+        permissions.IsAuthenticated, IsApplyStaffUser,
+    )
diff --git a/opentech/apply/funds/blocks.py b/opentech/apply/funds/blocks.py
index d6a87a5f919876520865192f3e1dde137a13a782..7ddff78f7ef5869c3f92078415d452ab913d88d3 100644
--- a/opentech/apply/funds/blocks.py
+++ b/opentech/apply/funds/blocks.py
@@ -39,6 +39,9 @@ class ValueBlock(ApplicationSingleIncludeFieldBlock):
     class Meta:
         label = _('Requested amount')
 
+    def prepare_data(self, value, data, serialize):
+        return '$' + str(data)
+
 
 class EmailBlock(ApplicationMustIncludeFieldBlock):
     name = 'email'
@@ -62,14 +65,29 @@ class AddressFieldBlock(ApplicationSingleIncludeFieldBlock):
 
     def format_data(self, data):
         # Based on the fields listed in addressfields/widgets.py
+        return ', '.join(
+            data[field]
+            for field in order_fields
+            if data[field]
+        )
+
+    def prepare_data(self, value, data, serialize):
         order_fields = [
             'thoroughfare', 'premise', 'localityname', 'administrativearea', 'postalcode', 'country'
         ]
-        address = json.loads(data)
-        return ', '.join(
-            address[field]
+        data = json.loads(data)
+        data = {
+            field: data[field]
             for field in order_fields
-            if address[field]
+        }
+
+        if serialize:
+            return data
+
+        return ', '.join(
+            value
+            for value in data.values()
+            if value
         )
 
 
@@ -108,7 +126,7 @@ class DurationBlock(ApplicationMustIncludeFieldBlock):
         field_kwargs['choices'] = self.DURATION_OPTIONS.items()
         return field_kwargs
 
-    def format_data(self, data):
+    def prepare_data(self, value, data, serialize):
         return self.DURATION_OPTIONS[int(data)]
 
     class Meta:
diff --git a/opentech/apply/funds/forms.py b/opentech/apply/funds/forms.py
index dd435d559c7c1ad8fe05463bbf774398e294af66..0b1df3d3b4a79c45b485b0cff5600b80a4a3961a 100644
--- a/opentech/apply/funds/forms.py
+++ b/opentech/apply/funds/forms.py
@@ -22,6 +22,20 @@ class ProgressSubmissionForm(forms.ModelForm):
         self.should_show = bool(choices)
 
 
+class ScreeningSubmissionForm(forms.ModelForm):
+
+    class Meta:
+        model = ApplicationSubmission
+        fields = ('screening_status',)
+
+    def __init__(self, *args, **kwargs):
+        self.user = kwargs.pop('user')
+        super().__init__(*args, **kwargs)
+        self.should_show = False
+        if (self.instance.active and self.user.is_apply_staff) or self.user.is_superuser:
+            self.should_show = True
+
+
 class UpdateSubmissionLeadForm(forms.ModelForm):
     class Meta:
         model = ApplicationSubmission
diff --git a/opentech/apply/funds/migrations/0049_screening_status.py b/opentech/apply/funds/migrations/0049_screening_status.py
new file mode 100644
index 0000000000000000000000000000000000000000..ad1fb85306d9ac71a70cf6a79071ba401f60a1a3
--- /dev/null
+++ b/opentech/apply/funds/migrations/0049_screening_status.py
@@ -0,0 +1,29 @@
+# Generated by Django 2.0.10 on 2019-01-10 15:15
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('funds', '0048_add_field_slack_channel'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ScreeningStatus',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('title', models.CharField(max_length=128)),
+            ],
+            options={
+                'verbose_name_plural': 'screening statuses',
+            },
+        ),
+        migrations.AddField(
+            model_name='applicationsubmission',
+            name='screening_status',
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='funds.ScreeningStatus', verbose_name='screening status'),
+        ),
+    ]
diff --git a/opentech/apply/funds/migrations/0050_roundsandlabs.py b/opentech/apply/funds/migrations/0050_roundsandlabs.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1f65610caac3d58ea047bf60072ee920f5d98c0
--- /dev/null
+++ b/opentech/apply/funds/migrations/0050_roundsandlabs.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.0.9 on 2019-01-16 16:20
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('wagtailcore', '0040_page_draft_title'),
+        ('funds', '0049_screening_status'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='RoundsAndLabs',
+            fields=[
+            ],
+            options={
+                'proxy': True,
+                'indexes': [],
+            },
+            bases=('wagtailcore.page',),
+        ),
+    ]
diff --git a/opentech/apply/funds/models/__init__.py b/opentech/apply/funds/models/__init__.py
index 9cfc41a3b66c9995a9b7aca916bceec94f8b0928..101a4b48011e5d342fcf8164a75a073020d4de32 100644
--- a/opentech/apply/funds/models/__init__.py
+++ b/opentech/apply/funds/models/__init__.py
@@ -1,11 +1,12 @@
 from django.utils.translation import ugettext_lazy as _
 
-from .applications import ApplicationBase, RoundBase, LabBase
+from .applications import ApplicationBase, RoundBase, LabBase, RoundsAndLabs  # NOQA
 from .forms import ApplicationForm
+from .screening import ScreeningStatus
 from .submissions import ApplicationSubmission, ApplicationRevision
 
 
-__all__ = ['ApplicationSubmission', 'ApplicationRevision', 'ApplicationForm']
+__all__ = ['ApplicationSubmission', 'ApplicationRevision', 'ApplicationForm', 'ScreeningStatus']
 
 
 class FundType(ApplicationBase):
diff --git a/opentech/apply/funds/models/applications.py b/opentech/apply/funds/models/applications.py
index 0119e8c6503b93503336affddad338f2fd37ba3c..30097f1d3833a2c6f29beef9d29353bddf1c3c80 100644
--- a/opentech/apply/funds/models/applications.py
+++ b/opentech/apply/funds/models/applications.py
@@ -3,7 +3,21 @@ from datetime import date
 from django.conf import settings
 from django.core.exceptions import ValidationError
 from django.db import models
-from django.db.models import OuterRef, Q, Subquery
+from django.db.models import (
+    Case,
+    CharField,
+    Count,
+    F,
+    FloatField,
+    Func,
+    IntegerField,
+    OuterRef,
+    Q,
+    Subquery,
+    When,
+)
+from django.db.models.functions import Coalesce, Length
+
 from django.http import Http404
 from django.utils.functional import cached_property
 from django.utils.text import mark_safe
@@ -18,7 +32,7 @@ from wagtail.admin.edit_handlers import (
     ObjectList,
     TabbedInterface,
 )
-from wagtail.core.models import PageManager, PageQuerySet
+from wagtail.core.models import Page, PageManager, PageQuerySet
 
 from ..admin_forms import WorkflowFormAdminForm
 from ..edit_handlers import ReadOnlyPanel, ReadOnlyInlinePanel
@@ -104,6 +118,11 @@ class RoundBaseManager(PageQuerySet):
         )
         return rounds
 
+    def closed(self):
+        rounds = self.live().public().specific()
+        rounds = rounds.filter(end_date__lt=date.today())
+        return rounds
+
 
 class RoundBase(WorkflowStreamForm, SubmittableStreamForm):  # type: ignore
     is_creatable = False
@@ -314,3 +333,125 @@ class LabBase(EmailForm, WorkflowStreamForm, SubmittableStreamForm):  # type: ig
 
     def open_round(self):
         return self.live
+
+
+class RoundsAndLabsQueryset(PageQuerySet):
+    def new(self):
+        return self.filter(start_date__gt=date.today())
+
+    def open(self):
+        return self.filter(Q(end_date__gte=date.today(), start_date__lte=date.today()) | Q(end_date__isnull=True))
+
+    def closed(self):
+        return self.filter(end_date__lt=date.today())
+
+
+class RoundsAndLabsProgressQueryset(RoundsAndLabsQueryset):
+    def active(self):
+        return self.filter(progress__lt=100)
+
+    def inactive(self):
+        return self.filter(progress=100)
+
+
+class RoundsAndLabsManager(PageManager):
+    def get_queryset(self, base_queryset=RoundsAndLabsQueryset):
+        funds = ApplicationBase.objects.filter(path=OuterRef('parent_path'))
+
+        return base_queryset(self.model, using=self._db).type(SubmittableStreamForm).annotate(
+            lead=Coalesce(
+                F('roundbase__lead__full_name'),
+                F('labbase__lead__full_name'),
+            ),
+            start_date=F('roundbase__start_date'),
+            end_date=F('roundbase__end_date'),
+            parent_path=Left(F('path'), Length('path') - ApplicationBase.steplen, output_field=CharField()),
+            fund=Subquery(funds.values('title')[:1]),
+        )
+
+    def with_progress(self):
+        submissions = ApplicationSubmission.objects.filter(Q(round=OuterRef('pk')) | Q(page=OuterRef('pk'))).current()
+        closed_submissions = submissions.inactive()
+
+        return self.get_queryset(RoundsAndLabsProgressQueryset).annotate(
+            total_submissions=Coalesce(
+                Subquery(
+                    submissions.values('round').annotate(count=Count('pk')).values('count'),
+                    output_field=IntegerField(),
+                ),
+                0,
+            ),
+            closed_submissions=Coalesce(
+                Subquery(
+                    closed_submissions.values('round').annotate(count=Count('pk')).values('count'),
+                    output_field=IntegerField(),
+                ),
+                0,
+            ),
+        ).annotate(
+            progress=Case(
+                When(total_submissions=0, then=None),
+                default=(F('closed_submissions') * 100) / F('total_submissions'),
+                output_fields=FloatField(),
+            )
+
+        )
+
+    def open(self):
+        return self.get_queryset().open()
+
+    def closed(self):
+        return self.get_queryset().closed()
+
+    def new(self):
+        return self.get_queryset().new()
+
+
+class RoundsAndLabs(Page):
+    """
+    This behaves as a useful way to get all the rounds and labs that are defined
+    in the project regardless of how they are implemented (lab/round/sealed_round)
+    """
+    class Meta:
+        proxy = True
+
+    def __eq__(self, other):
+        # This is one way equality RoundAndLab == Round/Lab
+        # Round/Lab == RoundAndLab returns False due to different
+        # Concrete class
+        if not isinstance(other, models.Model):
+            return False
+        if not isinstance(other, SubmittableStreamForm):
+            return False
+        my_pk = self.pk
+        if my_pk is None:
+            return self is other
+        return my_pk == other.pk
+
+    objects = RoundsAndLabsManager()
+
+    def save(self, *args, **kwargs):
+        raise NotImplementedError('Do not save through this model')
+
+
+# TODO remove in django 2.1 where this is fixed
+F.relabeled_clone = lambda self, relabels: self
+
+
+# TODO remove in django 2.1 where this is added
+class Left(Func):
+    function = 'LEFT'
+    arity = 2
+
+    def __init__(self, expression, length, **extra):
+        """
+        expression: the name of a field, or an expression returning a string
+        length: the number of characters to return from the start of the string
+        """
+        if not hasattr(length, 'resolve_expression'):
+            if length < 1:
+                raise ValueError("'length' must be greater than 0.")
+        super().__init__(expression, length, **extra)
+
+    def get_substr(self):
+        return Substr(self.source_expressions[0], Value(1), self.source_expressions[1])
diff --git a/opentech/apply/funds/models/mixins.py b/opentech/apply/funds/models/mixins.py
index 87a1dd39ea31e63666f76fac46e9071fa3dd6d88..31a5b899affdd6817f197a886a099939f855dd7a 100644
--- a/opentech/apply/funds/models/mixins.py
+++ b/opentech/apply/funds/models/mixins.py
@@ -137,6 +137,22 @@ class AccessFormData:
             if isinstance(field.block, SingleIncludeMixin)
         }
 
+    @property
+    def normal_blocks(self):
+        return [
+            field_id
+            for field_id in self.question_field_ids
+            if field_id not in self.named_blocks
+        ]
+
+    def serialize(self, field_id):
+        field = self.field(field_id)
+        data = self.data(field_id)
+        return field.render(context={
+            'serialize': True,
+            'data': data,
+        })
+
     def render_answer(self, field_id, include_question=False):
         try:
             field = self.field(field_id)
@@ -149,8 +165,7 @@ class AccessFormData:
         # Returns a list of the rendered answers
         return [
             self.render_answer(field_id, include_question=True)
-            for field_id in self.question_field_ids
-            if field_id not in self.named_blocks
+            for field_id in self.normal_blocks
         ]
 
     def output_answers(self):
diff --git a/opentech/apply/funds/models/screening.py b/opentech/apply/funds/models/screening.py
new file mode 100644
index 0000000000000000000000000000000000000000..c590704b145651314664e60798c8a61ff563dc46
--- /dev/null
+++ b/opentech/apply/funds/models/screening.py
@@ -0,0 +1,11 @@
+from django.db import models
+
+
+class ScreeningStatus(models.Model):
+    title = models.CharField(max_length=128)
+
+    class Meta:
+        verbose_name_plural = "screening statuses"
+
+    def __str__(self):
+        return self.title
diff --git a/opentech/apply/funds/models/submissions.py b/opentech/apply/funds/models/submissions.py
index 3e5237407d5813713e2c34b6343ae84cede99b9c..0adeb684360ff6ddfa38b4406b7b2d01e752ea1f 100644
--- a/opentech/apply/funds/models/submissions.py
+++ b/opentech/apply/funds/models/submissions.py
@@ -61,7 +61,8 @@ class JSONOrderable(models.QuerySet):
                 field = field[1:]
             else:
                 descending = False
-            return OrderBy(RawSQL(f'LOWER({self.json_field}->>%s)', (field,)), descending=descending, nulls_last=True)
+            db_table = self.model._meta.db_table
+            return OrderBy(RawSQL(f'LOWER({db_table}.{self.json_field}->>%s)', (field,)), descending=descending, nulls_last=True)
 
         field_ordering = [build_json_order_by(field) for field in field_names]
         return super().order_by(*field_ordering)
@@ -309,6 +310,14 @@ class ApplicationSubmission(
     # Workflow inherited from WorkflowHelpers
     status = FSMField(default=INITIAL_STATE, protected=True)
 
+    screening_status = models.ForeignKey(
+        'funds.ScreeningStatus',
+        related_name='+',
+        on_delete=models.SET_NULL,
+        verbose_name='screening status',
+        null=True,
+    )
+
     is_draft = False
 
     live_revision = models.OneToOneField(
@@ -640,6 +649,9 @@ class ApplicationRevision(AccessFormData, models.Model):
     class Meta:
         ordering = ['-timestamp']
 
+    def __str__(self):
+        return f'Revision for {self.submission.title} by {self.author} '
+
     @property
     def form_fields(self):
         return self.submission.form_fields
diff --git a/opentech/apply/funds/permissions.py b/opentech/apply/funds/permissions.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec6f22f83b78b3476cf267333a68149c7c32e0df
--- /dev/null
+++ b/opentech/apply/funds/permissions.py
@@ -0,0 +1,13 @@
+from rest_framework import permissions
+
+
+class IsApplyStaffUser(permissions.BasePermission):
+    """
+    Custom permission to only allow OTF Staff or higher
+    """
+
+    def has_permission(self, request, view):
+        return request.user.is_apply_staff
+
+    def has_object_permission(self, request, view, obj):
+        return request.user.is_apply_staff
diff --git a/opentech/apply/funds/serializers.py b/opentech/apply/funds/serializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..3203a7ecca0cefc53594d594c9b39964655dbf3e
--- /dev/null
+++ b/opentech/apply/funds/serializers.py
@@ -0,0 +1,47 @@
+from rest_framework import serializers
+
+from .models import ApplicationSubmission
+
+
+class SubmissionListSerializer(serializers.ModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='funds:submissions-api:detail')
+
+    class Meta:
+        model = ApplicationSubmission
+        fields = ('id', 'title', 'status', 'url')
+
+
+class SubmissionDetailSerializer(serializers.ModelSerializer):
+    questions = serializers.SerializerMethodField()
+    meta_questions = serializers.SerializerMethodField()
+    stage = serializers.CharField(source='stage.name')
+
+    class Meta:
+        model = ApplicationSubmission
+        fields = ('id', 'title', 'stage', 'meta_questions', 'questions')
+
+    def serialize_questions(self, obj, fields):
+        for field_id in fields:
+            yield obj.serialize(field_id)
+
+    def get_meta_questions(self, obj):
+        meta_questions = {
+            'title': 'Project Name',
+            'full_name': 'Legal Name',
+            'email': 'Email',
+            'value': 'Requested Funding',
+            'duration': 'Project Duration',
+            'address': 'Address'
+        }
+        data = self.serialize_questions(obj, obj.named_blocks.values())
+        data = [
+            {
+                **response,
+                'question': meta_questions.get(response['type'], response['question'])
+            }
+            for response in data
+        ]
+        return data
+
+    def get_questions(self, obj):
+        return self.serialize_questions(obj, obj.normal_blocks)
diff --git a/opentech/apply/funds/tables.py b/opentech/apply/funds/tables.py
index b9d5626c11bfcfcb34d7da0b083ea5d3c48b231d..4456510530e47f6676caf9973e04d0eed9e8d320 100644
--- a/opentech/apply/funds/tables.py
+++ b/opentech/apply/funds/tables.py
@@ -5,6 +5,7 @@ from django.contrib.auth import get_user_model
 from django.db.models import F, Q
 from django.utils.html import format_html
 from django.utils.text import mark_safe, slugify
+from django.utils.translation import ugettext_lazy as _
 
 import django_filters as filters
 import django_tables2 as tables
@@ -12,14 +13,14 @@ from django_tables2.utils import A
 
 from wagtail.core.models import Page
 
-from opentech.apply.funds.models import ApplicationSubmission, Round
+from opentech.apply.funds.models import ApplicationSubmission, Round, ScreeningStatus
 from opentech.apply.funds.workflow import STATUSES
 from opentech.apply.users.groups import STAFF_GROUP_NAME
 from .widgets import Select2MultiCheckboxesWidget
 
 
 def make_row_class(record):
-    css_class = 'submission-meta__row' if record.next else 'all-submissions__parent'
+    css_class = 'submission-meta__row' if record.next else 'all-submissions-table__parent'
     css_class += '' if record.active else ' is-inactive'
     return css_class
 
@@ -34,21 +35,22 @@ class SubmissionsTable(tables.Table):
     submit_time = tables.DateColumn(verbose_name="Submitted")
     phase = tables.Column(verbose_name="Status", order_by=('status',))
     stage = tables.Column(verbose_name="Type", order_by=('status',))
-    page = tables.Column(verbose_name="Fund")
+    fund = tables.Column(verbose_name="Fund", accessor='page')
     comments = tables.Column(accessor='comment_count', verbose_name="Comments")
     last_update = tables.DateColumn(accessor="last_update", verbose_name="Last updated")
 
     class Meta:
         model = ApplicationSubmission
         order_by = ('-last_update',)
-        fields = ('title', 'phase', 'stage', 'page', 'round', 'submit_time', 'last_update')
+        fields = ('title', 'phase', 'stage', 'fund', 'round', 'submit_time', 'last_update')
         sequence = fields + ('comments',)
         template_name = 'funds/tables/table.html'
         row_attrs = {
             'class': make_row_class,
             'data-record-id': lambda record: record.id,
         }
-        attrs = {'class': 'all-submissions'}
+        attrs = {'class': 'all-submissions-table'}
+        empty_text = _('No submissions available')
 
     def render_user(self, value):
         return value.get_full_name()
@@ -67,15 +69,21 @@ class AdminSubmissionsTable(SubmissionsTable):
     """Adds admin only columns to the submissions table"""
     lead = tables.Column(order_by=('lead.full_name',))
     reviews_stats = tables.TemplateColumn(template_name='funds/tables/column_reviews.html', verbose_name=mark_safe("Reviews\n<span>Assgn.\tComp.</span>"), orderable=False)
+    screening_status = tables.Column(verbose_name="Screening")
 
     class Meta(SubmissionsTable.Meta):
-        fields = ('title', 'phase', 'stage', 'page', 'round', 'lead', 'submit_time', 'last_update', 'reviews_stats')  # type: ignore
+        fields = ('title', 'phase', 'stage', 'fund', 'round', 'lead', 'submit_time', 'last_update', 'screening_status', 'reviews_stats')  # type: ignore
         sequence = fields + ('comments',)
 
     def render_lead(self, value):
         return format_html('<span>{}</span>', value)
 
 
+class SummarySubmissionsTable(AdminSubmissionsTable):
+    class Meta(AdminSubmissionsTable.Meta):
+        orderable = False
+
+
 def get_used_rounds(request):
     return Round.objects.filter(submissions__isnull=False).distinct()
 
@@ -96,6 +104,11 @@ def get_reviewers(request):
     return User.objects.filter(Q(submissions_reviewer__isnull=False) | Q(groups__name=STAFF_GROUP_NAME) | Q(is_superuser=True)).distinct()
 
 
+def get_screening_statuses(request):
+    return ScreeningStatus.objects.filter(
+        id__in=ApplicationSubmission.objects.all().values('screening_status__id').distinct('screening_status__id'))
+
+
 class Select2CheckboxWidgetMixin(filters.Filter):
     def __init__(self, *args, **kwargs):
         label = kwargs.get('label')
@@ -129,15 +142,98 @@ class StatusMultipleChoiceFilter(Select2MultipleChoiceFilter):
 
 class SubmissionFilter(filters.FilterSet):
     round = Select2ModelMultipleChoiceFilter(queryset=get_used_rounds, label='Rounds')
-    funds = Select2ModelMultipleChoiceFilter(name='page', queryset=get_used_funds, label='Funds')
+    fund = Select2ModelMultipleChoiceFilter(name='page', queryset=get_used_funds, label='Funds')
     status = StatusMultipleChoiceFilter()
     lead = Select2ModelMultipleChoiceFilter(queryset=get_round_leads, label='Leads')
     reviewers = Select2ModelMultipleChoiceFilter(queryset=get_reviewers, label='Reviewers')
+    screening_status = Select2ModelMultipleChoiceFilter(queryset=get_screening_statuses, label='Screening')
 
     class Meta:
         model = ApplicationSubmission
-        fields = ('funds', 'round', 'status')
+        fields = ('fund', 'round', 'status')
+
+    def __init__(self, *args, exclude=list(), **kwargs):
+        super().__init__(*args, **kwargs)
+
+        self.filters = {
+            field: filter
+            for field, filter in self.filters.items()
+            if field not in exclude
+        }
 
 
 class SubmissionFilterAndSearch(SubmissionFilter):
     query = filters.CharFilter(field_name='search_data', lookup_expr="icontains", widget=forms.HiddenInput)
+
+
+class RoundsTable(tables.Table):
+    title = tables.LinkColumn('funds:rounds:detail', args=[A('pk')], orderable=True, text=lambda record: record.title)
+    fund = tables.Column(accessor=A('specific.fund'))
+    lead = tables.Column()
+    start_date = tables.Column()
+    end_date = tables.Column()
+    progress = tables.Column(verbose_name="Determined")
+
+    class Meta:
+        fields = ('title', 'fund', 'lead', 'start_date', 'end_date', 'progress')
+        attrs = {'class': 'all-rounds-table'}
+
+    def render_lead(self, value):
+        return format_html('<span>{}</span>', value)
+
+    def render_progress(self, record):
+        return f'{record.progress}%'
+
+    def _field_order(self, field, desc):
+        return getattr(F(f'{field}'), 'desc' if desc else 'asc')(nulls_last=True)
+
+    def order_start_date(self, qs, desc):
+        return qs.order_by(self._field_order('start_date', desc)), True
+
+    def order_end_date(self, qs, desc):
+        return qs.order_by(self._field_order('end_date', desc)), True
+
+    def order_fund(self, qs, desc):
+        return qs.order_by(self._field_order('fund', desc)), True
+
+    def order_progress(self, qs, desc):
+        return qs.order_by(self._field_order('progress', desc)), True
+
+
+class ActiveRoundFilter(Select2MultipleChoiceFilter):
+    def __init__(self, *args, **kwargs):
+        super().__init__(self, *args, choices=[('active', 'Active'), ('inactive', 'Inactive')], **kwargs)
+
+    def filter(self, qs, value):
+        if value is None or len(value) != 1:
+            return qs
+
+        value = value[0]
+        if value == 'active':
+            return qs.active()
+        else:
+            return qs.inactive()
+
+
+class OpenRoundFilter(Select2MultipleChoiceFilter):
+    def __init__(self, *args, **kwargs):
+        super().__init__(self, *args, choices=[('open', 'Open'), ('closed', 'Closed'), ('new', 'Not Started')], **kwargs)
+
+    def filter(self, qs, value):
+        if value is None or len(value) != 1:
+            return qs
+
+        value = value[0]
+        if value == 'closed':
+            return qs.closed()
+        if value == 'new':
+            return qs.new()
+
+        return qs.open()
+
+
+class RoundsFilter(filters.FilterSet):
+    fund = Select2ModelMultipleChoiceFilter(queryset=get_used_funds, label='Funds')
+    lead = Select2ModelMultipleChoiceFilter(queryset=get_round_leads, label='Leads')
+    active = ActiveRoundFilter(label='Active')
+    round_state = OpenRoundFilter(label='Open')
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
index e0a41610a6575d80050c321abbd4416b41a59bb6..d39cf28ada9ae8697491c16f859ae05c0674b285 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
@@ -12,6 +12,7 @@
 
 {% block sidebar_forms %}
         {% include "funds/includes/actions.html" %}
+        {% include "funds/includes/screening_form.html" %}
         {% include "funds/includes/progress_form.html" %}
         {% include "funds/includes/update_lead_form.html" %}
         {% include "funds/includes/update_reviewer_form.html" %}
@@ -32,6 +33,10 @@
     </div>
 {% endblock %}
 
+{% block screening_status %}
+    {% include 'funds/includes/screening_status_block.html' %}
+{% endblock %}
+
 {% block determination %}
     {% include 'determinations/includes/determination_block.html' with submission=object %}
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
index cb2a5197abb9eb45947716b98d599828db483004..c0b2799b270626282dc4d8f387e5a12f8f37f4d0 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -1,5 +1,5 @@
 {% extends "base-apply.html" %}
-{% load static workflow_tags wagtailcore_tags %}
+{% load static workflow_tags wagtailcore_tags statusbar_tags %}
 {% block title %}{{ object.title }}{% endblock %}
 {% block body_class %}{% endblock %}
 {% block content %}
@@ -17,7 +17,7 @@
             <span>{{ object.round }}</span>
             <span>Lead: {{ object.lead }}</span>
         </h5>
-        {% include "funds/includes/status_bar.html" with phases=object.workflow current_phase=object.phase same_stage=True%}
+        {% status_bar object.workflow object.phase request.user same_stage=True%}
 
         <div class="tabs js-tabs">
             <div class="tabs__container">
@@ -42,7 +42,7 @@
     </div>
 </div>
 
-<div class="wrapper wrapper--large wrapper--tabs">
+<div class="wrapper wrapper--large wrapper--tabs js-tabs-content">
 {# Tab 1 #}
     <div class="tabs__content" id="tab-1">
         {% block admin_actions %}
@@ -86,6 +86,11 @@
                     {% include 'determinations/includes/applicant_determination_block.html' with submission=object %}
                 {% endblock %}
 
+                {% if request.user.is_apply_staff %}
+                    {% block screening_status %}
+                    {% endblock %}
+                {% endif %}
+
                 {% block reviews %}
                 {% endblock %}
 
@@ -138,4 +143,3 @@
     <script src="{% static 'js/apply/tabs.js' %}"></script>
     <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
 {% endblock %}
-
diff --git a/opentech/apply/funds/templates/funds/base_submissions_table.html b/opentech/apply/funds/templates/funds/base_submissions_table.html
new file mode 100644
index 0000000000000000000000000000000000000000..d9214f80da196c86ca5211367455a9e292fd1bac
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/base_submissions_table.html
@@ -0,0 +1,25 @@
+{% extends "base-apply.html" %}
+{% load static %}
+{% load render_table from django_tables2 %}
+
+{% block extra_css %}
+{{ filter.form.media.css }}
+{% endblock %}
+
+{% block content %}
+    {% block table %}
+        {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action %}
+
+        {% render_table table %}
+    {% endblock %}
+{% endblock %}
+
+{% block extra_js %}
+    {{ filter.form.media.js }}
+    <script src="{% static 'js/apply/all-submissions-table.js' %}"></script>
+    <script src="https://cdn.jsdelivr.net/npm/symbol-es6@0.1.2/symbol-es6.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/url-search-params/1.1.0/url-search-params.js"></script>
+    <script src="{% static 'js/apply/submission-filters.js' %}"></script>
+    <script src="{% static 'js/apply/submission-tooltips.js' %}"></script>
+    <script src="{% static 'js/apply/tabs.js' %}"></script>
+{% endblock %}
diff --git a/opentech/apply/funds/templates/funds/includes/actions.html b/opentech/apply/funds/templates/funds/includes/actions.html
index b66583a84a0bb7c13435a6d61033d60c8ddc17ef..63e1ac00bf41195d1d0fcbee753b3310ed722e09 100644
--- a/opentech/apply/funds/templates/funds/includes/actions.html
+++ b/opentech/apply/funds/templates/funds/includes/actions.html
@@ -4,7 +4,12 @@
 
 <div class="js-actions-sidebar sidebar__inner sidebar__inner--light-blue sidebar__inner--actions {% if mobile %}sidebar__inner--mobile{% endif %}">
     <h5>Actions to take</h5>
+
+    <a data-fancybox data-src="#screen-application" class="button button--bottom-space button--primary button--full-width {% if screening_form.should_show %}is-not-disabled{% else %}is-disabled{% endif %}" href="#">Screen application</a>
+
     <a data-fancybox data-src="#update-status" class="button button--primary button--full-width {% if progress_form.should_show %}is-not-disabled{% else %}is-disabled{% endif %}" href="#">Update status</a>
+
+
     <p class="sidebar__separator">Assign</p>
 
     <div class="wrapper wrapper--sidebar-buttons">
diff --git a/opentech/apply/funds/templates/funds/includes/activity-feed.html b/opentech/apply/funds/templates/funds/includes/activity-feed.html
index e51c07d70dd324dea8ce5539f33b116a9ff08e9a..0a3595a6d1765fd7ab028c1bc83200a646f45054 100644
--- a/opentech/apply/funds/templates/funds/includes/activity-feed.html
+++ b/opentech/apply/funds/templates/funds/includes/activity-feed.html
@@ -13,7 +13,7 @@
         </div>
     </div>
 
-    <div class="wrapper wrapper--medium wrapper--activity-feed">
+    <div class="wrapper wrapper--medium wrapper--activity-feed js-tabs-content">
         <div class="tabs__content tabs__content--current" id="tab-1">
             {% include "activity/include/comment_list.html" with submission_title=True %}
         </div>
diff --git a/opentech/apply/funds/templates/funds/includes/round-block-listing.html b/opentech/apply/funds/templates/funds/includes/round-block-listing.html
new file mode 100644
index 0000000000000000000000000000000000000000..0c4fc9625b50ffbb9da14c63b2e28656d4c484fb
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/includes/round-block-listing.html
@@ -0,0 +1,33 @@
+<ul class="round-block">
+    {% for round in rounds %}
+        {% if forloop.counter0 < 5 %}
+            <li class="round-block__item">
+                <h5 class="round-block__title">{{ round }}</h5>
+                <p> {{ round.fund|default_if_none:"-" }} </p>
+                <p class="round-block__date">
+                    {% if round.end_date %}
+                        {{ display_text }} {{ round.end_date|date:"Y-m-d" }}
+                    {% else %}
+                        Open
+                    {% endif %}
+                    </p>
+                    <p class="round-block__determination">
+                        {% if round.progress is None%}
+                            -
+                        {% else %}
+                            {{ round.progress }}% Determined
+                        {% endif %}
+                    </p>
+                <a class="round-block__view" href="{% url 'apply:rounds:detail' pk=round.pk %}">View</a>
+            </li>
+        {% else %}
+            <li class="round-block__item round-block__item--more">
+                <a href="{% url 'apply:rounds:list' %}{{ query }}">Show all</a>
+            </li>
+        {% endif %}
+    {% empty %}
+        <p class="round-block__not-found">
+            There are no {% if round.end_date %} {{ display_text|lower }} {% else %} open {% endif %} rounds
+        </p>
+    {% endfor %}
+</ul>
diff --git a/opentech/apply/funds/templates/funds/includes/round-block.html b/opentech/apply/funds/templates/funds/includes/round-block.html
new file mode 100644
index 0000000000000000000000000000000000000000..8fdca206107d2438cef6a3115d49dfe101260797
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/includes/round-block.html
@@ -0,0 +1,22 @@
+<div class="wrapper wrapper--bottom-space">
+    <section class="section section--with-options">
+        <h4 class="heading heading--normal heading--no-margin">All Rounds and Labs</h4>
+        <div class="js-tabs">
+            <a class="tab__item tab__item--alt" href="#closed-rounds" data-tab="tab-1">Closed</a>
+            <a class="tab__item tab__item--alt" href="#open-rounds" data-tab="tab-2">Open</a>
+        </div>
+    </section>
+
+    {# Closed rounds/labs tab #}
+    <div class="js-tabs-content">
+        <div class="tabs__content" id="tab-1">
+            {% include "funds/includes/round-block-listing.html" with rounds=closed_rounds display_text="Closed" query=closed_query %}
+        </div>
+
+        {# Open rounds/labs tab #}
+        <div class="tabs__content" id="tab-2">
+            {% include "funds/includes/round-block-listing.html" with rounds=open_rounds display_text="Open until" query=open_query %}
+        </div>
+    </div>
+
+</div>
diff --git a/opentech/apply/funds/templates/funds/includes/screening_form.html b/opentech/apply/funds/templates/funds/includes/screening_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..87b3f9cd4a6cfdb2341f270704c9d793e1c7bec5
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/includes/screening_form.html
@@ -0,0 +1,7 @@
+{% if screening_form.should_show %}
+<div class="modal" id="screen-application">
+    <h4>Update status</h4>
+    <p>Current status: {{ object.screening_status }}</p>
+    {% include 'funds/includes/delegated_form_base.html' with form=screening_form value='Screen'%}
+</div>
+{% endif %}
diff --git a/opentech/apply/funds/templates/funds/includes/screening_status_block.html b/opentech/apply/funds/templates/funds/includes/screening_status_block.html
new file mode 100644
index 0000000000000000000000000000000000000000..c278709042f9a5f194de16f7dfc536606e92d497
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/includes/screening_status_block.html
@@ -0,0 +1,6 @@
+<div class="sidebar__inner">
+    <h5>Screening Status</h5>
+        <p>
+            {{ object.screening_status|default:"Awaiting Screen status" }}
+        </p>
+</div>
\ No newline at end of file
diff --git a/opentech/apply/funds/templates/funds/includes/search.html b/opentech/apply/funds/templates/funds/includes/search.html
deleted file mode 100644
index 5e3afc9d9c48017d2c59cf5baa5acc832010b672..0000000000000000000000000000000000000000
--- a/opentech/apply/funds/templates/funds/includes/search.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<form action="{% url 'funds:search' %}" method="get" role="search" class="form form--header-search-desktop">
-    <button class="button button--search" type="submit" aria-label="Search">
-        <svg class="icon icon--magnifying-glass icon--search"><use xlink:href="#magnifying-glass"></use></svg>
-    </button>
-    <input class="input input--search" type="text" placeholder="Search submissions" name="query"{% if search_query %} value="{{ search_query }}{% endif %}" aria-label="Search input">
-</form>
diff --git a/opentech/apply/funds/templates/funds/includes/status_bar.html b/opentech/apply/funds/templates/funds/includes/status_bar.html
index bc4fce3f3e4b0bcae5b618911e39ea7010cf7b24..eb5235a2ec9213c99817cb3f12941e53e70e6e78 100644
--- a/opentech/apply/funds/templates/funds/includes/status_bar.html
+++ b/opentech/apply/funds/templates/funds/includes/status_bar.html
@@ -1,26 +1,28 @@
+{% load statusbar_tags %}
 <div class="status-bar {{ class }}">
-    {% for phase_name, phase in phases.items %}
-        {% if not same_stage or current_phase.stage == phase.stage %}
-            {% ifchanged phase.step %}
-                <div class="status-bar__item
-                            {% if phase.step == current_phase.step %}
-                                status-bar__item--is-current
-                            {% elif current_phase.step > phase.step %}
-                                status-bar__item--is-complete
-                            {% endif %}">
-                    <span class="status-bar__tooltip"
-                    {% if phase.step != current_phase.step %}
-                        data-title="{{ phase }}" aria-label="{{ phase }}"
-                    {% else %}
-                        data-title="{{ current_phase }}" aria-label="{{ current_phase }}"
-                    {% endif %}
-                    ></span>
-                    <svg class="status-bar__icon"><use xlink:href="#tick-alt"></use></svg>
-                </div>
-                {% endifchanged %}
-        {% endif %}
+    {% for phase in phases %}
+        {% ifchanged phase.step %}
+            <div class="status-bar__item
+                        {% if phase.step == current_phase.step %}
+                            status-bar__item--is-current
+                        {% elif current_phase.step > phase.step %}
+                            status-bar__item--is-complete
+                        {% endif %}">
+                <span class="status-bar__tooltip"
+                    {% status_display current_phase phase public as display_text %}
+                    data-title="{{ display_text }}" aria-label="{{ display_text }}"
+                ></span>
+                <svg class="status-bar__icon"><use xlink:href="#tick-alt"></use></svg>
+            </div>
+        {% endifchanged %}
     {% endfor %}
 </div>
 <div class="status-bar--mobile">
-    <h6 class="status-bar__subheading">{{ current_phase }}</h6>
+    <h6 class="status-bar__subheading">
+        {% if public %}
+            {{ current_phase.public_name }}
+        {% else %}
+            {{ current_phase }}
+        {% endif %}
+    </h6>
 </div>
diff --git a/opentech/apply/funds/templates/funds/includes/table_filter_and_search.html b/opentech/apply/funds/templates/funds/includes/table_filter_and_search.html
new file mode 100644
index 0000000000000000000000000000000000000000..e4cff0f2d2f2147b94009bcebc63f27aefbe9f7f
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/includes/table_filter_and_search.html
@@ -0,0 +1,29 @@
+<div class="wrapper wrapper--table-actions">
+    <button class="button button--filters button--contains-icons js-toggle-filters">Filters</button>
+
+    {% if use_search|default:False %}
+    <form method="get" role="search" class="form form--search js-search-form">
+        <button class="button button--search" type="submit" aria-label="Search">
+            <svg class="icon icon--magnifying-glass icon--search"><use xlink:href="#magnifying-glass"></use></svg>
+        </button>
+        <input class="input input--search input--secondary js-search-input" type="text" placeholder="Search submissions" name="query"{% if search_term %} value="{{ search_term }}"{% endif %} aria-label="Search input">
+    </form>
+    {% endif %}
+</div>
+
+<div class="filters">
+    <div class="filters__header">
+        <button class="filters__button js-clear-filters">Clear</button>
+        <div>Filter by</div>
+        <button class="filters__button js-close-filters">Close</button>
+    </div>
+
+    <form action="{{ filter_action }}" method="get" class="form form--filters js-filter-form">
+        <ul class="form__filters select2">
+            {{ filter.form.as_ul }}
+            <li>
+                <button class="button button--primary" type="submit" value="Filter">Filter</button>
+            </li>
+        </ul>
+    </form>
+</div>
diff --git a/opentech/apply/funds/templates/funds/rounds.html b/opentech/apply/funds/templates/funds/rounds.html
new file mode 100644
index 0000000000000000000000000000000000000000..3f030e2baf8155a2a9d8809578d55a44517ddc8f
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/rounds.html
@@ -0,0 +1,34 @@
+{% extends "base-apply.html" %}
+{% load static %}
+{% load render_table from django_tables2 %}
+
+{% block title %}Rounds{% endblock %}
+
+{% block extra_css %}
+{{ filter.form.media.css }}
+{% endblock %}
+
+
+{% block content %}
+<div class="admin-bar">
+    <div class="admin-bar__inner">
+        <div>
+            <h1 class="gamma heading heading--no-margin heading--bold">Rounds</h1>
+            <h5>Explore current and past rounds</h5>
+        </div>
+    </div>
+</div>
+
+<div class="wrapper wrapper--large wrapper--inner-space-medium">
+    {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term %}
+    {% render_table table %}
+</div>
+
+{% endblock %}
+
+{% block extra_js %}
+{{ filter.form.media.js }}
+<script src="https://cdnjs.cloudflare.com/ajax/libs/url-search-params/1.1.0/url-search-params.js"></script>
+<script src="{% static 'js/apply/submission-filters.js' %}"></script>
+<script src="{% static 'js/apply/submission-tooltips.js' %}"></script>
+{% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submission_sealed.html b/opentech/apply/funds/templates/funds/submission_sealed.html
index ffd8069eafd28583caab930593e2447ca2b98f4d..15976eb85070f40ec11f9d1a09f8100c41767216 100644
--- a/opentech/apply/funds/templates/funds/submission_sealed.html
+++ b/opentech/apply/funds/templates/funds/submission_sealed.html
@@ -18,7 +18,7 @@
 <div class="wrapper wrapper--medium">
     <h2 class="heading">This application is sealed until the round is closed</h2>
     <h3>The round ends on: {{ object.round.specific.end_date }}</h3>
-    <a class="button button--primary" href="{% url 'apply:submissions:list' %}">Go back</a>
+    <a class="button button--primary" href="{% url 'apply:submissions:overview' %}">Go back</a>
     {% if can_view_sealed %}
         <p>As an admin you are allowed to access the application. However, this action will be recorded.</p>
         <form method="post">
diff --git a/opentech/apply/funds/templates/funds/submissions.html b/opentech/apply/funds/templates/funds/submissions.html
index adf89194bf39019ee4c80427aeab312757190a06..353450fa78d785a9339a12023d7eb3f69c5f3736 100644
--- a/opentech/apply/funds/templates/funds/submissions.html
+++ b/opentech/apply/funds/templates/funds/submissions.html
@@ -1,64 +1,32 @@
-{% extends "base-apply.html" %}
-{% load render_table from django_tables2 %}
+{% extends "funds/base_submissions_table.html" %}
 {% load static %}
 {% block title %}Submissions{% endblock %}
 
-{% block extra_css %}
-    {{ filter.form.media.css }}
-{% endblock %}
-
 {% block content %}
 <div class="admin-bar">
     <div class="admin-bar__inner wrapper--search">
         {% block page_header %}
             <div>
-                <h1 class="gamma heading heading--no-margin heading--bold">Received Submissions</h1>
-                <h5>Track and explore recent submissions</h5>
+                <h1 class="gamma heading heading--no-margin heading--bold">All Submissions</h1>
             </div>
         {% endblock %}
-        {% include "funds/includes/search.html" %}
     </div>
 </div>
 
 <div class="wrapper wrapper--large wrapper--inner-space-medium">
-
-    {% if table.data or active_filters %}
-        <div class="button button--filters button--contains-icons js-open-filters">Filter By</div>
-
-        <div class="filters js-filter-wrapper">
-            <div class="filters__header">
-                <div class="js-clear-filters">Clear</div>
-                <div>Filter by</div>
-                <div class="js-close-filters">Close</div>
-            </div>
-
-            <form action="" method="get" class="form form--filters">
-                <ul class="form__filters select2 js-filter-list">
-                    {{ filter.form.as_ul }}
-                    <li>
-                        <button class="button button--primary" type="submit" value="Filter">Filter</button>
-                    </li>
-                </ul>
-            </form>
-        </div>
-    {% endif %}
-
-    {% render_table table %}
+    {% block table %}
+        {{ block.super }}
+    {% endblock %}
 </div>
 
 <a href="#" class="js-open-feed link link--open-feed">
     <h4 class="heading heading--no-margin heading--activity-feed">Activity Feed</h4>
 </a>
-
 {% include "funds/includes/activity-feed.html" %}
 
 {% endblock %}
 
 {% block extra_js %}
-    {{ filter.form.media.js }}
-    <script src="{% static 'js/apply/tabs.js' %}"></script>
-    <script src="{% static 'js/apply/all-submissions-table.js' %}"></script>
-    <script src="{% static 'js/apply/submission-filters.js' %}"></script>
-    <script src="{% static 'js/apply/submission-tooltips.js' %}"></script>
+    {{ block.super }}
     <script src="{% static 'js/apply/activity-feed.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submissions_by_round.html b/opentech/apply/funds/templates/funds/submissions_by_round.html
index 30324a16596f2200fd6a3c983fe4d8bbf9f845dd..2aee68595093c4fb1ecc7df571dbef701a500b53 100644
--- a/opentech/apply/funds/templates/funds/submissions_by_round.html
+++ b/opentech/apply/funds/templates/funds/submissions_by_round.html
@@ -1,25 +1,26 @@
-{% extends "base-apply.html" %}
+{% extends "funds/base_submissions_table.html" %}
 {% load render_bundle from webpack_loader %}
 
 {% block title %}{{ object }}{% endblock %}
 
 {% block content %}
-<div class="admin-bar">
-    <div class="admin-bar__inner">
-        <div>
-            <h5><a href="{% url "apply:submissions:list" %}">< Submissions</a></h5>
-            <h1 class="gamma heading heading--no-margin heading--bold">{{ object }}</h1>
-            <h5>{% if object.fund %}{{ object.fund }} | {% endif %}Lead: {{ object.lead }}</h5>
+    <div class="admin-bar">
+        <div class="admin-bar__inner admin-bar__inner--with-button">
+            <div>
+                <h1 class="gamma heading heading--no-margin heading--bold">{{ object }}</h1>
+                <p class="admin-bar__meta">{% if object.fund %}{{ object.fund }} <span>|</span> {% endif %}Lead: {{ object.lead }}</p>
+            </div>
+            <div id="submissions-by-round-app-react-switcher"></div>
         </div>
     </div>
-</div>
 
-<div class="wrapper wrapper--large">
-    <div id="react-app">
-        <h2>THERE WILL BE A TABLE HERE</h2>
+    <div id="submissions-by-round-react-app" data-round-id="{{ object.id }}">
+        <div class="wrapper wrapper--large wrapper--inner-space-medium">
+            {% block table %}
+                {{ block.super }}
+            {% endblock %}
+        </div>
     </div>
-</div>
-
 {% render_bundle 'main' %}
 
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submissions_overview.html b/opentech/apply/funds/templates/funds/submissions_overview.html
new file mode 100644
index 0000000000000000000000000000000000000000..3963db804992e273f05a4202a2846aede8554c0a
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/submissions_overview.html
@@ -0,0 +1,42 @@
+{% extends "funds/base_submissions_table.html" %}
+{% load static %}
+{% block title %}Submissions{% endblock %}
+
+{% block content %}
+<div class="admin-bar">
+    <div class="admin-bar__inner wrapper--search">
+        {% block page_header %}
+            <div>
+                <h1 class="gamma heading heading--no-margin heading--bold">Submissions</h1>
+                <h5>Track and explore recent submissions</h5>
+            </div>
+        {% endblock %}
+    </div>
+</div>
+
+<div class="wrapper wrapper--large wrapper--inner-space-medium">
+
+    {% if closed_rounds or open_rounds %}
+        {% include "funds/includes/round-block.html" with closed_rounds=closed_rounds open_rounds=open_rounds %}
+    {% endif %}
+
+    {% block table %}
+        <h4 class="heading heading--normal heading--no-margin">All Submissions</h4>
+        {{ block.super }}
+        <div class="all-submissions-table__more">
+            <a href="{% url 'apply:submissions:list' %}">Show all</a>
+        </div>
+    {% endblock %}
+</div>
+
+<a href="#" class="js-open-feed link link--open-feed">
+    <h4 class="heading heading--no-margin heading--activity-feed">Activity Feed</h4>
+</a>
+{% include "funds/includes/activity-feed.html" %}
+
+{% endblock %}
+
+{% block extra_js %}
+    {{ block.super }}
+    <script src="{% static 'js/apply/activity-feed.js' %}"></script>
+{% endblock %}
diff --git a/opentech/apply/funds/templates/funds/tables/table.html b/opentech/apply/funds/templates/funds/tables/table.html
index 9a7848ff770c3d0dd7df0cfb57a6be91f56c75d5..cb3095fc7f961f67e78ed0eadc73308fbf4e2f24 100644
--- a/opentech/apply/funds/templates/funds/tables/table.html
+++ b/opentech/apply/funds/templates/funds/tables/table.html
@@ -12,7 +12,7 @@
     </tr>
 
     {% with submission=row.record %}
-        <tr class="all-submissions__child" data-parent-id="{{ submission.id }}">
+        <tr class="all-submissions-table__child" data-parent-id="{{ submission.id }}">
             <td colspan="{{ table.columns|length }}">
                 <table class="submission-meta">
                     <tr class="submission-meta__row">
@@ -48,7 +48,7 @@
 
     {% if row.record.previous %}
         {# we have a linked application, re-render the header row #}
-        <tr class="all-submissions__child" data-parent-id="{{ row.record.id }}">
+        <tr class="all-submissions-table__child" data-parent-id="{{ row.record.id }}">
             <td colspan="{{ table.columns|length }}">
                 <table class="submission-meta">
                     <tr class="submission-meta__row">
@@ -71,3 +71,7 @@
     {% endif %}
 
 {% endblock %}
+
+{% block table.tbody.empty_text %}
+<tr class="all-submissions-table__empty"><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
+{% endblock table.tbody.empty_text %}
diff --git a/opentech/apply/funds/templatetags/statusbar_tags.py b/opentech/apply/funds/templatetags/statusbar_tags.py
new file mode 100644
index 0000000000000000000000000000000000000000..438adb2180ffe5c9c604c5f432f5e3e8a618779e
--- /dev/null
+++ b/opentech/apply/funds/templatetags/statusbar_tags.py
@@ -0,0 +1,56 @@
+from django import template
+
+register = template.Library()
+
+
+@register.inclusion_tag('funds/includes/status_bar.html')
+def status_bar(workflow, current_phase, user, css_class='', same_stage=False):
+
+    phases = workflow.phases_for(user)
+
+    if same_stage and not user.is_applicant:
+        phases = [
+            phase for phase in phases
+            if phase.stage == current_phase.stage
+        ]
+
+    if not current_phase.permissions.can_view(user):
+        current_phase = workflow.previous_visible(current_phase, user)
+
+    # Current step not shown for user, move current phase to last good location
+    elif not workflow.stepped_phases[current_phase.step][0].permissions.can_view(user):
+        new_phase_list = []
+        for phase in reversed(phases):
+            if phase.step <= current_phase.step and current_phase not in new_phase_list:
+                next_phase = current_phase
+            else:
+                next_phase = phase
+            new_phase_list = [next_phase, *new_phase_list]
+        phases = new_phase_list
+
+    return {
+        'phases': phases,
+        'current_phase': current_phase,
+        'class': css_class,
+        'public': user.is_applicant,
+    }
+
+
+@register.simple_tag()
+def status_display(current_phase, phase, public):
+    if phase.step == current_phase.step:
+        if public:
+            return current_phase.public_name
+        else:
+            return current_phase.display_name
+
+    if phase.step > current_phase.step:
+        if public:
+            return phase.future_name_public
+        else:
+            return phase.future_name_staff
+
+    if public:
+        return phase.public_name
+    else:
+        return phase.display_name
diff --git a/opentech/apply/funds/tests/factories/models.py b/opentech/apply/funds/tests/factories/models.py
index fc9722cc7ccae76c1a29ed81903a0c8240b59f5e..6cc1e8165379c40dc229242e941bcb90c123e21d 100644
--- a/opentech/apply/funds/tests/factories/models.py
+++ b/opentech/apply/funds/tests/factories/models.py
@@ -10,6 +10,7 @@ from opentech.apply.funds.models import (
     LabType,
     RequestForPartners,
     Round,
+    ScreeningStatus,
     SealedRound,
 )
 from opentech.apply.funds.models.forms import (
@@ -43,6 +44,7 @@ __all__ = [
     'LabBaseFormFactory',
     'LabSubmissionFactory',
     'RequestForPartnersFactory',
+    'ScreeningStatusFactory',
     'SealedRoundFactory',
     'SealedSubmissionFactory',
     'TodayRoundFactory',
@@ -134,6 +136,10 @@ class RoundFactory(wagtail_factories.PageFactory):
             start_date=factory.LazyFunction(datetime.date.today),
             end_date=factory.LazyFunction(lambda: datetime.date.today() + datetime.timedelta(days=7)),
         )
+        closed = factory.Trait(
+            start_date=factory.LazyFunction(lambda: datetime.date.today() - datetime.timedelta(days=7)),
+            end_date=factory.LazyFunction(lambda: datetime.date.today() - datetime.timedelta(days=1)),
+        )
 
     title = factory.Sequence('Round {}'.format)
     start_date = factory.Sequence(lambda n: datetime.date.today() + datetime.timedelta(days=7 * n + 1))
@@ -311,3 +317,10 @@ class LabBaseReviewFormFactory(AbstractReviewFormFactory):
         model = LabBaseReviewForm
 
     lab = factory.SubFactory(LabFactory)
+
+
+class ScreeningStatusFactory(factory.DjangoModelFactory):
+    class Meta:
+        model = ScreeningStatus
+
+    title = factory.Iterator(["Bad", "Good"])
diff --git a/opentech/apply/funds/tests/models/__init__.py b/opentech/apply/funds/tests/models/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/apply/funds/tests/models/test_roundsandlabs.py b/opentech/apply/funds/tests/models/test_roundsandlabs.py
new file mode 100644
index 0000000000000000000000000000000000000000..5eb8709d7b39e407a568deb51dd14ed9ff0ee27c
--- /dev/null
+++ b/opentech/apply/funds/tests/models/test_roundsandlabs.py
@@ -0,0 +1,138 @@
+from django.test import TestCase
+
+from opentech.apply.funds.models import RoundsAndLabs
+
+from opentech.apply.funds.tests.factories import (
+    ApplicationSubmissionFactory,
+    FundTypeFactory,
+    LabFactory,
+    LabSubmissionFactory,
+    RoundFactory,
+)
+
+
+class BaseRoundsAndLabTestCase:
+    def test_can_get(self):
+        obj = self.base_factory()
+        qs = RoundsAndLabs.objects.all()
+        self.assertEqual(qs.first(), obj)
+
+    def test_with_progress(self):
+        obj = self.base_factory()
+        self.submission_factory(**{self.relation_to_app: obj})
+        qs = RoundsAndLabs.objects.with_progress()
+        fetched_obj = qs.first()
+        self.assertEqual(fetched_obj.total_submissions, 1)
+        self.assertEqual(fetched_obj.closed_submissions, 0)
+        self.assertEqual(fetched_obj.progress, 0)
+
+    def test_with_determined(self):
+        obj = self.base_factory()
+        self.submission_factory(**{self.relation_to_app: obj}, rejected=True)
+        qs = RoundsAndLabs.objects.with_progress()
+        fetched_obj = qs.first()
+        self.assertEqual(fetched_obj.total_submissions, 1)
+        self.assertEqual(fetched_obj.closed_submissions, 1)
+        self.assertEqual(fetched_obj.progress, 100)
+
+    def test_annotated(self):
+        obj = self.base_factory()
+        qs = RoundsAndLabs.objects.with_progress()
+        fetched_obj = qs.first()
+        self.assertEqual(fetched_obj.lead, obj.lead.full_name)
+        self.assertEqual(fetched_obj.start_date, getattr(obj, 'start_date', None))
+        self.assertEqual(fetched_obj.end_date, getattr(obj, 'end_date', None))
+        self.assertEqual(fetched_obj.parent_path, obj.get_parent().path)
+        self.assertEqual(fetched_obj.fund, getattr(getattr(obj, 'fund', None), 'title', None))
+
+    def test_active(self):
+        obj = self.base_factory()
+        self.submission_factory(**{self.relation_to_app: obj})
+        base_qs = RoundsAndLabs.objects.with_progress()
+        fetched_obj = base_qs.active().first()
+        self.assertEqual(fetched_obj, obj)
+        self.assertFalse(base_qs.inactive().exists())
+
+    def test_no_submissions_not_either(self):
+        self.base_factory()
+        base_qs = RoundsAndLabs.objects.with_progress()
+        self.assertFalse(base_qs.inactive().exists())
+        self.assertFalse(base_qs.active().exists())
+
+    def test_inactive(self):
+        obj = self.base_factory()
+        self.submission_factory(**{self.relation_to_app: obj}, rejected=True)
+        base_qs = RoundsAndLabs.objects.with_progress()
+        fetched_obj = base_qs.inactive().first()
+        self.assertEqual(fetched_obj, obj)
+        self.assertFalse(base_qs.active().exists())
+
+
+class TestForLab(BaseRoundsAndLabTestCase, TestCase):
+    base_factory = LabFactory
+    submission_factory = LabSubmissionFactory
+    relation_to_app = 'page'
+
+    # Specific tests as labs and round have very different behaviour here
+    def test_new(self):
+        self.base_factory()
+        fetched_obj = RoundsAndLabs.objects.new().first()
+        self.assertIsNone(fetched_obj)
+
+    def test_closed(self):
+        self.base_factory()
+        fetched_obj = RoundsAndLabs.objects.closed().first()
+        self.assertIsNone(fetched_obj)
+
+    def test_open(self):
+        obj = self.base_factory()
+        fetched_obj = RoundsAndLabs.objects.open().first()
+        self.assertEqual(fetched_obj, obj)
+
+
+class TestForRound(BaseRoundsAndLabTestCase, TestCase):
+    base_factory = RoundFactory
+    submission_factory = ApplicationSubmissionFactory
+    relation_to_app = 'round'
+
+    # Specific tests as labs and round have very different behaviour here
+    def test_new(self):
+        round = self.base_factory()
+        fetched_obj = RoundsAndLabs.objects.new().first()
+        self.assertEqual(fetched_obj, round)
+
+    def test_closed(self):
+        round = self.base_factory(closed=True)
+        fetched_obj = RoundsAndLabs.objects.closed().first()
+        self.assertEqual(fetched_obj, round)
+
+    def test_open(self):
+        obj = self.base_factory(now=True)
+        fetched_obj = RoundsAndLabs.objects.open().first()
+        self.assertEqual(fetched_obj, obj)
+
+
+class TestRoundsAndLabsManager(TestCase):
+    def test_cant_get_fund(self):
+        FundTypeFactory()
+        qs = RoundsAndLabs.objects.all()
+        self.assertEqual(qs.count(), 0)
+
+    def test_doesnt_confuse_lab_and_round(self):
+        round = RoundFactory()
+        lab = LabFactory()
+
+        # Lab 50% progress
+        LabSubmissionFactory(page=lab)
+        LabSubmissionFactory(page=lab, rejected=True)
+
+        # Round 0% progress
+        ApplicationSubmissionFactory.create_batch(2, round=round)
+
+        fetched_lab = RoundsAndLabs.objects.with_progress().last()
+        fetched_round = RoundsAndLabs.objects.with_progress().first()
+
+        self.assertEqual([fetched_round, fetched_lab], [round, lab])
+
+        self.assertEqual(fetched_round.progress, 0)
+        self.assertEqual(fetched_lab.progress, 50)
diff --git a/opentech/apply/funds/tests/test_views.py b/opentech/apply/funds/tests/test_views.py
index 2b1cc1c3bb748f1be73dc47e1dda271fb2b0f6ed..6b8943cd74e0dd8fb7784adef43d447496efed78 100644
--- a/opentech/apply/funds/tests/test_views.py
+++ b/opentech/apply/funds/tests/test_views.py
@@ -1,15 +1,14 @@
 from datetime import datetime, timedelta
 import json
 
-from opentech.apply.activity.models import Activity
+from opentech.apply.activity.models import Activity, INTERNAL
 from opentech.apply.determinations.tests.factories import DeterminationFactory
 from opentech.apply.funds.tests.factories import (
     ApplicationSubmissionFactory,
     ApplicationRevisionFactory,
     InvitedToProposalFactory,
-    LabFactory,
     LabSubmissionFactory,
-    RoundFactory,
+    ScreeningStatusFactory,
     SealedRoundFactory,
     SealedSubmissionFactory,
 )
@@ -182,6 +181,25 @@ class TestStaffSubmissionView(BaseSubmissionViewTestCase):
         response = self.get_page(submission)
         self.assertNotContains(response, 'Value')
 
+    def test_can_screen_submission(self):
+        screening_outcome = ScreeningStatusFactory()
+        self.post_page(self.submission, {'form-submitted-screening_form': '', 'screening_status': screening_outcome.id})
+        submission = self.refresh(self.submission)
+        self.assertEqual(submission.screening_status, screening_outcome)
+
+    def test_cant_screen_submission(self):
+        """
+        Now that the submission has been rejected, we cannot screen it as staff
+        """
+        submission = ApplicationSubmissionFactory(rejected=True)
+        screening_outcome = ScreeningStatusFactory()
+        response = self.post_page(submission, {'form-submitted-screening_form': '', 'screening_status': screening_outcome.id})
+        self.assertEqual(response.context_data['screening_form'].should_show, False)
+
+    def test_can_view_submission_screening_block(self):
+        response = self.get_page(self.submission)
+        self.assertContains(response, 'Screening Status')
+
 
 class TestReviewersUpdateView(BaseSubmissionViewTestCase):
     user_factory = StaffFactory
@@ -361,6 +379,21 @@ class TestApplicantSubmissionView(BaseSubmissionViewTestCase):
         response = self.get_page(submission, 'edit')
         self.assertEqual(response.status_code, 403)
 
+    def test_cant_screen_submission(self):
+        """
+        Test that an applicant cannot set the screening status
+        and that they don't see the screening status form.
+        """
+        screening_outcome = ScreeningStatusFactory()
+        response = self.post_page(self.submission, {'form-submitted-screening_form': '', 'screening_status': screening_outcome.id})
+        self.assertNotIn('screening_form', response.context_data)
+        submission = self.refresh(self.submission)
+        self.assertNotEqual(submission.screening_status, screening_outcome)
+
+    def test_cant_see_screening_status_block(self):
+        response = self.get_page(self.submission)
+        self.assertNotContains(response, 'Screening Status')
+
 
 class TestRevisionsView(BaseSubmissionViewTestCase):
     user_factory = UserFactory
@@ -551,49 +584,35 @@ class TestSuperUserSealedView(BaseSubmissionViewTestCase):
         self.assertTrue(str(second.id) in self.client.session['peeked'])
 
 
-class ByRoundTestCase(BaseViewTestCase):
-    url_name = 'apply:submissions:{}'
-    base_view_name = 'by_round'
-
-    def get_kwargs(self, instance):
-        return {'pk': instance.id}
-
-
-class TestStaffSubmissionByRound(ByRoundTestCase):
-    user_factory = StaffFactory
-
-    def test_can_access_round_page(self):
-        new_round = RoundFactory()
-        response = self.get_page(new_round)
-        self.assertContains(response, new_round.title)
-
-    def test_can_access_lab_page(self):
-        new_lab = LabFactory()
-        response = self.get_page(new_lab)
-        self.assertContains(response, new_lab.title)
-
-    def test_cant_access_normal_page(self):
-        new_round = RoundFactory()
-        page = new_round.get_site().root_page
-        response = self.get_page(page)
-        self.assertEqual(response.status_code, 404)
-
+class TestSuperUserSubmissionView(BaseSubmissionViewTestCase):
+    user_factory = SuperUserFactory
 
-class TestApplicantSubmissionByRound(ByRoundTestCase):
-    user_factory = UserFactory
+    @classmethod
+    def setUpTestData(cls):
+        cls.submission = ApplicationSubmissionFactory()
+        super().setUpTestData()
 
-    def test_cant_access_round_page(self):
-        new_round = RoundFactory()
-        response = self.get_page(new_round)
-        self.assertEqual(response.status_code, 403)
+    def __setUp__(self):
+        self.refresh(self.submission)
 
-    def test_cant_access_lab_page(self):
-        new_lab = LabFactory()
-        response = self.get_page(new_lab)
-        self.assertEqual(response.status_code, 403)
+    def test_can_screen_submission(self):
+        screening_outcome = ScreeningStatusFactory()
+        self.post_page(self.submission, {'form-submitted-screening_form': '', 'screening_status': screening_outcome.id})
+        submission = self.refresh(self.submission)
+        self.assertEqual(submission.screening_status, screening_outcome)
+
+    def test_can_screen_applications_in_final_status(self):
+        """
+        Now that the submission has been rejected (final determination),
+        we can still screen it because we are super user
+        """
+        submission = ApplicationSubmissionFactory(rejected=True)
+        screening_outcome = ScreeningStatusFactory()
+        response = self.post_page(submission, {'form-submitted-screening_form': '', 'screening_status': screening_outcome.id})
+        submission = self.refresh(submission)
+        self.assertEqual(response.context_data['screening_form'].should_show, True)
+        self.assertEqual(submission.screening_status, screening_outcome)
 
-    def test_cant_access_normal_page(self):
-        new_round = RoundFactory()
-        page = new_round.get_site().root_page
-        response = self.get_page(page)
-        self.assertEqual(response.status_code, 403)
+        # Check that an activity was created that should only be viewable internally
+        activity = Activity.objects.filter(message__contains='Screening status').first()
+        self.assertEqual(activity.visibility, INTERNAL)
diff --git a/opentech/apply/funds/tests/views/test_rounds.py b/opentech/apply/funds/tests/views/test_rounds.py
new file mode 100644
index 0000000000000000000000000000000000000000..93b3bd7107be9653543ac74446b761de78d9bd14
--- /dev/null
+++ b/opentech/apply/funds/tests/views/test_rounds.py
@@ -0,0 +1,99 @@
+from opentech.apply.funds.tests.factories import (
+    LabFactory,
+    RoundFactory,
+)
+
+from opentech.apply.users.tests.factories import (
+    ReviewerFactory,
+    StaffFactory,
+    UserFactory,
+)
+from opentech.apply.utils.testing.tests import BaseViewTestCase
+
+
+class BaseAllRoundsViewTestCase(BaseViewTestCase):
+    url_name = 'funds:rounds:{}'
+    base_view_name = 'list'
+
+
+class TestStaffRoundPage(BaseAllRoundsViewTestCase):
+    user_factory = StaffFactory
+
+    def test_can_access_page(self):
+        response = self.get_page()
+        self.assertEqual(response.status_code, 200)
+
+
+class TestReviewerAllRoundPage(BaseAllRoundsViewTestCase):
+    user_factory = ReviewerFactory
+
+    def test_cant_access_page(self):
+        response = self.get_page()
+        self.assertEqual(response.status_code, 403)
+
+
+class TestApplicantRoundPage(BaseAllRoundsViewTestCase):
+    user_factory = UserFactory
+
+    def test_cant_access_page(self):
+        response = self.get_page()
+        self.assertEqual(response.status_code, 403)
+
+
+class ByRoundTestCase(BaseViewTestCase):
+    url_name = 'apply:rounds:{}'
+    base_view_name = 'detail'
+
+    def get_kwargs(self, instance):
+        try:
+            return {'pk': instance.id}
+        except AttributeError:
+            return {'pk': instance['id']}
+
+
+class TestStaffSubmissionByRound(ByRoundTestCase):
+    user_factory = StaffFactory
+
+    def test_can_access_round_page(self):
+        new_round = RoundFactory()
+        response = self.get_page(new_round)
+        self.assertContains(response, new_round.title)
+
+    def test_can_access_lab_page(self):
+        new_lab = LabFactory()
+        response = self.get_page(new_lab)
+        self.assertContains(response, new_lab.title)
+
+    def test_cant_access_normal_page(self):
+        new_round = RoundFactory()
+        page = new_round.get_site().root_page
+        response = self.get_page(page)
+        self.assertEqual(response.status_code, 404)
+
+    def test_cant_access_non_existing_page(self):
+        response = self.get_page({'id': 555})
+        self.assertEqual(response.status_code, 404)
+
+
+class TestApplicantSubmissionByRound(ByRoundTestCase):
+    user_factory = UserFactory
+
+    def test_cant_access_round_page(self):
+        new_round = RoundFactory()
+        response = self.get_page(new_round)
+        self.assertEqual(response.status_code, 403)
+
+    def test_cant_access_lab_page(self):
+        new_lab = LabFactory()
+        response = self.get_page(new_lab)
+        self.assertEqual(response.status_code, 403)
+
+    def test_cant_access_normal_page(self):
+        new_round = RoundFactory()
+        page = new_round.get_site().root_page
+        response = self.get_page(page)
+        self.assertEqual(response.status_code, 403)
+
+    def test_cant_access_non_existing_page(self):
+        response = self.get_page({'id': 555})
+        self.assertEqual(response.status_code, 403)
diff --git a/opentech/apply/funds/urls.py b/opentech/apply/funds/urls.py
index d9f29072400c042075367adee6bcb78654ff56b0..7897ce287fc42c0919b4bbd171a1f4c9096a8ca3 100644
--- a/opentech/apply/funds/urls.py
+++ b/opentech/apply/funds/urls.py
@@ -3,13 +3,15 @@ from django.urls import include, path
 from .views import (
     RevisionCompareView,
     RevisionListView,
+    RoundListView,
     SubmissionsByRound,
     SubmissionDetailView,
     SubmissionEditView,
     SubmissionListView,
+    SubmissionOverviewView,
     SubmissionSealedView,
-    SubmissionSearchView,
 )
+from .api_views import SubmissionList, SubmissionDetail
 
 
 revision_urls = ([
@@ -21,7 +23,8 @@ revision_urls = ([
 app_name = 'funds'
 
 submission_urls = ([
-    path('', SubmissionListView.as_view(), name="list"),
+    path('', SubmissionOverviewView.as_view(), name="overview"),
+    path('all/', SubmissionListView.as_view(), name="list"),
     path('<int:pk>/', include([
         path('', SubmissionDetailView.as_view(), name="detail"),
         path('edit/', SubmissionEditView.as_view(), name="edit"),
@@ -32,11 +35,23 @@ submission_urls = ([
         path('', include('opentech.apply.determinations.urls', namespace="determinations")),
         path('revisions/', include(revision_urls, namespace="revisions")),
     ])),
-    path('rounds/<int:pk>/', SubmissionsByRound.as_view(), name="by_round"),
 ], 'submissions')
 
 
+submission_api_urls = ([
+    path('', SubmissionList.as_view(), name='list'),
+    path('<int:pk>/', SubmissionDetail.as_view(), name='detail'),
+], 'submissions-api')
+
+
+rounds_urls = ([
+    path('', RoundListView.as_view(), name="list"),
+    path('<int:pk>/', SubmissionsByRound.as_view(), name="detail"),
+], 'rounds')
+
+
 urlpatterns = [
     path('submissions/', include(submission_urls)),
-    path('search/', SubmissionSearchView.as_view(), name="search"),
+    path('rounds/', include(rounds_urls)),
+    path('api/submissions/', include(submission_api_urls)),
 ]
diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py
index b96a1fbe15c7f7ded3bf76e94318c92c5d5e7017..76e3dbf082deb524cb3d04d00a9d2d15cc49cde9 100644
--- a/opentech/apply/funds/views.py
+++ b/opentech/apply/funds/views.py
@@ -3,6 +3,7 @@ from copy import copy
 from django.contrib.auth.decorators import login_required
 from django.contrib import messages
 from django.core.exceptions import PermissionDenied
+from django.db.models import Q
 from django.http import HttpResponseRedirect, Http404
 from django.shortcuts import get_object_or_404
 from django.urls import reverse_lazy
@@ -29,50 +30,104 @@ from opentech.apply.users.decorators import staff_required
 from opentech.apply.utils.views import DelegateableView, ViewDispatcher
 
 from .differ import compare
-from .forms import ProgressSubmissionForm, UpdateReviewersForm, UpdateSubmissionLeadForm
-from .models import ApplicationSubmission, ApplicationRevision, RoundBase, LabBase
-from .tables import AdminSubmissionsTable, SubmissionFilter, SubmissionFilterAndSearch
+from .forms import ProgressSubmissionForm, ScreeningSubmissionForm, UpdateReviewersForm, UpdateSubmissionLeadForm
+from .models import ApplicationSubmission, ApplicationRevision, RoundsAndLabs, RoundBase, LabBase
+from .tables import (
+    AdminSubmissionsTable,
+    RoundsTable,
+    RoundsFilter,
+    SubmissionFilterAndSearch,
+    SummarySubmissionsTable,
+)
 from .workflow import STAGE_CHANGE_ACTIONS
 
 
 @method_decorator(staff_required, name='dispatch')
-class SubmissionListView(AllActivityContextMixin, SingleTableMixin, FilterView):
-    template_name = 'funds/submissions.html'
+class BaseAdminSubmissionsTable(SingleTableMixin, FilterView):
     table_class = AdminSubmissionsTable
+    filterset_class = SubmissionFilterAndSearch
+    filter_action = ''
+
+    excluded_fields = []
+
+    @property
+    def excluded(self):
+        return {
+            'exclude': self.excluded_fields
+        }
+
+    def get_table_kwargs(self, **kwargs):
+        return {**self.excluded, **kwargs}
 
-    filterset_class = SubmissionFilter
+    def get_filterset_kwargs(self, filterset_class):
+        kwargs = super().get_filterset_kwargs(filterset_class)
+        kwargs.update(self.excluded)
+        return kwargs
 
     def get_queryset(self):
         return self.filterset_class._meta.model.objects.current().for_table(self.request.user)
 
     def get_context_data(self, **kwargs):
-        active_filters = self.filterset.data
-        return super().get_context_data(active_filters=active_filters, **kwargs)
+        kwargs = super().get_context_data(**kwargs)
 
+        search_term = self.request.GET.get('query')
+        kwargs.update(
+            search_term=search_term,
+            filter_action=self.filter_action,
+        )
 
-@method_decorator(staff_required, name='dispatch')
-class SubmissionSearchView(SingleTableMixin, FilterView):
-    template_name = 'funds/submissions_search.html'
-    table_class = AdminSubmissionsTable
+        return super().get_context_data(**kwargs)
 
-    filterset_class = SubmissionFilterAndSearch
+
+class SubmissionOverviewView(AllActivityContextMixin, BaseAdminSubmissionsTable):
+    template_name = 'funds/submissions_overview.html'
+    table_class = SummarySubmissionsTable
+    table_pagination = False
+    filter_action = reverse_lazy('funds:submissions:list')
 
     def get_queryset(self):
-        return self.filterset_class._meta.model.objects.current().for_table(self.request.user)
+        return super().get_queryset()[:5]
 
     def get_context_data(self, **kwargs):
-        search_term = self.request.GET.get('query')
-
-        # We have more data than just 'query'
-        active_filters = len(self.filterset.data) > 1
+        base_query = RoundsAndLabs.objects.with_progress().order_by('end_date')
+        open_rounds = base_query.open()[:6]
+        open_query = '?round_state=open'
+        closed_rounds = base_query.closed()[:6]
+        closed_query = '?round_state=closed'
 
         return super().get_context_data(
-            search_term=search_term,
-            active_filters=active_filters,
+            open_rounds=open_rounds,
+            open_query=open_query,
+            closed_rounds=closed_rounds,
+            closed_query=closed_query,
             **kwargs,
         )
 
 
+class SubmissionListView(AllActivityContextMixin, BaseAdminSubmissionsTable):
+    template_name = 'funds/submissions.html'
+
+
+class SubmissionsByRound(BaseAdminSubmissionsTable):
+    template_name = 'funds/submissions_by_round.html'
+
+    excluded_fields = ('round', 'lead', 'fund')
+
+    def get_queryset(self):
+        # We want to only show lab or Rounds in this view, their base class is Page
+        try:
+            self.obj = Page.objects.get(pk=self.kwargs.get('pk')).specific
+        except Page.DoesNotExist:
+            raise Http404(_("No Round or Lab found matching the query"))
+
+        if not isinstance(self.obj, (LabBase, RoundBase)):
+            raise Http404(_("No Round or Lab found matching the query"))
+        return super().get_queryset().filter(Q(round=self.obj) | Q(page=self.obj))
+
+    def get_context_data(self, **kwargs):
+        return super().get_context_data(object=self.obj, **kwargs)
+
+
 @method_decorator(staff_required, name='dispatch')
 class ProgressSubmissionView(DelegatedViewMixin, UpdateView):
     model = ApplicationSubmission
@@ -90,6 +145,26 @@ class ProgressSubmissionView(DelegatedViewMixin, UpdateView):
         return super().form_valid(form)
 
 
+@method_decorator(staff_required, name='dispatch')
+class ScreeningSubmissionView(DelegatedViewMixin, UpdateView):
+    model = ApplicationSubmission
+    form_class = ScreeningSubmissionForm
+    context_name = 'screening_form'
+
+    def form_valid(self, form):
+        old = copy(self.get_object())
+        response = super().form_valid(form)
+        # Record activity
+        messenger(
+            MESSAGES.SCREENING,
+            request=self.request,
+            user=self.request.user,
+            submission=self.object,
+            related=str(old.screening_status),
+        )
+        return response
+
+
 @method_decorator(staff_required, name='dispatch')
 class UpdateLeadView(DelegatedViewMixin, UpdateView):
     model = ApplicationSubmission
@@ -140,6 +215,7 @@ class AdminSubmissionDetailView(ReviewContextMixin, ActivityContextMixin, Delega
     model = ApplicationSubmission
     form_views = [
         ProgressSubmissionView,
+        ScreeningSubmissionView,
         CommentFormView,
         UpdateLeadView,
         UpdateReviewersView,
@@ -423,14 +499,10 @@ class RevisionCompareView(DetailView):
 
 
 @method_decorator(staff_required, name='dispatch')
-class SubmissionsByRound(DetailView):
-    model = Page
-    template_name = 'funds/submissions_by_round.html'
+class RoundListView(SingleTableMixin, FilterView):
+    template_name = 'funds/rounds.html'
+    table_class = RoundsTable
+    filterset_class = RoundsFilter
 
-    def get_object(self):
-        # We want to only show lab or Rounds in this view, their base class is Page
-        obj = super().get_object()
-        obj = obj.specific
-        if not isinstance(obj, (LabBase, RoundBase)):
-            raise Http404(_("No Round or Lab found matching the query"))
-        return obj
+    def get_queryset(self):
+        return RoundsAndLabs.objects.with_progress()
diff --git a/opentech/apply/funds/workflow.py b/opentech/apply/funds/workflow.py
index 4f08d21476feb1d0edf9df379844a73aad7cf75e..39cb99ecd230dee979b823c34a8be8502f15e542 100644
--- a/opentech/apply/funds/workflow.py
+++ b/opentech/apply/funds/workflow.py
@@ -38,13 +38,48 @@ class Workflow(dict):
                 stages.append(phase.stage)
         return stages
 
+    @property
+    def stepped_phases(self):
+        phases = defaultdict(list)
+        for phase in list(self.values()):
+            phases[phase.step].append(phase)
+        return phases
+
+    def phases_for(self, user=None):
+        # Grab the first phase for each step - visible only, the display phase
+        return [
+            phase for phase, *_ in self.stepped_phases.values()
+            if not user or phase.permissions.can_view(user)
+        ]
+
+    def previous_visible(self, current, user):
+        """Find the latest phase that the user has view permissions for"""
+        display_phase = self.stepped_phases[current.step][0]
+        phases = self.phases_for()
+        index = phases.index(display_phase)
+        for phase in phases[index - 1::-1]:
+            if phase.permissions.can_view(user):
+                return phase
+
 
 class Phase:
-    def __init__(self, name, display, stage, permissions, step, transitions=dict()):
+    """
+    Phase Names:
+    display_name = phase name displayed to staff members in the system
+    public_name = phase name displayed to applicants in the system
+    future_name = phase_name displayed to applicants if they haven't passed this stage
+    """
+    def __init__(self, name, display, stage, permissions, step, public=None, future=None, transitions=dict()):
         self.name = name
         self.display_name = display
+        if public and future:
+            raise ValueError("Cant provide both a future and a public name")
+
+        self.public_name = public or self.display_name
+        self.future_name_staff = future or self.display_name
+        self.future_name_public = future or self.public_name
         self.stage = stage
-        self.permissions = permissions
+        self.permissions = Permissions(permissions)
         self.step = step
 
         # For building transition methods on the parent
@@ -69,6 +104,9 @@ class Phase:
     def __str__(self):
         return self.display_name
 
+    def __repr__(self):
+        return f'<Phase {self.display_name} ({self.public_name})>'
+
 
 class Stage:
     def __init__(self, name, has_external_review=False):
@@ -79,60 +117,48 @@ class Stage:
         return self.name
 
 
-class BasePermissions:
-    def can_edit(self, user: 'User') -> bool:
-        if user.is_apply_staff:
-            return self.can_staff_edit(user)
-
-        if user.is_applicant:
-            return self.can_applicant_edit(user)
+class Permissions:
+    def __init__(self, permissions):
+        self.permissions = permissions
 
-    def can_staff_edit(self, user: 'User') -> bool:
-        return False
+    def can_do(self, user, action):
+        checks = self.permissions.get(action, list())
+        return any(check(user) for check in checks)
 
-    def can_applicant_edit(self, user: 'User') -> bool:
-        return False
+    def can_edit(self, user):
+        return self.can_do(user, 'edit')
 
-    def can_review(self, user: 'User') -> bool:
-        if user.is_apply_staff:
-            return self.can_staff_review(user)
+    def can_review(self, user):
+        return self.can_do(user, 'review')
 
-        if user.is_reviewer:
-            return self.can_reviewer_review(user)
+    def can_view(self, user):
+        return self.can_do(user, 'view')
 
-    def can_staff_review(self, user: 'User') -> bool:
-        return False
 
-    def can_reviewer_review(self, user: 'User') -> bool:
-        return False
+staff_can = lambda user: user.is_apply_staff  # NOQA
 
+applicant_can = lambda user: user.is_applicant  # NOQA
 
-class NoPermissions(BasePermissions):
-    pass
+reviewer_can = lambda user: user.is_reviewer  # NOQA
 
 
-class DefaultPermissions(BasePermissions):
-    # Other Permissions should inherit from this class
-    # Staff can review at any time
-    def can_staff_review(self, user: 'User') -> bool:
-        return True
+def make_permissions(edit=list(), review=list(), view=[staff_can, applicant_can, reviewer_can]):
+    return {
+        'edit': edit,
+        'review': review,
+        'view': view,
+    }
 
-    def can_staff_edit(self, user: 'User') -> bool:
-        return True
 
+no_permissions = make_permissions()
 
-class ReviewerReviewPermissions(DefaultPermissions):
-    def can_reviewer_review(self, user: 'User') -> bool:
-        return True
+default_permissions = make_permissions(edit=[staff_can], review=[staff_can])
 
+hidden_from_applicant_permissions = make_permissions(edit=[staff_can], review=[staff_can], view=[staff_can, reviewer_can])
 
-class CanEditPermissions(DefaultPermissions):
-    def can_applicant_edit(self, user: 'User') -> bool:
-        return True
+reviewer_review_permissions = make_permissions(edit=[staff_can], review=[staff_can, reviewer_can])
 
-    def can_staff_edit(self, user: 'User') -> bool:
-        # Prevent staff editing whilst with the user for edits
-        return False
+applicant_edit_permissions = make_permissions(edit=[applicant_can], review=[staff_can])
 
 
 Request = Stage('Request', False)
@@ -146,409 +172,487 @@ Proposal = Stage('Proposal', True)
 
 INITIAL_STATE = 'in_discussion'
 
-SingleStageDefinition = {
-    INITIAL_STATE: {
-        'transitions': {
-            'internal_review': 'Open Review',
-            'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'more_info': 'Request More Information',
-            'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'Under Discussion',
-        'stage': Request,
-        'permissions': DefaultPermissions(),
-        'step': 0,
-    },
-    'more_info': {
-        'transitions': {
-            INITIAL_STATE: {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'More information required',
-        'stage': Request,
-        'permissions': CanEditPermissions(),
-        'step': 0,
-    },
-    'internal_review': {
-        'transitions': {
-            'post_review_discussion': 'Close Review',
-        },
-        'display': 'Internal Review',
-        'stage': Request,
-        'permissions': DefaultPermissions(),
-        'step': 1,
+SingleStageDefinition = [
+    {
+        INITIAL_STATE: {
+            'transitions': {
+                'internal_review': 'Open Review',
+                'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'more_info': 'Request More Information',
+                'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Screening',
+            'public': 'Application Received',
+            'stage': Request,
+            'permissions': default_permissions,
+        },
+        'more_info': {
+            'transitions': {
+                INITIAL_STATE: {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'More information required',
+            'stage': Request,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'post_review_discussion': {
-        'transitions': {
-            'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'post_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': Request,
-        'permissions': DefaultPermissions(),
-        'step': 2,
+    {
+        'internal_review': {
+            'transitions': {
+                'post_review_discussion': 'Close Review',
+            },
+            'display': 'Internal Review',
+            'public': 'OTF Review',
+            'stage': Request,
+            'permissions': default_permissions,
+        },
     },
-    'post_review_more_info': {
-        'transitions': {
-            'post_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'More information required',
-        'stage': Request,
-        'permissions': CanEditPermissions(),
-        'step': 2,
+    {
+        'post_review_discussion': {
+            'transitions': {
+                'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'post_review_more_info': 'Request More Information',
+            },
+            'display': 'Ready For Discussion',
+            'stage': Request,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'post_review_more_info': {
+            'transitions': {
+                'post_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'More information required',
+            'stage': Request,
+            'permissions': applicant_edit_permissions,
+        },
     },
-
-    'accepted': {
-        'display': 'Accepted',
-        'stage': Request,
-        'permissions': NoPermissions(),
-        'step': 3,
+    {
+        'determination': {
+            'transitions': {
+                'accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Determination',
+            'permissions': hidden_from_applicant_permissions,
+            'stage': Request,
+        },
     },
-    'rejected': {
-        'display': 'Dismissed',
-        'stage': Request,
-        'permissions': NoPermissions(),
-        'step': 3,
+    {
+        'accepted': {
+            'display': 'Accepted',
+            'future': 'Application Outcome',
+            'stage': Request,
+            'permissions': no_permissions,
+        },
+        'rejected': {
+            'display': 'Dismissed',
+            'stage': Request,
+            'permissions': no_permissions,
+        },
     },
-}
+]
 
-SingleStageExternalDefinition = {
-    INITIAL_STATE: {
-        'transitions': {
-            'ext_internal_review': 'Open Review',
-            'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'ext_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': RequestExt,
-        'permissions': DefaultPermissions(),
-        'step': 0,
-    },
-    'ext_more_info': {
-        'transitions': {
-            INITIAL_STATE: {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-        },
-        'display': 'More information required',
-        'stage': RequestExt,
-        'permissions': CanEditPermissions(),
-        'step': 0,
-    },
-    'ext_internal_review': {
-        'transitions': {
-            'ext_post_review_discussion': 'Close Review',
-        },
-        'display': 'Internal Review',
-        'stage': RequestExt,
-        'permissions': DefaultPermissions(),
-        'step': 1,
-    },
-    'ext_post_review_discussion': {
-        'transitions': {
-            'ext_external_review': 'Open AC review',
-            'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'ext_post_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': RequestExt,
-        'permissions': DefaultPermissions(),
-        'step': 2,
+SingleStageExternalDefinition = [
+    {
+        INITIAL_STATE: {
+            'transitions': {
+                'ext_internal_review': 'Open Review',
+                'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'ext_more_info': 'Request More Information',
+                'ext_determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Screening',
+            'public': 'Application Received',
+            'stage': RequestExt,
+            'permissions': default_permissions,
+        },
+        'ext_more_info': {
+            'transitions': {
+                INITIAL_STATE: {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+            },
+            'display': 'More information required',
+            'stage': RequestExt,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'ext_post_review_more_info': {
-        'transitions': {
-            'ext_post_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-        },
-        'display': 'More information required',
-        'stage': RequestExt,
-        'permissions': CanEditPermissions(),
-        'step': 2,
+    {
+        'ext_internal_review': {
+            'transitions': {
+                'ext_post_review_discussion': 'Close Review',
+            },
+            'display': 'Internal Review',
+            'public': 'OTF Review',
+            'stage': RequestExt,
+            'permissions': default_permissions,
+        },
     },
-    'ext_external_review': {
-        'transitions': {
-            'ext_post_external_review_discussion': 'Close Review',
-        },
-        'display': 'Advisory Council Review',
-        'stage': RequestExt,
-        'permissions': ReviewerReviewPermissions(),
-        'step': 3,
+    {
+        'ext_post_review_discussion': {
+            'transitions': {
+                'ext_external_review': 'Open AC review',
+                'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'ext_post_review_more_info': 'Request More Information',
+                'ext_determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready For Discussion',
+            'stage': RequestExt,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'ext_post_review_more_info': {
+            'transitions': {
+                'ext_post_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+            },
+            'display': 'More information required',
+            'stage': RequestExt,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'ext_post_external_review_discussion': {
-        'transitions': {
-            'ext_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'ext_post_external_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': RequestExt,
-        'permissions': DefaultPermissions(),
-        'step': 4,
+    {
+        'ext_external_review': {
+            'transitions': {
+                'ext_post_external_review_discussion': 'Close Review',
+            },
+            'display': 'Advisory Council Review',
+            'stage': RequestExt,
+            'permissions': reviewer_review_permissions,
+        },
     },
-    'ext_post_external_review_more_info': {
-        'transitions': {
-            'ext_post_external_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-        },
-        'display': 'More information required',
-        'stage': RequestExt,
-        'permissions': CanEditPermissions(),
-        'step': 4,
+    {
+        'ext_post_external_review_discussion': {
+            'transitions': {
+                'ext_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'ext_post_external_review_more_info': 'Request More Information',
+                'ext_determination': {'display': 'Ready For Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Discussion',
+            'stage': RequestExt,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'ext_post_external_review_more_info': {
+            'transitions': {
+                'ext_post_external_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+            },
+            'display': 'More information required',
+            'stage': RequestExt,
+            'permissions': applicant_edit_permissions,
+        },
     },
-
-    'ext_accepted': {
-        'display': 'Accepted',
-        'stage': RequestExt,
-        'permissions': NoPermissions(),
-        'step': 5,
+    {
+        'ext_determination': {
+            'transitions': {
+                'ext_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'ext_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Determination',
+            'permissions': hidden_from_applicant_permissions,
+            'stage': RequestExt,
+        },
     },
-    'ext_rejected': {
-        'display': 'Dismissed',
-        'stage': RequestExt,
-        'permissions': NoPermissions(),
-        'step': 5,
+    {
+        'ext_accepted': {
+            'display': 'Accepted',
+            'future': 'Application Outcome',
+            'stage': RequestExt,
+            'permissions': no_permissions,
+        },
+        'ext_rejected': {
+            'display': 'Dismissed',
+            'stage': RequestExt,
+            'permissions': no_permissions,
+        },
     },
-}
+]
 
 
-DoubleStageDefinition = {
-    INITIAL_STATE: {
-        'transitions': {
-            'concept_internal_review': 'Open Review',
-            'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'concept_more_info': 'Request More Information',
-            'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+DoubleStageDefinition = [
+    {
+        INITIAL_STATE: {
+            'transitions': {
+                'concept_internal_review': 'Open Review',
+                'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_more_info': 'Request More Information',
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_determination': {'display': 'Ready For Preliminary Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Screening',
+            'public': 'Concept Note Received',
+            'stage': Concept,
+            'permissions': default_permissions,
+        },
+        'concept_more_info': {
+            'transitions': {
+                INITIAL_STATE: {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_determination': {'display': 'Ready For Preliminary Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'More information required',
+            'stage': Concept,
+            'permissions': applicant_edit_permissions,
         },
-        'display': 'Under Discussion',
-        'stage': Concept,
-        'permissions': DefaultPermissions(),
-        'step': 0,
-    },
-    'concept_more_info': {
-        'transitions': {
-            INITIAL_STATE: {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'More information required',
-        'stage': Concept,
-        'permissions': CanEditPermissions(),
-        'step': 0,
-    },
-    'concept_internal_review': {
-        'transitions': {
-            'concept_review_discussion': 'Close Review',
-            'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'Internal Review',
-        'stage': Concept,
-        'permissions': DefaultPermissions(),
-        'step': 1,
-    },
-    'concept_review_discussion': {
-        'transitions': {
-            'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'concept_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': Concept,
-        'permissions': DefaultPermissions(),
-        'step': 2,
-    },
-    'concept_review_more_info': {
-        'transitions': {
-            'concept_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-        },
-        'display': 'More information required',
-        'stage': Concept,
-        'permissions': CanEditPermissions(),
-        'step': 2,
-    },
-    'invited_to_proposal': {
-        'display': 'Concept Accepted',
-        'transitions': {
-            'draft_proposal': {
-                'display': 'Progress',
-                'method': 'progress_application',
-                'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD},
-                'conditions': 'not_progressed',
-            },
-        },
-        'stage': Concept,
-        'permissions': NoPermissions(),
-        'step': 3,
     },
-    'concept_rejected': {
-        'display': 'Dismissed',
-        'stage': Concept,
-        'permissions': NoPermissions(),
-        'step': 3,
+    {
+        'concept_internal_review': {
+            'transitions': {
+                'concept_review_discussion': 'Close Review',
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Internal Review',
+            'public': 'OTF Review',
+            'stage': Concept,
+            'permissions': default_permissions,
+        },
     },
-    'draft_proposal': {
-        'transitions': {
-            'proposal_discussion': {'display': 'Submit', 'permissions': {UserPermissions.APPLICANT}, 'method': 'create_revision'},
-            'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'external_review': 'Open AC review',
-        },
-        'display': 'Invited for Proposal',
-        'stage': Proposal,
-        'permissions': CanEditPermissions(),
-        'step': 4,
+    {
+        'concept_review_discussion': {
+            'transitions': {
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_review_more_info': 'Request More Information',
+                'concept_determination': {'display': 'Ready For Preliminary Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Discussion',
+            'stage': Concept,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'concept_review_more_info': {
+            'transitions': {
+                'concept_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'More information required',
+            'stage': Concept,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'proposal_discussion': {
-        'transitions': {
-            'proposal_internal_review': 'Open Review',
-            'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'proposal_more_info': 'Request More Information',
-            'external_review': 'Open AC review',
-        },
-        'display': 'Under Discussion',
-        'stage': Proposal,
-        'permissions': DefaultPermissions(),
-        'step': 5,
+    {
+        'concept_determination': {
+            'transitions': {
+                'invited_to_proposal': {'display': 'Invite to Proposal', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'concept_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Preliminary Determination',
+            'permissions': hidden_from_applicant_permissions,
+            'stage': Concept,
+        },
     },
-    'proposal_more_info': {
-        'transitions': {
-            'proposal_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'external_review': 'Open AC review',
-        },
-        'display': 'More information required',
-        'stage': Proposal,
-        'permissions': CanEditPermissions(),
-        'step': 5,
+    {
+        'invited_to_proposal': {
+            'display': 'Concept Accepted',
+            'future': 'Preliminary Determination',
+            'transitions': {
+                'draft_proposal': {
+                    'display': 'Progress',
+                    'method': 'progress_application',
+                    'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD},
+                    'conditions': 'not_progressed',
+                },
+            },
+            'stage': Concept,
+            'permissions': no_permissions,
+        },
+        'concept_rejected': {
+            'display': 'Dismissed',
+            'stage': Concept,
+            'permissions': no_permissions,
+        },
     },
-    'proposal_internal_review': {
-        'transitions': {
-            'post_proposal_review_discussion': 'Close Review',
-        },
-        'display': 'Internal Review',
-        'stage': Proposal,
-        'permissions': DefaultPermissions(),
-        'step': 6,
+    {
+        'draft_proposal': {
+            'transitions': {
+                'proposal_discussion': {'display': 'Submit', 'permissions': {UserPermissions.APPLICANT}, 'method': 'create_revision'},
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'external_review': 'Open AC review',
+                'proposal_determination': {'display': 'Ready For Final Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Invited for Proposal',
+            'stage': Proposal,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'post_proposal_review_discussion': {
-        'transitions': {
-            'external_review': 'Open AC review',
-            'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'post_proposal_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': Proposal,
-        'permissions': DefaultPermissions(),
-        'step': 7,
+    {
+        'proposal_discussion': {
+            'transitions': {
+                'proposal_internal_review': 'Open Review',
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_more_info': 'Request More Information',
+                'proposal_determination': {'display': 'Ready For Final Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'external_review': 'Open AC review',
+            },
+            'display': 'Proposal Received',
+            'stage': Proposal,
+            'permissions': default_permissions,
+        },
+        'proposal_more_info': {
+            'transitions': {
+                'proposal_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_determination': {'display': 'Ready For Final Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'external_review': 'Open AC review',
+            },
+            'display': 'More information required',
+            'stage': Proposal,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'post_proposal_review_more_info': {
-        'transitions': {
-            'post_proposal_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-            'external_review': 'Open AC review',
-        },
-        'display': 'More information required',
-        'stage': Proposal,
-        'permissions': CanEditPermissions(),
-        'step': 7,
+    {
+        'proposal_internal_review': {
+            'transitions': {
+                'post_proposal_review_discussion': 'Close Review',
+            },
+            'display': 'Internal Review',
+            'public': 'OTF Review',
+            'stage': Proposal,
+            'permissions': default_permissions,
+        },
     },
-    'external_review': {
-        'transitions': {
-            'post_external_review_discussion': 'Close Review',
-        },
-        'display': 'Advisory Council Review',
-        'stage': Proposal,
-        'permissions': ReviewerReviewPermissions(),
-        'step': 8,
+    {
+        'post_proposal_review_discussion': {
+            'transitions': {
+                'external_review': 'Open AC review',
+                'proposal_determination': {'display': 'Ready For Final Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'post_proposal_review_more_info': 'Request More Information',
+            },
+            'display': 'Ready for Discussion',
+            'stage': Proposal,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'post_proposal_review_more_info': {
+            'transitions': {
+                'post_proposal_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+                'external_review': 'Open AC review',
+            },
+            'display': 'More information required',
+            'stage': Proposal,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'post_external_review_discussion': {
-        'transitions': {
-            'proposal_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
-            'post_external_review_more_info': 'Request More Information',
-        },
-        'display': 'Under Discussion',
-        'stage': Proposal,
-        'permissions': DefaultPermissions(),
-        'step': 9,
+    {
+        'external_review': {
+            'transitions': {
+                'post_external_review_discussion': 'Close Review',
+            },
+            'display': 'Advisory Council Review',
+            'stage': Proposal,
+            'permissions': reviewer_review_permissions,
+        },
     },
-    'post_external_review_more_info': {
-        'transitions': {
-            'post_external_review_discussion': {
-                'display': 'Submit',
-                'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
-                'method': 'create_revision',
-            },
-        },
-        'display': 'More information required',
-        'stage': Proposal,
-        'permissions': CanEditPermissions(),
-        'step': 9,
+    {
+        'post_external_review_discussion': {
+            'transitions': {
+                'proposal_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_determination': {'display': 'Ready For Final Determination', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'post_external_review_more_info': 'Request More Information',
+            },
+            'display': 'Ready for Discussion',
+            'stage': Proposal,
+            'permissions': hidden_from_applicant_permissions,
+        },
+        'post_external_review_more_info': {
+            'transitions': {
+                'post_external_review_discussion': {
+                    'display': 'Submit',
+                    'permissions': {UserPermissions.APPLICANT, UserPermissions.LEAD, UserPermissions.ADMIN},
+                    'method': 'create_revision',
+                },
+            },
+            'display': 'More information required',
+            'stage': Proposal,
+            'permissions': applicant_edit_permissions,
+        },
     },
-    'proposal_accepted': {
-        'display': 'Accepted',
-        'stage': Proposal,
-        'permissions': NoPermissions(),
-        'step': 10,
+    {
+        'proposal_determination': {
+            'transitions': {
+                'proposal_accepted': {'display': 'Accept', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+                'proposal_rejected': {'display': 'Dismiss', 'permissions': {UserPermissions.ADMIN, UserPermissions.LEAD}},
+            },
+            'display': 'Ready for Final Determination',
+            'permissions': hidden_from_applicant_permissions,
+            'stage': Proposal,
+        },
     },
-    'proposal_rejected': {
-        'display': 'Dismissed',
-        'stage': Proposal,
-        'permissions': NoPermissions(),
-        'step': 10,
+    {
+        'proposal_accepted': {
+            'display': 'Accepted',
+            'future': 'Final Determination',
+            'stage': Proposal,
+            'permissions': no_permissions,
+        },
+        'proposal_rejected': {
+            'display': 'Dismissed',
+            'stage': Proposal,
+            'permissions': no_permissions,
+        },
     },
+]
 
-}
+
+def unpack_phases(phases):
+    for step, step_data in enumerate(phases):
+        for name, phase_data in step_data.items():
+            yield step, name, phase_data
+
+
+def phase_data(phases):
+    return {
+        phase_name: Phase(phase_name, step=step, **phase_data)
+        for step, phase_name, phase_data in unpack_phases(phases)
+    }
 
 
-Request = Workflow('Request', 'single', **{
-    phase_name: Phase(phase_name, **phase_data)
-    for phase_name, phase_data in SingleStageDefinition.items()
-})
+Request = Workflow('Request', 'single', **phase_data(SingleStageDefinition))
 
-RequestExternal = Workflow('Request with external review', 'single_ext', **{
-    phase_name: Phase(phase_name, **phase_data)
-    for phase_name, phase_data in SingleStageExternalDefinition.items()
-})
+RequestExternal = Workflow('Request with external review', 'single_ext', **phase_data(SingleStageExternalDefinition))
 
-ConceptProposal = Workflow('Concept & Proposal', 'double', **{
-    phase_name: Phase(phase_name, **phase_data)
-    for phase_name, phase_data in DoubleStageDefinition.items()
-})
+ConceptProposal = Workflow('Concept & Proposal', 'double', **phase_data(DoubleStageDefinition))
 
 
 WORKFLOWS = {
diff --git a/opentech/apply/review/templatetags/review_tags.py b/opentech/apply/review/templatetags/review_tags.py
index 444a7e27cbb9fe50fcdabff84e9ec9c03cf39538..e5ef985c5bb9a148cb20a60a4aaccf07593dba08 100644
--- a/opentech/apply/review/templatetags/review_tags.py
+++ b/opentech/apply/review/templatetags/review_tags.py
@@ -21,7 +21,7 @@ TRAFFIC_LIGHT_COLORS = {
     }
 }
 
-TRAFFIC_LIGHT_TEMPLATE = '<span class="traffic-light traffic-light--{color}">{value}</span>'
+TRAFFIC_LIGHT_TEMPLATE = '<span aria-label="Traffic light score" class="traffic-light traffic-light--{color}">{value}</span>'
 
 
 @register.filter()
diff --git a/opentech/apply/stream_forms/blocks.py b/opentech/apply/stream_forms/blocks.py
index 684a692e88e083c2ef4b63f16a75fe162113d62e..d911275742eb4d0f1f8444bce96aa649a2d2563f 100644
--- a/opentech/apply/stream_forms/blocks.py
+++ b/opentech/apply/stream_forms/blocks.py
@@ -1,5 +1,6 @@
 # Credit to https://github.com/BertrandBordage for initial implementation
 import bleach
+from django_bleach.templatetags.bleach_tags import bleach_value
 
 from django import forms
 from django.db.models import BLANK_CHOICE_DASH
@@ -50,17 +51,39 @@ class FormFieldBlock(StructBlock):
         field_kwargs = self.get_field_kwargs(struct_value)
         return self.get_field_class(struct_value)(**field_kwargs)
 
-    def get_context(self, value, parent_context):
-        context = super().get_context(value, parent_context)
-        parent_context['data'] = self.format_data(parent_context['data']) or self.no_response()
-        return context
+    def serialize(self, value, context):
+        return {
+            'question': value['field_label'],
+            'answer': context.get('data'),
+            'type': self.name,
+        }
+
+    def serialize_no_response(self, value, context):
+        return {
+            'question': value['field_label'],
+            'answer': 'No Response',
+            'type': 'no_response',
+        }
+
+    def prepare_data(self, value, data, serialize=False):
+        return bleach_value(str(data))
+
+    def render(self, value, context):
+        data = context.get('data')
+        data = self.prepare_data(value, data, context.get('serialize', False))
+
+        context.update(data=data or self.no_response())
+
+        if context.get('serialize'):
+            if not data:
+                return self.serialize_no_response(value, context)
+            return self.serialize(value, context)
+
+        return super().render(value, context)
 
     def get_searchable_content(self, value, data):
         return str(data)
 
-    def format_data(self, data):
-        return data
-
     def no_response(self):
         return "No response"
 
@@ -273,6 +296,12 @@ class UploadableMediaBlock(OptionalFormFieldBlock):
     def get_searchable_content(self, value, data):
         return None
 
+    def prepare_data(self, value, data, serialize):
+        if serialize:
+            return data.serialize()
+
+        return data
+
 
 class ImageFieldBlock(UploadableMediaBlock):
     field_class = forms.ImageField
@@ -301,6 +330,11 @@ class MultiFileFieldBlock(UploadableMediaBlock):
         label = _('Multiple File field')
         template = 'stream_forms/render_multi_file_field.html'
 
+    def prepare_data(self, value, data, serialize):
+        if serialize:
+            return [file.serialize() for file in data]
+        return data
+
     def no_response(self):
         return [super().no_response()]
 
diff --git a/opentech/apply/stream_forms/files.py b/opentech/apply/stream_forms/files.py
index 1d5b8ce5d7df2b780b2e70269fa8bffc227dfe73..8fdf2febd2906c7baf65f19efe2f9dcb45db596e 100644
--- a/opentech/apply/stream_forms/files.py
+++ b/opentech/apply/stream_forms/files.py
@@ -66,6 +66,12 @@ class StreamFieldFile(File):
             return self.file.size
         return self.storage.size(self.name)
 
+    def serialize(self):
+        return {
+            'url': self.url,
+            'filename': self.filename,
+        }
+
     def open(self, mode='rb'):
         if getattr(self, '_file', None) is None:
             self.file = self.storage.open(self.name, mode)
diff --git a/opentech/apply/urls.py b/opentech/apply/urls.py
index 27483633b8fb3bad18a4649f396e9a4a7758cc62..deb32700492d24ef9fe3db8d49680f0241fcb757 100644
--- a/opentech/apply/urls.py
+++ b/opentech/apply/urls.py
@@ -1,9 +1,11 @@
+from django.conf import settings
 from django.urls import include, path
 
+from .utils import views
 from .users import urls as users_urls
 from .dashboard import urls as dashboard_urls
 
-from opentech.urls import urlpatterns as base_urlpatterns
+from opentech.urls import base_urlpatterns
 
 
 urlpatterns = [
@@ -14,4 +16,13 @@ urlpatterns = [
     path('hijack/', include('hijack.urls', 'hijack')),
 ]
 
+if settings.DEBUG:
+    urlpatterns += [
+        # Add views for testing 404 and 500 templates
+        path('test404/', views.page_not_found),
+    ]
+
 urlpatterns += base_urlpatterns
+
+
+handler404 = 'opentech.apply.utils.views.page_not_found'
diff --git a/opentech/apply/utils/__init__.py b/opentech/apply/utils/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..406254cfe657826bdc2a6ce7992d38cb46a4af9f 100644
--- a/opentech/apply/utils/__init__.py
+++ b/opentech/apply/utils/__init__.py
@@ -0,0 +1 @@
+default_app_config = 'opentech.apply.utils.app.UtilsConfig'
diff --git a/opentech/apply/utils/app.py b/opentech/apply/utils/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..b7215b4e1eb04ecd21099117b9989161f82be7ad
--- /dev/null
+++ b/opentech/apply/utils/app.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class UtilsConfig(AppConfig):
+    name = 'opentech.apply.utils'
+    label = 'apply_utils'
diff --git a/opentech/apply/utils/templates/apply/404.html b/opentech/apply/utils/templates/apply/404.html
new file mode 100644
index 0000000000000000000000000000000000000000..30b1072c3da83893225f7fe931f2292f5f4b5651
--- /dev/null
+++ b/opentech/apply/utils/templates/apply/404.html
@@ -0,0 +1,13 @@
+{% extends "base-apply.html" %}
+{% load wagtailcore_tags wagtailsettings_tags %}
+
+{% block title %}{{ settings.utils.SystemMessagesSettings.title_404 }}{% endblock %}
+
+{% block body_class %}template-404{% endblock %}
+
+{% block content %}
+<div class="wrapper wrapper--small wrapper--inner-space-large">
+    <h1>{{ settings.utils.SystemMessagesSettings.title_404 }}</h1>
+    {{ settings.utils.SystemMessagesSettings.body_404|richtext }}
+</div>
+{% endblock %}
diff --git a/opentech/apply/utils/views.py b/opentech/apply/utils/views.py
index d77666e5accbec25b5f044e3b5b315c3915341dc..87932814703c400b72c81e554d1bc1695c9e806e 100644
--- a/opentech/apply/utils/views.py
+++ b/opentech/apply/utils/views.py
@@ -1,10 +1,17 @@
 from django.contrib.auth.decorators import login_required
 from django.utils.decorators import method_decorator
+from django.views import defaults
 from django.views.generic import DetailView, View
 from django.views.generic.detail import SingleObjectTemplateResponseMixin
 from django.views.generic.edit import ModelFormMixin, ProcessFormView
 
 
+def page_not_found(request, exception=None, template_name='apply/404.html'):
+    if not request.user.is_authenticated:
+        template_name = '404.html'
+    return defaults.page_not_found(request, exception, template_name)
+
+
 @method_decorator(login_required, name='dispatch')
 class ViewDispatcher(View):
     admin_view: View = None
diff --git a/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html b/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
index 1bd9984c700dee25081225c9309e896eb011efed..d45a2dfd5298a870f4c0c8c42a49533f8aebf4db 100644
--- a/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
+++ b/opentech/public/mailchimp/templates/mailchimp/newsletter_signup.html
@@ -1,5 +1,5 @@
 <h4>Get the latest internet freedom news</h4>
-<form class="form" action="{% url "newsletter:subscribe" %}" method="post">
+<form class="form" action="{{ PUBLIC_SITE.root_url }}{% url "newsletter:subscribe" %}" method="post">
     <div>
         {% for field in newsletter_form %}
         <label for="{{ field.id_for_label }}"{% if field.field.required %} required{% endif %}>
diff --git a/opentech/public/navigation/templates/navigation/primarynav-apply.html b/opentech/public/navigation/templates/navigation/primarynav-apply.html
index a9c9bda2226cb6e045a7409b2e7b0dde80d65577..a48968ebc8b9f5415e12efe286bd9d25af079341 100644
--- a/opentech/public/navigation/templates/navigation/primarynav-apply.html
+++ b/opentech/public/navigation/templates/navigation/primarynav-apply.html
@@ -2,7 +2,7 @@
     <ul class="nav nav--primary" role="menubar">
         {% if request.user.is_apply_staff %}
             {% include "navigation/primarynav-apply-item.html" with name="Dashboard" url="dashboard:dashboard" %}
-            {% include "navigation/primarynav-apply-item.html" with name="Submissions" url="funds:submissions:list" %}
+            {% include "navigation/primarynav-apply-item.html" with name="Submissions" url="funds:submissions:overview" %}
         {% else %}
             {% include "navigation/primarynav-apply-item.html" with name="Dashboard" url="dashboard:dashboard" %}
         {% endif %}
diff --git a/opentech/public/search/views.py b/opentech/public/search/views.py
index 63031455fffca994a04892891a63b22de1fa91d3..a3aa058ae5361db6acfb7cd267ee70bd73ff02d9 100644
--- a/opentech/public/search/views.py
+++ b/opentech/public/search/views.py
@@ -1,11 +1,17 @@
 from django.conf import settings
 from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
+from django.http import Http404
 from django.shortcuts import render
 from wagtail.core.models import Page
 from wagtail.search.models import Query
 
+from opentech.public.home.models import HomePage
+
 
 def search(request):
+    if request.site != HomePage.objects.first().get_site():
+        raise Http404
+
     search_query = request.GET.get('query', None)
     page = request.GET.get('page', 1)
 
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index a8146b1edc17c7ebfafe7b7482c437d3c28d4e5c..fb39394186581b10c4c316deb34e0a6de93ce67c 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -73,6 +73,7 @@ INSTALLED_APPS = [
     'opentech.apply.review',
     'opentech.apply.determinations',
     'opentech.apply.stream_forms',
+    'opentech.apply.utils',
 
     'opentech.public.funds',
     'opentech.public.home',
@@ -116,6 +117,7 @@ INSTALLED_APPS = [
     'django_bleach',
     'django_fsm',
     'django_pwned_passwords',
+    'rest_framework',
 
     'hijack',
     'compat',
@@ -333,6 +335,11 @@ LOGGING = {
             'level': 'INFO',
             'propagate': False,
         },
+        'django': {
+            'handlers': ['console', 'sentry'],
+            'level': 'ERROR',
+            'propagate': False,
+        },
         'django.request': {
             'handlers': ['console', 'sentry'],
             'level': 'WARNING',
@@ -605,3 +612,15 @@ WEBPACK_LOADER = {
 COUNTRIES_OVERRIDE = {
     'KV': 'Kosovo',
 }
+
+# Rest Framework configuration
+REST_FRAMEWORK = {
+    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
+    'PAGE_SIZE': 10,
+    'DEFAULT_AUTHENTICATION_CLASSES': (
+        'rest_framework.authentication.SessionAuthentication',
+    ),
+    'DEFAULT_PERMISSION_CLASSES': (
+        'rest_framework.permissions.IsAuthenticated',
+    )
+}
diff --git a/opentech/static_src/src/app/.eslintrc b/opentech/static_src/src/app/.eslintrc
new file mode 100644
index 0000000000000000000000000000000000000000..4217ad2a7fec678e4574f84dd1ffbe0ed10bf833
--- /dev/null
+++ b/opentech/static_src/src/app/.eslintrc
@@ -0,0 +1,31 @@
+{
+    "parser": "babel-eslint",
+    "plugins": [
+        "react"
+    ],
+    "parserOptions": {
+        "ecmaVersion": 6,
+        "sourceType": "module",
+        "ecmaFeatures": {
+            "jsx": true
+        }
+    },
+    "env": {
+        "es6":     true,
+        "browser": true,
+        "node":    true,
+        "mocha":   true
+    },
+    "extends": [
+        "eslint:recommended",
+        "plugin:react/recommended"
+    ],
+    "settings": {
+        "react": {
+            "version": "detect"
+        }
+    },
+    "rules": {
+        "no-console": "off"
+    }
+}
diff --git a/opentech/static_src/src/app/src/App.js b/opentech/static_src/src/app/src/App.js
deleted file mode 100644
index 6704bbda9de764f34f2fe86880f136bae946e9bd..0000000000000000000000000000000000000000
--- a/opentech/static_src/src/app/src/App.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import { hot } from 'react-hot-loader'
-
-import './App.scss';
-
-class App extends React.Component {
-    constructor(props){
-        super(props);
-        this.state = {
-            detailOpen: false
-        }
-    }
-
-    detailOpen = (state) => {this.setState({detailOpen: state})}
-
-    render () {
-        return (
-            <div>
-                <div>
-                    <button className="red-button" onClick={() => this.detailOpen(true)}>Detail View</button>
-                    |
-                    <button onClick={() => this.detailOpen(false)}>List View</button>
-                </div>
-                {this.state.detailOpen ? (
-                    <div><h2>THIS IS REACT</h2></div>
-                ) : (
-                    <div dangerouslySetInnerHTML={ {__html: this.props.originalContent} } />
-                )}
-            </div>
-    )}
-}
-
-export default hot(module)(App)
diff --git a/opentech/static_src/src/app/src/App.scss b/opentech/static_src/src/app/src/App.scss
deleted file mode 100644
index 57adbe106905eda2913b07b743c6fa7eeabd2954..0000000000000000000000000000000000000000
--- a/opentech/static_src/src/app/src/App.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.red-button {
-    background-color: red;
-}
diff --git a/opentech/static_src/src/app/src/SubmissionsByRoundApp.js b/opentech/static_src/src/app/src/SubmissionsByRoundApp.js
new file mode 100644
index 0000000000000000000000000000000000000000..133ec908ac6d5d229408761c8f6bb708eae82fed
--- /dev/null
+++ b/opentech/static_src/src/app/src/SubmissionsByRoundApp.js
@@ -0,0 +1,68 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { hot } from 'react-hot-loader';
+import { connect } from 'react-redux'
+
+import Switcher from '@components/Switcher';
+import GroupByStatusDetailView from '@containers/GroupByStatusDetailView';
+import { setCurrentSubmissionRound } from '@actions/submissions';
+
+
+class SubmissionsByRoundApp extends React.Component {
+    static propTypes = {
+        roundID: PropTypes.number,
+        setSubmissionRound: PropTypes.func,
+        pageContent: PropTypes.node.isRequired,
+    };
+
+
+    state = { detailOpened: false };
+
+    componentDidMount() {
+        this.props.setSubmissionRound(this.props.roundID);
+    }
+
+    openDetail = () => {
+        this.setState(state => ({
+            style: { ...state.style, display: 'none' } ,
+            detailOpened: true,
+        }));
+    }
+
+    closeDetail = () => {
+        this.setState(state => {
+            const newStyle = { ...state.style };
+            delete newStyle.display;
+            return {
+                style: newStyle,
+                detailOpened: false,
+            };
+        });
+    }
+
+    render() {
+        return (
+            <>
+                <Switcher selector='submissions-by-round-app-react-switcher' open={this.state.detailOpened} handleOpen={this.openDetail} handleClose={this.closeDetail} />
+
+                <div style={this.state.style} ref={this.setOriginalContentRef} dangerouslySetInnerHTML={{ __html: this.props.pageContent }} />
+
+                {this.state.detailOpened &&
+                    <GroupByStatusDetailView roundId={this.props.roundID} />
+                }
+            </>
+        )
+    }
+}
+
+const mapDispatchToProps = dispatch => {
+    return {
+        setSubmissionRound: id => {
+            dispatch(setCurrentSubmissionRound(id));
+        },
+    }
+};
+
+export default hot(module)(
+    connect(null, mapDispatchToProps)(SubmissionsByRoundApp)
+);
diff --git a/opentech/static_src/src/app/src/api/index.js b/opentech/static_src/src/app/src/api/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6fcd16016bf03484a9777a09772ecd92b46f4507
--- /dev/null
+++ b/opentech/static_src/src/app/src/api/index.js
@@ -0,0 +1,6 @@
+import { fetchSubmission, fetchSubmissionsByRound } from '@api/submissions';
+
+export default {
+    fetchSubmissionsByRound,
+    fetchSubmission,
+};
diff --git a/opentech/static_src/src/app/src/api/submissions.js b/opentech/static_src/src/app/src/api/submissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d7f95f776558bdb14a68dc874901214de1dcceb
--- /dev/null
+++ b/opentech/static_src/src/app/src/api/submissions.js
@@ -0,0 +1,13 @@
+import { apiFetch } from '@api/utils';
+
+export async function fetchSubmissionsByRound(id) {
+    return apiFetch('/apply/api/submissions/', 'GET', {
+        'round': id,
+        'page_size': 1000,
+    });
+}
+
+
+export async function fetchSubmission(id) {
+    return apiFetch(`/apply/api/submissions/${id}/`, 'GET');
+}
diff --git a/opentech/static_src/src/app/src/api/utils.js b/opentech/static_src/src/app/src/api/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..094b3281fc9d5ee1ff4d5ea12e8ede48d92f40af
--- /dev/null
+++ b/opentech/static_src/src/app/src/api/utils.js
@@ -0,0 +1,20 @@
+const getBaseUrl = () => {
+    return process.env.API_BASE_URL;
+};
+
+export async function apiFetch(path, method = 'GET', params, options) {
+    const url = new URL(getBaseUrl());
+    url.pathname = path;
+
+    if (params !== undefined) {
+        for (const [paramKey, paramValue] of Object.entries(params)) {
+            url.searchParams.set(paramKey, paramValue);
+        }
+    }
+    return fetch(url, {
+        ...options,
+        method,
+        mode: 'same-origin',
+        credentials: 'include'
+    });
+}
diff --git a/opentech/static_src/src/app/src/components/DetailView/index.js b/opentech/static_src/src/app/src/components/DetailView/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..b392e211ef577a62aaa64ad8a674b62544cf83cf
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/DetailView/index.js
@@ -0,0 +1,101 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux';
+import PropTypes from 'prop-types';
+import { withWindowSizeListener } from 'react-window-size-listener';
+
+import { clearCurrentSubmission } from '@actions/submissions';
+import DisplayPanel from '@containers/DisplayPanel';
+import SlideInRight from '@components/Transitions/SlideInRight'
+import SlideOutLeft from '@components/Transitions/SlideOutLeft'
+import { getCurrentSubmissionID } from '@selectors/submissions';
+
+import './style.scss';
+
+class DetailView extends Component {
+    static propTypes = {
+        listing: PropTypes.element.isRequired,
+        submissionID: PropTypes.number,
+        windowSize: PropTypes.objectOf(PropTypes.number),
+        clearSubmission: PropTypes.func.isRequired,
+    };
+
+    state = {
+        listingShown: true,
+        firstRender: true,
+    }
+
+    isMobile = (width) => (width ? width : this.props.windowSize.windowWidth) < 1024
+
+    renderDisplay () {
+        return <DisplayPanel />
+    }
+
+    componentDidUpdate (prevProps, prevState) {
+        if (this.isMobile()) {
+            const haveCleared = prevProps.submissionID && !this.props.submissionID
+            const haveUpdated = !prevProps.submissionID && this.props.submissionID
+
+            if ( haveCleared ) {
+                this.setState({listingShown: true})
+            } else if ( haveUpdated && this.state.firstRender ) {
+                // Listing automatically updating after update
+                // clear, but dont run again
+                this.props.clearSubmission()
+                this.setState({firstRender: false})
+            } else if ( prevProps.submissionID !== this.props.submissionID) {
+                // Submission has changed and we want to show it
+                // reset the firstRender so that we can clear it again
+                this.setState({
+                    listingShown: false,
+                    firstRender: true,
+                })
+            }
+        }
+    }
+
+    render() {
+        const { listing } = this.props;
+
+        if (this.isMobile()) {
+            var activeDisplay;
+            if (this.state.listingShown){
+                activeDisplay = (
+                    <SlideOutLeft key={"listing"}>
+                        {listing}
+                    </SlideOutLeft>
+                )
+            } else {
+                activeDisplay = (
+                    <SlideInRight key={"display"}>
+                        { this.renderDisplay() }
+                    </SlideInRight>
+                )
+            }
+
+            return (
+                <div className="detail-view">
+                    { activeDisplay }
+                </div>
+            )
+        } else {
+            return (
+                <div className="detail-view">
+                    {listing}
+                    { this.renderDisplay() }
+                </div>
+            )
+        }
+
+    }
+}
+
+const mapStateToProps = state => ({
+    submissionID: getCurrentSubmissionID(state),
+});
+
+const mapDispatchToProps = {
+    clearSubmission: clearCurrentSubmission
+}
+
+
+export default connect(mapStateToProps, mapDispatchToProps)(withWindowSizeListener(DetailView));
diff --git a/opentech/static_src/src/app/src/components/DetailView/style.scss b/opentech/static_src/src/app/src/components/DetailView/style.scss
new file mode 100644
index 0000000000000000000000000000000000000000..2c70a676efe6257473dd79fc4c59d2ae0214535e
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/DetailView/style.scss
@@ -0,0 +1,24 @@
+.detail-view {
+    margin: 0 -20px;
+    overflow-y: overlay;
+
+    @include media-query(tablet-landscape) {
+        display: grid;
+        grid-template-columns: 250px 1fr;
+    }
+
+    @include media-query(desktop) {
+        // breakout of the wrapper
+        width: 100vw;
+        position: relative;
+        left: 50%;
+        right: 50%;
+        margin-left: -50vw;
+        margin-right: -50vw;
+        grid-template-columns: 390px 1fr;
+    }
+
+    @include target-ie11 {
+        display: flex;
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/Listing/index.js b/opentech/static_src/src/app/src/components/Listing/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..65f786726b058511d888c230700a004e3c03c841
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Listing/index.js
@@ -0,0 +1,124 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import ListingGroup from '@components/ListingGroup';
+import ListingItem from '@components/ListingItem';
+import LoadingPanel from '@components/LoadingPanel';
+
+import './style.scss';
+
+export default class Listing extends React.Component {
+    static propTypes = {
+        items: PropTypes.array,
+        activeItem: PropTypes.number,
+        isLoading: PropTypes.bool,
+        error: PropTypes.string,
+        groupBy: PropTypes.string,
+        order: PropTypes.arrayOf(PropTypes.string),
+        onItemSelection: PropTypes.func,
+    };
+
+    state = {
+        orderedItems: [],
+    };
+
+    componentDidMount() {
+        this.orderItems();
+    }
+
+    componentDidUpdate(prevProps, prevState) {
+        // Order items
+        if (this.props.items !== prevProps.items) {
+            this.orderItems();
+        }
+
+        const oldItem = prevProps.activeItem
+        const newItem = this.props.activeItem
+
+        // If we have never activated a submission, get the first item
+        if ( !newItem && !oldItem ) {
+            const firstGroup = this.state.orderedItems[0]
+            if ( firstGroup && firstGroup.items[0] ) {
+                this.setState({firstUpdate: false})
+                this.props.onItemSelection(firstGroup.items[0].id)
+            }
+        }
+    }
+
+    renderListItems() {
+        const { isLoading, error, items, onItemSelection, activeItem } = this.props;
+
+        if (isLoading) {
+            return (
+                <div className="listing__list is-loading">
+                    <LoadingPanel />
+                </div>
+            )
+        } else if (error) {
+            return (
+                <div className="listing__list is-loading">
+                    <p>Something went wrong. Please try again later.</p>
+                    <p>{ error }</p>
+                </div>
+            )
+        } else if (items.length === 0) {
+            return (
+                <div className="listing__list is-loading">
+                    <p>No results found.</p>
+                </div>
+            )
+        }
+
+        return (
+            <ul className="listing__list">
+                {this.state.orderedItems.map(group => {
+                    return (
+                        <ListingGroup key={`listing-group-${group.name}`} item={group}>
+                            {group.items.map(item => {
+                                return <ListingItem
+                                    selected={!!activeItem && activeItem===item.id}
+                                    onClick={() => onItemSelection(item.id)}
+                                    key={`listing-item-${item.id}`}
+                                    item={item}/>;
+                            })}
+                        </ListingGroup>
+                    );
+                })}
+            </ul>
+        );
+    }
+
+    getGroupedItems() {
+        const { groupBy, items } = this.props;
+
+        return items.reduce((tmpItems, v) => {
+            const groupByValue = v[groupBy];
+            if (!(groupByValue in tmpItems)) {
+                tmpItems[groupByValue] = [];
+            }
+            tmpItems[groupByValue].push({...v});
+            return tmpItems;
+        }, {});
+    }
+
+    orderItems() {
+        const groupedItems = this.getGroupedItems();
+        const { order = [] } = this.props;
+        const leftOverKeys = Object.keys(groupedItems).filter(v => !order.includes(v));
+        this.setState({
+            orderedItems: order.concat(leftOverKeys).filter(key => groupedItems[key] ).map(key => ({
+                name: key,
+                items: groupedItems[key] || []
+            })),
+        });
+    }
+
+    render() {
+        return (
+            <div className="listing">
+                <div className="listing__header"></div>
+                {this.renderListItems()}
+            </div>
+        );
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/Listing/style.scss b/opentech/static_src/src/app/src/components/Listing/style.scss
new file mode 100644
index 0000000000000000000000000000000000000000..97b57fb30221cf84bc81de50bb72f32c7ff9e6c3
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Listing/style.scss
@@ -0,0 +1,105 @@
+.listing {
+    @include target-ie11 {
+        max-width: 390px;
+        width: 100%;
+    }
+
+    &__header {
+        @include submission-list-item;
+        height: $listing-header-height;
+        padding: 20px;
+    }
+
+    // containing <ul>
+    &__list {
+        @include media-query(tablet-landscape) {
+            // only allow columns to be scrolled on larger screens
+            height: calc(100vh - var(--header-admin-height) - #{$listing-header-height});
+            overflow-y: scroll;
+        }
+
+        @include media-query(laptop-short) {
+            // allow for vertical scrolling on laptops
+            height: calc(100vh -  #{$listing-header-height});
+        }
+
+        &.is-loading {
+            padding: 20px;
+            border-right: 2px solid $color--light-mid-grey;
+
+            p {
+                margin: 20px 0 20px 20px;
+            }
+
+            .loading-panel__icon::after {
+                background: $color--light-grey;
+            }
+        }
+    }
+
+    // inner <li>'s
+    &__item {
+        @include submission-list-item;
+
+        &.is-active {
+            @include target-edge {
+                margin-left: 8px;
+            }
+
+            border-right: 2px solid $color--white;
+            transition: border $transition;
+        }
+
+        &--heading {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            background-color: $color--fog;
+            padding: 15px 20px;
+        }
+    }
+
+    // <a> tags
+    &__link {
+        display: block;
+        padding: 30px;
+        background-color: transparent;
+        transition: background-color $quick-transition;
+        position: relative;
+        color: $color--default;
+
+        &::before {
+            content: '';
+            height: 100%;
+            width: 0;
+            position: absolute;
+            left: 0;
+            top: 0;
+            background-color: $color--dark-blue;
+            transition: width $transition;
+        }
+
+        &:hover {
+            background-color: $color--white;
+        }
+
+        .is-active & {
+            background-color: $color--white;
+
+            &::before {
+                width: 8px;
+            }
+        }
+    }
+
+    &__title {
+        margin: 0;
+    }
+
+    &__count {
+        background-color: $color--white;
+        padding: 0 8px;
+        border-radius: 5px;
+        font-size: 14px;
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/ListingGroup.js b/opentech/static_src/src/app/src/components/ListingGroup.js
new file mode 100644
index 0000000000000000000000000000000000000000..6508a18b13c4c5574109451211c0fcd6c4af8f6f
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/ListingGroup.js
@@ -0,0 +1,26 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import ListingHeading from '@components/ListingHeading';
+
+
+export default class ListingGroup extends React.Component {
+    static propTypes = {
+        children: PropTypes.arrayOf(PropTypes.node),
+        item: PropTypes.shape({
+            name: PropTypes.string,
+        }),
+    };
+
+    render() {
+        const {item, children} = this.props
+        return (
+            <>
+                <ListingHeading title={item.name} count={children.length} />
+                <ul>
+                    {children}
+                </ul>
+            </>
+        );
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/ListingHeading.js b/opentech/static_src/src/app/src/components/ListingHeading.js
new file mode 100644
index 0000000000000000000000000000000000000000..996f7a933e214c8ae0aad300df9f4d1d8fda27ff
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/ListingHeading.js
@@ -0,0 +1,21 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+export default class ListingHeading extends React.Component {
+    render() {
+        return (
+            <li className="listing__item listing__item--heading">
+                <h5 className="listing__title">{this.props.title}</h5>
+                <span className="listing__count">{this.props.count}</span>
+            </li>
+        );
+    }
+}
+
+ListingHeading.propTypes = {
+    title: PropTypes.string,
+    count: PropTypes.oneOfType([
+        PropTypes.string,
+        PropTypes.number,
+    ]),
+};
diff --git a/opentech/static_src/src/app/src/components/ListingItem.js b/opentech/static_src/src/app/src/components/ListingItem.js
new file mode 100644
index 0000000000000000000000000000000000000000..65969c7deae3a1ddb5e54a1dc0fd6cf19ebacbc8
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/ListingItem.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+
+export default class ListingItem extends React.Component {
+    render() {
+        const { onClick, item, selected} = this.props;
+        return (
+            <li className={"listing__item " + (selected ? "is-active" : "")}>
+                <a className="listing__link" onClick={onClick}>
+                    {item.title}
+                </a>
+            </li>
+        );
+    }
+}
+
+ListingItem.propTypes = {
+    item: PropTypes.shape({
+        title: PropTypes.string,
+    }),
+    onClick: PropTypes.func,
+    selected: PropTypes.bool,
+};
diff --git a/opentech/static_src/src/app/src/components/LoadingPanel/index.js b/opentech/static_src/src/app/src/components/LoadingPanel/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc263937a7eba3378927c1dbd32a1703ce7ca41b
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/LoadingPanel/index.js
@@ -0,0 +1,14 @@
+import React from 'react'
+
+import './styles.scss';
+
+const LoadingIcon = () => {
+  return (
+      <div className="loading-panel">
+          <h5>Loading...</h5>
+          <div className="loading-panel__icon" />
+      </div>
+  )
+}
+
+export default LoadingIcon
diff --git a/opentech/static_src/src/app/src/components/LoadingPanel/styles.scss b/opentech/static_src/src/app/src/components/LoadingPanel/styles.scss
new file mode 100644
index 0000000000000000000000000000000000000000..aaaad97ad9b4bb64522d7e988a23995fa27d2053
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/LoadingPanel/styles.scss
@@ -0,0 +1,40 @@
+.loading-panel {
+    text-align: center;
+
+    &__icon {
+        font-size: 10px;
+        margin: 20px auto;
+        text-indent: -9999em;
+        width: 40px;
+        height: 40px;
+        border-radius: 50%;
+        background: linear-gradient(to right, $color--dark-grey 10%, transparent 42%);
+        position: relative;
+        animation: spin .4s infinite linear;
+        transform: translateZ(0);
+
+        &::after {
+            background: $color--white;
+            width: 75%;
+            height: 75%;
+            border-radius: 50%;
+            content: '';
+            margin: auto;
+            position: absolute;
+            top: 0;
+            left: 0;
+            bottom: 0;
+            right: 0;
+        }
+
+        @keyframes spin {
+            0% {
+                transform: rotate(0deg);
+            }
+
+            100% {
+                transform: rotate(360deg);
+            }
+        }
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/SubmissionDisplay/answers.js b/opentech/static_src/src/app/src/components/SubmissionDisplay/answers.js
new file mode 100644
index 0000000000000000000000000000000000000000..06ddea15efbe82c8d0b42798b0c1cd2b1ac7df0f
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/SubmissionDisplay/answers.js
@@ -0,0 +1,98 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import Download from 'images/download.svg';
+import File from 'images/file.svg';
+
+const answerType = {answer: PropTypes.string.isRequired}
+const arrayAnswerType = {answer: PropTypes.arrayOf(PropTypes.string)}
+const fileType = {answer: PropTypes.shape({
+    filename: PropTypes.string.isRequired,
+    url:PropTypes.string.isRequired,
+})}
+
+const ListAnswer = ({Wrapper, answers}) => {
+    return (
+        <ul className={`${Wrapper === FileAnswer ? 'remove-list-style' : ''}`}>{
+            answers.map((answer, index) => <li key={index}><Wrapper answer={answer} /></li>)
+        }</ul>
+    )
+};
+ListAnswer.propTypes = {
+    Wrapper: PropTypes.element,
+    ...arrayAnswerType,
+}
+
+const BasicAnswer = ({answer}) => <p>{ answer }</p>;
+BasicAnswer.propTypes = answerType
+
+const BasicListAnswer = ({answer}) => <ListAnswer Wrapper={BasicAnswer} answers={answer} />;
+BasicListAnswer.propTypes = arrayAnswerType
+
+const RichTextAnswer = ({answer}) => <div dangerouslySetInnerHTML={{ __html: answer }} />;
+RichTextAnswer.propTypes = answerType
+
+const FileAnswer = ({answer}) => (
+    <a className="link link--download" href={answer.url}>
+        <div>
+            <File /><span>{answer.filename}</span>
+        </div>
+        <Download />
+    </a>
+);
+FileAnswer.propTypes = fileType
+
+const MultiFileAnswer = ({answer}) => <ListAnswer Wrapper={FileAnswer} answers={answer} />;
+MultiFileAnswer.propTypes = {answer: PropTypes.arrayOf(fileType)}
+
+const AddressAnswer = ({answer}) => (
+    <div>{
+        Object.entries(answer)
+            .filter(([key, value]) => !!value )
+                .map(([key, value]) => <p key={key}>{value}</p> )}
+    </div>
+)
+AddressAnswer.propTypes = {answer: PropTypes.objectOf(PropTypes.string)}
+
+
+const answerTypes = {
+    'no_response': BasicAnswer,
+    'char': BasicAnswer,
+    'email': BasicAnswer,
+    'name': BasicAnswer,
+    'value': BasicAnswer,
+    'title': BasicAnswer,
+    'full_name': BasicAnswer,
+    'duration': BasicAnswer,
+    'date': BasicAnswer,
+    'checkbox': BasicAnswer,
+    'dropdown': BasicAnswer,
+    'radios': BasicAnswer,
+
+    // SPECIAL
+    'rich_text': RichTextAnswer,
+    'address': AddressAnswer,
+    'category': BasicListAnswer,
+    // Files
+    'file': FileAnswer,
+    'multi_file': MultiFileAnswer,
+}
+
+export const answerPropTypes = PropTypes.oneOfType([
+    PropTypes.string,
+    PropTypes.object,
+    PropTypes.arrayOf(PropTypes.string),
+    PropTypes.arrayOf(PropTypes.object),
+])
+
+const Answer = ({ answer, type }) => {
+    const AnswerType = answerTypes[type];
+
+    return <AnswerType answer={answer} />;
+}
+Answer.propTypes = {
+    answer: answerPropTypes,
+    type: PropTypes.string.isRequired,
+}
+
+export default Answer;
diff --git a/opentech/static_src/src/app/src/components/SubmissionDisplay/index.js b/opentech/static_src/src/app/src/components/SubmissionDisplay/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..b917578e041a12a90ea442b59624a7b24bd73ee1
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/SubmissionDisplay/index.js
@@ -0,0 +1,87 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+
+import Answer, { answerPropTypes } from './answers'
+import LoadingPanel from '@components/LoadingPanel';
+
+import './styles.scss'
+
+
+const MetaResponse = ({ question, answer, type }) => {
+    return (
+        <div>
+            <h5>{question}</h5>
+            <Answer type={type} answer={answer} />
+        </div>
+    )
+}
+MetaResponse.propTypes = {
+    question: PropTypes.string.isRequired,
+    answer: answerPropTypes,
+    type: PropTypes.string.isRequired,
+}
+
+
+const Response = ({question, answer, type}) => {
+    return (
+        <section>
+            <h4>{question}</h4>
+            <Answer type={type} answer={answer} />
+        </section>
+    )
+}
+Response.propTypes = {
+    question: PropTypes.string.isRequired,
+    answer: answerPropTypes,
+    type: PropTypes.string.isRequired,
+}
+
+
+export default class SubmissionDisplay extends Component {
+    static propTypes = {
+        isLoading: PropTypes.bool,
+        isError: PropTypes.bool,
+        submission: PropTypes.object,
+    }
+
+    render() {
+        if (this.props.isLoading) {
+            return (
+                <div className="display-panel__loading">
+                    <LoadingPanel />
+                </div>
+            )
+        } else if (this.props.isError) {
+            return (
+                <div className="display-panel__loading">
+                    <p>Something went wrong. Please try again later.</p>
+                </div>
+            )
+        } else if (this.props.submission === undefined) {
+            return (
+                <div className="display-panel__loading">
+                    <p>Please select a submission.</p>
+                </div>
+            )
+        }
+        const { meta_questions = [], questions = [], stage} = this.props.submission;
+
+        return (
+            <div className="application-display">
+                <h3>{stage} Information</h3>
+
+                <div className="grid grid--proposal-info">
+                    {meta_questions.map((response, index) => (
+                        <MetaResponse key={index} {...response} />
+                    ))}
+                </div>
+
+                <div className="rich-text rich-text--answers">
+                    {questions.map((response, index) => (
+                        <Response key={index} {...response} />
+                    ))}
+                </div>
+            </div>
+        )
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/SubmissionDisplay/styles.scss b/opentech/static_src/src/app/src/components/SubmissionDisplay/styles.scss
new file mode 100644
index 0000000000000000000000000000000000000000..5bb01974ad7f67428f6cced6b0f09f9da9ddad0d
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/SubmissionDisplay/styles.scss
@@ -0,0 +1,11 @@
+.application-display {
+    @include media-query(tablet-landscape) {
+        height: calc(100vh - var(--header-admin-height) - #{$listing-header-height} - 40px);
+        overflow-y: scroll;
+    }
+
+    @include media-query(laptop-short) {
+        // allow for vertical scrolling on laptops
+        height: calc(100vh -  #{$listing-header-height} - 40px);
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/Switcher/index.js b/opentech/static_src/src/app/src/components/Switcher/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..58fabc37430ba43f60dceacf49327f2a3f83652d
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Switcher/index.js
@@ -0,0 +1,36 @@
+import React from 'react'
+import ReactDOM from 'react-dom';
+import PropTypes from 'prop-types';
+
+import ArrayIcon from 'images/icon-array.svg'
+import GridIcon from 'images/icon-grid.svg';
+
+import './styles.scss';
+
+class Switcher extends React.Component {
+    static propTypes = {
+        handleOpen: PropTypes.func.isRequired,
+        handleClose: PropTypes.func.isRequired,
+        selector: PropTypes.string.isRequired,
+        open: PropTypes.bool,
+    }
+
+    constructor(props) {
+        super(props);
+        this.el = document.getElementById(props.selector);
+    }
+
+    render() {
+        const { handleOpen, handleClose, open } = this.props;
+
+        return ReactDOM.createPortal(
+            <>
+                <button className={`button button--switcher ${open ? '' : 'is-active'}`} onClick={handleClose} aria-label="Show table"><GridIcon /></button>
+                <button className={`button button--switcher ${open ? 'is-active' : ''}`} onClick={handleOpen} aria-label="Show grid"><ArrayIcon /></button>
+            </>,
+            this.el,
+        );
+    }
+}
+
+export default Switcher
diff --git a/opentech/static_src/src/app/src/components/Switcher/styles.scss b/opentech/static_src/src/app/src/components/Switcher/styles.scss
new file mode 100644
index 0000000000000000000000000000000000000000..8a86bd0441dc50bffb44b26c325145bfdc90dbd4
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Switcher/styles.scss
@@ -0,0 +1,24 @@
+.button {
+    &--switcher {
+        fill: transparentize($color--white, .5);
+        transition: fill $transition;
+
+        &:hover,
+        &:focus {
+            fill: transparentize($color--white, .25);
+        }
+
+        &:first-child {
+            margin-right: 10px;
+        }
+
+        &.is-active {
+            fill: $color--white;
+        }
+
+        svg {
+            width: 45px;
+            height: 45px;
+        }
+    }
+}
diff --git a/opentech/static_src/src/app/src/components/Tabber/index.js b/opentech/static_src/src/app/src/components/Tabber/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..1b1ee8a357ddc3c527d589305bed96414800805c
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Tabber/index.js
@@ -0,0 +1,59 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+
+
+
+export const Tab = ({button, children, handleClick}) => <div>{children}</div>
+Tab.propTypes = {
+    button: PropTypes.node,
+    children: PropTypes.node,
+    handleClick: PropTypes.func,
+}
+
+class Tabber extends Component {
+    static propTypes = {
+        children: PropTypes.arrayOf(PropTypes.element),
+    }
+
+    constructor() {
+        super();
+
+        this.state = {
+            activeTab: 0
+        }
+    }
+
+    componentDidUpdate(prevProps, prevState) {
+        const { children } = this.props;
+        if ( !children[prevState.activeTab].props.children ) {
+            this.setState({activeTab: children.findIndex(child => child.props.children)})
+        }
+    }
+
+    handleClick = (child) => {
+        this.setState({
+            activeTab: child
+        })
+    }
+
+    render() {
+        const { children } = this.props;
+
+        return (
+            <div className="tabber">
+                <div className="tabber__navigation">
+                    {children.map((child, i) => {
+                            return <a onClick={child.props.handleClick ? child.props.handleClick : () => this.handleClick(i)} className="display-panel__link" key={child.key}>{child.props.button}</a>
+                        })
+                    }
+                </div>
+                <div className="tabber-tab__active">
+                    { children[this.state.activeTab] }
+                </div>
+            </div>
+        )
+    }
+
+}
+
+export default Tabber;
diff --git a/opentech/static_src/src/app/src/components/Transitions/SlideInRight.js b/opentech/static_src/src/app/src/components/Transitions/SlideInRight.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d02d4bf40da82afb2d8e009540f4e26950176ef
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Transitions/SlideInRight.js
@@ -0,0 +1,40 @@
+import React from 'react'
+import PropTypes from 'prop-types';
+import Transition from 'react-transition-group/Transition';
+
+
+const SlideInRight = ({ children, in: inProp }) => {
+    const duration = 250;
+
+    const defaultStyle = {
+        transition: `transform ${duration}ms ease-in-out`,
+        transform: 'translate3d(0, 0, 0)',
+        position: 'absolute',
+        zIndex: 2,
+        width: '100%'
+    }
+
+    const transitionStyles = {
+        entering: { transform: 'translate3d(0, 0, 0)' },
+        entered: { transform: 'translate3d(100%, 0, 0)' },
+        exiting: { transform: 'translate3d(100%, 0, 0)' },
+        exited: { transform: 'translate3d(0, 0, 0)' }
+    };
+
+    return (
+        <Transition in={inProp} timeout={duration}>
+            {(state) => (
+                <div style={{ ...defaultStyle, ...transitionStyles[state] }}>
+                    {children}
+                </div>
+            )}
+        </Transition>
+    )
+}
+
+SlideInRight.propTypes = {
+    children: PropTypes.node,
+    in: PropTypes.bool,
+}
+
+export default SlideInRight
diff --git a/opentech/static_src/src/app/src/components/Transitions/SlideOutLeft.js b/opentech/static_src/src/app/src/components/Transitions/SlideOutLeft.js
new file mode 100644
index 0000000000000000000000000000000000000000..49345eb18fa0ddc1501f9a6ca1b901c1621ea02b
--- /dev/null
+++ b/opentech/static_src/src/app/src/components/Transitions/SlideOutLeft.js
@@ -0,0 +1,39 @@
+import React from 'react'
+import PropTypes from 'prop-types';
+import Transition from 'react-transition-group/Transition';
+
+
+const SlideOutLeft = ({ children, in: inProp }) => {
+    const duration = 250;
+
+    const defaultStyle = {
+        transition: `transform ${duration}ms ease-in-out`,
+        transform: 'translate3d(0, 0, 0)',
+        position: 'absolute',
+        width: '100%'
+    }
+
+    const transitionStyles = {
+        entering: { transform: 'translate3d(0, 0, 0)' },
+        entered: { transform: 'translate3d(-100%, 0, 0)' },
+        exiting: { transform: 'translate3d(-100%, 0, 0)' },
+        exited: { transform: 'translate3d(0, 0, 0)' }
+    };
+
+    return (
+        <Transition in={inProp} timeout={duration}>
+            {(state) => (
+                <div style={{ ...defaultStyle, ...transitionStyles[state] }}>
+                    {children}
+                </div>
+            )}
+        </Transition>
+    )
+}
+
+SlideOutLeft.propTypes = {
+    children: PropTypes.node,
+    in: PropTypes.bool,
+}
+
+export default SlideOutLeft
diff --git a/opentech/static_src/src/app/src/containers/ByStatusListing.js b/opentech/static_src/src/app/src/containers/ByStatusListing.js
new file mode 100644
index 0000000000000000000000000000000000000000..873036c9467564588ebc4fba69d8bba81002c29c
--- /dev/null
+++ b/opentech/static_src/src/app/src/containers/ByStatusListing.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux'
+
+import Listing from '@components/Listing';
+import {
+    loadCurrentRound,
+    setCurrentSubmission,
+} from '@actions/submissions';
+import {
+    getCurrentRound,
+    getCurrentRoundID,
+    getCurrentRoundSubmissions,
+    getCurrentSubmissionID,
+    getSubmissionsByRoundError,
+} from '@selectors/submissions';
+
+
+const loadData = props => {
+    props.loadSubmissions(['submissions'])
+}
+
+class ByStatusListing extends React.Component {
+    static propTypes = {
+        loadSubmissions: PropTypes.func,
+        submissions: PropTypes.arrayOf(PropTypes.object),
+        roundID: PropTypes.number,
+        round: PropTypes.object,
+        error: PropTypes.string,
+        setCurrentItem: PropTypes.func,
+        activeSubmission: PropTypes.number,
+    };
+
+    componentDidMount() {
+        // Update items if round ID is defined.
+        if ( this.props.roundID ) {
+            loadData(this.props)
+        }
+    }
+
+    componentDidUpdate(prevProps) {
+        const { roundID } = this.props;
+        // Update entries if round ID is changed or is not null.
+        if (roundID && prevProps.roundID !== roundID) {
+            console.log('wooop')
+            loadData(this.props)
+        }
+    }
+
+    render() {
+        const { error, submissions, round, setCurrentItem, activeSubmission } = this.props;
+        const isLoading = round && round.isFetching
+        return <Listing
+                    isLoading={isLoading}
+                    error={error}
+                    items={submissions}
+                    activeItem={activeSubmission}
+                    onItemSelection={setCurrentItem}
+                    groupBy={'status'}
+                    order={[
+                        // TODO: Set the proper order of statuses.
+                        'post_external_review_discussion',
+                        'in_discussion',
+                        'more_info',
+                        'internal_review',
+                        'post_review_discussion',
+                        'post_review_more_info',
+                        'accepted',
+                        'rejected',
+                    ]}
+            />;
+    }
+}
+
+const mapStateToProps = state => ({
+    roundID: getCurrentRoundID(state),
+    submissions: getCurrentRoundSubmissions(state),
+    round: getCurrentRound(state),
+    error: getSubmissionsByRoundError(state),
+    activeSubmission: getCurrentSubmissionID(state),
+})
+
+const mapDispatchToProps = dispatch => ({
+    loadSubmissions: () => dispatch(loadCurrentRound()),
+    setCurrentItem: id => dispatch(setCurrentSubmission(id)),
+});
+
+export default connect(
+    mapStateToProps,
+    mapDispatchToProps
+)(ByStatusListing);
diff --git a/opentech/static_src/src/app/src/containers/CurrentSubmissionDisplay.js b/opentech/static_src/src/app/src/containers/CurrentSubmissionDisplay.js
new file mode 100644
index 0000000000000000000000000000000000000000..75a4a018e0597651c70d9524b9c08c112980da89
--- /dev/null
+++ b/opentech/static_src/src/app/src/containers/CurrentSubmissionDisplay.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { connect } from 'react-redux'
+
+import { loadCurrentSubmission } from '@actions/submissions'
+import {
+    getCurrentSubmission,
+    getCurrentSubmissionID,
+} from '@selectors/submissions'
+import SubmissionDisplay from '@components/SubmissionDisplay';
+
+const loadData = props => {
+    props.loadCurrentSubmission(['questions'])
+
+}
+
+class CurrentSubmissionDisplay extends React.Component {
+    static propTypes = {
+        submission: PropTypes.object,
+        submissionID: PropTypes.number,
+    }
+
+    componentDidMount() {
+        loadData(this.props)
+    }
+
+    componentDidUpdate(prevProps) {
+        if (this.props.submissionID !== prevProps.submissionID ) {
+            loadData(this.props)
+        }
+    }
+
+    render () {
+        const { submission } = this.props
+        if ( !submission ) {
+            return <p>Loading</p>
+        }
+        return <SubmissionDisplay
+                   submission={submission}
+                   isLoading={submission.isFetching}
+                   isError={submission.isErrored} />
+    }
+
+}
+
+const mapStateToProps = state => ({
+    submissionID: getCurrentSubmissionID(state),
+    submission: getCurrentSubmission(state),
+})
+
+
+export default connect(mapStateToProps, {loadCurrentSubmission})(CurrentSubmissionDisplay)
diff --git a/opentech/static_src/src/app/src/containers/DisplayPanel/index.js b/opentech/static_src/src/app/src/containers/DisplayPanel/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..e09e83f962d083bafa4acb743007b7443aef068b
--- /dev/null
+++ b/opentech/static_src/src/app/src/containers/DisplayPanel/index.js
@@ -0,0 +1,92 @@
+import React from 'react';
+import { connect } from 'react-redux';
+import PropTypes from 'prop-types';
+import { withWindowSizeListener } from 'react-window-size-listener';
+
+import { clearCurrentSubmission } from '@actions/submissions';
+import {
+    getCurrentSubmission,
+    getCurrentSubmissionID,
+    getSubmissionErrorState,
+    getSubmissionLoadingState,
+
+} from '@selectors/submissions';
+
+import CurrentSubmissionDisplay from '@containers/CurrentSubmissionDisplay'
+import Tabber, {Tab} from '@components/Tabber'
+import './style.scss';
+
+
+class DisplayPanel extends React.Component  {
+    static propTypes = {
+        submissionID: PropTypes.number,
+        loadSubmission: PropTypes.func,
+        isLoading: PropTypes.bool,
+        isError: PropTypes.bool,
+        clearSubmission: PropTypes.func.isRequired,
+        windowSize: PropTypes.objectOf(PropTypes.number)
+    };
+
+    render() {
+        const { windowSize: {windowWidth: width} } = this.props;
+        const { clearSubmission } = this.props;
+
+        const isMobile = width < 1024;
+
+        const submission = <CurrentSubmissionDisplay />
+
+        let tabs = [
+            <Tab button="Notes" key="note">
+                <p>Notes</p>
+            </Tab>,
+            <Tab button="Status" key="status">
+                <p>Status</p>
+            </Tab>
+        ]
+
+        if ( isMobile ) {
+            tabs = [
+                <Tab button="Back" key="back" handleClick={ clearSubmission } />,
+                <Tab button="Application" key="application">
+                    { submission }
+                </Tab>,
+                ...tabs
+            ]
+        }
+
+        return (
+            <div className="display-panel">
+                { !isMobile && (
+                    <div className="display-panel__column">
+                        <div className="display-panel__header display-panel__header--spacer"></div>
+                        <div className="display-panel__body">
+                            { submission }
+                        </div>
+                    </div>
+                )}
+                <div className="display-panel__column">
+                    <div className="display-panel__body">
+                        <Tabber>
+                            { tabs }
+                        </Tabber>
+                    </div>
+                </div>
+            </div>
+
+        )
+    }
+}
+
+const mapStateToProps = state => ({
+    isLoading: getSubmissionLoadingState(state),
+    isError: getSubmissionErrorState(state),
+    submissionID: getCurrentSubmissionID(state),
+    submission: getCurrentSubmission(state),
+});
+
+const mapDispatchToProps = {
+    clearSubmission: clearCurrentSubmission
+}
+
+
+export default connect(mapStateToProps, mapDispatchToProps)(withWindowSizeListener(DisplayPanel));
diff --git a/opentech/static_src/src/app/src/containers/DisplayPanel/style.scss b/opentech/static_src/src/app/src/containers/DisplayPanel/style.scss
new file mode 100644
index 0000000000000000000000000000000000000000..673a9b9266a9501e4a417f087cc8aa11e3bb97d0
--- /dev/null
+++ b/opentech/static_src/src/app/src/containers/DisplayPanel/style.scss
@@ -0,0 +1,72 @@
+.display-panel {
+    background-color: $color--white;
+
+    @include media-query(tablet-landscape) {
+        display: grid;
+        grid-template-columns: 1fr 250px;
+    }
+
+    @include media-query(desktop) {
+        grid-template-columns: 1fr 390px;
+        grid-template-rows: 75px 1fr;
+    }
+
+    @include target-ie11 {
+        display: flex;
+        flex-wrap: wrap;
+        width: 100%;
+    }
+
+    &__body,
+    &__header {
+        @include submission-list-item;
+        padding: 20px;
+    }
+
+    // loading container
+    &__loading {
+        @include media-query(tablet-portrait) {
+            height: calc(100vh - var(--header-admin-height) - #{$listing-header-height} - 40px);
+        }
+
+        // 100vh - listing header - display-panel__body padding
+        @include media-query(laptop-short) {
+            height: calc(100vh -  #{$listing-header-height} - 40px);
+        }
+    }
+
+    &__header {
+        &--spacer {
+            display: none;
+            min-height: 75px;
+
+            @include media-query(tablet-landscape) {
+                display: block;
+            }
+        }
+    }
+
+    &__links {
+        display: flex;
+        align-items: center;
+        padding: 0;
+    }
+
+    &__link {
+        padding: 20px;
+    }
+
+    &__column {
+        &:first-child {
+            @include target-ie11 {
+                width: 70%;
+            }
+        }
+
+        &:last-child {
+            @include target-ie11 {
+                width: 30%;
+            }
+        }
+    }
+}
diff --git a/opentech/static_src/src/app/src/containers/GroupByStatusDetailView.js b/opentech/static_src/src/app/src/containers/GroupByStatusDetailView.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0ce02e5378e383edd7bfe8b75010f97870ae939
--- /dev/null
+++ b/opentech/static_src/src/app/src/containers/GroupByStatusDetailView.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import DetailView from '@components/DetailView';
+import ByStatusListing from '@containers/ByStatusListing';
+
+export default class GroupByStatusDetailView extends React.Component {
+    render() {
+        const listing = <ByStatusListing />;
+        return (
+            <DetailView listing={listing} />
+        );
+    }
+}
diff --git a/opentech/static_src/src/app/src/index.js b/opentech/static_src/src/app/src/index.js
index 3ce0eb6fec8d1cd8ad247e59bb1ba04cb867e793..96cb05daa85321660990598ae80cf8a252dda7d2 100644
--- a/opentech/static_src/src/app/src/index.js
+++ b/opentech/static_src/src/app/src/index.js
@@ -1,13 +1,18 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
+import { Provider } from 'react-redux';
 
-import App from './App'
+import SubmissionsByRoundApp from './SubmissionsByRoundApp';
+import createStore from '@redux/store';
 
 
-const container = document.getElementById('react-app')
+const container = document.getElementById('submissions-by-round-react-app');
 
+const store = createStore();
 
 ReactDOM.render(
-    <App originalContent={container.innerHTML} />,
+    <Provider store={store}>
+        <SubmissionsByRoundApp pageContent={container.innerHTML} roundID={parseInt(container.dataset.roundId)} />
+    </Provider>,
     container
 );
diff --git a/opentech/static_src/src/app/src/main.scss b/opentech/static_src/src/app/src/main.scss
new file mode 100644
index 0000000000000000000000000000000000000000..0508a4af4c6ea528096d39243eafb8a2466b8e49
--- /dev/null
+++ b/opentech/static_src/src/app/src/main.scss
@@ -0,0 +1,3 @@
+@import 'sass/apply/abstracts/_functions.scss';
+@import 'sass/apply/abstracts/_mixins.scss';
+@import 'sass/apply/abstracts/_variables.scss';
diff --git a/opentech/static_src/src/app/src/redux/actions/submissions.js b/opentech/static_src/src/app/src/redux/actions/submissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..db35aec0678e3239cec174980b3de9ff6a8d6459
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/actions/submissions.js
@@ -0,0 +1,134 @@
+import api from '@api';
+import {
+    getCurrentSubmission,
+    getCurrentSubmissionID,
+    getCurrentRoundID,
+    getCurrentRound,
+} from '@selectors/submissions';
+
+
+// Submissions by round
+export const SET_CURRENT_SUBMISSION_ROUND = 'SET_CURRENT_SUBMISSION_ROUND';
+export const UPDATE_SUBMISSIONS_BY_ROUND = 'UPDATE_SUBMISSIONS_BY_ROUND';
+export const START_LOADING_SUBMISSIONS_BY_ROUND = 'START_LOADING_SUBMISSIONS_BY_ROUND';
+export const FAIL_LOADING_SUBMISSIONS_BY_ROUND = 'FAIL_LOADING_SUBMISSIONS_BY_ROUND';
+
+// Submissions
+export const SET_CURRENT_SUBMISSION = 'SET_CURRENT_SUBMISSION';
+export const START_LOADING_SUBMISSION = 'START_LOADING_SUBMISSION';
+export const FAIL_LOADING_SUBMISSION = 'FAIL_LOADING_SUBMISSION';
+export const UPDATE_SUBMISSION = 'UPDATE_SUBMISSION';
+export const CLEAR_CURRENT_SUBMISSION = 'CLEAR_CURRENT_SUBMISSION';
+
+export const setCurrentSubmissionRound = id => ({
+    type: SET_CURRENT_SUBMISSION_ROUND,
+    id,
+});
+
+export const setCurrentSubmission = id => ({
+    type: SET_CURRENT_SUBMISSION,
+    id,
+});
+
+export const loadCurrentRound = (requiredFields=[]) => (dispatch, getState) => {
+    const round = getCurrentRound(getState())
+
+    if (round && requiredFields.every(key => round.hasOwnProperty(key))) {
+        return null
+    }
+
+    return dispatch(fetchSubmissionsByRound(getCurrentRoundID(getState())))
+}
+
+
+export const fetchSubmissionsByRound = roundID => {
+    return async function(dispatch) {
+        dispatch(startLoadingSubmissionsByRound(roundID));
+        try {
+            const response = await api.fetchSubmissionsByRound(roundID);
+            const json = await response.json();
+            if (response.ok) {
+                dispatch(updateSubmissionsByRound(roundID, json));
+            } else {
+                dispatch(failLoadingSubmissionsByRound(json.meta.error));
+            }
+        } catch (e) {
+            dispatch(failLoadingSubmissionsByRound(e.message));
+        }
+    };
+};
+
+
+const updateSubmissionsByRound = (roundID, data) => ({
+    type: UPDATE_SUBMISSIONS_BY_ROUND,
+    roundID,
+    data,
+});
+
+
+const startLoadingSubmissionsByRound = (roundID) => ({
+    type: START_LOADING_SUBMISSIONS_BY_ROUND,
+    roundID,
+});
+
+
+const failLoadingSubmissionsByRound = (message) => ({
+    type: FAIL_LOADING_SUBMISSIONS_BY_ROUND,
+    message,
+});
+
+
+export const loadCurrentSubmission = (requiredFields=[]) => (dispatch, getState) => {
+    const submissionID = getCurrentSubmissionID(getState())
+    if ( !submissionID ) {
+        return null
+    }
+    const submission = getCurrentSubmission(getState())
+
+    if (submission && requiredFields.every(key => submission.hasOwnProperty(key))) {
+        return null
+    }
+
+    return dispatch(fetchSubmission(getCurrentSubmissionID(getState())))
+}
+
+
+export const fetchSubmission = submissionID => {
+    return async function(dispatch) {
+
+        dispatch(startLoadingSubmission(submissionID));
+        try {
+            const response = await api.fetchSubmission(submissionID);
+            const json = await response.json();
+            if (response.ok) {
+                dispatch(updateSubmission(submissionID, json));
+            } else {
+                dispatch(failLoadingSubmission(json.meta.error));
+            }
+        } catch (e) {
+            dispatch(failLoadingSubmission(e.message));
+        }
+    };
+};
+
+
+const startLoadingSubmission = submissionID => ({
+    type: START_LOADING_SUBMISSION,
+    submissionID,
+});
+
+const failLoadingSubmission = submissionID => ({
+    type: FAIL_LOADING_SUBMISSION,
+    submissionID,
+});
+
+
+const updateSubmission = (submissionID, data) => ({
+    type: UPDATE_SUBMISSION,
+    submissionID,
+    data,
+});
+
+export const clearCurrentSubmission = () => ({
+    type: CLEAR_CURRENT_SUBMISSION,
+});
diff --git a/opentech/static_src/src/app/src/redux/reducers/index.js b/opentech/static_src/src/app/src/redux/reducers/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1e5e237467ee34a6e305045c469b99560e3e92b
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/reducers/index.js
@@ -0,0 +1,9 @@
+import { combineReducers } from 'redux'
+
+import submissions from '@reducers/submissions';
+import rounds from '@reducers/rounds';
+
+export default combineReducers({
+    submissions,
+    rounds,
+});
diff --git a/opentech/static_src/src/app/src/redux/reducers/rounds.js b/opentech/static_src/src/app/src/redux/reducers/rounds.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f4253b713fa386196a99315fa6221bb47e12630
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/reducers/rounds.js
@@ -0,0 +1,82 @@
+import { combineReducers } from 'redux';
+
+import {
+    FAIL_LOADING_SUBMISSIONS_BY_ROUND,
+    SET_CURRENT_SUBMISSION_ROUND,
+    START_LOADING_SUBMISSIONS_BY_ROUND,
+    UPDATE_SUBMISSIONS_BY_ROUND,
+} from '@actions/submissions';
+
+
+function round(state={id: null, submissions: [], isFetching: false}, action) {
+    switch(action.type) {
+        case UPDATE_SUBMISSIONS_BY_ROUND:
+            return {
+                ...state,
+                id: action.roundID,
+                submissions: action.data.results.map(submission => submission.id),
+                isFetching: false,
+            };
+        case FAIL_LOADING_SUBMISSIONS_BY_ROUND:
+            return {
+                ...state,
+                isFetching: false,
+            };
+        case START_LOADING_SUBMISSIONS_BY_ROUND:
+            return {
+                ...state,
+                id: action.roundID,
+                isFetching: true,
+            };
+        default:
+            return state;
+    }
+}
+
+
+function roundsByID(state = {}, action) {
+    switch(action.type) {
+        case UPDATE_SUBMISSIONS_BY_ROUND:
+        case FAIL_LOADING_SUBMISSIONS_BY_ROUND:
+        case START_LOADING_SUBMISSIONS_BY_ROUND:
+            return {
+                ...state,
+                [action.roundID]: round(state[action.roundID], action)
+            };
+        default:
+            return state;
+    }
+}
+
+
+function errorMessage(state = null, action) {
+    switch(action.type) {
+    case FAIL_LOADING_SUBMISSIONS_BY_ROUND:
+        return action.message;
+    case UPDATE_SUBMISSIONS_BY_ROUND:
+    case START_LOADING_SUBMISSIONS_BY_ROUND:
+        return null;
+    default:
+        return state;
+    }
+
+}
+
+
+function currentRound(state = null, action) {
+    switch(action.type) {
+        case SET_CURRENT_SUBMISSION_ROUND:
+            return action.id;
+        default:
+            return state;
+    }
+}
+
+
+const rounds = combineReducers({
+    byID: roundsByID,
+    current: currentRound,
+    error: errorMessage,
+});
+
+export default rounds;
diff --git a/opentech/static_src/src/app/src/redux/reducers/submissions.js b/opentech/static_src/src/app/src/redux/reducers/submissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..7563d1e25f0ac19364f82d0c96af3624f2125d4c
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/reducers/submissions.js
@@ -0,0 +1,86 @@
+import { combineReducers } from 'redux';
+
+import {
+    CLEAR_CURRENT_SUBMISSION,
+    FAIL_LOADING_SUBMISSION,
+    START_LOADING_SUBMISSION,
+    UPDATE_SUBMISSIONS_BY_ROUND,
+    UPDATE_SUBMISSION,
+    SET_CURRENT_SUBMISSION,
+} from '@actions/submissions';
+
+
+function submission(state, action) {
+    switch(action.type) {
+        case START_LOADING_SUBMISSION:
+            return {
+                ...state,
+                isFetching: true,
+                isErrored: false,
+            };
+        case FAIL_LOADING_SUBMISSION:
+            return {
+                ...state,
+                isFetching: false,
+                isErrored: true,
+            };
+        case UPDATE_SUBMISSION:
+            return {
+                ...state,
+                ...action.data,
+                isFetching: false,
+                isErrored: false,
+            };
+        default:
+            return state;
+    }
+}
+
+
+function submissionsByID(state = {}, action) {
+    switch(action.type) {
+        case START_LOADING_SUBMISSION:
+        case FAIL_LOADING_SUBMISSION:
+        case UPDATE_SUBMISSION:
+            return {
+                ...state,
+                [action.submissionID]: submission(state[action.submissionID], action),
+            };
+        case UPDATE_SUBMISSIONS_BY_ROUND:
+            return {
+                ...state,
+                ...action.data.results.reduce((newItems, newSubmission) => {
+                    newItems[newSubmission.id] = submission(
+                        state[newSubmission.id],
+                        {
+                            type: UPDATE_SUBMISSION,
+                            data: newSubmission,
+                        }
+                    );
+                    return newItems;
+                }, {}),
+            };
+        default:
+            return state;
+    }
+}
+
+
+function currentSubmission(state = null, action) {
+    switch(action.type) {
+        case SET_CURRENT_SUBMISSION:
+            return action.id;
+        case CLEAR_CURRENT_SUBMISSION:
+            return null;
+        default:
+            return state;
+    }
+}
+
+
+const submissions = combineReducers({
+    byID: submissionsByID,
+    current: currentSubmission,
+});
+
+export default submissions;
diff --git a/opentech/static_src/src/app/src/redux/selectors/submissions.js b/opentech/static_src/src/app/src/redux/selectors/submissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..09124b6896da42c2c177f2e706a8b2528deaca54
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/selectors/submissions.js
@@ -0,0 +1,53 @@
+import { createSelector } from 'reselect';
+
+const getSubmissions = state => state.submissions.byID;
+
+const getRounds = state => state.rounds.byID;
+
+const getCurrentRoundID = state => state.rounds.current;
+
+const getCurrentRound = createSelector(
+    [ getCurrentRoundID, getRounds],
+    (id, rounds) => {
+        return rounds[id];
+    }
+);
+
+const getCurrentSubmissionID = state => state.submissions.current;
+
+
+const getCurrentRoundSubmissions = createSelector(
+    [ getCurrentRound, getSubmissions],
+    (round, submissions) => {
+        const roundSubmissions = round ? round.submissions : [];
+        return roundSubmissions.map(submissionID => submissions[submissionID]);
+    }
+);
+
+
+const getCurrentSubmission = createSelector(
+    [ getCurrentSubmissionID, getSubmissions ],
+    (id, submissions) => {
+        return submissions[id];
+    }
+);
+
+const getSubmissionLoadingState = state => state.submissions.itemLoading === true;
+
+const getSubmissionErrorState = state => state.submissions.itemLoadingError === true;
+
+const getSubmissionsByRoundError = state => state.rounds.error;
+
+const getSubmissionsByRoundLoadingState = state => state.submissions.itemsLoading === true;
+
+export {
+    getCurrentRoundID,
+    getCurrentRound,
+    getCurrentRoundSubmissions,
+    getCurrentSubmission,
+    getCurrentSubmissionID,
+    getSubmissionsByRoundError,
+    getSubmissionsByRoundLoadingState,
+    getSubmissionLoadingState,
+    getSubmissionErrorState,
+};
diff --git a/opentech/static_src/src/app/src/redux/store.js b/opentech/static_src/src/app/src/redux/store.js
new file mode 100644
index 0000000000000000000000000000000000000000..ed0b719d6c0ff1968140fc66689ce15d53ddaa07
--- /dev/null
+++ b/opentech/static_src/src/app/src/redux/store.js
@@ -0,0 +1,25 @@
+import { createStore, applyMiddleware } from 'redux'
+import ReduxThunk from 'redux-thunk'
+import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'
+import logger from 'redux-logger'
+
+import rootReducer from '@reducers';
+
+const MIDDLEWARE = [
+    ReduxThunk,
+];
+
+if (process.env.NODE_ENV === 'development') {
+    MIDDLEWARE.push(logger);
+}
+
+
+export default initialState => {
+    const store = createStore(
+        rootReducer,
+        composeWithDevTools(
+            applyMiddleware(...MIDDLEWARE)
+        )
+    )
+    return store;
+};
diff --git a/opentech/static_src/src/app/webpack.base.config.js b/opentech/static_src/src/app/webpack.base.config.js
index 0a4c392f3cb62c7c39831fbb7ed13c8a3e214653..b6017a03190fc4870e014265d069f79bdd48d734 100644
--- a/opentech/static_src/src/app/webpack.base.config.js
+++ b/opentech/static_src/src/app/webpack.base.config.js
@@ -1,16 +1,15 @@
-var path = require("path")
+var path = require('path');
 
 module.exports = {
     context: __dirname,
 
-    entry: ['./src/index'],
+    entry: ['@babel/polyfill', './src/index'],
 
     output: {
-        filename: "[name]-[hash].js"
+        filename: '[name]-[hash].js'
     },
 
-    plugins: [
-    ], // add all common plugins here
+    plugins: [],
 
     module: {
         rules: [
@@ -19,26 +18,60 @@ module.exports = {
                 loader: 'babel-loader',
                 include: [path.resolve(__dirname, './src')],
                 query: {
-                    presets: ['@babel/preset-react'],
+                    presets: ['@babel/preset-react', '@babel/preset-env'],
                     plugins: [
                         'react-hot-loader/babel',
                         '@babel/plugin-proposal-class-properties'
                     ]
-                }
+                },
+            },
+            {
+                test: /\.js$/,
+                exclude: /node_modules/,
+                include: [path.resolve(__dirname, './src')],
+                loader: 'eslint-loader',
+                options: {
+                    configFile: path.resolve(__dirname, './.eslintrc'),
+                },
             },
             {
                 test: /\.scss$/,
-                use: [
-                    'style-loader',
-                    'css-loader',
-                    'sass-loader'
-                ]
+                use: [{
+                    loader: 'style-loader'
+                }, {
+                    loader: 'css-loader',
+                    options: {
+                        sourceMap: true
+                    }
+                }, {
+                    loader: 'sass-loader',
+                    options: {
+                        sourceMap: true,
+                        data: '@import "main.scss";',
+                        includePaths: [
+                            path.join(__dirname, 'src')
+                        ]
+                    }
+                }]
+            },
+            {
+                test: /\.svg$/,
+                use: ['@svgr/webpack']
             }
         ]
     },
 
     resolve: {
-        modules: ['node_modules'],
-        extensions: ['.js', '.jsx']
-    },
-}
+        modules: ['node_modules', './src'],
+        extensions: ['.js', '.jsx'],
+        alias: {
+            '@components': path.resolve(__dirname, 'src/components'),
+            '@containers': path.resolve(__dirname, 'src/containers'),
+            '@redux': path.resolve(__dirname, 'src/redux'),
+            '@reducers': path.resolve(__dirname, 'src/redux/reducers'),
+            '@selectors': path.resolve(__dirname, 'src/redux/selectors'),
+            '@actions': path.resolve(__dirname, 'src/redux/actions'),
+            '@api': path.resolve(__dirname, 'src/api'),
+        }
+    }
+};
diff --git a/opentech/static_src/src/app/webpack.dev.config.js b/opentech/static_src/src/app/webpack.dev.config.js
index ca91ad2d1efda7e637e217e7ef2ac12d31e730fb..e609036e52110ccc23ef1cc93158c14893846966 100644
--- a/opentech/static_src/src/app/webpack.dev.config.js
+++ b/opentech/static_src/src/app/webpack.dev.config.js
@@ -12,6 +12,9 @@ config.plugins = config.plugins.concat([
     new webpack.HotModuleReplacementPlugin(),
     new webpack.NoEmitOnErrorsPlugin(),
     new BundleTracker({filename: './opentech/static_compiled/app/webpack-stats.json'}),
+    new webpack.EnvironmentPlugin({
+        API_BASE_URL: 'http://apply.localhost:8000/',
+    }),
 ])
 
 // Add a loader for JSX files with react-hot enabled
diff --git a/opentech/static_src/src/app/webpack.prod.config.js b/opentech/static_src/src/app/webpack.prod.config.js
index 9b0ff64acf263045ea57e046147492c9f347a7d2..9f85413c07e0cc3b652e0fb7135b675e634dfe07 100644
--- a/opentech/static_src/src/app/webpack.prod.config.js
+++ b/opentech/static_src/src/app/webpack.prod.config.js
@@ -7,12 +7,10 @@ config.output.path = require('path').resolve('./assets/dist')
 
 config.plugins = config.plugins.concat([
     new BundleTracker({filename: './opentech/static_compiled/app/webpack-stats-prod.json'}),
-
-    // removes a lot of debugging code in React
-    new webpack.DefinePlugin({
-        'process.env': {
-            'NODE_ENV': JSON.stringify('production')
-        }}),
+    new webpack.EnvironmentPlugin({
+        NODE_ENV: 'production',
+        API_BASE_URL: null ,
+    }),
 ])
 
 config.optimization = {
diff --git a/opentech/static_src/src/images/download.svg b/opentech/static_src/src/images/download.svg
new file mode 100644
index 0000000000000000000000000000000000000000..9c729aba1bcd0ea17eb1bb8ea72babcc9366bf40
--- /dev/null
+++ b/opentech/static_src/src/images/download.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg viewBox="0 0 16 21" height="21" width="16" xmlns="http://www.w3.org/2000/svg">
+  <g stroke-width="3" fill="none" fill-rule="evenodd" stroke-linecap="square">
+      <path d="M8.176 13.833V2.167M8.303 14l4.991-4.714M8 14L3.009 9.286M13.824 19.5H2.176" />
+  </g>
+</svg>
diff --git a/opentech/static_src/src/images/file.svg b/opentech/static_src/src/images/file.svg
new file mode 100644
index 0000000000000000000000000000000000000000..936d57b3b18cd09fbe4b54a8c053bf21cd707a3b
--- /dev/null
+++ b/opentech/static_src/src/images/file.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg viewBox="0 0 27 32" height="32" width="27" xmlns="http://www.w3.org/2000/svg">
+    <g stroke-width="2" fill="none" fill-rule="evenodd">
+        <path d="M1.296 1v29.25H25V9.429h-8.218V1H1.296z" />
+        <path d="M5.5 20h15M5.5 15H12" stroke-linecap="square" />
+        <path d="M16.828.729l8.551 8.5" />
+    </g>
+</svg>
diff --git a/opentech/static_src/src/images/icon-array.svg b/opentech/static_src/src/images/icon-array.svg
new file mode 100644
index 0000000000000000000000000000000000000000..47982a5baa08eb2de4f43ac9a7f01d55dbc000a7
--- /dev/null
+++ b/opentech/static_src/src/images/icon-array.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
diff --git a/opentech/static_src/src/images/icon-grid.svg b/opentech/static_src/src/images/icon-grid.svg
new file mode 100644
index 0000000000000000000000000000000000000000..8b094a0fbd5243d3c68a49b1d5e3b4c9df26fe87
--- /dev/null
+++ b/opentech/static_src/src/images/icon-grid.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"/><path d="M0 0h24v24H0z" fill="none"/></svg>
diff --git a/opentech/static_src/src/javascript/apply/all-submissions-table.js b/opentech/static_src/src/javascript/apply/all-submissions-table.js
index 71d6f2087b86be10e79e5b4bbb811a90661c6ec4..f98d014546012f9ff6030911ad36445591430963 100644
--- a/opentech/static_src/src/javascript/apply/all-submissions-table.js
+++ b/opentech/static_src/src/javascript/apply/all-submissions-table.js
@@ -3,7 +3,7 @@
     'use strict';
 
     // add the toggle arrow before the submission titles
-    $('.all-submissions__parent td.title').prepend('<span class="all-submissions__toggle js-toggle-submission"><span class="arrow"></span></span>');
+    $('.all-submissions-table__parent td.title').prepend('<span class="all-submissions-table__toggle js-toggle-submission"><span class="arrow"></span></span>');
 
     // grab all the toggles
     const children = Array.prototype.slice.call(
@@ -13,7 +13,7 @@
     // show/hide the submission child rows
     children.forEach(function (child) {
         child.addEventListener('click', (e) => {
-            $(e.target).closest('.all-submissions__parent').toggleClass('is-expanded');
+            $(e.target).closest('.all-submissions-table__parent').toggleClass('is-expanded');
         });
     });
 
diff --git a/opentech/static_src/src/javascript/apply/submission-filters.js b/opentech/static_src/src/javascript/apply/submission-filters.js
index fe4f36b9c2e7368c7675f98eec0918c616c3dda9..2201fc5d3a2eea39451dedd21ceb1b7d177a5727 100644
--- a/opentech/static_src/src/javascript/apply/submission-filters.js
+++ b/opentech/static_src/src/javascript/apply/submission-filters.js
@@ -2,15 +2,44 @@
 
     'use strict';
 
-    const $openButton = $('.js-open-filters');
+    // Variables
+    const $body = $('body');
+    const $toggleButton = $('.js-toggle-filters');
     const $closeButton = $('.js-close-filters');
     const $clearButton = $('.js-clear-filters');
-    const $filterList = $('.js-filter-list');
-    const $filterWrapper = $('.js-filter-wrapper');
+    const filterOpenClass = 'filters-open';
+    const filterActiveClass = 'is-active';
+
+    const $searchInput = $('.js-search-input');
+    const $queryInput = $('#id_query');
+    const $searchForm = $('.js-search-form');
+
+    const $filterForm = $('.js-filter-form');
+
+    const urlParams = new URLSearchParams(window.location.search);
+
+    const persistedParams = ['sort', 'query'];
+
+    // check if the page has a query string and keep filters open if so on desktop
+    const minimumNumberParams = persistedParams.reduce(
+        (count, param) => count + urlParams.has(param) ? 1 : 0,
+        0
+    );
+
+    if ([...urlParams].length > minimumNumberParams && $(window).width() > 1024) {
+        $body.addClass(filterOpenClass);
+        updateButtonText();
+    }
+
+    $searchForm.submit((e) => {
+        e.preventDefault();
+        $queryInput.val($searchInput.val());
+        $filterForm.submit();
+    });
 
     // Add active class to filters - dropdowns are dynamically appended to the dom,
     // so we have to listen for the event higher up
-    $('body').on('click', '.select2-dropdown', (e) => {
+    $body.on('click', '.select2-dropdown', (e) => {
         // get the id of the dropdown
         let selectId = e.target.parentElement.parentElement.id;
 
@@ -19,44 +48,122 @@
 
         // if the dropdown contains a clear class, the filters are active
         if ($(match[0]).find('span.select2-selection__clear').length !== 0) {
-            match[0].classList.add('is-active');
+            match[0].classList.add(filterActiveClass);
         }
         else {
-            match[0].classList.remove('is-active');
+            match[0].classList.remove(filterActiveClass);
         }
     });
 
     // remove active class on clearing select2
     $('.select2').on('select2:unselecting', (e) => {
         const dropdown = e.target.nextElementSibling.firstChild.firstChild;
-        if (dropdown.classList.contains('is-active')) {
-            dropdown.classList.remove('is-active');
+        if (dropdown.classList.contains(filterActiveClass)) {
+            dropdown.classList.remove(filterActiveClass);
         }
     });
 
-    // open mobile filters
-    $openButton.on('click', (e) => {
-        $('body').addClass('no-scroll');
-        $(e.target).next($filterWrapper).addClass('is-open');
-        $filterList.addClass('form__filters--mobile');
+    // toggle filters
+    $toggleButton.on('click', () => {
+        if ($body.hasClass(filterOpenClass)) {
+            handleClearFilters();
+        }
+        else {
+            $body.addClass(filterOpenClass);
+            updateButtonText();
+        }
     });
 
-    // close mobile filters
+    // close filters on mobile
     $closeButton.on('click', (e) => {
-        $('body').removeClass('no-scroll');
-        $(e.target).closest($filterWrapper).removeClass('is-open');
-        $filterList.removeClass('form__filters--mobile');
+        $body.removeClass(filterOpenClass);
+        updateButtonText();
     });
 
+    // redirect to submissions home to clear filters
+    function handleClearFilters() {
+        const query = persistedParams.reduce(
+            (query, param) => query + (urlParams.get(param) ? `&${param}=${urlParams.get(param)}` : ''), '?');
+        window.location.href = window.location.href.split('?')[0] + query;
+    }
+
+    // toggle filters button wording
+    function updateButtonText() {
+        if ($body.hasClass(filterOpenClass)) {
+            $toggleButton.text('Clear filters');
+        }
+        else {
+            $toggleButton.text('Filters');
+        }
+    }
+
+    // corrects spacing of dropdowns when toggled on mobile
+    function mobileFilterPadding(element) {
+        const expanded = 'expanded-filter-element';
+        const dropdown = $(element).closest('.select2');
+        const openDropdown = $('.select2 .' + expanded);
+        let dropdownMargin = 0;
+
+        if (openDropdown.length > 0 && !openDropdown.hasClass('select2-container--open')) {
+            // reset the margin of the select we previously worked
+            openDropdown.removeClass(expanded);
+            // store the offset to adjust the new select box (elements above the old dropdown unaffected)
+            if (dropdown.position().top > openDropdown.position().top) {
+                dropdownMargin = parseInt(openDropdown.css('marginBottom'));
+            }
+            openDropdown.css('margin-bottom', '0px');
+        }
+
+        if (dropdown.hasClass('select2-container--open')) {
+            dropdown.addClass(expanded);
+            const dropdownID = $(element).closest('.select2-selection').attr('aria-owns');
+            // Element which has the height of the select dropdown
+            const match = $(`ul#${dropdownID}`);
+            const dropdownHeight = match.outerHeight(true);
+
+            // Element which has the position of the dropdown
+            const positionalMatch = match.closest('.select2-container');
+
+            // Pad the bottom of the select box
+            dropdown.css('margin-bottom', `${dropdownHeight}px`);
+
+            // bump up the dropdown options by height of closed elements
+            positionalMatch.css('top', positionalMatch.position().top - dropdownMargin);
+        }
+    }
+
     // clear all filters
     $clearButton.on('click', () => {
-        const dropdowns = document.querySelectorAll('.form__filters--mobile select');
+        const dropdowns = document.querySelectorAll('.form__filters select');
         dropdowns.forEach(dropdown => {
             $(dropdown).val(null).trigger('change');
-            $('.select2-selection.is-active').removeClass('is-active');
+            $('.select2-selection.is-active').removeClass(filterActiveClass);
             mobileFilterPadding(dropdown); // eslint-disable-line no-undef
         });
     });
 
-})(jQuery);
+    $(function () {
+        // Add active class to select2 checkboxes after page has been filtered
+        const clearButtons = document.querySelectorAll('.select2-selection__clear');
+        clearButtons.forEach(clearButton => {
+            clearButton.parentElement.parentElement.classList.add(filterActiveClass);
+        });
+    });
+
+    // reset mobile filters if they're open past the tablet breakpoint
+    $(window).resize(function resize() {
+        if ($(window).width() < 1024) {
+            // close the filters if open when reducing the window size
+            $('body').removeClass('filters-open');
 
+            // update filter button text
+            $('.js-toggle-filters').text('Filters');
+
+            // Correct spacing of dropdowns when toggled
+            $('.select2').on('click', (e) => {
+                mobileFilterPadding(e.target);
+            });
+        }
+    }).trigger('resize');
+
+})(jQuery);
diff --git a/opentech/static_src/src/javascript/apply/tabs.js b/opentech/static_src/src/javascript/apply/tabs.js
index d7ade577561e477f2c9371657ce47d62e9f3e93d..27e6a900499855ef1f662334ca5dcfd0b4a5dbea 100644
--- a/opentech/static_src/src/javascript/apply/tabs.js
+++ b/opentech/static_src/src/javascript/apply/tabs.js
@@ -7,20 +7,36 @@
             return '.js-tabs';
         }
 
-        constructor() {
+        constructor(node) {
+            this.node = node[0];
             // The tabs
-            this.tabItems = Array.prototype.slice.call(document.querySelectorAll('.tab__item:not(.js-tabs-off)'));
+            this.tabItems = Array.prototype.slice.call(this.node.querySelectorAll('.tab__item:not(.js-tabs-off)'));
 
             // The tabs content
             this.tabsContents = Array.prototype.slice.call(document.querySelectorAll('.tabs__content'));
 
+            // The tabs content container
+            this.tabsContentsContainer = Array.prototype.slice.call(document.querySelectorAll('.js-tabs-content'));
+
             // Active classes
             this.tabActiveClass = 'tab__item--active';
             this.tabContentActiveClass = 'tabs__content--current';
             this.defaultSelectedTab = 'tab-1';
+            this.addDataAttributes();
             this.bindEvents();
         }
 
+        addDataAttributes() {
+            // Add data-attrs for multiple tabs
+            this.tabsContentsContainer.forEach((tabsContent, i) => {
+                tabsContent.dataset.tabs = i + 1;
+            });
+
+            $('.js-tabs').each(function (i) {
+                $(this).attr('data-tabs', i + 1);
+            });
+        }
+
         bindEvents() {
             this.updateTabOnLoad();
 
@@ -48,15 +64,19 @@
         tabs(e) {
             // Find current tab
             const tab = e.currentTarget;
-            this.stripTabClasses();
+
+            const tabContentId = $(tab).closest('.js-tabs').data('tabs');
+            this.stripTabClasses(tabContentId);
             this.addTabClasses(tab);
             this.updateUrl(tab);
         }
 
-        stripTabClasses() {
+        stripTabClasses(tabContentId) {
             // remove active classes from all tabs and tab contents
-            this.tabItems.forEach(tabItem => tabItem.classList.remove(this.tabActiveClass));
-            this.tabsContents.forEach(tabsContent => tabsContent.classList.remove(this.tabContentActiveClass));
+            const parents = Array.prototype.slice.call($(`.js-tabs-content[data-tabs=${tabContentId}]`).find('.tabs__content'));
+            const childTabs = Array.prototype.slice.call($(`.js-tabs[data-tabs=${tabContentId}]`).find('.tab__item'));
+            childTabs.forEach(tabItem => tabItem.classList.remove(this.tabActiveClass));
+            parents.forEach(tabsContent => tabsContent.classList.remove(this.tabContentActiveClass));
         }
 
         addTabClasses(tab) {
@@ -65,10 +85,12 @@
             }
 
             const tabId = tab.getAttribute('data-tab');
+            const tabContentId = $(tab).closest('.js-tabs').data('tabs');
+            const parents = $(`.js-tabs-content[data-tabs=${tabContentId}]`);
 
             // add active classes to tabs and their respecitve content
             tab.classList.add(this.tabActiveClass);
-            document.querySelector(`#${tabId}`).classList.add(this.tabContentActiveClass);
+            $(parents).find(`#${tabId}`).addClass(this.tabContentActiveClass);
         }
 
         updateUrl(tab) {
diff --git a/opentech/static_src/src/javascript/main.js b/opentech/static_src/src/javascript/main.js
index 8356fe85e95e43e5fcd325c6c5619b00a7019f0b..9d1e0e9e5022577f26cff13451fdcdcd83e1224f 100644
--- a/opentech/static_src/src/javascript/main.js
+++ b/opentech/static_src/src/javascript/main.js
@@ -126,67 +126,15 @@
         message.classList.add('messages__text--hide');
     });
 
-    // Add active class to select2 checkboxes after page has been filtered
-    document.addEventListener('DOMContentLoaded', () => {
-        // If there are clear buttons in the dom, it means the filters have been applied
-        const clearButtons = document.querySelectorAll('.select2-selection__clear');
-        clearButtons.forEach(clearButton => {
-            clearButton.parentElement.parentElement.classList.add('is-active');
-        });
-    });
-
     // reset mobile filters if they're open past the tablet breakpoint
     $(window).resize(function resize() {
-        if ($(window).width() < 768) {
-            $('.select2').on('click', (e) => {
-                mobileFilterPadding(e.target);
-            });
-        }
-        else {
-            $('body').removeClass('no-scroll');
-            $('.js-filter-wrapper').removeClass('is-open');
-            $('.js-filter-list').removeClass('form__filters--mobile');
+        if ($(window).width() > 1024) {
             $('.js-actions-toggle').removeClass('is-active');
             $('.js-actions-sidebar').removeClass('is-visible');
             $('.tr--parent.is-expanded').removeClass('is-expanded');
         }
     }).trigger('resize');
 
-    function mobileFilterPadding(element) {
-        const expanded = 'expanded-filter-element';
-        const dropdown = $(element).closest('.select2');
-        const openDropdown = $('.select2 .' + expanded);
-        let dropdownMargin = 0;
-
-        if (openDropdown.length > 0 && !openDropdown.hasClass('select2-container--open')) {
-            // reset the margin of the select we previously worked
-            openDropdown.removeClass(expanded);
-            // store the offset to adjust the new select box (elements above the old dropdown unaffected)
-            if (dropdown.position().top > openDropdown.position().top) {
-                dropdownMargin = parseInt(openDropdown.css('marginBottom'));
-            }
-            openDropdown.css('margin-bottom', '0px');
-        }
-
-        if (dropdown.hasClass('select2-container--open')) {
-            dropdown.addClass(expanded);
-            const dropdownID = $(element).closest('.select2-selection').attr('aria-owns');
-            // Element which has the height of the select dropdown
-            const match = $(`ul#${dropdownID}`);
-            const dropdownHeight = match.outerHeight(true);
-
-            // Element which has the position of the dropdown
-            const positionalMatch = match.closest('.select2-container');
-
-            // Pad the bottom of the select box
-            dropdown.css('margin-bottom', `${dropdownHeight}px`);
-
-            // bump up the dropdown options by height of closed elements
-            positionalMatch.css('top', positionalMatch.position().top - dropdownMargin);
-        }
-    }
-
-
     $('form').filter('.form__comments').submit(function (e) {
         var $form = $(this);
         var formValues = $form.serialize();
@@ -201,4 +149,10 @@
         }
     });
 
+    // Get the header and admin bar height and set custom prop with value
+    $(window).on('load', function () {
+        const headerHeight = $('.header').outerHeight();
+        const adminbarHeight = $('.admin-bar').outerHeight();
+        document.documentElement.style.setProperty('--header-admin-height', headerHeight + adminbarHeight + 'px');
+    });
 })(jQuery);
diff --git a/opentech/static_src/src/sass/apply/abstracts/_mixins.scss b/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
index 24509a3ef802fb81c132e6610dc72a471817ad97..a4ac8a42d3d28b1fc951d0226fb1a445087cdc1e 100644
--- a/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
+++ b/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
@@ -155,3 +155,57 @@
     }
   }
 
+// used for the submission list items in the react app
+@mixin submission-list-item {
+    border-bottom: 2px solid $color--light-mid-grey;
+    border-right: 2px solid $color--light-mid-grey;
+}
+
+// ie11-specific css
+@mixin target-ie11 {
+    @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+        @content;
+    }
+}
+
+// ms-edge specific css
+@mixin target-edge {
+    @supports (-ms-ime-align: auto) {
+        @content;
+    }
+}
+
+@mixin table-ordering-styles {
+    thead {
+        th {
+            // ordering
+            &.desc,
+            &.asc {
+                position: relative;
+                color: $color--dark-grey;
+
+                &::after {
+                    position: absolute;
+                    top: 32px;
+                    margin-left: 3px;
+                }
+
+                a {
+                    color: inherit;
+                }
+            }
+
+            &.desc {
+                &::after {
+                    @include triangle(top, $color--default, 5px);
+                }
+            }
+
+            &.asc {
+                &::after {
+                    @include triangle(bottom, $color--default, 5px);
+                }
+            }
+        }
+    }
+}
diff --git a/opentech/static_src/src/sass/apply/abstracts/_variables.scss b/opentech/static_src/src/sass/apply/abstracts/_variables.scss
index 8f6c7113797a6ed556b4e59ef7446e7f88156958..c4e87dfd68b25855e2d32040473b05eebd7d5b49 100644
--- a/opentech/static_src/src/sass/apply/abstracts/_variables.scss
+++ b/opentech/static_src/src/sass/apply/abstracts/_variables.scss
@@ -1,4 +1,7 @@
 // sass-lint:disable no-color-keywords; no-color-hex
+:root {
+    --header-admin-height: 0;
+}
 
 // Default
 $color--white: #fff;
@@ -23,11 +26,12 @@ $color--mint: #40c2ad;
 $color--grass: #7dc588;
 $color--ocean: #1888b1;
 $color--sky-blue: #e7f2f6;
-$color--marine: #177da8;
+$color--marine: #14729a;
 $color--mist: #f3fafe;
 $color--green: #7dc558;
 $color--pastel-red: #f1a9a9;
 $color--pastel-green: #afe6af;
+$color--fog: #eff2f5;
 
 // Social
 $color--twitter: #1da6f6;
@@ -35,6 +39,7 @@ $color--linkedin: #137ab8;
 $color--facebook: #396ab5;
 
 // Transparent
+$color--black-60: rgba(0, 0, 0, .6);
 $color--black-50: rgba(0, 0, 0, .5);
 $color--black-40: rgba(0, 0, 0, .4);
 $color--black-25: rgba(0, 0, 0, .25);
@@ -91,13 +96,28 @@ $breakpoints: (
     'small-tablet'      '(min-width: 600px)',
     'tablet-portrait'   '(min-width: 768px)',
     'tablet-landscape'  '(min-width: 1024px)',
+    'laptop-short'      '(min-width: 1024px) and (max-height: 1280px)',
     'desktop'           '(min-width: 1320px)',
-    'deskop-wide'       '(min-width: 2556px)'
+    'desktop-medium'    '(min-width: 1920px)',
+    'desktop-wide'      '(min-width: 2556px)'
 );
 
 // Transition
 $transition: .25s ease-out;
 $quick-transition: .15s ease;
+$medium-transition: .5s ease;
+
+// Delays
+$base-delay: 30ms;
 
 // Spacing
 $mobile-gutter: 20px;
+
+// Filters
+$filter-dropdown: '.select2 .select2-selection.select2-selection--single';
+
+// listing header/spacer height
+$listing-header-height: 75px;
+
+// Table breakpoint
+$table-breakpoint: 'tablet-landscape';
diff --git a/opentech/static_src/src/sass/apply/base/_base.scss b/opentech/static_src/src/sass/apply/base/_base.scss
index 64fac05a4b13c45752c01e9ca281c1c86f718327..8ab04c2e5d8a29a34c90e499fe7e255cecb5004d 100644
--- a/opentech/static_src/src/sass/apply/base/_base.scss
+++ b/opentech/static_src/src/sass/apply/base/_base.scss
@@ -16,6 +16,10 @@ html {
     -webkit-text-size-adjust: 100%;
     -webkit-font-smoothing: antialiased;
     -moz-osx-font-smoothing: grayscale;
+
+    @supports(overflow-y: overlay) {
+        overflow-y: overlay;
+    }
 }
 
 body {
diff --git a/opentech/static_src/src/sass/apply/components/_admin-bar.scss b/opentech/static_src/src/sass/apply/components/_admin-bar.scss
index 9cc8a34affd212942794afee61b732f8529eb8b6..ef371d1a796b90145ab925a322066cb3ea3cf1c0 100644
--- a/opentech/static_src/src/sass/apply/components/_admin-bar.scss
+++ b/opentech/static_src/src/sass/apply/components/_admin-bar.scss
@@ -28,4 +28,12 @@
             margin-bottom: 0;
         }
     }
+
+    &__meta {
+        margin: 0 0 10px;
+
+        span {
+            margin: 0 5px;
+        }
+    }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_all-rounds-table.scss b/opentech/static_src/src/sass/apply/components/_all-rounds-table.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3be90e1d1aeed7bea486547e45a16653f0d757c5
--- /dev/null
+++ b/opentech/static_src/src/sass/apply/components/_all-rounds-table.scss
@@ -0,0 +1,23 @@
+.all-rounds-table {
+    @include table-ordering-styles;
+
+    thead {
+        display: none;
+
+        @include media-query($table-breakpoint) {
+            display: table-header-group;
+        }
+
+        th {
+            padding: 25px 10px;
+        }
+    }
+
+    tbody {
+        td {
+            &.title {
+                padding-top: 15px;
+            }
+        }
+    }
+}
diff --git a/opentech/static_src/src/sass/apply/components/_all-submissions.scss b/opentech/static_src/src/sass/apply/components/_all-submissions-table.scss
similarity index 88%
rename from opentech/static_src/src/sass/apply/components/_all-submissions.scss
rename to opentech/static_src/src/sass/apply/components/_all-submissions-table.scss
index ea72a28ba297d19475de991e4081269086dcd04b..81df77c7fe8888b7d61db64eda57aaaaa8f5850f 100644
--- a/opentech/static_src/src/sass/apply/components/_all-submissions.scss
+++ b/opentech/static_src/src/sass/apply/components/_all-submissions-table.scss
@@ -1,10 +1,9 @@
-// also in _table.scss
-$table-breakpoint: 'tablet-landscape';
-
-.all-submissions {
+.all-submissions-table {
+    @include table-ordering-styles;
     $root: &;
     font-size: 14px;
 
+
     thead {
         display: none;
 
@@ -13,37 +12,8 @@ $table-breakpoint: 'tablet-landscape';
         }
 
         th {
-            // ordering
-            &.desc,
-            &.asc {
-                position: relative;
-                color: $color--dark-grey;
-
-                &::after {
-                    position: absolute;
-                    top: 32px;
-                    margin-left: 3px;
-                }
-
-                a {
-                    color: inherit;
-                }
-            }
-
-            &.desc {
-                &::after {
-                    @include triangle(top, $color--default, 5px);
-                }
-            }
-
-            &.asc {
-                &::after {
-                    @include triangle(bottom, $color--default, 5px);
-                }
-            }
-
             &.reviews_stats { // sass-lint:disable-line class-name-format
-                color: $color--mid-dark-grey;
+                color: $color--black-60;
 
                 span {
                     font-size: 13px;
@@ -254,7 +224,27 @@ $table-breakpoint: 'tablet-landscape';
         }
     }
 
+    &__empty {
+        td {
+            padding: 20px;
+        }
+    }
+
     &__toggle {
         padding: 5px 0 5px 5px;
     }
+
+    &__more {
+        display: flex;
+        justify-content: center;
+        background-color: $color--white;
+        padding: 20px 25px;
+        min-height: auto;
+
+        a {
+            margin: 0;
+            flex-basis: auto;
+            font-weight: $weight--semibold;
+        }
+    }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_button.scss b/opentech/static_src/src/sass/apply/components/_button.scss
index 32efcfb5da86bc49602c897f429e5cad93fc46ab..5ebcce8979c9328a65d199918924f6676d478454 100644
--- a/opentech/static_src/src/sass/apply/components/_button.scss
+++ b/opentech/static_src/src/sass/apply/components/_button.scss
@@ -11,8 +11,8 @@
 
         .form--filters & {
             width: 100%;
-            height: 100%;
             text-align: center;
+            height: 45px;
         }
     }
 
@@ -72,21 +72,34 @@
         justify-content: space-between;
         max-width: 300px;
         padding: 15px 20px;
-        margin-bottom: 20px;
         font-weight: $weight--normal;
         color: $color--default;
         background: url('./../../images/filters.svg') $color--white no-repeat 93% center;
         border: 1px solid $color--light-mid-grey;
         transition: none;
-
-        &:focus,
-        &:active,
-        &:hover {
-            background: url('./../../images/filters.svg') $color--white no-repeat 93% center;
-        }
+        width: 100%;
 
         @include media-query(tablet-landscape) {
-            display: none;
+            background: none;
+            padding: 0 10px;
+            border: 0;
+            align-items: center;
+            justify-content: flex-start;
+            max-width: initial;
+            width: auto;
+
+            &::before {
+                content: '';
+                background-image: url('./../../images/filters.svg');
+                background-color: transparent;
+                background-position: left center;
+                transform: rotate(90deg);
+                background-size: 20px;
+                width: 20px;
+                height: 20px;
+                display: inline-block;
+                margin-right: 10px;
+            }
         }
     }
 
@@ -96,7 +109,7 @@
 
     &--search {
         position: absolute;
-        top: 12px;
+        top: .65em;
         right: 10px;
 
         svg {
diff --git a/opentech/static_src/src/sass/apply/components/_filters.scss b/opentech/static_src/src/sass/apply/components/_filters.scss
index 812e3758fdda9463815598c4d655fe4ae916d40f..f6018235d5ad2ecc37b175d9bb8225ac92c9f5c1 100644
--- a/opentech/static_src/src/sass/apply/components/_filters.scss
+++ b/opentech/static_src/src/sass/apply/components/_filters.scss
@@ -1,11 +1,7 @@
 .filters {
     display: none;
 
-    @include media-query(tablet-landscape) {
-        display: block;
-    }
-
-    &.is-open {
+    .filters-open & {
         position: fixed;
         top: 0;
         right: 0;
@@ -18,6 +14,26 @@
         background: $color--white;
     }
 
+    @include media-query(tablet-landscape) {
+        display: block;
+        max-height: 0;
+        transition: max-height $medium-transition;
+        transition-delay: $base-delay;
+        pointer-events: none;
+
+        .filters-open & {
+            position: relative;
+            top: auto;
+            left: auto;
+            right: auto;
+            bottom: auto;
+            height: auto;
+            background: transparent;
+            max-height: 85px;
+            pointer-events: all;
+        }
+    }
+
     &__header {
         display: flex;
         align-items: center;
@@ -36,4 +52,12 @@
             }
         }
     }
+
+    &__button {
+        appearance: none;
+        -webkit-appearance: none; // sass-lint:disable-line no-vendor-prefixes
+        border: 0;
+        color: $color--primary;
+        background: transparent;
+    }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_form.scss b/opentech/static_src/src/sass/apply/components/_form.scss
index 44c94c9aea1d60515fde8b2ce023234235c57936..c7708add8d06a46a2ac14c522915aa821a09bc82 100644
--- a/opentech/static_src/src/sass/apply/components/_form.scss
+++ b/opentech/static_src/src/sass/apply/components/_form.scss
@@ -17,12 +17,15 @@
         }
     }
 
-    &--header-search-desktop {
+    &--search {
         position: relative;
-        width: 280px;
+        max-width: 300px;
+        margin-top: $mobile-gutter;
+        width: 100%;
 
-        @include media-query(small-tablet) {
-            margin-top: 15px;
+        @include media-query(tablet-landscape) {
+            max-width: 280px;
+            margin: 0 0 0 30px;
         }
     }
 
@@ -107,8 +110,33 @@
     }
 
     &__filters {
-        display: flex;
-        padding: 10px 0 30px;
+        #{$filter-dropdown} {
+            border: 0;
+            border-top: 1px solid $color--mid-grey;
+
+            &.is-active {
+                font-weight: $weight--normal;
+                background-color: transparentize($color--primary, .9);
+                border-color: $color--mid-grey;
+            }
+
+            @include media-query(tablet-landscape) {
+                border: 1px solid $color--mid-grey;
+            }
+        }
+
+        @include media-query(tablet-landscape) {
+            display: flex;
+            align-items: flex-start;
+            padding: 10px 0 30px;
+            opacity: 0;
+            transition: opacity $transition;
+
+            .filters-open & {
+                opacity: 1;
+                transition-delay: $base-delay * 10;
+            }
+        }
 
         label {
             display: none;
@@ -116,25 +144,19 @@
 
         // so the form can be output in any tag
         > * {
-            flex-basis: 225px;
-            margin-right: 10px;
+            @include media-query(tablet-landscape) {
+                flex-basis: 225px;
+
+                &:not(:last-child) {
+                    margin-right: 10px;
+                }
+            }
         }
 
         &--mobile {
             flex-direction: column;
             padding: 0;
 
-            .select2 .select2-selection.select2-selection--single { // sass-lint:disable-line force-element-nesting
-                border: 0;
-                border-top: 1px solid $color--mid-grey;
-
-                &.is-active {
-                    font-weight: $weight--normal;
-                    background-color: transparentize($color--primary, .9);
-                    border-color: $color--mid-grey;
-                }
-            }
-
             // so the form can be output in any tag
             > * {
                 flex-basis: auto;
@@ -179,6 +201,7 @@
         }
 
         .form__filters & {
+            background: $color--white;
             max-width: 100%;
         }
 
@@ -385,4 +408,3 @@
         max-width: 410px;
     }
 }
-
diff --git a/opentech/static_src/src/sass/apply/components/_input.scss b/opentech/static_src/src/sass/apply/components/_input.scss
index e73b1d50d0c1e20e5b140a3c091e9eca3e298bc9..fa64ea285549a1667ce69b28956e986ce9035b1c 100644
--- a/opentech/static_src/src/sass/apply/components/_input.scss
+++ b/opentech/static_src/src/sass/apply/components/_input.scss
@@ -2,8 +2,8 @@
     &--search {
         width: 100%;
         padding: 10px;
-        color: $color--white;
+        color: $color--dark-grey;
         background: transparent;
-        border: 1px solid $color--white;
+        border: 1px solid $color--mid-dark-grey;
     }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_link.scss b/opentech/static_src/src/sass/apply/components/_link.scss
index 65917654e32eb79eb5e59afb500db9050585f364..9217908648e8a569ebe7e7d86b8769db2ab0d153 100644
--- a/opentech/static_src/src/sass/apply/components/_link.scss
+++ b/opentech/static_src/src/sass/apply/components/_link.scss
@@ -54,7 +54,7 @@
             }
 
             &:last-child {
-                width: 12px;
+                width: 15px;
                 height: 18px;
                 stroke: $color--white;
             }
diff --git a/opentech/static_src/src/sass/apply/components/_rich-text.scss b/opentech/static_src/src/sass/apply/components/_rich-text.scss
index 4457e5494ae076fbaeb38f2d63f8b3b09b8d4fd6..8a0211b4450779c46b90b04dfe3bdb7e7bdd23c1 100644
--- a/opentech/static_src/src/sass/apply/components/_rich-text.scss
+++ b/opentech/static_src/src/sass/apply/components/_rich-text.scss
@@ -33,6 +33,11 @@
     ul {
         padding-left: 20px;
         list-style: outside disc;
+
+        &.remove-list-style {
+            padding: 0;
+            list-style: none;
+        }
     }
 
     ol {
diff --git a/opentech/static_src/src/sass/apply/components/_round-block.scss b/opentech/static_src/src/sass/apply/components/_round-block.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3e5e49227cc55351e3023364c03762adb5ff436e
--- /dev/null
+++ b/opentech/static_src/src/sass/apply/components/_round-block.scss
@@ -0,0 +1,90 @@
+.round-block {
+    $root: &;
+
+    p {
+        font-size: 14px;
+    }
+
+    &__item {
+        align-items: center;
+        background-color: $color--white;
+        border: 1px solid $color--light-mid-grey;
+        border-bottom: 0;
+        padding: 25px;
+        transition: background-color $quick-transition;
+        min-height: 80px;
+
+        &:last-child {
+            border-bottom: 1px solid $color--light-mid-grey;
+        }
+
+        @include media-query(tablet-landscape) {
+            display: flex;
+
+            &:hover {
+                background-color: $color--light-grey;
+                border-right: 1px solid $color--light-grey;
+                border-left: 1px solid $color--light-grey;
+            }
+
+            // item spacing
+            > * {
+                margin: 0 30px 0 0;
+                flex-basis: 200px;
+            }
+        }
+
+        &--more {
+            padding: 20px 25px;
+            justify-content: center;
+            border-bottom: 1px solid $color--light-mid-grey;
+            min-height: auto;
+
+            &:hover {
+                background-color: $color--white;
+            }
+
+            // show more link
+            a {
+                margin: 0;
+                flex-basis: auto;
+                font-weight: $weight--semibold;
+            }
+        }
+    }
+
+    &__view {
+        margin: 0 0 0 auto;
+        transition: color $quick-transition;
+        font-weight: $weight--bold;
+        text-transform: uppercase;
+
+        @include media-query(tablet-landscape) {
+            color: transparent;
+            flex-basis: auto;
+            pointer-events: none;
+        }
+
+        &:focus,
+        #{$root}__item:hover & {
+            color: $color--primary;
+            pointer-events: all;
+        }
+    }
+
+    &__date,
+    &__determination {
+        color: $color--primary;
+    }
+
+    &__title {
+        font-weight: $weight--semibold;
+    }
+
+    &__not-found {
+        margin: 0;
+        padding: 20px;
+        background-color: $color--white;
+        border: 1px solid $color--light-mid-grey;
+    }
+}
diff --git a/opentech/static_src/src/sass/apply/components/_section.scss b/opentech/static_src/src/sass/apply/components/_section.scss
index 4b7d3979b2b25d4725b21bb407eaec2334a63710..c7142f198c31cafdc2a42addce47023a00251b28 100644
--- a/opentech/static_src/src/sass/apply/components/_section.scss
+++ b/opentech/static_src/src/sass/apply/components/_section.scss
@@ -8,4 +8,15 @@
             margin-bottom: 0;
         }
     }
+
+    &--with-options {
+        display: flex;
+        flex-direction: column;
+
+        @include media-query(small-tablet) {
+            flex-direction: row;
+            justify-content: space-between;
+            align-items: center;
+        }
+    }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_select2.scss b/opentech/static_src/src/sass/apply/components/_select2.scss
index 54147955936b9ec77cc96fd6bab97db832395664..dff4cdb83d084a81fd0bb1c4f5c18685167da01c 100644
--- a/opentech/static_src/src/sass/apply/components/_select2.scss
+++ b/opentech/static_src/src/sass/apply/components/_select2.scss
@@ -1,3 +1,5 @@
+$dropdown-height: 45px;
+
 .select2 {
     &-container {
         z-index: 99995; // to override any modals
@@ -8,7 +10,7 @@
         width: 100% !important; // sass-lint:disable-line no-important
 
         .select2-selection--single {
-            height: 55px;
+            height: $dropdown-height;
             border: 1px solid $color--mid-grey;
             border-radius: 0;
 
@@ -18,27 +20,22 @@
             }
 
             .select2-selection__clear {
-                position: absolute;
-                right: 35px;
                 display: none;
-                float: none;
-
-                @include media-query(small-tablet) {
-                    display: block;
-                }
             }
 
             .select2-selection__rendered {
                 padding-left: 15px;
-                line-height: 55px;
+                padding-right: 30px;
+                line-height: $dropdown-height;
             }
 
             .select2-selection__arrow {
                 right: 15px;
-                height: 53px;
+                height: $dropdown-height;
                 pointer-events: none;
                 background: url('./../../images/dropdown.svg') transparent no-repeat 95% center;
                 background-size: 8px;
+                width: 8px;
 
                 b[role='presentation'] {
                     display: none;
@@ -90,7 +87,7 @@
             padding: 6px;
 
             &::before {
-                width: 20px;
+                min-width: 20px;
                 height: 20px;
                 margin-right: 10px;
                 background: $color--white;
diff --git a/opentech/static_src/src/sass/apply/components/_table.scss b/opentech/static_src/src/sass/apply/components/_table.scss
index 2ff8ebb0e69bf1684e5274926cd8cd39a6e150aa..5bb173ed3f425c1ca9a4f557d5b2414287e5e4b6 100644
--- a/opentech/static_src/src/sass/apply/components/_table.scss
+++ b/opentech/static_src/src/sass/apply/components/_table.scss
@@ -1,6 +1,4 @@
-// also in _all-submissions.scss
-$table-breakpoint: 'tablet-landscape';
-
+// base table styles - specific ones in their own scss partial
 table {
     width: 100%;
     background-color: $color--white;
@@ -15,7 +13,7 @@ table {
         text-align: left;
 
         a {
-            color: $color--mid-dark-grey;
+            color: $color--black-60;
             transition: color .25s ease-out;
         }
     }
@@ -78,6 +76,12 @@ table {
                     }
                 }
             }
+
+            &.title {
+                a {
+                    font-weight: $weight--bold;
+                }
+            }
         }
     }
 
@@ -88,5 +92,9 @@ table {
         @include media-query($table-breakpoint) {
             padding: 15px 10px;
         }
+
+        &.title {
+            padding-left: 20px;
+        }
     }
 }
diff --git a/opentech/static_src/src/sass/apply/components/_tabs.scss b/opentech/static_src/src/sass/apply/components/_tabs.scss
index 7bfc204205a2a8159a3cbd5bcfa792d5c0004a31..ca285d185d6256f6d2e6ef6db1bee4c6557083f5 100644
--- a/opentech/static_src/src/sass/apply/components/_tabs.scss
+++ b/opentech/static_src/src/sass/apply/components/_tabs.scss
@@ -11,11 +11,12 @@
         &--current {
             display: inherit;
         }
-
     }
 }
 
 .tab__item {
+    $root: &;
+
     @include responsive-font-sizes(12px, 15px);
     position: relative;
     padding: 10px;
@@ -39,6 +40,32 @@
         color: $color--light-blue;
     }
 
+    &--alt {
+        font-size: map-get($font-sizes, zeta);
+        font-weight: $weight--semibold;
+        padding: 20px 10px;
+        text-transform: none;
+        display: inline-block;
+        margin-right: 20px;
+        border-bottom: 3px solid transparent;
+        color: $color--mid-dark-grey;
+        width: auto;
+
+        &:hover {
+            color: $color--default;
+        }
+
+        &#{$root}--active {
+            background-color: transparent;
+            border-bottom: 3px solid $color--primary;
+
+            &:hover {
+                color: $color--default;
+                background-color: transparent;
+            }
+        }
+    }
+
     &--active {
         color: $color--default;
         cursor: default;
diff --git a/opentech/static_src/src/sass/apply/components/_wrapper.scss b/opentech/static_src/src/sass/apply/components/_wrapper.scss
index cf14c2fe9e3c99c34137f3c664e107db9a940445..1d4ac18c0817957a345fd68d67e2b977ca37f3b0 100644
--- a/opentech/static_src/src/sass/apply/components/_wrapper.scss
+++ b/opentech/static_src/src/sass/apply/components/_wrapper.scss
@@ -265,4 +265,18 @@
     &--reviews-table {
         overflow-x: scroll;
     }
+
+    &--table-actions {
+        margin-bottom: 20px;
+
+        @include media-query(tablet-portrait) {
+            display: flex;
+            justify-content: space-between;
+
+        }
+
+        @include media-query(tablet-landscape) {
+            justify-content: flex-end;
+        }
+    }
 }
diff --git a/opentech/static_src/src/sass/apply/main.scss b/opentech/static_src/src/sass/apply/main.scss
index 745f50807ad3b43d597b5a7f82021f9bec2de050..4423f6ed552181b4708da92017bba897de5f1aa7 100644
--- a/opentech/static_src/src/sass/apply/main.scss
+++ b/opentech/static_src/src/sass/apply/main.scss
@@ -8,7 +8,8 @@
 @import 'base/typography';
 
 // Components
-@import 'components/all-submissions';
+@import 'components/all-submissions-table';
+@import 'components/all-rounds-table';
 @import 'components/admin-bar';
 @import 'components/activity-feed';
 @import 'components/comment';
@@ -37,6 +38,7 @@
 @import 'components/reviews-list';
 @import 'components/reviews-summary';
 @import 'components/reviews-sidebar';
+@import 'components/round-block';
 @import 'components/select2';
 @import 'components/submission-meta';
 @import 'components/revision';
diff --git a/opentech/static_src/src/sass/public/abstracts/_variables.scss b/opentech/static_src/src/sass/public/abstracts/_variables.scss
index 8f6c7113797a6ed556b4e59ef7446e7f88156958..e501e189b0d40067423ab61d8e127718ec3e15f5 100644
--- a/opentech/static_src/src/sass/public/abstracts/_variables.scss
+++ b/opentech/static_src/src/sass/public/abstracts/_variables.scss
@@ -92,12 +92,15 @@ $breakpoints: (
     'tablet-portrait'   '(min-width: 768px)',
     'tablet-landscape'  '(min-width: 1024px)',
     'desktop'           '(min-width: 1320px)',
-    'deskop-wide'       '(min-width: 2556px)'
+    'desktop-wide'      '(min-width: 2556px)'
 );
 
 // Transition
 $transition: .25s ease-out;
 $quick-transition: .15s ease;
 
+// Delays
+$base-delay: 30ms;
+
 // Spacing
 $mobile-gutter: 20px;
diff --git a/opentech/templates/base.html b/opentech/templates/base.html
index 94e1cd306d2ef3fa48167831508a0af03cccee3a..0844af725b963c8d288c791f1eeea958e0afb73d 100644
--- a/opentech/templates/base.html
+++ b/opentech/templates/base.html
@@ -129,7 +129,7 @@
                 </div>
 
                 <div class="header__search">
-                    <form action="{% url 'search' %}" method="get" role="search" class="form form--header-search-desktop">
+                    <form action="{{ PUBLIC_SITE.root_url }}{% url 'search' %}" method="get" role="search" class="form form--header-search-desktop">
                         <button class="button" type="submit" aria-label="Search">
                             <svg class="icon icon--magnifying-glass icon--search"><use xlink:href="#magnifying-glass"></use></svg>
                         </button>
diff --git a/opentech/urls.py b/opentech/urls.py
index 8cb2fe3067cbc3bd1c7e042adb4d2243ae8c6b07..e6845757630e342d14af0be4b2e95fdb6cd03a13 100644
--- a/opentech/urls.py
+++ b/opentech/urls.py
@@ -14,14 +14,27 @@ from opentech.public import urls as public_urls
 from opentech.apply.users.urls import public_urlpatterns as user_urls
 
 
+def apply_cache_control(*patterns):
+    # Cache-control
+    cache_length = getattr(settings, 'CACHE_CONTROL_MAX_AGE', None)
+
+    if cache_length:
+        patterns = decorate_urlpatterns(
+            patterns,
+            cache_control(max_age=cache_length)
+        )
+
+    return list(patterns)
+
+
 urlpatterns = [
     path('django-admin/', admin.site.urls),
     path('admin/', include(wagtailadmin_urls)),
 
     path('documents/', include(wagtaildocs_urls)),
     path('sitemap.xml', sitemap),
-    path('', include(public_urls)),
     path('', include((user_urls, 'users_public'))),
+    path('', include(public_urls)),
     path('', include('social_django.urls', namespace='social')),
     path('tinymce/', include('tinymce.urls')),
     path('select2/', include('django_select2.urls')),
@@ -52,18 +65,14 @@ urlpatterns += [
     path('', include(wagtail_urls)),
 ]
 
+urlpatterns = apply_cache_control(*urlpatterns)
 
-# Cache-control
-cache_length = getattr(settings, 'CACHE_CONTROL_MAX_AGE', None)
-
-if cache_length:
-    urlpatterns = decorate_urlpatterns(
-        urlpatterns,
-        cache_control(max_age=cache_length)
-    )
 
 if settings.DEBUG and settings.DEBUGTOOLBAR:
     import debug_toolbar
     urlpatterns = [
         path('__debug__/', include(debug_toolbar.urls)),
     ] + urlpatterns
+
+
+base_urlpatterns = [*urlpatterns]
diff --git a/package-lock.json b/package-lock.json
index beb4fa32aade77e10ca01e4e27c1ac72dbe8c95a..c03d14147002a5f8545753a762f00216e4b07807 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
             "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
-            "dev": true,
             "requires": {
                 "@babel/highlight": "^7.0.0"
             }
@@ -17,7 +16,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.2.2.tgz",
             "integrity": "sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw==",
-            "dev": true,
             "requires": {
                 "@babel/code-frame": "^7.0.0",
                 "@babel/generator": "^7.2.2",
@@ -39,7 +37,6 @@
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
                     "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
-                    "dev": true,
                     "requires": {
                         "ms": "^2.1.1"
                     }
@@ -50,7 +47,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz",
             "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.2.2",
                 "jsesc": "^2.5.1",
@@ -63,7 +59,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
             "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -72,7 +67,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
             "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
-            "dev": true,
             "requires": {
                 "@babel/helper-explode-assignable-expression": "^7.1.0",
                 "@babel/types": "^7.0.0"
@@ -82,7 +76,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.0.0.tgz",
             "integrity": "sha512-ebJ2JM6NAKW0fQEqN8hOLxK84RbRz9OkUhGS/Xd5u56ejMfVbayJ4+LykERZCOUM6faa6Fp3SZNX3fcT16MKHw==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0",
                 "esutils": "^2.0.0"
@@ -92,7 +85,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz",
             "integrity": "sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-hoist-variables": "^7.0.0",
                 "@babel/traverse": "^7.1.0",
@@ -116,7 +108,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz",
             "integrity": "sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-function-name": "^7.1.0",
                 "@babel/types": "^7.0.0",
@@ -127,7 +118,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
             "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
-            "dev": true,
             "requires": {
                 "@babel/traverse": "^7.1.0",
                 "@babel/types": "^7.0.0"
@@ -137,7 +127,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
             "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-get-function-arity": "^7.0.0",
                 "@babel/template": "^7.1.0",
@@ -148,7 +137,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
             "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -157,7 +145,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz",
             "integrity": "sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -166,7 +153,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz",
             "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -175,7 +161,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
             "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -184,7 +169,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz",
             "integrity": "sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-imports": "^7.0.0",
                 "@babel/helper-simple-access": "^7.1.0",
@@ -198,7 +182,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
             "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -206,14 +189,12 @@
         "@babel/helper-plugin-utils": {
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
-            "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
-            "dev": true
+            "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA=="
         },
         "@babel/helper-regex": {
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0.tgz",
             "integrity": "sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==",
-            "dev": true,
             "requires": {
                 "lodash": "^4.17.10"
             }
@@ -222,7 +203,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
             "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.0.0",
                 "@babel/helper-wrap-function": "^7.1.0",
@@ -235,7 +215,6 @@
             "version": "7.2.3",
             "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz",
             "integrity": "sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-member-expression-to-functions": "^7.0.0",
                 "@babel/helper-optimise-call-expression": "^7.0.0",
@@ -247,7 +226,6 @@
             "version": "7.1.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
             "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
-            "dev": true,
             "requires": {
                 "@babel/template": "^7.1.0",
                 "@babel/types": "^7.0.0"
@@ -257,7 +235,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz",
             "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==",
-            "dev": true,
             "requires": {
                 "@babel/types": "^7.0.0"
             }
@@ -266,7 +243,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
             "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-function-name": "^7.1.0",
                 "@babel/template": "^7.1.0",
@@ -278,7 +254,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz",
             "integrity": "sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==",
-            "dev": true,
             "requires": {
                 "@babel/template": "^7.1.2",
                 "@babel/traverse": "^7.1.5",
@@ -289,7 +264,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
             "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
-            "dev": true,
             "requires": {
                 "chalk": "^2.0.0",
                 "esutils": "^2.0.2",
@@ -299,14 +273,12 @@
         "@babel/parser": {
             "version": "7.2.3",
             "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz",
-            "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==",
-            "dev": true
+            "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA=="
         },
         "@babel/plugin-proposal-async-generator-functions": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
             "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-remap-async-to-generator": "^7.1.0",
@@ -327,7 +299,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
             "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-syntax-json-strings": "^7.2.0"
@@ -337,7 +308,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz",
             "integrity": "sha512-1L5mWLSvR76XYUQJXkd/EEQgjq8HHRP6lQuZTTg0VA4tTGPpGemmCdAfQIz1rzEuWAm+ecP8PyyEm30jC1eQCg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
@@ -347,7 +317,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
             "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
@@ -357,7 +326,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz",
             "integrity": "sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-regex": "^7.0.0",
@@ -368,7 +336,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
             "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -377,7 +344,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
             "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -386,7 +352,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz",
             "integrity": "sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -395,7 +360,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
             "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -404,7 +368,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
             "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -413,7 +376,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
             "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -422,7 +384,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz",
             "integrity": "sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-imports": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0",
@@ -433,7 +394,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
             "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -442,7 +402,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz",
             "integrity": "sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "lodash": "^4.17.10"
@@ -452,7 +411,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz",
             "integrity": "sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.0.0",
                 "@babel/helper-define-map": "^7.1.0",
@@ -468,7 +426,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
             "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -477,7 +434,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz",
             "integrity": "sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -486,7 +442,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz",
             "integrity": "sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-regex": "^7.0.0",
@@ -497,7 +452,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz",
             "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -506,7 +460,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
             "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
-            "dev": true,
             "requires": {
                 "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -516,7 +469,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz",
             "integrity": "sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -525,7 +477,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz",
             "integrity": "sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-function-name": "^7.1.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -535,7 +486,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
             "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -544,7 +494,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz",
             "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-transforms": "^7.1.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -554,7 +503,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz",
             "integrity": "sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-transforms": "^7.1.0",
                 "@babel/helper-plugin-utils": "^7.0.0",
@@ -565,7 +513,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz",
             "integrity": "sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ==",
-            "dev": true,
             "requires": {
                 "@babel/helper-hoist-variables": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -575,7 +522,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
             "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-transforms": "^7.1.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -585,7 +531,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz",
             "integrity": "sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -594,7 +539,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz",
             "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-replace-supers": "^7.1.0"
@@ -604,18 +548,25 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz",
             "integrity": "sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-call-delegate": "^7.1.0",
                 "@babel/helper-get-function-arity": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
         },
+        "@babel/plugin-transform-react-constant-elements": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.2.0.tgz",
+            "integrity": "sha512-YYQFg6giRFMsZPKUM9v+VcHOdfSQdz9jHCx3akAi3UYgyjndmdYGSXylQ/V+HswQt4fL8IklchD9HTsaOCrWQQ==",
+            "requires": {
+                "@babel/helper-annotate-as-pure": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
         "@babel/plugin-transform-react-display-name": {
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz",
             "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -624,7 +575,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.2.0.tgz",
             "integrity": "sha512-h/fZRel5wAfCqcKgq3OhbmYaReo7KkoJBpt8XnvpS7wqaNMqtw5xhxutzcm35iMUWucfAdT/nvGTsWln0JTg2Q==",
-            "dev": true,
             "requires": {
                 "@babel/helper-builder-react-jsx": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0",
@@ -635,7 +585,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.2.0.tgz",
             "integrity": "sha512-v6S5L/myicZEy+jr6ielB0OR8h+EH/1QFx/YJ7c7Ua+7lqsjj/vW6fD5FR9hB/6y7mGbfT4vAURn3xqBxsUcdg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-syntax-jsx": "^7.2.0"
@@ -645,7 +594,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.2.0.tgz",
             "integrity": "sha512-A32OkKTp4i5U6aE88GwwcuV4HAprUgHcTq0sSafLxjr6AW0QahrCRCjxogkbbcdtpbXkuTOlgpjophCxb6sh5g==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-syntax-jsx": "^7.2.0"
@@ -655,7 +603,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz",
             "integrity": "sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==",
-            "dev": true,
             "requires": {
                 "regenerator-transform": "^0.13.3"
             }
@@ -664,7 +611,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
             "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -673,7 +619,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
             "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -682,7 +627,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
             "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-regex": "^7.0.0"
@@ -692,7 +636,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz",
             "integrity": "sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg==",
-            "dev": true,
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0"
@@ -702,7 +645,6 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
             "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0"
             }
@@ -711,18 +653,25 @@
             "version": "7.2.0",
             "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz",
             "integrity": "sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/helper-regex": "^7.0.0",
                 "regexpu-core": "^4.1.3"
             }
         },
+        "@babel/polyfill": {
+            "version": "7.2.5",
+            "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.2.5.tgz",
+            "integrity": "sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug==",
+            "requires": {
+                "core-js": "^2.5.7",
+                "regenerator-runtime": "^0.12.0"
+            }
+        },
         "@babel/preset-env": {
             "version": "7.2.3",
             "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.2.3.tgz",
             "integrity": "sha512-AuHzW7a9rbv5WXmvGaPX7wADxFkZIqKlbBh1dmZUQp4iwiPpkE/Qnrji6SC4UQCQzvWY/cpHET29eUhXS9cLPw==",
-            "dev": true,
             "requires": {
                 "@babel/helper-module-imports": "^7.0.0",
                 "@babel/helper-plugin-utils": "^7.0.0",
@@ -771,7 +720,6 @@
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz",
             "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==",
-            "dev": true,
             "requires": {
                 "@babel/helper-plugin-utils": "^7.0.0",
                 "@babel/plugin-transform-react-display-name": "^7.0.0",
@@ -780,11 +728,18 @@
                 "@babel/plugin-transform-react-jsx-source": "^7.0.0"
             }
         },
+        "@babel/runtime": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
+            "integrity": "sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg==",
+            "requires": {
+                "regenerator-runtime": "^0.12.0"
+            }
+        },
         "@babel/template": {
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz",
             "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==",
-            "dev": true,
             "requires": {
                 "@babel/code-frame": "^7.0.0",
                 "@babel/parser": "^7.2.2",
@@ -795,7 +750,6 @@
             "version": "7.2.3",
             "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz",
             "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==",
-            "dev": true,
             "requires": {
                 "@babel/code-frame": "^7.0.0",
                 "@babel/generator": "^7.2.2",
@@ -812,7 +766,6 @@
                     "version": "4.1.0",
                     "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
                     "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
-                    "dev": true,
                     "requires": {
                         "ms": "^2.1.1"
                     }
@@ -823,7 +776,6 @@
             "version": "7.2.2",
             "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz",
             "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==",
-            "dev": true,
             "requires": {
                 "esutils": "^2.0.2",
                 "lodash": "^4.17.10",
@@ -861,6 +813,158 @@
                 "through2": "^2.0.3"
             }
         },
+        "@svgr/babel-plugin-add-jsx-attribute": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.0.0.tgz",
+            "integrity": "sha512-PDvHV2WhSGCSExp+eIMEKxYd1Q0SBvXLb4gAOXbdh0dswHFFgXWzxGjCmx5aln4qGrhkuN81khzYzR/44DYaMA=="
+        },
+        "@svgr/babel-plugin-remove-jsx-attribute": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.0.3.tgz",
+            "integrity": "sha512-fpG7AzzJxz1tc8ITYS1jCAt1cq4ydK2R+sx//BMTJgvOjfk91M5GiqFolP8aYTzLcum92IGNAVFS3zEcucOQEA=="
+        },
+        "@svgr/babel-plugin-remove-jsx-empty-expression": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.0.0.tgz",
+            "integrity": "sha512-nBGVl6LzXTdk1c6w3rMWcjq3mYGz+syWc5b3CdqAiEeY/nswYDoW/cnGUKKC8ofD6/LaG+G/IUnfv3jKoHz43A=="
+        },
+        "@svgr/babel-plugin-replace-jsx-attribute-value": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.0.0.tgz",
+            "integrity": "sha512-ejQqpTfORy6TT5w1x/2IQkscgfbtNFjitcFDu63GRz7qfhVTYhMdiJvJ1+Aw9hmv9bO4tXThGQDr1IF5lIvgew=="
+        },
+        "@svgr/babel-plugin-svg-dynamic-title": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.0.0.tgz",
+            "integrity": "sha512-OE6GT9WRKWqd0Dk6NJ5TYXTF5OxAyn74+c/D+gTLbCXnK2A0luEXuwMbe5zR5Px4A/jow2OeEBboTENl4vtuQg=="
+        },
+        "@svgr/babel-plugin-svg-em-dimensions": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.0.0.tgz",
+            "integrity": "sha512-QeDRGHXfjYEBTXxV0TsjWmepsL9Up5BOOlMFD557x2JrSiVGUn2myNxHIrHiVW0+nnWnaDcrkjg/jUvbJ5nKCg=="
+        },
+        "@svgr/babel-plugin-transform-react-native-svg": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.0.0.tgz",
+            "integrity": "sha512-c6eE6ovs14k6dmHKoy26h7iRFhjWNnwYVrDWIPfouVm/gcLIeMw/ME4i91O5LEfaDHs6kTRCcVpbAVbNULZOtw=="
+        },
+        "@svgr/babel-plugin-transform-svg-component": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.1.0.tgz",
+            "integrity": "sha512-uulxdx2p3nrM2BkrtADQHK8IhEzCxdUILfC/ddvFC8tlFWuKiA3ych8C6q0ulyQHq34/3hzz+3rmUbhWF9redg=="
+        },
+        "@svgr/babel-preset": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.1.0.tgz",
+            "integrity": "sha512-Nat5aJ3VO3LE8KfMyIbd3sGWnaWPiFCeWIdEV+lalga0To/tpmzsnPDdnrR9fNYhvSSLJbwhU/lrLYt9wXY0ZQ==",
+            "requires": {
+                "@svgr/babel-plugin-add-jsx-attribute": "^4.0.0",
+                "@svgr/babel-plugin-remove-jsx-attribute": "^4.0.3",
+                "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.0.0",
+                "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.0.0",
+                "@svgr/babel-plugin-svg-dynamic-title": "^4.0.0",
+                "@svgr/babel-plugin-svg-em-dimensions": "^4.0.0",
+                "@svgr/babel-plugin-transform-react-native-svg": "^4.0.0",
+                "@svgr/babel-plugin-transform-svg-component": "^4.1.0"
+            }
+        },
+        "@svgr/core": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.1.0.tgz",
+            "integrity": "sha512-ahv3lvOKuUAcs0KbQ4Jr5fT5pGHhye4ew8jZVS4lw8IQdWrbG/o3rkpgxCPREBk7PShmEoGQpteeXVwp2yExuQ==",
+            "requires": {
+                "@svgr/plugin-jsx": "^4.1.0",
+                "camelcase": "^5.0.0",
+                "cosmiconfig": "^5.0.7"
+            },
+            "dependencies": {
+                "camelcase": {
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
+                    "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA=="
+                }
+            }
+        },
+        "@svgr/hast-util-to-babel-ast": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.1.0.tgz",
+            "integrity": "sha512-tdkEZHmigYYiVhIEzycAMKN5aUSpddUnjr6v7bPwaNTFuSyqGUrpCg1JlIGi7PUaaJVHbn6whGQMGUpKOwT5nw==",
+            "requires": {
+                "@babel/types": "^7.1.6"
+            }
+        },
+        "@svgr/plugin-jsx": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.1.0.tgz",
+            "integrity": "sha512-xwu+9TGziuN7cu7p+vhCw2EJIfv8iDNMzn2dR0C7fBYc8q+SRtYTcg4Uyn8ZWh6DM+IZOlVrS02VEMT0FQzXSA==",
+            "requires": {
+                "@babel/core": "^7.1.6",
+                "@svgr/babel-preset": "^4.1.0",
+                "@svgr/hast-util-to-babel-ast": "^4.1.0",
+                "rehype-parse": "^6.0.0",
+                "unified": "^7.0.2",
+                "vfile": "^3.0.1"
+            }
+        },
+        "@svgr/plugin-svgo": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.0.3.tgz",
+            "integrity": "sha512-MgL1CrlxvNe+1tQjPUc2bIJtsdJOIE5arbHlPgW+XVWGjMZTUcyNNP8R7/IjM2Iyrc98UJY+WYiiWHrinnY9ZQ==",
+            "requires": {
+                "cosmiconfig": "^5.0.7",
+                "merge-deep": "^3.0.2",
+                "svgo": "^1.1.1"
+            }
+        },
+        "@svgr/webpack": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.1.0.tgz",
+            "integrity": "sha512-d09ehQWqLMywP/PT/5JvXwPskPK9QCXUjiSkAHehreB381qExXf5JFCBWhfEyNonRbkIneCeYM99w+Ud48YIQQ==",
+            "requires": {
+                "@babel/core": "^7.1.6",
+                "@babel/plugin-transform-react-constant-elements": "^7.0.0",
+                "@babel/preset-env": "^7.1.6",
+                "@babel/preset-react": "^7.0.0",
+                "@svgr/core": "^4.1.0",
+                "@svgr/plugin-jsx": "^4.1.0",
+                "@svgr/plugin-svgo": "^4.0.3",
+                "loader-utils": "^1.1.0"
+            }
+        },
+        "@types/node": {
+            "version": "10.12.18",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
+            "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
+        },
+        "@types/q": {
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz",
+            "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA=="
+        },
+        "@types/unist": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.2.tgz",
+            "integrity": "sha512-iHI60IbyfQilNubmxsq4zqSjdynlmc2Q/QvH9kjzg9+CCYVVzq1O6tc7VBzSygIwnmOt07w80IG6HDQvjv3Liw=="
+        },
+        "@types/vfile": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz",
+            "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==",
+            "requires": {
+                "@types/node": "*",
+                "@types/unist": "*",
+                "@types/vfile-message": "*"
+            }
+        },
+        "@types/vfile-message": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz",
+            "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==",
+            "requires": {
+                "@types/node": "*",
+                "@types/unist": "*"
+            }
+        },
         "@webassemblyjs/ast": {
             "version": "1.7.11",
             "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz",
@@ -1265,6 +1369,16 @@
             "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
             "dev": true
         },
+        "array-includes": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
+            "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.2",
+                "es-abstract": "^1.7.0"
+            }
+        },
         "array-initial": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz",
@@ -1452,6 +1566,32 @@
             "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
             "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
         },
+        "babel-eslint": {
+            "version": "10.0.1",
+            "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz",
+            "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "@babel/parser": "^7.0.0",
+                "@babel/traverse": "^7.0.0",
+                "@babel/types": "^7.0.0",
+                "eslint-scope": "3.7.1",
+                "eslint-visitor-keys": "^1.0.0"
+            },
+            "dependencies": {
+                "eslint-scope": {
+                    "version": "3.7.1",
+                    "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
+                    "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
+                    "dev": true,
+                    "requires": {
+                        "esrecurse": "^4.1.0",
+                        "estraverse": "^4.1.1"
+                    }
+                }
+            }
+        },
         "babel-loader": {
             "version": "8.0.4",
             "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.4.tgz",
@@ -1480,6 +1620,11 @@
                 "now-and-later": "^2.0.0"
             }
         },
+        "bail": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz",
+            "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg=="
+        },
         "balanced-match": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -1558,8 +1703,7 @@
         "big.js": {
             "version": "3.2.0",
             "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
-            "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
-            "dev": true
+            "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
         },
         "binary-extensions": {
             "version": "1.11.0",
@@ -1644,6 +1788,11 @@
                 "multicast-dns-service-types": "^1.1.0"
             }
         },
+        "boolbase": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+        },
         "brace-expansion": {
             "version": "1.1.11",
             "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1761,7 +1910,6 @@
             "version": "4.3.6",
             "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.6.tgz",
             "integrity": "sha512-kMGKs4BTzRWviZ8yru18xBpx+CyHG9eqgRbj9XbE3IMgtczf4aiA0Y1YCpVdvUieKGZ03kolSPXqTcscBCb9qw==",
-            "dev": true,
             "requires": {
                 "caniuse-lite": "^1.0.30000921",
                 "electron-to-chromium": "^1.3.92",
@@ -1885,6 +2033,21 @@
                 "unset-value": "^1.0.0"
             }
         },
+        "caller-callsite": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+            "requires": {
+                "callsites": "^2.0.0"
+            },
+            "dependencies": {
+                "callsites": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+                    "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA="
+                }
+            }
+        },
         "caller-path": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
@@ -1924,14 +2087,18 @@
         "caniuse-lite": {
             "version": "1.0.30000923",
             "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000923.tgz",
-            "integrity": "sha512-j5ur7eeluOFjjPUkydtXP4KFAsmH3XaQNch5tvWSO+dLHYt5PE+VgJZLWtbVOodfWij6m6zas28T4gB/cLYq1w==",
-            "dev": true
+            "integrity": "sha512-j5ur7eeluOFjjPUkydtXP4KFAsmH3XaQNch5tvWSO+dLHYt5PE+VgJZLWtbVOodfWij6m6zas28T4gB/cLYq1w=="
         },
         "caseless": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
             "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
         },
+        "ccount": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz",
+            "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw=="
+        },
         "chalk": {
             "version": "2.4.1",
             "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
@@ -2110,6 +2277,16 @@
             "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
             "dev": true
         },
+        "coa": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+            "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
+            "requires": {
+                "@types/q": "^1.5.1",
+                "chalk": "^2.4.1",
+                "q": "^1.1.2"
+            }
+        },
         "code-point-at": {
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@@ -2152,6 +2329,11 @@
             "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
             "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg=="
         },
+        "colors": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+            "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
+        },
         "combined-stream": {
             "version": "1.0.7",
             "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
@@ -2160,6 +2342,14 @@
                 "delayed-stream": "~1.0.0"
             }
         },
+        "comma-separated-tokens": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.5.tgz",
+            "integrity": "sha512-Cg90/fcK93n0ecgYTAz1jaA3zvnQ0ExlmKY1rdbyHqAx6BHxwoJc+J7HDu0iuQ7ixEs1qaa+WyQ6oeuBpYP1iA==",
+            "requires": {
+                "trim": "0.0.1"
+            }
+        },
         "commander": {
             "version": "2.17.1",
             "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
@@ -2319,11 +2509,38 @@
                 "is-plain-object": "^2.0.1"
             }
         },
+        "core-js": {
+            "version": "2.6.2",
+            "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz",
+            "integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g=="
+        },
         "core-util-is": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
             "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
         },
+        "cosmiconfig": {
+            "version": "5.0.7",
+            "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz",
+            "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==",
+            "requires": {
+                "import-fresh": "^2.0.0",
+                "is-directory": "^0.3.1",
+                "js-yaml": "^3.9.0",
+                "parse-json": "^4.0.0"
+            },
+            "dependencies": {
+                "parse-json": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+                    "requires": {
+                        "error-ex": "^1.3.1",
+                        "json-parse-better-errors": "^1.0.1"
+                    }
+                }
+            }
+        },
         "create-ecdh": {
             "version": "4.0.3",
             "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -2466,6 +2683,22 @@
                 }
             }
         },
+        "css-select": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz",
+            "integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==",
+            "requires": {
+                "boolbase": "^1.0.0",
+                "css-what": "^2.1.2",
+                "domutils": "^1.7.0",
+                "nth-check": "^1.0.2"
+            }
+        },
+        "css-select-base-adapter": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+            "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
+        },
         "css-selector-tokenizer": {
             "version": "0.7.1",
             "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
@@ -2511,12 +2744,50 @@
                 }
             }
         },
+        "css-tree": {
+            "version": "1.0.0-alpha.28",
+            "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz",
+            "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==",
+            "requires": {
+                "mdn-data": "~1.1.0",
+                "source-map": "^0.5.3"
+            }
+        },
+        "css-url-regex": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz",
+            "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w="
+        },
+        "css-what": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz",
+            "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ=="
+        },
         "cssesc": {
             "version": "0.1.0",
             "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
             "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
             "dev": true
         },
+        "csso": {
+            "version": "3.5.1",
+            "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
+            "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==",
+            "requires": {
+                "css-tree": "1.0.0-alpha.29"
+            },
+            "dependencies": {
+                "css-tree": {
+                    "version": "1.0.0-alpha.29",
+                    "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
+                    "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==",
+                    "requires": {
+                        "mdn-data": "~1.1.0",
+                        "source-map": "^0.5.3"
+                    }
+                }
+            }
+        },
         "currently-unhandled": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -2583,6 +2854,11 @@
             "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
             "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
         },
+        "deep-diff": {
+            "version": "0.3.8",
+            "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz",
+            "integrity": "sha1-wB3mPvsO7JeYgB1Ax+Da4ltYLIQ="
+        },
         "deep-equal": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
@@ -2783,6 +3059,30 @@
                 "esutils": "^2.0.2"
             }
         },
+        "dom-helpers": {
+            "version": "3.4.0",
+            "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
+            "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
+            "requires": {
+                "@babel/runtime": "^7.1.2"
+            }
+        },
+        "dom-serializer": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
+            "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=",
+            "requires": {
+                "domelementtype": "~1.1.1",
+                "entities": "~1.1.1"
+            },
+            "dependencies": {
+                "domelementtype": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+                    "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
+                }
+            }
+        },
         "dom-walk": {
             "version": "0.1.1",
             "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
@@ -2795,6 +3095,20 @@
             "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
             "dev": true
         },
+        "domelementtype": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+            "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
+        },
+        "domutils": {
+            "version": "1.7.0",
+            "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
+            "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
+            "requires": {
+                "dom-serializer": "0",
+                "domelementtype": "1"
+            }
+        },
         "duplexer": {
             "version": "0.1.1",
             "resolved": "http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
@@ -2838,8 +3152,7 @@
         "electron-to-chromium": {
             "version": "1.3.95",
             "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.95.tgz",
-            "integrity": "sha512-0JZEDKOQAE05EO/4rk3vLAE+PYFI9OLCVLAS4QAq1y+Bb2y1N6MyQJz62ynzHN/y0Ka/nO5jVJcahbCEdfiXLQ==",
-            "dev": true
+            "integrity": "sha512-0JZEDKOQAE05EO/4rk3vLAE+PYFI9OLCVLAS4QAq1y+Bb2y1N6MyQJz62ynzHN/y0Ka/nO5jVJcahbCEdfiXLQ=="
         },
         "elliptic": {
             "version": "6.4.1",
@@ -2859,8 +3172,7 @@
         "emojis-list": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
-            "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
-            "dev": true
+            "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
         },
         "encodeurl": {
             "version": "1.0.2",
@@ -2887,6 +3199,11 @@
                 "tapable": "^1.0.0"
             }
         },
+        "entities": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+            "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
+        },
         "errno": {
             "version": "0.1.7",
             "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
@@ -2908,7 +3225,6 @@
             "version": "1.12.0",
             "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
             "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
-            "dev": true,
             "requires": {
                 "es-to-primitive": "^1.1.1",
                 "function-bind": "^1.1.1",
@@ -2921,7 +3237,6 @@
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
             "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
-            "dev": true,
             "requires": {
                 "is-callable": "^1.1.4",
                 "is-date-object": "^1.0.1",
@@ -3118,6 +3433,45 @@
                 }
             }
         },
+        "eslint-loader": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.1.1.tgz",
+            "integrity": "sha512-1GrJFfSevQdYpoDzx8mEE2TDWsb/zmFuY09l6hURg1AeFIKQOvZ+vH0UPjzmd1CZIbfTV5HUkMeBmFiDBkgIsQ==",
+            "dev": true,
+            "requires": {
+                "loader-fs-cache": "^1.0.0",
+                "loader-utils": "^1.0.2",
+                "object-assign": "^4.0.1",
+                "object-hash": "^1.1.4",
+                "rimraf": "^2.6.1"
+            }
+        },
+        "eslint-plugin-react": {
+            "version": "7.12.4",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz",
+            "integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==",
+            "dev": true,
+            "requires": {
+                "array-includes": "^3.0.3",
+                "doctrine": "^2.1.0",
+                "has": "^1.0.3",
+                "jsx-ast-utils": "^2.0.1",
+                "object.fromentries": "^2.0.0",
+                "prop-types": "^15.6.2",
+                "resolve": "^1.9.0"
+            },
+            "dependencies": {
+                "resolve": {
+                    "version": "1.9.0",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz",
+                    "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                }
+            }
+        },
         "eslint-scope": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz",
@@ -3182,8 +3536,7 @@
         "esutils": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
-            "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
-            "dev": true
+            "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
         },
         "etag": {
             "version": "1.8.1",
@@ -3903,9 +4256,9 @@
             "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
         },
         "fsevents": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
-            "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
+            "version": "1.2.7",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz",
+            "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==",
             "optional": true,
             "requires": {
                 "nan": "^2.9.2",
@@ -3914,25 +4267,21 @@
             "dependencies": {
                 "abbrev": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+                    "bundled": true,
                     "optional": true
                 },
                 "ansi-regex": {
                     "version": "2.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+                    "bundled": true
                 },
                 "aproba": {
                     "version": "1.2.0",
-                    "resolved": false,
-                    "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+                    "bundled": true,
                     "optional": true
                 },
                 "are-we-there-yet": {
-                    "version": "1.1.4",
-                    "resolved": false,
-                    "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
+                    "version": "1.1.5",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "delegates": "^1.0.0",
@@ -3941,76 +4290,64 @@
                 },
                 "balanced-match": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+                    "bundled": true
                 },
                 "brace-expansion": {
                     "version": "1.1.11",
-                    "resolved": false,
-                    "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+                    "bundled": true,
                     "requires": {
                         "balanced-match": "^1.0.0",
                         "concat-map": "0.0.1"
                     }
                 },
                 "chownr": {
-                    "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=",
+                    "version": "1.1.1",
+                    "bundled": true,
                     "optional": true
                 },
                 "code-point-at": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+                    "bundled": true
                 },
                 "concat-map": {
                     "version": "0.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+                    "bundled": true
                 },
                 "console-control-strings": {
                     "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+                    "bundled": true
                 },
                 "core-util-is": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+                    "bundled": true,
                     "optional": true
                 },
                 "debug": {
                     "version": "2.6.9",
-                    "resolved": false,
-                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "ms": "2.0.0"
                     }
                 },
                 "deep-extend": {
-                    "version": "0.5.1",
-                    "resolved": false,
-                    "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
+                    "version": "0.6.0",
+                    "bundled": true,
                     "optional": true
                 },
                 "delegates": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+                    "bundled": true,
                     "optional": true
                 },
                 "detect-libc": {
                     "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
+                    "bundled": true,
                     "optional": true
                 },
                 "fs-minipass": {
                     "version": "1.2.5",
-                    "resolved": false,
-                    "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "minipass": "^2.2.1"
@@ -4018,14 +4355,12 @@
                 },
                 "fs.realpath": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+                    "bundled": true,
                     "optional": true
                 },
                 "gauge": {
                     "version": "2.7.4",
-                    "resolved": false,
-                    "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "aproba": "^1.0.3",
@@ -4039,9 +4374,8 @@
                     }
                 },
                 "glob": {
-                    "version": "7.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+                    "version": "7.1.3",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "fs.realpath": "^1.0.0",
@@ -4054,23 +4388,20 @@
                 },
                 "has-unicode": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+                    "bundled": true,
                     "optional": true
                 },
                 "iconv-lite": {
-                    "version": "0.4.21",
-                    "resolved": false,
-                    "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==",
+                    "version": "0.4.24",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
-                        "safer-buffer": "^2.1.0"
+                        "safer-buffer": ">= 2.1.2 < 3"
                     }
                 },
                 "ignore-walk": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "minimatch": "^3.0.4"
@@ -4078,8 +4409,7 @@
                 },
                 "inflight": {
                     "version": "1.0.6",
-                    "resolved": false,
-                    "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "once": "^1.3.0",
@@ -4088,55 +4418,47 @@
                 },
                 "inherits": {
                     "version": "2.0.3",
-                    "resolved": false,
-                    "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+                    "bundled": true
                 },
                 "ini": {
                     "version": "1.3.5",
-                    "resolved": false,
-                    "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+                    "bundled": true,
                     "optional": true
                 },
                 "is-fullwidth-code-point": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+                    "bundled": true,
                     "requires": {
                         "number-is-nan": "^1.0.0"
                     }
                 },
                 "isarray": {
                     "version": "1.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+                    "bundled": true,
                     "optional": true
                 },
                 "minimatch": {
                     "version": "3.0.4",
-                    "resolved": false,
-                    "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+                    "bundled": true,
                     "requires": {
                         "brace-expansion": "^1.1.7"
                     }
                 },
                 "minimist": {
                     "version": "0.0.8",
-                    "resolved": false,
-                    "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+                    "bundled": true
                 },
                 "minipass": {
-                    "version": "2.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
+                    "version": "2.3.5",
+                    "bundled": true,
                     "requires": {
-                        "safe-buffer": "^5.1.1",
+                        "safe-buffer": "^5.1.2",
                         "yallist": "^3.0.0"
                     }
                 },
                 "minizlib": {
-                    "version": "1.1.0",
-                    "resolved": false,
-                    "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==",
+                    "version": "1.2.1",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "minipass": "^2.2.1"
@@ -4144,22 +4466,19 @@
                 },
                 "mkdirp": {
                     "version": "0.5.1",
-                    "resolved": false,
-                    "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+                    "bundled": true,
                     "requires": {
                         "minimist": "0.0.8"
                     }
                 },
                 "ms": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                    "bundled": true,
                     "optional": true
                 },
                 "needle": {
-                    "version": "2.2.0",
-                    "resolved": false,
-                    "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==",
+                    "version": "2.2.4",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "debug": "^2.1.2",
@@ -4168,18 +4487,17 @@
                     }
                 },
                 "node-pre-gyp": {
-                    "version": "0.10.0",
-                    "resolved": false,
-                    "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==",
+                    "version": "0.10.3",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "detect-libc": "^1.0.2",
                         "mkdirp": "^0.5.1",
-                        "needle": "^2.2.0",
+                        "needle": "^2.2.1",
                         "nopt": "^4.0.1",
                         "npm-packlist": "^1.1.6",
                         "npmlog": "^4.0.2",
-                        "rc": "^1.1.7",
+                        "rc": "^1.2.7",
                         "rimraf": "^2.6.1",
                         "semver": "^5.3.0",
                         "tar": "^4"
@@ -4187,8 +4505,7 @@
                 },
                 "nopt": {
                     "version": "4.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "abbrev": "1",
@@ -4196,15 +4513,13 @@
                     }
                 },
                 "npm-bundled": {
-                    "version": "1.0.3",
-                    "resolved": false,
-                    "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==",
+                    "version": "1.0.5",
+                    "bundled": true,
                     "optional": true
                 },
                 "npm-packlist": {
-                    "version": "1.1.10",
-                    "resolved": false,
-                    "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==",
+                    "version": "1.2.0",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "ignore-walk": "^3.0.1",
@@ -4213,8 +4528,7 @@
                 },
                 "npmlog": {
                     "version": "4.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "are-we-there-yet": "~1.1.2",
@@ -4225,39 +4539,33 @@
                 },
                 "number-is-nan": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+                    "bundled": true
                 },
                 "object-assign": {
                     "version": "4.1.1",
-                    "resolved": false,
-                    "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+                    "bundled": true,
                     "optional": true
                 },
                 "once": {
                     "version": "1.4.0",
-                    "resolved": false,
-                    "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+                    "bundled": true,
                     "requires": {
                         "wrappy": "1"
                     }
                 },
                 "os-homedir": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+                    "bundled": true,
                     "optional": true
                 },
                 "os-tmpdir": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+                    "bundled": true,
                     "optional": true
                 },
                 "osenv": {
                     "version": "0.1.5",
-                    "resolved": false,
-                    "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "os-homedir": "^1.0.0",
@@ -4266,23 +4574,20 @@
                 },
                 "path-is-absolute": {
                     "version": "1.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+                    "bundled": true,
                     "optional": true
                 },
                 "process-nextick-args": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+                    "bundled": true,
                     "optional": true
                 },
                 "rc": {
-                    "version": "1.2.7",
-                    "resolved": false,
-                    "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==",
+                    "version": "1.2.8",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
-                        "deep-extend": "^0.5.1",
+                        "deep-extend": "^0.6.0",
                         "ini": "~1.3.0",
                         "minimist": "^1.2.0",
                         "strip-json-comments": "~2.0.1"
@@ -4290,16 +4595,14 @@
                     "dependencies": {
                         "minimist": {
                             "version": "1.2.0",
-                            "resolved": false,
-                            "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+                            "bundled": true,
                             "optional": true
                         }
                     }
                 },
                 "readable-stream": {
                     "version": "2.3.6",
-                    "resolved": false,
-                    "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "core-util-is": "~1.0.0",
@@ -4312,53 +4615,45 @@
                     }
                 },
                 "rimraf": {
-                    "version": "2.6.2",
-                    "resolved": false,
-                    "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+                    "version": "2.6.3",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
-                        "glob": "^7.0.5"
+                        "glob": "^7.1.3"
                     }
                 },
                 "safe-buffer": {
-                    "version": "5.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+                    "version": "5.1.2",
+                    "bundled": true
                 },
                 "safer-buffer": {
                     "version": "2.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+                    "bundled": true,
                     "optional": true
                 },
                 "sax": {
                     "version": "1.2.4",
-                    "resolved": false,
-                    "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+                    "bundled": true,
                     "optional": true
                 },
                 "semver": {
-                    "version": "5.5.0",
-                    "resolved": false,
-                    "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+                    "version": "5.6.0",
+                    "bundled": true,
                     "optional": true
                 },
                 "set-blocking": {
                     "version": "2.0.0",
-                    "resolved": false,
-                    "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+                    "bundled": true,
                     "optional": true
                 },
                 "signal-exit": {
                     "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+                    "bundled": true,
                     "optional": true
                 },
                 "string-width": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+                    "bundled": true,
                     "requires": {
                         "code-point-at": "^1.0.0",
                         "is-fullwidth-code-point": "^1.0.0",
@@ -4367,8 +4662,7 @@
                 },
                 "string_decoder": {
                     "version": "1.1.1",
-                    "resolved": false,
-                    "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
                         "safe-buffer": "~5.1.0"
@@ -4376,57 +4670,50 @@
                 },
                 "strip-ansi": {
                     "version": "3.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+                    "bundled": true,
                     "requires": {
                         "ansi-regex": "^2.0.0"
                     }
                 },
                 "strip-json-comments": {
                     "version": "2.0.1",
-                    "resolved": false,
-                    "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+                    "bundled": true,
                     "optional": true
                 },
                 "tar": {
-                    "version": "4.4.1",
-                    "resolved": false,
-                    "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==",
+                    "version": "4.4.8",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
-                        "chownr": "^1.0.1",
+                        "chownr": "^1.1.1",
                         "fs-minipass": "^1.2.5",
-                        "minipass": "^2.2.4",
-                        "minizlib": "^1.1.0",
+                        "minipass": "^2.3.4",
+                        "minizlib": "^1.1.1",
                         "mkdirp": "^0.5.0",
-                        "safe-buffer": "^5.1.1",
+                        "safe-buffer": "^5.1.2",
                         "yallist": "^3.0.2"
                     }
                 },
                 "util-deprecate": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+                    "bundled": true,
                     "optional": true
                 },
                 "wide-align": {
-                    "version": "1.1.2",
-                    "resolved": false,
-                    "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
+                    "version": "1.1.3",
+                    "bundled": true,
                     "optional": true,
                     "requires": {
-                        "string-width": "^1.0.2"
+                        "string-width": "^1.0.2 || 2"
                     }
                 },
                 "wrappy": {
                     "version": "1.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+                    "bundled": true
                 },
                 "yallist": {
-                    "version": "3.0.2",
-                    "resolved": false,
-                    "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k="
+                    "version": "3.0.3",
+                    "bundled": true
                 }
             }
         },
@@ -4663,8 +4950,7 @@
         "globals": {
             "version": "11.7.0",
             "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
-            "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==",
-            "dev": true
+            "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg=="
         },
         "globby": {
             "version": "6.1.0",
@@ -5198,7 +5484,6 @@
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
             "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
-            "dev": true,
             "requires": {
                 "function-bind": "^1.1.1"
             }
@@ -5283,6 +5568,34 @@
                 "minimalistic-assert": "^1.0.1"
             }
         },
+        "hast-util-from-parse5": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-5.0.0.tgz",
+            "integrity": "sha512-A7ev5OseS/J15214cvDdcI62uwovJO2PB60Xhnq7kaxvvQRFDEccuqbkrFXU03GPBGopdPqlpQBRqIcDS/Fjbg==",
+            "requires": {
+                "ccount": "^1.0.3",
+                "hastscript": "^5.0.0",
+                "property-information": "^5.0.0",
+                "web-namespaces": "^1.1.2",
+                "xtend": "^4.0.1"
+            }
+        },
+        "hast-util-parse-selector": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.1.tgz",
+            "integrity": "sha512-Xyh0v+nHmQvrOqop2Jqd8gOdyQtE8sIP9IQf7mlVDqp924W4w/8Liuguk2L2qei9hARnQSG2m+wAOCxM7npJVw=="
+        },
+        "hastscript": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-5.0.0.tgz",
+            "integrity": "sha512-xJtuJ8D42Xtq5yJrnDg/KAIxl2cXBXKoiIJwmWX9XMf8113qHTGl/Bf7jEsxmENJ4w6q4Tfl8s/Y6mEZo8x8qw==",
+            "requires": {
+                "comma-separated-tokens": "^1.0.0",
+                "hast-util-parse-selector": "^2.2.0",
+                "property-information": "^5.0.1",
+                "space-separated-tokens": "^1.0.0"
+            }
+        },
         "hmac-drbg": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -5436,6 +5749,30 @@
             "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
             "dev": true
         },
+        "import-fresh": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+            "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+            "requires": {
+                "caller-path": "^2.0.0",
+                "resolve-from": "^3.0.0"
+            },
+            "dependencies": {
+                "caller-path": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+                    "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+                    "requires": {
+                        "caller-callsite": "^2.0.0"
+                    }
+                },
+                "resolve-from": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+                    "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
+                }
+            }
+        },
         "import-local": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
@@ -5623,7 +5960,6 @@
             "version": "2.2.4",
             "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
             "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
-            "dev": true,
             "requires": {
                 "loose-envify": "^1.0.0"
             }
@@ -5707,8 +6043,7 @@
         "is-callable": {
             "version": "1.1.4",
             "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
-            "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
-            "dev": true
+            "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
         },
         "is-data-descriptor": {
             "version": "0.1.4",
@@ -5731,8 +6066,7 @@
         "is-date-object": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
-            "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
-            "dev": true
+            "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
         },
         "is-descriptor": {
             "version": "0.1.6",
@@ -5751,6 +6085,11 @@
                 }
             }
         },
+        "is-directory": {
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+            "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
+        },
         "is-dotfile": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
@@ -5861,6 +6200,11 @@
                 "path-is-inside": "^1.0.1"
             }
         },
+        "is-plain-obj": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+            "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4="
+        },
         "is-plain-object": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@@ -5895,7 +6239,6 @@
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
             "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
-            "dev": true,
             "requires": {
                 "has": "^1.0.1"
             }
@@ -5924,7 +6267,6 @@
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
             "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
-            "dev": true,
             "requires": {
                 "has-symbols": "^1.0.0"
             }
@@ -5991,8 +6333,7 @@
         "js-levenshtein": {
             "version": "1.1.4",
             "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.4.tgz",
-            "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==",
-            "dev": true
+            "integrity": "sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow=="
         },
         "js-tokens": {
             "version": "4.0.0",
@@ -6016,14 +6357,12 @@
         "jsesc": {
             "version": "2.5.2",
             "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-            "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-            "dev": true
+            "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
         },
         "json-parse-better-errors": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
-            "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
-            "dev": true
+            "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
         },
         "json-schema": {
             "version": "0.2.3",
@@ -6064,7 +6403,6 @@
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
             "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
-            "dev": true,
             "requires": {
                 "minimist": "^1.2.0"
             }
@@ -6100,6 +6438,15 @@
                 "verror": "1.10.0"
             }
         },
+        "jsx-ast-utils": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
+            "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
+            "dev": true,
+            "requires": {
+                "array-includes": "^3.0.3"
+            }
+        },
         "just-debounce": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz",
@@ -6131,6 +6478,11 @@
                 "es6-weak-map": "^2.0.1"
             }
         },
+        "lazy-cache": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+        },
         "lazystream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
@@ -6199,6 +6551,38 @@
                 }
             }
         },
+        "loader-fs-cache": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz",
+            "integrity": "sha1-VuC/CL2XCLJqdltoUJhAyN7J/bw=",
+            "dev": true,
+            "requires": {
+                "find-cache-dir": "^0.1.1",
+                "mkdirp": "0.5.1"
+            },
+            "dependencies": {
+                "find-cache-dir": {
+                    "version": "0.1.1",
+                    "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz",
+                    "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=",
+                    "dev": true,
+                    "requires": {
+                        "commondir": "^1.0.1",
+                        "mkdirp": "^0.5.1",
+                        "pkg-dir": "^1.0.0"
+                    }
+                },
+                "pkg-dir": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
+                    "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^1.0.0"
+                    }
+                }
+            }
+        },
         "loader-runner": {
             "version": "2.3.1",
             "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz",
@@ -6209,7 +6593,6 @@
             "version": "1.1.0",
             "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
             "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
-            "dev": true,
             "requires": {
                 "big.js": "^3.1.3",
                 "emojis-list": "^2.0.0",
@@ -6219,8 +6602,7 @@
                 "json5": {
                     "version": "0.5.1",
                     "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
-                    "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
-                    "dev": true
+                    "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
                 }
             }
         },
@@ -6247,6 +6629,11 @@
             "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
             "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
         },
+        "lodash._getnative": {
+            "version": "3.9.1",
+            "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
+            "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U="
+        },
         "lodash.assign": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
@@ -6428,6 +6815,11 @@
                 "safe-buffer": "^5.1.2"
             }
         },
+        "mdn-data": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
+            "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA=="
+        },
         "media-typer": {
             "version": "0.3.0",
             "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -6494,6 +6886,72 @@
             "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==",
             "dev": true
         },
+        "merge-deep": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz",
+            "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==",
+            "requires": {
+                "arr-union": "^3.1.0",
+                "clone-deep": "^0.2.4",
+                "kind-of": "^3.0.2"
+            },
+            "dependencies": {
+                "clone-deep": {
+                    "version": "0.2.4",
+                    "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz",
+                    "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=",
+                    "requires": {
+                        "for-own": "^0.1.3",
+                        "is-plain-object": "^2.0.1",
+                        "kind-of": "^3.0.2",
+                        "lazy-cache": "^1.0.3",
+                        "shallow-clone": "^0.1.2"
+                    }
+                },
+                "for-own": {
+                    "version": "0.1.5",
+                    "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+                    "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+                    "requires": {
+                        "for-in": "^1.0.1"
+                    }
+                },
+                "kind-of": {
+                    "version": "3.2.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "requires": {
+                        "is-buffer": "^1.1.5"
+                    }
+                },
+                "shallow-clone": {
+                    "version": "0.1.2",
+                    "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
+                    "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=",
+                    "requires": {
+                        "is-extendable": "^0.1.1",
+                        "kind-of": "^2.0.1",
+                        "lazy-cache": "^0.2.3",
+                        "mixin-object": "^2.0.1"
+                    },
+                    "dependencies": {
+                        "kind-of": {
+                            "version": "2.0.1",
+                            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz",
+                            "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=",
+                            "requires": {
+                                "is-buffer": "^1.0.2"
+                            }
+                        },
+                        "lazy-cache": {
+                            "version": "0.2.7",
+                            "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz",
+                            "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U="
+                        }
+                    }
+                }
+            }
+        },
         "merge-descriptors": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -6648,7 +7106,6 @@
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
             "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
-            "dev": true,
             "requires": {
                 "for-in": "^0.1.3",
                 "is-extendable": "^0.1.1"
@@ -6657,8 +7114,7 @@
                 "for-in": {
                     "version": "0.1.8",
                     "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
-                    "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=",
-                    "dev": true
+                    "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE="
                 }
             }
         },
@@ -6694,8 +7150,7 @@
         "ms": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-            "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-            "dev": true
+            "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
         },
         "multicast-dns": {
             "version": "6.2.3",
@@ -6843,7 +7298,6 @@
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.2.tgz",
             "integrity": "sha512-j1gEV/zX821yxdWp/1vBMN0pSUjuH9oGUdLCb4PfUko6ZW7KdRs3Z+QGGwDUhYtSpQvdVVyLd2V0YvLsmdg5jQ==",
-            "dev": true,
             "requires": {
                 "semver": "^5.3.0"
             }
@@ -6961,6 +7415,14 @@
                 "set-blocking": "~2.0.0"
             }
         },
+        "nth-check": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
+            "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
+            "requires": {
+                "boolbase": "~1.0.0"
+            }
+        },
         "number-is-nan": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
@@ -7004,6 +7466,12 @@
                 }
             }
         },
+        "object-hash": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz",
+            "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==",
+            "dev": true
+        },
         "object-keys": {
             "version": "1.0.12",
             "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
@@ -7039,11 +7507,22 @@
                 "isobject": "^3.0.0"
             }
         },
+        "object.fromentries": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
+            "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.2",
+                "es-abstract": "^1.11.0",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.1"
+            }
+        },
         "object.getownpropertydescriptors": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
             "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
-            "dev": true,
             "requires": {
                 "define-properties": "^1.1.2",
                 "es-abstract": "^1.5.1"
@@ -7094,6 +7573,17 @@
                 "make-iterator": "^1.0.0"
             }
         },
+        "object.values": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
+            "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
+            "requires": {
+                "define-properties": "^1.1.3",
+                "es-abstract": "^1.12.0",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.3"
+            }
+        },
         "obuf": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
@@ -7337,6 +7827,11 @@
             "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
             "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY="
         },
+        "parse5": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+            "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ=="
+        },
         "parseurl": {
             "version": "1.3.2",
             "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
@@ -7619,8 +8114,7 @@
         "private": {
             "version": "0.1.8",
             "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
-            "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
-            "dev": true
+            "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
         },
         "process": {
             "version": "0.11.10",
@@ -7654,6 +8148,14 @@
                 "object-assign": "^4.1.1"
             }
         },
+        "property-information": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.0.1.tgz",
+            "integrity": "sha512-nAtBDVeSwFM3Ot/YxT7s4NqZmqXI7lLzf46BThvotEtYf2uk2yH0ACYuWQkJ7gxKs49PPtKVY0UlDGkyN9aJlw==",
+            "requires": {
+                "xtend": "^4.0.1"
+            }
+        },
         "proxy-addr": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
@@ -7718,6 +8220,11 @@
             "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
             "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
         },
+        "q": {
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+            "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+        },
         "qs": {
             "version": "6.5.2",
             "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
@@ -7853,11 +8360,69 @@
                 }
             }
         },
+        "react-is": {
+            "version": "16.7.0",
+            "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.7.0.tgz",
+            "integrity": "sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g=="
+        },
         "react-lifecycles-compat": {
             "version": "3.0.4",
             "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
-            "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==",
-            "dev": true
+            "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+        },
+        "react-redux": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.0.tgz",
+            "integrity": "sha512-EmbC3uLl60pw2VqSSkj6HpZ6jTk12RMrwXMBdYtM6niq0MdEaRq9KYCwpJflkOZj349BLGQm1MI/JO1W96kLWQ==",
+            "requires": {
+                "@babel/runtime": "^7.2.0",
+                "hoist-non-react-statics": "^3.2.1",
+                "invariant": "^2.2.4",
+                "loose-envify": "^1.4.0",
+                "prop-types": "^15.6.2",
+                "react-is": "^16.6.3"
+            },
+            "dependencies": {
+                "hoist-non-react-statics": {
+                    "version": "3.2.1",
+                    "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.2.1.tgz",
+                    "integrity": "sha512-TFsu3TV3YLY+zFTZDrN8L2DTFanObwmBLpWvJs1qfUuEQ5bTAdFcwfx2T/bsCXfM9QHSLvjfP+nihEl0yvozxw==",
+                    "requires": {
+                        "react-is": "^16.3.2"
+                    }
+                }
+            }
+        },
+        "react-transition-group": {
+            "version": "2.5.3",
+            "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.5.3.tgz",
+            "integrity": "sha512-2DGFck6h99kLNr8pOFk+z4Soq3iISydwOFeeEVPjTN6+Y01CmvbWmnN02VuTWyFdnRtIDPe+wy2q6Ui8snBPZg==",
+            "requires": {
+                "dom-helpers": "^3.3.1",
+                "loose-envify": "^1.4.0",
+                "prop-types": "^15.6.2",
+                "react-lifecycles-compat": "^3.0.4"
+            }
+        },
+        "react-window-size-listener": {
+            "version": "1.2.3",
+            "resolved": "https://registry.npmjs.org/react-window-size-listener/-/react-window-size-listener-1.2.3.tgz",
+            "integrity": "sha512-95lyZTMBBqH0xuhBEP0LshEKlHVF+VHQO7UojfDYmyMoO9jriTAY9Ktr5p9ZF4yR8QKzWZBAUdOEndY/JuMmwA==",
+            "requires": {
+                "lodash.debounce": "^3.1.1",
+                "prop-types": "^15.6.0",
+                "randomatic": ">=3.0.0"
+            },
+            "dependencies": {
+                "lodash.debounce": {
+                    "version": "3.1.1",
+                    "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz",
+                    "integrity": "sha1-gSIRw3ipTMKdWqTjNGzwv846ffU=",
+                    "requires": {
+                        "lodash._getnative": "^3.0.0"
+                    }
+                }
+            }
         },
         "read-pkg": {
             "version": "1.1.0",
@@ -7945,26 +8510,56 @@
                 "strip-indent": "^1.0.1"
             }
         },
+        "redux": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz",
+            "integrity": "sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==",
+            "requires": {
+                "loose-envify": "^1.4.0",
+                "symbol-observable": "^1.2.0"
+            }
+        },
+        "redux-devtools-extension": {
+            "version": "2.13.7",
+            "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.7.tgz",
+            "integrity": "sha512-F2GlWMWxCTJGRjJ+GSZcGDcVAj6Pbf77FKb4C9S8eni5Eah6UBGNwxNj8K1MTtmItdZH1Wx+EvIifHN2KKcQrw==",
+            "dev": true
+        },
+        "redux-logger": {
+            "version": "3.0.6",
+            "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz",
+            "integrity": "sha1-91VZZvMJjzyIYExEnPC69XeCdL8=",
+            "requires": {
+                "deep-diff": "^0.3.5"
+            }
+        },
+        "redux-thunk": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz",
+            "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw=="
+        },
         "regenerate": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
-            "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
-            "dev": true
+            "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
         },
         "regenerate-unicode-properties": {
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz",
             "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==",
-            "dev": true,
             "requires": {
                 "regenerate": "^1.4.0"
             }
         },
+        "regenerator-runtime": {
+            "version": "0.12.1",
+            "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
+            "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
+        },
         "regenerator-transform": {
             "version": "0.13.3",
             "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.3.tgz",
             "integrity": "sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==",
-            "dev": true,
             "requires": {
                 "private": "^0.1.6"
             }
@@ -7996,7 +8591,6 @@
             "version": "4.4.0",
             "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz",
             "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==",
-            "dev": true,
             "requires": {
                 "regenerate": "^1.4.0",
                 "regenerate-unicode-properties": "^7.0.0",
@@ -8009,14 +8603,12 @@
         "regjsgen": {
             "version": "0.5.0",
             "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz",
-            "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==",
-            "dev": true
+            "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA=="
         },
         "regjsparser": {
             "version": "0.6.0",
             "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
             "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
-            "dev": true,
             "requires": {
                 "jsesc": "~0.5.0"
             },
@@ -8024,11 +8616,20 @@
                 "jsesc": {
                     "version": "0.5.0",
                     "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
-                    "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
-                    "dev": true
+                    "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
                 }
             }
         },
+        "rehype-parse": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-6.0.0.tgz",
+            "integrity": "sha512-V2OjMD0xcSt39G4uRdMTqDXXm6HwkUbLMDayYKA/d037j8/OtVSQ+tqKwYWOuyBeoCs/3clXRe30VUjeMDTBSA==",
+            "requires": {
+                "hast-util-from-parse5": "^5.0.0",
+                "parse5": "^5.0.0",
+                "xtend": "^4.0.1"
+            }
+        },
         "remove-bom-buffer": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
@@ -8139,6 +8740,11 @@
             "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
             "dev": true
         },
+        "reselect": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
+            "integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
+        },
         "resolve": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
@@ -8623,6 +9229,11 @@
                 "semver": "^5.5.0"
             }
         },
+        "sax": {
+            "version": "1.2.4",
+            "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+            "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+        },
         "scheduler": {
             "version": "0.12.0",
             "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.12.0.tgz",
@@ -9084,6 +9695,14 @@
             "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
             "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
         },
+        "space-separated-tokens": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.2.tgz",
+            "integrity": "sha512-G3jprCEw+xFEs0ORweLmblJ3XLymGGr6hxZYTYZjIlvDti9vOBUjRQa1Rzjt012aRrocKstHwdNi+F7HguPsEA==",
+            "requires": {
+                "trim": "0.0.1"
+            }
+        },
         "sparkles": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
@@ -9218,6 +9837,11 @@
                 "figgy-pudding": "^3.5.1"
             }
         },
+        "stable": {
+            "version": "0.1.8",
+            "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
+            "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w=="
+        },
         "stack-trace": {
             "version": "0.0.10",
             "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
@@ -9404,6 +10028,32 @@
                 "es6-symbol": "^3.1.1"
             }
         },
+        "svgo": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.1.1.tgz",
+            "integrity": "sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g==",
+            "requires": {
+                "coa": "~2.0.1",
+                "colors": "~1.1.2",
+                "css-select": "^2.0.0",
+                "css-select-base-adapter": "~0.1.0",
+                "css-tree": "1.0.0-alpha.28",
+                "css-url-regex": "^1.1.0",
+                "csso": "^3.5.0",
+                "js-yaml": "^3.12.0",
+                "mkdirp": "~0.5.1",
+                "object.values": "^1.0.4",
+                "sax": "~1.2.4",
+                "stable": "~0.1.6",
+                "unquote": "~1.1.1",
+                "util.promisify": "~1.0.0"
+            }
+        },
+        "symbol-observable": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+            "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
+        },
         "table": {
             "version": "4.0.3",
             "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz",
@@ -9701,8 +10351,7 @@
         "to-fast-properties": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-            "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-            "dev": true
+            "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
         },
         "to-object-path": {
             "version": "0.3.0",
@@ -9759,6 +10408,11 @@
                 "punycode": "^1.4.1"
             }
         },
+        "trim": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz",
+            "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
+        },
         "trim-newlines": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
@@ -9767,8 +10421,12 @@
         "trim-right": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
-            "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
-            "dev": true
+            "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
+        },
+        "trough": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.3.tgz",
+            "integrity": "sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw=="
         },
         "true-case-path": {
             "version": "1.0.3",
@@ -9872,14 +10530,12 @@
         "unicode-canonical-property-names-ecmascript": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
-            "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==",
-            "dev": true
+            "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ=="
         },
         "unicode-match-property-ecmascript": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
             "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
-            "dev": true,
             "requires": {
                 "unicode-canonical-property-names-ecmascript": "^1.0.4",
                 "unicode-property-aliases-ecmascript": "^1.0.4"
@@ -9888,14 +10544,27 @@
         "unicode-match-property-value-ecmascript": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz",
-            "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==",
-            "dev": true
+            "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ=="
         },
         "unicode-property-aliases-ecmascript": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz",
-            "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==",
-            "dev": true
+            "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg=="
+        },
+        "unified": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/unified/-/unified-7.1.0.tgz",
+            "integrity": "sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw==",
+            "requires": {
+                "@types/unist": "^2.0.0",
+                "@types/vfile": "^3.0.0",
+                "bail": "^1.0.0",
+                "extend": "^3.0.0",
+                "is-plain-obj": "^1.1.0",
+                "trough": "^1.0.0",
+                "vfile": "^3.0.0",
+                "x-is-string": "^0.1.0"
+            }
         },
         "union-value": {
             "version": "1.0.0",
@@ -9956,6 +10625,11 @@
                 "through2-filter": "^2.0.0"
             }
         },
+        "unist-util-stringify-position": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
+            "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ=="
+        },
         "universalify": {
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -9968,6 +10642,11 @@
             "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
             "dev": true
         },
+        "unquote": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
+            "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ="
+        },
         "unset-value": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
@@ -10089,7 +10768,6 @@
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
             "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
-            "dev": true,
             "requires": {
                 "define-properties": "^1.1.2",
                 "object.getownpropertydescriptors": "^2.0.3"
@@ -10150,6 +10828,32 @@
                 "extsprintf": "^1.2.0"
             }
         },
+        "vfile": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/vfile/-/vfile-3.0.1.tgz",
+            "integrity": "sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ==",
+            "requires": {
+                "is-buffer": "^2.0.0",
+                "replace-ext": "1.0.0",
+                "unist-util-stringify-position": "^1.0.0",
+                "vfile-message": "^1.0.0"
+            },
+            "dependencies": {
+                "is-buffer": {
+                    "version": "2.0.3",
+                    "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
+                    "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
+                }
+            }
+        },
+        "vfile-message": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz",
+            "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==",
+            "requires": {
+                "unist-util-stringify-position": "^1.1.1"
+            }
+        },
         "vinyl": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
@@ -10238,6 +10942,11 @@
                 "minimalistic-assert": "^1.0.0"
             }
         },
+        "web-namespaces": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.2.tgz",
+            "integrity": "sha512-II+n2ms4mPxK+RnIxRPOw3zwF2jRscdJIUE9BfkKHm4FYEg9+biIoTMnaZF5MpemE3T+VhMLrhbyD4ilkPCSbg=="
+        },
         "webpack": {
             "version": "4.28.3",
             "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.28.3.tgz",
@@ -10881,6 +11590,11 @@
                 "mkdirp": "^0.5.1"
             }
         },
+        "x-is-string": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz",
+            "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI="
+        },
         "xregexp": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz",
diff --git a/package.json b/package.json
index 6d744610c1a72832dfece7ac5bceab094a52e4ac..7ad0fcfa4597981cdb4b18bee2f73c21963125a2 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,8 @@
         "last 2 versions"
     ],
     "dependencies": {
+        "@babel/polyfill": "^7.2.5",
+        "@svgr/webpack": "^4.1.0",
         "del": "^3.0.0",
         "gulp": "^4.0.0",
         "gulp-babel": "^8.0.0",
@@ -22,21 +24,33 @@
         "gulp-touch-cmd": "0.0.1",
         "gulp-uglify": "^3.0.1",
         "node-sass-import-once": "^1.2.0",
+        "prop-types": "^15.6.2",
         "react": "^16.7.0",
-        "react-dom": "^16.7.0"
+        "react-dom": "^16.7.0",
+        "react-redux": "^6.0.0",
+        "react-transition-group": "^2.5.3",
+        "react-window-size-listener": "^1.2.3",
+        "redux": "^4.0.1",
+        "redux-logger": "^3.0.6",
+        "redux-thunk": "^2.3.0",
+        "reselect": "^4.0.0"
     },
     "devDependencies": {
         "@babel/core": "^7.2.2",
         "@babel/plugin-proposal-class-properties": "^7.2.3",
         "@babel/preset-env": "^7.2.3",
         "@babel/preset-react": "^7.0.0",
+        "babel-eslint": "^10.0.1",
         "babel-loader": "^8.0.4",
         "css-loader": "^2.1.0",
+        "eslint-loader": "^2.1.1",
+        "eslint-plugin-react": "^7.12.4",
         "gulp-eslint": "^5.0.0",
         "gulp-sass-lint": "^1.4.0",
         "gulp-sourcemaps": "^2.6.4",
         "node-sass": "^4.11.0",
         "react-hot-loader": "^4.6.3",
+        "redux-devtools-extension": "^2.13.7",
         "sass-loader": "^7.1.0",
         "style-loader": "^0.23.1",
         "webpack": "^4.28.3",
diff --git a/requirements.txt b/requirements.txt
index 25b2bb484519f959a7b91e525edfb1713e75396c..fbc49f76778fdab1ff33dee15eeee2015d01854d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
 django~=2.0.0
-djangorestframework==3.7.4
+djangorestframework==3.9.0
 django-fsm==2.6.0
 wagtail~=2.2.0
 psycopg2==2.7.3.1