hr_lite 0.22.0 → 0.22.1
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b224591c52bc41368791e59547fe81b69fe9765462b998f9e23ffc47ee286a27
|
|
4
|
+
data.tar.gz: 62300f5cad84aa9c3c710e533943ebb84c9775c20941f40fbbb80b6eeee2e2a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad4011c24f0534b96301e647c1e3c6a908036917f4640ec934acd543787464554dbadaf94ce20724f7f8826c48dd81b89c2c450addf63ebf3750e8fcda070b5d
|
|
7
|
+
data.tar.gz: 564668224c10513104b7f5b05326a7c3a1c1e052e5f0ad4f045b19c23a50d9f6f4c2d67b387fb291bc4a45610eb6f0384d9b861a0a51556393603f56f5acabb5
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.22.1] - 2026-10-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Location help on the punch card: when a punch has no GPS, the card lists the steps to turn location on for the device in use (iPhone and iPad in Safari, Chrome, Firefox or Edge; Android in Chrome or Samsung Internet; desktop Chrome, Edge, Brave, Firefox or Safari, plus the macOS or Windows location switch). A web page cannot open device settings, so the steps say where to tap. New `.hrl-geo-help` list.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- With `config.require_punch_location`, the punch form carries `data-hrl-geo-required` and the browser holds a timed-out or unavailable fix on the page, with the same steps, instead of submitting a punch the server refuses.
|
|
17
|
+
|
|
10
18
|
## [0.22.0] - 2026-10-09
|
|
11
19
|
|
|
12
20
|
The HRMS UI/UX pass: Keka/greytHR patterns and a ui-ux-pro-max review of every screen, phone first. No migrations. Hosts that theme through `--hrl-*` variables keep their values; the engine defaults for radius, info background and muted text change (see Changed).
|
|
@@ -1,16 +1,64 @@
|
|
|
1
1
|
// Dependency-free geolocation capture for punch forms.
|
|
2
2
|
// Markup contract:
|
|
3
|
-
// <form data-hrl-geo-punch>
|
|
3
|
+
// <form data-hrl-geo-punch [data-hrl-geo-required]>
|
|
4
4
|
// <input type="hidden" name="lat"><input type="hidden" name="lng">
|
|
5
5
|
// <input type="hidden" name="accuracy_m"><input type="hidden" name="geo_status">
|
|
6
6
|
// <button type="submit">…</button>
|
|
7
7
|
// <p data-hrl-geo-status role="status" aria-live="polite"></p> (not hidden, or the first message is missed)
|
|
8
8
|
// </form>
|
|
9
9
|
// A denied permission holds the punch; timeout/unavailable submit anyway
|
|
10
|
-
// with geo_status set
|
|
10
|
+
// with geo_status set (the server flags them) — unless the form is marked
|
|
11
|
+
// data-hrl-geo-required, which holds those too. A held punch shows how to
|
|
12
|
+
// turn location on for this device: no web page can open device settings.
|
|
11
13
|
(function () {
|
|
12
14
|
"use strict";
|
|
13
15
|
|
|
16
|
+
// Steps per device, matched on the user agent. iPadOS reports a Mac UA, so a
|
|
17
|
+
// touch-capable "Mac" counts as iOS.
|
|
18
|
+
function locationSteps() {
|
|
19
|
+
var ua = navigator.userAgent;
|
|
20
|
+
var ios = /iPhone|iPad|iPod/.test(ua) || (/Macintosh/.test(ua) && navigator.maxTouchPoints > 1);
|
|
21
|
+
if (ios) {
|
|
22
|
+
var app = /CriOS/.test(ua) ? "Chrome" : /FxiOS/.test(ua) ? "Firefox" : /EdgiOS/.test(ua) ? "Edge" : null;
|
|
23
|
+
return [
|
|
24
|
+
"Open Settings → Privacy & Security → Location Services and turn it on.",
|
|
25
|
+
app ? "In Settings, open Apps → " + app + " → Location and choose While Using the App."
|
|
26
|
+
: "In Settings, open Apps → Safari → Location and choose Allow (or Ask).",
|
|
27
|
+
"Come back here, reload the page and tap again."
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
if (/Android/.test(ua)) {
|
|
31
|
+
var samsung = /SamsungBrowser/.test(ua);
|
|
32
|
+
return [
|
|
33
|
+
"Swipe down from the top of the screen and turn Location on.",
|
|
34
|
+
samsung ? "In Samsung Internet, tap ☰ → Settings → Sites and downloads → Site permissions → Location, and allow this site."
|
|
35
|
+
: "Tap the icon left of the web address → Permissions → Location → Allow. (Or ⋮ → Settings → Site settings → Location.)",
|
|
36
|
+
"Reload the page and tap again."
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
var steps = [];
|
|
40
|
+
if (/Firefox/.test(ua)) steps.push("Click the icon left of the web address and remove the blocked Location permission.");
|
|
41
|
+
else if (/Safari/.test(ua) && !/Chrome|Chromium|Edg/.test(ua)) steps.push("Open Safari → Settings → Websites → Location and set this site to Allow.");
|
|
42
|
+
else steps.push("Click the icon left of the web address → Location → Allow.");
|
|
43
|
+
if (/Mac OS X|Macintosh/.test(ua)) steps.push("On the Mac, open System Settings → Privacy & Security → Location Services and turn it on for this browser.");
|
|
44
|
+
else if (/Windows/.test(ua)) steps.push("In Windows, open Settings → Privacy & security → Location and turn on location access.");
|
|
45
|
+
steps.push("Reload the page and tap again.");
|
|
46
|
+
return steps;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function showHelp(label, headline) {
|
|
50
|
+
if (!label) return;
|
|
51
|
+
label.textContent = headline;
|
|
52
|
+
var list = document.createElement("ol");
|
|
53
|
+
list.className = "hrl-geo-help";
|
|
54
|
+
locationSteps().forEach(function (step) {
|
|
55
|
+
var item = document.createElement("li");
|
|
56
|
+
item.textContent = step;
|
|
57
|
+
list.appendChild(item);
|
|
58
|
+
});
|
|
59
|
+
label.appendChild(list);
|
|
60
|
+
}
|
|
61
|
+
|
|
14
62
|
function setup(form) {
|
|
15
63
|
var fields = {
|
|
16
64
|
lat: form.querySelector("[name=lat]"),
|
|
@@ -20,6 +68,7 @@
|
|
|
20
68
|
};
|
|
21
69
|
var button = form.querySelector("[type=submit]");
|
|
22
70
|
var label = form.querySelector("[data-hrl-geo-status]");
|
|
71
|
+
var required = form.hasAttribute("data-hrl-geo-required");
|
|
23
72
|
var locating = false;
|
|
24
73
|
|
|
25
74
|
function send(status) {
|
|
@@ -28,6 +77,12 @@
|
|
|
28
77
|
form.submit();
|
|
29
78
|
}
|
|
30
79
|
|
|
80
|
+
function hold(headline) {
|
|
81
|
+
locating = false;
|
|
82
|
+
if (button) { button.disabled = false; button.removeAttribute("aria-busy"); }
|
|
83
|
+
showHelp(label, headline);
|
|
84
|
+
}
|
|
85
|
+
|
|
31
86
|
form.addEventListener("submit", function (event) {
|
|
32
87
|
if (locating || fields.status.value) return; // second pass: let it through
|
|
33
88
|
event.preventDefault();
|
|
@@ -35,7 +90,11 @@
|
|
|
35
90
|
if (button) { button.disabled = true; button.setAttribute("aria-busy", "true"); }
|
|
36
91
|
if (label) { label.hidden = false; label.textContent = "Getting location…"; }
|
|
37
92
|
|
|
38
|
-
if (!navigator.geolocation) {
|
|
93
|
+
if (!navigator.geolocation) {
|
|
94
|
+
if (required) hold("This browser cannot share your location. Open this page in Chrome or Safari.");
|
|
95
|
+
else send("unavailable");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
39
98
|
|
|
40
99
|
navigator.geolocation.getCurrentPosition(
|
|
41
100
|
function (pos) {
|
|
@@ -47,12 +106,8 @@
|
|
|
47
106
|
function (err) {
|
|
48
107
|
// Browsers ask only once; a past "Don't allow" denies silently forever.
|
|
49
108
|
// Hold the punch so it is never filed (and flagged) without GPS.
|
|
50
|
-
if (err && err.code === 1) {
|
|
51
|
-
|
|
52
|
-
if (button) { button.disabled = false; button.removeAttribute("aria-busy"); }
|
|
53
|
-
if (label) label.textContent = "Location is blocked. Allow location for this site in your browser settings, then tap again.";
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
109
|
+
if (err && err.code === 1) { hold("Location is blocked. To allow it:"); return; }
|
|
110
|
+
if (required) { hold("Couldn't get your location. Check that location is on:"); return; }
|
|
56
111
|
send("timeout");
|
|
57
112
|
},
|
|
58
113
|
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 }
|
|
@@ -240,6 +240,8 @@ html:has(.hrl-body) { scroll-padding-top: 4rem; scroll-padding-bottom: calc(4.4r
|
|
|
240
240
|
.hrl-listrow > :first-child { display: inline-flex; align-items: center; gap: var(--hrl-s-1); line-height: var(--hrl-lh-tight); }
|
|
241
241
|
/* The punch status stays in the accessibility tree (no `hidden`) so its first message is announced; empty, it takes no space. */
|
|
242
242
|
[data-hrl-geo-status]:empty { margin: 0; }
|
|
243
|
+
.hrl-geo-help { margin: var(--hrl-s-2) 0 0; padding-left: var(--hrl-s-4); color: var(--hrl-ink); }
|
|
244
|
+
.hrl-geo-help li + li { margin-top: var(--hrl-s-1); }
|
|
243
245
|
.hrl-grid { display: grid; gap: .85rem; grid-template-columns: 1fr; margin-bottom: .85rem; }
|
|
244
246
|
.hrl-grid > * { min-width: 0; }
|
|
245
247
|
.hrl-grid > .hrl-card { margin-bottom: 0; }
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
<% if open_yesterday %>
|
|
36
36
|
<%= form_with url: hr_lite.check_out_attendance_path, method: :post, local: true,
|
|
37
|
-
html: { data: { "hrl-geo-punch": true } } do %>
|
|
37
|
+
html: { data: { "hrl-geo-punch": true, "hrl-geo-required": HrLite.config.require_punch_location.presence } } do %>
|
|
38
38
|
<input type="hidden" name="lat"><input type="hidden" name="lng">
|
|
39
39
|
<input type="hidden" name="accuracy_m"><input type="hidden" name="geo_status">
|
|
40
40
|
<button type="submit" class="hrl-btn hrl-btn--big hrl-btn--block">
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
<% end %>
|
|
45
45
|
<% elsif record&.check_in_at.blank? %>
|
|
46
46
|
<%= form_with url: hr_lite.check_in_attendance_path, method: :post, local: true,
|
|
47
|
-
html: { data: { "hrl-geo-punch": true } } do %>
|
|
47
|
+
html: { data: { "hrl-geo-punch": true, "hrl-geo-required": HrLite.config.require_punch_location.presence } } do %>
|
|
48
48
|
<input type="hidden" name="lat"><input type="hidden" name="lng">
|
|
49
49
|
<input type="hidden" name="accuracy_m"><input type="hidden" name="geo_status">
|
|
50
50
|
<button type="submit" class="hrl-btn hrl-btn--primary hrl-btn--big hrl-btn--block">Check in</button>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
<% end %>
|
|
53
53
|
<% else %>
|
|
54
54
|
<%= form_with url: hr_lite.check_out_attendance_path, method: :post, local: true,
|
|
55
|
-
html: { data: { "hrl-geo-punch": true } } do %>
|
|
55
|
+
html: { data: { "hrl-geo-punch": true, "hrl-geo-required": HrLite.config.require_punch_location.presence } } do %>
|
|
56
56
|
<input type="hidden" name="lat"><input type="hidden" name="lng">
|
|
57
57
|
<input type="hidden" name="accuracy_m"><input type="hidden" name="geo_status">
|
|
58
58
|
<button type="submit" class="hrl-btn hrl-btn--big hrl-btn--block">
|
data/lib/hr_lite/version.rb
CHANGED