recourse 7.8.3 → 7.10.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +4 -3
- data/app/views/recourses/_sidebar.html.erb +13 -4
- data/config/locales/recourse.en.yml +5 -0
- data/lib/recourse/bookmarks.rb +4 -2
- data/lib/recourse/helpers/maps.rb +19 -4
- data/lib/recourse/helpers/sidebars.rb +16 -0
- data/lib/recourse/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a5ba4a5b982928c2ee9ea80e400a2d95c9b59102224902787ea3b3d6b9f4c9a8
|
|
4
|
+
data.tar.gz: 0d44134228230f5a15f4bc7545df435407518a074ae34299605d90294a93a4bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7db938770e4ecf06d930a89b965cc9790b2596b6c889be4f0a77cb0fff553739978408c22706da03abb4209964b17f6875b3c6703335e0bc9744d70c213768a1
|
|
7
|
+
data.tar.gz: b6a11dad45cae5cac88c42890b8551fd2f8a6c527c554672e7fe07221af251c1dbb1b59b35facc89b3c802ff57e1aec6ae01878d49e6424fe2b8d8b772eb85a2
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ For more information about changelogs, check [Keep a Changelog](http://keepachan
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## 7.10.0 - 2026-09-26
|
|
11
|
+
|
|
12
|
+
* [FEATURE] The sidebar's foot says what each icon does
|
|
13
|
+
|
|
14
|
+
The moon, the sun, the way in and the way out each open a tooltip to the right, away
|
|
15
|
+
from the sidebar's edge, the way a column's icon opens one above it: `Dark theme`,
|
|
16
|
+
`Light theme`, `Sign in` and `Sign out`. A host that answers `exit_name` with whoever is
|
|
17
|
+
signed in earns `Sign out N-100L`. The words are `recourse.dark_theme`, `light_theme`,
|
|
18
|
+
`sign_out` and `sign_out_as` in the locale.
|
|
19
|
+
|
|
20
|
+
## 7.9.0 - 2026-09-26
|
|
21
|
+
|
|
22
|
+
* [FEATURE] A pin or an area on a map leads to its row's page
|
|
23
|
+
|
|
24
|
+
Each point is sent as `[lat, lng, href, title]` and each place as `[id, href, title]`: the
|
|
25
|
+
record's own page wherever one is routed, and its label. bh's map controller makes a pin
|
|
26
|
+
or an area with an `href` clickable, following it through Turbo. Needs the bh that reads
|
|
27
|
+
these shapes: an older one still draws points, but takes a place's whole triple for its
|
|
28
|
+
ID and draws nothing, which is why this release requires bh 6.10.
|
|
29
|
+
|
|
30
|
+
* [FEATURE] A route named `enter` earns the sidebar a way in
|
|
31
|
+
|
|
32
|
+
The mirror of `exit`: `get 'session/new', to: 'sessions#new', as: :enter` draws a
|
|
33
|
+
`Sign in` link beside the toggle, to wherever the host signs people in. A host that
|
|
34
|
+
signs people in shows one or the other by answering `enter?` and `exit?` itself.
|
|
35
|
+
|
|
36
|
+
* [FEATURE] A bookmarks Proc answering nil draws no bookmark column
|
|
37
|
+
|
|
38
|
+
A visitor who never signed in has nowhere to keep a row, so `Recourse.bookmarks =
|
|
39
|
+
-> { Current.user&.bookmarks }` leaves them without the squares rather than raising.
|
|
40
|
+
|
|
10
41
|
## 7.8.3 - 2026-09-21
|
|
11
42
|
|
|
12
43
|
* [FIX] A delete button in a table row is no taller than the row
|
data/README.md
CHANGED
|
@@ -78,8 +78,8 @@ draws the route a dragged row reports its place to, and `retrievable: true` draw
|
|
|
78
78
|
one a `Retrieve` button on the table posts to, for rows that came from somewhere else.
|
|
79
79
|
Both are refused on a resource with no `index`, since there is nowhere for either to
|
|
80
80
|
stand. The [routes guide](https://claudiob.github.io/recourse/guides/routes.html) has
|
|
81
|
-
the rest: namespaces, the defaults a nested resource takes, and the `
|
|
82
|
-
|
|
81
|
+
the rest: namespaces, the defaults a nested resource takes, and the `enter` and `exit`
|
|
82
|
+
routes that earn the sidebar a sign-in link and a log-out button.
|
|
83
83
|
|
|
84
84
|
## Step 2. Enhance your models
|
|
85
85
|
|
|
@@ -211,7 +211,8 @@ Recourse.bookmarks = -> { Keepsake.where agent: Current.agent }
|
|
|
211
211
|
|
|
212
212
|
A Proc rather than a relation, because at boot the viewer is nobody. Every model with a
|
|
213
213
|
`has_many` at that class then opens its table with a square to keep a row by, and kept
|
|
214
|
-
rows come first. A model that cannot hold a bookmark gets no column
|
|
214
|
+
rows come first. A model that cannot hold a bookmark gets no column, and neither does a
|
|
215
|
+
visitor the Proc answers nil for — somebody who never signed in has nowhere to keep one.
|
|
215
216
|
|
|
216
217
|
<img width="3824" height="1220" alt="Image" src="https://github.com/user-attachments/assets/d1db4adb-0b5c-4e41-8bb6-cf72a35288f0" />
|
|
217
218
|
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
<%# The foot of the sidebar: a reader's own say in how the page looks and, where the
|
|
13
13
|
host drew a route named `exit`, the way out beside it — a button, since ending a
|
|
14
|
-
session is never a GET. Each
|
|
14
|
+
session is never a GET. Each icon says what it does in a tooltip that opens to the right,
|
|
15
|
+
away from the sidebar's edge. Each takes half the row and centers its icon in it, so the
|
|
15
16
|
toggle alone sits in the middle and the two together sit at a quarter and at three
|
|
16
17
|
quarters. Which side of the fold the foot lands on is the layout's business, and so
|
|
17
18
|
is which of the two mode icons shows — the mode may be the system's, which only CSS
|
|
@@ -40,21 +41,29 @@
|
|
|
40
41
|
<%= tag.button type: 'button', class: 'nav-link border-0 bg-transparent',
|
|
41
42
|
data: scheme_data do %>
|
|
42
43
|
<span class='recourse-scheme-light'>
|
|
43
|
-
|
|
44
|
+
<%= tag.i class: 'bi bi-moon-fill', data: tooltip_data(t('recourse.dark_theme'), placement: 'right') %>
|
|
44
45
|
<span class='recourse-foot-word'><%= t 'recourse.darken' %></span>
|
|
45
46
|
</span>
|
|
46
47
|
<span class='recourse-scheme-dark'>
|
|
47
|
-
|
|
48
|
+
<%= tag.i class: 'bi bi-sun-fill', data: tooltip_data(t('recourse.light_theme'), placement: 'right') %>
|
|
48
49
|
<span class='recourse-foot-word'><%= t 'recourse.lighten' %></span>
|
|
49
50
|
</span>
|
|
50
51
|
<% end %>
|
|
51
52
|
</div>
|
|
52
53
|
<%# Submitted by the browser rather than by Turbo: a log out ends with a redirect to
|
|
53
54
|
wherever the host signs people in, which is another origin a fetch cannot follow. -%>
|
|
55
|
+
<%# The way in, where the host drew a route named `enter`: a link, since what it
|
|
56
|
+
leads to is a form rather than a change. -%>
|
|
57
|
+
<% if enter? %>
|
|
58
|
+
<%= link_to enter_path, class: 'nav-link border-0 bg-transparent' do %>
|
|
59
|
+
<%= tag.i class: 'bi bi-box-arrow-in-right', data: tooltip_data(t('recourse.enter'), placement: 'right') %>
|
|
60
|
+
<span class='recourse-foot-word'><%= t 'recourse.enter' %></span>
|
|
61
|
+
<% end %>
|
|
62
|
+
<% end %>
|
|
54
63
|
<% if exit? %>
|
|
55
64
|
<%= button_to exit_path, method: :delete, class: 'nav-link border-0 bg-transparent',
|
|
56
65
|
form: { data: { turbo: false } } do %>
|
|
57
|
-
|
|
66
|
+
<%= tag.i class: 'bi bi-box-arrow-right', data: tooltip_data(exit_tooltip, placement: 'right') %>
|
|
58
67
|
<span class='recourse-foot-word'><%= t 'recourse.exit' %></span>
|
|
59
68
|
<% end %>
|
|
60
69
|
<% end %>
|
|
@@ -47,12 +47,16 @@ en:
|
|
|
47
47
|
create: Create
|
|
48
48
|
created: "%{record} was created."
|
|
49
49
|
created_error: "%{model} could not be created."
|
|
50
|
+
dark_theme: Dark theme
|
|
50
51
|
darken: Dark
|
|
51
52
|
delete: Delete %{model}
|
|
52
53
|
deleted: "%{model} was deleted."
|
|
53
54
|
deleted_error: "%{model} could not be deleted."
|
|
54
55
|
destroy: Delete
|
|
55
56
|
exit: Exit
|
|
57
|
+
sign_out: Sign out
|
|
58
|
+
sign_out_as: "Sign out %{name}"
|
|
59
|
+
enter: Sign in
|
|
56
60
|
displaying:
|
|
57
61
|
one: Displaying 1 item
|
|
58
62
|
other: Displaying %{count} items
|
|
@@ -66,6 +70,7 @@ en:
|
|
|
66
70
|
items:
|
|
67
71
|
one: 1 item
|
|
68
72
|
other: "%{count} items"
|
|
73
|
+
light_theme: Light theme
|
|
69
74
|
lighten: Light
|
|
70
75
|
missing_model: You declared `recourses :%{name}` in your routes file, but this app
|
|
71
76
|
has no %{model} model.
|
data/lib/recourse/bookmarks.rb
CHANGED
|
@@ -17,7 +17,8 @@ module Recourse
|
|
|
17
17
|
# would run a host's Proc long before there is a request for it to read.
|
|
18
18
|
def self.bookmarks? = !@declared_bookmarks.nil?
|
|
19
19
|
|
|
20
|
-
# The viewer's bookmarks, resolved for this request
|
|
20
|
+
# The viewer's bookmarks, resolved for this request, or nil where the Proc answered
|
|
21
|
+
# nil: nobody is looking whose rows could be kept, a visitor who never signed in.
|
|
21
22
|
def self.bookmarks
|
|
22
23
|
bookmarks = @declared_bookmarks
|
|
23
24
|
bookmarks = bookmarks.call if bookmarks.respond_to? :call
|
|
@@ -28,10 +29,11 @@ module Recourse
|
|
|
28
29
|
# How a model's bookmarks point back at it: its own `has_many` at the bookmark
|
|
29
30
|
# class, which is both the opt-in and everything needed to write one. A model that
|
|
30
31
|
# cannot hold a bookmark has not declared one, so it gets no column.
|
|
32
|
+
# And none for a viewer the Proc named nobody, who has nowhere to keep a row.
|
|
31
33
|
def self.bookmarks_for(model)
|
|
32
34
|
return unless bookmarks?
|
|
33
35
|
|
|
34
|
-
klass = bookmarks
|
|
36
|
+
klass = bookmarks&.klass or return
|
|
35
37
|
model.reflect_on_all_associations(:has_many).find { |one| one.klass == klass }
|
|
36
38
|
end
|
|
37
39
|
|
|
@@ -15,23 +15,38 @@ module Recourse
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# The places, with the layer they are areas on — pins where the model is no geography
|
|
18
|
-
# — or the points, where a model keeps no place.
|
|
18
|
+
# — or the points, where a model keeps no place. Each carries where its row leads and
|
|
19
|
+
# what it is called, so a pin or an area is clicked through to the record the way the
|
|
20
|
+
# row's own link in the table is.
|
|
19
21
|
def map_rows(recourses)
|
|
20
22
|
return { map_points_value: map_points(recourses) } unless Recourse.placed? resource_model
|
|
21
23
|
|
|
22
24
|
{
|
|
23
25
|
map_boundary_value: Recourse.boundary(resource_model)&.to_s&.upcase,
|
|
24
|
-
map_places_value: recourses
|
|
26
|
+
map_places_value: map_places(recourses),
|
|
25
27
|
}
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
#
|
|
30
|
+
# Each place as `[id, href, title]`, for a row that names one.
|
|
31
|
+
def map_places(recourses)
|
|
32
|
+
recourses.filter_map do |one|
|
|
33
|
+
place = one.attributes[Recourse::PLACE_COLUMN]
|
|
34
|
+
[place, *map_lead(one)] if place
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Each point as `[lat, lng, href, title]`. Only a row with both halves is a point; one
|
|
39
|
+
# with either missing is nowhere.
|
|
29
40
|
def map_points(recourses)
|
|
30
41
|
recourses.filter_map do |one|
|
|
31
42
|
point = one.attributes.values_at(*Recourse::POINT_COLUMNS)
|
|
32
|
-
point.map(&:to_f) if point.all?
|
|
43
|
+
[*point.map(&:to_f), *map_lead(one)] if point.all?
|
|
33
44
|
end
|
|
34
45
|
end
|
|
46
|
+
|
|
47
|
+
# Where a row's pin leads, the record's own page wherever one is routed, and what the
|
|
48
|
+
# pin says on hover: nothing to lead to where no page is.
|
|
49
|
+
def map_lead(record) = [resource_action_path(:show, record), Recourse.record_title(record)]
|
|
35
50
|
end
|
|
36
51
|
end
|
|
37
52
|
end
|
|
@@ -10,6 +10,22 @@ module Recourse
|
|
|
10
10
|
# convention, and its helper existing is what the sidebar asks.
|
|
11
11
|
def exit? = respond_to? :exit_path
|
|
12
12
|
|
|
13
|
+
# And the way in, its mirror: a route named `enter` — `resource :session, only:
|
|
14
|
+
# :new, as: :enter`, or a `get` of the host's own — earns a link beside the toggle
|
|
15
|
+
# to wherever the host signs people in. A link rather than a button, since asking
|
|
16
|
+
# for a form to sign in with changes nothing. Whether a viewer who already signed
|
|
17
|
+
# in still sees it is the host's to say, by answering this for them.
|
|
18
|
+
def enter? = respond_to? :enter_path
|
|
19
|
+
|
|
20
|
+
# Who is signed in, as the way out names them: `Sign out N-100L`. Nil, as it is where
|
|
21
|
+
# the host does not say, leaves the tooltip at `Sign out`.
|
|
22
|
+
def exit_name = nil
|
|
23
|
+
|
|
24
|
+
# What the way out's tooltip says.
|
|
25
|
+
def exit_tooltip
|
|
26
|
+
exit_name.present? ? t('recourse.sign_out_as', name: exit_name) : t('recourse.sign_out')
|
|
27
|
+
end
|
|
28
|
+
|
|
13
29
|
# Sidebar entries as [name, title, path, key], in the order routes.rb declares
|
|
14
30
|
# them, `key` being where in the title the letter that reaches it sits.
|
|
15
31
|
def sidebar_resources
|
data/lib/recourse/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: recourse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.
|
|
4
|
+
version: 7.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- claudiob
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - ">="
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '6.
|
|
46
|
+
version: '6.10'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - ">="
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '6.
|
|
53
|
+
version: '6.10'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: pagy
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|