forked from boyska/sito-hackit-17
plugin talks configurabile
This commit is contained in:
parent
3b80ed79b0
commit
3d172beb73
2 changed files with 50 additions and 35 deletions
|
@ -2,6 +2,7 @@
|
||||||
Manage talks scheduling in a semantic way
|
Manage talks scheduling in a semantic way
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os
|
import os
|
||||||
import io
|
import io
|
||||||
|
@ -23,11 +24,9 @@ from docutils.parsers.rst import directives, Directive
|
||||||
from pelican import signals, generators
|
from pelican import signals, generators
|
||||||
import jinja2
|
import jinja2
|
||||||
|
|
||||||
|
pelican = None # This will be set during register()
|
||||||
|
|
||||||
|
|
||||||
TALKS_PATH = 'talks'
|
|
||||||
TALK_ATTACHMENT_PATH = 'res'
|
|
||||||
TALK_ICS = 'schedule.ics'
|
|
||||||
GRID_STEP = 30
|
|
||||||
|
|
||||||
|
|
||||||
def memoize(function):
|
def memoize(function):
|
||||||
|
@ -56,7 +55,7 @@ def setlocale(name):
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def get_talk_names():
|
def get_talk_names():
|
||||||
return [name for name in os.listdir(TALKS_PATH)
|
return [name for name in os.listdir(pelican.settings['TALKS_PATH'])
|
||||||
if not name.startswith('_') and
|
if not name.startswith('_') and
|
||||||
get_talk_data(name) is not None
|
get_talk_data(name) is not None
|
||||||
]
|
]
|
||||||
|
@ -73,7 +72,7 @@ def unique_attr(iterable, attr):
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def get_global_data():
|
def get_global_data():
|
||||||
fname = os.path.join(TALKS_PATH, 'meta.yaml')
|
fname = os.path.join(pelican.settings['TALKS_PATH'], 'meta.yaml')
|
||||||
if not os.path.isfile(fname):
|
if not os.path.isfile(fname):
|
||||||
return None
|
return None
|
||||||
with io.open(fname, encoding='utf8') as buf:
|
with io.open(fname, encoding='utf8') as buf:
|
||||||
|
@ -92,7 +91,7 @@ def get_global_data():
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
def get_talk_data(talkname):
|
def get_talk_data(talkname):
|
||||||
fname = os.path.join(TALKS_PATH, talkname, 'meta.yaml')
|
fname = os.path.join(pelican.settings['TALKS_PATH'], talkname, 'meta.yaml')
|
||||||
if not os.path.isfile(fname):
|
if not os.path.isfile(fname):
|
||||||
return None
|
return None
|
||||||
with io.open(fname, encoding='utf8') as buf:
|
with io.open(fname, encoding='utf8') as buf:
|
||||||
|
@ -104,6 +103,7 @@ def get_talk_data(talkname):
|
||||||
if data is None:
|
if data is None:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
|
gridstep = pelican.settings['TALKS_GRID_STEP']
|
||||||
if 'title' not in data:
|
if 'title' not in data:
|
||||||
logging.warn("Talk <{}> has no `title` field".format(talkname))
|
logging.warn("Talk <{}> has no `title` field".format(talkname))
|
||||||
data['title'] = talkname
|
data['title'] = talkname
|
||||||
|
@ -115,10 +115,10 @@ def get_talk_data(talkname):
|
||||||
.format(talkname))
|
.format(talkname))
|
||||||
data['duration'] = 50
|
data['duration'] = 50
|
||||||
data['duration'] = int(data['duration'])
|
data['duration'] = int(data['duration'])
|
||||||
if data['duration'] < GRID_STEP:
|
if data['duration'] < gridstep:
|
||||||
logging.info("Talk <{}> lasts only {} minutes; changing to {}"
|
logging.info("Talk <{}> lasts only {} minutes; changing to {}"
|
||||||
.format(talkname, data['duration'], GRID_STEP))
|
.format(talkname, data['duration'], gridstep))
|
||||||
data['duration'] = GRID_STEP
|
data['duration'] = gridstep
|
||||||
if 'links' not in data or not data['links']:
|
if 'links' not in data or not data['links']:
|
||||||
data['links'] = []
|
data['links'] = []
|
||||||
if 'contacts' not in data or not data['contacts']:
|
if 'contacts' not in data or not data['contacts']:
|
||||||
|
@ -145,7 +145,8 @@ def get_talk_data(talkname):
|
||||||
else:
|
else:
|
||||||
logging.error("Talk <%s> has malformed `time`", talkname)
|
logging.error("Talk <%s> has malformed `time`", talkname)
|
||||||
data['id'] = talkname
|
data['id'] = talkname
|
||||||
resdir = os.path.join(TALKS_PATH, talkname, TALK_ATTACHMENT_PATH)
|
resdir = os.path.join(pelican.settings['TALKS_PATH'], talkname,
|
||||||
|
pelican.settings['TALKS_ATTACHMENT_PATH'])
|
||||||
if os.path.isdir(resdir) and os.listdir(resdir):
|
if os.path.isdir(resdir) and os.listdir(resdir):
|
||||||
data['resources'] = resdir
|
data['resources'] = resdir
|
||||||
return data
|
return data
|
||||||
|
@ -154,16 +155,19 @@ def get_talk_data(talkname):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
jinja_env = jinja2.Environment(
|
@memoize
|
||||||
loader=jinja2.FileSystemLoader(os.path.join(TALKS_PATH, '_templates')),
|
def jinja_env():
|
||||||
autoescape=True,
|
env = jinja2.Environment(
|
||||||
)
|
loader=jinja2.FileSystemLoader(os.path.join(pelican.settings['TALKS_PATH'], '_templates')),
|
||||||
jinja_env.filters['markdown'] = lambda text: \
|
autoescape=True,
|
||||||
jinja2.Markup(markdown.Markdown(extensions=['meta']).
|
)
|
||||||
convert(text))
|
env.filters['markdown'] = lambda text: \
|
||||||
jinja_env.filters['dateformat'] = format_date
|
jinja2.Markup(markdown.Markdown(extensions=['meta']).
|
||||||
jinja_env.filters['datetimeformat'] = format_datetime
|
convert(text))
|
||||||
jinja_env.filters['timeformat'] = format_time
|
env.filters['dateformat'] = format_date
|
||||||
|
env.filters['datetimeformat'] = format_datetime
|
||||||
|
env.filters['timeformat'] = format_time
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
class TalkListDirective(Directive):
|
class TalkListDirective(Directive):
|
||||||
|
@ -175,7 +179,7 @@ class TalkListDirective(Directive):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
lang = self.options.get('lang', 'C')
|
lang = self.options.get('lang', 'C')
|
||||||
tmpl = jinja_env.get_template('talk.html')
|
tmpl = jinja_env().get_template('talk.html')
|
||||||
return [
|
return [
|
||||||
nodes.raw('', tmpl.render(lang=lang, **get_talk_data(n)),
|
nodes.raw('', tmpl.render(lang=lang, **get_talk_data(n)),
|
||||||
format='html')
|
format='html')
|
||||||
|
@ -193,7 +197,7 @@ class TalkDirective(Directive):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
lang = self.options.get('lang', 'C')
|
lang = self.options.get('lang', 'C')
|
||||||
tmpl = jinja_env.get_template('talk.html')
|
tmpl = jinja_env().get_template('talk.html')
|
||||||
data = get_talk_data(self.arguments[0])
|
data = get_talk_data(self.arguments[0])
|
||||||
if data is None:
|
if data is None:
|
||||||
return []
|
return []
|
||||||
|
@ -213,9 +217,10 @@ class TalkGridDirective(Directive):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
lang = self.options.get('lang', 'C')
|
lang = self.options.get('lang', 'C')
|
||||||
tmpl = jinja_env.get_template('grid.html')
|
tmpl = jinja_env().get_template('grid.html')
|
||||||
output = []
|
output = []
|
||||||
days = unique_attr(all_talks(), 'day')
|
days = unique_attr(all_talks(), 'day')
|
||||||
|
gridstep = pelican.settings['TALKS_GRID_STEP']
|
||||||
for day in sorted(days):
|
for day in sorted(days):
|
||||||
talks = {talk['id'] for talk in all_talks()
|
talks = {talk['id'] for talk in all_talks()
|
||||||
if talk.get('day', None) == day
|
if talk.get('day', None) == day
|
||||||
|
@ -231,18 +236,18 @@ class TalkGridDirective(Directive):
|
||||||
del rooms[rooms.index('*')]
|
del rooms[rooms.index('*')]
|
||||||
mintime = min({talk['time'].hour * 60 +
|
mintime = min({talk['time'].hour * 60 +
|
||||||
talk['time'].minute
|
talk['time'].minute
|
||||||
for talk in talks}) // GRID_STEP * GRID_STEP
|
for talk in talks}) // gridstep * gridstep
|
||||||
maxtime = max({talk['time'].hour * 60 +
|
maxtime = max({talk['time'].hour * 60 +
|
||||||
talk['time'].minute +
|
talk['time'].minute +
|
||||||
talk['duration']
|
talk['duration']
|
||||||
for talk in talks})
|
for talk in talks})
|
||||||
times = {}
|
times = {}
|
||||||
|
|
||||||
for t in range(mintime, maxtime, GRID_STEP):
|
for t in range(mintime, maxtime, gridstep):
|
||||||
times[t] = [None] * len(rooms)
|
times[t] = [None] * len(rooms)
|
||||||
for talk in sorted(talks, key=lambda x: x['time']):
|
for talk in sorted(talks, key=lambda x: x['time']):
|
||||||
talktime = talk['time'].hour * 60 + talk['time'].minute
|
talktime = talk['time'].hour * 60 + talk['time'].minute
|
||||||
position = talktime // GRID_STEP * GRID_STEP # round
|
position = talktime // gridstep * gridstep # round
|
||||||
assert position in times
|
assert position in times
|
||||||
if talk['room'] == '*':
|
if talk['room'] == '*':
|
||||||
roomnums = range(len(rooms))
|
roomnums = range(len(rooms))
|
||||||
|
@ -258,14 +263,14 @@ class TalkGridDirective(Directive):
|
||||||
continue
|
continue
|
||||||
times[position][roomnum] = copy(talk)
|
times[position][roomnum] = copy(talk)
|
||||||
times[position][roomnum]['skip'] = False
|
times[position][roomnum]['skip'] = False
|
||||||
for i in range(1, talk['duration'] // GRID_STEP):
|
for i in range(1, talk['duration'] // gridstep):
|
||||||
times[position + i*GRID_STEP][roomnum] = copy(talk)
|
times[position + i*gridstep][roomnum] = copy(talk)
|
||||||
times[position + i*GRID_STEP][roomnum]['skip'] = True
|
times[position + i*gridstep][roomnum]['skip'] = True
|
||||||
|
|
||||||
render = tmpl.render(times=times,
|
render = tmpl.render(times=times,
|
||||||
rooms=rooms,
|
rooms=rooms,
|
||||||
mintime=mintime, maxtime=maxtime,
|
mintime=mintime, maxtime=maxtime,
|
||||||
timestep=GRID_STEP,
|
timestep=gridstep,
|
||||||
lang=lang,
|
lang=lang,
|
||||||
)
|
)
|
||||||
output.append(nodes.raw(
|
output.append(nodes.raw(
|
||||||
|
@ -321,25 +326,33 @@ class TalksGenerator(generators.Generator):
|
||||||
def generate_output(self, writer=None):
|
def generate_output(self, writer=None):
|
||||||
for talkname in self.talks:
|
for talkname in self.talks:
|
||||||
if 'resources' in self.talks[talkname]:
|
if 'resources' in self.talks[talkname]:
|
||||||
outdir = os.path.join(self.output_path, TALKS_PATH, talkname,
|
outdir = os.path.join(self.output_path,
|
||||||
TALK_ATTACHMENT_PATH)
|
pelican.settings['TALKS_PATH'], talkname,
|
||||||
|
pelican.settings['TALKS_ATTACHMENT_PATH'])
|
||||||
if os.path.isdir(outdir):
|
if os.path.isdir(outdir):
|
||||||
shutil.rmtree(outdir)
|
shutil.rmtree(outdir)
|
||||||
shutil.copytree(self.talks[talkname]['resources'], outdir)
|
shutil.copytree(self.talks[talkname]['resources'], outdir)
|
||||||
with io.open(os.path.join(self.output_path, TALK_ICS),
|
with io.open(os.path.join(self.output_path, pelican.settings.get('TALKS_ICS')),
|
||||||
'w',
|
'w',
|
||||||
encoding='utf8') as buf:
|
encoding='utf8') as buf:
|
||||||
buf.write(talks_to_ics())
|
buf.write(talks_to_ics())
|
||||||
|
|
||||||
|
|
||||||
def add_talks_option_defaults(pelican):
|
def add_talks_option_defaults(pelican):
|
||||||
pelican.settings.setdefault('TALKS_PATH', TALKS_PATH)
|
pelican.settings.setdefault('TALKS_PATH', 'talks')
|
||||||
|
pelican.settings.setdefault('TALKS_ATTACHMENT_PATH', 'res')
|
||||||
|
pelican.settings.setdefault('TALKS_ICS', 'schedule.ics')
|
||||||
|
pelican.settings.setdefault('TALKS_GRID_STEP', 30)
|
||||||
|
|
||||||
|
|
||||||
def get_generators(gen):
|
def get_generators(gen):
|
||||||
return TalksGenerator
|
return TalksGenerator
|
||||||
|
|
||||||
|
|
||||||
|
def pelican_init(pelicanobj):
|
||||||
|
global pelican
|
||||||
|
pelican = pelicanobj
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import yaml
|
import yaml
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -350,6 +363,7 @@ except ImportError:
|
||||||
else:
|
else:
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
|
signals.initialized.connect(pelican_init)
|
||||||
signals.get_generators.connect(get_generators)
|
signals.get_generators.connect(get_generators)
|
||||||
signals.initialized.connect(add_talks_option_defaults)
|
signals.initialized.connect(add_talks_option_defaults)
|
||||||
directives.register_directive('talklist', TalkListDirective)
|
directives.register_directive('talklist', TalkListDirective)
|
||||||
|
|
|
@ -12,6 +12,7 @@ from pelicanconf import *
|
||||||
|
|
||||||
SITEURL = '/hackit17'
|
SITEURL = '/hackit17'
|
||||||
RELATIVE_URLS = True
|
RELATIVE_URLS = True
|
||||||
|
TALKS_GRID_STEP = 30
|
||||||
|
|
||||||
# DELETE_OUTPUT_DIRECTORY = True
|
# DELETE_OUTPUT_DIRECTORY = True
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue