Browse Source

Add Job comments

pull/13/head
Nafies Luthfi 7 years ago
parent
commit
19071f5cf8
  1. 82
      app/Http/Controllers/Jobs/CommentsController.php
  2. 9
      app/Http/Controllers/JobsController.php
  3. 27
      app/Policies/Projects/JobPolicy.php
  4. 6
      resources/lang/id/comment.php
  5. 32
      resources/views/jobs/partials/comment-section.blade.php
  6. 39
      resources/views/jobs/show.blade.php
  7. 2
      routes/web.php
  8. 10
      routes/web/projects.php
  9. 104
      tests/Feature/Projects/JobCommentsTest.php
  10. 30
      tests/Unit/Policies/JobPolicyTest.php

82
app/Http/Controllers/Jobs/CommentsController.php

@ -0,0 +1,82 @@
<?php
namespace App\Http\Controllers\Jobs;
use Illuminate\Http\Request;
use App\Entities\Projects\Job;
use App\Entities\Projects\Comment;
use App\Http\Controllers\Controller;
class CommentsController extends Controller
{
/**
* Store a new comment in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Entities\Projects\Job $job
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request, Job $job)
{
$this->authorize('comment-on', $job);
$newComment = $request->validate([
'body' => 'required|string|max:255',
]);
$job->comments()->create([
'body' => $newComment['body'],
'creator_id' => auth()->id(),
]);
flash(__('comment.created'), 'success');
return back();
}
/**
* Update the specified comment.
*
* @param \Illuminate\Http\Request $request
* @param \App\Entities\Projects\Job $job
* @param \App\Entities\Jobs\Comment $comment
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Job $job, Comment $comment)
{
$this->authorize('update', $comment);
$commentData = $request->validate([
'body' => 'required|string|max:255',
]);
$comment->update($commentData);
flash(__('comment.updated'), 'success');
return redirect()->route('jobs.show', [$job] + request(['page']));
}
/**
* Remove the specified comment.
*
* @param \App\Entities\Jobs\Comment $comment
* @return \Illuminate\Routing\Redirector
*/
public function destroy(Job $job, Comment $comment)
{
$this->authorize('delete', $comment);
request()->validate([
'comment_id' => 'required|exists:comments,id',
]);
if (request('comment_id') == $comment->id && $comment->delete()) {
$routeParam = [$job] + request(['page']);
flash(__('comment.deleted'), 'warning');
return redirect()->route('jobs.show', $routeParam);
}
flash(__('comment.undeleted'), 'error');
return back();
}
}

9
app/Http/Controllers/JobsController.php

@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Entities\Projects\Job;
use App\Entities\Projects\Comment;
use App\Entities\Projects\Project;
use App\Entities\Projects\JobsRepository;
use App\Http\Requests\Jobs\DeleteRequest;
@ -65,6 +66,8 @@ class JobsController extends Controller
$this->authorize('view', $job);
$editableTask = null;
$editableComment = null;
$comments = $job->comments()->with('creator')->latest()->paginate();
if ($request->get('action') == 'task_edit' && $request->has('task_id')) {
$editableTask = $this->repo->requireTaskById($request->get('task_id'));
@ -74,7 +77,11 @@ class JobsController extends Controller
$editableTask = $this->repo->requireTaskById($request->get('task_id'));
}
return view('jobs.show', compact('job', 'editableTask'));
if (request('action') == 'comment-edit' && request('comment_id') != null) {
$editableComment = Comment::find(request('comment_id'));
}
return view('jobs.show', compact('job', 'editableTask', 'comments', 'editableComment'));
}
/**

27
app/Policies/Projects/JobPolicy.php

@ -80,4 +80,31 @@ class JobPolicy
{
return $user->hasRole('admin');
}
/**
* Determine whether the user can view job comments.
*
* @param \App\Entities\Users\User $user
* @param \App\Entities\Projects\Job $job
* @return bool
*/
public function viewComments(User $user, Job $job)
{
// Admin and job workers can commenting on their job.
return $user->hasRole('admin')
|| ($user->hasRole('worker') && $job->worker_id == $user->id);
}
/**
* Determine whether the user can add comment to a job.
*
* @param \App\Entities\Users\User $user
* @param \App\Entities\Projects\Job $job
* @return bool
*/
public function commentOn(User $user, Job $job)
{
// Admin and job workers can commenting on their job.
return $this->viewComments($user, $job);
}
}

6
resources/lang/id/comment.php

@ -15,9 +15,9 @@ return [
'updated' => 'Update data Komentar telah berhasil.',
'delete' => 'Hapus Komentar',
'delete_confirm' => 'Anda yakin akan menghapus Komentar ini?',
'deleted' => 'Hapus data Komentar telah berhasil.',
'undeleted' => 'Data Komentar gagal dihapus.',
'undeleteable' => 'Data Komentar tidak dapat dihapus.',
'deleted' => 'Komentar berhasil dihapus.',
'undeleted' => 'Komentar gagal dihapus.',
'undeleteable' => 'Komentar tidak dapat dihapus.',
// Attributes
'body' => 'Komentar',

32
resources/views/jobs/partials/comment-section.blade.php

@ -0,0 +1,32 @@
@can('comment-on', $job)
{{ Form::open(['route' => ['jobs.comments.store', $job]]) }}
<div class="row">
<div class="col-md-9">{!! FormField::textarea('body', ['required' => true, 'label' => false, 'placeholder' => __('comment.create_text')]) !!}</div>
<div class="col-md-3">
{{ Form::submit(__('comment.create'), ['class' => 'btn btn-success btn-block']) }}<br>
</div>
</div>
{{ Form::close() }}
@endcan
@foreach($comments as $comment)
<div class="alert alert-warning">
<legend style="font-size: 14px;margin-bottom: 10px;">
<span class="label label-default pull-right">{{ $comment->time_display }}</span>
<strong>{{ $comment->creator->name }}</strong>
</legend>
<div class="pull-right">
@can('update', $comment)
{{ link_to_route('jobs.show', __('app.edit'), [$job, 'action' => 'comment-edit', 'comment_id' => $comment->id], ['id' => 'edit-comment-'.$comment->id, 'class' => 'small', 'title' => __('comment.edit')]) }}
@endcan
@can('delete', $comment)
{!! FormField::delete(
['route' => ['jobs.comments.destroy', $job, $comment], 'class' => ''],
'&times;',
['class' => 'btn-link', 'id' => 'delete-comment-'.$comment->id],
['comment_id' => $comment->id, 'page' => request('page')]
) !!}
@endcan
</div>
{!! nl2br($comment->body) !!}
</div>
@endforeach

39
resources/views/jobs/show.blade.php

@ -29,6 +29,39 @@
<div class="row">
<div class="col-md-8 col-md-offset-2">
@include('jobs.partials.job-tasks')
@can('view-comments', $job)
<div class="row">
<div class="col-md-12">
{{ $comments->links() }}
@include('jobs.partials.comment-section')
{{ $comments->links() }}
</div>
</div>
@if (Request::get('action') == 'comment-edit' && $editableComment)
<div id="commentModal" class="modal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
{{ link_to_route('jobs.show', '&times;', [$job] + request(['page']), ['class' => 'close']) }}
<h4 class="modal-title">{{ __('comment.edit') }}</h4>
</div>
{!! Form::model($editableComment, ['route' => ['jobs.comments.update', $job, $editableComment->id],'method' => 'patch']) !!}
<div class="modal-body">
{!! FormField::textarea('body', ['label' => __('comment.body')]) !!}
{{ Form::hidden('page', request('page')) }}
</div>
<div class="modal-footer">
{!! Form::submit(__('comment.update'), ['class' => 'btn btn-success']) !!}
{{ link_to_route('jobs.show', __('app.cancel'), [$job] + request(['page']), ['class' => 'btn btn-default']) }}
</div>
{!! Form::close() !!}
</div>
</div>
</div>
@endif
@endcan
</div>
</div>
@endsection
@ -50,6 +83,7 @@
width: 8px;
height: 8px;
}
ul.pagination { margin-top: 0px }
</style>
@endsection
@ -66,6 +100,11 @@
var ap_weight = e.currentTarget.value;
$('#ap_weight').text(ap_weight);
});
$('#commentModal').modal({
show: true,
backdrop: 'static',
});
})();
</script>
@endsection

2
routes/web.php

@ -1,5 +1,5 @@
<?php
// auth()->loginUsingId(1);
require __DIR__.'/web/pages.php';
require __DIR__.'/web/users.php';
require __DIR__.'/web/references.php';

10
routes/web/projects.php

@ -69,9 +69,6 @@ Route::group(['middleware' => ['auth']], function () {
*/
Route::get('jobs', ['as' => 'jobs.index', 'uses' => 'JobsController@index']);
Route::get('jobs/{job}', ['as' => 'jobs.show', 'uses' => 'JobsController@show']);
});
Route::group(['middleware' => ['auth']], function () {
/*
* Job Actions Routes
@ -81,4 +78,11 @@ Route::group(['middleware' => ['auth']], function () {
Route::get('jobs/{job}/delete', ['as' => 'jobs.delete', 'uses' => 'JobsController@delete']);
Route::delete('jobs/{job}', ['as' => 'jobs.destroy', 'uses' => 'JobsController@destroy']);
Route::post('jobs/{id}/tasks-reorder', ['as' => 'jobs.tasks-reorder', 'uses' => 'JobsController@tasksReorder']);
/*
* Project Comments Routes
*/
Route::post('jobs/{job}/comments', 'Jobs\CommentsController@store')->name('jobs.comments.store');
Route::patch('jobs/{job}/comments/{comment}', 'Jobs\CommentsController@update')->name('jobs.comments.update');
Route::delete('jobs/{job}/comments/{comment}', 'Jobs\CommentsController@destroy')->name('jobs.comments.destroy');
});

104
tests/Feature/Projects/JobCommentsTest.php

@ -0,0 +1,104 @@
<?php
namespace Tests\Feature\Projects;
use Tests\TestCase;
use App\Entities\Projects\Job;
use App\Entities\Projects\Comment;
class JobCommentsTest extends TestCase
{
/** @test */
public function user_can_view_job_comments()
{
$this->adminUserSigningIn();
$job = factory(Job::class)->create();
$comment = factory(Comment::class)->create([
'commentable_type' => 'jobs',
'commentable_id' => $job->id,
'body' => 'This is job comment.',
]);
$this->visitRoute('jobs.show', $job);
$this->seeRouteIs('jobs.show', $job);
$this->seeText('This is job comment.');
}
/** @test */
public function admin_can_add_comment_to_a_job()
{
$admin = $this->adminUserSigningIn();
$job = factory(Job::class)->create();
$this->visitRoute('jobs.show', $job);
$this->submitForm(__('comment.create'), [
'body' => 'Komentar pertama.',
]);
$this->seePageIs(route('jobs.show', $job));
$this->see(__('comment.created'));
$this->seeInDatabase('comments', [
'commentable_type' => 'jobs',
'commentable_id' => $job->id,
'body' => 'Komentar pertama.',
'creator_id' => $admin->id,
]);
}
/** @test */
public function user_can_edit_comment()
{
$this->adminUserSigningIn();
$job = factory(Job::class)->create();
$comment = factory(Comment::class)->create([
'commentable_type' => 'jobs',
'commentable_id' => $job->id,
'body' => 'This is job comment.',
]);
$this->visitRoute('jobs.show', $job);
$this->seeElement('a', ['id' => 'edit-comment-'.$comment->id]);
$this->click('edit-comment-'.$comment->id);
$this->seeRouteIs('jobs.show', [$job, 'action' => 'comment-edit', 'comment_id' => $comment->id]);
$this->submitForm(__('comment.update'), [
'body' => 'Komentar pertama.',
]);
$this->seePageIs(route('jobs.show', $job));
$this->see(__('comment.updated'));
$this->seeInDatabase('comments', [
'id' => $comment->id,
'commentable_type' => 'jobs',
'commentable_id' => $job->id,
'body' => 'Komentar pertama.',
]);
}
/** @test */
public function user_can_delete_comment()
{
$this->adminUserSigningIn();
$job = factory(Job::class)->create();
$comment = factory(Comment::class)->create([
'commentable_type' => 'jobs',
'commentable_id' => $job->id,
'body' => 'This is job comment.',
]);
$this->visitRoute('jobs.show', $job);
$this->seeElement('button', ['id' => 'delete-comment-'.$comment->id]);
$this->press('delete-comment-'.$comment->id);
$this->seePageIs(route('jobs.show', $job));
$this->see(__('comment.deleted'));
$this->dontSeeInDatabase('comments', [
'id' => $comment->id,
]);
}
}

30
tests/Unit/Policies/JobPolicyTest.php

@ -2,8 +2,8 @@
namespace Tests\Unit\Policies;
use Tests\TestCase;
use App\Entities\Projects\Job;
use Tests\TestCase as TestCase;
class JobPolicyTest extends TestCase
{
@ -81,4 +81,32 @@ class JobPolicyTest extends TestCase
$this->assertTrue($admin->can('see-pricings', $job));
$this->assertFalse($worker->can('see-pricings', $job));
}
/** @test */
public function admin_and_worker_view_job_comment_list()
{
$admin = $this->createUser('admin');
$worker = $this->createUser('worker');
$job = factory(Job::class)->create([
'worker_id' => $worker->id,
]);
$this->assertTrue($admin->can('view-comments', $job));
$this->assertTrue($worker->can('view-comments', $job));
}
/** @test */
public function admin_and_job_workers_can_add_comment_to_job()
{
$admin = $this->createUser('admin');
$worker = $this->createUser('worker');
$job = factory(Job::class)->create([
'worker_id' => $worker->id,
]);
$this->assertTrue($admin->can('comment-on', $job));
$this->assertTrue($worker->can('comment-on', $job));
}
}
Loading…
Cancel
Save