| @@ -48,6 +48,20 @@ def campaign(name): | |||
| return render_template("campaigns/campaign.mako", | |||
| 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"]) | |||
| def set_campaign(): | |||
| """Update the user's currently selected campaign.""" | |||
| @@ -7,9 +7,37 @@ enabled: | |||
| - foo | |||
| - 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: | |||
| # ... | |||
| 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: | |||
| title: Bar | |||
| title: Save the Bar | |||
| operations: [] | |||
| @@ -27,7 +27,7 @@ a:hover { | |||
| text-decoration: underline; | |||
| } | |||
| h2 { | |||
| h2, h3 { | |||
| margin: 0.5em 0; | |||
| } | |||
| @@ -360,6 +360,73 @@ h2 .disabled::after { | |||
| 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-list { | |||
| @@ -6,4 +6,29 @@ | |||
| <span class="understate">Campaign:</span> | |||
| <span${"" if enabled else ' class="disabled"'}>${campaign["title"] | h}</span> | |||
| </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> | |||