feedback_engine 0.3.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -2
- data/README.md +4 -7
- data/app/assets/feedback_engine/widget.js +6 -86
- data/lib/feedback_engine/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12457e35c33daf8032e5eae4336964217b969d4d45d8d8a13ca85f6706833e26
|
|
4
|
+
data.tar.gz: 82ce331114ef1a88718e9879f7a263c6ea89456d0fb32c098804431df8fa6106
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16ab901cdc39fbd5dfa1c26ef896717610f8da85a2afd96348bfbaa1b13b196b4d9e12e6fb8d47f2194d0bd86e6ba46729f88e86a3e5089f853ab9dbdfff097c
|
|
7
|
+
data.tar.gz: ee81a5410c06cfaaea26f143ef0ce2bccde945d2d1826e68e30b90f154191e4178cac1f2b2f8279465ccf22b1f20810ca8f9aa2828f6ab184594e7582b56ec2a
|
data/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 (2026-07-22)
|
|
4
|
+
|
|
5
|
+
- Removed the clipboard-paste / drag-and-drop / file-chips screenshot intake
|
|
6
|
+
added in 0.3.0 — pasted files all arrive as `image.png` and the extra UI
|
|
7
|
+
wasn't worth its complexity. Screenshots are back to a plain file input.
|
|
8
|
+
|
|
3
9
|
## 0.3.0 (2026-07-22)
|
|
4
10
|
|
|
5
|
-
- Screenshots can
|
|
11
|
+
- Screenshots can be pasted (Cmd/Ctrl+V) or dragged & dropped anywhere on
|
|
6
12
|
the feedback form, not just picked via the file dialog. Selected files show
|
|
7
13
|
as removable chips; non-images are ignored and the configured maximum is
|
|
8
|
-
enforced at intake.
|
|
14
|
+
enforced at intake. (Removed again in 0.4.0.)
|
|
9
15
|
- The dialog traps Tab focus while open and is labelled for screen readers
|
|
10
16
|
(`aria-labelledby`).
|
|
11
17
|
- Dashboard search across message, author, and section (case-insensitive,
|
data/README.md
CHANGED
|
@@ -20,8 +20,7 @@ app.
|
|
|
20
20
|
- **Trigger it your way.** Use the built-in floating button, or hide it and
|
|
21
21
|
open the form from any element with a `data-feedback-engine-open` attribute.
|
|
22
22
|
- **Screenshots included.** Users can attach up to 3 images (via Active
|
|
23
|
-
Storage) —
|
|
24
|
-
configurable and enforced server-side.
|
|
23
|
+
Storage) — limits are configurable and enforced server-side.
|
|
25
24
|
- **Pluggable gating and attribution.** You decide who can send feedback, who
|
|
26
25
|
can read it, and how a submission is attributed to a user.
|
|
27
26
|
- **Localized.** The widget follows your app's `I18n.locale`; translations ship
|
|
@@ -177,11 +176,9 @@ end
|
|
|
177
176
|
### Screenshots
|
|
178
177
|
|
|
179
178
|
Uploads use Active Storage: `bin/rails active_storage:install` if you haven't
|
|
180
|
-
already.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
as a hint in the widget. If Active Storage isn't loaded, the upload control
|
|
184
|
-
simply doesn't render and uploads are rejected.
|
|
179
|
+
already. Limits (`max_screenshots`, `max_screenshot_size`) are enforced
|
|
180
|
+
server-side and shown as a hint in the widget. If Active Storage isn't loaded,
|
|
181
|
+
the upload control simply doesn't render and uploads are rejected.
|
|
185
182
|
|
|
186
183
|
### Notifications
|
|
187
184
|
|
|
@@ -20,8 +20,6 @@
|
|
|
20
20
|
var Z = 2147483000;
|
|
21
21
|
var overlay = null;
|
|
22
22
|
var lastFocused = null;
|
|
23
|
-
var fileInput = null;
|
|
24
|
-
var fileChips = null;
|
|
25
23
|
|
|
26
24
|
function ready(fn) {
|
|
27
25
|
if (document.readyState === "loading") {
|
|
@@ -114,25 +112,6 @@
|
|
|
114
112
|
// Keep Tab (and Shift+Tab) cycling inside the dialog while it is open.
|
|
115
113
|
overlay.addEventListener("keydown", trapFocus);
|
|
116
114
|
|
|
117
|
-
// Screenshots can be pasted (Cmd/Ctrl+V) or dropped anywhere on the form —
|
|
118
|
-
// the file picker is just one way in.
|
|
119
|
-
if (config.screenshots.enabled) {
|
|
120
|
-
dialog.addEventListener("paste", function (event) {
|
|
121
|
-
var files = event.clipboardData && event.clipboardData.files;
|
|
122
|
-
if (files && files.length) {
|
|
123
|
-
event.preventDefault();
|
|
124
|
-
addFiles(files);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
dialog.addEventListener("dragover", function (event) {
|
|
128
|
-
event.preventDefault();
|
|
129
|
-
});
|
|
130
|
-
dialog.addEventListener("drop", function (event) {
|
|
131
|
-
event.preventDefault();
|
|
132
|
-
if (event.dataTransfer) addFiles(event.dataTransfer.files);
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
115
|
var first = dialog.querySelector("select, textarea, input");
|
|
137
116
|
if (first) first.focus();
|
|
138
117
|
}
|
|
@@ -141,8 +120,6 @@
|
|
|
141
120
|
if (!overlay) return;
|
|
142
121
|
overlay.remove();
|
|
143
122
|
overlay = null;
|
|
144
|
-
fileInput = null;
|
|
145
|
-
fileChips = null;
|
|
146
123
|
if (lastFocused && lastFocused.focus) lastFocused.focus();
|
|
147
124
|
}
|
|
148
125
|
|
|
@@ -265,69 +242,19 @@
|
|
|
265
242
|
}
|
|
266
243
|
|
|
267
244
|
function screenshotsField() {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
var wrap = field(config.labels.screenshots, fileInput);
|
|
245
|
+
var input = document.createElement("input");
|
|
246
|
+
input.type = "file";
|
|
247
|
+
input.name = "screenshots";
|
|
248
|
+
input.multiple = true;
|
|
249
|
+
input.accept = "image/*";
|
|
250
|
+
var wrap = field(config.labels.screenshots, input);
|
|
275
251
|
var hint = document.createElement("span");
|
|
276
252
|
hint.className = "fbe-hint";
|
|
277
253
|
hint.textContent = config.labels.screenshotsHint;
|
|
278
254
|
wrap.appendChild(hint);
|
|
279
|
-
fileChips = document.createElement("ul");
|
|
280
|
-
fileChips.className = "fbe-chips";
|
|
281
|
-
wrap.appendChild(fileChips);
|
|
282
255
|
return wrap;
|
|
283
256
|
}
|
|
284
257
|
|
|
285
|
-
// Merge pasted/dropped images into the file input (the single source of
|
|
286
|
-
// truth for what gets uploaded), capped at the configured maximum.
|
|
287
|
-
function addFiles(files) {
|
|
288
|
-
if (!fileInput) return;
|
|
289
|
-
var transfer = new DataTransfer();
|
|
290
|
-
var current = Array.prototype.slice.call(fileInput.files);
|
|
291
|
-
var incoming = Array.prototype.slice.call(files).filter(function (file) {
|
|
292
|
-
return /^image\//.test(file.type);
|
|
293
|
-
});
|
|
294
|
-
current.concat(incoming).slice(0, config.screenshots.max).forEach(function (file) {
|
|
295
|
-
transfer.items.add(file);
|
|
296
|
-
});
|
|
297
|
-
fileInput.files = transfer.files;
|
|
298
|
-
renderFileChips();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function removeFile(index) {
|
|
302
|
-
if (!fileInput) return;
|
|
303
|
-
var transfer = new DataTransfer();
|
|
304
|
-
Array.prototype.slice.call(fileInput.files).forEach(function (file, i) {
|
|
305
|
-
if (i !== index) transfer.items.add(file);
|
|
306
|
-
});
|
|
307
|
-
fileInput.files = transfer.files;
|
|
308
|
-
renderFileChips();
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function renderFileChips() {
|
|
312
|
-
if (!fileChips) return;
|
|
313
|
-
fileChips.textContent = "";
|
|
314
|
-
Array.prototype.slice.call(fileInput.files).forEach(function (file, index) {
|
|
315
|
-
var chip = document.createElement("li");
|
|
316
|
-
var name = document.createElement("span");
|
|
317
|
-
name.textContent = file.name;
|
|
318
|
-
var remove = document.createElement("button");
|
|
319
|
-
remove.type = "button";
|
|
320
|
-
remove.setAttribute("aria-label", config.labels.close + " " + file.name);
|
|
321
|
-
remove.textContent = "×";
|
|
322
|
-
remove.addEventListener("click", function () {
|
|
323
|
-
removeFile(index);
|
|
324
|
-
});
|
|
325
|
-
chip.appendChild(name);
|
|
326
|
-
chip.appendChild(remove);
|
|
327
|
-
fileChips.appendChild(chip);
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
258
|
// --- submit -------------------------------------------------------------------
|
|
332
259
|
|
|
333
260
|
function submit(form) {
|
|
@@ -436,12 +363,6 @@
|
|
|
436
363
|
"border:1px solid #d1d5db;border-radius:6px;background:none;color:#1c2024;font:inherit;cursor:pointer}",
|
|
437
364
|
"#fbe-dialog textarea{resize:vertical}",
|
|
438
365
|
"#fbe-dialog .fbe-hint{display:block;margin-top:4px;font-size:12px;color:#6b7280;font-weight:400}",
|
|
439
|
-
"#fbe-dialog .fbe-chips{list-style:none;margin:6px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px}",
|
|
440
|
-
"#fbe-dialog .fbe-chips li{display:flex;align-items:center;gap:4px;max-width:100%;",
|
|
441
|
-
"padding:2px 4px 2px 10px;border:1px solid #d1d5db;border-radius:999px;font-size:12px;font-weight:400}",
|
|
442
|
-
"#fbe-dialog .fbe-chips span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:180px}",
|
|
443
|
-
"#fbe-dialog .fbe-chips button{border:0;background:none;color:inherit;cursor:pointer;",
|
|
444
|
-
"font-size:14px;line-height:1;padding:2px 6px}",
|
|
445
366
|
"#fbe-dialog .fbe-error{color:#dc2626;margin:0 0 12px}",
|
|
446
367
|
"#fbe-dialog .fbe-actions{display:flex;justify-content:flex-end;gap:8px}",
|
|
447
368
|
"#fbe-dialog button{padding:8px 14px;border-radius:8px;cursor:pointer;font:inherit}",
|
|
@@ -454,7 +375,6 @@
|
|
|
454
375
|
"#fbe-dialog select,#fbe-dialog textarea,#fbe-dialog input[type=file]{border-color:#2a313a}",
|
|
455
376
|
"#fbe-dialog input[type=file]{color:#9aa2ab}",
|
|
456
377
|
"#fbe-dialog input[type=file]::file-selector-button{border-color:#2a313a;color:#e6e8ea}",
|
|
457
|
-
"#fbe-dialog .fbe-chips li{border-color:#2a313a}",
|
|
458
378
|
"#fbe-dialog .fbe-secondary{border-color:#2a313a}",
|
|
459
379
|
"#fbe-dialog .fbe-hint{color:#9aa2ab}",
|
|
460
380
|
"}"
|