diff --git a/app/Http/Controllers/Api/ProjectsController.php b/app/Http/Controllers/Api/ProjectsController.php
index ed7184b..512d4b8 100644
--- a/app/Http/Controllers/Api/ProjectsController.php
+++ b/app/Http/Controllers/Api/ProjectsController.php
@@ -33,7 +33,6 @@ class ProjectsController extends Controller
public function jobs($id)
{
$project = $this->repo->requireById($id);
- // $project->load('jobs.tasks');
$response = fractal()
->item($project->toArray())
->transformWith(function ($project) {
diff --git a/app/Http/Controllers/Jobs/CommentsController.php b/app/Http/Controllers/Jobs/CommentsController.php
new file mode 100644
index 0000000..2fc978b
--- /dev/null
+++ b/app/Http/Controllers/Jobs/CommentsController.php
@@ -0,0 +1,102 @@
+authorize('view-comments', $job);
+
+ $editableComment = null;
+ $comments = $job->comments()->with('creator')->latest()->paginate();
+
+ if (request('action') == 'comment-edit' && request('comment_id') != null) {
+ $editableComment = Comment::find(request('comment_id'));
+ }
+
+ return view('jobs.comments', compact('job', 'comments', 'editableComment'));
+ }
+
+ /**
+ * 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.comments.index', [$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.comments.index', $routeParam);
+ }
+ flash(__('comment.undeleted'), 'error');
+
+ return back();
+ }
+}
diff --git a/app/Http/Controllers/JobsController.php b/app/Http/Controllers/JobsController.php
index f5dbe36..35fbc23 100755
--- a/app/Http/Controllers/JobsController.php
+++ b/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'));
}
/**
diff --git a/app/Policies/Projects/JobPolicy.php b/app/Policies/Projects/JobPolicy.php
index 3806e78..5e27101 100644
--- a/app/Policies/Projects/JobPolicy.php
+++ b/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);
+ }
}
diff --git a/resources/lang/id/comment.php b/resources/lang/id/comment.php
index b20b834..95a1586 100644
--- a/resources/lang/id/comment.php
+++ b/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',
diff --git a/resources/views/jobs/comments.blade.php b/resources/views/jobs/comments.blade.php
new file mode 100755
index 0000000..df0c010
--- /dev/null
+++ b/resources/views/jobs/comments.blade.php
@@ -0,0 +1,54 @@
+@extends('layouts.job')
+
+@section('subtitle', __('comment.list'))
+
+@section('content-job')
+
+
+ {{ $comments->links() }}
+ @include('jobs.partials.comment-section')
+ {{ $comments->links() }}
+
+
+
+@if (Request::get('action') == 'comment-edit' && $editableComment)
+
+@endif
+@endsection
+
+@section('ext_css')
+
+@endsection
+
+@section('script')
+
+@endsection
diff --git a/resources/views/jobs/partials/comment-section.blade.php b/resources/views/jobs/partials/comment-section.blade.php
new file mode 100644
index 0000000..88809c8
--- /dev/null
+++ b/resources/views/jobs/partials/comment-section.blade.php
@@ -0,0 +1,32 @@
+@can('comment-on', $job)
+{{ Form::open(['route' => ['jobs.comments.store', $job]]) }}
+
+
{!! FormField::textarea('body', ['required' => true, 'label' => false, 'placeholder' => __('comment.create_text')]) !!}
+
+ {{ Form::submit(__('comment.create'), ['class' => 'btn btn-success btn-block']) }}
+
+
+{{ Form::close() }}
+@endcan
+@foreach($comments as $comment)
+
+
+
+ @can('update', $comment)
+ {{ link_to_route('jobs.comments.index', __('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' => ''],
+ '×',
+ ['class' => 'btn-link', 'id' => 'delete-comment-'.$comment->id],
+ ['comment_id' => $comment->id, 'page' => request('page')]
+ ) !!}
+ @endcan
+
+ {!! nl2br($comment->body) !!}
+
+@endforeach
diff --git a/resources/views/jobs/partials/job-tasks-operation.blade.php b/resources/views/jobs/partials/job-tasks-operation.blade.php
index 05304f2..4887762 100644
--- a/resources/views/jobs/partials/job-tasks-operation.blade.php
+++ b/resources/views/jobs/partials/job-tasks-operation.blade.php
@@ -1,45 +1,19 @@
-@if (Request::has('action') == false)
-@can('create', new App\Entities\Projects\Task)
-{!! Form::open(['route' => ['tasks.store', $job->id]])!!}
-
-
{{ __('task.create') }}
-
-
-
{!! FormField::text('name', ['label' => __('task.name')]) !!}
-
- {!! Form::label('progress', __('task.progress'), ['class' => 'control-label']) !!}
- {!! Form::input('range', 'progress', 0, [
- 'min' => '0', 'max' => '100', 'step' => '10',
- ]) !!}
-
-
- 0%
-
-
- {!! FormField::textarea('description', ['label' => __('task.description')]) !!}
- {!! Form::submit(__('task.create'), ['class' => 'btn btn-primary']) !!}
- {!! Form::close() !!}
-
-
-@endcan
-@endif
-
@if (Request::get('action') == 'task_edit' && $editableTask)
@can('update', $editableTask)
-{!! Form::model($editableTask, ['route' => ['tasks.update', $editableTask], 'method' => 'patch'])!!}
+{{ Form::model($editableTask, ['route' => ['tasks.update', $editableTask], 'method' => 'patch']) }}
{{ __('task.edit') }}
{!! FormField::text('name') !!}
- {!! Form::label('progress', __('task.progress'), ['class' => 'control-label']) !!}
+ {{ Form::label('progress', __('task.progress'), ['class' => 'control-label']) }}
- {!! Form::input('range', 'progress', null, [
+ {{ Form::input('range', 'progress', null, [
'min' => '0',
'max' => '100',
'step' => '10',
- ]) !!}
+ ]) }}
{{ $editableTask->progress }}%
@@ -50,10 +24,12 @@
{!! FormField::select('job_id', $job->project->jobs->pluck('name', 'id'), ['label' => __('task.move_to_other_job')]) !!}
+
+ {{ Form::submit(__('task.update'), ['class' => 'btn btn-warning']) }}
+ {{ link_to_route('jobs.show', __('app.cancel'), [$job], ['class' => 'btn btn-default']) }}
+
- {!! Form::submit(__('task.update'), ['class' => 'btn btn-warning']) !!}
- {{ link_to_route('jobs.show', __('app.cancel'), [$job], ['class' => 'btn btn-default']) }}
- {!! Form::close() !!}
+ {{ Form::close() }}
@endcan
diff --git a/resources/views/jobs/partials/job-tasks.blade.php b/resources/views/jobs/partials/job-tasks.blade.php
index 222f206..ea906d0 100644
--- a/resources/views/jobs/partials/job-tasks.blade.php
+++ b/resources/views/jobs/partials/job-tasks.blade.php
@@ -80,6 +80,31 @@
@endif
+@if (Request::has('action') == false)
+@can('create', new App\Entities\Projects\Task)
+{{ Form::open(['route' => ['tasks.store', $job->id]]) }}
+
+
{{ __('task.create') }}
+
+
+
{!! FormField::text('name', ['label' => __('task.name')]) !!}
+
+ {{ Form::label('progress', __('task.progress'), ['class' => 'control-label']) }}
+ {{ Form::input('range', 'progress', 0, [
+ 'min' => '0', 'max' => '100', 'step' => '10',
+ ]) }}
+
+
+ 0%
+
+
+ {!! FormField::textarea('description', ['label' => __('task.description')]) !!}
+ {{ Form::submit(__('task.create'), ['class' => 'btn btn-primary']) }}
+ {{ Form::close() }}
+
+
+@endcan
+@endif
@if (request('action') == 'sort_tasks')
@section('ext_js')
diff --git a/resources/views/jobs/partials/nav-tabs.blade.php b/resources/views/jobs/partials/nav-tabs.blade.php
new file mode 100644
index 0000000..e1fb60e
--- /dev/null
+++ b/resources/views/jobs/partials/nav-tabs.blade.php
@@ -0,0 +1,12 @@
+
+
+ -
+ {!! link_to_route('jobs.show', __('job.detail'), $job) !!}
+
+ @can('view-comments', $job)
+
+ @endcan
+
+
diff --git a/resources/views/jobs/show.blade.php b/resources/views/jobs/show.blade.php
index 051d4b2..4ff3eda 100755
--- a/resources/views/jobs/show.blade.php
+++ b/resources/views/jobs/show.blade.php
@@ -1,34 +1,29 @@
-@extends('layouts.app')
+@extends('layouts.job')
-@section('title', __('job.detail') . ' | ' . $job->name . ' | ' . $job->project->name)
+@section('subtitle', __('job.detail'))
-@section('content')
-@include('jobs.partials.breadcrumb')
+@section('action-buttons')
+@can('create', new App\Entities\Projects\Job)
+ {!! html_link_to_route('projects.jobs.create', __('job.create'), [$job->project_id], ['class' => 'btn btn-success','icon' => 'plus']) !!}
+@endcan
+@can('update', $job)
+ {{ link_to_route('jobs.edit', __('job.edit'), [$job], ['class' => 'btn btn-warning']) }}
+@endcan
+@endsection
+@section('content-job')
-
@include('jobs.partials.job-show')
+ @include('jobs.partials.job-dates')
- @include('jobs.partials.job-dates')
@include('jobs.partials.job-tasks-operation')
+ @include('jobs.partials.job-tasks')
- @include('jobs.partials.job-tasks')
@endsection
@@ -50,6 +45,7 @@
width: 8px;
height: 8px;
}
+ ul.pagination { margin-top: 0px }
@endsection
@@ -66,6 +62,11 @@
var ap_weight = e.currentTarget.value;
$('#ap_weight').text(ap_weight);
});
+
+ $('#commentModal').modal({
+ show: true,
+ backdrop: 'static',
+ });
})();
@endsection
diff --git a/resources/views/jobs/unfinished.blade.php b/resources/views/jobs/unfinished.blade.php
index 498ca0a..74dfcae 100755
--- a/resources/views/jobs/unfinished.blade.php
+++ b/resources/views/jobs/unfinished.blade.php
@@ -6,7 +6,7 @@
- {{ __('job.on_progress') }}
-
+
{{ Form::open(['method' => 'get', 'class' => 'form-inline']) }}
{!! FormField::select('project_id', $projects, ['label' => __('project.select'), 'placeholder' => __('project.all')]) !!}
diff --git a/resources/views/layouts/job.blade.php b/resources/views/layouts/job.blade.php
new file mode 100755
index 0000000..302dc99
--- /dev/null
+++ b/resources/views/layouts/job.blade.php
@@ -0,0 +1,22 @@
+@extends('layouts.app')
+
+@section('title')
+@yield('subtitle', __('job.detail')) - {{ $job->name }}
+@endsection
+
+@section('content')
+@include('jobs.partials.breadcrumb')
+
+
+
+@include('jobs.partials.nav-tabs')
+
+@yield('content-job')
+
+@endsection
diff --git a/resources/views/projects/jobs/add-from-other-project.blade.php b/resources/views/projects/jobs/add-from-other-project.blade.php
index 94293a4..63a85b8 100755
--- a/resources/views/projects/jobs/add-from-other-project.blade.php
+++ b/resources/views/projects/jobs/add-from-other-project.blade.php
@@ -4,8 +4,8 @@
@section('action-buttons')
@can('create', new App\Entities\Projects\Job)
- {!! html_link_to_route('projects.jobs.create', trans('job.create'), [$project->id], ['class' => 'btn btn-success','icon' => 'plus']) !!}
- {!! html_link_to_route('projects.jobs.add-from-other-project', trans('job.add_from_other_project'), [$project->id], ['class' => 'btn btn-default','icon' => 'plus']) !!}
+ {!! html_link_to_route('projects.jobs.create', __('job.create'), [$project->id], ['class' => 'btn btn-success','icon' => 'plus']) !!}
+ {!! html_link_to_route('projects.jobs.add-from-other-project', __('job.add_from_other_project'), [$project->id], ['class' => 'btn btn-default','icon' => 'plus']) !!}
@endcan
@endsection
@@ -21,18 +21,18 @@
{{ Form::submit(__('project.show_jobs'), ['class' => 'btn btn-default btn-sm']) }}
{{ Form::close() }}
@if ($selectedProject)
- {!! Form::open(['route' => ['projects.jobs.store-from-other-project', $project->id]]) !!}
+ {{ Form::open(['route' => ['projects.jobs.store-from-other-project', $project->id]]) }}
@forelse($selectedProject->jobs as $key => $job)
-