OXYGENHUB
# 7e01a7665aa5 oxygenhub / templates / dashboard.html
5.4 KiB · HTML · last changed feat(web): Backdrops, the engine in Rust and WASM, and the dashboard's Your sky (refs #157) 22 days ago source blame history raw
1
{% extends "base.html" %}
2
{% block title %}Dashboard{% endblock %}
3
{% block content %}
4
{# Your sky (docs/backgrounds.md §5, #157): the engine is Rust compiled to
5
   WebAssembly. The viewer's choice (Settings › Appearance) is a cookie;
6
   unset, a touch-only device or Save-Data gets a still sky. Any failure
7
   leaves no backdrop and nothing else changed. #}
8
<canvas id="backdrop" aria-hidden="true"></canvas>
9
<script type="application/json" id="backdrop-data">{{ backdrop|safe }}</script>
10
<script type="module">
11
const canvas = document.getElementById("backdrop");
12
const chosen = document.cookie.match(/(?:^|; )backdrop=(moving|still|off)/);
13
const touch = matchMedia("(pointer: coarse)").matches && !matchMedia("(pointer: fine)").matches;
14
const pick = chosen ? chosen[1] : (touch || (navigator.connection && navigator.connection.saveData) ? "still" : "moving");
15
if (pick === "off") {
16
  canvas.remove();
17
} else {
18
  try {
19
    const bd = await import("/static/backdrop/backdrop.js?v={{ shell.assets() }}");
20
    await bd.default({ module_or_path: "/static/backdrop/backdrop_bg.wasm?v={{ shell.assets() }}" });
21
    bd.start(canvas, JSON.parse(document.getElementById("backdrop-data").textContent), pick === "still");
22
  } catch (e) {
23
    canvas.remove();
24
  }
25
}
26
</script>
27
<div class="head">
28
  <h1>Dashboard <small>signed in as {% if let Some(u) = shell.user %}{{ u }}{% endif %}</small></h1>
29
</div>
30
<div class="side-layout rev dash">
31
  <div>
32
    <section class="card-box">
33
    <div class="card-head"><h2>Waiting for your review</h2><span class="count-chip">{{ reviews.len() }}</span></div>
34
    {% if reviews.is_empty() %}
35
    <p class="empty small">Nothing waits on you. Proposals by others in your repositories land here until you review them.</p>
36
    {% else %}
37
    <ul class="rows">
38
    {% for p in reviews %}
39
      <li>
40
        <div>
41
          <a class="name" href="/{{ p.owner }}/{{ p.name }}/proposal/{{ p.number }}"><span class="mute">{{ p.owner }}/{{ p.name }} #{{ p.number }}</span> <strong>{{ p.title }}</strong></a>
42
          {% if p.conflicted %}<span class="tag bad">conflicts</span>{% endif %}
43
          <p class="small">by {{ p.author }}</p>
44
        </div>
45
        <div class="right small">updated <time title="{{ p.updated_ms|when_i }}">{{ p.updated_ms|ago_i }}</time></div>
46
      </li>
47
    {% endfor %}
48
    </ul>
49
    {% endif %}
50
    </section>
51
52
    {% if !authored.is_empty() %}
53
    <section class="card-box">
54
    <div class="card-head"><h2>Your proposals</h2><span class="count-chip">{{ authored.len() }}</span></div>
55
    <ul class="rows">
56
    {% for p in authored %}
57
      <li>
58
        <div>
59
          <a class="name" href="/{{ p.owner }}/{{ p.name }}/proposal/{{ p.number }}"><span class="mute">{{ p.owner }}/{{ p.name }} #{{ p.number }}</span> <strong>{{ p.title }}</strong></a>
60
          {% if p.state == "draft" %}<span class="tag">draft</span>{% endif %}
61
          {% if p.conflicted %}<span class="tag bad">conflicts</span>{% endif %}
62
        </div>
63
        <div class="right small">updated <time title="{{ p.updated_ms|when_i }}">{{ p.updated_ms|ago_i }}</time></div>
64
      </li>
65
    {% endfor %}
66
    </ul>
67
    </section>
68
    {% endif %}
69
70
    {% if !assigned.is_empty() %}
71
    <section class="card-box">
72
    <div class="card-head"><h2>Issues assigned to you</h2><span class="count-chip">{{ assigned.len() }}</span></div>
73
    <ul class="rows">
74
    {% for i in assigned %}
75
      <li>
76
        <div><a class="name" href="/{{ i.owner }}/{{ i.name }}/issue/{{ i.number }}"><span class="mute">{{ i.owner }}/{{ i.name }} #{{ i.number }}</span> <strong>{{ i.title }}</strong></a></div>
77
        <div class="right small">updated <time title="{{ i.updated_ms|when_i }}">{{ i.updated_ms|ago_i }}</time></div>
78
      </li>
79
    {% endfor %}
80
    </ul>
81
    </section>
82
    {% endif %}
83
84
    <section class="card-box">
85
    <div class="card-head"><h2>Recent activity</h2></div>
86
    {% if feed.is_empty() %}
87
    <p class="empty small">No activity yet. Push to a repository and it shows here.</p>
88
    {% else %}
89
    <ul class="feed">
90
    {% for a in feed %}
91
      <li>
92
        <span class="who">{% if a.actor.is_empty() %}the hub{% else %}<img class="avatar xs" src="/avatar/{{ a.actor }}" alt=""> <a href="/{{ a.actor }}">{{ a.actor }}</a>{% endif %}</span>
93
        {% if a.kind == "push" %}pushed <span class="lbl lbl-bm">{{ a.event }}</span> to
94
        {% else if a.kind == "release" %}published <a href="{{ a.url() }}">{{ a.title }}</a> in
95
        {% else %}{{ a.event }} {{ a.kind }} <a href="{{ a.url() }}">#{{ a.number }} {{ a.title }}</a> in
96
        {% endif %}
97
        <a href="/{{ a.owner }}/{{ a.name }}">{{ a.owner }}/{{ a.name }}</a>
98
        <time class="mute small" title="{{ a.at_ms|when_i }}">{{ a.at_ms|ago_i }}</time>
99
      </li>
100
    {% endfor %}
101
    </ul>
102
    {% endif %}
103
    </section>
104
  </div>
105
  <aside class="side cards">
106
    <section class="side-card"><h3>Your repositories <span class="count-chip">{{ mine.len() }}</span><a class="more" href="/new">+ New</a></h3><div class="body">
107
    {% if mine.is_empty() %}
108
    <p class="small mute">None yet. <a href="/new">Create one</a>, or <a href="/explore">explore</a>.</p>
109
    {% else %}
110
    <ul class="plain repo-list">
111
    {% for r in mine %}
112
      <li><a href="/{{ r.owner }}/{{ r.name }}" title="{{ r.owner }}/{{ r.name }}"><span class="mute">{{ r.owner }} /</span> {{ r.name }}</a>{% if r.visibility != "public" %}<span class="tag">{{ r.visibility }}</span>{% endif %}</li>
113
    {% endfor %}
114
    </ul>
115
    {% endif %}
116
    </div></section>
117
  </aside>
118
</div>
119
{% endblock %}