Browse Source

Add more nuanced/cleaner styling for campaign summaries.

master
Ben Kurtovic 8 years ago
parent
commit
6c331ee827
6 changed files with 234 additions and 23 deletions
  1. +66
    -0
      calefaction/format.py
  2. +2
    -0
      calefaction/modules/campaigns/update.py
  3. +89
    -1
      static/main.css
  4. +19
    -0
      static/main.js
  5. +7
    -3
      templates/campaigns/campaign.mako
  6. +51
    -19
      templates/campaigns/renderers.mako

+ 66
- 0
calefaction/format.py View File

@@ -0,0 +1,66 @@
from datetime import datetime, timedelta

import humanize

__all__ = ["format_isk", "format_isk_compact", "format_utctime",
"format_utctime_compact"]

def format_isk(value):
"""Nicely format an ISK value."""
if value < 10**6:
return "{:,.2f}".format(value)
return humanize.intword(value, "%.2f")

def format_isk_compact(value):
"""Nicely format an ISK value compactly."""
# Based on humanize.intword().
powers = [10 ** x for x in [3, 6, 9, 12, 15]]
letters = ["k", "m", "b", "t", "q"]

if value < powers[0]:
return "{:,.2f}".format(value)
for ordinal, power in enumerate(powers[1:], 1):
if value < power:
chopped = value / float(powers[ordinal - 1])
return "{:,.2f}{}".format(chopped, letters[ordinal - 1])
return str(value)

def format_utctime(value):
"""Format a UTC timestamp."""
return humanize.naturaltime(datetime.utcnow() - value)

def _format_compact_delta(delta):
"""Return a snippet of formatting for a time delta."""
# Based on humanize.naturaldelta().
seconds = abs(delta.seconds)
days = abs(delta.days)
years = days // 365
days = days % 365
months = int(days // 30.5)

if years == 0 and days < 1:
if seconds < 60:
return "{}s".format(seconds)
if seconds < 3600:
minutes = seconds // 60
return "{}m".format(minutes)
hours = seconds // 3600
return "{}h".format(hours)
if years == 0:
if months == 0:
return "{}d".format(days)
return "{}mo".format(months)
if years == 1:
if months == 0:
if days == 0:
return "1y"
return "1y {}d".format(days)
return "1y {}mo".format(months)
return "{}y".format(years)

def format_utctime_compact(value):
"""Format a UTC timestamp compactly."""
delta = datetime.utcnow() - value
if delta < timedelta(seconds=1):
return "just now"
return "{} ago".format(_format_compact_delta(delta))

+ 2
- 0
calefaction/modules/campaigns/update.py View File

@@ -87,6 +87,8 @@ def _update_collection_operations(cname, opnames):
operation = campaign["operations"][opname] operation = campaign["operations"][opname]
show_isk = operation.get("isk", True) show_isk = operation.get("isk", True)


# store per-user counts; update for all users in corp who have fresh
# API keys and leave other data stale
... ...
primary = __import__("random").randint(10, 99) primary = __import__("random").randint(10, 99)
secondary = __import__("random").randint(10000000, 5000000000) / 100 \ secondary = __import__("random").randint(10000000, 5000000000) / 100 \


+ 89
- 1
static/main.css View File

@@ -31,6 +31,11 @@ h2, h3 {
margin: 0.5em 0; margin: 0.5em 0;
} }


abbr[title], acronym[title] {
border-bottom: 1px dotted #555;
text-decoration: none;
}

.understate { .understate {
font-weight: normal; font-weight: normal;
} }
@@ -393,13 +398,88 @@ h2 .disabled-info {
font-size: 150%; font-size: 150%;
} }


.operation .secondary {
font-size: 105%;
}

.operation .unit { .operation .unit {
font-style: italic; font-style: italic;
} }


.operation .summary .head {
margin-top: 1em;
font-size: 14px;
}

.operation .summary .contents {
position: relative;
margin-top: 0.5em;
border: 1px solid #282828;
font-size: 14px;
}

.operation .killboard {
border-spacing: 0;
border-collapse: collapse;
text-align: left;
}

.operation .killboard:not(.expanded) tr:nth-child(2n) {
background-color: #181818;
}

.operation .killboard:not(.expanded) tr:nth-child(2n+1) {
background-color: #0A0A0A;
}

.operation .killboard td {
padding: 0.25em 0;
}

.operation .killboard td:first-child {
padding-left: 1em;
}

.operation .killboard td:last-child {
padding-right: 1em;
}

.operation .killboard .fluid {
padding-right: 0.5em;
}

.operation .killboard .icon {
width: 46px;
}

.operation .killboard.expanded {
position: absolute;
z-index: 1;
transition: clip-path 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
clip-path: inset(0 100% 0 0);
}

.operation .killboard:not(.expanded) .extra {
display: none;
}

.operation .killboard.expanded .spacer {
display: none;
}

.operation .killboard img {
width: 42px;
height: 42px;
vertical-align: middle;
}

.operation .killboard abbr {
border-bottom: none;
}

@media (min-width: 800px) { @media (min-width: 800px) {
#operations { #operations {
margin: 1em 2em;
margin: 1em 0;
} }


#operations section { #operations section {
@@ -429,6 +509,10 @@ h2 .disabled-info {
margin: 0.5em 0; margin: 0.5em 0;
} }


.operation .overview {
margin-left: 1em;
}

.operation .primary, .operation .primary .unit { .operation .primary, .operation .primary .unit {
display: inline-block; display: inline-block;
} }
@@ -436,6 +520,10 @@ h2 .disabled-info {
.operation .unit { .operation .unit {
margin-left: 0.15em; margin-left: 0.15em;
} }

.operation .killboard:not(.expanded) {
width: 100%;
}
} }


/* -------------------------------- Members -------------------------------- */ /* -------------------------------- Members -------------------------------- */


+ 19
- 0
static/main.js View File

@@ -64,4 +64,23 @@ $(function() {
this.form.submit(); this.form.submit();
}); });
$('#campaigns-select input[type="submit"]').hide(); $('#campaigns-select input[type="submit"]').hide();

//Campaigns: selectively reveal operation summary details:
$(".operation .killboard tr").mouseenter(function() {
var div = $("<table>", {addClass: "killboard expanded"})
.css($(this).position())
.css("background-color", $(this).css("background-color"))
.css("position", "fixed")
.append($("<tr>").html($(this).html()))
.mouseleave(function() { $(this).remove(); });
div.find(".spacer").remove();
$(this).closest(".summary").find(".expanded").remove();
$(this).closest(".contents").prepend(div);
div.css("width", Math.max(div.width(), $(this).width()));
div.css("position", "");
div.css("clip-path", "inset(0 0% 0 0)");
});
$(".operation .summary").mouseleave(function() {
$(this).find(".expanded").remove();
});
}); });

+ 7
- 3
templates/campaigns/campaign.mako View File

@@ -1,4 +1,6 @@
<%! import humanize %>
<%!
from calefaction.format import format_isk
%>
<%inherit file="../_default.mako"/> <%inherit file="../_default.mako"/>
<%namespace file="renderers.mako" import="render_summary"/> <%namespace file="renderers.mako" import="render_summary"/>
<%block name="title"> <%block name="title">
@@ -37,14 +39,16 @@
% if secondary is not None: % if secondary is not None:
<div class="secondary"> <div class="secondary">
<abbr title="${"{:,.2f}".format(secondary)} ${sunit}"> <abbr title="${"{:,.2f}".format(secondary)} ${sunit}">
<span class="num">${humanize.intword(secondary) | h}</span>
<span class="num">${format_isk(secondary) | h}</span>
<span class="unit">${sunit}</span> <span class="unit">${sunit}</span>
</abbr> </abbr>
</div> </div>
% endif % endif
</div> </div>
% if summary: % if summary:
${render_summary(renderer, summary)}
<div class="summary">
${render_summary(renderer, summary)}
</div>
% endif % endif
</div> </div>
% endfor % endfor


+ 51
- 19
templates/campaigns/renderers.mako View File

@@ -1,25 +1,57 @@
<%! import humanize %>
<%!
from calefaction.format import format_isk_compact, format_utctime_compact
%>
<%def name="_killboard_kill(kill)">
<% victim = kill["victim"] %>
<tr>
<td class="fluid">
<span>
<abbr title="${kill["date"].strftime("%Y-%m-%d %H:%M")}">${format_utctime_compact(kill["date"]) | h}</abbr><br/>
<abbr title="${"{:,.2f}".format(kill["value"])} ISK">${format_isk_compact(kill["value"]) | h}</abbr>
</span>
</td>
<td class="fluid extra">
<span>
${kill["system"]} 0.3<br/><!-- ... -->
Region<!-- ... -->
</span>
</td>
<td class="icon">
<a href="https://zkillboard.com/kill/${kill['id']}/"><img title="" alt="<!-- ... -->" src="${g.eve.image.inventory(victim["ship_id"], 64)}"/></a>
</td>
<td class="icon extra">
<a href="https://zkillboard.com/character/${victim['char_id']}/"><img title="" alt="<!-- ... -->" src="${g.eve.image.character(victim["char_id"], 128)}"/></a>
</td>
<td class="icon${' extra' if victim["alliance_id"] and victim["faction_id"] else ''}">
<a href="https://zkillboard.com/corporation/${victim['corp_id']}/"><img title="" alt="<!-- ... -->" src="${g.eve.image.corp(victim["corp_id"], 128)}"/></a>
</td>
<td class="icon${'' if victim["alliance_id"] else ' extra'}">
% if victim["alliance_id"]:
<a href="https://zkillboard.com/alliance/${victim['alliance_id']}/"><img title="" alt="<!-- ... -->" src="${g.eve.image.alliance(victim["alliance_id"], 128)}"/></a>
% endif
</td>
<td class="icon${'' if victim["faction_id"] else ' extra'}">
% if victim["faction_id"]:
<a href="https://zkillboard.com/faction/${victim['faction_id']}/"><img title="" alt="<!-- ... -->" src="${g.eve.image.faction(victim["faction_id"], 128)}"/></a>
% endif
</td>
% if not victim["alliance_id"] and not victim["faction_id"]:
<td class="icon spacer"></td>
% endif
</tr>
</%def>
<%def name="_killboard_recent(summary)"> <%def name="_killboard_recent(summary)">
<ul class="summary">
% for kill in summary:
<li>
<a href="https://zkillboard.com/kill/${kill['id']}/">${kill["id"]}</a>
${kill["system"]}
<abbr title="${kill["date"].strftime("%Y-%m-%d %H:%M")}">${humanize.naturaltime(kill["date"]) | h}</abbr>
<img src="${g.eve.image.render(kill["victim"]["ship_id"], 128)}"/>
<img src="${g.eve.image.character(kill["victim"]["char_id"], 128)}"/>
<img src="${g.eve.image.corp(kill["victim"]["corp_id"], 128)}"/>
<img src="${g.eve.image.alliance(kill["victim"]["alliance_id"], 128)}"/>
<img src="${g.eve.image.faction(kill["victim"]["faction_id"], 128)}"/>
<abbr title="${"{:,.2f}".format(kill["value"])} ISK">${humanize.intword(kill["value"]) | h} ISK</abbr>
</li>
% endfor
</ul>
<div class="head">Most recent kills:</div>
<div class="contents">
<table class="killboard">
% for kill in summary:
${_killboard_kill(kill)}
% endfor
</table>
</div>
</%def> </%def>

<%def name="render_summary(renderer, summary)"><% <%def name="render_summary(renderer, summary)"><%
if renderer == "killboard_recent": if renderer == "killboard_recent":
return _killboard_recent(summary) return _killboard_recent(summary)
else:
raise RuntimeError("Unknown renderer: %s" % renderer)
raise RuntimeError("Unknown renderer: %s" % renderer)
%></%def> %></%def>

Loading…
Cancel
Save