From 5eb5a7bc065d669513a72f367916f8710b991808 Mon Sep 17 00:00:00 2001 From: F4ilji Date: Fri, 10 Apr 2026 10:51:42 +0500 Subject: [PATCH] changes --- .../Actions/Pages/ReorderPagesAction.php | 41 +++++++++++++ app/Observers/PageObserver.php | 5 ++ ..._081834_add_sort_column_to_pages_table.php | 28 +++++++++ .../ContentBuilder/blocks/ImageBlock.vue | 50 ++++++++++++---- .../ContentBuilder/blocks/ImagesBlock.vue | 59 ++++++++++++++----- .../pageBuilder/blocks/BasicImageSlider.vue | 8 +-- .../builder/pageBuilder/blocks/ImageBlock.vue | 22 +++---- 7 files changed, 174 insertions(+), 39 deletions(-) create mode 100644 app/Containers/Dashboard/Actions/Pages/ReorderPagesAction.php create mode 100644 database/migrations/2026_04_10_081834_add_sort_column_to_pages_table.php diff --git a/app/Containers/Dashboard/Actions/Pages/ReorderPagesAction.php b/app/Containers/Dashboard/Actions/Pages/ReorderPagesAction.php new file mode 100644 index 0000000..74dba4b --- /dev/null +++ b/app/Containers/Dashboard/Actions/Pages/ReorderPagesAction.php @@ -0,0 +1,41 @@ + $pageId) { + Page::where('id', $pageId) + ->where('sub_section_id', $subSectionId) + ->update(['sort' => $index + 1]); + } + + // Clear navigation cache since sort order changed + Cache::forget('navigation'); + + // Clear page data cache for all pages in this subsection + // so that section.pages relation is re-fetched with correct order + $pages = Page::where('sub_section_id', $subSectionId)->get(); + foreach ($pages as $page) { + $cacheKey = 'page_data_' . md5($page->path); + Cache::forget($cacheKey); + } + + return true; + }); + } +} diff --git a/app/Observers/PageObserver.php b/app/Observers/PageObserver.php index 37f966b..c9a49b2 100755 --- a/app/Observers/PageObserver.php +++ b/app/Observers/PageObserver.php @@ -29,6 +29,11 @@ class PageObserver public function updated(Page $page): void { $this->pageCacheService->clearAllCacheByModel(); + + // Clear navigation cache if sort order changed + if ($page->isDirty('sort')) { + Cache::forget('navigation'); + } } /** diff --git a/database/migrations/2026_04_10_081834_add_sort_column_to_pages_table.php b/database/migrations/2026_04_10_081834_add_sort_column_to_pages_table.php new file mode 100644 index 0000000..d1d0838 --- /dev/null +++ b/database/migrations/2026_04_10_081834_add_sort_column_to_pages_table.php @@ -0,0 +1,28 @@ +integer('sort')->default(0)->after('sub_section_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('pages', function (Blueprint $table) { + $table->dropColumn('sort'); + }); + } +}; diff --git a/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImageBlock.vue b/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImageBlock.vue index 34f0458..ca8fb15 100644 --- a/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImageBlock.vue +++ b/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImageBlock.vue @@ -6,7 +6,7 @@
- Preview + Preview
@@ -56,22 +58,50 @@ export default { required: true } }, - emits: ['update:modelValue'], + emits: ['update:modelValue', 'update'], + data() { + return { + uploading: false, + }; + }, methods: { update(field, value) { this.$emit('update:modelValue', { ...this.modelValue, [field]: value }); + this.$emit('update'); }, - handleFileUpload(event) { + async handleFileUpload(event) { const file = event.target.files[0]; - if (file) { - const reader = new FileReader(); - reader.onload = (e) => { - this.update('url', e.target.result); - }; - reader.readAsDataURL(file); + if (!file) return; + + this.uploading = true; + + try { + const formData = new FormData(); + formData.append('images[]', file); + + const response = await fetch(route('dashboard.posts.upload-images'), { + method: 'POST', + headers: { + 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, + 'Accept': 'application/json', + }, + body: formData, + }); + + const result = await response.json(); + + if (result.success && result.paths && result.paths.length > 0) { + this.update('url', result.paths[0]); + } + } catch (error) { + console.error('Image upload error:', error); + } finally { + this.uploading = false; + // Reset input so the same file can be selected again + event.target.value = ''; } } } diff --git a/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImagesBlock.vue b/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImagesBlock.vue index cff9b62..c2eceaa 100644 --- a/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImagesBlock.vue +++ b/resources/js/Pages/Dashboard/Components/ContentBuilder/blocks/ImagesBlock.vue @@ -10,7 +10,7 @@ :key="index" class="relative group" > - Preview + Preview
@@ -60,29 +62,58 @@ export default { required: true } }, - emits: ['update:modelValue'], + emits: ['update:modelValue', 'update'], + data() { + return { + uploading: false, + }; + }, methods: { update(field, value) { this.$emit('update:modelValue', { ...this.modelValue, [field]: value }); + this.$emit('update'); }, - handleFilesUpload(event) { + async handleFilesUpload(event) { const files = Array.from(event.target.files); + if (files.length === 0) return; + const remaining = 5 - this.modelValue.url.length; const toProcess = files.slice(0, remaining); + if (toProcess.length === 0) return; - let processed = 0; - toProcess.forEach((file) => { - const reader = new FileReader(); - reader.onload = (e) => { - const newUrls = [...this.modelValue.url, e.target.result]; + this.uploading = true; + + try { + const formData = new FormData(); + toProcess.forEach(file => { + formData.append('images[]', file); + }); + + const response = await fetch(route('dashboard.posts.upload-images'), { + method: 'POST', + headers: { + 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, + 'Accept': 'application/json', + }, + body: formData, + }); + + const result = await response.json(); + + if (result.success && result.paths) { + const newUrls = [...this.modelValue.url, ...result.paths]; this.update('url', newUrls); - processed++; - }; - reader.readAsDataURL(file); - }); + } + } catch (error) { + console.error('Images upload error:', error); + } finally { + this.uploading = false; + // Reset input so the same files can be selected again + event.target.value = ''; + } }, removeImage(index) { const newUrls = this.modelValue.url.filter((_, i) => i !== index); diff --git a/resources/js/componentss/shared/builder/pageBuilder/blocks/BasicImageSlider.vue b/resources/js/componentss/shared/builder/pageBuilder/blocks/BasicImageSlider.vue index 027cfef..8e981d2 100755 --- a/resources/js/componentss/shared/builder/pageBuilder/blocks/BasicImageSlider.vue +++ b/resources/js/componentss/shared/builder/pageBuilder/blocks/BasicImageSlider.vue @@ -1,5 +1,5 @@