Dan Brown

Added attachment creation from link/name

...@@ -71,8 +71,13 @@ abstract class Controller extends BaseController ...@@ -71,8 +71,13 @@ abstract class Controller extends BaseController
71 */ 71 */
72 protected function showPermissionError() 72 protected function showPermissionError()
73 { 73 {
74 - Session::flash('error', trans('errors.permission')); 74 + if (request()->wantsJson()) {
75 - $response = request()->wantsJson() ? response()->json(['error' => trans('errors.permissionJson')], 403) : redirect('/'); 75 + $response = response()->json(['error' => trans('errors.permissionJson')], 403);
76 + } else {
77 + $response = redirect('/');
78 + session()->flash('error', trans('errors.permission'));
79 + }
80 +
76 throw new HttpResponseException($response); 81 throw new HttpResponseException($response);
77 } 82 }
78 83
...@@ -83,7 +88,7 @@ abstract class Controller extends BaseController ...@@ -83,7 +88,7 @@ abstract class Controller extends BaseController
83 */ 88 */
84 protected function checkPermission($permissionName) 89 protected function checkPermission($permissionName)
85 { 90 {
86 - if (!$this->currentUser || !$this->currentUser->can($permissionName)) { 91 + if (!user() || !user()->can($permissionName)) {
87 $this->showPermissionError(); 92 $this->showPermissionError();
88 } 93 }
89 return true; 94 return true;
......
...@@ -36,7 +36,8 @@ class FileController extends Controller ...@@ -36,7 +36,8 @@ class FileController extends Controller
36 { 36 {
37 // TODO - ensure uploads are deleted on page delete. 37 // TODO - ensure uploads are deleted on page delete.
38 $this->validate($request, [ 38 $this->validate($request, [
39 - 'uploaded_to' => 'required|integer|exists:pages,id' 39 + 'uploaded_to' => 'required|integer|exists:pages,id',
40 + 'file' => 'required|file'
40 ]); 41 ]);
41 42
42 $pageId = $request->get('uploaded_to'); 43 $pageId = $request->get('uploaded_to');
...@@ -57,6 +58,32 @@ class FileController extends Controller ...@@ -57,6 +58,32 @@ class FileController extends Controller
57 } 58 }
58 59
59 /** 60 /**
61 + * Attach a link to a page as a file.
62 + * @param Request $request
63 + * @return mixed
64 + */
65 + public function attachLink(Request $request)
66 + {
67 + $this->validate($request, [
68 + 'uploaded_to' => 'required|integer|exists:pages,id',
69 + 'name' => 'string',
70 + 'link' => 'url'
71 + ]);
72 +
73 + $pageId = $request->get('uploaded_to');
74 + $page = $this->pageRepo->getById($pageId);
75 +
76 + $this->checkPermission('file-create-all');
77 + $this->checkOwnablePermission('page-update', $page);
78 +
79 + $fileName = $request->get('name');
80 + $link = $request->get('link');
81 + $file = $this->fileService->saveNewFromLink($fileName, $link, $pageId);
82 +
83 + return response()->json($file);
84 + }
85 +
86 + /**
60 * Get the files for a specific page. 87 * Get the files for a specific page.
61 * @param $pageId 88 * @param $pageId
62 * @return mixed 89 * @return mixed
...@@ -85,7 +112,7 @@ class FileController extends Controller ...@@ -85,7 +112,7 @@ class FileController extends Controller
85 112
86 $files = $request->get('files'); 113 $files = $request->get('files');
87 $this->fileService->updateFileOrderWithinPage($files, $pageId); 114 $this->fileService->updateFileOrderWithinPage($files, $pageId);
88 - return response()->json(['message' => 'File order updated']); 115 + return response()->json(['message' => 'Attachment order updated']);
89 } 116 }
90 117
91 /** 118 /**
...@@ -98,6 +125,10 @@ class FileController extends Controller ...@@ -98,6 +125,10 @@ class FileController extends Controller
98 $page = $this->pageRepo->getById($file->uploaded_to); 125 $page = $this->pageRepo->getById($file->uploaded_to);
99 $this->checkOwnablePermission('page-view', $page); 126 $this->checkOwnablePermission('page-view', $page);
100 127
128 + if ($file->external) {
129 + return redirect($file->path);
130 + }
131 +
101 $fileContents = $this->fileService->getFile($file); 132 $fileContents = $this->fileService->getFile($file);
102 return response($fileContents, 200, [ 133 return response($fileContents, 200, [
103 'Content-Type' => 'application/octet-stream', 134 'Content-Type' => 'application/octet-stream',
...@@ -113,8 +144,8 @@ class FileController extends Controller ...@@ -113,8 +144,8 @@ class FileController extends Controller
113 public function delete($fileId) 144 public function delete($fileId)
114 { 145 {
115 $file = $this->file->findOrFail($fileId); 146 $file = $this->file->findOrFail($fileId);
116 - $this->checkOwnablePermission($file, 'file-delete'); 147 + $this->checkOwnablePermission('file-delete', $file);
117 $this->fileService->deleteFile($file); 148 $this->fileService->deleteFile($file);
118 - return response()->json(['message' => 'File deleted']); 149 + return response()->json(['message' => 'Attachment deleted']);
119 } 150 }
120 } 151 }
......
...@@ -67,6 +67,27 @@ class FileService extends UploadService ...@@ -67,6 +67,27 @@ class FileService extends UploadService
67 } 67 }
68 68
69 /** 69 /**
70 + * Save a new File attachment from a given link and name.
71 + * @param string $name
72 + * @param string $link
73 + * @param int $page_id
74 + * @return File
75 + */
76 + public function saveNewFromLink($name, $link, $page_id)
77 + {
78 + $largestExistingOrder = File::where('uploaded_to', '=', $page_id)->max('order');
79 + return File::forceCreate([
80 + 'name' => $name,
81 + 'path' => $link,
82 + 'external' => true,
83 + 'uploaded_to' => $page_id,
84 + 'created_by' => user()->id,
85 + 'updated_by' => user()->id,
86 + 'order' => $largestExistingOrder + 1
87 + ]);
88 + }
89 +
90 + /**
70 * Get the file storage base path, amended for storage type. 91 * Get the file storage base path, amended for storage type.
71 * This allows us to keep a generic path in the database. 92 * This allows us to keep a generic path in the database.
72 * @return string 93 * @return string
...@@ -94,6 +115,11 @@ class FileService extends UploadService ...@@ -94,6 +115,11 @@ class FileService extends UploadService
94 */ 115 */
95 public function deleteFile(File $file) 116 public function deleteFile(File $file)
96 { 117 {
118 + if ($file->external) {
119 + $file->delete();
120 + return;
121 + }
122 +
97 $storedFilePath = $this->getStorageBasePath() . $file->path; 123 $storedFilePath = $this->getStorageBasePath() . $file->path;
98 $storage = $this->getStorage(); 124 $storage = $this->getStorage();
99 $dirPath = dirname($storedFilePath); 125 $dirPath = dirname($storedFilePath);
......
...@@ -606,6 +606,18 @@ module.exports = function (ngApp, events) { ...@@ -606,6 +606,18 @@ module.exports = function (ngApp, events) {
606 }); 606 });
607 }; 607 };
608 608
609 + $scope.attachLinkSubmit = function(fileName, fileLink) {
610 + $http.post('/files/link', {
611 + uploaded_to: pageId,
612 + name: fileName,
613 + link: fileLink
614 + }).then(resp => {
615 + $scope.files.unshift(resp.data);
616 + events.emit('success', 'Link attached');
617 + });
618 + $scope.fileName = $scope.fileLink = '';
619 + };
620 +
609 }]); 621 }]);
610 622
611 }; 623 };
......
...@@ -41,6 +41,19 @@ ...@@ -41,6 +41,19 @@
41 <p class="muted small">Upload some files to display on your page. This are visible in the page sidebar.</p> 41 <p class="muted small">Upload some files to display on your page. This are visible in the page sidebar.</p>
42 <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone> 42 <drop-zone upload-url="@{{getUploadUrl()}}" uploaded-to="@{{uploadedTo}}" event-success="uploadSuccess"></drop-zone>
43 43
44 + <hr class="even">
45 +
46 + <div class="form-group">
47 + <label for="attachment-via-link">File Name</label>
48 + <input type="text" placeholder="File name" ng-model="fileName">
49 + </div>
50 + <div class="form-group">
51 + <label for="attachment-via-link">Link to file</label>
52 + <input type="text" placeholder="File url" ng-model="fileLink">
53 + </div>
54 + <button type="button" ng-click="attachLinkSubmit(fileName, fileLink)" class="button pos">Attach</button>
55 +
56 +
44 <table class="no-style" tag-autosuggestions style="width: 100%;"> 57 <table class="no-style" tag-autosuggestions style="width: 100%;">
45 <tbody ui-sortable="sortOptions" ng-model="files" > 58 <tbody ui-sortable="sortOptions" ng-model="files" >
46 <tr ng-repeat="file in files track by $index"> 59 <tr ng-repeat="file in files track by $index">
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 <h6 class="text-muted">Attachments</h6> 5 <h6 class="text-muted">Attachments</h6>
6 @foreach($page->files as $file) 6 @foreach($page->files as $file)
7 <div class="attachment"> 7 <div class="attachment">
8 - <a href="{{ $file->getUrl() }}"><i class="zmdi zmdi-file"></i> {{ $file->name }}</a> 8 + <a href="{{ $file->getUrl() }}" @if($file->external) target="_blank" @endif><i class="zmdi zmdi-file"></i> {{ $file->name }}</a>
9 </div> 9 </div>
10 @endforeach 10 @endforeach
11 @endif 11 @endif
......
...@@ -90,6 +90,7 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -90,6 +90,7 @@ Route::group(['middleware' => 'auth'], function () {
90 // File routes 90 // File routes
91 Route::get('/files/{id}', 'FileController@get'); 91 Route::get('/files/{id}', 'FileController@get');
92 Route::post('/files/upload', 'FileController@upload'); 92 Route::post('/files/upload', 'FileController@upload');
93 + Route::post('/files/link', 'FileController@attachLink');
93 Route::get('/files/get/page/{pageId}', 'FileController@listForPage'); 94 Route::get('/files/get/page/{pageId}', 'FileController@listForPage');
94 Route::put('/files/sort/page/{pageId}', 'FileController@sortForPage'); 95 Route::put('/files/sort/page/{pageId}', 'FileController@sortForPage');
95 Route::delete('/files/{id}', 'FileController@delete'); 96 Route::delete('/files/{id}', 'FileController@delete');
......