katalyst-koi 5.1.0 → 5.3.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/README.md +6 -4
- data/app/assets/builds/katalyst/koi.esm.js +23 -337
- data/app/assets/builds/katalyst/koi.js +23 -337
- data/app/assets/builds/katalyst/koi.min.js +1 -1
- data/app/assets/builds/katalyst/koi.min.js.map +1 -1
- data/app/assets/fonts/koi/inconsolata-license.txt +93 -0
- data/app/assets/fonts/koi/inconsolata-v37-latin-regular.woff2 +0 -0
- data/app/assets/fonts/koi/inter-license.txt +92 -0
- data/app/assets/fonts/koi/inter-variable-v4-1-italic.woff2 +0 -0
- data/app/assets/fonts/koi/inter-variable-v4-1.woff2 +0 -0
- data/app/assets/stylesheets/koi/blocks/pagy.css +2 -1
- data/app/assets/stylesheets/koi/global/fonts.css +85 -7
- data/app/assets/stylesheets/koi/utilities/visually-hidden.css +0 -7
- data/app/controllers/admin/admin_users_controller.rb +3 -3
- data/app/controllers/admin/caches_controller.rb +1 -1
- data/app/controllers/admin/otps_controller.rb +1 -1
- data/app/controllers/admin/sessions_controller.rb +5 -2
- data/app/controllers/concerns/koi/controller/has_admin_users.rb +10 -1
- data/app/controllers/concerns/koi/controller/has_webauthn.rb +1 -1
- data/app/controllers/concerns/koi/controller.rb +9 -5
- data/app/controllers/well_knowns_controller.rb +8 -13
- data/app/javascript/koi/controllers/index.js +0 -15
- data/app/javascript/koi/controllers/webauthn_authentication_controller.js +13 -12
- data/app/javascript/koi/controllers/webauthn_registration_controller.js +10 -11
- data/app/models/admin/user.rb +24 -0
- data/app/models/well_known.rb +0 -4
- data/app/views/admin/admin_users/index.html.erb +1 -3
- data/app/views/layouts/koi/application.html.erb +8 -3
- data/app/views/layouts/koi/frame.html.erb +2 -2
- data/app/views/layouts/koi/login.html.erb +9 -4
- data/config/importmap.rb +0 -1
- data/config/locales/pagy/en.yml +24 -0
- data/db/seeds.rb +1 -2
- data/lib/generators/koi/admin_controller/templates/controller.rb.tt +8 -8
- data/lib/koi/engine.rb +6 -1
- metadata +8 -8
- data/Upgrade.md +0 -10
- data/app/assets/stylesheets/koi/blocks/index-actions.css +0 -69
- data/app/helpers/koi/index_actions_helper.rb +0 -98
- data/app/javascript/koi/controllers/form_request_submit_controller.js +0 -11
- data/app/javascript/koi/controllers/index_actions_controller.js +0 -60
- data/config/locales/pagy.en.yml +0 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6937b0a5bf4cdef293b89e7c161bd5d93f04ad21a36f49cbd4076fc2852f18de
|
|
4
|
+
data.tar.gz: 1972770915bc76a57277111d7f89f7765b318f658ce8e038f81f62bb4ada74f5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9413dc2f0a998a20ea1e7b82aad89a00f184a2bb7ba092bcb05107da11e20ed62bf4542e9142139ae66c6f004187ffbce38c051c58664c20811ab98161a5f291
|
|
7
|
+
data.tar.gz: e11c4ca35de970aee07600c460d17c6c11a6a77e74a0925d2ca05fc7ca9eb8f86844417d3c24f67af5c679edee7fd803ae920ed80d32a736298bbd9dbfdae708
|
data/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Koi
|
|
2
2
|
|
|
3
|
+
Koi is a framework for building Rails admin functionality.
|
|
4
|
+
|
|
3
5
|
## Installation
|
|
4
6
|
|
|
5
7
|
Add this line to your application's Gemfile:
|
|
@@ -14,10 +16,10 @@ And then execute:
|
|
|
14
16
|
bundle install
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
##
|
|
19
|
+
## Contributing
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/katalyst/katalyst-tables.
|
|
20
22
|
|
|
21
|
-
##
|
|
23
|
+
## License
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
Katalyst Tables is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -6,7 +6,6 @@ import { Application, Controller } from '@hotwired/stimulus';
|
|
|
6
6
|
import content from '@katalyst/content';
|
|
7
7
|
import navigation from '@katalyst/navigation';
|
|
8
8
|
import tables from '@katalyst/tables';
|
|
9
|
-
import { get, parseRequestOptionsFromJSON, create, parseCreationOptionsFromJSON } from '@github/webauthn-json/browser-ponyfill';
|
|
10
9
|
|
|
11
10
|
const application = Application.start();
|
|
12
11
|
|
|
@@ -43,75 +42,6 @@ class FlashController extends Controller {
|
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
/**
|
|
47
|
-
A stimulus controller to request form submissions.
|
|
48
|
-
This controller should be attached to a form element.
|
|
49
|
-
*/
|
|
50
|
-
class FormRequestSubmitController extends Controller {
|
|
51
|
-
requestSubmit() {
|
|
52
|
-
this.element.requestSubmit();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
class IndexActionsController extends Controller {
|
|
57
|
-
static targets = ["create", "search", "sort"];
|
|
58
|
-
|
|
59
|
-
initialize() {
|
|
60
|
-
// debounce search
|
|
61
|
-
this.update = debounce(this, this.update);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
disconnect() {
|
|
65
|
-
clearTimeout(this.timer);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
create() {
|
|
69
|
-
this.createTarget.click();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
search() {
|
|
73
|
-
this.searchTarget.focus();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
clear() {
|
|
77
|
-
this.searchTarget.value = "";
|
|
78
|
-
this.searchTarget.closest("form").requestSubmit();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
update() {
|
|
82
|
-
this.searchTarget.closest("form").requestSubmit();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
submit() {
|
|
86
|
-
const shouldFocus = document.activeElement === this.searchTarget;
|
|
87
|
-
|
|
88
|
-
if (this.searchTarget.value === "") {
|
|
89
|
-
this.searchTarget.disabled = true;
|
|
90
|
-
}
|
|
91
|
-
if (this.sortTarget.value === "") {
|
|
92
|
-
this.sortTarget.disabled = true;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// restore state and focus after submit
|
|
96
|
-
Promise.resolve().then(() => {
|
|
97
|
-
this.searchTarget.disabled = false;
|
|
98
|
-
this.sortTarget.disabled = false;
|
|
99
|
-
if (shouldFocus) {
|
|
100
|
-
this.searchTarget.focus();
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function debounce(self, f) {
|
|
107
|
-
return (...args) => {
|
|
108
|
-
clearTimeout(self.timer);
|
|
109
|
-
self.timer = setTimeout(() => {
|
|
110
|
-
f.apply(self, ...args);
|
|
111
|
-
}, 300);
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
45
|
class KeyboardController extends Controller {
|
|
116
46
|
static values = {
|
|
117
47
|
mapping: String,
|
|
@@ -423,248 +353,6 @@ class PagyNavController extends Controller {
|
|
|
423
353
|
};
|
|
424
354
|
}
|
|
425
355
|
|
|
426
|
-
const DEFAULT_DELAY = 250;
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* A utility class for managing CSS transition animations.
|
|
430
|
-
*
|
|
431
|
-
* Transition uses Javascript timers to track state instead of relying on
|
|
432
|
-
* CSS transition events, which is a more complicated API. Please call `cancel`
|
|
433
|
-
* when the node being animated is detached from the DOM to avoid unexpected
|
|
434
|
-
* errors or animation glitches.
|
|
435
|
-
*
|
|
436
|
-
* Transition assumes that CSS already specifies styles to achieve the expected
|
|
437
|
-
* start and end states. Transition adds temporary overrides and then animates
|
|
438
|
-
* between those values using CSS transitions. For example, to use the collapse
|
|
439
|
-
* transition:
|
|
440
|
-
*
|
|
441
|
-
* @example
|
|
442
|
-
* // CSS:
|
|
443
|
-
* target {
|
|
444
|
-
* max-height: unset;
|
|
445
|
-
* overflow: 0;
|
|
446
|
-
* }
|
|
447
|
-
* target.hidden {
|
|
448
|
-
* max-height: 0;
|
|
449
|
-
* }
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* // Javascript
|
|
453
|
-
* target.addClass("hidden");
|
|
454
|
-
* new Transition(target).collapse().start();
|
|
455
|
-
*/
|
|
456
|
-
class Transition {
|
|
457
|
-
constructor(target, options) {
|
|
458
|
-
const { delay } = this._setDefaults(options);
|
|
459
|
-
|
|
460
|
-
this.target = target;
|
|
461
|
-
this.runner = new Runner(this, delay);
|
|
462
|
-
this.properties = [];
|
|
463
|
-
|
|
464
|
-
this.startingCallbacks = [];
|
|
465
|
-
this.startedCallbacks = [];
|
|
466
|
-
this.completeCallbacks = [];
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
add(property) {
|
|
470
|
-
this.properties.push(property);
|
|
471
|
-
return this;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/** Adds callback for transition events */
|
|
475
|
-
addCallback(type, callback) {
|
|
476
|
-
switch (type) {
|
|
477
|
-
case "starting":
|
|
478
|
-
this.startingCallbacks.push(callback);
|
|
479
|
-
break;
|
|
480
|
-
case "started":
|
|
481
|
-
this.startedCallbacks.push(callback);
|
|
482
|
-
break;
|
|
483
|
-
case "complete":
|
|
484
|
-
this.completeCallbacks.push(callback);
|
|
485
|
-
break;
|
|
486
|
-
}
|
|
487
|
-
return this;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
/** Collapse an element in place, assumes overflow is set appropriately, margin is not collapsed */
|
|
491
|
-
collapse() {
|
|
492
|
-
return this.add(
|
|
493
|
-
new PropertyTransition(
|
|
494
|
-
"max-height",
|
|
495
|
-
`${this.target.scrollHeight}px`,
|
|
496
|
-
"0px",
|
|
497
|
-
),
|
|
498
|
-
);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/** Restore a collapsed element */
|
|
502
|
-
expand() {
|
|
503
|
-
return this.add(
|
|
504
|
-
new PropertyTransition(
|
|
505
|
-
"max-height",
|
|
506
|
-
"0px",
|
|
507
|
-
`${this.target.scrollHeight}px`,
|
|
508
|
-
),
|
|
509
|
-
);
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
/** Slide an element left or right by its scroll width, assumes position relative */
|
|
513
|
-
slideOut(direction) {
|
|
514
|
-
return this.add(
|
|
515
|
-
new PropertyTransition(direction, "0px", `-${this.target.scrollWidth}px`),
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/** Restore an element that has been slid */
|
|
520
|
-
slideIn(direction) {
|
|
521
|
-
return this.add(
|
|
522
|
-
new PropertyTransition(direction, `-${this.target.scrollWidth}px`, "0px"),
|
|
523
|
-
);
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
/** Cause an element to become transparent by transforming opacity */
|
|
527
|
-
fadeOut() {
|
|
528
|
-
return this.add(new PropertyTransition("opacity", "100%", "0%"));
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
/** Cause a transparent element to become visible again */
|
|
532
|
-
fadeIn() {
|
|
533
|
-
return this.add(new PropertyTransition("opacity", "0%", "100%"));
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
start(callback = null) {
|
|
537
|
-
// start the runner on next tick so that any side-effects of the current execution can occur first
|
|
538
|
-
requestAnimationFrame(() => {
|
|
539
|
-
this.runner.start(this.target);
|
|
540
|
-
if (callback) callback();
|
|
541
|
-
});
|
|
542
|
-
return this;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
cancel() {
|
|
546
|
-
this.runner.stop(this.target);
|
|
547
|
-
return this;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
_starting() {
|
|
551
|
-
const event = new Event("transition:starting");
|
|
552
|
-
this.startingCallbacks.forEach((cb) => cb(event));
|
|
553
|
-
this.target.dispatchEvent(event);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
_started() {
|
|
557
|
-
const event = new Event("transition:started");
|
|
558
|
-
this.startedCallbacks.forEach((cb) => cb(event));
|
|
559
|
-
this.target.dispatchEvent(event);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
_complete() {
|
|
563
|
-
const event = new Event("transition:complete");
|
|
564
|
-
this.completeCallbacks.forEach((cb) => cb(event));
|
|
565
|
-
this.target.dispatchEvent(event);
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
_setDefaults(options) {
|
|
569
|
-
return Object.assign({ delay: DEFAULT_DELAY }, options);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/**
|
|
574
|
-
* Encapsulates internal execution and timing functionality for `Transition`
|
|
575
|
-
*/
|
|
576
|
-
class Runner {
|
|
577
|
-
constructor(transition, delay) {
|
|
578
|
-
this.transition = transition;
|
|
579
|
-
this.running = null;
|
|
580
|
-
this.delay = delay;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
start(target) {
|
|
584
|
-
// 1. Set the initial state(s)
|
|
585
|
-
this.transition.properties.forEach((t) => t.onStarting(target));
|
|
586
|
-
|
|
587
|
-
// 2. On next update, set transition and final state(s)
|
|
588
|
-
requestAnimationFrame(() => this.onStarted(target));
|
|
589
|
-
|
|
590
|
-
// 3. After transition has finished, clean up
|
|
591
|
-
this.running = setTimeout(() => this.stop(target, true), this.delay);
|
|
592
|
-
|
|
593
|
-
this.transition._starting();
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
onStarted(target) {
|
|
597
|
-
target.style.transitionProperty = this.transition.properties
|
|
598
|
-
.map((t) => t.property)
|
|
599
|
-
.join(",");
|
|
600
|
-
target.style.transitionDuration = `${this.delay}ms`;
|
|
601
|
-
this.transition.properties.forEach((t) => t.onStarted(target));
|
|
602
|
-
|
|
603
|
-
this.transition._started();
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
stop(target, timeout = false) {
|
|
607
|
-
if (!this.running) return;
|
|
608
|
-
if (!timeout) clearTimeout(this.running);
|
|
609
|
-
|
|
610
|
-
this.running = null;
|
|
611
|
-
|
|
612
|
-
target.style.removeProperty("transition-property");
|
|
613
|
-
target.style.removeProperty("transition-duration");
|
|
614
|
-
this.transition.properties.forEach((t) => t.onComplete(target));
|
|
615
|
-
|
|
616
|
-
this.transition._complete();
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* Represents animation of a single CSS property. Currently only CSS animations
|
|
622
|
-
* are supported, but this could be a natural extension point for Javascript
|
|
623
|
-
* animations in the future.
|
|
624
|
-
*/
|
|
625
|
-
class PropertyTransition {
|
|
626
|
-
constructor(property, from, to) {
|
|
627
|
-
this.property = property;
|
|
628
|
-
this.from = from;
|
|
629
|
-
this.to = to;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
onStarting(target) {
|
|
633
|
-
target.style.setProperty(this.property, this.from);
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
onStarted(target) {
|
|
637
|
-
target.style.setProperty(this.property, this.to);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
onComplete(target) {
|
|
641
|
-
target.style.removeProperty(this.property);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
class ShowHideController extends Controller {
|
|
646
|
-
static targets = ["content"];
|
|
647
|
-
|
|
648
|
-
toggle() {
|
|
649
|
-
const element = this.contentTarget;
|
|
650
|
-
const hide = element.toggleAttribute("data-collapsed");
|
|
651
|
-
|
|
652
|
-
// cancel previous animation, if any
|
|
653
|
-
if (this.transition) this.transition.cancel();
|
|
654
|
-
|
|
655
|
-
const transition = (this.transition = new Transition(element)
|
|
656
|
-
.addCallback("starting", function () {
|
|
657
|
-
element.setAttribute("data-collapsed-transitioning", "true");
|
|
658
|
-
})
|
|
659
|
-
.addCallback("complete", function () {
|
|
660
|
-
element.removeAttribute("data-collapsed-transitioning");
|
|
661
|
-
}));
|
|
662
|
-
hide ? transition.collapse() : transition.expand();
|
|
663
|
-
|
|
664
|
-
transition.start();
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
356
|
/**
|
|
669
357
|
* Connect an input (e.g. title) to slug.
|
|
670
358
|
*/
|
|
@@ -696,25 +384,31 @@ function parameterize(input) {
|
|
|
696
384
|
|
|
697
385
|
class WebauthnAuthenticationController extends Controller {
|
|
698
386
|
static targets = ["response"];
|
|
699
|
-
static values = {
|
|
387
|
+
static values = {
|
|
388
|
+
options: Object,
|
|
389
|
+
};
|
|
700
390
|
|
|
701
|
-
authenticate() {
|
|
702
|
-
get(this.options)
|
|
703
|
-
this.responseTarget.value = JSON.stringify(response);
|
|
391
|
+
async authenticate() {
|
|
392
|
+
const credential = await navigator.credentials.get(this.options);
|
|
704
393
|
|
|
705
|
-
|
|
706
|
-
|
|
394
|
+
this.responseTarget.value = JSON.stringify(credential.toJSON());
|
|
395
|
+
|
|
396
|
+
this.element.requestSubmit();
|
|
707
397
|
}
|
|
708
398
|
|
|
709
399
|
get options() {
|
|
710
|
-
return
|
|
400
|
+
return {
|
|
401
|
+
publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(
|
|
402
|
+
this.optionsValue.publicKey,
|
|
403
|
+
),
|
|
404
|
+
};
|
|
711
405
|
}
|
|
712
406
|
}
|
|
713
407
|
|
|
714
408
|
class WebauthnRegistrationController extends Controller {
|
|
715
409
|
static values = {
|
|
716
410
|
options: Object,
|
|
717
|
-
response:
|
|
411
|
+
response: Object,
|
|
718
412
|
};
|
|
719
413
|
static targets = ["intro", "nickname", "response"];
|
|
720
414
|
|
|
@@ -724,15 +418,15 @@ class WebauthnRegistrationController extends Controller {
|
|
|
724
418
|
e.submitter.formMethod !== "dialog"
|
|
725
419
|
) {
|
|
726
420
|
e.preventDefault();
|
|
727
|
-
this.createCredential();
|
|
421
|
+
this.createCredential().then();
|
|
728
422
|
}
|
|
729
423
|
}
|
|
730
424
|
|
|
731
425
|
async createCredential() {
|
|
732
|
-
const
|
|
426
|
+
const credential = await navigator.credentials.create(this.options);
|
|
733
427
|
|
|
734
|
-
this.responseValue =
|
|
735
|
-
this.responseTarget.value = JSON.stringify(
|
|
428
|
+
this.responseValue = credential.toJSON();
|
|
429
|
+
this.responseTarget.value = JSON.stringify(credential.toJSON());
|
|
736
430
|
}
|
|
737
431
|
|
|
738
432
|
responseValueChanged(response) {
|
|
@@ -742,7 +436,11 @@ class WebauthnRegistrationController extends Controller {
|
|
|
742
436
|
}
|
|
743
437
|
|
|
744
438
|
get options() {
|
|
745
|
-
return
|
|
439
|
+
return {
|
|
440
|
+
publicKey: PublicKeyCredential.parseCreationOptionsFromJSON(
|
|
441
|
+
this.optionsValue.publicKey,
|
|
442
|
+
),
|
|
443
|
+
};
|
|
746
444
|
}
|
|
747
445
|
}
|
|
748
446
|
|
|
@@ -760,14 +458,6 @@ const Definitions = [
|
|
|
760
458
|
identifier: "flash",
|
|
761
459
|
controllerConstructor: FlashController,
|
|
762
460
|
},
|
|
763
|
-
{
|
|
764
|
-
identifier: "form-request-submit",
|
|
765
|
-
controllerConstructor: FormRequestSubmitController,
|
|
766
|
-
},
|
|
767
|
-
{
|
|
768
|
-
identifier: "index-actions",
|
|
769
|
-
controllerConstructor: IndexActionsController,
|
|
770
|
-
},
|
|
771
461
|
{
|
|
772
462
|
identifier: "keyboard",
|
|
773
463
|
controllerConstructor: KeyboardController,
|
|
@@ -788,10 +478,6 @@ const Definitions = [
|
|
|
788
478
|
identifier: "pagy-nav",
|
|
789
479
|
controllerConstructor: PagyNavController,
|
|
790
480
|
},
|
|
791
|
-
{
|
|
792
|
-
identifier: "show-hide",
|
|
793
|
-
controllerConstructor: ShowHideController,
|
|
794
|
-
},
|
|
795
481
|
{
|
|
796
482
|
identifier: "sluggable",
|
|
797
483
|
controllerConstructor: SluggableController,
|