diff --git a/themes_legacy/MANIFEST.in b/themes_legacy/MANIFEST.in
new file mode 100644
index 0000000..9f8b156
--- /dev/null
+++ b/themes_legacy/MANIFEST.in
@@ -0,0 +1,6 @@
+graft indico_themes_legacy/static
+graft indico_themes_legacy/templates
+graft indico_themes_legacy/themes
+recursive-include indico_themes_legacy *.yaml
+
+global-exclude *.pyc __pycache__ .keep
diff --git a/themes_legacy/indico_themes_legacy/__init__.py b/themes_legacy/indico_themes_legacy/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/themes_legacy/indico_themes_legacy/plugin.py b/themes_legacy/indico_themes_legacy/plugin.py
new file mode 100644
index 0000000..759136d
--- /dev/null
+++ b/themes_legacy/indico_themes_legacy/plugin.py
@@ -0,0 +1,28 @@
+# This file is part of the Indico plugins.
+# Copyright (C) 2002 - 2021 CERN
+#
+# The Indico plugins are free software; you can redistribute
+# them and/or modify them under the terms of the MIT License;
+# see the LICENSE file for more details.
+
+import os
+
+from indico.core import signals
+from indico.core.plugins import IndicoPlugin, IndicoPluginBlueprint
+
+
+class LegacyThemesPlugin(IndicoPlugin):
+ """Legacy Themes
+
+ Provides legacy event themes
+ """
+
+ def init(self):
+ super().init()
+ self.connect(signals.plugin.get_event_themes_files, self._get_themes_yaml)
+
+ def get_blueprints(self):
+ return IndicoPluginBlueprint(self.name, __name__)
+
+ def _get_themes_yaml(self, sender, **kwargs):
+ return os.path.join(self.root_path, 'themes-legacy.yaml')
diff --git a/themes_legacy/indico_themes_legacy/static/.keep b/themes_legacy/indico_themes_legacy/static/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/themes_legacy/indico_themes_legacy/templates/compact_event.html b/themes_legacy/indico_themes_legacy/templates/compact_event.html
new file mode 100644
index 0000000..d1545f5
--- /dev/null
+++ b/themes_legacy/indico_themes_legacy/templates/compact_event.html
@@ -0,0 +1,79 @@
+{% from 'events/display/common/_legacy.html' import render_event_time, render_location %}
+{% from 'events/display/common/_manage_button.html' import render_manage_button %}
+
+
+
+
+
+ {{ template_hook('meeting-body', event=event) }}
+
+
diff --git a/themes_legacy/indico_themes_legacy/templates/compact_timetable.html b/themes_legacy/indico_themes_legacy/templates/compact_timetable.html
new file mode 100644
index 0000000..2e9bef6
--- /dev/null
+++ b/themes_legacy/indico_themes_legacy/templates/compact_timetable.html
@@ -0,0 +1,171 @@
+{% from 'attachments/_display.html' import render_attachments_folders %}
+{% from 'events/display/common/_manage_button.html' import render_manage_button %}
+{% from 'events/display/indico/_common.html' import render_users %}
+
+{% macro render_break(break_, timezone) %}
+
+ |
+ {{ break_.timetable_entry.start_dt | format_time(timezone=timezone) }}
+ |
+
+ --- {{ break_.title }} ---
+ |
+
+{% endmacro %}
+
+{% macro render_session_block(block, timezone) %}
+ {% set entries = block.timetable_entry.children %}
+
+ |
+
+ {{ block.timetable_entry.start_dt | format_time(timezone=timezone) }}
+
+ |
+
+
+ {{ render_manage_button(block, 'SESSION_BLOCK', toggle_notes=false, show_note_operations=true) }}
+ {% if block.has_note %}
+
+ {% endif %}
+
+
+ {{- block.session.title }}
+
+ {% set conveners = block.person_links|list %}
+ {% if conveners %}
+ -{{ render_users(conveners, span_class="speakerList", separator=' ') }}
+ {% endif %}
+
+ (until {{ block.timetable_entry.end_dt | format_time(timezone=timezone) }})
+
+ {% if not block.inherits_location %}
+ ({{ block.room_name }})
+ {% endif %}
+
+
+ {{ render_attachments_folders(item=block.session) }}
+
+ |
+
+ {% for entry in entries|sort(attribute='object.title')|sort(attribute='start_dt') %}
+ {% if entry.type.name == 'CONTRIBUTION' and entry.object.can_access(session.user) %}
+ {{ render_contribution(entry.contribution, timezone, loop.index) }}
+ {% elif entry.type.name == 'BREAK' %}
+ {{ render_break(entry.break_, timezone) }}
+ {% endif %}
+ {% endfor %}
+{% endmacro %}
+
+{% macro render_contribution(contrib, timezone, index) %}
+
+ |
+ {{ contrib.start_dt | format_time(timezone=timezone) }}
+ |
+
+ {{ contrib.title }}
+ {% set speakers = contrib.person_links|selectattr("is_speaker")|list %}
+ {% if speakers %}
+ - {{ render_users(speakers, span_class="speakerList", separator=' ') }}
+ {% endif %}
+
+
+
+ {% if not contrib.inherits_location %}
+ ({{ contrib.room_name }})
+ {% endif %}
+
+
+ {{ render_attachments_folders(item=contrib) }}
+
+
+ {{ render_manage_button(contrib, 'CONTRIBUTION', toggle_notes=false, show_note_operations=true) }}
+ {% if contrib.has_note %}
+
+ {% endif %}
+
+
+ |
+
+{% endmacro %}
+
+{% macro render_entry(entry, timezone, index) %}
+ {% if entry.type.name == 'CONTRIBUTION' -%}
+ {{ render_contribution(entry.object, timezone, index) }}
+ {% elif entry.type.name == 'SESSION_BLOCK' -%}
+ {{ render_session_block(entry.object, timezone) }}
+ {% elif entry.type.name == 'BREAK' -%}
+ {{ render_break(entry.object, timezone) }}
+ {% endif %}
+{% endmacro %}
+
+
+ |
+ {% for day, _ in days %}
+
+ {% endfor %}
+
+
+
+ {% for day, entries in days %}
+
+
+ {% for entry in entries %}
+ {% if entry.start_dt.astimezone(tz_object).hour < 12 %}
+ {{ render_entry(entry, tz_object, loop.index) }}
+ {% endif %}
+ {% endfor %}
+
+ |
+ {% endfor %}
+
+
+
+ {% for day, entries in days %}
+
+
+ {% for entry in entries %}
+ {% if entry.start_dt.astimezone(tz_object).hour >= 12 %}
+ {{ render_entry(entry, tz_object, loop.index) }}
+ {% endif %}
+ {% endfor %}
+
+ |
+ {% endfor %}
+
diff --git a/themes_legacy/indico_themes_legacy/themes-legacy.yaml b/themes_legacy/indico_themes_legacy/themes-legacy.yaml
new file mode 100644
index 0000000..065e027
--- /dev/null
+++ b/themes_legacy/indico_themes_legacy/themes-legacy.yaml
@@ -0,0 +1,10 @@
+definitions:
+ nicecompact:
+ event_types: [conference, meeting]
+ stylesheet: compact.scss
+ template: :compact_event.html
+ tt_template: :compact_timetable.html
+ title: Compact style
+ user_visible: true
+ settings:
+ page_is_dark: false
diff --git a/themes_legacy/indico_themes_legacy/themes/.no-headers b/themes_legacy/indico_themes_legacy/themes/.no-headers
new file mode 100644
index 0000000..e69de29
diff --git a/themes_legacy/indico_themes_legacy/themes/compact.scss b/themes_legacy/indico_themes_legacy/themes/compact.scss
new file mode 100644
index 0000000..8aed2d6
--- /dev/null
+++ b/themes_legacy/indico_themes_legacy/themes/compact.scss
@@ -0,0 +1,121 @@
+@import 'base/palette';
+
+div.main {
+ color: #000;
+ background: #fff;
+ font-family: helvetica, verdana, sans-serif;
+
+ > div {
+ overflow: auto;
+ }
+
+ p,
+ br,
+ dl,
+ strong,
+ em,
+ h1,
+ h2,
+ a {
+ font-family: helvetica, verdana, sans-serif;
+ font-size: 8pt;
+ color: #000;
+ }
+
+ td {
+ font-family: helvetica, verdana, sans-serif;
+ font-size: 8pt;
+ color: #000;
+ }
+
+ table p {
+ margin-top: 0;
+ }
+
+ .headerselected {
+ color: #fff;
+ background: #006;
+ }
+
+ a:visited {
+ color: #00f;
+ background: transparent;
+ text-decoration: none;
+ }
+
+ a:active {
+ color: $bright-orange;
+ background: transparent;
+ }
+
+ a:hover {
+ color: $bright-orange;
+ background: transparent;
+ }
+
+ a.img:hover {
+ color: #00c;
+ background: transparent;
+ }
+
+ a.img:active {
+ color: #00c;
+ background: transparent;
+ font-weight: normal;
+ }
+
+ table.eventHeader {
+ background: white;
+ width: 100%;
+ }
+
+ table.headerLegendsBorder {
+ background: silver;
+ border-spacing: 3px;
+ border: 0;
+ text-align: right;
+ }
+
+ table.headerLegendsContent {
+ background: white;
+ border-spacing: 0;
+ border: 0;
+ width: 100%;
+ text-align: right;
+ }
+
+ td.headerLegends {
+ text-align: right;
+ }
+
+ td.sessionsLegend {
+ background: #90c0f0;
+ }
+
+ td.contribsLegendSilver {
+ background: silver;
+ }
+
+ td.contribsLegendGrey {
+ background: #d2d2d2;
+ }
+
+ td.breaksLegend {
+ background: #fcc;
+ }
+
+ table.dayList {
+ background: white;
+ border-spacing: 1px;
+ border: 0;
+ width: 100%;
+ }
+
+ .titleClass {
+ font-weight: bold;
+ }
+
+ .speakerList {
+ color: green;
+ }
+}
diff --git a/themes_legacy/setup.cfg b/themes_legacy/setup.cfg
new file mode 100644
index 0000000..d8e0c8c
--- /dev/null
+++ b/themes_legacy/setup.cfg
@@ -0,0 +1,30 @@
+[metadata]
+name = indico-plugin-themes-legacy
+version = 3.0-dev
+description = Legacy themes for Indico
+url = https://github.com/indico/indico-plugins
+license = MIT
+author = Indico Team
+author_email = indico-team@cern.ch
+classifiers =
+ Environment :: Plugins
+ Environment :: Web Environment
+ License :: OSI Approved :: MIT License
+ Programming Language :: Python :: 3.9
+
+[options]
+packages = find:
+zip_safe = false
+include_package_data = true
+python_requires = ~=3.9
+install_requires =
+ indico>=3.0.dev0
+
+[options.entry_points]
+indico.plugins =
+ themes_legacy = indico_themes_legacy.plugin:LegacyThemesPlugin
+
+
+
+[pydocstyle]
+ignore = D100,D101,D102,D103,D104,D105,D107,D203,D213
diff --git a/themes_legacy/setup.py b/themes_legacy/setup.py
new file mode 100644
index 0000000..03c7604
--- /dev/null
+++ b/themes_legacy/setup.py
@@ -0,0 +1,11 @@
+# This file is part of the Indico plugins.
+# Copyright (C) 2002 - 2021 CERN
+#
+# The Indico plugins are free software; you can redistribute
+# them and/or modify them under the terms of the MIT License;
+# see the LICENSE file for more details.
+
+from setuptools import setup
+
+
+setup()
diff --git a/themes_legacy/webpack-bundles.json b/themes_legacy/webpack-bundles.json
new file mode 100644
index 0000000..6cfeb50
--- /dev/null
+++ b/themes_legacy/webpack-bundles.json
@@ -0,0 +1,3 @@
+{
+ "indicoTheme": "indico_themes_legacy/themes-legacy.yaml"
+}