Skip to content

Commit 02dc315

Browse files
committed
Converted image-manager to be component/HTML based
Instead of vue based.
1 parent b6aa232 commit 02dc315

File tree

23 files changed

+482
-391
lines changed

23 files changed

+482
-391
lines changed

app/Http/Controllers/Images/DrawioImageController.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public function list(Request $request)
3030
$parentTypeFilter = $request->get('filter_type', null);
3131

3232
$imgData = $this->imageRepo->getEntityFiltered('drawio', $parentTypeFilter, $page, 24, $uploadedToFilter, $searchTerm);
33-
return response()->json($imgData);
33+
return view('components.image-manager-list', [
34+
'images' => $imgData['images'],
35+
'hasMore' => $imgData['has_more'],
36+
]);
3437
}
3538

3639
/**
@@ -72,6 +75,7 @@ public function getAsBase64($id)
7275
if ($imageData === null) {
7376
return $this->jsonError("Image data could not be found");
7477
}
78+
7579
return response()->json([
7680
'content' => base64_encode($imageData)
7781
]);

app/Http/Controllers/Images/GalleryImageController.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
use BookStack\Uploads\ImageRepo;
77
use Illuminate\Http\Request;
88
use BookStack\Http\Controllers\Controller;
9+
use Illuminate\Validation\ValidationException;
910

1011
class GalleryImageController extends Controller
1112
{
1213
protected $imageRepo;
1314

1415
/**
1516
* GalleryImageController constructor.
16-
* @param ImageRepo $imageRepo
1717
*/
1818
public function __construct(ImageRepo $imageRepo)
1919
{
@@ -24,8 +24,6 @@ public function __construct(ImageRepo $imageRepo)
2424
/**
2525
* Get a list of gallery images, in a list.
2626
* Can be paged and filtered by entity.
27-
* @param Request $request
28-
* @return \Illuminate\Http\JsonResponse
2927
*/
3028
public function list(Request $request)
3129
{
@@ -35,14 +33,15 @@ public function list(Request $request)
3533
$parentTypeFilter = $request->get('filter_type', null);
3634

3735
$imgData = $this->imageRepo->getEntityFiltered('gallery', $parentTypeFilter, $page, 24, $uploadedToFilter, $searchTerm);
38-
return response()->json($imgData);
36+
return view('components.image-manager-list', [
37+
'images' => $imgData['images'],
38+
'hasMore' => $imgData['has_more'],
39+
]);
3940
}
4041

4142
/**
4243
* Store a new gallery image in the system.
43-
* @param Request $request
44-
* @return Illuminate\Http\JsonResponse
45-
* @throws \Exception
44+
* @throws ValidationException
4645
*/
4746
public function create(Request $request)
4847
{

app/Http/Controllers/Images/ImageController.php

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
use BookStack\Repos\PageRepo;
77
use BookStack\Uploads\Image;
88
use BookStack\Uploads\ImageRepo;
9+
use Exception;
910
use Illuminate\Filesystem\Filesystem as File;
11+
use Illuminate\Http\JsonResponse;
1012
use Illuminate\Http\Request;
13+
use Illuminate\Validation\ValidationException;
1114

1215
class ImageController extends Controller
1316
{
@@ -17,9 +20,6 @@ class ImageController extends Controller
1720

1821
/**
1922
* ImageController constructor.
20-
* @param Image $image
21-
* @param File $file
22-
* @param ImageRepo $imageRepo
2323
*/
2424
public function __construct(Image $image, File $file, ImageRepo $imageRepo)
2525
{
@@ -31,8 +31,6 @@ public function __construct(Image $image, File $file, ImageRepo $imageRepo)
3131

3232
/**
3333
* Provide an image file from storage.
34-
* @param string $path
35-
* @return mixed
3634
*/
3735
public function showImage(string $path)
3836
{
@@ -47,13 +45,10 @@ public function showImage(string $path)
4745

4846
/**
4947
* Update image details
50-
* @param Request $request
51-
* @param integer $id
52-
* @return \Illuminate\Http\JsonResponse
5348
* @throws ImageUploadException
54-
* @throws \Exception
49+
* @throws ValidationException
5550
*/
56-
public function update(Request $request, $id)
51+
public function update(Request $request, string $id)
5752
{
5853
$this->validate($request, [
5954
'name' => 'required|min:2|string'
@@ -64,47 +59,50 @@ public function update(Request $request, $id)
6459
$this->checkOwnablePermission('image-update', $image);
6560

6661
$image = $this->imageRepo->updateImageDetails($image, $request->all());
67-
return response()->json($image);
62+
63+
$this->imageRepo->loadThumbs($image);
64+
return view('components.image-manager-form', [
65+
'image' => $image,
66+
'dependantPages' => null,
67+
]);
6868
}
6969

7070
/**
71-
* Show the usage of an image on pages.
71+
* Get the form for editing the given image.
72+
* @throws Exception
7273
*/
73-
public function usage(int $id)
74+
public function edit(Request $request, string $id)
7475
{
7576
$image = $this->imageRepo->getById($id);
7677
$this->checkImagePermission($image);
7778

78-
$pages = Page::visible()->where('html', 'like', '%' . $image->url . '%')->get(['id', 'name', 'slug', 'book_id']);
79-
foreach ($pages as $page) {
80-
$page->url = $page->getUrl();
81-
$page->html = '';
82-
$page->text = '';
79+
if ($request->has('delete')) {
80+
$dependantPages = $this->imageRepo->getPagesUsingImage($image);
8381
}
84-
$result = count($pages) > 0 ? $pages : false;
8582

86-
return response()->json($result);
83+
$this->imageRepo->loadThumbs($image);
84+
return view('components.image-manager-form', [
85+
'image' => $image,
86+
'dependantPages' => $dependantPages ?? null,
87+
]);
8788
}
8889

8990
/**
9091
* Deletes an image and all thumbnail/image files
91-
* @param int $id
92-
* @return \Illuminate\Http\JsonResponse
93-
* @throws \Exception
92+
* @throws Exception
9493
*/
95-
public function destroy($id)
94+
public function destroy(string $id)
9695
{
9796
$image = $this->imageRepo->getById($id);
9897
$this->checkOwnablePermission('image-delete', $image);
9998
$this->checkImagePermission($image);
10099

101100
$this->imageRepo->destroyImage($image);
102-
return response()->json(trans('components.images_deleted'));
101+
return response('');
103102
}
104103

105104
/**
106105
* Check related page permission and ensure type is drawio or gallery.
107-
* @param Image $image
108106
*/
109107
protected function checkImagePermission(Image $image)
110108
{

app/Uploads/ImageRepo.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public function destroyByType(string $imageType)
185185
* Load thumbnails onto an image object.
186186
* @throws Exception
187187
*/
188-
protected function loadThumbs(Image $image)
188+
public function loadThumbs(Image $image)
189189
{
190190
$image->thumbs = [
191191
'gallery' => $this->getThumbnail($image, 150, 150, false),
@@ -219,4 +219,20 @@ public function getImageData(Image $image): ?string
219219
return null;
220220
}
221221
}
222+
223+
/**
224+
* Get the user visible pages using the given image.
225+
*/
226+
public function getPagesUsingImage(Image $image): array
227+
{
228+
$pages = Page::visible()
229+
->where('html', 'like', '%' . $image->url . '%')
230+
->get(['id', 'name', 'slug', 'book_id']);
231+
232+
foreach ($pages as $page) {
233+
$page->url = $page->getUrl();
234+
}
235+
236+
return $pages->all();
237+
}
222238
}

resources/js/components/ajax-form.js

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,76 @@ import {onEnterPress, onSelect} from "../services/dom";
55
* Will handle button clicks or input enter press events and submit
66
* the data over ajax. Will always expect a partial HTML view to be returned.
77
* Fires an 'ajax-form-success' event when submitted successfully.
8+
*
9+
* Will handle a real form if that's what the component is added to
10+
* otherwise will act as a fake form element.
11+
*
812
* @extends {Component}
913
*/
1014
class AjaxForm {
1115
setup() {
1216
this.container = this.$el;
17+
this.responseContainer = this.container;
1318
this.url = this.$opts.url;
1419
this.method = this.$opts.method || 'post';
1520
this.successMessage = this.$opts.successMessage;
1621
this.submitButtons = this.$manyRefs.submit || [];
1722

23+
if (this.$opts.responseContainer) {
24+
this.responseContainer = this.container.closest(this.$opts.responseContainer);
25+
}
26+
1827
this.setupListeners();
1928
}
2029

2130
setupListeners() {
31+
32+
if (this.container.tagName === 'FORM') {
33+
this.container.addEventListener('submit', this.submitRealForm.bind(this));
34+
return;
35+
}
36+
2237
onEnterPress(this.container, event => {
23-
this.submit();
38+
this.submitFakeForm();
2439
event.preventDefault();
2540
});
2641

27-
this.submitButtons.forEach(button => onSelect(button, this.submit.bind(this)));
42+
this.submitButtons.forEach(button => onSelect(button, this.submitFakeForm.bind(this)));
2843
}
2944

30-
async submit() {
45+
submitFakeForm() {
3146
const fd = new FormData();
3247
const inputs = this.container.querySelectorAll(`[name]`);
33-
console.log(inputs);
3448
for (const input of inputs) {
3549
fd.append(input.getAttribute('name'), input.value);
3650
}
51+
this.submit(fd);
52+
}
53+
54+
submitRealForm(event) {
55+
event.preventDefault();
56+
const fd = new FormData(this.container);
57+
this.submit(fd);
58+
}
59+
60+
async submit(formData) {
61+
this.responseContainer.style.opacity = '0.7';
62+
this.responseContainer.style.pointerEvents = 'none';
3763

38-
this.container.style.opacity = '0.7';
39-
this.container.style.pointerEvents = 'none';
4064
try {
41-
const resp = await window.$http[this.method.toLowerCase()](this.url, fd);
42-
this.container.innerHTML = resp.data;
43-
this.$emit('success', {formData: fd});
65+
const resp = await window.$http[this.method.toLowerCase()](this.url, formData);
66+
this.$emit('success', {formData});
67+
this.responseContainer.innerHTML = resp.data;
4468
if (this.successMessage) {
4569
window.$events.emit('success', this.successMessage);
4670
}
4771
} catch (err) {
48-
this.container.innerHTML = err.data;
72+
this.responseContainer.innerHTML = err.data;
4973
}
5074

51-
window.components.init(this.container);
52-
this.container.style.opacity = null;
53-
this.container.style.pointerEvents = null;
75+
window.components.init(this.responseContainer);
76+
this.responseContainer.style.opacity = null;
77+
this.responseContainer.style.pointerEvents = null;
5478
}
5579

5680
}

resources/js/components/dropzone.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ class Dropzone {
4343
}
4444

4545
onSuccess(file, data) {
46-
this.container.dispatchEvent(new Event('dropzone'))
4746
this.$emit('success', {file, data});
4847

4948
if (this.successMessage) {

0 commit comments

Comments
 (0)