headmin 0.2.3 → 0.2.7
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/.nvmrc +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +10 -7
- data/app/helpers/headmin/admin_helper.rb +3 -59
- data/app/helpers/headmin/bootstrap_helper.rb +9 -0
- data/app/helpers/headmin/filter_helper.rb +7 -3
- data/app/helpers/headmin/form_helper.rb +36 -0
- data/app/helpers/headmin/request_helper.rb +39 -0
- data/app/models/concerns/headmin/fieldable.rb +53 -23
- data/app/services/block_service.rb +8 -4
- data/app/views/headmin/_blocks.html.erb +1 -1
- data/app/views/headmin/_filters.html.erb +1 -1
- data/app/views/headmin/_pagination.html.erb +4 -1
- data/app/views/headmin/dropdown/_devise.html.erb +20 -10
- data/app/views/headmin/dropdown/_list.html.erb +17 -7
- data/app/views/headmin/filters/_select.html.erb +3 -2
- data/app/views/headmin/filters/filter/_button.html.erb +0 -1
- data/app/views/headmin/forms/_blocks.html.erb +11 -4
- data/app/views/headmin/forms/_date.html.erb +1 -1
- data/app/views/headmin/forms/_label.html.erb +2 -2
- data/app/views/headmin/forms/_repeater.html.erb +6 -10
- data/app/views/headmin/table/_actions.html.erb +37 -11
- data/app/views/headmin/views/devise/confirmations/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/passwords/_edit.html.erb +2 -2
- data/app/views/headmin/views/devise/passwords/_new.html.erb +1 -1
- data/app/views/headmin/views/devise/registrations/_edit.html.erb +4 -4
- data/app/views/headmin/views/devise/registrations/_new.html.erb +3 -3
- data/app/views/headmin/views/devise/shared/_links.html.erb +7 -7
- data/app/views/headmin/views/devise/unlocks/_new.html.erb +1 -1
- data/config/locales/activerecord/en.yml +9 -0
- data/config/locales/activerecord/nl.yml +9 -0
- data/config/locales/headmin/table/en.yml +5 -1
- data/config/locales/headmin/table/nl.yml +5 -1
- data/config/locales/headmin/views/en.yml +1 -1
- data/config/locales/headmin/views/nl.yml +14 -14
- data/dist/css/headmin.css +54 -13
- data/dist/js/headmin.js +45 -513
- data/docs/blocks-and-fields.md +54 -0
- data/docs/blocks.md +1 -54
- data/docs/devise.md +40 -2
- data/docs/fields.md +31 -9
- data/headmin.gemspec +1 -1
- data/lib/generators/headmin/blocks_generator.rb +4 -1
- data/lib/generators/headmin/devise_generator.rb +16 -0
- data/lib/generators/headmin/fields_generator.rb +5 -1
- data/lib/generators/templates/controllers/auth/confirmations_controller.rb +31 -0
- data/lib/generators/templates/controllers/auth/omniauth_callbacks_controller.rb +31 -0
- data/lib/generators/templates/controllers/auth/passwords_controller.rb +35 -0
- data/lib/generators/templates/controllers/auth/registrations_controller.rb +63 -0
- data/lib/generators/templates/controllers/auth/sessions_controller.rb +28 -0
- data/lib/generators/templates/controllers/auth/unlocks_controller.rb +31 -0
- data/lib/generators/templates/migrations/create_field_hierarchies.rb +16 -0
- data/lib/generators/templates/views/auth/confirmations/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/confirmation_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/email_changed.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/password_change.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/reset_password_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/mailer/unlock_instructions.html.erb +1 -0
- data/lib/generators/templates/views/auth/passwords/edit.html.erb +1 -0
- data/lib/generators/templates/views/auth/passwords/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/registrations/edit.html.erb +1 -0
- data/lib/generators/templates/views/auth/registrations/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/sessions/new.html.erb +1 -0
- data/lib/generators/templates/views/auth/unlocks/new.html.erb +1 -0
- data/lib/generators/templates/views/layouts/auth.html.erb +20 -0
- data/lib/headmin/version.rb +1 -1
- data/package.json +4 -3
- data/src/js/headmin/controllers/blocks_controller.js +1 -1
- data/src/js/headmin/controllers/filter_controller.js +1 -1
- data/src/js/headmin/controllers/filters_controller.js +1 -1
- data/src/js/headmin/controllers/popup_controller.js +1 -1
- data/src/js/headmin/controllers/repeater_controller.js +9 -10
- data/src/js/headmin/controllers/table_actions_controller.js +104 -9
- data/src/js/headmin/controllers/table_controller.js +28 -57
- data/src/js/headmin/headmin.js +2 -2
- data/src/scss/headmin/table.scss +1 -0
- data/yarn.lock +1159 -1237
- metadata +33 -7
- data/docs/README.md +0 -5
@@ -1,4 +1,4 @@
|
|
1
|
-
import {Controller} from "stimulus"
|
1
|
+
import {Controller} from "@hotwired/stimulus"
|
2
2
|
import Sortable from "sortablejs";
|
3
3
|
|
4
4
|
export default class extends Controller {
|
@@ -38,7 +38,6 @@ export default class extends Controller {
|
|
38
38
|
}
|
39
39
|
|
40
40
|
updatePopupButtonIndices(index) {
|
41
|
-
console.log(index)
|
42
41
|
const popup = document.querySelector(`[data-popup-target="popup"][data-popup-id="repeater-buttons-${this.idValue}"]`)
|
43
42
|
const buttons = popup.querySelectorAll('a')
|
44
43
|
buttons.forEach((button) => {
|
@@ -53,8 +52,8 @@ export default class extends Controller {
|
|
53
52
|
let rowIndex = button.dataset.rowIndex
|
54
53
|
|
55
54
|
// Prepare html from template
|
56
|
-
|
57
|
-
html = this.replaceIdsWithTimestamps(
|
55
|
+
const template = this.getTemplate(templateName)
|
56
|
+
const html = this.replaceIdsWithTimestamps(template)
|
58
57
|
|
59
58
|
// Fallback to last row if no index is set
|
60
59
|
if (rowIndex) {
|
@@ -93,16 +92,16 @@ export default class extends Controller {
|
|
93
92
|
this.toggleEmpty()
|
94
93
|
}
|
95
94
|
|
96
|
-
|
97
|
-
|
95
|
+
getTemplate(name) {
|
96
|
+
return this.templateTargets.filter((template) => {
|
98
97
|
return template.dataset.templateName === name
|
99
98
|
})[0]
|
100
|
-
return template.innerHTML
|
101
99
|
}
|
102
100
|
|
103
|
-
replaceIdsWithTimestamps(
|
104
|
-
|
105
|
-
|
101
|
+
replaceIdsWithTimestamps(template) {
|
102
|
+
console.log(template)
|
103
|
+
const regex = new RegExp(template.dataset.templateIdRegex, "g")
|
104
|
+
return template.innerHTML.replace(regex, new Date().getTime())
|
106
105
|
}
|
107
106
|
|
108
107
|
visibleRowsCount() {
|
@@ -1,33 +1,128 @@
|
|
1
|
-
import {Controller} from "stimulus"
|
1
|
+
import {Controller} from "@hotwired/stimulus"
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
|
+
static get values() {
|
5
|
+
return {
|
6
|
+
count: {type: Number, default: 0}
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
4
10
|
static get targets() {
|
5
|
-
return ["form", "select", "method", "button"]
|
11
|
+
return ["wrapper", "form", "select", "method", "button", "idInputTemplate", "id", "counter"]
|
6
12
|
}
|
7
13
|
|
8
14
|
connect() {
|
9
|
-
this.
|
15
|
+
this.wrapperTarget.addEventListener('idSelectionChanged', (event) => {
|
16
|
+
const ids = event.detail.ids
|
17
|
+
this.updateIdFields(ids)
|
18
|
+
this.updateCountValueWithIds(ids)
|
19
|
+
})
|
20
|
+
|
10
21
|
}
|
11
22
|
|
12
23
|
update(event) {
|
13
24
|
event.preventDefault()
|
14
|
-
|
25
|
+
this.updateFormAction()
|
26
|
+
this.updateFormMethod()
|
27
|
+
this.updateButton()
|
28
|
+
}
|
29
|
+
|
30
|
+
updateIdFields(ids) {
|
31
|
+
this.removeIds()
|
32
|
+
if (ids instanceof Array) {
|
33
|
+
this.countValue = ids.length
|
34
|
+
ids.forEach((id) => {
|
35
|
+
this.addId(id)
|
36
|
+
})
|
37
|
+
} else {
|
38
|
+
this.countValue = Infinity
|
39
|
+
this.addId('')
|
40
|
+
}
|
41
|
+
}
|
15
42
|
|
16
|
-
|
43
|
+
updateCounter() {
|
44
|
+
let htmlString = ''
|
45
|
+
switch (this.countValue) {
|
46
|
+
case 0:
|
47
|
+
htmlString = this.counterTarget.getAttribute('data-items-zero')
|
48
|
+
break;
|
49
|
+
case 1:
|
50
|
+
htmlString = this.counterTarget.getAttribute('data-items-one')
|
51
|
+
break;
|
52
|
+
case Infinity:
|
53
|
+
htmlString = this.counterTarget.getAttribute('data-items-other')
|
54
|
+
htmlString = htmlString.replace(/<b>[\s\S]*?<\/b>/, '<b>' + this.totalCount() + '<\/b>');
|
55
|
+
break;
|
56
|
+
default:
|
57
|
+
htmlString = this.counterTarget.getAttribute('data-items-other')
|
58
|
+
let count = this.countValue === Infinity ? this.totalCount() : this.countValue
|
59
|
+
htmlString = htmlString.replace(/<b>[\s\S]*?<\/b>/, `<b>${count}<\/b>`);
|
60
|
+
}
|
61
|
+
this.counterTarget.innerHTML = htmlString;
|
62
|
+
}
|
63
|
+
|
64
|
+
totalCount() {
|
65
|
+
return this.counterTarget.getAttribute('data-total-count')
|
66
|
+
}
|
67
|
+
|
68
|
+
updateCountValueWithIds(ids) {
|
69
|
+
if (ids instanceof Array) {
|
70
|
+
this.countValue = ids.length
|
71
|
+
} else {
|
72
|
+
this.countValue = Infinity
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
countValueChanged() {
|
77
|
+
this.updateCounter()
|
78
|
+
this.toggle()
|
79
|
+
}
|
80
|
+
|
81
|
+
toggle() {
|
82
|
+
if (this.countValue > 0) {
|
83
|
+
this.wrapperTarget.classList.remove('d-none')
|
84
|
+
} else {
|
85
|
+
this.wrapperTarget.classList.add('d-none')
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
updateFormAction() {
|
17
90
|
this.formTarget.action = this.selectTarget.value
|
91
|
+
}
|
18
92
|
|
19
|
-
|
93
|
+
updateFormMethod() {
|
94
|
+
const option = this.selectedOption()
|
20
95
|
this.methodTarget.value = option.dataset.method
|
96
|
+
}
|
21
97
|
|
22
|
-
|
98
|
+
updateButton() {
|
99
|
+
const option = this.selectedOption()
|
23
100
|
const confirm = option.dataset.confirm
|
24
|
-
if(confirm) {
|
101
|
+
if (confirm) {
|
25
102
|
this.buttonTarget.dataset.confirm = confirm
|
26
103
|
} else {
|
27
104
|
this.buttonTarget.removeAttribute('data-confirm')
|
28
105
|
}
|
106
|
+
this.enableButton()
|
107
|
+
}
|
108
|
+
|
109
|
+
selectedOption() {
|
110
|
+
return this.selectTarget.options[this.selectTarget.selectedIndex]
|
111
|
+
}
|
29
112
|
|
30
|
-
|
113
|
+
enableButton() {
|
31
114
|
this.buttonTarget.removeAttribute('disabled')
|
32
115
|
}
|
116
|
+
|
117
|
+
addId(id) {
|
118
|
+
const template = this.idInputTemplateTarget
|
119
|
+
const input = template.innerHTML.replace(/ID/g, id)
|
120
|
+
this.formTarget.insertAdjacentHTML('afterbegin', input)
|
121
|
+
}
|
122
|
+
|
123
|
+
removeIds() {
|
124
|
+
this.idTargets.forEach((input) => {
|
125
|
+
this.formTarget.removeChild(input)
|
126
|
+
});
|
127
|
+
}
|
33
128
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {Controller} from "stimulus"
|
1
|
+
import {Controller} from "@hotwired/stimulus"
|
2
2
|
import Sortable from "sortablejs";
|
3
3
|
import Rails from "@rails/ujs";
|
4
4
|
|
@@ -38,25 +38,43 @@ export default class extends Controller {
|
|
38
38
|
const checkbox = event.target
|
39
39
|
this.toggleIdsCheckboxes(checkbox.checked)
|
40
40
|
this.toggleIdCheckboxes(checkbox.checked)
|
41
|
-
this.
|
42
|
-
this.toggleActions()
|
41
|
+
this.updateActions()
|
43
42
|
}
|
44
43
|
|
45
44
|
toggleId(event) {
|
46
45
|
this.toggleIdsCheckboxes(false)
|
47
|
-
this.
|
48
|
-
this.toggleActions()
|
46
|
+
this.updateActions()
|
49
47
|
}
|
50
48
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
updateActions() {
|
50
|
+
this.actionsTarget.dispatchEvent(
|
51
|
+
new CustomEvent(
|
52
|
+
'idSelectionChanged',
|
53
|
+
{
|
54
|
+
detail: {
|
55
|
+
ids: this.ids()
|
56
|
+
}
|
57
|
+
}
|
58
|
+
)
|
59
|
+
)
|
60
|
+
}
|
61
|
+
|
62
|
+
ids() {
|
63
|
+
if (this.idsCheckboxTarget.checked) {
|
64
|
+
return null
|
55
65
|
} else {
|
56
|
-
this.
|
66
|
+
return this.selectedIdCheckboxes().map((checkbox) => {
|
67
|
+
return checkbox.value
|
68
|
+
})
|
57
69
|
}
|
58
70
|
}
|
59
71
|
|
72
|
+
selectedIdCheckboxes() {
|
73
|
+
return this.idCheckboxTargets.filter((checkbox) => {
|
74
|
+
return checkbox.checked
|
75
|
+
})
|
76
|
+
}
|
77
|
+
|
60
78
|
toggleIdsCheckboxes(checked) {
|
61
79
|
this.idsCheckboxTargets.forEach((checkbox) => {
|
62
80
|
checkbox.checked = checked
|
@@ -69,51 +87,4 @@ export default class extends Controller {
|
|
69
87
|
});
|
70
88
|
}
|
71
89
|
|
72
|
-
syncFields() {
|
73
|
-
this.removeIds()
|
74
|
-
if(this.idsCheckboxTarget.checked) {
|
75
|
-
this.addId('')
|
76
|
-
} else {
|
77
|
-
this.idCheckboxTargets.forEach((checkbox) => {
|
78
|
-
if(checkbox.checked) {
|
79
|
-
this.addId(checkbox.value)
|
80
|
-
}
|
81
|
-
});
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
|
-
addId(id) {
|
86
|
-
let field = this.getIdField(id)
|
87
|
-
if (!field) {
|
88
|
-
field = this.newIdField(id)
|
89
|
-
this.actionsTarget.querySelector('form').insertAdjacentHTML('afterbegin', field)
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
removeIds() {
|
94
|
-
const fields = this.getIdFields()
|
95
|
-
fields.forEach((field) => {
|
96
|
-
this.actionsTarget.querySelector('form').removeChild(field)
|
97
|
-
});
|
98
|
-
}
|
99
|
-
|
100
|
-
removeId(id) {
|
101
|
-
const field = this.getIdField(id)
|
102
|
-
if (field) {
|
103
|
-
this.actionsTarget.querySelector('form').removeChild(field)
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
newIdField(id) {
|
108
|
-
const template = this.actionsTarget.querySelector('[data-table-target="idFieldTemplate"]')
|
109
|
-
return template.innerHTML.replace(/ID/g, id)
|
110
|
-
}
|
111
|
-
|
112
|
-
getIdFields() {
|
113
|
-
return this.actionsTarget.querySelectorAll(`input[name="ids[]"]`);
|
114
|
-
}
|
115
|
-
|
116
|
-
getIdField(id) {
|
117
|
-
return this.actionsTarget.querySelector(`input[name="ids[]"][value="${id}"]`);
|
118
|
-
}
|
119
90
|
}
|
data/src/js/headmin/headmin.js
CHANGED
@@ -4,8 +4,8 @@ import flatpickr from "flatpickr";
|
|
4
4
|
import bootstrap from "bootstrap/dist/js/bootstrap.bundle";
|
5
5
|
import Rails from "@rails/ujs";
|
6
6
|
|
7
|
-
import {Application} from "stimulus"
|
8
|
-
import {definitionsFromContext} from "stimulus
|
7
|
+
import {Application} from "@hotwired/stimulus"
|
8
|
+
import {definitionsFromContext} from "@hotwired/stimulus-webpack-helpers"
|
9
9
|
|
10
10
|
export class Headmin {
|
11
11
|
static start() {
|