@@ -48,6 +48,20 @@ def campaign(name): | |||||
return render_template("campaigns/campaign.mako", | return render_template("campaigns/campaign.mako", | ||||
name=name, campaign=campaign, enabled=enabled) | name=name, campaign=campaign, enabled=enabled) | ||||
@blueprint.rroute("/campaigns/<cname>/operations/<opname>") | |||||
def operation(cname, opname): | |||||
"""Render and return an operation page.""" | |||||
if cname not in config["campaigns"]: | |||||
abort(404) | |||||
campaign = config["campaigns"][cname] | |||||
if opname not in campaign["operations"]: | |||||
abort(404) | |||||
operation = campaign["operations"][opname] | |||||
enabled = cname in config["enabled"] and opname in campaign["enabled"] | |||||
return render_template("campaigns/operation.mako", | |||||
cname=cname, campaign=campaign, opname=opname, | |||||
operation=operation, enabled=enabled) | |||||
@blueprint.rroute("/settings/campaign", methods=["POST"]) | @blueprint.rroute("/settings/campaign", methods=["POST"]) | ||||
def set_campaign(): | def set_campaign(): | ||||
"""Update the user's currently selected campaign.""" | """Update the user's currently selected campaign.""" | ||||
@@ -7,9 +7,37 @@ enabled: | |||||
- foo | - foo | ||||
- bar | - bar | ||||
# Data for each campaign. Name must match entry in the enabled list above. If a | |||||
# campaign is defined here but not enabled, its URL will be accessible but not | |||||
# advertised anywhere, and it will be marked as inactive. | |||||
campaigns: | campaigns: | ||||
# ... | |||||
foo: | foo: | ||||
title: Foo | |||||
# Campaign title. This is possibly a longer or more colorful version of the | |||||
# name used as the internal key/campaign ID. | |||||
title: Stop the Foo | |||||
# List of active operations: | |||||
enabled: | |||||
- frigates | |||||
- titan | |||||
# Determines order of elements on campaign page; use separate lists for | |||||
# section breaks: | |||||
layout: | |||||
- [frigates, titan] | |||||
# Definitions for each operation. Operations track certain statistics. | |||||
operations: | |||||
# Will track the number of Foo frigates killed by the corp: | |||||
frigates: | |||||
title: "Operation: Kill Foo Frigates" | |||||
type: killboard | |||||
qualifiers: |- | |||||
return ((victim_corp == "Foo Corporation") and | |||||
(victim_ship_class == "Frigate")) | |||||
# Will track possession of Tritanium by all corp members: | |||||
titan: | |||||
title: Let's Build a Titan | |||||
type: collection | |||||
qualifiers: |- | |||||
return item_type == "Tritanium" | |||||
bar: | bar: | ||||
title: Bar | |||||
title: Save the Bar | |||||
operations: [] |
@@ -27,7 +27,7 @@ a:hover { | |||||
text-decoration: underline; | text-decoration: underline; | ||||
} | } | ||||
h2 { | |||||
h2, h3 { | |||||
margin: 0.5em 0; | margin: 0.5em 0; | ||||
} | } | ||||
@@ -360,6 +360,73 @@ h2 .disabled::after { | |||||
content: "✘"; | content: "✘"; | ||||
} | } | ||||
#operations { | |||||
margin-bottom: 1em; | |||||
} | |||||
#operations section { | |||||
display: flex; | |||||
justify-content: space-around; | |||||
} | |||||
.operation .stats .primary { | |||||
line-height: 60px; | |||||
height: 60px; | |||||
} | |||||
.operation .stats .primary .big { | |||||
font-size: 300%; | |||||
} | |||||
.operation .stats .primary .medium { | |||||
font-size: 200%; | |||||
} | |||||
.operation .stats .primary .small { | |||||
font-size: 150%; | |||||
} | |||||
.operation .stats .unit { | |||||
font-style: italic; | |||||
} | |||||
@media (min-width: 800px) { | |||||
#operations { | |||||
margin-top: 1em; | |||||
} | |||||
#operations section:not(:last-child) { | |||||
margin-bottom: 3em; | |||||
} | |||||
#operations section:last-child { | |||||
margin-bottom: 2em; | |||||
} | |||||
.operation { | |||||
margin: 0 0.75em; | |||||
text-align: center; | |||||
} | |||||
} | |||||
@media (max-width: 799px) { | |||||
#operations section { | |||||
flex-direction: column; | |||||
} | |||||
.operation { | |||||
margin: 0.5em 0; | |||||
} | |||||
.operation .stats > div { | |||||
display: inline-block; | |||||
} | |||||
.operation .stats .unit { | |||||
margin-left: 0.25em; | |||||
} | |||||
} | |||||
/* -------------------------------- Members -------------------------------- */ | /* -------------------------------- Members -------------------------------- */ | ||||
#members-list { | #members-list { | ||||
@@ -6,4 +6,29 @@ | |||||
<span class="understate">Campaign:</span> | <span class="understate">Campaign:</span> | ||||
<span${"" if enabled else ' class="disabled"'}>${campaign["title"] | h}</span> | <span${"" if enabled else ' class="disabled"'}>${campaign["title"] | h}</span> | ||||
</h2> | </h2> | ||||
<p>Hello! ...</p> | |||||
<div id="operations"> | |||||
% for section in campaign["layout"]: | |||||
<section> | |||||
% for opname in section: | |||||
<% operation = campaign["operations"][opname] %> | |||||
<div class="operation"> | |||||
<h3><a href="${url_for('.operation', cname=name, opname=opname)}">${operation["title"] | h}</a></h3> | |||||
<div class="stats"> | |||||
<!-- ... --> | |||||
<% | |||||
random = __import__("random") | |||||
n = [random.randint(0, 500), random.randint(10000, 500000), random.randint(10000000, 50000000000)][random.randint(0, 2)] | |||||
%> | |||||
<% | |||||
klass = "big" if n < 1000 else "medium" if n < 1000000 else "small" | |||||
%> | |||||
<div class="primary"> | |||||
<span class="${klass}">${"{:,}".format(n)}</span> | |||||
</div> | |||||
<div class="unit">${"ships" if klass == "big" else "points" if klass == "medium" else "ISK"}</div> <!-- ... plural --> | |||||
</div> | |||||
</div> | |||||
% endfor | |||||
</section> | |||||
% endfor | |||||
</div> |
@@ -0,0 +1,9 @@ | |||||
<%inherit file="../_default.mako"/> | |||||
<%block name="title"> | |||||
${self.maketitle(operation["title"], campaign["title"], "Campaigns")} | |||||
</%block> | |||||
<h2> <!-- ... breadcrumb --> | |||||
<span class="understate">Operation:</span> | |||||
<span${"" if enabled else ' class="disabled"'}>${operation["title"] | h}</span> | |||||
</h2> | |||||
<p>...</p> |