diff --git a/opentech/apply/dashboard/templates/dashboard/dashboard.html b/opentech/apply/dashboard/templates/dashboard/dashboard.html
index 6c6f84d4e84b696b45218bd7aaa12a2ef50bfe6c..dc4ca09908509d0adf3d883ba171d476271299f1 100644
--- a/opentech/apply/dashboard/templates/dashboard/dashboard.html
+++ b/opentech/apply/dashboard/templates/dashboard/dashboard.html
@@ -54,6 +54,10 @@
         {% include "dashboard/includes/waiting-for-review.html" with in_review_count=awating_reviews.count my_review=awaiting_reviews.table display_more=awaiting_reviews.display_more active_statuses_filter=awaiting_reviews.active_statuses_filter %}
     </div>
 
+    <div id="submissions-flagged" class="wrapper wrapper--bottom-space">
+        {% include "dashboard/includes/flagged.html" with my_flagged=my_flagged.table display_more=my_flagged.display_more %}
+    </div>
+
     {% if rounds.closed or rounds.open %}
         {% include "funds/includes/round-block.html" with closed_rounds=rounds.closed open_rounds=rounds.open title="Your rounds and labs" %}
     {% endif %}
@@ -109,4 +113,5 @@
     <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>
+    <script src="{% static 'js/apply/flag.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/dashboard/templates/dashboard/includes/flagged.html b/opentech/apply/dashboard/templates/dashboard/includes/flagged.html
new file mode 100644
index 0000000000000000000000000000000000000000..b2c25d15b18f576b9b6a16cd9a90095f5bfa3fe5
--- /dev/null
+++ b/opentech/apply/dashboard/templates/dashboard/includes/flagged.html
@@ -0,0 +1,14 @@
+{% load render_table from django_tables2 %}
+
+<h4 class="heading heading--normal">
+    My Flagged Submissions
+</h4>
+
+{% if my_flagged.data %}
+    {% render_table my_flagged %}
+    {% if display_more %}
+        <div class="all-submissions-table__more">
+            <a href="{% url 'apply:submissions:flagged' %}">Show all</a>
+        </div>
+    {% endif %}
+{% endif %}
diff --git a/opentech/apply/dashboard/views.py b/opentech/apply/dashboard/views.py
index 148bddc9bff5fde9602e26662ecb1e5ee1a1ba56..9b963a58f1b778eafe431a0da02875d55bd3a9d1 100644
--- a/opentech/apply/dashboard/views.py
+++ b/opentech/apply/dashboard/views.py
@@ -38,7 +38,8 @@ class AdminDashboardView(TemplateView):
             'my_reviewed': self.get_my_reviewed(self.request, submissions),
             'projects': self.get_my_projects(self.request),
             'projects_to_approve': self.get_my_projects_to_approve(self.request.user),
-            'rounds': self.get_rounds(self.request.user)
+            'rounds': self.get_rounds(self.request.user),
+            'my_flagged': self.get_my_flagged(self.request, submissions),
         }
         current_context = super().get_context_data(**kwargs)
         return {**current_context, **extra_context}
@@ -110,13 +111,24 @@ class AdminDashboardView(TemplateView):
         }
 
     def get_rounds(self, user):
+        limit = 6
         qs = (RoundsAndLabs.objects.with_progress()
                                    .active()
                                    .order_by('-end_date')
                                    .by_lead(user))
         return {
-            'closed': qs.closed()[:6],
-            'open': qs.open()[:6],
+            'closed': qs.closed()[:limit],
+            'open': qs.open()[:limit],
+        }
+
+    def get_my_flagged(self, request, qs):
+        qs = qs.flagged_by(request.user).order_by('-submit_time')
+        row_attrs = dict({'data-flag-type': 'user'}, **SummarySubmissionsTable._meta.row_attrs)
+
+        limit = 5
+        return {
+            'table': SummarySubmissionsTable(qs[:limit], prefix='my-flagged-', attrs={'class': 'all-submissions-table flagged-table'}, row_attrs=row_attrs),
+            'display_more': qs.count() > limit,
         }
 
 
@@ -159,9 +171,10 @@ class ReviewerDashboardView(TemplateView):
         return render(request, 'dashboard/reviewer_dashboard.html', context)
 
     def get_my_reviews(self, user, qs):
+        limit = 5
         my_review_qs = qs.in_review_for(user).order_by('-submit_time')
-        my_review_table = ReviewerSubmissionsTable(my_review_qs[:5], prefix='my-review-')
-        display_more = (my_review_qs.count() > 5)
+        my_review_table = ReviewerSubmissionsTable(my_review_qs[:limit], prefix='my-review-')
+        display_more = (my_review_qs.count() > limit)
 
         return my_review_qs, my_review_table, display_more
 
@@ -177,8 +190,9 @@ class ReviewerDashboardView(TemplateView):
         filterset = SubmissionReviewerFilterAndSearch(**kwargs)
         my_reviewed_qs = filterset.qs
 
-        my_reviewed_table = ReviewerSubmissionsTable(my_reviewed_qs[:5], prefix='my-reviewed-')
-        display_more_reviewed = (my_reviewed_qs.count() > 5)
+        limit = 5
+        my_reviewed_table = ReviewerSubmissionsTable(my_reviewed_qs[:limit], prefix='my-reviewed-')
+        display_more_reviewed = (my_reviewed_qs.count() > limit)
 
         return filterset, my_reviewed_qs, my_reviewed_table, display_more_reviewed
 
diff --git a/opentech/apply/flags/__init__.py b/opentech/apply/flags/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/apply/flags/migrations/0001_initial.py b/opentech/apply/flags/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..dccfeb0966fc578042b8c854fb7d0469c41f53d3
--- /dev/null
+++ b/opentech/apply/flags/migrations/0001_initial.py
@@ -0,0 +1,29 @@
+# Generated by Django 2.1.11 on 2019-10-29 13:20
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('contenttypes', '0002_remove_content_type_name'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Flag',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('target_object_id', models.PositiveIntegerField()),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('type', models.CharField(choices=[('staff', 'Staff'), ('user', 'User')], default='user', max_length=15)),
+                ('target_content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
+                ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/opentech/apply/flags/migrations/__init__.py b/opentech/apply/flags/migrations/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/apply/flags/models.py b/opentech/apply/flags/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..726fd0be4a41e1546c38c343d3d915ed859e708e
--- /dev/null
+++ b/opentech/apply/flags/models.py
@@ -0,0 +1,26 @@
+from django.conf import settings
+from django.db import models
+from django.contrib.contenttypes.fields import GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
+
+
+class Flag(models.Model):
+    STAFF = 'staff'
+    USER = 'user'
+    FLAG_TYPES = {
+        STAFF: 'Staff',
+        USER: 'User',
+    }
+    target_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
+    target_object_id = models.PositiveIntegerField()
+    target = GenericForeignKey('target_content_type', 'target_object_id')
+    timestamp = models.DateTimeField(auto_now_add=True)
+    type = models.CharField(
+        choices=FLAG_TYPES.items(),
+        default='user',
+        max_length=15,
+    )
+    user = models.ForeignKey(
+        settings.AUTH_USER_MODEL,
+        on_delete=models.PROTECT,
+    )
diff --git a/opentech/apply/flags/templates/flags/flags.html b/opentech/apply/flags/templates/flags/flags.html
new file mode 100644
index 0000000000000000000000000000000000000000..4f68e8e16eae817dec9af75f1d8c1a55447eaa82
--- /dev/null
+++ b/opentech/apply/flags/templates/flags/flags.html
@@ -0,0 +1,12 @@
+{% load flag_tags %}
+<div class="sidebar__inner">
+    <h5>Add to your flagged list</h5>
+    <button class="button button--primary button--full-width button--flag{% if submission|flagged_by:user %} flagged{% endif %}" data-id="{{ submission.id }}" data-type="user">Flag</button>
+</div>
+
+{% if request.user.is_apply_staff %}
+<div class="sidebar__inner">
+    <h5>Add to staff flagged list</h5>
+    <button class="button button--primary button--full-width button--flag{% if submission|flagged_staff %} flagged{% endif %}" data-id="{{ submission.id }}" data-type="staff">Staff flag</button>
+</div>
+{% endif %}
diff --git a/opentech/apply/flags/templatetags/__init__.py b/opentech/apply/flags/templatetags/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/opentech/apply/flags/templatetags/flag_tags.py b/opentech/apply/flags/templatetags/flag_tags.py
new file mode 100644
index 0000000000000000000000000000000000000000..4a51294a42037eb4d648b4eded5ccfe02fbe921b
--- /dev/null
+++ b/opentech/apply/flags/templatetags/flag_tags.py
@@ -0,0 +1,13 @@
+from django import template
+
+register = template.Library()
+
+
+@register.filter
+def flagged_by(submission, user):
+    return submission.flagged_by(user)
+
+
+@register.filter
+def flagged_staff(submission):
+    return submission.flagged_staff
diff --git a/opentech/apply/flags/urls.py b/opentech/apply/flags/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea85dab48e78434371ba1f9759fdefd3cee083f1
--- /dev/null
+++ b/opentech/apply/flags/urls.py
@@ -0,0 +1,9 @@
+from django.urls import path
+
+from .views import FlagSubmissionCreateView
+
+app_name = 'flags'
+
+urlpatterns = [
+    path('<int:submission_pk>/<type>/flag/', FlagSubmissionCreateView.as_view(), name="create_submission_flag"),
+]
diff --git a/opentech/apply/flags/views.py b/opentech/apply/flags/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..776c68992d1a10a40c6d34c5531652651f0441e0
--- /dev/null
+++ b/opentech/apply/flags/views.py
@@ -0,0 +1,28 @@
+from django.contrib.contenttypes.models import ContentType
+from django.utils.decorators import method_decorator
+from django.http import JsonResponse, HttpResponseNotAllowed
+from django.views import View
+
+from opentech.apply.funds.models import ApplicationSubmission
+from opentech.apply.users.decorators import staff_required
+
+from .models import Flag
+
+
+@method_decorator(staff_required, name='dispatch')
+class FlagSubmissionCreateView(View):
+    model = Flag
+
+    def post(self, request, type, submission_pk):
+        if not request.is_ajax():
+            return HttpResponseNotAllowed()
+
+        submission_type = ContentType.objects.get_for_model(ApplicationSubmission)
+        # Trying to get a flag from the table, or create a new one
+        flag, created = self.model.objects.get_or_create(user=request.user, target_object_id=submission_pk, target_content_type=submission_type, type=type)
+        # If no new flag has been created,
+        # Then we believe that the request was to delete the flag.
+        if not created:
+            flag.delete()
+
+        return JsonResponse({"result": created})
diff --git a/opentech/apply/funds/models/submissions.py b/opentech/apply/funds/models/submissions.py
index 11f98e2b1060877ab5916f40be05a02f0be7ec47..ee66786c37d42d70259d6bf79718b6d781804dff 100644
--- a/opentech/apply/funds/models/submissions.py
+++ b/opentech/apply/funds/models/submissions.py
@@ -34,6 +34,7 @@ from wagtail.contrib.forms.models import AbstractFormSubmission
 from opentech.apply.activity.messaging import messenger, MESSAGES
 from opentech.apply.categories.models import MetaTerm
 from opentech.apply.determinations.models import Determination
+from opentech.apply.flags.models import Flag
 from opentech.apply.review.models import ReviewOpinion
 from opentech.apply.review.options import MAYBE, AGREE, DISAGREE
 from opentech.apply.stream_forms.files import StreamFieldDataEncoder
@@ -125,6 +126,12 @@ class ApplicationSubmissionQueryset(JSONOrderable):
     def reviewed_by(self, user):
         return self.filter(reviews__author__reviewer=user)
 
+    def flagged_by(self, user):
+        return self.filter(flags__user=user, flags__type=Flag.USER)
+
+    def flagged_staff(self):
+        return self.filter(flags__type=Flag.STAFF)
+
     def partner_for(self, user):
         return self.filter(partners=user)
 
@@ -399,6 +406,12 @@ class ApplicationSubmission(
         related_name='submissions',
         blank=True,
     )
+    flags = GenericRelation(
+        Flag,
+        content_type_field='target_content_type',
+        object_id_field='target_object_id',
+        related_query_name='submission',
+    )
     activities = GenericRelation(
         'activity.Activity',
         content_type_field='source_content_type',
@@ -650,6 +663,13 @@ class ApplicationSubmission(
     def reviewed_by(self, user):
         return self.assigned.reviewed().filter(reviewer=user).exists()
 
+    def flagged_by(self, user):
+        return self.flags.filter(user=user, type=Flag.USER).exists()
+
+    @property
+    def flagged_staff(self):
+        return self.flags.filter(type=Flag.STAFF).exists()
+
     def has_permission_to_review(self, user):
         if user.is_apply_staff:
             return True
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
index 4aeff8b6464d151641626801271bb18e06d98b87..4fcf1fc15172f635ea3ebe61507c890c700d228e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
@@ -28,6 +28,10 @@
     {% include "funds/includes/update_meta_terms_form.html" %}
 {% endblock %}
 
+{% block flags %}
+    {% include 'flags/flags.html' with submission=object user=request.user %}
+{% endblock %}
+
 {% block reviews %}
     <div class="sidebar__inner">
         <h5>Reviews &amp; assignees</h5>
@@ -59,15 +63,13 @@
     {{ reviewer_form.media.js }}
     {{ comment_form.media.js }}
     {{ partner_form.media.js }}
+    {{ block.super }}
     <script src="//cdnjs.cloudflare.com/ajax/libs/fancybox/3.4.1/jquery.fancybox.min.js"></script>
     <script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
     <script src="{% static 'js/apply/fancybox-global.js' %}"></script>
-    <script src="{% static 'js/apply/tabs.js' %}"></script>
     <script src="{% static 'js/apply/toggle-actions-panel.js' %}"></script>
     <script src="{% static 'js/apply/toggle-reviewers.js' %}"></script>
     <script src="{% static 'js/apply/toggle-sidebar.js' %}"></script>
-    <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
     <script src="{% static 'js/apply/toggle-related.js' %}"></script>
-    <script src="{% static 'js/apply/edit-comment.js' %}"></script>
     <script src="{% static 'js/apply/toggle-proposal-info.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_community_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_community_detail.html
index 4299c0aad4fd32882bf5f72db675c7cd41f0213d..f6ce10384853bd6ac87963f5ee0e8087b201248e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_community_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_community_detail.html
@@ -19,9 +19,7 @@
 {% block extra_js %}
     {{ reviewer_form.media.js }}
     {{ comment_form.media.js }}
-    <script src="{% static 'js/apply/tabs.js' %}"></script>
+    {{ block.super }}
     <script src="{% static 'js/apply/toggle-reviewers.js' %}"></script>
     <script src="{% static 'js/apply/toggle-sidebar.js' %}"></script>
-    <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
-    <script src="{% static 'js/apply/edit-comment.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
index 006202f030cefea19cf4251c10cacfb0b30e5eb0..09c04a170e811ef94abda9f11d513158ac8ee81a 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -97,6 +97,9 @@
                 {% block sidebar_top %}
                 {% endblock %}
 
+                {% block flags %}
+                {% endblock %}
+
                 {% if object.project and PROJECTS_ENABLED %}
                     {% include 'funds/includes/project_block.html' %}
                 {% endif %}
@@ -105,12 +108,11 @@
                     {% include 'determinations/includes/applicant_determination_block.html' with submission=object %}
                 {% endblock %}
 
-                {% if request.user.is_apply_staff %}
-                    {% block screening_status %}
-                    {% endblock %}
-                    {% block meta_terms %}
-                    {% endblock %}
-                {% endif %}
+                {% block screening_status %}
+                {% endblock %}
+
+                {% block meta_terms %}
+                {% endblock %}
 
                 {% block reviews %}
                 {% endblock %}
@@ -166,4 +168,5 @@
     <script src="{% static 'js/apply/tabs.js' %}"></script>
     <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
     <script src="{% static 'js/apply/edit-comment.js' %}"></script>
+    <script src="{% static 'js/apply/flag.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_partner_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_partner_detail.html
index 4299c0aad4fd32882bf5f72db675c7cd41f0213d..f6ce10384853bd6ac87963f5ee0e8087b201248e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_partner_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_partner_detail.html
@@ -19,9 +19,7 @@
 {% block extra_js %}
     {{ reviewer_form.media.js }}
     {{ comment_form.media.js }}
-    <script src="{% static 'js/apply/tabs.js' %}"></script>
+    {{ block.super }}
     <script src="{% static 'js/apply/toggle-reviewers.js' %}"></script>
     <script src="{% static 'js/apply/toggle-sidebar.js' %}"></script>
-    <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
-    <script src="{% static 'js/apply/edit-comment.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_reviewer_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_reviewer_detail.html
index 4299c0aad4fd32882bf5f72db675c7cd41f0213d..f6ce10384853bd6ac87963f5ee0e8087b201248e 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_reviewer_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_reviewer_detail.html
@@ -19,9 +19,7 @@
 {% block extra_js %}
     {{ reviewer_form.media.js }}
     {{ comment_form.media.js }}
-    <script src="{% static 'js/apply/tabs.js' %}"></script>
+    {{ block.super }}
     <script src="{% static 'js/apply/toggle-reviewers.js' %}"></script>
     <script src="{% static 'js/apply/toggle-sidebar.js' %}"></script>
-    <script src="{% static 'js/apply/submission-text-cleanup.js' %}"></script>
-    <script src="{% static 'js/apply/edit-comment.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
index 6b6e6d4763412ff71ed8510cbe604ee26db1417c..cbc14661e487df5828230ddd2cfb7dc624f198c8 100644
--- a/opentech/apply/funds/templates/funds/base_submissions_table.html
+++ b/opentech/apply/funds/templates/funds/base_submissions_table.html
@@ -26,4 +26,5 @@
     <script src="{% static 'js/apply/submission-tooltips.js' %}"></script>
     <script src="{% static 'js/apply/tabs.js' %}"></script>
     <script src="{% static 'js/apply/batch-actions.js' %}"></script>
+    <script src="{% static 'js/apply/flag.js' %}"></script>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submissions_overview.html b/opentech/apply/funds/templates/funds/submissions_overview.html
index 94c9092a804252fa86a7c31685f685e0faf15651..5f927338d8911ee5372f27c754592e870d03761e 100644
--- a/opentech/apply/funds/templates/funds/submissions_overview.html
+++ b/opentech/apply/funds/templates/funds/submissions_overview.html
@@ -23,12 +23,26 @@
     {% endif %}
 
     {% 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 use_batch_actions=False heading="All Submissions" %}
+        <div class="wrapper wrapper--bottom-space">
+            {% include "funds/includes/table_filter_and_search.html" with filter_form=filter_form search_term=search_term use_search=True filter_action=filter_action use_batch_actions=False heading="All Submissions" %}
 
-        {% render_table table %}
-        <div class="all-submissions-table__more">
-            <a href="{% url 'apply:submissions:list' %}">Show all</a>
+            {% render_table table %}
+            <div class="all-submissions-table__more">
+                <a href="{% url 'apply:submissions:list' %}">Show all</a>
+            </div>
+        </div>
+
+        {% if staff_flagged.table.data %}
+        <div class="wrapper wrapper--bottom-space">
+            <h4 class="heading heading--normal">Staff Flagged Submissions</h4>
+            {% render_table staff_flagged.table %}
+            {% if staff_flagged.display_more %}
+                <div class="all-submissions-table__more">
+                    <a href="{% url 'apply:submissions:staff_flagged' %}">Show all</a>
+                </div>
+            {% endif %}
         </div>
+        {% endif %}
     {% endblock %}
 </div>
 {% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submissions_staff_flagged.html b/opentech/apply/funds/templates/funds/submissions_staff_flagged.html
new file mode 100644
index 0000000000000000000000000000000000000000..328d6c7e8647ad0e4df827c709cf13dfd6c82922
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/submissions_staff_flagged.html
@@ -0,0 +1,7 @@
+{% extends "funds/submissions.html" %}
+
+{% block page_header %}
+    <div>
+        <h1 class="gamma heading heading--no-margin heading--bold">Staff Flagged Submissions</h1>
+    </div>
+{% endblock %}
diff --git a/opentech/apply/funds/templates/funds/submissions_user_flagged.html b/opentech/apply/funds/templates/funds/submissions_user_flagged.html
new file mode 100644
index 0000000000000000000000000000000000000000..47f7839456b94fec2c92bcba496c4b21f0cfa3a3
--- /dev/null
+++ b/opentech/apply/funds/templates/funds/submissions_user_flagged.html
@@ -0,0 +1,7 @@
+{% extends "funds/submissions.html" %}
+
+{% block page_header %}
+    <div>
+        <h1 class="gamma heading heading--no-margin heading--bold">My Flagged Submissions</h1>
+    </div>
+{% endblock %}
diff --git a/opentech/apply/funds/urls.py b/opentech/apply/funds/urls.py
index 122472c123c1d140a63e006fb13dbddedac2c044..82e31476aa4bf6312cac9d9bac97da4ca8f6cd57 100644
--- a/opentech/apply/funds/urls.py
+++ b/opentech/apply/funds/urls.py
@@ -17,6 +17,8 @@ from .views import (
     SubmissionPrivateMediaView,
     SubmissionDetailPDFView,
     SubmissionDetailSimplifiedView,
+    SubmissionUserFlaggedView,
+    SubmissionStaffFlaggedView,
 )
 from .api_views import (
     CommentEdit,
@@ -41,6 +43,10 @@ app_name = 'funds'
 submission_urls = ([
     path('', SubmissionOverviewView.as_view(), name="overview"),
     path('all/', SubmissionListView.as_view(), name="list"),
+    path('flagged/', include([
+        path('', SubmissionUserFlaggedView.as_view(), name="flagged"),
+        path('staff/', SubmissionStaffFlaggedView.as_view(), name="staff_flagged"),
+    ])),
     path('<int:pk>/', include([
         path('', SubmissionDetailView.as_view(), name="detail"),
         path('edit/', SubmissionEditView.as_view(), name="edit"),
@@ -58,6 +64,7 @@ submission_urls = ([
         path('revisions/', include(revision_urls, namespace="revisions")),
     ])),
     path('', include('opentech.apply.determinations.urls', namespace="determinations")),
+    path('', include('opentech.apply.flags.urls', namespace="flags")),
     path('<slug:status>/', SubmissionsByStatus.as_view(), name='status'),
 ], 'submissions')
 
diff --git a/opentech/apply/funds/views.py b/opentech/apply/funds/views.py
index c757e048335a60a1954748851c71d341c4d4a027..bd85a504b60df71597c0aa34a736f5c7eaa1ddc2 100644
--- a/opentech/apply/funds/views.py
+++ b/opentech/apply/funds/views.py
@@ -240,13 +240,15 @@ class SubmissionOverviewView(BaseAdminSubmissionsTable):
     filter_action = reverse_lazy('funds:submissions:list')
 
     def get_table_data(self):
-        return super().get_table_data().order_by(F('last_update').desc(nulls_last=True))[:5]
+        limit = 5
+        return super().get_table_data().order_by(F('last_update').desc(nulls_last=True))[:limit]
 
     def get_context_data(self, **kwargs):
+        limit = 6
         base_query = RoundsAndLabs.objects.with_progress().active().order_by('-end_date')
-        open_rounds = base_query.open()[:6]
+        open_rounds = base_query.open()[:limit]
         open_query = '?round_state=open'
-        closed_rounds = base_query.closed()[:6]
+        closed_rounds = base_query.closed()[:limit]
         closed_query = '?round_state=closed'
         rounds_title = 'All Rounds and Labs'
 
@@ -265,6 +267,8 @@ class SubmissionOverviewView(BaseAdminSubmissionsTable):
             for status, data in PHASES_MAPPING.items()
         }
 
+        staff_flagged = self.get_staff_flagged()
+
         return super().get_context_data(
             open_rounds=open_rounds,
             open_query=open_query,
@@ -272,9 +276,20 @@ class SubmissionOverviewView(BaseAdminSubmissionsTable):
             closed_query=closed_query,
             rounds_title=rounds_title,
             status_counts=grouped_statuses,
+            staff_flagged=staff_flagged,
             **kwargs,
         )
 
+    def get_staff_flagged(self):
+        qs = super().get_queryset().flagged_staff().order_by('-submit_time')
+        row_attrs = dict({'data-flag-type': 'staff'}, **SummarySubmissionsTable._meta.row_attrs)
+
+        limit = 5
+        return {
+            'table': SummarySubmissionsTable(qs[:limit], prefix='staff-flagged-', attrs={'class': 'all-submissions-table flagged-table'}, row_attrs=row_attrs),
+            'display_more': qs.count() > limit,
+        }
+
 
 class SubmissionAdminListView(BaseAdminSubmissionsTable, DelegateableListView):
     template_name = 'funds/submissions.html'
@@ -294,6 +309,22 @@ class SubmissionListView(ViewDispatcher):
     reviewer_view = SubmissionReviewerListView
 
 
+@method_decorator(staff_required, name='dispatch')
+class SubmissionStaffFlaggedView(BaseAdminSubmissionsTable):
+    template_name = 'funds/submissions_staff_flagged.html'
+
+    def get_queryset(self):
+        return self.filterset_class._meta.model.objects.current().for_table(self.request.user).flagged_staff().order_by('-submit_time')
+
+
+@method_decorator(staff_required, name='dispatch')
+class SubmissionUserFlaggedView(BaseAdminSubmissionsTable):
+    template_name = 'funds/submissions_user_flagged.html'
+
+    def get_queryset(self):
+        return self.filterset_class._meta.model.objects.current().for_table(self.request.user).flagged_by(self.request.user).order_by('-submit_time')
+
+
 @method_decorator(staff_required, name='dispatch')
 class SubmissionsByRound(BaseAdminSubmissionsTable, DelegateableListView):
     template_name = 'funds/submissions_by_round.html'
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index 9ec76d95997468bbbedb312928356f9e08b3e32b..0aebe1efce6d9f484565bc6ea109210618b4c61d 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -71,6 +71,7 @@ INSTALLED_APPS = [
     'opentech.apply.categories',
     'opentech.apply.funds',
     'opentech.apply.dashboard',
+    'opentech.apply.flags',
     'opentech.apply.home',
     'opentech.apply.users',
     'opentech.apply.review',
diff --git a/opentech/static_src/src/javascript/apply/flag.js b/opentech/static_src/src/javascript/apply/flag.js
new file mode 100644
index 0000000000000000000000000000000000000000..932622b582da6ea26d9931ce63d774060f1db262
--- /dev/null
+++ b/opentech/static_src/src/javascript/apply/flag.js
@@ -0,0 +1,34 @@
+(function ($) {
+
+    'use strict';
+
+    $('.flagged-table').find('.all-submissions-table__parent').each(function () {
+        var $flagged_item = $(this);
+        var submission_id = $flagged_item.data('record-id');
+        var flag_type = $flagged_item.data('flag-type');
+        var $button = '<span class="button--float"><button class="button button--flag button--unflag flagged" data-id="' + submission_id + '" data-type="' + flag_type + '">Flag</button></span>';
+        $flagged_item.find('td.comments').css('position', 'relative').append($button);
+    });
+
+    $('.button--flag').on('click', function (e) {
+        e.preventDefault();
+
+        var $current = $(this);
+        var id = $current.data('id');
+        var type = $current.data('type');
+
+        $.ajax({
+            url: '/apply/submissions/' + id + '/' + type + '/flag/',
+            type: 'POST',
+            success: function (json) {
+                if (json.result) {
+                    $current.addClass('flagged');
+                }
+                else {
+                    $current.removeClass('flagged');
+                }
+            }
+        });
+    });
+
+})(jQuery);
diff --git a/opentech/static_src/src/javascript/js.cookie.min.js b/opentech/static_src/src/javascript/js.cookie.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5f4c36c17146c4d1fb7346fca83f196de695e8b
--- /dev/null
+++ b/opentech/static_src/src/javascript/js.cookie.min.js
@@ -0,0 +1,3 @@
+/*! js-cookie v2.2.1 | MIT */
+
+!function(a){var b;if("function"==typeof define&&define.amd&&(define(a),b=!0),"object"==typeof exports&&(module.exports=a(),b=!0),!b){var c=window.Cookies,d=window.Cookies=a();d.noConflict=function(){return window.Cookies=c,d}}}(function(){function a(){for(var a=0,b={};a<arguments.length;a++){var c=arguments[a];for(var d in c)b[d]=c[d]}return b}function b(a){return a.replace(/(%[0-9A-Z]{2})+/g,decodeURIComponent)}function c(d){function e(){}function f(b,c,f){if("undefined"!=typeof document){f=a({path:"/"},e.defaults,f),"number"==typeof f.expires&&(f.expires=new Date(1*new Date+864e5*f.expires)),f.expires=f.expires?f.expires.toUTCString():"";try{var g=JSON.stringify(c);/^[\{\[]/.test(g)&&(c=g)}catch(j){}c=d.write?d.write(c,b):encodeURIComponent(c+"").replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),b=encodeURIComponent(b+"").replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent).replace(/[\(\)]/g,escape);var h="";for(var i in f)f[i]&&(h+="; "+i,!0!==f[i]&&(h+="="+f[i].split(";")[0]));return document.cookie=b+"="+c+h}}function g(a,c){if("undefined"!=typeof document){for(var e={},f=document.cookie?document.cookie.split("; "):[],g=0;g<f.length;g++){var h=f[g].split("="),i=h.slice(1).join("=");c||'"'!==i.charAt(0)||(i=i.slice(1,-1));try{var j=b(h[0]);if(i=(d.read||d)(i,j)||b(i),c)try{i=JSON.parse(i)}catch(k){}if(e[j]=i,a===j)break}catch(k){}}return a?e[a]:e}}return e.set=f,e.get=function(a){return g(a,!1)},e.getJSON=function(a){return g(a,!0)},e.remove=function(b,c){f(b,"",a(c,{expires:-1}))},e.defaults={},e.withConverter=c,e}return c(function(){})});
\ No newline at end of file
diff --git a/opentech/static_src/src/javascript/main.js b/opentech/static_src/src/javascript/main.js
index c49fc879d90c48691fcadfe0c68a1e9ec0f2adc1..6dc0b3e5f608ea73ca1aa75e950393e754a11157 100644
--- a/opentech/static_src/src/javascript/main.js
+++ b/opentech/static_src/src/javascript/main.js
@@ -1,4 +1,3 @@
-
 (function ($) {
 
     'use strict';
@@ -157,4 +156,18 @@
         document.documentElement.style.setProperty('--header-admin-height', headerHeight + adminbarHeight + 'px');
     });
 
+    // Setting the CSRF token on AJAX requests.
+    var csrftoken = window.Cookies.get('csrftoken');
+    function csrfSafeMethod(method) {
+        // these HTTP methods do not require CSRF protection
+        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
+    }
+    $.ajaxSetup({
+        beforeSend: function (xhr, settings) {
+            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
+                xhr.setRequestHeader('X-CSRFToken', csrftoken);
+            }
+        }
+    });
+
 })(jQuery);
diff --git a/opentech/static_src/src/sass/apply/abstracts/_mixins.scss b/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
index e1beb948c3a18d620144909ed2d2eba0bf56887f..ec269cd16c687695bcba7835739154ed2a8aae54 100644
--- a/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
+++ b/opentech/static_src/src/sass/apply/abstracts/_mixins.scss
@@ -106,6 +106,16 @@
     }
 }
 
+// Small button mixin
+@mixin button--small {
+    padding: 2px;
+    font-size: 12px;
+
+    @include media-query(tablet-landscape) {
+        padding: 3px 5px;
+    }
+}
+
 // Viewport sized typography mixin that takes a min and max pixel-based value
 @mixin responsive-font-sizes($min, $max) {
 
diff --git a/opentech/static_src/src/sass/apply/components/_button.scss b/opentech/static_src/src/sass/apply/components/_button.scss
index f5b89abb31e2b2d794f975eaf89f6b15934e514a..18cf4fd45886a46f511e7dc5bd4563a6f03f62ce 100644
--- a/opentech/static_src/src/sass/apply/components/_button.scss
+++ b/opentech/static_src/src/sass/apply/components/_button.scss
@@ -326,4 +326,44 @@
             background-color: $color--button-disabled;
         }
     }
+
+    &--flag {
+        &.flagged {
+            position: relative;
+
+            &::after {
+                content: '\2691';
+                color:  $color--tomato;
+                position: absolute;
+                top:  4px;
+                padding-left: 5px;
+                font-size: map-get($font-sizes, delta);
+                line-height: 1;
+            }
+        }
+    }
+
+    &--unflag {
+        @include button($color--light-blue, $color--dark-blue);
+        @include button--small;
+        padding-right: 18px;
+
+        @include media-query(tablet-landscape) {
+            padding-right: 18px;
+        }
+
+        &.flagged {
+            &::after {
+                top:  2px;
+                padding-left: 3px;
+                font-size: map-get($font-sizes, zeta);
+            }
+        }
+    }
+
+    &--float {
+        position: absolute;
+        top:  2px;
+        right:  2px;
+    }
 }
diff --git a/opentech/templates/base-apply.html b/opentech/templates/base-apply.html
index 3291995c6148c0442aab8cb5c35c0da23c01a9e6..630279b297e90e889ec799916027312ca00563d8 100644
--- a/opentech/templates/base-apply.html
+++ b/opentech/templates/base-apply.html
@@ -32,6 +32,7 @@
         <link rel="stylesheet" href="{% static 'css/print.css' %}" media="print">
 
         <script src="{% static 'js/jquery.min.js' %}"></script>
+        <script src="{% static 'js/js.cookie.min.js' %}"></script>
         <script src="{% static 'js/main.js' %}"></script>
     </head>