From 255f6321ec5a09b06ce5aa06b202ea04f2c4e8de Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Wed, 28 Oct 2020 23:53:03 -0400 Subject: [PATCH 01/10] feat: add messages in project --- app/Helpers/LogHelper.php | 26 +- .../Company/Project/ProjectController.php | 35 --- .../Project/ProjectMessagesController.php | 211 ++++++++++++++++ .../Project/ProjectDecisionsViewHelper.php | 2 +- .../Project/ProjectMessagesViewHelper.php | 133 ++++++++++ app/Models/Company/Employee.php | 12 +- app/Models/Company/Project.php | 10 + app/Models/Company/ProjectMessage.php | 48 ++++ .../Company/Project/CreateProjectMessage.php | 100 ++++++++ .../Company/Project/DestroyProjectMessage.php | 83 ++++++ .../Company/Project/ReadProjectMessage.php | 79 ++++++ .../Company/Project/UpdateProjectMessage.php | 91 +++++++ database/factories/CompanyFactory.php | 19 ++ ...0_195724_create_project_messages_table.php | 36 +++ ...streamline-icon-morning-news-1@140x140.png | Bin 0 -> 8201 bytes .../js/Pages/Project/Decisions/Index.vue | 2 +- resources/js/Pages/Project/Members/Index.vue | 1 - resources/js/Pages/Project/Message.vue | 4 +- resources/js/Pages/Project/Messages.vue | 125 ---------- .../js/Pages/Project/Messages/Create.vue | 138 ++++++++++ resources/js/Pages/Project/Messages/Index.vue | 162 ++++++++++++ resources/js/Pages/Project/Messages/Show.vue | 236 ++++++++++++++++++ .../js/Pages/Project/Messages/Update.vue | 147 +++++++++++ .../js/Pages/Project/Partials/ProjectMenu.vue | 4 +- resources/lang/en/account.php | 3 + resources/lang/en/project.php | 2 + routes/web.php | 11 +- .../Models/Company/ProjectMessageTest.php | 26 ++ tests/Unit/Models/Company/ProjectTest.php | 12 + .../Project/CreateProjectMessageTest.php | 113 +++++++++ .../Project/DestroyProjectMessageTest.php | 124 +++++++++ .../Project/ReadProjectMessageTest.php | 114 +++++++++ .../Project/UpdateProjectMessageTest.php | 128 ++++++++++ 33 files changed, 2065 insertions(+), 172 deletions(-) create mode 100644 app/Http/Controllers/Company/Project/ProjectMessagesController.php create mode 100644 app/Http/ViewHelpers/Project/ProjectMessagesViewHelper.php create mode 100644 app/Models/Company/ProjectMessage.php create mode 100644 app/Services/Company/Project/CreateProjectMessage.php create mode 100644 app/Services/Company/Project/DestroyProjectMessage.php create mode 100644 app/Services/Company/Project/ReadProjectMessage.php create mode 100644 app/Services/Company/Project/UpdateProjectMessage.php create mode 100644 database/migrations/2020_10_20_195724_create_project_messages_table.php create mode 100644 public/img/streamline-icon-morning-news-1@140x140.png delete mode 100644 resources/js/Pages/Project/Messages.vue create mode 100644 resources/js/Pages/Project/Messages/Create.vue create mode 100644 resources/js/Pages/Project/Messages/Index.vue create mode 100644 resources/js/Pages/Project/Messages/Show.vue create mode 100644 resources/js/Pages/Project/Messages/Update.vue create mode 100644 tests/Unit/Models/Company/ProjectMessageTest.php create mode 100644 tests/Unit/Services/Company/Project/CreateProjectMessageTest.php create mode 100644 tests/Unit/Services/Company/Project/DestroyProjectMessageTest.php create mode 100644 tests/Unit/Services/Company/Project/ReadProjectMessageTest.php create mode 100644 tests/Unit/Services/Company/Project/UpdateProjectMessageTest.php diff --git a/app/Helpers/LogHelper.php b/app/Helpers/LogHelper.php index 07bd10ecd..dce618fce 100644 --- a/app/Helpers/LogHelper.php +++ b/app/Helpers/LogHelper.php @@ -870,8 +870,32 @@ public static function processAuditLog(AuditLog $log): string 'project_name' => $log->object->{'project_name'}, 'title' => $log->object->{'title'}, ]); + break; + + case 'project_message_created': + $sentence = trans('account.log_project_message_created', [ + 'project_id' => $log->object->{'project_id'}, + 'project_name' => $log->object->{'project_name'}, + 'title' => $log->object->{'title'}, + ]); + break; + + case 'project_message_destroyed': + $sentence = trans('account.log_project_message_destroyed', [ + 'project_id' => $log->object->{'project_id'}, + 'project_name' => $log->object->{'project_name'}, + 'title' => $log->object->{'title'}, + ]); + break; + + case 'project_message_updated': + $sentence = trans('account.log_project_message_updated', [ + 'project_id' => $log->object->{'project_id'}, + 'project_name' => $log->object->{'project_name'}, + 'title' => $log->object->{'project_message_title'}, + ]); + break; - // no break default: $sentence = ''; break; diff --git a/app/Http/Controllers/Company/Project/ProjectController.php b/app/Http/Controllers/Company/Project/ProjectController.php index d8e991d15..01b3714bc 100644 --- a/app/Http/Controllers/Company/Project/ProjectController.php +++ b/app/Http/Controllers/Company/Project/ProjectController.php @@ -372,41 +372,6 @@ public function clear(Request $request, int $companyId, int $projectId): JsonRes ], 200); } - /** - * Display the project messages. - * - * @param Request $request - * @param int $companyId - * @param int $projectId - * @return Response - */ - public function messages(Request $request, int $companyId, int $projectId): Response - { - $company = InstanceHelper::getLoggedCompany(); - - return Inertia::render('Project/Messages', [ - 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), - ]); - } - - /** - * Display the project messages. - * - * @param Request $request - * @param int $companyId - * @param int $projectId - * @param int $messageId - * @return Response - */ - public function message(Request $request, int $companyId, int $projectId, int $messageId): Response - { - $company = InstanceHelper::getLoggedCompany(); - - return Inertia::render('Project/Message', [ - 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), - ]); - } - /** * Display the create new project form. * diff --git a/app/Http/Controllers/Company/Project/ProjectMessagesController.php b/app/Http/Controllers/Company/Project/ProjectMessagesController.php new file mode 100644 index 000000000..4c285523d --- /dev/null +++ b/app/Http/Controllers/Company/Project/ProjectMessagesController.php @@ -0,0 +1,211 @@ +id) + ->with('employees') + ->findOrFail($projectId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + return Inertia::render('Project/Messages/Index', [ + 'tab' => 'messages', + 'project' => ProjectViewHelper::info($project), + 'messages' => ProjectMessagesViewHelper::index($project), + 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), + ]); + } + + /** + * Display the Create message view. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|Response + */ + public function create(Request $request, int $companyId, int $projectId) + { + $company = InstanceHelper::getLoggedCompany(); + + try { + $project = Project::where('company_id', $company->id) + ->with('employees') + ->findOrFail($projectId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + return Inertia::render('Project/Messages/Create', [ + 'project' => ProjectViewHelper::info($project), + 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), + ]); + } + + /** + * Create the message. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * @return JsonResponse + */ + public function store(Request $request, int $companyId, int $projectId): JsonResponse + { + $loggedEmployee = InstanceHelper::getLoggedEmployee(); + $company = InstanceHelper::getLoggedCompany(); + + $data = [ + 'company_id' => $company->id, + 'author_id' => $loggedEmployee->id, + 'project_id' => $projectId, + 'title' => $request->input('title'), + 'content' => $request->input('content'), + ]; + + $message = (new CreateProjectMessage)->execute($data); + + return response()->json([ + 'data' => $message->id, + ], 201); + } + + /** + * Display the detail of a given message. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * @param int $messageId + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|Response + */ + public function show(Request $request, int $companyId, int $projectId, int $messageId) + { + $company = InstanceHelper::getLoggedCompany(); + + try { + $project = Project::where('company_id', $company->id) + ->with('employees') + ->findOrFail($projectId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + try { + $message = ProjectMessage::where('project_id', $project->id) + ->with('project') + ->findOrFail($messageId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + return Inertia::render('Project/Messages/Show', [ + 'tab' => 'messages', + 'project' => ProjectViewHelper::info($project), + 'message' => ProjectMessagesViewHelper::show($message), + 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), + ]); + } + + /** + * Display the edit message page. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * @param int $messageId + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|Response + */ + public function edit(Request $request, int $companyId, int $projectId, int $messageId) + { + $company = InstanceHelper::getLoggedCompany(); + + try { + $project = Project::where('company_id', $company->id) + ->with('employees') + ->findOrFail($projectId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + try { + $message = ProjectMessage::where('project_id', $project->id) + ->with('project') + ->findOrFail($messageId); + } catch (ModelNotFoundException $e) { + return redirect('home'); + } + + return Inertia::render('Project/Messages/Update', [ + 'tab' => 'messages', + 'project' => ProjectViewHelper::info($project), + 'message' => ProjectMessagesViewHelper::edit($message), + 'notifications' => NotificationHelper::getNotifications(InstanceHelper::getLoggedEmployee()), + ]); + } + + /** + * Create the message. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * @param int $projectMessageId + * @return JsonResponse + */ + public function update(Request $request, int $companyId, int $projectId, int $projectMessageId): JsonResponse + { + $loggedEmployee = InstanceHelper::getLoggedEmployee(); + $company = InstanceHelper::getLoggedCompany(); + + $data = [ + 'company_id' => $company->id, + 'author_id' => $loggedEmployee->id, + 'project_id' => $projectId, + 'project_message_id' => $projectMessageId, + 'title' => $request->input('title'), + 'content' => $request->input('content'), + ]; + + $message = (new UpdateProjectMessage)->execute($data); + + return response()->json([ + 'data' => $message->id, + ], 201); + } +} diff --git a/app/Http/ViewHelpers/Project/ProjectDecisionsViewHelper.php b/app/Http/ViewHelpers/Project/ProjectDecisionsViewHelper.php index 9975b4d73..353aaaba7 100644 --- a/app/Http/ViewHelpers/Project/ProjectDecisionsViewHelper.php +++ b/app/Http/ViewHelpers/Project/ProjectDecisionsViewHelper.php @@ -24,7 +24,7 @@ public static function decisions(Project $project): Collection $decisionsCollection = collect([]); foreach ($decisions as $decision) { - $deciders = $decision->deciders()->get(); + $deciders = $decision->deciders; $decidersCollection = collect([]); foreach ($deciders as $decider) { $decidersCollection->push([ diff --git a/app/Http/ViewHelpers/Project/ProjectMessagesViewHelper.php b/app/Http/ViewHelpers/Project/ProjectMessagesViewHelper.php new file mode 100644 index 000000000..217d9accc --- /dev/null +++ b/app/Http/ViewHelpers/Project/ProjectMessagesViewHelper.php @@ -0,0 +1,133 @@ +company; + $messages = $project->messages() + ->select('id', 'title', 'content', 'created_at', 'author_id') + ->with('author') + ->latest() + ->get(); + + $messageReadStatuses = DB::table('project_message_read_status') + ->whereIn('project_message_id', $messages->pluck('id')) + ->get(); + + $messagesCollection = collect([]); + foreach ($messages as $message) { + // check read status for each message + $readStatus = false; + if ($message->author) { + $readStatus = $messageReadStatuses->contains(function ($readStatus, $key) use ($message) { + return $readStatus->project_message_id == $message->id && $readStatus->employee_id == $message->author->id; + }); + } + + $messagesCollection->push([ + 'id' => $message->id, + 'title' => $message->title, + 'content' => Str::words($message->content, 10, '...'), + 'read_status' => $readStatus, + 'written_at' => $message->created_at->diffForHumans(), + 'url' => route('projects.messages.show', [ + 'company' => $company, + 'project' => $project, + 'message' => $message, + ]), + 'author' => $message->author ? [ + 'id' => $message->author->id, + 'name' => $message->author->name, + 'avatar' => $message->author->avatar, + 'url_view' => route('employees.show', [ + 'company' => $company, + 'employee' => $message->author, + ]), + ] : null, + ]); + } + + return $messagesCollection; + } + + /** + * Array containing the information about a given message. + * + * @param ProjectMessage $projectMessage + * @return array + */ + public static function show(ProjectMessage $projectMessage): array + { + // check author role in project + $author = $projectMessage->author; + if ($author) { + $role = DB::table('employee_project') + ->where('employee_id', $author->id) + ->where('project_id', $projectMessage->project->id) + ->select('role', 'created_at') + ->first(); + } + + return [ + 'id' => $projectMessage->id, + 'title' => $projectMessage->title, + 'content' => $projectMessage->content, + 'parsed_content' => StringHelper::parse($projectMessage->content), + 'written_at' => DateHelper::formatDate($projectMessage->created_at), + 'written_at_human' => $projectMessage->created_at->diffForHumans(), + 'url_edit' => route('projects.messages.edit', [ + 'company' => $projectMessage->project->company_id, + 'project' => $projectMessage->project, + 'message' => $projectMessage, + ]), + 'author' => $projectMessage->author ? [ + 'id' => $projectMessage->author->id, + 'name' => $projectMessage->author->name, + 'avatar' => $projectMessage->author->avatar, + 'role' => $role ? $role->role : null, + 'added_at' => $role ? DateHelper::formatDate(Carbon::createFromFormat('Y-m-d H:i:s', $role->created_at)) : null, + 'position' => (! $projectMessage->author->position) ? null : [ + 'id' => $projectMessage->author->position->id, + 'title' => $projectMessage->author->position->title, + ], + 'url' => route('employees.show', [ + 'company' => $projectMessage->project->company_id, + 'employee' => $projectMessage->author, + ]), + ] : null, + ]; + } + + /** + * Array containing the information necessary to edit a message. + * + * @param ProjectMessage $projectMessage + * @return array + */ + public static function edit(ProjectMessage $projectMessage): array + { + return [ + 'id' => $projectMessage->id, + 'title' => $projectMessage->title, + 'content' => $projectMessage->content, + ]; + } +} diff --git a/app/Models/Company/Employee.php b/app/Models/Company/Employee.php index 45ae1fef9..d0dfe666f 100644 --- a/app/Models/Company/Employee.php +++ b/app/Models/Company/Employee.php @@ -460,7 +460,7 @@ public function projectsAsLead() } /** - * Get the project decision record associated with the employee. + * Get the project decision records associated with the employee. * * @return HasMany */ @@ -469,6 +469,16 @@ public function projectDecisions() return $this->hasMany(ProjectDecision::class, 'author_id', 'id'); } + /** + * Get the project message records associated with the employee. + * + * @return HasMany + */ + public function projectMessages() + { + return $this->hasMany(ProjectMessage::class, 'author_id', 'id'); + } + /** * Scope a query to only include unlocked users. * diff --git a/app/Models/Company/Project.php b/app/Models/Company/Project.php index 852bc1845..a9a9902ad 100644 --- a/app/Models/Company/Project.php +++ b/app/Models/Company/Project.php @@ -127,4 +127,14 @@ public function decisions() { return $this->hasMany(ProjectDecision::class); } + + /** + * Get the project messages associated with the project. + * + * @return hasMany + */ + public function messages() + { + return $this->hasMany(ProjectMessage::class); + } } diff --git a/app/Models/Company/ProjectMessage.php b/app/Models/Company/ProjectMessage.php new file mode 100644 index 000000000..1f6abbda2 --- /dev/null +++ b/app/Models/Company/ProjectMessage.php @@ -0,0 +1,48 @@ +belongsTo(Project::class); + } + + /** + * Get the employee record associated with the project decision. + * + * @return BelongsTo + */ + public function author() + { + return $this->belongsTo(Employee::class, 'author_id'); + } +} diff --git a/app/Services/Company/Project/CreateProjectMessage.php b/app/Services/Company/Project/CreateProjectMessage.php new file mode 100644 index 000000000..2c4c4ce79 --- /dev/null +++ b/app/Services/Company/Project/CreateProjectMessage.php @@ -0,0 +1,100 @@ + 'required|integer|exists:companies,id', + 'author_id' => 'required|integer|exists:employees,id', + 'project_id' => 'required|integer|exists:projects,id', + 'title' => 'required|string|max:255', + 'content' => 'required|string|max:65535', + ]; + } + + /** + * Create a project message. + * + * @param array $data + * @return ProjectMessage + */ + public function execute(array $data): ProjectMessage + { + $this->data = $data; + $this->validate(); + $this->createMessage(); + $this->markAsReadForThisUser(); + $this->log(); + + return $this->projectMessage; + } + + private function validate(): void + { + $this->validateRules($this->data); + + $this->author($this->data['author_id']) + ->inCompany($this->data['company_id']) + ->asNormalUser() + ->canExecuteService(); + + $this->project = Project::where('company_id', $this->data['company_id']) + ->findOrFail($this->data['project_id']); + } + + private function createMessage(): void + { + $this->projectMessage = ProjectMessage::create([ + 'project_id' => $this->data['project_id'], + 'author_id' => $this->data['author_id'], + 'title' => $this->data['title'], + 'content' => $this->data['content'], + ]); + } + + private function markAsReadForThisUser(): void + { + (new ReadProjectMessage)->execute([ + 'company_id' => $this->data['company_id'], + 'author_id' => $this->data['author_id'], + 'project_id' => $this->data['project_id'], + 'project_message_id' => $this->projectMessage->id, + ]); + } + + private function log(): void + { + LogAccountAudit::dispatch([ + 'company_id' => $this->data['company_id'], + 'action' => 'project_message_created', + 'author_id' => $this->author->id, + 'author_name' => $this->author->name, + 'audited_at' => Carbon::now(), + 'objects' => json_encode([ + 'project_id' => $this->project->id, + 'project_name' => $this->project->name, + 'title' => $this->projectMessage->title, + ]), + ])->onQueue('low'); + } +} diff --git a/app/Services/Company/Project/DestroyProjectMessage.php b/app/Services/Company/Project/DestroyProjectMessage.php new file mode 100644 index 000000000..e1b5dda03 --- /dev/null +++ b/app/Services/Company/Project/DestroyProjectMessage.php @@ -0,0 +1,83 @@ + 'required|integer|exists:companies,id', + 'author_id' => 'required|integer|exists:employees,id', + 'project_id' => 'required|integer|exists:projects,id', + 'project_message_id' => 'required|integer|exists:project_messages,id', + ]; + } + + /** + * Destroy a project message. + * + * @param array $data + */ + public function execute(array $data): void + { + $this->data = $data; + $this->validate(); + $this->destroyMessage(); + $this->log(); + } + + private function validate(): void + { + $this->validateRules($this->data); + + $this->author($this->data['author_id']) + ->inCompany($this->data['company_id']) + ->asNormalUser() + ->canExecuteService(); + + $this->project = Project::where('company_id', $this->data['company_id']) + ->findOrFail($this->data['project_id']); + + $this->projectMessage = ProjectMessage::where('project_id', $this->data['project_id']) + ->findOrFail($this->data['project_message_id']); + } + + private function destroyMessage(): void + { + $this->projectMessage->delete(); + } + + private function log(): void + { + LogAccountAudit::dispatch([ + 'company_id' => $this->data['company_id'], + 'action' => 'project_message_destroyed', + 'author_id' => $this->author->id, + 'author_name' => $this->author->name, + 'audited_at' => Carbon::now(), + 'objects' => json_encode([ + 'project_id' => $this->project->id, + 'project_name' => $this->project->name, + 'title' => $this->projectMessage->title, + ]), + ])->onQueue('low'); + } +} diff --git a/app/Services/Company/Project/ReadProjectMessage.php b/app/Services/Company/Project/ReadProjectMessage.php new file mode 100644 index 000000000..73a0ee1e1 --- /dev/null +++ b/app/Services/Company/Project/ReadProjectMessage.php @@ -0,0 +1,79 @@ + 'required|integer|exists:companies,id', + 'author_id' => 'required|integer|exists:employees,id', + 'project_id' => 'required|integer|exists:projects,id', + 'project_message_id' => 'required|integer|exists:project_messages,id', + ]; + } + + /** + * Mark a project message as read. + * + * @param array $data + */ + public function execute(array $data): void + { + $this->data = $data; + $this->validate(); + $this->read(); + } + + private function validate(): void + { + $this->validateRules($this->data); + + $this->author($this->data['author_id']) + ->inCompany($this->data['company_id']) + ->asNormalUser() + ->canExecuteService(); + + $this->project = Project::where('company_id', $this->data['company_id']) + ->findOrFail($this->data['project_id']); + + $this->projectMessage = ProjectMessage::where('project_id', $this->data['project_id']) + ->findOrFail($this->data['project_message_id']); + } + + private function read(): void + { + $count = DB::table('project_message_read_status') + ->where('project_message_id', $this->projectMessage->id) + ->where('employee_id', $this->author->id) + ->count(); + + if ($count > 1) { + return; + } + + DB::table('project_message_read_status')->insert([ + 'project_message_id' => $this->projectMessage->id, + 'employee_id' => $this->author->id, + 'created_at' => Carbon::now(), + ]); + } +} diff --git a/app/Services/Company/Project/UpdateProjectMessage.php b/app/Services/Company/Project/UpdateProjectMessage.php new file mode 100644 index 000000000..0b771e415 --- /dev/null +++ b/app/Services/Company/Project/UpdateProjectMessage.php @@ -0,0 +1,91 @@ + 'required|integer|exists:companies,id', + 'author_id' => 'required|integer|exists:employees,id', + 'project_id' => 'nullable|integer|exists:projects,id', + 'project_message_id' => 'nullable|integer|exists:project_messages,id', + 'title' => 'required|string|max:255', + 'content' => 'required|string|max:65535', + ]; + } + + /** + * Update the project message. + * + * @param array $data + * @return ProjectMessage + */ + public function execute(array $data): ProjectMessage + { + $this->data = $data; + $this->validate(); + $this->update(); + $this->log(); + + return $this->projectMessage; + } + + private function validate(): void + { + $this->validateRules($this->data); + + $this->author($this->data['author_id']) + ->inCompany($this->data['company_id']) + ->asNormalUser() + ->canExecuteService(); + + $this->project = Project::where('company_id', $this->data['company_id']) + ->findOrFail($this->data['project_id']); + + $this->projectMessage = ProjectMessage::where('project_id', $this->project->id) + ->findOrFail($this->data['project_message_id']); + } + + private function update(): void + { + $this->projectMessage->title = $this->data['title']; + $this->projectMessage->content = $this->data['content']; + $this->projectMessage->save(); + } + + private function log(): void + { + LogAccountAudit::dispatch([ + 'company_id' => $this->data['company_id'], + 'action' => 'project_message_updated', + 'author_id' => $this->author->id, + 'author_name' => $this->author->name, + 'audited_at' => Carbon::now(), + 'objects' => json_encode([ + 'project_id' => $this->project->id, + 'project_name' => $this->project->name, + 'project_message_id' => $this->projectMessage->id, + 'project_message_title' => $this->projectMessage->title, + ]), + ])->onQueue('low'); + } +} diff --git a/database/factories/CompanyFactory.php b/database/factories/CompanyFactory.php index 73ca718be..7fa9ecc2f 100644 --- a/database/factories/CompanyFactory.php +++ b/database/factories/CompanyFactory.php @@ -532,3 +532,22 @@ 'decided_at' => Carbon::now(), ]; }); + +$factory->define(App\Models\Company\ProjectMessage::class, function () { + $companyId = factory(App\Models\Company\Company::class)->create()->id; + + return [ + 'project_id' => function () use ($companyId) { + return factory(App\Models\Company\Project::class)->create([ + 'company_id' => $companyId, + ])->id; + }, + 'author_id' => function () use ($companyId) { + return factory(App\Models\Company\Employee::class)->create([ + 'company_id' => $companyId, + ])->id; + }, + 'title' => 'This is a title', + 'content' => 'This is a description', + ]; +}); diff --git a/database/migrations/2020_10_20_195724_create_project_messages_table.php b/database/migrations/2020_10_20_195724_create_project_messages_table.php new file mode 100644 index 000000000..f7fb0db89 --- /dev/null +++ b/database/migrations/2020_10_20_195724_create_project_messages_table.php @@ -0,0 +1,36 @@ +id(); + $table->unsignedBigInteger('project_id'); + $table->unsignedBigInteger('author_id')->nullable(); + $table->string('title'); + $table->text('content'); + $table->timestamps(); + $table->foreign('project_id')->references('id')->on('projects')->onDelete('cascade'); + $table->foreign('author_id')->references('id')->on('employees')->onDelete('set null'); + }); + + Schema::create('project_message_read_status', function (Blueprint $table) { + $table->unsignedBigInteger('project_message_id'); + $table->unsignedBigInteger('employee_id'); + $table->timestamps(); + $table->foreign('project_message_id')->references('id')->on('project_messages')->onDelete('cascade'); + $table->foreign('employee_id')->references('id')->on('employees')->onDelete('cascade'); + }); + } +} diff --git a/public/img/streamline-icon-morning-news-1@140x140.png b/public/img/streamline-icon-morning-news-1@140x140.png new file mode 100644 index 0000000000000000000000000000000000000000..72a099d8bb925d4ff48f6b2ba57e89f451977bb8 GIT binary patch literal 8201 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 literal 0 HcmV?d00001 diff --git a/resources/js/Pages/Project/Decisions/Index.vue b/resources/js/Pages/Project/Decisions/Index.vue index b8d943d5b..2e2a4a03b 100644 --- a/resources/js/Pages/Project/Decisions/Index.vue +++ b/resources/js/Pages/Project/Decisions/Index.vue @@ -72,7 +72,7 @@

- 🗞 {{ $t('project.decision_index_title') }} + 🗞 {{ $t('project.decision_index_title') }} diff --git a/resources/js/Pages/Project/Members/Index.vue b/resources/js/Pages/Project/Members/Index.vue index fb651869f..a3ab781bf 100644 --- a/resources/js/Pages/Project/Members/Index.vue +++ b/resources/js/Pages/Project/Members/Index.vue @@ -290,7 +290,6 @@ export default { }, created() { - this.localProject = this.project; this.localMembers = this.members.members; this.localRoles = this.members.roles; }, diff --git a/resources/js/Pages/Project/Message.vue b/resources/js/Pages/Project/Message.vue index 4006fca3c..a03b6da79 100644 --- a/resources/js/Pages/Project/Message.vue +++ b/resources/js/Pages/Project/Message.vue @@ -31,10 +31,10 @@ ...

  • - Messages + {{ project.name }}
  • - Message details + Detail of a message
  • diff --git a/resources/js/Pages/Project/Messages.vue b/resources/js/Pages/Project/Messages.vue deleted file mode 100644 index 2421c58a7..000000000 --- a/resources/js/Pages/Project/Messages.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - - - diff --git a/resources/js/Pages/Project/Messages/Create.vue b/resources/js/Pages/Project/Messages/Create.vue new file mode 100644 index 000000000..0a1f80d76 --- /dev/null +++ b/resources/js/Pages/Project/Messages/Create.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/resources/js/Pages/Project/Messages/Index.vue b/resources/js/Pages/Project/Messages/Index.vue new file mode 100644 index 000000000..259c58b71 --- /dev/null +++ b/resources/js/Pages/Project/Messages/Index.vue @@ -0,0 +1,162 @@ + + + + + diff --git a/resources/js/Pages/Project/Messages/Show.vue b/resources/js/Pages/Project/Messages/Show.vue new file mode 100644 index 000000000..c8eeda5e6 --- /dev/null +++ b/resources/js/Pages/Project/Messages/Show.vue @@ -0,0 +1,236 @@ + + + + + diff --git a/resources/js/Pages/Project/Messages/Update.vue b/resources/js/Pages/Project/Messages/Update.vue new file mode 100644 index 000000000..e47d3fb1d --- /dev/null +++ b/resources/js/Pages/Project/Messages/Update.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/resources/js/Pages/Project/Partials/ProjectMenu.vue b/resources/js/Pages/Project/Partials/ProjectMenu.vue index c0dd68762..4b3aa3a93 100644 --- a/resources/js/Pages/Project/Partials/ProjectMenu.vue +++ b/resources/js/Pages/Project/Partials/ProjectMenu.vue @@ -22,7 +22,7 @@
    -

    +

    {{ project.name }} {{ project.code }} @@ -31,7 +31,7 @@

    -
    +

    Project members

    avatar 'Removed :employee_name as the project lead of the project called :project_name.', 'log_project_decision_created' => 'Added a decision called :title in the project called :project_name.', 'log_project_decision_destroyed' => 'Deleted a decision called :title in the project called :project_name.', + 'log_project_message_created' => 'Added a message called :title in the project called :project_name.', + 'log_project_message_destroyed' => 'Deleted a message called :title in the project called :project_name.', + 'log_project_message_updated' => 'Updated a message called :title in the project called :project_name.', // employee logs 'employee_log_employee_created' => 'Created this employee entry.', diff --git a/resources/lang/en/project.php b/resources/lang/en/project.php index 0617e6dfb..315363b46 100644 --- a/resources/lang/en/project.php +++ b/resources/lang/en/project.php @@ -91,4 +91,6 @@ 'decision_index_add_success' => 'The decision has been recorded.', 'decision_index_destroy_success' => 'The decision has been forgotten.', 'decision_index_title' => 'Decisions in the project', + + 'message_update_success' => 'The message has been updated.', ]; diff --git a/routes/web.php b/routes/web.php index 7ac596127..fc3d7426d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -213,9 +213,6 @@ Route::post('{project}/links', 'Company\\Project\\ProjectController@createLink'); Route::delete('{project}/links/{link}', 'Company\\Project\\ProjectController@destroyLink'); - Route::get('{project}/messages', 'Company\\Project\\ProjectController@messages'); - Route::get('{project}/messages/{message}', 'Company\\Project\\ProjectController@message'); - Route::get('{project}/status', 'Company\\Project\\ProjectController@createStatus'); Route::put('{project}/status', 'Company\\Project\\ProjectController@postStatus'); @@ -230,6 +227,14 @@ Route::get('{project}/members/search', 'Company\\Project\\ProjectMembersController@search'); Route::post('{project}/members/store', 'Company\\Project\\ProjectMembersController@store'); Route::post('{project}/members/remove', 'Company\\Project\\ProjectMembersController@remove'); + + // project messages + Route::get('{project}/messages', 'Company\\Project\\ProjectMessagesController@index'); + Route::get('{project}/messages/create', 'Company\\Project\\ProjectMessagesController@create'); + Route::post('{project}/messages', 'Company\\Project\\ProjectMessagesController@store'); + Route::get('{project}/messages/{message}', 'Company\\Project\\ProjectMessagesController@show')->name('projects.messages.show'); + Route::get('{project}/messages/{message}/edit', 'Company\\Project\\ProjectMessagesController@edit')->name('projects.messages.edit'); + Route::put('{project}/messages/{message}', 'Company\\Project\\ProjectMessagesController@update'); }); Route::prefix('company')->group(function () { diff --git a/tests/Unit/Models/Company/ProjectMessageTest.php b/tests/Unit/Models/Company/ProjectMessageTest.php new file mode 100644 index 000000000..30e26268c --- /dev/null +++ b/tests/Unit/Models/Company/ProjectMessageTest.php @@ -0,0 +1,26 @@ +create([]); + $this->assertTrue($decision->project()->exists()); + } + + /** @test */ + public function it_belongs_to_a_employee(): void + { + $decision = factory(ProjectDecision::class)->create([]); + $this->assertTrue($decision->author()->exists()); + } +} diff --git a/tests/Unit/Models/Company/ProjectTest.php b/tests/Unit/Models/Company/ProjectTest.php index 5ea4cb97c..3702ad224 100644 --- a/tests/Unit/Models/Company/ProjectTest.php +++ b/tests/Unit/Models/Company/ProjectTest.php @@ -8,6 +8,7 @@ use App\Models\Company\Employee; use App\Models\Company\ProjectLink; use App\Models\Company\ProjectStatus; +use App\Models\Company\ProjectMessage; use App\Models\Company\ProjectDecision; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -100,4 +101,15 @@ public function it_has_many_decisions(): void $this->assertTrue($project->decisions()->exists()); } + + /** @test */ + public function it_has_many_messages(): void + { + $project = factory(Project::class)->create(); + factory(ProjectMessage::class, 2)->create([ + 'project_id' => $project->id, + ]); + + $this->assertTrue($project->messages()->exists()); + } } diff --git a/tests/Unit/Services/Company/Project/CreateProjectMessageTest.php b/tests/Unit/Services/Company/Project/CreateProjectMessageTest.php new file mode 100644 index 000000000..b06abbb87 --- /dev/null +++ b/tests/Unit/Services/Company/Project/CreateProjectMessageTest.php @@ -0,0 +1,113 @@ +createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $this->executeService($michael, $project); + } + + /** @test */ + public function it_adds_a_message_to_a_project_as_hr(): void + { + $michael = $this->createHR(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $this->executeService($michael, $project); + } + + /** @test */ + public function it_adds_a_message_to_a_project_as_normal_user(): void + { + $michael = $this->createEmployee(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $this->executeService($michael, $project); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given(): void + { + $request = [ + 'first_name' => 'Dwight', + ]; + + $this->expectException(ValidationException::class); + (new CreateProjectStatus)->execute($request); + } + + /** @test */ + public function it_fails_if_the_project_is_not_in_the_company(): void + { + $michael = $this->createAdministrator(); + $project = factory(Project::class)->create(); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project); + } + + private function executeService(Employee $michael, Project $project): void + { + Queue::fake(); + + $request = [ + 'company_id' => $michael->company_id, + 'author_id' => $michael->id, + 'project_id' => $project->id, + 'title' => 'email', + 'content' => 'content', + ]; + + $projectMessage = (new CreateProjectMessage)->execute($request); + + $this->assertDatabaseHas('project_messages', [ + 'id' => $projectMessage->id, + 'project_id' => $project->id, + 'title' => 'email', + 'content' => 'content', + ]); + + $this->assertDatabaseHas('project_message_read_status', [ + 'project_message_id' => $projectMessage->id, + 'employee_id' => $michael->id, + ]); + + $this->assertInstanceOf( + ProjectMessage::class, + $projectMessage + ); + + Queue::assertPushed(LogAccountAudit::class, function ($job) use ($michael, $project, $projectMessage) { + return $job->auditLog['action'] === 'project_message_created' && + $job->auditLog['author_id'] === $michael->id && + $job->auditLog['objects'] === json_encode([ + 'project_id' => $project->id, + 'project_name' => $project->name, + 'title' => $projectMessage->title, + ]); + }); + } +} diff --git a/tests/Unit/Services/Company/Project/DestroyProjectMessageTest.php b/tests/Unit/Services/Company/Project/DestroyProjectMessageTest.php new file mode 100644 index 000000000..aa101a280 --- /dev/null +++ b/tests/Unit/Services/Company/Project/DestroyProjectMessageTest.php @@ -0,0 +1,124 @@ +createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_destroys_a_message_from_a_project_as_hr(): void + { + $michael = $this->createHR(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_destroys_a_message_from_a_project_as_normal_user(): void + { + $michael = $this->createEmployee(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given(): void + { + $request = [ + 'first_name' => 'Dwight', + ]; + + $this->expectException(ValidationException::class); + (new DestroyProjectDecision)->execute($request); + } + + /** @test */ + public function it_fails_if_the_project_is_not_in_the_company(): void + { + $michael = $this->createAdministrator(); + $project = factory(Project::class)->create(); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_the_project_message_is_not_part_of_the_project(): void + { + $michael = $this->createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([]); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + private function executeService(Employee $michael, Project $project, ProjectMessage $message): void + { + Queue::fake(); + + $request = [ + 'company_id' => $michael->company_id, + 'author_id' => $michael->id, + 'project_id' => $project->id, + 'project_message_id' => $message->id, + ]; + + (new DestroyProjectMessage)->execute($request); + + $this->assertDatabaseMissing('project_messages', [ + 'id' => $message->id, + ]); + + Queue::assertPushed(LogAccountAudit::class, function ($job) use ($michael, $project, $message) { + return $job->auditLog['action'] === 'project_message_destroyed' && + $job->auditLog['author_id'] === $michael->id && + $job->auditLog['objects'] === json_encode([ + 'project_id' => $project->id, + 'project_name' => $project->name, + 'title' => $message->title, + ]); + }); + } +} diff --git a/tests/Unit/Services/Company/Project/ReadProjectMessageTest.php b/tests/Unit/Services/Company/Project/ReadProjectMessageTest.php new file mode 100644 index 000000000..795943a74 --- /dev/null +++ b/tests/Unit/Services/Company/Project/ReadProjectMessageTest.php @@ -0,0 +1,114 @@ +createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_reads_a_message_from_a_project_as_hr(): void + { + $michael = $this->createHR(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_reads_a_message_from_a_project_as_normal_user(): void + { + $michael = $this->createEmployee(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given(): void + { + $request = [ + 'first_name' => 'Dwight', + ]; + + $this->expectException(ValidationException::class); + (new DestroyProjectDecision)->execute($request); + } + + /** @test */ + public function it_fails_if_the_project_is_not_in_the_company(): void + { + $michael = $this->createAdministrator(); + $project = factory(Project::class)->create(); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_the_project_message_is_not_part_of_the_project(): void + { + $michael = $this->createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([]); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + private function executeService(Employee $michael, Project $project, ProjectMessage $message): void + { + Queue::fake(); + + $request = [ + 'company_id' => $michael->company_id, + 'author_id' => $michael->id, + 'project_id' => $project->id, + 'project_message_id' => $message->id, + ]; + + (new ReadProjectMessage)->execute($request); + + $this->assertDatabaseHas('project_message_read_status', [ + 'project_message_id' => $message->id, + 'employee_id' => $michael->id, + ]); + } +} diff --git a/tests/Unit/Services/Company/Project/UpdateProjectMessageTest.php b/tests/Unit/Services/Company/Project/UpdateProjectMessageTest.php new file mode 100644 index 000000000..d1f2078ab --- /dev/null +++ b/tests/Unit/Services/Company/Project/UpdateProjectMessageTest.php @@ -0,0 +1,128 @@ +createAdministrator(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_updates_the_project_message_as_hr(): void + { + $michael = $this->createHR(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_updates_the_project_message_as_normal_user(): void + { + $michael = $this->createEmployee(); + $project = factory(Project::class)->create([ + 'company_id' => $michael->company_id, + ]); + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_project_is_not_part_of_the_company(): void + { + $michael = factory(Employee::class)->create([]); + $project = factory(Project::class)->create(); + + $projectMessage = factory(ProjectMessage::class)->create([ + 'project_id' => $project->id, + ]); + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_project_message_is_not_part_of_the_project(): void + { + $michael = factory(Employee::class)->create([]); + $project = factory(Project::class)->create(); + $projectMessage = factory(ProjectMessage::class)->create([]); + + $this->expectException(ModelNotFoundException::class); + $this->executeService($michael, $project, $projectMessage); + } + + /** @test */ + public function it_fails_if_wrong_parameters_are_given(): void + { + $michael = factory(Employee::class)->create([]); + + $request = [ + 'company_id' => $michael->company_id, + ]; + + $this->expectException(ValidationException::class); + (new UpdateProjectMessage)->execute($request); + } + + private function executeService(Employee $michael, Project $project, ProjectMessage $message): void + { + Queue::fake(); + + $request = [ + 'company_id' => $michael->company_id, + 'author_id' => $michael->id, + 'project_id' => $project->id, + 'project_message_id' => $message->id, + 'title' => 'Update', + 'content' => 'Content', + ]; + + $message = (new UpdateProjectMessage)->execute($request); + + $this->assertDatabaseHas('project_messages', [ + 'id' => $message->id, + 'title' => 'Update', + 'content' => 'Content', + ]); + + Queue::assertPushed(LogAccountAudit::class, function ($job) use ($michael, $project, $message) { + return $job->auditLog['action'] === 'project_message_updated' && + $job->auditLog['author_id'] === $michael->id && + $job->auditLog['objects'] === json_encode([ + 'project_id' => $project->id, + 'project_name' => $project->name, + 'project_message_id' => $message->id, + 'project_message_title' => $message->title, + ]); + }); + } +} From 7f7039fe982593fff5e0a3436803d7563c1e7e57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 03:54:50 +0000 Subject: [PATCH 02/10] Optimised images with calibre/image-actions --- ...streamline-icon-morning-news-1@140x140.png | Bin 8201 -> 6055 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/img/streamline-icon-morning-news-1@140x140.png b/public/img/streamline-icon-morning-news-1@140x140.png index 72a099d8bb925d4ff48f6b2ba57e89f451977bb8..63df9da7104281a5d9d6efc1edd0967de2342d8b 100644 GIT binary patch literal 6055 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 aho9`{40%9piv6d&<7uess?;bU!v6;@Phorj literal 8201 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 From 001373ee24f30863d2be8f06976cea875dfb521d Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sat, 31 Oct 2020 08:47:39 -0400 Subject: [PATCH 03/10] wip --- .../Project/ProjectMessagesController.php | 31 +++- .../js/Pages/Project/Messages/Create.vue | 4 +- resources/js/Pages/Project/Messages/Index.vue | 4 +- resources/js/Pages/Project/Messages/Show.vue | 137 ++++++++++-------- resources/lang/en/project.php | 4 + routes/web.php | 1 + 6 files changed, 119 insertions(+), 62 deletions(-) diff --git a/app/Http/Controllers/Company/Project/ProjectMessagesController.php b/app/Http/Controllers/Company/Project/ProjectMessagesController.php index 4c285523d..f1071c129 100644 --- a/app/Http/Controllers/Company/Project/ProjectMessagesController.php +++ b/app/Http/Controllers/Company/Project/ProjectMessagesController.php @@ -14,6 +14,7 @@ use App\Http\ViewHelpers\Project\ProjectViewHelper; use App\Services\Company\Project\CreateProjectMessage; use App\Services\Company\Project\UpdateProjectMessage; +use App\Services\Company\Project\DestroyProjectMessage; use Illuminate\Database\Eloquent\ModelNotFoundException; use App\Http\ViewHelpers\Project\ProjectMessagesViewHelper; @@ -180,7 +181,7 @@ public function edit(Request $request, int $companyId, int $projectId, int $mess } /** - * Create the message. + * Actually update the message. * * @param Request $request * @param int $companyId @@ -208,4 +209,32 @@ public function update(Request $request, int $companyId, int $projectId, int $pr 'data' => $message->id, ], 201); } + + /** + * Destroy the message. + * + * @param Request $request + * @param int $companyId + * @param int $projectId + * @param int $projectMessageId + * @return JsonResponse + */ + public function destroy(Request $request, int $companyId, int $projectId, int $projectMessageId): JsonResponse + { + $loggedEmployee = InstanceHelper::getLoggedEmployee(); + $company = InstanceHelper::getLoggedCompany(); + + $data = [ + 'company_id' => $company->id, + 'author_id' => $loggedEmployee->id, + 'project_id' => $projectId, + 'project_message_id' => $projectMessageId, + ]; + + (new DestroyProjectMessage)->execute($data); + + return response()->json([ + 'data' => true, + ], 201); + } } diff --git a/resources/js/Pages/Project/Messages/Create.vue b/resources/js/Pages/Project/Messages/Create.vue index 0a1f80d76..f79452629 100644 --- a/resources/js/Pages/Project/Messages/Create.vue +++ b/resources/js/Pages/Project/Messages/Create.vue @@ -124,8 +124,8 @@ export default { axios.post(`/${this.$page.props.auth.company.id}/projects/${this.project.id}/messages`, this.form) .then(response => { - localStorage.success = this.$t('account.company_news_create_success'); - this.$inertia.visit('/' + this.$page.props.auth.company.id + '/projects/' + this.project.id + '/messages'); + localStorage.success = this.$t('project.message_create_success'); + this.$inertia.visit('/' + this.$page.props.auth.company.id + '/projects/' + this.project.id + '/messages' + '/' + response.data.data); }) .catch(error => { this.loadingState = null; diff --git a/resources/js/Pages/Project/Messages/Index.vue b/resources/js/Pages/Project/Messages/Index.vue index 259c58b71..7d7cbf709 100644 --- a/resources/js/Pages/Project/Messages/Index.vue +++ b/resources/js/Pages/Project/Messages/Index.vue @@ -49,7 +49,7 @@

    - 📨 Messages + 📨 {{ $t('project.message_title') }} @@ -85,7 +85,7 @@ meeting -

    Messages are essential to make announcements, give feedback, ask questions and have a central point of documentation in the project.

    +

    {{ $t('project.message_blank') }}

    diff --git a/resources/js/Pages/Project/Messages/Show.vue b/resources/js/Pages/Project/Messages/Show.vue index c8eeda5e6..2fef8a28f 100644 --- a/resources/js/Pages/Project/Messages/Show.vue +++ b/resources/js/Pages/Project/Messages/Show.vue @@ -54,17 +54,19 @@
    +

    + {{ message.title }} +

    +
    -
    -

    - {{ message.title }} -

    +
    -
    + + -

    Comments

    + + - +
    @@ -115,66 +117,78 @@
    - + -->
    -
    -
    - -

    - Written by -

    - -
    - {{ message.author.name }} - - - - - - - - {{ message.author.role }} - - - - - - - - - - {{ $t('project.members_index_role', { date: message.author.added_at }) }} - + +

    + Written by +

    + +
    +
    + avatar +
    + +
    + {{ message.author.name }} + + + + + + + + {{ message.author.role }} - - {{ $t('project.members_index_position_with_role', { role: message.author.position.title }) }} + + + + + + - - {{ $t('project.members_index_position', { role: message.author.position.title }) }} + + {{ $t('project.members_index_role', { date: message.author.added_at }) }} -
    -
    - - -
    -

    - Written on -

    -

    {{ message.written_at }} ({{ message.written_at_human }})

    + + + {{ $t('project.members_index_position_with_role', { role: message.author.position.title }) }} + + + {{ $t('project.members_index_position', { role: message.author.position.title }) }} +
    - -
    @@ -185,12 +199,10 @@ diff --git a/resources/js/Pages/Project/Messages/Index.vue b/resources/js/Pages/Project/Messages/Index.vue index c263edcb7..6110a25aa 100644 --- a/resources/js/Pages/Project/Messages/Index.vue +++ b/resources/js/Pages/Project/Messages/Index.vue @@ -132,7 +132,6 @@ export default { data() { return { - localMessages: null, loadingState: '', addMode: false, decisionToDelete: 0, @@ -149,10 +148,6 @@ export default { }; }, - created() { - this.localMessages = this.decisions; - }, - mounted() { if (localStorage.success) { flash(localStorage.success, 'success'); From 500122f5abc9f811360f580ac044defe79858af0 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 1 Nov 2020 17:12:27 -0500 Subject: [PATCH 08/10] Apply suggestions from code review Co-authored-by: Alexis Saettler --- app/Helpers/LogHelper.php | 2 +- app/Models/Company/Project.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Helpers/LogHelper.php b/app/Helpers/LogHelper.php index dce618fce..ddbe5383f 100644 --- a/app/Helpers/LogHelper.php +++ b/app/Helpers/LogHelper.php @@ -888,7 +888,7 @@ public static function processAuditLog(AuditLog $log): string ]); break; - case 'project_message_updated': + case 'project_message_updated': $sentence = trans('account.log_project_message_updated', [ 'project_id' => $log->object->{'project_id'}, 'project_name' => $log->object->{'project_name'}, diff --git a/app/Models/Company/Project.php b/app/Models/Company/Project.php index a9a9902ad..1127f61e4 100644 --- a/app/Models/Company/Project.php +++ b/app/Models/Company/Project.php @@ -131,7 +131,7 @@ public function decisions() /** * Get the project messages associated with the project. * - * @return hasMany + * @return HasMany */ public function messages() { From 3b8bb7222235b3268e347e403ac8cc040be08581 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 1 Nov 2020 17:14:28 -0500 Subject: [PATCH 09/10] Update routes/web.php Co-authored-by: Alexis Saettler --- routes/web.php | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/routes/web.php b/routes/web.php index fb8a3cc1e..66619a055 100644 --- a/routes/web.php +++ b/routes/web.php @@ -229,13 +229,7 @@ Route::post('{project}/members/remove', 'Company\\Project\\ProjectMembersController@remove'); // project messages - Route::get('{project}/messages', 'Company\\Project\\ProjectMessagesController@index'); - Route::get('{project}/messages/create', 'Company\\Project\\ProjectMessagesController@create'); - Route::post('{project}/messages', 'Company\\Project\\ProjectMessagesController@store'); - Route::get('{project}/messages/{message}', 'Company\\Project\\ProjectMessagesController@show')->name('projects.messages.show'); - Route::get('{project}/messages/{message}/edit', 'Company\\Project\\ProjectMessagesController@edit')->name('projects.messages.edit'); - Route::put('{project}/messages/{message}', 'Company\\Project\\ProjectMessagesController@update'); - Route::delete('{project}/messages/{message}', 'Company\\Project\\ProjectMessagesController@destroy'); + Route::resource('{project}/messages', 'Company\\Project\\ProjectMessagesController', ['as' => 'projects.messages']); }); Route::prefix('company')->group(function () { From 6f422be40bae5ae09a8cfbcd255138dc5328ee44 Mon Sep 17 00:00:00 2001 From: Regis Freyd Date: Sun, 1 Nov 2020 17:36:47 -0500 Subject: [PATCH 10/10] wip --- routes/web.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/web.php b/routes/web.php index 66619a055..c31145671 100644 --- a/routes/web.php +++ b/routes/web.php @@ -229,7 +229,7 @@ Route::post('{project}/members/remove', 'Company\\Project\\ProjectMembersController@remove'); // project messages - Route::resource('{project}/messages', 'Company\\Project\\ProjectMessagesController', ['as' => 'projects.messages']); + Route::resource('{project}/messages', 'Company\\Project\\ProjectMessagesController', ['as' => 'projects']); }); Route::prefix('company')->group(function () {