headmin 0.5.1 → 0.5.2
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 +2 -2
- data/Gemfile +14 -0
- data/Gemfile.lock +77 -0
- data/app/assets/javascripts/headmin/controllers/media_controller.js +237 -0
- data/app/assets/javascripts/headmin/controllers/media_modal_controller.js +110 -0
- data/app/assets/javascripts/headmin/controllers/remote_modal_controller.js +10 -0
- data/app/assets/javascripts/headmin/controllers/textarea_controller.js +34 -0
- data/app/assets/javascripts/headmin/index.js +8 -0
- data/app/assets/javascripts/headmin.js +294 -0
- data/app/assets/stylesheets/headmin/forms/file.scss +40 -5
- data/app/assets/stylesheets/headmin/forms/media.scss +10 -0
- data/app/assets/stylesheets/headmin/forms/repeater.scss +4 -0
- data/app/assets/stylesheets/headmin/forms.scss +7 -0
- data/app/assets/stylesheets/headmin/layout/sidebar.scss +0 -1
- data/app/assets/stylesheets/headmin/media/index.scss +9 -0
- data/app/assets/stylesheets/headmin/media.scss +1 -0
- data/app/assets/stylesheets/headmin/table.scss +8 -0
- data/app/assets/stylesheets/headmin.css +64 -7
- data/app/assets/stylesheets/headmin.scss +1 -0
- data/app/controllers/headmin/media_controller.rb +52 -0
- data/app/controllers/headmin_controller.rb +2 -0
- data/app/models/concerns/headmin/field.rb +0 -1
- data/app/models/concerns/headmin/fieldable.rb +10 -1
- data/app/models/concerns/headmin/form/hintable.rb +6 -1
- data/app/models/headmin/filter/date.rb +49 -1
- data/app/models/headmin/form/media_view.rb +113 -0
- data/app/models/headmin/form/textarea_view.rb +6 -1
- data/app/views/examples/admin.html.erb +13 -13
- data/app/views/examples/auth.html.erb +1 -1
- data/app/views/headmin/_blocks.html.erb +2 -2
- data/app/views/headmin/_breadcrumbs.html.erb +1 -1
- data/app/views/headmin/_dropdown.html.erb +1 -1
- data/app/views/headmin/_filters.html.erb +3 -3
- data/app/views/headmin/_form.html.erb +2 -2
- data/app/views/headmin/_heading.html.erb +1 -1
- data/app/views/headmin/_index.html.erb +1 -1
- data/app/views/headmin/_notifications.html.erb +1 -1
- data/app/views/headmin/_pagination.html.erb +1 -1
- data/app/views/headmin/_popup.html.erb +2 -2
- data/app/views/headmin/_table.html.erb +1 -1
- data/app/views/headmin/dropdown/_devise.html.erb +8 -8
- data/app/views/headmin/dropdown/_list.html.erb +1 -1
- data/app/views/headmin/dropdown/_locale.html.erb +4 -4
- data/app/views/headmin/filters/_base.html.erb +20 -20
- data/app/views/headmin/filters/_boolean.html.erb +4 -4
- data/app/views/headmin/filters/_date.html.erb +4 -4
- data/app/views/headmin/filters/_flatpickr.html.erb +4 -4
- data/app/views/headmin/filters/_number.html.erb +4 -4
- data/app/views/headmin/filters/_options.html.erb +4 -4
- data/app/views/headmin/filters/_search.html.erb +3 -3
- data/app/views/headmin/filters/_text.html.erb +4 -4
- data/app/views/headmin/filters/filter/_button.html.erb +1 -1
- data/app/views/headmin/forms/_autocomplete.html.erb +2 -2
- data/app/views/headmin/forms/_blocks.html.erb +4 -4
- data/app/views/headmin/forms/_checkbox.html.erb +5 -5
- data/app/views/headmin/forms/_color.html.erb +5 -5
- data/app/views/headmin/forms/_date.html.erb +8 -8
- data/app/views/headmin/forms/_date_range.html.erb +3 -3
- data/app/views/headmin/forms/_datetime.html.erb +8 -8
- data/app/views/headmin/forms/_datetime_range.html.erb +3 -3
- data/app/views/headmin/forms/_email.html.erb +9 -9
- data/app/views/headmin/forms/_file.html.erb +12 -12
- data/app/views/headmin/forms/_flatpickr.html.erb +2 -2
- data/app/views/headmin/forms/_flatpickr_range.html.erb +8 -8
- data/app/views/headmin/forms/_hidden.html.erb +1 -1
- data/app/views/headmin/forms/_hint.html.erb +7 -2
- data/app/views/headmin/forms/_label.html.erb +1 -1
- data/app/views/headmin/forms/_media.html.erb +58 -0
- data/app/views/headmin/forms/_number.html.erb +8 -8
- data/app/views/headmin/forms/_password.html.erb +7 -7
- data/app/views/headmin/forms/_redactorx.html.erb +2 -2
- data/app/views/headmin/forms/_repeater.html.erb +12 -12
- data/app/views/headmin/forms/_search.html.erb +9 -9
- data/app/views/headmin/forms/_select.html.erb +8 -8
- data/app/views/headmin/forms/_switch.html.erb +2 -2
- data/app/views/headmin/forms/_text.html.erb +9 -9
- data/app/views/headmin/forms/_textarea.html.erb +7 -7
- data/app/views/headmin/forms/_url.html.erb +9 -9
- data/app/views/headmin/forms/_validation.html.erb +1 -1
- data/app/views/headmin/forms/_wysiwyg.html.erb +2 -2
- data/app/views/headmin/forms/fields/_base.html.erb +2 -2
- data/app/views/headmin/forms/fields/_file.html.erb +3 -3
- data/app/views/headmin/forms/fields/_files.html.erb +3 -3
- data/app/views/headmin/forms/fields/_group.html.erb +7 -7
- data/app/views/headmin/forms/fields/_list.html.erb +5 -5
- data/app/views/headmin/forms/fields/_text.html.erb +3 -3
- data/app/views/headmin/forms/media/_item.html.erb +32 -0
- data/app/views/headmin/forms/media/_validation.html.erb +10 -0
- data/app/views/headmin/forms/repeater/_row.html.erb +12 -11
- data/app/views/headmin/layout/_main.html.erb +3 -1
- data/app/views/headmin/layout/_remote_modal.html.erb +1 -0
- data/app/views/headmin/layout/_sidebar.html.erb +1 -1
- data/app/views/headmin/media/_item.html.erb +17 -0
- data/app/views/headmin/media/_media_item_modal.html.erb +51 -0
- data/app/views/headmin/media/_modal.html.erb +35 -0
- data/app/views/headmin/media/create.turbo_stream.erb +5 -0
- data/app/views/headmin/media/index.html.erb +3 -0
- data/app/views/headmin/media/show.html.erb +9 -0
- data/app/views/headmin/media/update.turbo_stream.erb +3 -0
- data/app/views/headmin/nav/_dropdown.html.erb +3 -3
- data/app/views/headmin/nav/_item.html.erb +2 -2
- data/app/views/headmin/nav/item/_devise.html.erb +6 -6
- data/app/views/headmin/nav/item/_locale.html.erb +4 -4
- data/app/views/headmin/table/_actions.html.erb +2 -2
- data/app/views/headmin/table/actions/_action.html.erb +3 -3
- data/app/views/headmin/table/actions/_delete.html.erb +2 -2
- data/app/views/headmin/table/actions/_export.html.erb +2 -2
- data/app/views/headmin/table/body/_image.html.erb +18 -0
- data/app/views/headmin/table/body/_row.html.erb +3 -3
- data/app/views/headmin/table/foot/_cell.html.erb +1 -1
- data/app/views/headmin/views/devise/confirmations/_new.html.erb +3 -3
- data/app/views/headmin/views/devise/passwords/_edit.html.erb +4 -4
- data/app/views/headmin/views/devise/passwords/_new.html.erb +3 -3
- data/app/views/headmin/views/devise/registrations/_edit.html.erb +5 -5
- data/app/views/headmin/views/devise/registrations/_new.html.erb +5 -5
- data/app/views/headmin/views/devise/sessions/_new.html.erb +4 -4
- data/app/views/headmin/views/devise/unlocks/_new.html.erb +3 -3
- data/config/locales/devise/nl.yml +1 -1
- data/config/locales/headmin/forms/en.yml +8 -0
- data/config/locales/headmin/forms/nl.yml +8 -0
- data/config/locales/headmin/media/en.yml +23 -0
- data/config/locales/headmin/media/nl.yml +22 -0
- data/config/locales/headmin/table/en.yml +2 -0
- data/config/locales/headmin/table/nl.yml +2 -0
- data/config/routes.rb +10 -0
- data/lib/generators/templates/views/auth/confirmations/new.html.erb +1 -1
- data/lib/generators/templates/views/auth/mailer/confirmation_instructions.html.erb +1 -1
- data/lib/generators/templates/views/auth/mailer/email_changed.html.erb +1 -1
- data/lib/generators/templates/views/auth/mailer/password_change.html.erb +1 -1
- data/lib/generators/templates/views/auth/mailer/reset_password_instructions.html.erb +1 -1
- data/lib/generators/templates/views/auth/mailer/unlock_instructions.html.erb +1 -1
- data/lib/generators/templates/views/auth/passwords/edit.html.erb +1 -1
- data/lib/generators/templates/views/auth/passwords/new.html.erb +1 -1
- data/lib/generators/templates/views/auth/registrations/edit.html.erb +1 -1
- data/lib/generators/templates/views/auth/registrations/new.html.erb +1 -1
- data/lib/generators/templates/views/auth/sessions/new.html.erb +1 -1
- data/lib/generators/templates/views/auth/unlocks/new.html.erb +1 -1
- data/lib/generators/templates/views/layouts/auth.html.erb +1 -1
- data/lib/headmin/version.rb +1 -1
- metadata +27 -3
- data/.lock-487e157d270f3062a98b7b2a012753708-1272821827 +0 -0
@@ -10093,6 +10093,260 @@ var hello_controller_default = class extends Controller {
|
|
10093
10093
|
}
|
10094
10094
|
};
|
10095
10095
|
|
10096
|
+
// app/assets/javascripts/headmin/controllers/media_controller.js
|
10097
|
+
var media_controller_default = class extends Controller {
|
10098
|
+
static get targets() {
|
10099
|
+
return ["item", "template", "thumbnails", "modalButton", "placeholder", "validationInput", "count", "editButton"];
|
10100
|
+
}
|
10101
|
+
connect() {
|
10102
|
+
document.addEventListener("mediaSelectionSubmitted", (event) => {
|
10103
|
+
if (event.detail.name === this.element.dataset.name) {
|
10104
|
+
this.selectItems(event.detail.items);
|
10105
|
+
}
|
10106
|
+
});
|
10107
|
+
if (this.hasSorting()) {
|
10108
|
+
this.initSortable();
|
10109
|
+
}
|
10110
|
+
this.validate();
|
10111
|
+
}
|
10112
|
+
destroy(event) {
|
10113
|
+
const item = event.currentTarget.closest("[data-media-target='item']");
|
10114
|
+
this.destroyItem(item);
|
10115
|
+
}
|
10116
|
+
syncIds() {
|
10117
|
+
const ids = this.activeIds();
|
10118
|
+
this.modalButtonTargets.forEach((button) => {
|
10119
|
+
const url = new URL(button.getAttribute("href"));
|
10120
|
+
url.searchParams.delete("ids[]");
|
10121
|
+
ids.forEach((id) => {
|
10122
|
+
url.searchParams.append("ids[]", id);
|
10123
|
+
});
|
10124
|
+
button.setAttribute("href", url.toString());
|
10125
|
+
});
|
10126
|
+
}
|
10127
|
+
initSortable() {
|
10128
|
+
sortable_esm_default.create(this.thumbnailsTarget, {
|
10129
|
+
handle: ".media-drag-sort-handle",
|
10130
|
+
onEnd: (event) => {
|
10131
|
+
this.resetPositions();
|
10132
|
+
}
|
10133
|
+
});
|
10134
|
+
}
|
10135
|
+
hasSorting() {
|
10136
|
+
return this.element.dataset.sort === "true";
|
10137
|
+
}
|
10138
|
+
destroyItem(item) {
|
10139
|
+
this.removeItem(item);
|
10140
|
+
this.postProcess();
|
10141
|
+
}
|
10142
|
+
selectItems(items) {
|
10143
|
+
this.removeAllItems();
|
10144
|
+
this.addItems(items);
|
10145
|
+
this.postProcess();
|
10146
|
+
}
|
10147
|
+
postProcess() {
|
10148
|
+
this.resetPositions();
|
10149
|
+
this.syncIds();
|
10150
|
+
this.togglePlaceholder();
|
10151
|
+
this.validate();
|
10152
|
+
}
|
10153
|
+
validate() {
|
10154
|
+
this.clearValidation();
|
10155
|
+
if (this.element.dataset.required === "0")
|
10156
|
+
return;
|
10157
|
+
this.validateMinimum();
|
10158
|
+
this.validateMaximum();
|
10159
|
+
}
|
10160
|
+
clearValidation() {
|
10161
|
+
this.validationInputTarget.setCustomValidity("");
|
10162
|
+
}
|
10163
|
+
validateMinimum() {
|
10164
|
+
const count = this.activeItems().length;
|
10165
|
+
if (count < this.minActiveItems()) {
|
10166
|
+
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.minMessage);
|
10167
|
+
}
|
10168
|
+
}
|
10169
|
+
validateMaximum() {
|
10170
|
+
const count = this.activeItems().length;
|
10171
|
+
if (count > this.maxActiveItems()) {
|
10172
|
+
this.validationInputTarget.setCustomValidity(this.validationInputTarget.dataset.maxMessage);
|
10173
|
+
}
|
10174
|
+
}
|
10175
|
+
minActiveItems() {
|
10176
|
+
return parseInt(this.element.dataset.min, 10) || 0;
|
10177
|
+
}
|
10178
|
+
maxActiveItems() {
|
10179
|
+
return parseInt(this.element.dataset.max, 10) || Infinity;
|
10180
|
+
}
|
10181
|
+
resetPositions() {
|
10182
|
+
this.activeItems().forEach((item, index2) => {
|
10183
|
+
const positionInput = item.querySelector("input[name*='position']");
|
10184
|
+
if (positionInput) {
|
10185
|
+
positionInput.value = index2;
|
10186
|
+
}
|
10187
|
+
});
|
10188
|
+
}
|
10189
|
+
addItems(items) {
|
10190
|
+
items.forEach((item) => this.addItem(item));
|
10191
|
+
}
|
10192
|
+
addItem(item) {
|
10193
|
+
const currentItem = this.itemByBlobId(item.blobId);
|
10194
|
+
if (currentItem) {
|
10195
|
+
this.enableItem(currentItem);
|
10196
|
+
} else {
|
10197
|
+
this.createItem(item);
|
10198
|
+
}
|
10199
|
+
}
|
10200
|
+
togglePlaceholder() {
|
10201
|
+
if (this.activeItems().length > 0) {
|
10202
|
+
this.hidePlaceholder();
|
10203
|
+
} else {
|
10204
|
+
this.showPlaceholder();
|
10205
|
+
}
|
10206
|
+
}
|
10207
|
+
showPlaceholder() {
|
10208
|
+
this.placeholderTarget.classList.remove("d-none");
|
10209
|
+
}
|
10210
|
+
hidePlaceholder() {
|
10211
|
+
this.placeholderTarget.classList.add("d-none");
|
10212
|
+
}
|
10213
|
+
enableItem(item) {
|
10214
|
+
item.querySelector(`input[name*='_destroy']`).value = false;
|
10215
|
+
item.classList.remove("d-none");
|
10216
|
+
}
|
10217
|
+
createItem(item) {
|
10218
|
+
const template = this.templateTarget;
|
10219
|
+
const html = this.randomizeIds(template);
|
10220
|
+
this.thumbnailsTarget.insertAdjacentHTML("beforeend", html);
|
10221
|
+
const newItem = this.itemTargets.pop();
|
10222
|
+
newItem.querySelector(`input[name*="[blob_id]"]`).value = item.blobId;
|
10223
|
+
newItem.querySelector(`input[name*="[_destroy]"]`).value = false;
|
10224
|
+
const editButton = newItem.querySelector(`[data-media-target="editButton"]`);
|
10225
|
+
editButton.setAttribute("href", editButton.getAttribute("href").replace("$1", item.blobId));
|
10226
|
+
const oldThumbnail = newItem.querySelector(".h-thumbnail");
|
10227
|
+
const newThumbnail = item.thumbnail.cloneNode(true);
|
10228
|
+
oldThumbnail.parentNode.replaceChild(newThumbnail, oldThumbnail);
|
10229
|
+
}
|
10230
|
+
randomizeIds(template) {
|
10231
|
+
const regex = new RegExp(template.dataset.templateIdRegex, "g");
|
10232
|
+
const randomNumber = Math.floor(1e8 + Math.random() * 9e8);
|
10233
|
+
return template.innerHTML.replace(regex, randomNumber);
|
10234
|
+
}
|
10235
|
+
removeAllItems() {
|
10236
|
+
this.removeItems(this.itemTargets);
|
10237
|
+
}
|
10238
|
+
removeItems(items) {
|
10239
|
+
items.forEach((item) => {
|
10240
|
+
this.removeItem(item);
|
10241
|
+
});
|
10242
|
+
}
|
10243
|
+
removeItem(item) {
|
10244
|
+
item.querySelector(`input[name*='_destroy']`).value = 1;
|
10245
|
+
item.classList.add("d-none");
|
10246
|
+
this.resetPositions();
|
10247
|
+
this.syncIds();
|
10248
|
+
this.togglePlaceholder();
|
10249
|
+
}
|
10250
|
+
itemByBlobId(blobId) {
|
10251
|
+
return this.itemTargets.find((item) => {
|
10252
|
+
return item.querySelector(`input[name*='blob_id']`).value === blobId;
|
10253
|
+
});
|
10254
|
+
}
|
10255
|
+
activeItems() {
|
10256
|
+
return this.itemTargets.filter((item) => {
|
10257
|
+
return item.querySelector(`input[name$='[_destroy]']`).value === "false";
|
10258
|
+
});
|
10259
|
+
}
|
10260
|
+
activeIds() {
|
10261
|
+
return this.activeItems().map((item) => {
|
10262
|
+
return item.querySelector(`input[name$='[blob_id]']`).value;
|
10263
|
+
});
|
10264
|
+
}
|
10265
|
+
};
|
10266
|
+
|
10267
|
+
// app/assets/javascripts/headmin/controllers/media_modal_controller.js
|
10268
|
+
var media_modal_controller_default = class extends Controller {
|
10269
|
+
static get targets() {
|
10270
|
+
return ["idCheckbox", "item", "form", "selectButton", "placeholder", "count"];
|
10271
|
+
}
|
10272
|
+
connect() {
|
10273
|
+
this.validate();
|
10274
|
+
this.updateCount();
|
10275
|
+
}
|
10276
|
+
select() {
|
10277
|
+
this.dispatchSelectionEvent();
|
10278
|
+
}
|
10279
|
+
submitForm() {
|
10280
|
+
this.hidePlaceholder();
|
10281
|
+
this.triggerFormSubmission();
|
10282
|
+
}
|
10283
|
+
inputChange() {
|
10284
|
+
this.handleInputChange();
|
10285
|
+
this.updateCount();
|
10286
|
+
}
|
10287
|
+
hidePlaceholder() {
|
10288
|
+
this.placeholderTarget.classList.add("d-none");
|
10289
|
+
}
|
10290
|
+
handleInputChange() {
|
10291
|
+
this.validate();
|
10292
|
+
}
|
10293
|
+
dispatchSelectionEvent() {
|
10294
|
+
document.dispatchEvent(new CustomEvent("mediaSelectionSubmitted", {
|
10295
|
+
detail: {
|
10296
|
+
name: this.element.dataset.name,
|
10297
|
+
items: this.renderItemsForEvent(this.selectedItems())
|
10298
|
+
}
|
10299
|
+
}));
|
10300
|
+
}
|
10301
|
+
triggerFormSubmission() {
|
10302
|
+
this.formTarget.requestSubmit();
|
10303
|
+
}
|
10304
|
+
renderItemsForEvent(items) {
|
10305
|
+
return items.map((item) => this.renderItemForEvent(item));
|
10306
|
+
}
|
10307
|
+
renderItemForEvent(item) {
|
10308
|
+
return {
|
10309
|
+
blobId: item.querySelector('input[type="checkbox"]').value,
|
10310
|
+
thumbnail: item.querySelector(".h-thumbnail")
|
10311
|
+
};
|
10312
|
+
}
|
10313
|
+
selectedItems() {
|
10314
|
+
return this.itemTargets.filter((item) => {
|
10315
|
+
const checkbox = item.querySelector('input[type="checkbox"]');
|
10316
|
+
return checkbox.checked;
|
10317
|
+
});
|
10318
|
+
}
|
10319
|
+
selectedItemsCount() {
|
10320
|
+
return this.selectedItems().length;
|
10321
|
+
}
|
10322
|
+
minSelectedItems() {
|
10323
|
+
return parseInt(this.element.dataset.min, 10) || 0;
|
10324
|
+
}
|
10325
|
+
maxSelectedItems() {
|
10326
|
+
return parseInt(this.element.dataset.max, 10) || Infinity;
|
10327
|
+
}
|
10328
|
+
validate() {
|
10329
|
+
if (this.isValid()) {
|
10330
|
+
this.enableSelectButton();
|
10331
|
+
} else {
|
10332
|
+
this.disableSelectButton();
|
10333
|
+
}
|
10334
|
+
}
|
10335
|
+
enableSelectButton() {
|
10336
|
+
this.selectButtonTarget.removeAttribute("disabled");
|
10337
|
+
}
|
10338
|
+
disableSelectButton() {
|
10339
|
+
this.selectButtonTarget.setAttribute("disabled", "");
|
10340
|
+
}
|
10341
|
+
isValid() {
|
10342
|
+
const count = this.selectedItemsCount();
|
10343
|
+
return count >= this.minSelectedItems() && count <= this.maxSelectedItems();
|
10344
|
+
}
|
10345
|
+
updateCount() {
|
10346
|
+
this.countTarget.innerHTML = this.idCheckboxTargets.filter((checkbox) => checkbox.checked).length;
|
10347
|
+
}
|
10348
|
+
};
|
10349
|
+
|
10096
10350
|
// node_modules/@popperjs/core/lib/index.js
|
10097
10351
|
var lib_exports = {};
|
10098
10352
|
__export(lib_exports, {
|
@@ -15236,6 +15490,14 @@ var redactorx_controller_default = class extends Controller {
|
|
15236
15490
|
}
|
15237
15491
|
};
|
15238
15492
|
|
15493
|
+
// app/assets/javascripts/headmin/controllers/remote_modal_controller.js
|
15494
|
+
var remote_modal_controller_default = class extends Controller {
|
15495
|
+
connect() {
|
15496
|
+
this.modal = new Modal(this.element);
|
15497
|
+
this.modal.show();
|
15498
|
+
}
|
15499
|
+
};
|
15500
|
+
|
15239
15501
|
// app/assets/javascripts/headmin/controllers/repeater_controller.js
|
15240
15502
|
var repeater_controller_default = class extends Controller {
|
15241
15503
|
static get values() {
|
@@ -15580,6 +15842,34 @@ var table_controller_default = class extends Controller {
|
|
15580
15842
|
}
|
15581
15843
|
};
|
15582
15844
|
|
15845
|
+
// app/assets/javascripts/headmin/controllers/textarea_controller.js
|
15846
|
+
var textarea_controller_default = class extends Controller {
|
15847
|
+
static get targets() {
|
15848
|
+
return ["textarea", "count"];
|
15849
|
+
}
|
15850
|
+
connect() {
|
15851
|
+
this.update();
|
15852
|
+
}
|
15853
|
+
update() {
|
15854
|
+
this.resize();
|
15855
|
+
this.updateCount();
|
15856
|
+
}
|
15857
|
+
resize() {
|
15858
|
+
this.textareaTarget.style.height = "auto";
|
15859
|
+
this.textareaTarget.setAttribute("style", "height:" + this.textareaTarget.scrollHeight + "px;overflow-y:hidden;");
|
15860
|
+
}
|
15861
|
+
updateCount() {
|
15862
|
+
if (this.textareaTarget.getAttribute("maxlength")) {
|
15863
|
+
this.updateCountLength();
|
15864
|
+
}
|
15865
|
+
}
|
15866
|
+
updateCountLength() {
|
15867
|
+
const current_length = this.textareaTarget.value.length;
|
15868
|
+
const maximum_length = this.textareaTarget.getAttribute("maxlength");
|
15869
|
+
this.countTarget.textContent = `${current_length}/${maximum_length}`;
|
15870
|
+
}
|
15871
|
+
};
|
15872
|
+
|
15583
15873
|
// app/assets/javascripts/headmin/index.js
|
15584
15874
|
var Headmin = class {
|
15585
15875
|
static start() {
|
@@ -15594,13 +15884,17 @@ var Headmin = class {
|
|
15594
15884
|
Stimulus.register("filters", filters_controller_default);
|
15595
15885
|
Stimulus.register("flatpickr", flatpickr_controller_default);
|
15596
15886
|
Stimulus.register("hello", hello_controller_default);
|
15887
|
+
Stimulus.register("media", media_controller_default);
|
15888
|
+
Stimulus.register("media-modal", media_modal_controller_default);
|
15597
15889
|
Stimulus.register("notification", notification_controller_default);
|
15598
15890
|
Stimulus.register("popup", popup_controller_default);
|
15599
15891
|
Stimulus.register("redactorx", redactorx_controller_default);
|
15892
|
+
Stimulus.register("remote-modal", remote_modal_controller_default);
|
15600
15893
|
Stimulus.register("repeater", repeater_controller_default);
|
15601
15894
|
Stimulus.register("select", select_controller_default);
|
15602
15895
|
Stimulus.register("table", table_controller_default);
|
15603
15896
|
Stimulus.register("table-actions", table_actions_controller_default);
|
15897
|
+
Stimulus.register("textarea", textarea_controller_default);
|
15604
15898
|
}
|
15605
15899
|
};
|
15606
15900
|
export {
|
@@ -17,26 +17,41 @@
|
|
17
17
|
display: flex;
|
18
18
|
flex-wrap: wrap;
|
19
19
|
gap: map-get($spacers, 2);
|
20
|
+
|
21
|
+
a, a:link, a:hover {
|
22
|
+
color: inherit;
|
23
|
+
text-decoration: inherit;
|
24
|
+
}
|
20
25
|
}
|
21
26
|
|
22
27
|
.h-form-file-thumbnail {
|
23
28
|
position: relative;
|
24
29
|
pointer-events: initial !important;
|
25
30
|
display: flex;
|
31
|
+
|
32
|
+
&:hover {
|
33
|
+
.h-form-file-thumbnail-actions {
|
34
|
+
display: block;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
.h-form-file-thumbnail-actions {
|
40
|
+
display: none;
|
26
41
|
}
|
27
42
|
|
28
43
|
.h-form-file-thumbnail-remove {
|
29
44
|
position: absolute;
|
30
|
-
top:
|
31
|
-
right:
|
45
|
+
top: 5px;
|
46
|
+
right: 5px;
|
32
47
|
background: $danger;
|
33
|
-
width:
|
34
|
-
height:
|
48
|
+
width: 25px;
|
49
|
+
height: 25px;
|
35
50
|
display: flex;
|
36
51
|
align-items: center;
|
37
52
|
justify-content: center;
|
38
53
|
color: white;
|
39
|
-
border-radius: $border-radius;
|
54
|
+
border-radius: $border-radius-pill;
|
40
55
|
z-index: 3;
|
41
56
|
cursor: pointer;
|
42
57
|
|
@@ -44,3 +59,23 @@
|
|
44
59
|
background: tint-color($danger, $btn-hover-bg-tint-amount)
|
45
60
|
}
|
46
61
|
}
|
62
|
+
|
63
|
+
.h-form-file-thumbnail-edit {
|
64
|
+
position: absolute;
|
65
|
+
top: 5px;
|
66
|
+
right: 35px;
|
67
|
+
background-color: rgba(0, 0, 0, 0.7);
|
68
|
+
width: 25px;
|
69
|
+
height: 25px;
|
70
|
+
display: flex;
|
71
|
+
align-items: center;
|
72
|
+
justify-content: center;
|
73
|
+
border-radius: $border-radius-pill;
|
74
|
+
z-index: 3;
|
75
|
+
cursor: pointer;
|
76
|
+
color: white !important;
|
77
|
+
|
78
|
+
&:hover {
|
79
|
+
background-color: rgba(0, 0, 0, 1);
|
80
|
+
}
|
81
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "media/index";
|
@@ -1,7 +1,7 @@
|
|
1
1
|
@charset "UTF-8";
|
2
2
|
@import "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css";
|
3
3
|
|
4
|
-
/* sass-plugin-0:/
|
4
|
+
/* sass-plugin-0:/usr/local/var/www/headmin/src/scss/headmin.scss */
|
5
5
|
:root {
|
6
6
|
--bs-blue: #0d6efd;
|
7
7
|
--bs-indigo: #6610f2;
|
@@ -12971,6 +12971,9 @@ span.flatpickr-weekday {
|
|
12971
12971
|
content: " *";
|
12972
12972
|
color: #dc3545;
|
12973
12973
|
}
|
12974
|
+
.card-body .mb-3:last-child {
|
12975
|
+
margin-bottom: 0 !important;
|
12976
|
+
}
|
12974
12977
|
.h-autocomplete {
|
12975
12978
|
position: absolute;
|
12976
12979
|
top: calc(100% + 2px);
|
@@ -13019,29 +13022,69 @@ span.flatpickr-weekday {
|
|
13019
13022
|
flex-wrap: wrap;
|
13020
13023
|
gap: 0.5rem;
|
13021
13024
|
}
|
13025
|
+
.h-form-file-thumbnails a,
|
13026
|
+
.h-form-file-thumbnails a:link,
|
13027
|
+
.h-form-file-thumbnails a:hover {
|
13028
|
+
color: inherit;
|
13029
|
+
text-decoration: inherit;
|
13030
|
+
}
|
13022
13031
|
.h-form-file-thumbnail {
|
13023
13032
|
position: relative;
|
13024
13033
|
pointer-events: initial !important;
|
13025
13034
|
display: flex;
|
13026
13035
|
}
|
13036
|
+
.h-form-file-thumbnail:hover .h-form-file-thumbnail-actions {
|
13037
|
+
display: block;
|
13038
|
+
}
|
13039
|
+
.h-form-file-thumbnail-actions {
|
13040
|
+
display: none;
|
13041
|
+
}
|
13027
13042
|
.h-form-file-thumbnail-remove {
|
13028
13043
|
position: absolute;
|
13029
|
-
top:
|
13030
|
-
right:
|
13044
|
+
top: 5px;
|
13045
|
+
right: 5px;
|
13031
13046
|
background: #dc3545;
|
13032
|
-
width:
|
13033
|
-
height:
|
13047
|
+
width: 25px;
|
13048
|
+
height: 25px;
|
13034
13049
|
display: flex;
|
13035
13050
|
align-items: center;
|
13036
13051
|
justify-content: center;
|
13037
13052
|
color: white;
|
13038
|
-
border-radius:
|
13053
|
+
border-radius: 50rem;
|
13039
13054
|
z-index: 3;
|
13040
13055
|
cursor: pointer;
|
13041
13056
|
}
|
13042
13057
|
.h-form-file-thumbnail-remove:hover {
|
13043
13058
|
background: #e15361;
|
13044
13059
|
}
|
13060
|
+
.h-form-file-thumbnail-edit {
|
13061
|
+
position: absolute;
|
13062
|
+
top: 5px;
|
13063
|
+
right: 35px;
|
13064
|
+
background-color: rgba(0, 0, 0, 0.7);
|
13065
|
+
width: 25px;
|
13066
|
+
height: 25px;
|
13067
|
+
display: flex;
|
13068
|
+
align-items: center;
|
13069
|
+
justify-content: center;
|
13070
|
+
border-radius: 50rem;
|
13071
|
+
z-index: 3;
|
13072
|
+
cursor: pointer;
|
13073
|
+
color: white !important;
|
13074
|
+
}
|
13075
|
+
.h-form-file-thumbnail-edit:hover {
|
13076
|
+
background-color: black;
|
13077
|
+
}
|
13078
|
+
.h-form-media-validation {
|
13079
|
+
opacity: 0;
|
13080
|
+
width: 100px;
|
13081
|
+
height: 0;
|
13082
|
+
padding: 0;
|
13083
|
+
margin: 0;
|
13084
|
+
position: absolute;
|
13085
|
+
bottom: 0;
|
13086
|
+
left: 0;
|
13087
|
+
}
|
13045
13088
|
.repeater {
|
13046
13089
|
position: relative;
|
13047
13090
|
}
|
@@ -13057,6 +13100,9 @@ span.flatpickr-weekday {
|
|
13057
13100
|
.repeater-row:hover .repeater-row-handle {
|
13058
13101
|
visibility: visible;
|
13059
13102
|
}
|
13103
|
+
.repeater-row .mb-3:last-of-type {
|
13104
|
+
margin-bottom: 0 !important;
|
13105
|
+
}
|
13060
13106
|
.repeater-row-remove {
|
13061
13107
|
position: absolute;
|
13062
13108
|
top: calc(50% - 17px);
|
@@ -13138,7 +13184,6 @@ mark,
|
|
13138
13184
|
.nav-brand svg,
|
13139
13185
|
.nav-brand img {
|
13140
13186
|
max-width: 100%;
|
13141
|
-
height: 30px;
|
13142
13187
|
}
|
13143
13188
|
.nav-brand svg {
|
13144
13189
|
fill: #ffffff;
|
@@ -13204,6 +13249,12 @@ body.empty {
|
|
13204
13249
|
width: 300px;
|
13205
13250
|
max-width: 100%;
|
13206
13251
|
}
|
13252
|
+
.h-table-cell-image {
|
13253
|
+
padding: 0.4rem 1rem !important;
|
13254
|
+
}
|
13255
|
+
.h-table-cell-image img {
|
13256
|
+
border-radius: 3px;
|
13257
|
+
}
|
13207
13258
|
.h-table-cell-color {
|
13208
13259
|
width: 22px;
|
13209
13260
|
height: 22px;
|
@@ -13390,6 +13441,12 @@ body.empty {
|
|
13390
13441
|
z-index: 9;
|
13391
13442
|
display: none;
|
13392
13443
|
}
|
13444
|
+
.media-modal .h-thumbnail {
|
13445
|
+
cursor: pointer;
|
13446
|
+
}
|
13447
|
+
.media-modal input[type=checkbox]:checked + label .h-thumbnail {
|
13448
|
+
background-color: #0d6efd;
|
13449
|
+
}
|
13393
13450
|
.h-popup {
|
13394
13451
|
padding: 10px;
|
13395
13452
|
background: #ffffff;
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class Headmin::MediaController < HeadminController
|
2
|
+
layout false
|
3
|
+
|
4
|
+
def index
|
5
|
+
@blobs =
|
6
|
+
ActiveStorage::Blob
|
7
|
+
.left_outer_joins(:attachments)
|
8
|
+
.where.not(active_storage_attachments: {record_type: "ActiveStorage::VariantRecord"}) # Not a variant
|
9
|
+
.or(ActiveStorage::Blob.where(active_storage_attachments: {id: nil})) # Or an orphan
|
10
|
+
.order(created_at: :desc)
|
11
|
+
.group(:id)
|
12
|
+
.all
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
blobs = []
|
17
|
+
media_params[:files].reject { |c| c.blank? }.each do |file|
|
18
|
+
blobs << ActiveStorage::Blob.create_and_upload!(io: file, filename: file.original_filename)
|
19
|
+
end
|
20
|
+
|
21
|
+
respond_to do |format|
|
22
|
+
format.turbo_stream {
|
23
|
+
@blobs = blobs
|
24
|
+
}
|
25
|
+
format.html { redirect_to root_path }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def show
|
30
|
+
@blob = ActiveStorage::Blob.find(params[:id])
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
@blob = ActiveStorage::Blob.find(params[:id])
|
35
|
+
media_item_params[:filename] = media_item_params[:filename] + "." + @blob.filename.to_s.rpartition(".").last
|
36
|
+
if @blob.update(media_item_params)
|
37
|
+
flash.now[:notice] = t("admin.flash.updated", name: @blob.filename)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def media_params
|
44
|
+
params.permit(
|
45
|
+
files: []
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
def media_item_params
|
50
|
+
params.require(:blob).permit!
|
51
|
+
end
|
52
|
+
end
|