s3arch 0.0.7.alpha → 0.0.10.alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64302e564d9997605768c4ded4ae5dbfad42e1b560e965114b28d5aef70f2383
4
- data.tar.gz: b03157dcd54910490c46f6d31322795fc3ed0cca3ccc828c23b520ceebec756b
3
+ metadata.gz: 5a0d2326cf5f5e354aa45effa234ff9c97f4c230bdec828caaf1dfa62376a4f8
4
+ data.tar.gz: d725c1861974f8d11fffcfaf9327a4758c287204be5fe96ac498c53777fe3a55
5
5
  SHA512:
6
- metadata.gz: fc4416d80a68b834acb136d6465a7849641127b68180b6b6fe6efdba9bfa3b4f35b78e761b16b331e02352807fe8d7298fe3f0446a8f882885039fa372e3c368
7
- data.tar.gz: e0042712abb3a5ff25615d9ff828e6c9a310b7493dc72a5dd04f50bf5b0918a052e4ac5c616fc04645fc74287a516c663ba2e52ed862d621ef3d786ece9ca2a3
6
+ metadata.gz: ce063c6b1c86a53480a13f306a7db31ef20333490a243f0c66f0bfed684988d0e32647e096bf00190ff1e0453c5139a2ea83adff27edf46d42e1c42ece61e41c
7
+ data.tar.gz: 3b2529be62bc69d2b2928040edb84d06d1037234ab8cc41e497c2837fca6a4431b1524c24e116ced19668c53473263b20353270de6073eee67df5304f9190e22
checksums.yaml.gz.sig CHANGED
Binary file
@@ -2,12 +2,40 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>S3arch Dashboard</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <script>
7
+ (function() {
8
+ function getIdToken() {
9
+ try {
10
+ for (var i = 0; i < localStorage.length; i++) {
11
+ var key = localStorage.key(i);
12
+ if (key && key.indexOf('.idToken') !== -1) return localStorage.getItem(key);
13
+ }
14
+ } catch(e) {}
15
+ return null;
16
+ }
17
+ function isTokenValid(token) {
18
+ try {
19
+ var payload = JSON.parse(atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/')));
20
+ return payload.exp && payload.exp > Date.now() / 1000;
21
+ } catch(e) { return false; }
22
+ }
23
+ var token = getIdToken();
24
+ if (!token || !isTokenValid(token)) {
25
+ window.location.replace('/login');
26
+ }
27
+ })();
28
+ </script>
5
29
  <style>
6
30
  * { box-sizing: border-box; margin: 0; padding: 0; }
7
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 2rem; }
8
- h1 { margin-bottom: 1.5rem; font-size: 1.5rem; }
31
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 1.5rem; }
32
+ h1 { margin-bottom: 1rem; font-size: 1.5rem; }
9
33
  .error { background: #fee; border: 1px solid #fcc; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; color: #c00; }
10
34
  .success { background: #efe; border: 1px solid #cfc; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; color: #060; display: none; }
35
+ .meta { font-size: 0.85rem; color: #666; margin-bottom: 1rem; }
36
+ .empty { padding: 2rem; text-align: center; color: #666; }
37
+
38
+ /* Desktop: table */
11
39
  table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
12
40
  th, td { padding: 0.75rem 1rem; text-align: left; border-bottom: 1px solid #eee; }
13
41
  th { background: #fafafa; font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; color: #555; }
@@ -18,8 +46,20 @@
18
46
  .btn-rebuild:hover { background: #1d4ed8; }
19
47
  .btn-rebuild:disabled { background: #93c5fd; cursor: not-allowed; }
20
48
  .owner-id { font-family: "SF Mono", SFMono-Regular, Consolas, monospace; font-size: 0.8rem; }
21
- .empty { padding: 2rem; text-align: center; color: #666; }
22
- .meta { font-size: 0.85rem; color: #666; margin-bottom: 1rem; }
49
+
50
+ /* Mobile: card layout */
51
+ @media (max-width: 640px) {
52
+ body { padding: 1rem; }
53
+ table, thead, tbody, th, tr, td { display: block; }
54
+ thead { display: none; }
55
+ tr { background: #fff; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 0.75rem; padding: 0.75rem; }
56
+ tr:hover td { background: transparent; }
57
+ td { padding: 0.25rem 0; border: none; display: flex; justify-content: space-between; align-items: center; }
58
+ td::before { content: attr(data-label); font-weight: 600; font-size: 0.75rem; text-transform: uppercase; color: #555; margin-right: 0.5rem; }
59
+ td:last-child { margin-top: 0.5rem; justify-content: flex-start; }
60
+ td:last-child::before { display: none; }
61
+ .btn { width: 100%; text-align: center; padding: 0.6rem; }
62
+ }
23
63
  </style>
24
64
  </head>
25
65
  <body>
@@ -46,10 +86,10 @@
46
86
  <tbody>
47
87
  <%- @owners.each do |owner| -%>
48
88
  <tr>
49
- <td class="owner-id"><%= owner[:owner_id] %></td>
50
- <td><%= owner[:version] %></td>
51
- <td><%= owner[:record_count] || '—' %></td>
52
- <td><%= owner[:updated_at] || '—' %></td>
89
+ <td class="owner-id" data-label="Owner"><%= owner[:owner_id] %></td>
90
+ <td data-label="Version"><%= owner[:version].to_i %></td>
91
+ <td data-label="Records"><%= owner[:record_count] ? owner[:record_count].to_i.to_s.gsub(/(\d)(?=(\d{3})+$)/, '\1,') : '—' %></td>
92
+ <td data-label="Updated"><%= owner[:updated_at] || '—' %></td>
53
93
  <td>
54
94
  <button class="btn btn-rebuild" onclick="rebuild('<%= owner[:owner_id] %>', this)">Recreate SQLite</button>
55
95
  </td>
@@ -62,16 +102,24 @@
62
102
  <%- end -%>
63
103
 
64
104
  <script>
105
+ function getIdToken() {
106
+ try {
107
+ for (var i = 0; i < localStorage.length; i++) {
108
+ var key = localStorage.key(i);
109
+ if (key && key.indexOf('.idToken') !== -1) return localStorage.getItem(key);
110
+ }
111
+ } catch(e) {}
112
+ return null;
113
+ }
114
+
65
115
  function rebuild(ownerId, btn) {
66
116
  btn.disabled = true;
67
- btn.textContent = 'Rebuilding';
117
+ btn.textContent = 'Rebuilding\u2026';
68
118
  var headers = { 'Content-Type': 'application/json' };
69
- var authMeta = document.querySelector('meta[name="authorization"]');
70
- if (authMeta) headers['Authorization'] = authMeta.content;
71
- var baseMeta = document.querySelector('meta[name="api-base"]');
72
- var base = baseMeta ? baseMeta.content : window.location.pathname.replace(/\/$/, '');
119
+ var token = getIdToken();
120
+ if (token) headers['Authorization'] = 'Bearer ' + token;
73
121
 
74
- fetch(base + '/rebuild', {
122
+ fetch(window.location.pathname.replace(/\/$/, '') + '/rebuild', {
75
123
  method: 'POST',
76
124
  headers: headers,
77
125
  body: JSON.stringify({ owner_id: ownerId })
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module S3arch
4
- VERSION = '0.0.7.alpha'
4
+ VERSION = '0.0.10.alpha'
5
5
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3arch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7.alpha
4
+ version: 0.0.10.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Dalton
metadata.gz.sig CHANGED
Binary file