feat(admin): rebuild release upload form with Livewire and CDN validation
Replace the server-rendered release upload form with a Livewire component, introducing an interactive admin release form that supports dynamic episode management, real‑time CDN path validation, and direct download file checks. Key changes: - New `AdminReleaseForm` Livewire component with dynamic episode fields, Tagify integration, and upload handling via Livewire's file uploads. - Added `CdnPathValidator` service to verify download and stream paths across all configured mirrors, caching results and capturing file sizes. - Extended `EpisodeService` and `GalleryService` to support array‑based data and temporary uploaded files from Livewire. - Persist validated download sizes and store the validation timestamp on the `downloads` table via a new migration; also add a unique constraint on `hentais.slug` to prevent duplicates. - Remove the old POST `/admin/release/upload` route and controller logic, along with the legacy `upload.js` script. - Add comprehensive feature and unit tests covering the new component and the CDN validation service.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import Tagify from '@yaireo/tagify';
|
||||
import '@yaireo/tagify/dist/tagify.css';
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
const Alpine = window.Alpine;
|
||||
|
||||
const dropdownOptions = {
|
||||
classname: "color-blue",
|
||||
enabled: 0,
|
||||
maxItems: 10,
|
||||
position: "text",
|
||||
closeOnSelect: false,
|
||||
highlightFirst: true
|
||||
};
|
||||
|
||||
Alpine.data('adminReleaseTags', () => ({
|
||||
tagify: null,
|
||||
|
||||
init() {
|
||||
const el = this.$refs.tags;
|
||||
|
||||
window.axios.get('/admin/tags').then((response) => {
|
||||
if (response.status != 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tagify = new Tagify(el, {
|
||||
whitelist: response.data.tags,
|
||||
dropdown: dropdownOptions
|
||||
});
|
||||
|
||||
this.tagify.on('change', () => {
|
||||
this.$wire.set('tags', this.tagify.value.map((t) => t.value));
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
Alpine.data('adminReleaseStudio', () => ({
|
||||
tagify: null,
|
||||
|
||||
init() {
|
||||
const el = this.$refs.studio;
|
||||
|
||||
window.axios.get('/admin/studios').then((response) => {
|
||||
if (response.status != 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tagify = new Tagify(el, {
|
||||
whitelist: response.data.studios,
|
||||
dropdown: dropdownOptions
|
||||
});
|
||||
|
||||
this.tagify.on('change', () => {
|
||||
const values = this.tagify.value.map((t) => t.value);
|
||||
this.$wire.set('studio', values.length ? values[values.length - 1] : '');
|
||||
});
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}));
|
||||
});
|
||||
Reference in New Issue
Block a user