diff options
| -rw-r--r-- | config-example.json | 14 | ||||
| -rwxr-xr-x | export.py | 15 | ||||
| -rw-r--r-- | instance/.gitignore | 0 | ||||
| -rwxr-xr-x | rater.py | 84 | ||||
| -rw-r--r-- | requirements.txt | 28 | ||||
| -rw-r--r-- | static/rater.css | 23 | ||||
| -rw-r--r-- | templates/index.html | 21 |
7 files changed, 99 insertions, 86 deletions
diff --git a/config-example.json b/config-example.json index 5c4e4bc..6afccea 100644 --- a/config-example.json +++ b/config-example.json | |||
| @@ -1,19 +1,19 @@ | |||
| 1 | { | 1 | { |
| 2 | "track": "polsoc", | 2 | "track": "polsoc", |
| 3 | "track-name": "Ethics%2C+Society+%26+Politics", | 3 | "track-name": "Ethics%2C+Society+%26+Politics", |
| 4 | "track-id": 7, | ||
| 4 | "host": "127.0.0.1", | 5 | "host": "127.0.0.1", |
| 5 | "port": 5000, | 6 | "port": 5000, |
| 6 | "frab-url": "https://frab.cccv.de/", | 7 | "pretalx-url": "https://cfp.cccv.de/", |
| 7 | "frab-user": "<FRAB-USER>", | 8 | "pretalx-token": "<PRETALX-TOKEN>", |
| 8 | "frab-password": "<FRAB-PASSWORD>", | 9 | "pretalx-conference": "38c3", |
| 9 | "frab-conference": "36C3", | ||
| 10 | "rt-url": "https://rt.cccv.de/", | 10 | "rt-url": "https://rt.cccv.de/", |
| 11 | "rt-user": "<RT-USER>", | 11 | "rt-user": "<RT-USER>", |
| 12 | "rt-password": "<RT-PASS>", | 12 | "rt-password": "<RT-PASS>", |
| 13 | "categories": [ "Relevanz", "Expertise", "Praesentation", "Nachfrage" ], | 13 | "categories": [ "Relevanz", "Expertise", "Praesentation", "Nachfrage" ], |
| 14 | "frab-person-map": { | 14 | "pretalx-person-map": { |
| 15 | "anna": 12345, | 15 | "anna": "", |
| 16 | "ben": 6789 | 16 | "ben": "" |
| 17 | }, | 17 | }, |
| 18 | "rt-person-map": { | 18 | "rt-person-map": { |
| 19 | "anna": "anna@mail.org", | 19 | "anna": "anna@mail.org", |
| @@ -11,7 +11,7 @@ import sys | |||
| 11 | dryrun=False | 11 | dryrun=False |
| 12 | 12 | ||
| 13 | parser = ArgumentParser(description="C3 rating helper") | 13 | parser = ArgumentParser(description="C3 rating helper") |
| 14 | parser.add_argument("-d", action="store_true", dest="dryrun", default=False, help="Don't actually execute anything on frab or rt, just show what would have been done") | 14 | parser.add_argument("-d", action="store_true", dest="dryrun", default=False, help="Don't actually execute anything on pretalx or rt, just show what would have been done") |
| 15 | args = parser.parse_args() | 15 | args = parser.parse_args() |
| 16 | 16 | ||
| 17 | if args.dryrun: | 17 | if args.dryrun: |
| @@ -21,7 +21,7 @@ with open(args.config, mode="r", encoding="utf-8") as json_file: | |||
| 21 | cfg = json.load(json_file) | 21 | cfg = json.load(json_file) |
| 22 | 22 | ||
| 23 | app = Flask(__name__) | 23 | app = Flask(__name__) |
| 24 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + cfg['frab-conference'] + '-' + cfg['track'] + '.db' | 24 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + cfg['pretalx-conference'] + '-' + cfg['track'] + '.db' |
| 25 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | 25 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| 26 | app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' | 26 | app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' |
| 27 | app.jinja_env.trim_blocks = True | 27 | app.jinja_env.trim_blocks = True |
| @@ -30,13 +30,12 @@ app.jinja_env.lstrip_blocks = True | |||
| 30 | db = SQLAlchemy(app) | 30 | db = SQLAlchemy(app) |
| 31 | 31 | ||
| 32 | config['rt-rest-url'] = cfg['rt-url'] + 'REST/1.0/' | 32 | config['rt-rest-url'] = cfg['rt-url'] + 'REST/1.0/' |
| 33 | config['frab-conf-url'] = config['frab-url'] + config['frab-conference'] | 33 | config['pretalx-conf-url'] = config['pretalx-url'] + config['pretalx-conference'] |
| 34 | 34 | ||
| 35 | class Event(db.Model): | 35 | class Event(db.Model): |
| 36 | """An event as dumped from frab""" | 36 | """An event as dumped from pretalx""" |
| 37 | frab_id = db.Column(db.Integer, primary_key=True) | 37 | pretalx_id = db.Column(db.String(16), primary_key=True) |
| 38 | title = db.Column(db.String(1024)) | 38 | title = db.Column(db.String(1024)) |
| 39 | subtitle = db.Column(db.String(1024)) | ||
| 40 | abstract = db.Column(db.Text()) | 39 | abstract = db.Column(db.Text()) |
| 41 | description = db.Column(db.Text()) | 40 | description = db.Column(db.Text()) |
| 42 | state = db.Column(db.String(64)) | 41 | state = db.Column(db.String(64)) |
| @@ -49,13 +48,13 @@ class EventRating(db.Model): | |||
| 49 | """A rating as given by a logged in user""" | 48 | """A rating as given by a logged in user""" |
| 50 | id = db.Column(db.Integer, primary_key=True) | 49 | id = db.Column(db.Integer, primary_key=True) |
| 51 | submitter = db.Column(db.String(1024)) | 50 | submitter = db.Column(db.String(1024)) |
| 52 | event_id = db.Column(db.Integer, db.ForeignKey('event.frab_id')) | 51 | event_id = db.Column(db.Integer, db.ForeignKey('event.pretalx_id')) |
| 53 | event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) | 52 | event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) |
| 54 | comment = db.Column(db.Text()) | 53 | comment = db.Column(db.Text()) |
| 55 | rating_dict = db.Column(db.String(1024), server_default="{}") | 54 | rating_dict = db.Column(db.String(1024), server_default="{}") |
| 56 | 55 | ||
| 57 | def add_coordinator(sess, person, event): | 56 | def add_coordinator(sess, person, event): |
| 58 | edit_person_page = sess.get(config['frab-conf-url'] + '/events/' + event + '/edit_people') | 57 | edit_person_page = sess.get(config['pretalx-conf-url'] + '/events/' + event + '/edit_people') |
| 59 | tree = etree.HTML(edit_person_page.text) | 58 | tree = etree.HTML(edit_person_page.text) |
| 60 | for option in tree.xpath('//option[@selected]'): | 59 | for option in tree.xpath('//option[@selected]'): |
| 61 | if option.text.lower() == 'coordinator': | 60 | if option.text.lower() == 'coordinator': |
diff --git a/instance/.gitignore b/instance/.gitignore new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/instance/.gitignore | |||
| @@ -12,7 +12,7 @@ import json | |||
| 12 | # urllib3.contrib.pyopenssl.inject_into_urllib3() | 12 | # urllib3.contrib.pyopenssl.inject_into_urllib3() |
| 13 | 13 | ||
| 14 | parser = ArgumentParser(description="C3 rating helper") | 14 | parser = ArgumentParser(description="C3 rating helper") |
| 15 | parser.add_argument("-i", action="store_true", dest="frab_import", default=False, help="import events from frab") | 15 | parser.add_argument("-i", action="store_true", dest="pretalx_import", default=False, help="import events from pretalx") |
| 16 | parser.add_argument("-c", "--config", help="Config file location", default="./config.json") | 16 | parser.add_argument("-c", "--config", help="Config file location", default="./config.json") |
| 17 | args = parser.parse_args() | 17 | args = parser.parse_args() |
| 18 | 18 | ||
| @@ -20,7 +20,7 @@ with open(args.config, mode="r", encoding="utf-8") as json_file: | |||
| 20 | config = json.load(json_file) | 20 | config = json.load(json_file) |
| 21 | 21 | ||
| 22 | app = Flask(__name__) | 22 | app = Flask(__name__) |
| 23 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config['frab-conference'] + '-' + config['track'] + '.db' | 23 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + config['pretalx-conference'] + '-' + config['track'] + '.db' |
| 24 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | 24 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
| 25 | app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' | 25 | app.config['SECRET_KEY'] = 'Silence is golden. Gerd Eist.' |
| 26 | app.jinja_env.trim_blocks = True | 26 | app.jinja_env.trim_blocks = True |
| @@ -28,11 +28,12 @@ app.jinja_env.lstrip_blocks = True | |||
| 28 | 28 | ||
| 29 | db = SQLAlchemy(app) | 29 | db = SQLAlchemy(app) |
| 30 | 30 | ||
| 31 | config['frab-conf-url'] = config['frab-url'] + config['frab-conference'] | 31 | config['pretalx-conf-url'] = config['pretalx-url'] + 'orga/event/' + config['pretalx-conference'] |
| 32 | config['pretalx-api-url'] = config['pretalx-url'] + 'api/events/' + config['pretalx-conference'] + '/submissions?track_id' + str(config['track-id']) | ||
| 32 | 33 | ||
| 33 | class Event(db.Model): | 34 | class Event(db.Model): |
| 34 | """An event as dumped from frab""" | 35 | """An event as dumped from pretalx""" |
| 35 | frab_id = db.Column(db.Integer, primary_key=True) | 36 | pretalx_id = db.Column(db.String(64), primary_key=True) |
| 36 | title = db.Column(db.String(1024)) | 37 | title = db.Column(db.String(1024)) |
| 37 | subtitle = db.Column(db.String(1024)) | 38 | subtitle = db.Column(db.String(1024)) |
| 38 | abstract = db.Column(db.Text()) | 39 | abstract = db.Column(db.Text()) |
| @@ -42,12 +43,13 @@ class Event(db.Model): | |||
| 42 | speakers = db.Column(db.String(1024)) | 43 | speakers = db.Column(db.String(1024)) |
| 43 | coordinator = db.Column(db.String(1024)) | 44 | coordinator = db.Column(db.String(1024)) |
| 44 | notes = db.Column(db.Text()) | 45 | notes = db.Column(db.Text()) |
| 46 | duration = db.Column(db.Integer()) | ||
| 45 | 47 | ||
| 46 | class EventRating(db.Model): | 48 | class EventRating(db.Model): |
| 47 | """A rating as given by a logged in user""" | 49 | """A rating as given by a logged in user""" |
| 48 | id = db.Column(db.Integer, primary_key=True) | 50 | id = db.Column(db.Integer, primary_key=True) |
| 49 | submitter = db.Column(db.String(1024)) | 51 | submitter = db.Column(db.String(1024)) |
| 50 | event_id = db.Column(db.Integer, db.ForeignKey('event.frab_id')) | 52 | pretalx_id = db.Column(db.String(64), db.ForeignKey('event.pretalx_id')) |
| 51 | event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) | 53 | event = db.relationship('Event', backref=db.backref('ratings', lazy='dynamic')) |
| 52 | comment = db.Column(db.Text()) | 54 | comment = db.Column(db.Text()) |
| 53 | rating_dict = db.Column(db.String(1024), server_default="{}") | 55 | rating_dict = db.Column(db.String(1024), server_default="{}") |
| @@ -64,7 +66,7 @@ def get_ratings(): | |||
| 64 | @app.route('/api/set_event_state/<eventid>', methods=['POST']) | 66 | @app.route('/api/set_event_state/<eventid>', methods=['POST']) |
| 65 | def set_sevent_state(eventid): | 67 | def set_sevent_state(eventid): |
| 66 | content = request.json | 68 | content = request.json |
| 67 | dbevent = Event.query.get(eventid) | 69 | dbevent = db.session.get(Event, eventid) |
| 68 | dbevent.state = content.get('state', 'new') | 70 | dbevent.state = content.get('state', 'new') |
| 69 | db.session.commit() | 71 | db.session.commit() |
| 70 | return jsonify({"result":"ok"}) | 72 | return jsonify({"result":"ok"}) |
| @@ -72,14 +74,14 @@ def set_sevent_state(eventid): | |||
| 72 | @app.route('/api/set_event_coordinator/<eventid>', methods=['POST']) | 74 | @app.route('/api/set_event_coordinator/<eventid>', methods=['POST']) |
| 73 | def set_sevent_coordinator(eventid): | 75 | def set_sevent_coordinator(eventid): |
| 74 | content = request.json | 76 | content = request.json |
| 75 | dbevent = Event.query.get(eventid) | 77 | dbevent = db.session.get(Event, eventid) |
| 76 | dbevent.coordinator = content['coordinator'] | 78 | dbevent.coordinator = content['coordinator'] |
| 77 | db.session.commit() | 79 | db.session.commit() |
| 78 | return jsonify({"result":"ok"}) | 80 | return jsonify({"result":"ok"}) |
| 79 | 81 | ||
| 80 | @app.route('/api/remove_event/<eventid>', methods=['POST']) | 82 | @app.route('/api/remove_event/<eventid>', methods=['POST']) |
| 81 | def remove_event(eventid): | 83 | def remove_event(eventid): |
| 82 | dbevent = Event.query.get(eventid) | 84 | dbevent = db.session.get(Event, eventid) |
| 83 | if dbevent.state == 'gone': | 85 | if dbevent.state == 'gone': |
| 84 | db.session.delete(dbevent) | 86 | db.session.delete(dbevent) |
| 85 | db.session.commit() | 87 | db.session.commit() |
| @@ -88,7 +90,7 @@ def remove_event(eventid): | |||
| 88 | @app.route('/api/remove_rating/<eventid>', methods=['POST']) | 90 | @app.route('/api/remove_rating/<eventid>', methods=['POST']) |
| 89 | def remove_rating(eventid): | 91 | def remove_rating(eventid): |
| 90 | content = request.json | 92 | content = request.json |
| 91 | rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() | 93 | rating = EventRating.query.filter_by(pretalx_id = eventid, submitter = content['author']).first() |
| 92 | if rating: | 94 | if rating: |
| 93 | db.session.delete(rating) | 95 | db.session.delete(rating) |
| 94 | db.session.commit() | 96 | db.session.commit() |
| @@ -100,7 +102,7 @@ def add_rating(eventid): | |||
| 100 | print ( str(eventid) + " " + str(content)) | 102 | print ( str(eventid) + " " + str(content)) |
| 101 | r = content.get('ratings', '{}'); | 103 | r = content.get('ratings', '{}'); |
| 102 | 104 | ||
| 103 | rating = EventRating.query.filter_by(event_id = eventid, submitter = content['author']).first() | 105 | rating = EventRating.query.filter_by(pretalx_id = eventid, submitter = content['author']).first() |
| 104 | 106 | ||
| 105 | rd = json.dumps({ k: r.get(k,'0') for k in ['category1', 'category2', 'category3', 'category4'] }) | 107 | rd = json.dumps({ k: r.get(k,'0') for k in ['category1', 'category2', 'category3', 'category4'] }) |
| 106 | if rating: | 108 | if rating: |
| @@ -108,65 +110,57 @@ def add_rating(eventid): | |||
| 108 | rating.comment = content['comment'] | 110 | rating.comment = content['comment'] |
| 109 | rating.rating_dict = rd | 111 | rating.rating_dict = rd |
| 110 | else: | 112 | else: |
| 111 | db.session.add( EventRating( submitter = content.get('author','anonymous'), event_id = eventid, comment = content['comment'], rating_dict = rd)) | 113 | db.session.add( EventRating( submitter = content.get('author','anonymous'), pretalx_id = eventid, comment = content['comment'], rating_dict = rd)) |
| 112 | 114 | ||
| 113 | db.session.commit() | 115 | db.session.commit() |
| 114 | return jsonify({"result":"ok"}) | 116 | return jsonify({"result":"ok"}) |
| 115 | 117 | ||
| 116 | def fetch_talks(): | 118 | def fetch_talks(): |
| 117 | sess = requests.Session() | 119 | sess = requests.Session() |
| 118 | new_session_page = sess.get(config['frab-url']) | 120 | |
| 119 | tree = etree.HTML(new_session_page.text) | 121 | response = sess.get(config['pretalx-api-url'] + '&format=json&limit=20000' , verify=False, stream=True, headers={'Authorization': "Token " + config['pretalx-token']}) |
| 120 | auth_token = tree.xpath("//meta[@name='csrf-token']")[0].get("content") | ||
| 121 | login_data = dict() | ||
| 122 | login_data['user[email]'] = config['frab-user'] | ||
| 123 | login_data['user[password]'] = config['frab-password'] | ||
| 124 | login_data['user[remember_me]'] = 1 | ||
| 125 | login_data['authenticity_token'] = auth_token | ||
| 126 | |||
| 127 | sess.post(config['frab-url'] + 'users/sign_in?conference_acronym=' + config['frab-conference'] + '&locale=en', login_data, verify=False) | ||
| 128 | response = sess.get(config['frab-conf-url'] + '/events?track_name=' + config['track-name'] + '&format=json', verify=False, stream=True) | ||
| 129 | 122 | ||
| 130 | talks_json = json.loads(response.text) | 123 | talks_json = json.loads(response.text) |
| 131 | 124 | ||
| 132 | # with open('dump.txt', mode='wb') as localfile: | 125 | # with open('dump.txt', mode='wb') as localfile: |
| 133 | # localfile.write(response.content) | 126 | # localfile.write(response.content) |
| 127 | |||
| 128 | submissions = [s for s in talks_json['results'] if s['track_id'] == config['track-id'] ] | ||
| 134 | 129 | ||
| 135 | imported = 0 | 130 | imported = 0 |
| 136 | for json_event in talks_json['events']: | 131 | for json_event in submissions: |
| 137 | # print (json_event) | 132 | print (json_event) |
| 138 | rawhtml = sess.get(config['frab-conf-url'] + '/events/'+ str(json_event['id']), verify=False, stream=True) | 133 | |
| 139 | tree = etree.HTML(rawhtml.text) | 134 | dbevent = db.session.get(Event, json_event['code']) |
| 140 | submission_notes = tree.xpath('//b[text()="Submission Notes(user and admin):"]')[0].tail.strip() | 135 | speakers = { speaker['code']: speaker['name'] for speaker in json_event['speakers'] } |
| 141 | 136 | submission_type = json_event['submission_type'].get('de') or json_event['submission_type'].get('en') | |
| 142 | dbevent = Event.query.get(json_event['id']) | ||
| 143 | speakers = { speaker['id']: speaker['full_public_name'] for speaker in json_event['speakers'] } | ||
| 144 | if dbevent: | 137 | if dbevent: |
| 145 | dbevent.title = json_event['title'] | 138 | dbevent.title = json_event['title'] |
| 146 | dbevent.subtitle = json_event['subtitle'] | ||
| 147 | dbevent.abstract = json_event['abstract'] | 139 | dbevent.abstract = json_event['abstract'] |
| 148 | dbevent.description = json_event['description'] | 140 | dbevent.description = json_event['description'] |
| 149 | dbevent.event_type = json_event['type'] | 141 | dbevent.event_type = submission_type |
| 150 | dbevent.notes = submission_notes | 142 | dbevent.notes = json_event.get('notes') |
| 143 | dbevent.duration = int(json_event['duration']) | ||
| 151 | if 'state' in json_event: | 144 | if 'state' in json_event: |
| 152 | if json_event['state'] != 'new' or dbevent.state == 'gone': | 145 | if json_event['state'] != 'submitted' or dbevent.state == 'gone': |
| 153 | dbevent.state = json_event['state'] | 146 | dbevent.state = json_event['state'] |
| 154 | dbevent.speakers = json.dumps(speakers) | 147 | dbevent.speakers = json.dumps(speakers) |
| 155 | else: | 148 | else: |
| 156 | db.session.add( Event( frab_id = json_event['id'], title = json_event['title'], subtitle = json_event['subtitle'], abstract = json_event['abstract'], description = json_event['description'], speakers = json.dumps(speakers), state = json_event.get('state', 'new'), event_type = json_event['type'], notes = submission_notes) ) | 149 | db.session.add( Event( pretalx_id = json_event['code'], title = json_event['title'], abstract = json_event['abstract'], description = json_event['description'], speakers = json.dumps(speakers), state = json_event.get('state', 'submitted'), event_type = submission_type, notes = json_event.get('notes'), duration = int(json_event['duration'])) ) |
| 157 | imported += 1 | 150 | imported += 1 |
| 158 | 151 | ||
| 159 | for goner in Event.query.filter( Event.frab_id.notin_([ ev['id'] for ev in talks_json['events'] ])).all(): | 152 | for goner in Event.query.filter( Event.pretalx_id.notin_([ ev['code'] for ev in submissions ])).all(): |
| 160 | goner.state = 'gone' | 153 | goner.state = 'gone' |
| 161 | 154 | ||
| 162 | db.session.commit() | 155 | db.session.commit() |
| 163 | print ('Conference: ' + config['track'] + ', track: ' + config['track'] + ', imported ' + str(len(talks_json['events'])) + ' events, ' + str(imported) + ' new.') | 156 | print ('Conference: ' + config['track'] + ', track: ' + config['track'] + ', imported ' + str(len(submissions)) + ' events, ' + str(imported) + ' new.') |
| 164 | 157 | ||
| 165 | 158 | ||
| 166 | if __name__ == "__main__": | 159 | if __name__ == "__main__": |
| 167 | db.create_all() | 160 | with app.app_context(): |
| 168 | if args.frab_import: | 161 | db.create_all() |
| 169 | fetch_talks() | 162 | if args.pretalx_import: |
| 170 | else: | 163 | fetch_talks() |
| 171 | app.run(host=config.get('host', '127.0.0.1'), port=int(config.get('port', '8080'))) | 164 | else: |
| 165 | app.run(host=config.get('host', '127.0.0.1'), port=int(config.get('port', '8080'))) | ||
| 172 | 166 | ||
diff --git a/requirements.txt b/requirements.txt index fa92333..1f599f3 100644 --- a/requirements.txt +++ b/requirements.txt | |||
| @@ -1,14 +1,14 @@ | |||
| 1 | certifi==2017.7.27.1 | 1 | certifi |
| 2 | chardet==3.0.4 | 2 | chardet |
| 3 | click==6.7 | 3 | click |
| 4 | Flask==0.12.2 | 4 | Flask |
| 5 | Flask-SQLAlchemy==2.2 | 5 | Flask-SQLAlchemy |
| 6 | idna==2.6 | 6 | idna |
| 7 | itsdangerous==0.24 | 7 | itsdangerous |
| 8 | Jinja2==2.9.6 | 8 | Jinja2 |
| 9 | lxml==3.8.0 | 9 | lxml |
| 10 | MarkupSafe==1.0 | 10 | MarkupSafe |
| 11 | requests==2.18.4 | 11 | requests |
| 12 | SQLAlchemy==1.1.14 | 12 | SQLAlchemy |
| 13 | urllib3==1.22 | 13 | urllib3 |
| 14 | Werkzeug==0.12.2 | 14 | Werkzeug |
diff --git a/static/rater.css b/static/rater.css index ae54a13..b73f4a0 100644 --- a/static/rater.css +++ b/static/rater.css | |||
| @@ -112,10 +112,31 @@ body.four-column .event-list-item { | |||
| 112 | font-weight: bold; | 112 | font-weight: bold; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | .event-duration, | ||
| 116 | .event-speaker-count, | ||
| 115 | .event-subtitle { | 117 | .event-subtitle { |
| 116 | font-size: smaller; | 118 | font-size: smaller; |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 121 | .event-speaker-count, | ||
| 122 | .event-duration { | ||
| 123 | display: inline; | ||
| 124 | font-weight: bold; | ||
| 125 | background-color: cyan; | ||
| 126 | border-radius: 2px; | ||
| 127 | margin: 0.2em; | ||
| 128 | padding: 0.2em; | ||
| 129 | } | ||
| 130 | |||
| 131 | .event-duration:before { content: '🕒 '; } | ||
| 132 | .event-speaker-count:before { content: '👥 '; } | ||
| 133 | |||
| 134 | .event-duration:before, | ||
| 135 | .event-speaker-count:before { | ||
| 136 | font-size: smaller; | ||
| 137 | padding-bottom: 0.2rem; | ||
| 138 | } | ||
| 139 | |||
| 119 | .event-rating-comment { | 140 | .event-rating-comment { |
| 120 | min-height: 3em; | 141 | min-height: 3em; |
| 121 | margin-top: 0.1em; | 142 | margin-top: 0.1em; |
| @@ -283,7 +304,7 @@ meter.meter-4::-webkit-meter-bar { | |||
| 283 | clear: both; | 304 | clear: both; |
| 284 | } | 305 | } |
| 285 | 306 | ||
| 286 | body.only-lectures .event-list-item:not([event_type="lecture"]), | 307 | body.only-lectures .event-list-item:not([event_type="Talk"]), |
| 287 | body.only-todo .event-list-item.has-own-rating, | 308 | body.only-todo .event-list-item.has-own-rating, |
| 288 | .filtered, | 309 | .filtered, |
| 289 | .hidden { | 310 | .hidden { |
diff --git a/templates/index.html b/templates/index.html index c8ccf71..1d42018 100644 --- a/templates/index.html +++ b/templates/index.html | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | <html> | 1 | <html> |
| 2 | <title>{{ config.get('frab-conference') }} {{ config.get('track') }} rating helper</title> | 2 | <title>{{ config.get('pretalx-conference') }} {{ config.get('track') }} rating helper</title> |
| 3 | <head> | 3 | <head> |
| 4 | <script type="text/javascript">categories = { | 4 | <script type="text/javascript">categories = { |
| 5 | {%- for category in config['categories'] -%} | 5 | {%- for category in config['categories'] -%} |
| @@ -69,28 +69,27 @@ | |||
| 69 | 69 | ||
| 70 | <ul id="event-list"> | 70 | <ul id="event-list"> |
| 71 | {% for ev in events -%} | 71 | {% for ev in events -%} |
| 72 | <li class="event-list-item" event_state="{{ev.state}}" event_type="{{ev.event_type}}" id="event-{{ev.frab_id}}"> | 72 | <li class="event-list-item" event_state="{{ev.state}}" event_type="{{ev.event_type}}" event_duration="{{ev.duration}}" event_speaker_count="{{ json.loads(ev.speakers) | length}}" id="event-{{ev.pretalx_id}}"> |
| 73 | <div class="event-meter-bar"> | 73 | <div class="event-meter-bar"> |
| 74 | {%- for m in range(1+config['categories']|length) -%} | 74 | {%- for m in range(1+config['categories']|length) -%} |
| 75 | <meter class="top-meter meter-{{m}}" id="event-{{ev.frab_id}}-meter-{{m}}" value="0" min="0" max="100"></meter> | 75 | <meter class="top-meter meter-{{m}}" id="event-{{ev.pretalx_id}}-meter-{{m}}" value="0" min="0" max="100"></meter> |
| 76 | {%- endfor -%} | 76 | {%- endfor -%} |
| 77 | </div> | 77 | </div> |
| 78 | {%- if not ev.state == 'gone' -%} | 78 | {%- if not ev.state == 'gone' -%} |
| 79 | <button onclick="do_set_state('{{ev.frab_id}}', 'accepted')" title="accept this event" class="mini-button accept-button">acc</button><button onclick="do_set_state('{{ev.frab_id}}', 'rejected')" title="reject this event" class="mini-button reject-button">rej</button><button onclick="toggleEdit('{{ev.frab_id}}')" title="edit this event" class="edit-button mini-button">edit</button><button onclick="do_take('{{ev.frab_id}}')" title="make me coordinator for this event" class="mini-button take-button">take</button> | 79 | <button onclick="do_set_state('{{ev.pretalx_id}}', 'accepted')" title="accept this event" class="mini-button accept-button">acc</button><button onclick="do_set_state('{{ev.pretalx_id}}', 'rejected')" title="reject this event" class="mini-button reject-button">rej</button><button onclick="toggleEdit('{{ev.pretalx_id}}')" title="edit this event" class="edit-button mini-button">edit</button><button onclick="do_take('{{ev.pretalx_id}}')" title="make me coordinator for this event" class="mini-button take-button">take</button> |
| 80 | {%- else -%} | 80 | {%- else -%} |
| 81 | <button onclick="do_remove_event('{{ev.frab_id}}')" title="remove this event" class="mini-button remove-button">del</button> | 81 | <button onclick="do_remove_event('{{ev.pretalx_id}}')" title="remove this event" class="mini-button remove-button">del</button> |
| 82 | {%- endif -%} | ||
| 83 | <div class="event-title"><a href="{{ config['frab-conf-url'] }}/events/{{ ev.frab_id }}/">{{ ev.title }}</a></div> | ||
| 84 | {%- if ev.subtitle -%} | ||
| 85 | <div class="event-subtitle"> {{ ev.subtitle }}</div> | ||
| 86 | {%- endif -%} | 82 | {%- endif -%} |
| 83 | <div class="event-duration">{{ev.duration}}</div> | ||
| 84 | <div class="event-speaker-count">{{ json.loads(ev.speakers) | length}}</div> | ||
| 85 | <div class="event-title"><a href="{{ config['pretalx-conf-url'] }}/submissions/{{ ev.pretalx_id }}/">{{ ev.title }}</a></div> | ||
| 87 | <div class="event-persons"> | 86 | <div class="event-persons"> |
| 88 | {%- if ev.coordinator -%} | 87 | {%- if ev.coordinator -%} |
| 89 | <div class="event-coordinator" coordinator="{{ev.coordinator}}"><em>coordinator: </em> {{ev.coordinator}}</div> | 88 | <div class="event-coordinator" coordinator="{{ev.coordinator}}"><em>coordinator: </em> {{ev.coordinator}}</div> |
| 90 | {%- endif -%} | 89 | {%- endif -%} |
| 91 | <div class="event-speaker"><em>speakers: </em> | 90 | <div class="event-speaker"><em>speakers: </em> |
| 92 | {%- for speaker_id, speaker_name in json.loads(ev.speakers or '{}').items() -%} | 91 | {%- for speaker_id, speaker_name in json.loads(ev.speakers or '{}').items() -%} |
| 93 | <a href="{{ config['frab-conf-url'] }}/people/{{speaker_id}}">{{speaker_name}}</a> | 92 | <a href="{{ config['pretalx-conf-url'] }}/speakers/{{speaker_id}}">{{speaker_name}}</a> |
| 94 | {%- endfor -%} | 93 | {%- endfor -%} |
| 95 | </div> | 94 | </div> |
| 96 | </div> | 95 | </div> |
| @@ -103,7 +102,7 @@ | |||
| 103 | {%- endif -%} | 102 | {%- endif -%} |
| 104 | <div class="event-ratings"> | 103 | <div class="event-ratings"> |
| 105 | {%- for rating in ev.ratings -%} | 104 | {%- for rating in ev.ratings -%} |
| 106 | <div class="event-rating" id="event-rating-{{ev.frab_id}}" submitter="{{rating.submitter}}"> | 105 | <div class="event-rating" id="event-rating-{{ev.pretalx_id}}" submitter="{{rating.submitter}}"> |
| 107 | <div class="event-rating-submitter">{{rating.submitter}}:</div> | 106 | <div class="event-rating-submitter">{{rating.submitter}}:</div> |
| 108 | {%- for category, value in json.loads(rating.rating_dict or '{}').items()|sort -%} | 107 | {%- for category, value in json.loads(rating.rating_dict or '{}').items()|sort -%} |
| 109 | <div><meter category="{{category}}" value="{{value}}" min="0" max="100"></meter><span class="event-rating-category-output" category="{{category}}"> {{ config['categories'][loop.index-1] + " " + value|string + " %" }}</span></div> | 108 | <div><meter category="{{category}}" value="{{value}}" min="0" max="100"></meter><span class="event-rating-category-output" category="{{category}}"> {{ config['categories'][loop.index-1] + " " + value|string + " %" }}</span></div> |
