Skip to content

Commit 3c90393

Browse files
authored
Add content warnings for videos/links (#457)
1 parent d796a55 commit 3c90393

File tree

13 files changed

+216
-10
lines changed

13 files changed

+216
-10
lines changed

OpenOversight/app/main/forms.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ class LinkForm(Form):
242242
default="",
243243
validators=[AnyOf(allowed_values(LINK_CHOICES))],
244244
)
245+
has_content_warning = BooleanField(
246+
"Include content warning?", default=True, validators=[Optional()]
247+
)
245248

246249
def validate(self, extra_validators=None):
247250
success = super(LinkForm, self).validate(extra_validators=extra_validators)

OpenOversight/app/main/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,6 +2381,7 @@ def new(self, form: FlaskForm = None):
23812381
link_type=form.link_type.data,
23822382
description=form.description.data,
23832383
author=form.author.data,
2384+
has_content_warning=form.has_content_warning.data,
23842385
created_by=current_user.id,
23852386
last_updated_by=current_user.id,
23862387
)

OpenOversight/app/models/database.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ class Link(BaseModel, TrackUpdates):
659659
link_type = db.Column(db.String(100), index=True)
660660
description = db.Column(db.Text(), nullable=True)
661661
author = db.Column(db.String(255), nullable=True)
662+
has_content_warning = db.Column(db.Boolean, nullable=False, default=False)
662663

663664
@validates("url")
664665
def validate_url(self, key, url):

OpenOversight/app/static/css/openoversight.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,3 +684,15 @@ tr:hover .row-actions {
684684
.bottom-margin {
685685
margin-bottom: 2rem;
686686
}
687+
688+
.video-container .overlay {
689+
align-items: center;
690+
background: black;
691+
color: white;
692+
display: flex;
693+
height: 100%;
694+
justify-content: center;
695+
position: absolute;
696+
top: 0;
697+
width: 100%;
698+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function createOverlay(container) {
2+
const warningText = $(
3+
"<span><h3>Content Warning</h3><p>This video may be disturbing for some viewers</p></span>"
4+
)
5+
const hide = $('<button type="button" class="btn btn-lg">Show video</button>')
6+
hide.click(() => overlay.css("display", "none"))
7+
8+
const wrapper = $("<div>")
9+
wrapper.append(warningText)
10+
wrapper.append(hide)
11+
12+
const overlay = $('<div class="overlay">')
13+
overlay.append(wrapper)
14+
container.append(overlay)
15+
}
16+
17+
$(document).ready(() => {
18+
$(".video-container").each((index, element) => {
19+
const container = $(element)
20+
if (container.data("has-content-warning")) {
21+
createOverlay(container)
22+
}
23+
})
24+
})

OpenOversight/app/templates/incident_detail.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@ <h4>Incident Description</h4>
8282
</div>
8383
{% endif %}
8484
</main>
85+
<script src="{{ url_for('static', filename='js/contentWarning.js') }}"></script>
8586
{% endblock content %}

OpenOversight/app/templates/officer.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,5 @@ <h1>
136136
</div>
137137
{# end row #}
138138
</div>
139+
<script src="{{ url_for('static', filename='js/contentWarning.js') }}"></script>
139140
{% endblock content %}

OpenOversight/app/templates/partials/links_and_videos_row.html

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ <h3>Links</h3>
66
{% for link in list %}
77
<li class="list-group-item">
88
<a href="{{ link.url }}" rel="noopener noreferrer" target="_blank">{{ link.title or link.url }}</a>
9+
{% if link.has_content_warning %}
10+
<span class="label label-danger"
11+
title="The linked page may be disturbing for some viewers">Content Warning</span>
12+
{% endif %}
913
{% if officer and (is_admin_or_coordinator or link.created_by == current_user.id) %}
1014
<a href="{{ url_for('main.link_api_edit', officer_id=officer.id, obj_id=link.id) }}">
1115
<span class="sr-only">Edit</span>
@@ -30,10 +34,6 @@ <h3>Links</h3>
3034
</ul>
3135
{% endif %}
3236
{% endfor %}
33-
{% if officer and (current_user.is_admin_or_coordinator(officer.department)) %}
34-
<a href="{{ url_for("main.link_api_new", officer_id=officer.id) }}"
35-
class="btn btn-primary">New Link/Video</a>
36-
{% endif %}
3737
{% for type, list in obj.links | groupby("link_type") %}
3838
{% if type == "video" %}
3939
<h3>Videos</h3>
@@ -53,7 +53,8 @@ <h3>Videos</h3>
5353
<i class="fa-solid fa-trash-can" aria-hidden="true"></i>
5454
</a>
5555
{% endif %}
56-
<div class="video-container">
56+
<div class="video-container"
57+
data-has-content-warning="{{ link.has_content_warning | lower }}">
5758
<iframe width="560"
5859
height="315"
5960
src="https://www.youtube.com/embed/{{ link_url }}"
@@ -81,6 +82,10 @@ <h3>Other videos</h3>
8182
{% for link in list %}
8283
<li class="list-group-item">
8384
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer">{{ link.title or link.url }}</a>
85+
{% if link.has_content_warning %}
86+
<span class="label label-danger"
87+
title="The linked video may be disturbing for some viewers">Content Warning</span>
88+
{% endif %}
8489
{% if officer and (current_user.is_admin_or_coordinator(officer.department)
8590
or link.created_by == current_user.id) %}
8691
<a href="{{ url_for('main.link_api_edit', officer_id=officer.id, obj_id=link.id) }}">
@@ -106,4 +111,8 @@ <h3>Other videos</h3>
106111
</ul>
107112
{% endif %}
108113
{% endfor %}
114+
{% if officer and (current_user.is_admin_or_coordinator(officer.department)) %}
115+
<a href="{{ url_for("main.link_api_new", officer_id=officer.id) }}"
116+
class="btn btn-primary">New Link/Video</a>
117+
{% endif %}
109118
{% endif %}

OpenOversight/app/utils/forms.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ def get_or_create_link_from_form(link_form, user: User) -> Union[Link, None]:
257257
link_type=if_exists_or_none(link_form["link_type"]),
258258
title=if_exists_or_none(link_form["title"]),
259259
url=if_exists_or_none(link_form["url"]),
260+
has_content_warning=link_form["has_content_warning"],
260261
created_by=user.id,
261262
last_updated_by=user.id,
262263
)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Add has_content_warning column to link model
2+
3+
Revision ID: 939ea0f2b26d
4+
Revises: 52d3f6a21dd9
5+
Create Date: 2024-06-05 02:03:29.168771
6+
7+
"""
8+
import sqlalchemy as sa
9+
from alembic import op
10+
11+
12+
revision = "939ea0f2b26d"
13+
down_revision = "52d3f6a21dd9"
14+
15+
16+
def upgrade():
17+
# This is not expected to impact performance: https://dba.stackexchange.com/a/216153
18+
with op.batch_alter_table("links", schema=None) as batch_op:
19+
batch_op.add_column(
20+
sa.Column(
21+
"has_content_warning",
22+
sa.Boolean(),
23+
nullable=False,
24+
server_default="false",
25+
)
26+
)
27+
28+
29+
def downgrade():
30+
with op.batch_alter_table("links", schema=None) as batch_op:
31+
batch_op.drop_column("has_content_warning")

0 commit comments

Comments
 (0)