janela 0.2.1 → 0.4.0

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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +244 -23
  5. data/UPGRADING.md +172 -0
  6. data/app/assets/javascripts/janela/chart_controller.js +23 -10
  7. data/app/assets/javascripts/janela/frame_controller.js +188 -0
  8. data/app/assets/javascripts/janela/vitral_controller.js +263 -0
  9. data/app/assets/stylesheets/janela.css +164 -0
  10. data/app/assets/stylesheets/vitral.css +343 -0
  11. data/app/controllers/janela/application_controller.rb +25 -0
  12. data/app/controllers/janela/frames_controller.rb +57 -0
  13. data/app/controllers/janela/panes_controller.rb +66 -13
  14. data/app/controllers/janela/queries_controller.rb +17 -0
  15. data/app/controllers/janela/{snapshot_panes_controller.rb → snapshot_queries_controller.rb} +7 -5
  16. data/app/helpers/janela/{dashboard_helper.rb → frames_helper.rb} +26 -9
  17. data/app/models/janela/frame.rb +28 -0
  18. data/app/models/janela/pane.rb +102 -99
  19. data/app/models/janela/query.rb +162 -0
  20. data/app/models/janela/snapshot.rb +5 -5
  21. data/app/views/janela/frames/_card.html.erb +7 -0
  22. data/app/views/janela/frames/_form.html.erb +23 -0
  23. data/app/views/janela/frames/_frame.html.erb +5 -0
  24. data/app/views/janela/frames/_pane.html.erb +12 -0
  25. data/app/views/janela/frames/edit.html.erb +25 -0
  26. data/app/views/janela/frames/index.html.erb +15 -0
  27. data/app/views/janela/frames/new.html.erb +5 -0
  28. data/app/views/janela/frames/show.html.erb +9 -0
  29. data/app/views/janela/panes/_form.html.erb +58 -0
  30. data/app/views/janela/panes/_row.html.erb +12 -0
  31. data/app/views/janela/panes/edit.html.erb +5 -0
  32. data/app/views/janela/panes/new.html.erb +22 -0
  33. data/app/views/janela/panes/show.html.erb +3 -46
  34. data/app/views/janela/queries/_query.html.erb +47 -0
  35. data/app/views/janela/queries/show.html.erb +4 -0
  36. data/app/views/janela/shared/_errors.html.erb +7 -0
  37. data/app/views/layouts/janela/application.html.erb +22 -5
  38. data/config/importmap.rb +2 -1
  39. data/config/locales/en.yml +65 -0
  40. data/config/routes.rb +15 -2
  41. data/db/migrate/20260916000001_create_janela_frames.rb +13 -0
  42. data/db/migrate/20260916000002_create_janela_panes.rb +22 -0
  43. data/docs/decisions/001-built-to-be-forked.md +4 -0
  44. data/docs/decisions/009-snapshots.md +5 -2
  45. data/docs/decisions/010-agent-guidance-ships-the-agent-waits.md +8 -4
  46. data/docs/decisions/012-frames-and-panes-are-data.md +166 -0
  47. data/docs/decisions/013-naming-and-addressing-frames.md +119 -0
  48. data/docs/decisions/014-corrections-before-frames-are-built.md +222 -0
  49. data/docs/decisions/015-how-breaking-change-is-communicated.md +114 -0
  50. data/docs/decisions/016-the-styling-vocabulary.md +100 -0
  51. data/docs/decisions/017-janela-owns-no-data-store.md +113 -0
  52. data/docs/decisions/018-a-table-is-the-universal-renderer.md +75 -0
  53. data/docs/decisions/019-a-created-frame-asks-the-host-who-owns-it.md +79 -0
  54. data/docs/decisions/020-formatting-belongs-to-the-measure.md +93 -0
  55. data/docs/decisions/021-a-check-has-a-name-a-host-can-silence.md +84 -0
  56. data/docs/decisions/022-host-route-helpers-work-inside-the-engine.md +104 -0
  57. data/docs/decisions/023-vitral-is-a-theme-not-the-stylesheet.md +86 -0
  58. data/docs/decisions/024-selecting-more-than-one-value.md +127 -0
  59. data/docs/decisions/INDEX.md +25 -7
  60. data/docs/multi-tenancy.md +175 -0
  61. data/docs/naming.md +172 -0
  62. data/lib/janela/definition.rb +5 -5
  63. data/lib/janela/doctor.rb +219 -0
  64. data/lib/janela/engine.rb +24 -2
  65. data/lib/janela/host_routes.rb +31 -0
  66. data/lib/janela/measure.rb +65 -4
  67. data/lib/janela/version.rb +1 -1
  68. data/lib/janela.rb +24 -0
  69. data/lib/tasks/janela.rake +6 -0
  70. metadata +57 -4
  71. data/app/assets/javascripts/janela/dashboard_controller.js +0 -58
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: janela
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jay Killeen
@@ -95,21 +95,47 @@ files:
95
95
  - CHANGELOG.md
96
96
  - LICENSE.txt
97
97
  - README.md
98
+ - UPGRADING.md
98
99
  - app/assets/javascripts/janela/chart_controller.js
99
- - app/assets/javascripts/janela/dashboard_controller.js
100
+ - app/assets/javascripts/janela/frame_controller.js
100
101
  - app/assets/javascripts/janela/vendor/chart.js
102
+ - app/assets/javascripts/janela/vitral_controller.js
103
+ - app/assets/stylesheets/janela.css
104
+ - app/assets/stylesheets/vitral.css
101
105
  - app/controllers/janela/application_controller.rb
106
+ - app/controllers/janela/frames_controller.rb
102
107
  - app/controllers/janela/panes_controller.rb
103
- - app/controllers/janela/snapshot_panes_controller.rb
104
- - app/helpers/janela/dashboard_helper.rb
108
+ - app/controllers/janela/queries_controller.rb
109
+ - app/controllers/janela/snapshot_queries_controller.rb
110
+ - app/helpers/janela/frames_helper.rb
105
111
  - app/jobs/janela/snapshot_job.rb
112
+ - app/models/janela/frame.rb
106
113
  - app/models/janela/pane.rb
114
+ - app/models/janela/query.rb
107
115
  - app/models/janela/snapshot.rb
116
+ - app/views/janela/frames/_card.html.erb
117
+ - app/views/janela/frames/_form.html.erb
118
+ - app/views/janela/frames/_frame.html.erb
119
+ - app/views/janela/frames/_pane.html.erb
120
+ - app/views/janela/frames/edit.html.erb
121
+ - app/views/janela/frames/index.html.erb
122
+ - app/views/janela/frames/new.html.erb
123
+ - app/views/janela/frames/show.html.erb
124
+ - app/views/janela/panes/_form.html.erb
125
+ - app/views/janela/panes/_row.html.erb
126
+ - app/views/janela/panes/edit.html.erb
127
+ - app/views/janela/panes/new.html.erb
108
128
  - app/views/janela/panes/show.html.erb
129
+ - app/views/janela/queries/_query.html.erb
130
+ - app/views/janela/queries/show.html.erb
131
+ - app/views/janela/shared/_errors.html.erb
109
132
  - app/views/layouts/janela/application.html.erb
110
133
  - config/importmap.rb
134
+ - config/locales/en.yml
111
135
  - config/routes.rb
112
136
  - db/migrate/20260915000001_create_janela_snapshots.rb
137
+ - db/migrate/20260916000001_create_janela_frames.rb
138
+ - db/migrate/20260916000002_create_janela_panes.rb
113
139
  - docs/decisions/001-built-to-be-forked.md
114
140
  - docs/decisions/002-measures-and-dimensions-over-ransack.md
115
141
  - docs/decisions/003-cross-filtering-with-turbo-frames.md
@@ -121,14 +147,32 @@ files:
121
147
  - docs/decisions/009-snapshots.md
122
148
  - docs/decisions/010-agent-guidance-ships-the-agent-waits.md
123
149
  - docs/decisions/011-panes-do-not-render-in-the-host-layout.md
150
+ - docs/decisions/012-frames-and-panes-are-data.md
151
+ - docs/decisions/013-naming-and-addressing-frames.md
152
+ - docs/decisions/014-corrections-before-frames-are-built.md
153
+ - docs/decisions/015-how-breaking-change-is-communicated.md
154
+ - docs/decisions/016-the-styling-vocabulary.md
155
+ - docs/decisions/017-janela-owns-no-data-store.md
156
+ - docs/decisions/018-a-table-is-the-universal-renderer.md
157
+ - docs/decisions/019-a-created-frame-asks-the-host-who-owns-it.md
158
+ - docs/decisions/020-formatting-belongs-to-the-measure.md
159
+ - docs/decisions/021-a-check-has-a-name-a-host-can-silence.md
160
+ - docs/decisions/022-host-route-helpers-work-inside-the-engine.md
161
+ - docs/decisions/023-vitral-is-a-theme-not-the-stylesheet.md
162
+ - docs/decisions/024-selecting-more-than-one-value.md
124
163
  - docs/decisions/INDEX.md
164
+ - docs/multi-tenancy.md
165
+ - docs/naming.md
125
166
  - lib/janela.rb
126
167
  - lib/janela/definition.rb
127
168
  - lib/janela/dimension.rb
169
+ - lib/janela/doctor.rb
128
170
  - lib/janela/engine.rb
171
+ - lib/janela/host_routes.rb
129
172
  - lib/janela/measure.rb
130
173
  - lib/janela/model.rb
131
174
  - lib/janela/version.rb
175
+ - lib/tasks/janela.rake
132
176
  homepage: https://github.com/retail-tasker/janela
133
177
  licenses:
134
178
  - MIT
@@ -138,6 +182,15 @@ metadata:
138
182
  changelog_uri: https://github.com/retail-tasker/janela/blob/main/CHANGELOG.md
139
183
  bug_tracker_uri: https://github.com/retail-tasker/janela/issues
140
184
  rubygems_mfa_required: 'true'
185
+ post_install_message: |
186
+ Janela 0.4.0 selects more than one value in a dimension. Most applications
187
+ need do nothing. You need to act only if you override a pane view, where
188
+ selected_value is now selected_values, or if something of yours reads
189
+ Janela's URLs, where a click now writes q[field_in][] rather than
190
+ q[field_eq]. Links already shared keep working.
191
+
192
+ Steps: UPGRADING.md in this gem, or
193
+ https://github.com/retail-tasker/janela/blob/main/UPGRADING.md
141
194
  rdoc_options: []
142
195
  require_paths:
143
196
  - lib
@@ -1,58 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
-
3
- // Shared filter state for every pane on the page. Clicking a value rewrites
4
- // each frame's src, and Turbo reloads a frame whenever its src changes, so
5
- // cross-filtering needs no streams, no sockets and no state library.
6
- export default class extends Controller {
7
- static targets = ["pane"]
8
- static values = { filters: Object }
9
-
10
- // Table buttons send key/value as Stimulus action params; charts dispatch a
11
- // custom event carrying them in detail. Either way it is one filter toggle.
12
- toggle(event) {
13
- const { key, value } = { ...event.detail, ...event.params }
14
- const filters = { ...this.filtersValue }
15
-
16
- if (filters[key] === String(value)) {
17
- delete filters[key]
18
- } else {
19
- filters[key] = String(value)
20
- }
21
-
22
- this.filtersValue = filters
23
- }
24
-
25
- clear() {
26
- this.filtersValue = {}
27
- }
28
-
29
- filtersValueChanged() {
30
- this.paneTargets.forEach((pane) => {
31
- const url = new URL(pane.dataset.janelaSrc, window.location.origin)
32
- this.writeFilters(url)
33
- if (pane.src !== url.href) pane.src = url.href
34
- })
35
-
36
- this.syncPageUrl()
37
- }
38
-
39
- // The page URL carries the same q[...] the panes do, so a reload or a
40
- // pasted link opens the dashboard filtered (ADR 008). Replaced rather than
41
- // pushed: a click is not a place the back button should return to.
42
- syncPageUrl() {
43
- const url = new URL(window.location.href)
44
- for (const key of [...url.searchParams.keys()]) {
45
- if (key.startsWith("q[")) url.searchParams.delete(key)
46
- }
47
- this.writeFilters(url)
48
- if (url.href !== window.location.href) history.replaceState(history.state, "", url)
49
- }
50
-
51
- // Sorted so the browser serialises filters the same way the server does and
52
- // an unchanged src is never reloaded.
53
- writeFilters(url) {
54
- for (const key of Object.keys(this.filtersValue).sort()) {
55
- url.searchParams.set(`q[${key}]`, this.filtersValue[key])
56
- }
57
- }
58
- }