Browse Source

Merge branch 'project-issue-priority' into project-issue

pull/37/head
Nafies Luthfi 7 years ago
parent
commit
ed2ae6e0cb
  1. 16
      app/Entities/Projects/Issue.php
  2. 35
      app/Entities/Projects/Priority.php
  3. 2
      app/Http/Controllers/Issues/OptionController.php
  4. 13
      app/Http/Controllers/Projects/IssueController.php
  5. 1
      database/factories/IssueFactory.php
  6. 1
      database/migrations/2019_03_03_210017_create_issues_table.php
  7. 5
      resources/lang/de/issue.php
  8. 6
      resources/lang/en/issue.php
  9. 5
      resources/lang/id/issue.php
  10. 1
      resources/views/projects/issues/create.blade.php
  11. 2
      resources/views/projects/issues/index.blade.php
  12. 3
      resources/views/projects/issues/show.blade.php
  13. 26
      tests/Feature/Projects/ProjectIssuesTest.php
  14. 18
      tests/Unit/Models/IssueTest.php

16
app/Entities/Projects/Issue.php

@ -8,7 +8,9 @@ use Illuminate\Database\Eloquent\Model;
class Issue extends Model class Issue extends Model
{ {
protected $fillable = ['project_id', 'title', 'body', 'pic_id', 'creator_id'];
protected $fillable = [
'project_id', 'title', 'body', 'priority_id', 'pic_id', 'creator_id',
];
public function project() public function project()
{ {
@ -25,6 +27,18 @@ class Issue extends Model
return $this->belongsTo(User::class); return $this->belongsTo(User::class);
} }
public function getPriorityAttribute()
{
return Priority::getNameById($this->priority_id);
}
public function getPriorityLabelAttribute()
{
$classColor = Priority::getColorById($this->priority_id);
return '<span class="label label-'.$classColor.'">'.$this->priority.'</span>';
}
public function getStatusAttribute() public function getStatusAttribute()
{ {
return IssueStatus::getNameById($this->status_id); return IssueStatus::getNameById($this->status_id);

35
app/Entities/Projects/Priority.php

@ -0,0 +1,35 @@
<?php
namespace App\Entities\Projects;
use App\Entities\ReferenceAbstract;
class Priority extends ReferenceAbstract
{
protected static $lists = [
1 => 'minor',
2 => 'major',
3 => 'critical',
];
protected static $colors = [
1 => 'info',
2 => 'warning',
3 => 'danger',
];
public static function getNameById($singleId)
{
return trans('issue.'.static::getById($singleId));
}
public static function toArray()
{
$lists = [];
foreach (static::$lists as $key => $value) {
$lists[$key] = trans('issue.'.$value);
}
return $lists;
}
}

2
app/Http/Controllers/Issues/OptionController.php

@ -11,9 +11,11 @@ class OptionController extends Controller
public function update(Request $request, Issue $issue) public function update(Request $request, Issue $issue)
{ {
$issueData = $request->validate([ $issueData = $request->validate([
'priority_id' => 'required|in:1,2,3',
'status_id' => 'required|in:0,1,2,3,4', 'status_id' => 'required|in:0,1,2,3,4',
'pic_id' => 'nullable|exists:users,id', 'pic_id' => 'nullable|exists:users,id',
]); ]);
$issue->priority_id = $issueData['priority_id'];
$issue->status_id = $issueData['status_id']; $issue->status_id = $issueData['status_id'];
$issue->pic_id = $issueData['pic_id']; $issue->pic_id = $issueData['pic_id'];
$issue->save(); $issue->save();

13
app/Http/Controllers/Projects/IssueController.php

@ -6,6 +6,7 @@ use App\Entities\Users\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Entities\Projects\Issue; use App\Entities\Projects\Issue;
use App\Entities\Projects\Project; use App\Entities\Projects\Project;
use App\Entities\Projects\Priority;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Entities\Projects\IssueStatus; use App\Entities\Projects\IssueStatus;
@ -15,14 +16,15 @@ class IssueController extends Controller
{ {
$issues = $project->issues()->with(['pic', 'creator'])->get(); $issues = $project->issues()->with(['pic', 'creator'])->get();
return view('projects.issues', compact('project', 'issues'));
return view('projects.issues.index', compact('project', 'issues'));
} }
public function create(Project $project) public function create(Project $project)
{ {
$users = User::pluck('name', 'id'); $users = User::pluck('name', 'id');
$priorities = Priority::toArray();
return view('projects.issues.create', compact('project', 'users'));
return view('projects.issues.create', compact('project', 'users', 'priorities'));
} }
public function store(Request $request, Project $project) public function store(Request $request, Project $project)
@ -30,6 +32,7 @@ class IssueController extends Controller
$issueData = $request->validate([ $issueData = $request->validate([
'title' => 'required|max:60', 'title' => 'required|max:60',
'body' => 'required|max:255', 'body' => 'required|max:255',
'priority_id' => 'required|in:1,2,3',
'pic_id' => 'nullable|exists:users,id', 'pic_id' => 'nullable|exists:users,id',
]); ]);
Issue::create([ Issue::create([
@ -37,6 +40,7 @@ class IssueController extends Controller
'creator_id' => auth()->id(), 'creator_id' => auth()->id(),
'title' => $issueData['title'], 'title' => $issueData['title'],
'body' => $issueData['body'], 'body' => $issueData['body'],
'priority_id' => $issueData['priority_id'],
'pic_id' => $issueData['pic_id'], 'pic_id' => $issueData['pic_id'],
]); ]);
flash(__('issue.created'), 'success'); flash(__('issue.created'), 'success');
@ -46,10 +50,13 @@ class IssueController extends Controller
public function show(Project $project, Issue $issue) public function show(Project $project, Issue $issue)
{ {
$priorities = Priority::toArray();
$statuses = IssueStatus::toArray(); $statuses = IssueStatus::toArray();
$users = User::pluck('name', 'id'); $users = User::pluck('name', 'id');
return view('projects.issues.show', compact('project', 'issue', 'users', 'statuses'));
return view('projects.issues.show', compact(
'project', 'issue', 'users', 'statuses', 'priorities'
));
} }
public function edit(Project $project, Issue $issue) public function edit(Project $project, Issue $issue)

1
database/factories/IssueFactory.php

@ -16,5 +16,6 @@ $factory->define(Issue::class, function (Faker $faker) {
return factory(User::class)->create()->id; return factory(User::class)->create()->id;
}, },
'status_id' => 0, 'status_id' => 0,
'priority_id' => 1,
]; ];
}); });

1
database/migrations/2019_03_03_210017_create_issues_table.php

@ -19,6 +19,7 @@ class CreateIssuesTable extends Migration
$table->string('title', 60); $table->string('title', 60);
$table->string('body'); $table->string('body');
$table->unsignedInteger('creator_id'); $table->unsignedInteger('creator_id');
$table->unsignedTinyInteger('priority_id');
$table->unsignedInteger('pic_id')->nullable(); $table->unsignedInteger('pic_id')->nullable();
$table->unsignedTinyInteger('status_id')->default(0); $table->unsignedTinyInteger('status_id')->default(0);
$table->timestamps(); $table->timestamps();

5
resources/lang/de/issue.php

@ -41,6 +41,11 @@ return [
'pic' => 'Issue PIC', 'pic' => 'Issue PIC',
'creator' => 'Issue Creator', 'creator' => 'Issue Creator',
// Priority
'minor' => 'Minor',
'major' => 'Major',
'critical' => 'Critical',
// Statuses // Statuses
'open' => 'Open', 'open' => 'Open',
'resolved' => 'Resolved', 'resolved' => 'Resolved',

6
resources/lang/en/issue.php

@ -41,6 +41,12 @@ return [
'pic' => 'Issue PIC', 'pic' => 'Issue PIC',
'creator' => 'Issue Creator', 'creator' => 'Issue Creator',
// Priority
'priority' => 'Priority',
'minor' => 'Minor',
'major' => 'Major',
'critical' => 'Critical',
// Statuses // Statuses
'open' => 'Open', 'open' => 'Open',
'resolved' => 'Resolved', 'resolved' => 'Resolved',

5
resources/lang/id/issue.php

@ -41,6 +41,11 @@ return [
'pic' => 'PIC Issue', 'pic' => 'PIC Issue',
'creator' => 'Pembuat Issue', 'creator' => 'Pembuat Issue',
// Priority
'minor' => 'Minor',
'major' => 'Major',
'critical' => 'Critical',
// Statuses // Statuses
'open' => 'Open', 'open' => 'Open',
'resolved' => 'Selesai', 'resolved' => 'Selesai',

1
resources/views/projects/issues/create.blade.php

@ -18,6 +18,7 @@
<div class="panel-body"> <div class="panel-body">
{!! FormField::text('title', ['label' => __('issue.title')]) !!} {!! FormField::text('title', ['label' => __('issue.title')]) !!}
{!! FormField::textarea('body', ['label' => __('issue.body')]) !!} {!! FormField::textarea('body', ['label' => __('issue.body')]) !!}
{!! FormField::radios('priority_id', $priorities, ['label' => __('issue.priority'), 'placeholder' => false]) !!}
{!! FormField::select('pic_id', $users, ['label' => __('issue.pic')]) !!} {!! FormField::select('pic_id', $users, ['label' => __('issue.pic')]) !!}
</div> </div>
<div class="panel-footer"> <div class="panel-footer">

2
resources/views/projects/issues.blade.php → resources/views/projects/issues/index.blade.php

@ -17,6 +17,7 @@
<thead> <thead>
<th>{{ __('app.table_no') }}</th> <th>{{ __('app.table_no') }}</th>
<th>{{ __('issue.title') }}</th> <th>{{ __('issue.title') }}</th>
<th>{{ __('issue.priority') }}</th>
<th>{{ __('app.status') }}</th> <th>{{ __('app.status') }}</th>
<th>{{ __('issue.pic') }}</th> <th>{{ __('issue.pic') }}</th>
<th>{{ __('issue.creator') }}</th> <th>{{ __('issue.creator') }}</th>
@ -30,6 +31,7 @@
<tr id="{{ $issue->id }}"> <tr id="{{ $issue->id }}">
<td>{{ $no }}</td> <td>{{ $no }}</td>
<td>{{ $issue->title }}</td> <td>{{ $issue->title }}</td>
<td>{!! $issue->priority_label !!}</td>
<td>{!! $issue->status_label !!}</td> <td>{!! $issue->status_label !!}</td>
<td>{{ $issue->pic->name }}</td> <td>{{ $issue->pic->name }}</td>
<td>{{ $issue->creator->name }}</td> <td>{{ $issue->creator->name }}</td>

3
resources/views/projects/issues/show.blade.php

@ -22,12 +22,14 @@
<tbody> <tbody>
<tr><th class="col-md-4">{{ __('issue.title') }}</th><td class="col-md-8">{{ $issue->title }}</td></tr> <tr><th class="col-md-4">{{ __('issue.title') }}</th><td class="col-md-8">{{ $issue->title }}</td></tr>
<tr><th>{{ __('issue.body') }}</th><td>{{ $issue->body }}</td></tr> <tr><th>{{ __('issue.body') }}</th><td>{{ $issue->body }}</td></tr>
<tr><th>{{ __('issue.priority') }}</th><td>{!! $issue->priority_label !!}</td></tr>
<tr><th>{{ __('issue.pic') }}</th><td>{{ $issue->pic->name }}</td></tr> <tr><th>{{ __('issue.pic') }}</th><td>{{ $issue->pic->name }}</td></tr>
<tr><th>{{ __('app.created_by') }}</th><td>{{ $issue->creator->name }}</td></tr> <tr><th>{{ __('app.created_by') }}</th><td>{{ $issue->creator->name }}</td></tr>
</tbody> </tbody>
</table> </table>
<div class="panel-footer"> <div class="panel-footer">
{{ link_to_route('projects.issues.edit', __('issue.edit'), [$project, $issue], ['id' => 'edit-issue-'.$issue->id, 'class' => 'btn btn-warning']) }} {{ link_to_route('projects.issues.edit', __('issue.edit'), [$project, $issue], ['id' => 'edit-issue-'.$issue->id, 'class' => 'btn btn-warning']) }}
{{ link_to_route('projects.issues.index', __('issue.back_to_index'), [$project], ['class' => 'btn btn-default pull-right']) }}
</div> </div>
</div> </div>
</div> </div>
@ -36,6 +38,7 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">{{ __('app.action') }}</h3></div> <div class="panel-heading"><h3 class="panel-title">{{ __('app.action') }}</h3></div>
<div class="panel-body"> <div class="panel-body">
{!! FormField::radios('priority_id', $priorities, ['label' => __('issue.priority')]) !!}
{!! FormField::radios('status_id', $statuses, ['label' => __('app.status')]) !!} {!! FormField::radios('status_id', $statuses, ['label' => __('app.status')]) !!}
{!! FormField::select('pic_id', $users, ['label' => __('issue.assign_pic'), 'placeholder' => __('issue.select_pic')]) !!} {!! FormField::select('pic_id', $users, ['label' => __('issue.assign_pic'), 'placeholder' => __('issue.select_pic')]) !!}
</div> </div>

26
tests/Feature/Projects/ProjectIssuesTest.php

@ -39,6 +39,7 @@ class ProjectIssuesTest extends TestCase
$this->submitForm(__('issue.create'), [ $this->submitForm(__('issue.create'), [
'title' => 'First Issue.', 'title' => 'First Issue.',
'body' => 'First Issue description.', 'body' => 'First Issue description.',
'priority_id' => 1,
'pic_id' => $admin->id, 'pic_id' => $admin->id,
]); ]);
@ -49,6 +50,7 @@ class ProjectIssuesTest extends TestCase
'project_id' => $project->id, 'project_id' => $project->id,
'title' => 'First Issue.', 'title' => 'First Issue.',
'body' => 'First Issue description.', 'body' => 'First Issue description.',
'priority_id' => 1,
'pic_id' => $admin->id, 'pic_id' => $admin->id,
'creator_id' => $admin->id, 'creator_id' => $admin->id,
]); ]);
@ -190,4 +192,28 @@ class ProjectIssuesTest extends TestCase
'status_id' => 2, // resolved 'status_id' => 2, // resolved
]); ]);
} }
/** @test */
public function user_can_change_issue_priority()
{
$this->adminUserSigningIn();
$worker = $this->createUser('worker');
$issue = factory(Issue::class)->create();
$this->visitRoute('projects.issues.show', [$issue->project, $issue]);
$this->submitForm(__('issue.update'), [
'priority_id' => 2, // major
'status_id' => 2, // resolved
'pic_id' => $worker->id,
]);
$this->seeRouteIs('projects.issues.show', [$issue->project, $issue]);
$this->seeText(__('issue.updated'));
$this->seeInDatabase('issues', [
'id' => $issue->id,
'pic_id' => $worker->id,
'priority_id' => 2, // major
'status_id' => 2, // resolved
]);
}
} }

18
tests/Unit/Models/IssueTest.php

@ -6,6 +6,7 @@ use Tests\TestCase;
use App\Entities\Users\User; use App\Entities\Users\User;
use App\Entities\Projects\Issue; use App\Entities\Projects\Issue;
use App\Entities\Projects\Project; use App\Entities\Projects\Project;
use App\Entities\Projects\Priority;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
class IssueTest extends TestCase class IssueTest extends TestCase
@ -63,4 +64,21 @@ class IssueTest extends TestCase
$this->assertEquals('<span class="badge">'.$issue->status.'</span>', $issue->status_label); $this->assertEquals('<span class="badge">'.$issue->status.'</span>', $issue->status_label);
} }
/** @test */
public function an_issue_has_priority_attribute()
{
$issue = factory(Issue::class)->make();
$this->assertEquals(__('issue.minor'), $issue->priority);
}
/** @test */
public function an_issue_has_priority_label_attribute()
{
$issue = factory(Issue::class)->make();
$colorClass = Priority::getColorById($issue->priority_id);
$this->assertEquals('<span class="label label-'.$colorClass.'">'.$issue->priority.'</span>', $issue->priority_label);
}
} }
Loading…
Cancel
Save