diff --git a/alembic/versions/0ba9060b0434_add_schedule_description_and_separate_.py b/alembic/versions/0ba9060b0434_add_schedule_description_and_separate_.py
new file mode 100644
index 000000000..1ed0ca05e
--- /dev/null
+++ b/alembic/versions/0ba9060b0434_add_schedule_description_and_separate_.py
@@ -0,0 +1,63 @@
+"""Add schedule description and separate recording preference option for panels
+
+Revision ID: 0ba9060b0434
+Revises: 983af01225fc
+Create Date: 2024-08-08 03:37:03.691021
+
+"""
+
+
+# revision identifiers, used by Alembic.
+revision = '0ba9060b0434'
+down_revision = '983af01225fc'
+branch_labels = None
+depends_on = None
+
+from alembic import op
+import sqlalchemy as sa
+
+
+
+try:
+ is_sqlite = op.get_context().dialect.name == 'sqlite'
+except Exception:
+ is_sqlite = False
+
+if is_sqlite:
+ op.get_context().connection.execute('PRAGMA foreign_keys=ON;')
+ utcnow_server_default = "(datetime('now', 'utc'))"
+else:
+ utcnow_server_default = "timezone('utc', current_timestamp)"
+
+def sqlite_column_reflect_listener(inspector, table, column_info):
+ """Adds parenthesis around SQLite datetime defaults for utcnow."""
+ if column_info['default'] == "datetime('now', 'utc')":
+ column_info['default'] = utcnow_server_default
+
+sqlite_reflect_kwargs = {
+ 'listeners': [('column_reflect', sqlite_column_reflect_listener)]
+}
+
+# ===========================================================================
+# HOWTO: Handle alter statements in SQLite
+#
+# def upgrade():
+# if is_sqlite:
+# with op.batch_alter_table('table_name', reflect_kwargs=sqlite_reflect_kwargs) as batch_op:
+# batch_op.alter_column('column_name', type_=sa.Unicode(), server_default='', nullable=False)
+# else:
+# op.alter_column('table_name', 'column_name', type_=sa.Unicode(), server_default='', nullable=False)
+#
+# ===========================================================================
+
+
+def upgrade():
+ op.add_column('event', sa.Column('public_description', sa.Unicode(), server_default='', nullable=False))
+ op.add_column('panel_application', sa.Column('public_description', sa.Unicode(), server_default='', nullable=False))
+ op.add_column('panel_application', sa.Column('record', sa.Integer(), server_default='227291107', nullable=False))
+
+
+def downgrade():
+ op.drop_column('panel_application', 'record')
+ op.drop_column('panel_application', 'public_description')
+ op.drop_column('event', 'public_description')
diff --git a/uber/api.py b/uber/api.py
index 0a7d925ac..fe224b6a0 100644
--- a/uber/api.py
+++ b/uber/api.py
@@ -1447,7 +1447,7 @@ def schedule(self):
'start_unix': int(mktime(event.start_time.utctimetuple())),
'end_unix': int(mktime(event.end_time.utctimetuple())),
'duration': event.minutes,
- 'description': event.description,
+ 'description': event.public_description or event.description,
'panelists': [panelist.attendee.full_name for panelist in event.assigned_panelists]
}
for event in sorted(session.query(Event).all(), key=lambda e: [e.start_time, e.location_label])
diff --git a/uber/configspec.ini b/uber/configspec.ini
index f07003e70..3bc29ff36 100644
--- a/uber/configspec.ini
+++ b/uber/configspec.ini
@@ -1724,8 +1724,6 @@ other = string(default="Other")
[[livestream]]
opt_in = string(default="It's fine to record or livestream this panel")
-record_only = string(default="Recording for the public is okay, but not livestreaming")
-private_record = string(default="Recording is okay, but please don't post it publicly")
opt_out = string(default="Please don't record or livestream this panel")
[[panel_app_status]]
diff --git a/uber/model_checks.py b/uber/model_checks.py
index 8d5d47adb..620e0306c 100644
--- a/uber/model_checks.py
+++ b/uber/model_checks.py
@@ -638,6 +638,19 @@ def specify_nonstandard_time(app):
return 'Please explain why your panel needs to be longer than sixty minutes.'
+@validation.PanelApplication
+def select_livestream_opt(app):
+ if not app.livestream:
+ return 'Please select your preference for recording/livestreaming.' \
+ if len(c.LIVESTREAM_OPTS) > 2 else 'Please tell us if we can livestream your panel.'
+
+
+@validation.PanelApplication
+def select_record_opt(app):
+ if not app.record and len(c.LIVESTREAM_OPTS) <= 2:
+ return 'Please tell us if we can record your panel.'
+
+
@validation.PanelApplication
def specify_table_needs(app):
if app.need_tables and not app.tables_desc:
diff --git a/uber/models/panels.py b/uber/models/panels.py
index 2511df46f..450375089 100644
--- a/uber/models/panels.py
+++ b/uber/models/panels.py
@@ -23,6 +23,7 @@ class Event(MagModel):
duration = Column(Integer) # half-hour increments
name = Column(UnicodeText, nullable=False)
description = Column(UnicodeText)
+ public_description = Column(UnicodeText)
assigned_panelists = relationship('AssignedPanelist', backref='event')
applications = relationship('PanelApplication', backref=backref('event', cascade="save-update,merge"),
@@ -73,7 +74,8 @@ def guidebook_desc(self):
panelists_creds = '
' + '
'.join(
a.other_credentials for a in self.applications[0].applicants if a.other_credentials
) if self.applications else ''
- return self.description + panelists_creds
+ description = self.public_description or self.description
+ return description + panelists_creds
@property
def guidebook_location(self):
@@ -104,6 +106,7 @@ class PanelApplication(MagModel):
length_text = Column(UnicodeText)
length_reason = Column(UnicodeText)
description = Column(UnicodeText)
+ public_description = Column(UnicodeText)
unavailable = Column(UnicodeText)
available = Column(UnicodeText)
affiliations = Column(UnicodeText)
@@ -123,6 +126,7 @@ class PanelApplication(MagModel):
tabletop = Column(Boolean, default=False)
cost_desc = Column(UnicodeText)
livestream = Column(Choice(c.LIVESTREAM_OPTS), default=c.OPT_IN)
+ record = Column(Choice(c.LIVESTREAM_OPTS), default=c.OPT_IN)
panelist_bringing = Column(UnicodeText)
extra_info = Column(UnicodeText)
applied = Column(UTCDateTime, server_default=utcnow(), default=lambda: datetime.now(UTC))
@@ -141,12 +145,18 @@ def update_event_info(self):
if self.event:
self.event.name = self.name
self.event.description = self.description
+ self.event.public_description = self.public_description
@presave_adjustment
def set_default_dept(self):
if len(c.PANEL_DEPT_OPTS) <= 1 and not self.department:
self.department = c.PANELS
+ @presave_adjustment
+ def set_record(self):
+ if len(c.LIVESTREAM_OPTS) > 2 and not self.record:
+ self.record = c.OPT_OUT
+
@property
def email(self):
return self.submitter and self.submitter.email
diff --git a/uber/site_sections/schedule.py b/uber/site_sections/schedule.py
index e4a49212b..33051b047 100644
--- a/uber/site_sections/schedule.py
+++ b/uber/site_sections/schedule.py
@@ -100,7 +100,7 @@ def schedule_tsv(self, session):
'date': event.start_time_local.strftime('%m/%d/%Y'),
'start_time': event.start_time_local.strftime('%I:%M:%S %p'),
'end_time': (event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'),
- 'description': normalize_newlines(event.description).replace('\n', ' ')
+ 'description': normalize_newlines(event.public_description or event.description).replace('\n', ' '),
}))
return render('schedule/schedule.tsv', {
@@ -132,7 +132,7 @@ def ical(self, session, **params):
name=event.name,
begin=event.start_time,
end=(event.start_time + timedelta(minutes=event.minutes)),
- description=normalize_newlines(event.description),
+ description=normalize_newlines(event.public_description or event.description),
created=event.created_info.when,
location=event.location_label))
@@ -160,7 +160,7 @@ def csv(self, out, session):
(event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'),
event.location_label,
event.guidebook_track,
- normalize_newlines(event.description).replace('\n', ' '),
+ normalize_newlines(event.public_description or event.description).replace('\n', ' '),
'', '', '', ''
])
for r in sorted(rows, key=lambda tup: tup[4]):
@@ -179,7 +179,7 @@ def panels(self, out, session):
event.start_time_local.strftime('%I%p %a').lstrip('0'),
'{} minutes'.format(event.minutes),
event.location_label,
- event.description,
+ event.public_description or event.description,
panelist_names])
@schedule_view
@@ -194,7 +194,7 @@ def panels_json(self, session):
'start_unix': int(mktime(event.start_time.utctimetuple())),
'end_unix': int(mktime(event.end_time.utctimetuple())),
'duration': event.minutes,
- 'description': event.description,
+ 'description': event.public_description or event.description,
'panelists': [panelist.attendee.full_name for panelist in event.assigned_panelists]
}
for event in sorted(session.query(Event).all(), key=lambda e: [e.start_time, e.location_label])
@@ -243,6 +243,7 @@ def form(self, session, message='', panelists=(), **params):
if event.is_new:
event.name = add_panel.name
event.description = add_panel.description
+ event.public_description = add_panel.public_description
for pa in add_panel.applicants:
if pa.attendee_id:
assigned_panelist = AssignedPanelist(attendee_id=pa.attendee.id, event_id=event.id)
diff --git a/uber/templates/emails/panels/application.html b/uber/templates/emails/panels/application.html
index e318b68fc..adbf3016d 100644
--- a/uber/templates/emails/panels/application.html
+++ b/uber/templates/emails/panels/application.html
@@ -33,6 +33,7 @@