rollout-ui 0.9.0 → 0.9.2

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: 4206916ef324d7cfb3884b9a3c49529ce13c1775c48d3de796ae2cea639355b7
4
- data.tar.gz: 9e0702e530a5dc7b9e22b5201e7a6165395573b3f4154236823cfc1dfe91a18c
3
+ metadata.gz: b5230ac819ea0e86c7dc2606f9b308c429b6b92b50e8fb402ac3b4f5519b8207
4
+ data.tar.gz: 67f902bcffbc98e99189b16c577c66952bde58b0dfff550318cadcb0779f9bc3
5
5
  SHA512:
6
- metadata.gz: 2023c3c6b08fe1d9ea02b976b1b8feacf96b64175c69fc9fcb673343a603afd3fb24674ed7adb852006b7f14b7da24dcd0a0fb4c3433ac24bdeb2bf6d303f0ce
7
- data.tar.gz: 1c881df9faa5d1f7ae3bafe43e09491bd37f0b6b5d38b21190ad826f4741a776f58d22a5cf9d8a90f79fbd38242e3eb98f647d34389ef799f11131432a9149ae
6
+ metadata.gz: af0154118022337d0963bb63013498f2292fecfe29dfd318729335fd724c4e4569e2c7a3f6662c19ce0c9ba729fd9a0149005963cbc531c3ae800b55077a8fa8
7
+ data.tar.gz: 85d005cfbf60f08c96032e3a4b9c607aca322f013050845489974c21a19a88259d68a98d011774e75c4c7d2e6f692969c3ee7daadffb6542a31bc2d144f49409
@@ -23,7 +23,7 @@ jobs:
23
23
  --health-retries 5
24
24
  steps:
25
25
  - name: Checkout code
26
- uses: actions/checkout@v4
26
+ uses: actions/checkout@v6
27
27
  with:
28
28
  persist-credentials: false
29
29
  - name: Setup Ruby
@@ -34,10 +34,17 @@ jobs:
34
34
  run: bundle exec rspec
35
35
  - name: Release to RubyGems
36
36
  uses: rubygems/release-gem@v1
37
+
38
+ github-release:
39
+ needs: release
40
+ runs-on: ubuntu-latest
41
+ permissions:
42
+ contents: write
43
+ steps:
37
44
  - name: Create GitHub Release
38
- uses: softprops/action-gh-release@v2
45
+ uses: softprops/action-gh-release@v3
39
46
  with:
40
- tag_name: ${{ github.ref }}
47
+ tag_name: ${{ github.ref_name }}
41
48
  name: ${{ github.ref_name }}
42
49
  generate_release_notes: true
43
50
  draft: false
@@ -23,10 +23,10 @@ jobs:
23
23
  --health-retries 5
24
24
  steps:
25
25
  - name: Checkout code
26
- uses: actions/checkout@v4
26
+ uses: actions/checkout@v6
27
27
  - name: Setup Ruby
28
28
  uses: ruby/setup-ruby@v1
29
29
  with:
30
30
  bundler-cache: true
31
31
  - name: Run tests
32
- run: bundle exec rspec
32
+ run: bundle exec rspec
@@ -70,6 +70,16 @@ module Rollout::UI
70
70
  end
71
71
  end
72
72
 
73
+ def formatted_timestamp(time)
74
+ time.strftime(config.get(:timestamp_format))
75
+ end
76
+
77
+ def relative_timestamp_tag(time)
78
+ return "" unless time
79
+
80
+ %(<span data-timestamp="#{h(time.iso8601)}" title="#{h(formatted_timestamp(time))}">#{h(time_ago(time))}</span>)
81
+ end
82
+
73
83
  def format_change_key(key)
74
84
  key.to_s.gsub('data.', '')
75
85
  end
@@ -1,5 +1,5 @@
1
1
  class Rollout
2
2
  module UI
3
- VERSION = "0.9.0"
3
+ VERSION = "0.9.2"
4
4
  end
5
5
  end
@@ -49,7 +49,7 @@
49
49
  <% if updated_at.nil? %>
50
50
  <span class="text-gray-400">Never</span>
51
51
  <% else %>
52
- <span title="<%= h(updated_at.strftime(Rollout::UI.config.timestamp_format)) %>"><%= h(time_ago(updated_at)) %></span>
52
+ <%= relative_timestamp_tag(updated_at) %>
53
53
  <% end %>
54
54
  </td>
55
55
  <% end %>
@@ -55,7 +55,7 @@
55
55
  </td>
56
56
 
57
57
  <td class="py-2 text-right whitespace-nowrap pl-3" style="min-width: 160px;">
58
- <span title="<%= h(event.created_at.strftime(Rollout::UI.config.timestamp_format)) %>"><%= h(time_ago(event.created_at)) %></span>
58
+ <%= relative_timestamp_tag(event.created_at) %>
59
59
  </td>
60
60
  </tr>
61
61
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html data-timestamp-format="<%= h(config.get(:timestamp_format)) %>">
3
3
  <head>
4
4
  <title>Rollout UI</title>
5
5
  <meta name="viewport" content="width=device-width initial-scale=1">
@@ -42,19 +42,85 @@
42
42
  }
43
43
  }
44
44
  applyTheme(theme);
45
+ const themeLabels = { system: 'Theme: System', light: 'Theme: Light', dark: 'Theme: Dark' };
46
+ const themeTitles = {
47
+ system: "Follows your device's light or dark appearance setting.",
48
+ light: 'Always use light appearance.',
49
+ dark: 'Always use dark appearance.'
50
+ };
45
51
  window.addEventListener('DOMContentLoaded', function() {
46
52
  const btn = document.getElementById('theme-toggle');
47
- btn.textContent = theme;
53
+ function applyThemeLabel(t) {
54
+ btn.textContent = themeLabels[t];
55
+ btn.title = themeTitles[t];
56
+ }
57
+ applyThemeLabel(theme);
48
58
  btn.addEventListener('click', function() {
49
59
  const current = localStorage.getItem('theme') || 'system';
50
60
  const next = current === 'light' ? 'dark' : current === 'dark' ? 'system' : 'light';
51
61
  localStorage.setItem('theme', next);
52
62
  applyTheme(next);
53
- btn.textContent = next;
63
+ applyThemeLabel(next);
54
64
  });
55
65
  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
56
66
  if (localStorage.getItem('theme') === 'system') applyTheme('system');
57
67
  });
68
+
69
+ const timezoneKey = 'timezone';
70
+ const timezoneBtn = document.getElementById('timezone-toggle');
71
+ function timezoneMode() {
72
+ return localStorage.getItem(timezoneKey) === 'utc' ? 'utc' : 'local';
73
+ }
74
+ function formatTimestamp(iso, mode) {
75
+ const date = new Date(iso);
76
+ if (Number.isNaN(date.getTime())) return null;
77
+ const format = document.documentElement.getAttribute('data-timestamp-format') || '%Y-%m-%d %H:%M %Z';
78
+ const parts = {};
79
+ new Intl.DateTimeFormat('en-US', {
80
+ year: 'numeric',
81
+ month: '2-digit',
82
+ day: '2-digit',
83
+ hour: '2-digit',
84
+ minute: '2-digit',
85
+ second: '2-digit',
86
+ hourCycle: 'h23',
87
+ timeZone: mode === 'utc' ? 'UTC' : undefined,
88
+ timeZoneName: 'short'
89
+ }).formatToParts(date).forEach(function(part) {
90
+ if (part.type !== 'literal') parts[part.type] = part.value;
91
+ });
92
+ const tokens = {
93
+ '%Y': parts.year,
94
+ '%y': parts.year.slice(-2),
95
+ '%m': parts.month,
96
+ '%d': parts.day,
97
+ '%H': parts.hour,
98
+ '%M': parts.minute,
99
+ '%S': parts.second,
100
+ '%Z': parts.timeZoneName,
101
+ '%%': '%'
102
+ };
103
+ return format.replace(/%[%YymdHMSZ]/g, function(token) {
104
+ return Object.prototype.hasOwnProperty.call(tokens, token) ? tokens[token] : token;
105
+ });
106
+ }
107
+ function applyTimezone(mode) {
108
+ const localZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'Local';
109
+ timezoneBtn.textContent = mode === 'utc' ? 'Time: UTC' : 'Time: Local';
110
+ timezoneBtn.title = mode === 'utc'
111
+ ? 'Uses Coordinated Universal Time.'
112
+ : "Uses your browser's timezone: " + localZone;
113
+ document.querySelectorAll('[data-timestamp]').forEach(function(el) {
114
+ const formatted = formatTimestamp(el.getAttribute('data-timestamp'), mode);
115
+ if (formatted) el.setAttribute('title', formatted);
116
+ });
117
+ }
118
+ applyTimezone(timezoneMode());
119
+ timezoneBtn.addEventListener('click', function() {
120
+ const next = timezoneMode() === 'local' ? 'utc' : 'local';
121
+ localStorage.setItem(timezoneKey, next);
122
+ applyTimezone(next);
123
+ });
58
124
  });
59
125
  })();
60
126
  </script>
@@ -63,7 +129,8 @@
63
129
  <h1 class="font-light text-4xl text-gray-600 flex-auto">
64
130
  <a href="<%= h(index_path) %>" class="hover:text-blue-700">Rollout </a>
65
131
  </h1>
66
- <button id="theme-toggle" class="text-sm text-gray-600 p-2 bg-gray-100 rounded-sm transition-colors duration-150 hover:bg-gray-200">system</button>
132
+ <button type="button" id="timezone-toggle" class="text-sm text-gray-600 p-2 bg-gray-100 rounded-sm transition-colors duration-150 hover:bg-gray-200 mr-2" title="Uses your browser's timezone">Time: Local</button>
133
+ <button type="button" id="theme-toggle" class="text-sm text-gray-600 p-2 bg-gray-100 rounded-sm transition-colors duration-150 hover:bg-gray-200" title="Follows your device's light or dark appearance setting.">Theme: System</button>
67
134
  </div>
68
135
  <%= yield %>
69
136
  </div>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollout-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - FetLife