diff --git a/src/api/controllers/Attachments.php b/src/api/controllers/Attachments.php index ef63e5a..74feefc 100644 --- a/src/api/controllers/Attachments.php +++ b/src/api/controllers/Attachments.php @@ -4,8 +4,7 @@ use RedBeanPHP\R; class Attachments extends BaseController { public function getAttachment($request, $response, $args) { - $status = $this->secureRoute($request, $response, - SecurityLevel::USER); + $status = $this->secureRoute($request, $response, SecurityLevel::USER); if ($status !== 200) { return $this->jsonResponse($response, $status); } @@ -33,14 +32,19 @@ class Attachments extends BaseController { } public function addAttachment($request, $response) { - $status = $this->secureRoute($request, $response, - SecurityLevel::USER); + $status = $this->secureRoute($request, $response, SecurityLevel::USER); if ($status !== 200) { return $this->jsonResponse($response, $status); } + if (!file_exists('uploads/')) { + mkdir('uploads', 0777, true); + } + + $body = $request->getBody(); $attachment = R::dispense('attachment'); - if (!BeanLoader::LoadAttachment($attachment, $request->getBody())) { + + if (!BeanLoader::LoadAttachment($attachment, $body)) { $attachment->task_id = 0; } @@ -58,6 +62,11 @@ class Attachments extends BaseController { return $this->jsonResponse($response, 403); } + $body = json_decode($body); + $attachment->diskfilename = sha1($body->filename); + + file_put_contents('uploads/' . $attachment->diskfilename, $body->data); + R::store($attachment); $actor = R::load('user', Auth::GetUserId($request)); @@ -73,8 +82,7 @@ class Attachments extends BaseController { } public function removeAttachment($request, $response, $args) { - $status = $this->secureRoute($request, $response, - SecurityLevel::USER); + $status = $this->secureRoute($request, $response, SecurityLevel::USER); if ($status !== 200) { return $this->jsonResponse($response, $status); } @@ -110,7 +118,9 @@ class Attachments extends BaseController { } $before = $attachment; - $attachment->delete(); + R::trash($attachment); + + unlink('uploads/' . $before->diskfilename); $this->dbLogger->logChange($actor->id, $actor->username .' removed attachment ' . $before->name, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 248e993..a6059d2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -11,6 +11,7 @@ import { ApiInterceptor } from './app.api-http'; import { LoginComponent } from './login/login.component'; import { BoardModule } from './board/board.module'; +import { FileModule } from './files/file-viewer.module'; import { DashboardModule } from './dashboard/dashboard.module'; import { SettingsModule } from './settings/settings.module'; import { SharedModule } from './shared/shared.module'; @@ -21,6 +22,7 @@ import { SharedModule } from './shared/shared.module'; FormsModule, HttpClientModule, BoardModule, + FileModule, DashboardModule, DragDropModule, SettingsModule, diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 1c7eee4..d5313aa 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,7 @@ import { Routes } from '@angular/router'; import { BoardDisplayComponent } from './board/board.component'; +import { FileViewerComponent } from './files/file-viewer.component'; import { LoginComponent } from './login/login.component'; import { SettingsComponent } from './settings/settings.component'; import { DashboardComponent } from './dashboard/dashboard.component'; @@ -30,6 +31,10 @@ export const ROUTES: Routes = [ path: 'dashboard', component: DashboardComponent, canActivate: [ AuthGuard ] + }, + { + path: 'files/:hash', + component: FileViewerComponent, } ]; diff --git a/src/app/shared/models/attachment.model.ts b/src/app/shared/models/attachment.model.ts index 773aa18..6a90ee4 100644 --- a/src/app/shared/models/attachment.model.ts +++ b/src/app/shared/models/attachment.model.ts @@ -1,11 +1,13 @@ export class Attachment { constructor(public id: number = 0, public filename: string = '', + public diskfilename: string = '', public name: string = '', public type: string = '', public user_id: number = 0, // tslint:disable-line public timestamp: number = Date.now(), - public task_id: number = 0) { // tslint:disable-line + public task_id: number = 0, + public data: any = null) { // tslint:disable-line } } diff --git a/src/app/shared/models/task.model.ts b/src/app/shared/models/task.model.ts index e7d3cd1..356bb3d 100644 --- a/src/app/shared/models/task.model.ts +++ b/src/app/shared/models/task.model.ts @@ -44,6 +44,7 @@ export class Task { attachmentArray.forEach((attachment: any) => { this.attachments.push(new Attachment(+attachment.id, attachment.filename, + attachment.diskfilename, attachment.name, attachment.type, +attachment.user_id, diff --git a/src/json/en.json b/src/json/en.json index dd320b0..03fa977 100644 --- a/src/json/en.json +++ b/src/json/en.json @@ -9,6 +9,7 @@ "dashboard": "Dashboard", "boards": "Boards", + "files": "File Viewer", "settings": "Settings", "logout": "Logout", @@ -155,6 +156,8 @@ "boards_confirmRemoveTask": "Confirm Task Removal", "boards_confirmWarning": "Removing a task cannot be undone.", "boards_confirmContinue": "Continue?", + "boards_confirmRemoveAttachment": "Confirm Attachment Removal", + "boards_confirmWarningAttachment": "Removing an attachment cannot be undone.", "boards_confirmRemoveComment": "Confirm Comment Removal", "boards_confirmWarningComment": "Removing a comment cannot be undone.", @@ -201,6 +204,10 @@ "boards_taskRemoveAttachment": "Remove Attachment", "boards_taskNoFileError": "Select a file before uploading.", "boards_taskUpload": "Upload", + "boards_taskUploadedBy": "Uploaded by", + "boards_taskUploadedOn": "on", + "boards_taskView": "View", + "boards_taskDownload": "Download", "boards_task": "Task", "boards_taskComplete": "Complete", diff --git a/src/scss/_board.scss b/src/scss/_board.scss index df516e4..8a3663a 100644 --- a/src/scss/_board.scss +++ b/src/scss/_board.scss @@ -377,6 +377,33 @@ } } + .list-group { + border: 1px solid $color-border; + border-radius: 3px; + + .list-group-item { + padding: 7px; + + &:nth-of-type(even) { + background-color: $color-table-row; + } + + .detail { + margin-left: 7px; + } + + .pull-right { + color: $color-primary; + float: right; + margin-top: -2.8rem; + + i { + margin-left: 7px; + } + } + } + } + .comment { @include shadow-low;