Skip to main content

max / makenotwork

6.2 KB · 131 lines History Blame Raw
1 <div class="content-section raised">
2 <div class="section-header">
3 <h2 class="subsection-title">Cloud Sync</h2>
4 </div>
5
6 <p class="form-hint mb-section">Cloud Sync lets your desktop or mobile apps sync data with Makenotwork using end-to-end encryption. Each app gets an API key your app uses to connect. <a href="/docs/synckit">Learn more</a></p>
7 <p class="form-hint mb-pane">Most creators don't need this: it's for developers who ship their own software through Makenotwork.</p>
8
9 <!-- Create new app form -->
10 <details class="form-section user-synckit-create">
11 <summary><h2 class="subsection-title">Create New App</h2></summary>
12 <div class="user-synckit-create-body">
13
14 <form id="synckit-create-form" class="user-synckit-create-form">
15 <div>
16 <label for="synckit-app-name">App Name</label>
17 <input type="text" id="synckit-app-name" name="name" required
18 placeholder="e.g. GoingsOn Desktop">
19 </div>
20 <div>
21 <label for="synckit-app-project">Project (optional)</label>
22 <select id="synckit-app-project">
23 <option value="">None</option>
24 {% for project in projects %}
25 <option value="{{ project.id }}">{{ project.title }}</option>
26 {% endfor %}
27 </select>
28 </div>
29 <button type="submit" class="btn">Create</button>
30 </form>
31 <div id="synckit-create-status"></div>
32 </div>
33 </details>
34
35 {% if apps.is_empty() %}
36 <p class="muted">No sync apps yet. Create one above to get started.</p>
37 {% else %}
38 <div class="scroll-x">
39 <table class="data-table well">
40 <thead>
41 <tr>
42 <th>Name</th>
43 <th title="Identifier used for over-the-air updates">Update Slug</th>
44 <th>Linked To</th>
45 <th title="Secret key your app uses to authenticate with Cloud Sync">API Key</th>
46 <th>Status</th>
47 <th title="Number of devices currently syncing">Devices</th>
48 <th title="Recent sync activity">Log Entries</th>
49 <th>Created</th>
50 <th>Billing</th>
51 <th>Actions</th>
52 </tr>
53 </thead>
54 <tbody>
55 {% for app in apps %}
56 <tr>
57 <td>{{ app.name }}</td>
58 <td id="synckit-slug-cell-{{ app.id }}">
59 {% if let Some(s) = app.slug %}
60 <code class="user-synckit-code">{{ s }}</code>
61 {% else %}
62 <span class="dimmed">-</span>
63 {% endif %}
64 <button class="btn-small btn-secondary user-synckit-inline-btn"
65 data-slug="{{ app.slug.as_deref().unwrap_or_default() }}"
66 data-action="syncKitShowSlugFromBtn" data-arg="{{ app.id }}">Set</button>
67 </td>
68 <td id="synckit-link-cell-{{ app.id }}">
69 {% if let Some(pname) = app.project_name %}
70 {% if let Some(pslug) = app.project_slug %}
71 <a href="/dashboard/project/{{ pslug }}">{{ pname }}</a>
72 {% endif %}
73 {% if let Some(ititle) = app.item_title %}
74 <span class="text-sm dimmed"> / {{ ititle }}</span>
75 {% endif %}
76 {% else %}
77 <span class="dimmed">-</span>
78 {% endif %}
79 <button class="btn-small btn-secondary user-synckit-inline-btn"
80 data-action="syncKitShowLinkForm" data-arg="{{ app.id }}">Link</button>
81 </td>
82 <td>
83 <code id="synckit-key-display-{{ app.id }}" class="user-synckit-code">{{ app.api_key_masked }}</code>
84 <span class="form-hint user-synckit-hint">(use Regenerate to get a new key)</span>
85 <div id="synckit-keys-secret-{{ app.id }}" class="user-synckit-hint">
86 {% if let Some(secret) = app.keys_secret_masked %}
87 <code class="user-synckit-code">{{ secret }}</code>
88 <span class="form-hint">keys secret (server-side only)</span>
89 {% else %}
90 <span class="form-hint">No keys secret. Generate one to use the key claim endpoints.</span>
91 {% endif %}
92 </div>
93 </td>
94 <td>
95 {% if app.is_active %}
96 <span class="user-synckit-status-active">Active</span>
97 {% else %}
98 <span class="user-synckit-status-inactive">Inactive</span>
99 {% endif %}
100 </td>
101 <td>{{ app.device_count }}</td>
102 <td>{{ app.log_entry_count }}</td>
103 <td>{{ app.created_at }}</td>
104 <td>{% include "partials/synckit_billing_panel.html" %}</td>
105 <td class="nowrap">
106 <button class="btn-small btn-secondary user-synckit-row-btn"
107 data-action="syncKitRegenKey" data-arg="{{ app.id }}">Regenerate Key</button>
108 <button class="btn-small btn-secondary user-synckit-row-btn"
109 data-action="syncKitRegenKeysSecret" data-arg="{{ app.id }}">Keys Secret</button>
110 <button class="btn-small btn-danger user-synckit-row-btn"
111 data-name="{{ app.name }}"
112 data-action="syncKitDeleteFromBtn" data-arg="{{ app.id }}">Delete</button>
113 </td>
114 </tr>
115 {% endfor %}
116 </tbody>
117 </table>
118 </div>
119 {% endif %}
120 </div>
121
122 <!-- Project options for the "Linked To" picker, HTML-escaped by Askama; the
123 static JS clones these instead of having titles interpolated into a script. -->
124 <template id="synckit-projects-options">
125 {% for project in projects %}
126 <option value="{{ project.id }}">{{ project.title }}</option>
127 {% endfor %}
128 </template>
129
130 <script src="/static/tab-user-synckit.js?v=0623"></script>
131