From b960a687d8fb40d6725b23a76a3bf5323f0305f2 Mon Sep 17 00:00:00 2001 From: Farhan Kathawala <37834439+farhaninfyom@users.noreply.github.com> Date: Tue, 10 Sep 2019 17:57:17 +0530 Subject: [PATCH 01/23] docs: add doc for deleted by property (#346) --- app/Models/ActivityType.php | 6 +++++- app/Models/Client.php | 20 +++++++++++--------- app/Models/Project.php | 2 ++ app/Models/Tag.php | 1 + app/Models/User.php | 17 +++++++++-------- 5 files changed, 28 insertions(+), 18 deletions(-) diff --git a/app/Models/ActivityType.php b/app/Models/ActivityType.php index 61eeca2c8..a2a7893a8 100644 --- a/app/Models/ActivityType.php +++ b/app/Models/ActivityType.php @@ -11,6 +11,7 @@ * @property int $id * @property string $name * @property int|null $created_by + * @property int $deleted_by * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property-read \App\Models\User|null $createdUser @@ -31,7 +32,9 @@ class ActivityType extends Model public $table = 'activity_types'; public $fillable = [ - 'name', 'created_by', 'deleted_by', + 'name', + 'created_by', + 'deleted_by', ]; /** @@ -43,6 +46,7 @@ class ActivityType extends Model 'id' => 'integer', 'name' => 'string', 'created_by' => 'integer', + 'deleted_by' => 'integer', ]; const ACTIVITY_TYPES = [ diff --git a/app/Models/Client.php b/app/Models/Client.php index 06b129831..4ffbb200c 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -12,6 +12,7 @@ * @property string $name * @property string $email * @property string $website + * @property int $deleted_by * @property int|null $created_by * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at @@ -48,10 +49,11 @@ class Client extends Model * @var array */ protected $casts = [ - 'id' => 'integer', - 'name' => 'string', - 'email' => 'string', - 'website' => 'string', + 'id' => 'integer', + 'name' => 'string', + 'email' => 'string', + 'website' => 'string', + 'deleted_by' => 'integer', ]; /** @@ -60,14 +62,14 @@ class Client extends Model * @var array */ public static $rules = [ - 'name' => 'required|unique:clients,name', - 'email' => 'nullable|email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', - 'website' => 'nullable|regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/', + 'name' => 'required|unique:clients,name', + 'email' => 'nullable|email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', + 'website' => 'nullable|regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/', ]; public static $editRules = [ - 'email' => 'nullable|email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', - 'website' => 'nullable|regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/', + 'email' => 'nullable|email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', + 'website' => 'nullable|regex:/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/', ]; public static $messages = [ diff --git a/app/Models/Project.php b/app/Models/Project.php index bf2ea001a..b6e062427 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -18,6 +18,7 @@ * @property-read \App\Models\Client|null $client * @property-read \App\Models\User|null $createdUser * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\User[] $users + * @property int $deleted_by * * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Project newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\Project newQuery() @@ -64,6 +65,7 @@ class Project extends Model 'description' => 'string', 'client_id' => 'integer', 'created_by' => 'integer', + 'deleted_by' => 'integer', ]; /** diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 48421f835..8bd9d9d41 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -11,6 +11,7 @@ * @property int $id * @property string $name * @property int|null $created_by + * @property int $deleted_by * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property-read \App\Models\User|null $createdUser diff --git a/app/Models/User.php b/app/Models/User.php index 24b5d7922..1ee92b9d8 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -24,6 +24,7 @@ * @property string|null $activation_code * @property int|null $created_by * @property string|null $remember_token + * @property int $deleted_by * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @property-read \App\Models\User|null $createdUser @@ -120,17 +121,17 @@ class User extends Authenticatable * @var array */ public static $rules = [ - 'name' => 'required|unique:users,name', - 'email' => 'required|email|unique:users,email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', - 'phone' => 'nullable|numeric|digits:10', - 'role_id' => 'required', + 'name' => 'required|unique:users,name', + 'email' => 'required|email|unique:users,email|regex:/^[\w\-\.\+]+\@[a-zA-Z0-9\.\-]+\.[a-zA-z0-9]{2,4}$/', + 'phone' => 'nullable|numeric|digits:10', + 'role_id' => 'required', ]; public static $messages = [ - 'phone.digits' => 'The phone number must be 10 digits long.', - 'email.regex' => 'Please enter valid email.', - 'photo.mimes' => 'The profile image must be a file of type: jpeg, jpg, png.', - 'role_id.required' => 'Please select user role.', + 'phone.digits' => 'The phone number must be 10 digits long.', + 'email.regex' => 'Please enter valid email.', + 'photo.mimes' => 'The profile image must be a file of type: jpeg, jpg, png.', + 'role_id.required' => 'Please select user role.', ]; public static $setPasswordRules = [ From 0ea87d86648936d35122fef8ca94eb6de412d54d Mon Sep 17 00:00:00 2001 From: Farhan Kathawala <37834439+farhaninfyom@users.noreply.github.com> Date: Tue, 10 Sep 2019 17:59:05 +0530 Subject: [PATCH 02/23] test(time-entry): test case for time entry (#349) --- tests/Controllers/TimeEntryControllerTest.php | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/Controllers/TimeEntryControllerTest.php b/tests/Controllers/TimeEntryControllerTest.php index 3b0aab799..80ef68588 100644 --- a/tests/Controllers/TimeEntryControllerTest.php +++ b/tests/Controllers/TimeEntryControllerTest.php @@ -4,6 +4,7 @@ use App\Models\Task; use App\Models\TimeEntry; +use App\Models\User; use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\TestCase; use Tests\Traits\MockRepositories; @@ -39,7 +40,7 @@ public function test_can_filter_time_entries_by_activity_type() } /** @test */ - public function test_can_filter_time_entries_by_project() + public function test_can_filter_time_entries_by_project_with_permission() { $this->withHeaders(['X-Requested-With' => 'XMLHttpRequest']); @@ -65,6 +66,36 @@ public function test_can_filter_time_entries_by_project() $this->assertEquals($task->project_id, $data[0]['task']['project_id']); } + /** @test */ + public function test_can_filter_time_entries_by_project() + { + $this->withHeaders(['X-Requested-With' => 'XMLHttpRequest']); + + $user = factory(User::class)->create(); + $this->actingAs($user); + + /** @var Task $task */ + $task = factory(Task::class)->create(); + $task->taskAssignee()->sync([$user->id]); + + /** @var TimeEntry $firstTimeEntry */ + $firstTimeEntry = factory(TimeEntry::class)->create([ + 'task_id' => $task->id, + 'user_id' => $user->id, + ]); + $secondTimeEntry = factory(TimeEntry::class)->create(); + + $response = $this->getJson(route('time-entries.index', [ + 'filter_project' => $task->project_id, + ])); + + $data = $response->original['data']; + $this->assertCount(1, $data); + $this->assertEquals($firstTimeEntry->id, $data[0]['id']); + $this->assertEquals($task->project_id, $data[0]['task']['project_id']); + $this->assertEquals($user->id, $data[0]['user_id']); + } + /** @test */ public function test_can_filter_time_entries_by_user() { From 49c8ecf40bff65a8084076387f8e7652a5a5132c Mon Sep 17 00:00:00 2001 From: Farhan Kathawala <37834439+farhaninfyom@users.noreply.github.com> Date: Tue, 10 Sep 2019 18:53:53 +0530 Subject: [PATCH 03/23] test: test cases for latest merged PRs (#351) --- app/Repositories/ClientRepository.php | 1 + app/Repositories/ProjectRepository.php | 1 + tests/Controllers/ClientControllerTest.php | 43 +++++--------------- tests/Controllers/ProjectControllerTest.php | 24 +++-------- tests/Repositories/ClientRepositoryTest.php | 29 +++++++++++++ tests/Repositories/ProjectRepositoryTest.php | 21 ++++++++++ 6 files changed, 67 insertions(+), 52 deletions(-) diff --git a/app/Repositories/ClientRepository.php b/app/Repositories/ClientRepository.php index daf80dd19..8f0f70977 100644 --- a/app/Repositories/ClientRepository.php +++ b/app/Repositories/ClientRepository.php @@ -60,6 +60,7 @@ public function getClientList() */ public function delete($clientId) { + /** @var Client $client */ $client = $this->find($clientId); $projectIds = Project::where('client_id', '=', $client->id)->get()->pluck('id'); diff --git a/app/Repositories/ProjectRepository.php b/app/Repositories/ProjectRepository.php index f55207124..cfe83c0a8 100644 --- a/app/Repositories/ProjectRepository.php +++ b/app/Repositories/ProjectRepository.php @@ -100,6 +100,7 @@ public function getProjectsList($clientId = null) */ public function delete($id) { + /** @var Project $project */ $project = $this->find($id); $taskIds = Task::whereProjectId($project->id)->pluck('id')->toArray(); diff --git a/tests/Controllers/ClientControllerTest.php b/tests/Controllers/ClientControllerTest.php index 06bb36928..aec5ad498 100644 --- a/tests/Controllers/ClientControllerTest.php +++ b/tests/Controllers/ClientControllerTest.php @@ -83,20 +83,18 @@ public function it_can_update_client() } /** @test */ - public function it_can_delete_client() + public function test_can_delete_client_with_all_its_child_records() { - /** @var Client $client */ - $client = factory(Client::class)->create(); - $project = factory(Project::class)->create(['client_id' => $client->id]); + /** @var Project $project */ + $project = factory(Project::class)->create(); $task = factory(Task::class)->create(['project_id' => $project->id]); $timeEntry = factory(TimeEntry::class)->create(['task_id' => $task->id]); - $response = $this->deleteJson(route('clients.destroy', $client->id)); + $response = $this->deleteJson(route('clients.destroy', $project->client_id)); $this->assertSuccessMessageResponse($response, 'Client deleted successfully.'); - //testing client deleted or not. - $response = $this->getJson(route('clients.edit', $client->id)); + $response = $this->getJson(route('clients.edit', $project->client_id)); $response->assertStatus(404); $response->assertJson([ @@ -104,32 +102,11 @@ public function it_can_delete_client() 'message' => 'Client not found.', ]); - //testing project deleted or not. - $response = $this->getJson(route('projects.edit', $project->id)); - - $response->assertStatus(404); - $response->assertJson([ - 'success' => false, - 'message' => 'Project not found.', - ]); - - //testing task deleted or not. - $response = $this->getJson(route('tasks.edit', $task->id)); - - $response->assertStatus(404); - $response->assertJson([ - 'success' => false, - 'message' => 'Task not found.', - ]); - - //testing timeEntry deleted or not. - $response = $this->getJson(route('time-entries.edit', $timeEntry->id)); - - $response->assertStatus(404); - $response->assertJson([ - 'success' => false, - 'message' => 'TimeEntry not found.', - ]); + $this->assertEmpty(Project::whereClientId($project->client_id)->first()); + $task = Task::withTrashed()->find($task->id); + $this->assertEquals($this->loggedInUserId, $task->deleted_by); + $timeEntry = TimeEntry::withTrashed()->find($timeEntry->id); + $this->assertEquals($this->loggedInUserId, $timeEntry->deleted_by); } /** @test */ diff --git a/tests/Controllers/ProjectControllerTest.php b/tests/Controllers/ProjectControllerTest.php index 192b78b3e..80c8c6213 100644 --- a/tests/Controllers/ProjectControllerTest.php +++ b/tests/Controllers/ProjectControllerTest.php @@ -82,7 +82,7 @@ public function it_can_retrieve_project() } /** @test */ - public function test_can_delete_project() + public function test_can_delete_project_with_all_its_child_records() { /** @var Project $project */ $project = factory(Project::class)->create(); @@ -93,7 +93,6 @@ public function test_can_delete_project() $this->assertSuccessMessageResponse($response, 'Project deleted successfully.'); - //testing project deleted or not. $response = $this->getJson(route('projects.edit', $project->id)); $response->assertStatus(404); @@ -102,23 +101,10 @@ public function test_can_delete_project() 'message' => 'Project not found.', ]); - //testing task deleted or not. - $response = $this->getJson(route('tasks.edit', $task->id)); - - $response->assertStatus(404); - $response->assertJson([ - 'success' => false, - 'message' => 'Task not found.', - ]); - - //testing timeEntry deleted or not. - $response = $this->getJson(route('time-entries.edit', $timeEntry->id)); - - $response->assertStatus(404); - $response->assertJson([ - 'success' => false, - 'message' => 'TimeEntry not found.', - ]); + $task = Task::withTrashed()->find($task->id); + $this->assertEquals($this->loggedInUserId, $task->deleted_by); + $timeEntry = TimeEntry::withTrashed()->find($timeEntry->id); + $this->assertEquals($this->loggedInUserId, $timeEntry->deleted_by); } /** @test */ diff --git a/tests/Repositories/ClientRepositoryTest.php b/tests/Repositories/ClientRepositoryTest.php index 9a439c305..d13438158 100644 --- a/tests/Repositories/ClientRepositoryTest.php +++ b/tests/Repositories/ClientRepositoryTest.php @@ -3,6 +3,9 @@ namespace Tests\Repositories; use App\Models\Client; +use App\Models\Project; +use App\Models\Task; +use App\Models\TimeEntry; use App\Repositories\ClientRepository; use Illuminate\Foundation\Testing\DatabaseTransactions; use Tests\TestCase; @@ -36,4 +39,30 @@ public function it_can_retrieve_clients_list() $this->assertContains($client, $clients); }); } + + /** @test */ + public function test_can_delete_client_with_all_its_child_records() + { + /** @var Client $client */ + $client = factory(Client::class)->create(); + + $projects = factory(Project::class)->times(2)->create(['client_id' => $client->id]); + + /** @var Task $firstTask */ + $firstTask = factory(Task::class)->create(['project_id' => $projects[0]->id]); + $secondTask = factory(Task::class)->create(['project_id' => $projects[1]->id]); + + $timeEntry = factory(TimeEntry::class)->create(['task_id' => $firstTask->id]); + + $this->clientRepo->delete($client->id); + + $this->assertEmpty(Client::find($client->id)); + $this->assertEmpty(Project::whereClientId($client->id)->first()); + + $task = Task::withTrashed()->find($firstTask->id); + $this->assertEquals($this->loggedInUserId, $task->deleted_by); + + $timeEntry = TimeEntry::withTrashed()->find($timeEntry->id); + $this->assertEquals($this->loggedInUserId, $timeEntry->deleted_by); + } } diff --git a/tests/Repositories/ProjectRepositoryTest.php b/tests/Repositories/ProjectRepositoryTest.php index 45720589e..46e89c235 100644 --- a/tests/Repositories/ProjectRepositoryTest.php +++ b/tests/Repositories/ProjectRepositoryTest.php @@ -4,6 +4,8 @@ use App\Models\Client; use App\Models\Project; +use App\Models\Task; +use App\Models\TimeEntry; use App\Models\User; use App\Repositories\ProjectRepository; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -120,4 +122,23 @@ public function it_can_retrieve_assigned_projects_list_array_of_logged_in_user() $this->assertCount(1, $allProjects); $this->assertContains($projectOfLoggedInUser->id, array_keys($allProjects)); } + + /** @test */ + public function test_can_delete_project_with_all_its_child_records() + { + $project = factory(Project::class)->create(); + /** @var Task $firstTask */ + $firstTask = factory(Task::class)->create(['project_id' => $project->id]); + $secondTask = factory(Task::class)->create(['project_id' => $project->id]); + $timeEntry = factory(TimeEntry::class)->create(['task_id' => $firstTask->id]); + + $this->projectRepo->delete($firstTask->project_id); + + $this->assertEmpty(Project::find($project->id)); + $task = Task::withTrashed()->find($firstTask->id); + $this->assertEquals($this->loggedInUserId, $task->deleted_by); + + $timeEntry = TimeEntry::withTrashed()->find($timeEntry->id); + $this->assertEquals($this->loggedInUserId, $timeEntry->deleted_by); + } } From 2f67a19a01d11a5633d3ea198c6195b919ea81f5 Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 14:33:38 +0530 Subject: [PATCH 04/23] fix(time-entry): in time entry table - duration format change,, notes as collapsible field, removed created at field (#353) --- resources/assets/js/custom.js | 32 ++++++++ resources/assets/js/task/task.js | 6 -- resources/assets/js/task/task_time_entry.js | 14 ++-- .../assets/js/time_entries/time_entry.js | 74 +++++++++++-------- .../views/tasks/time_tracking_modal.blade.php | 2 +- resources/views/time_entries/table.blade.php | 3 +- 6 files changed, 83 insertions(+), 48 deletions(-) diff --git a/resources/assets/js/custom.js b/resources/assets/js/custom.js index c39c18dea..a3405368a 100644 --- a/resources/assets/js/custom.js +++ b/resources/assets/js/custom.js @@ -229,3 +229,35 @@ $(function () { },150); }); }); + +window.roundToQuarterHourAll = function (minuts) { + var hours = Math.floor(minuts / 60); + var minutes = minuts % 60; + if (hours > 0) { + return pad(hours) + ":" + pad(minutes) + ' h'; + } else { + return pad(hours) + ":" + pad(minutes) + ' m'; + } +}; + +window.pad = function (d) { + return (d < 10) ? '0' + d : d; +}; + +window.nl2br = function (str, is_xhtml) { + if (typeof str === 'undefined' || str === null) { + return ''; + } + var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
'; + return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); +}; + +$(document).on('click', '.collapse-icon', function () { + let isShow = $(this).parent().parent().hasClass('shown'); + if (isShow) { + $(this).children().removeClass('fa-plus-circle').addClass("fa-minus-circle"); + } else { + $(this).children().removeClass('fa-minus-circle').addClass("fa-plus-circle"); + } +}); + diff --git a/resources/assets/js/task/task.js b/resources/assets/js/task/task.js index 79bfafb4c..6e2da1c1a 100644 --- a/resources/assets/js/task/task.js +++ b/resources/assets/js/task/task.js @@ -79,12 +79,6 @@ $(function () { $('[data-toggle="tooltip"]').tooltip(); }); -function getRandomColor() { - let num = Math.floor(Math.random() * 12) + 1; - let coloCodes = ['0095ff', '9594fe', 'da4342', '8e751c', 'ac1f87', 'c86069', '370e1c', 'ca4e7d', 'c02bd8', '289e05', '3aad14', '0D8ABC', '511852']; - return coloCodes[num]; -} - var tbl = $('#task_table').DataTable({ processing: true, serverSide: true, diff --git a/resources/assets/js/task/task_time_entry.js b/resources/assets/js/task/task_time_entry.js index bfdbfafc9..3f43964a6 100644 --- a/resources/assets/js/task/task_time_entry.js +++ b/resources/assets/js/task/task_time_entry.js @@ -1,13 +1,5 @@ $('#task_users').select2({ width: '100%', placeholder: "All", minimumResultsForSearch: -1 }); -function nl2br (str, is_xhtml) { - if (typeof str === 'undefined' || str === null) { - return ''; - } - var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '
' : '
'; - return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); -} - // open detail confirmation model $(document).on('click', '.taskDetails', function (event) { let id = $(event.currentTarget).data('id'); @@ -91,7 +83,11 @@ window.drawTaskDetailTable = function (data) { {data: "user.name"}, {data: "start_time"}, {data: "end_time"}, - {data: "duration"}, + { + data: function (row) { + return roundToQuarterHourAll(row.duration); + } + }, { orderable: false, data: function (data) { diff --git a/resources/assets/js/time_entries/time_entry.js b/resources/assets/js/time_entries/time_entry.js index 1b526ba40..3a99b218c 100644 --- a/resources/assets/js/time_entries/time_entry.js +++ b/resources/assets/js/time_entries/time_entry.js @@ -22,7 +22,7 @@ let editTaskId, editProjectId = null; let tbl = $('#timeEntryTable').DataTable({ processing: true, serverSide: true, - "order": [[7, "desc"]], + "order": [[9, "desc"]], ajax: { url: timeEntryUrl, data: function (data) { @@ -33,42 +33,45 @@ let tbl = $('#timeEntryTable').DataTable({ }, columnDefs: [ { - "targets": [8], - "orderable": false, + "targets": [9], + "width": "7%", "className": 'text-center', - "width": '5%' - }, - { - "targets": [10, 9], - "visible": false, + "visible": false }, { - "targets": [5], + "targets": [6], "width": "9%" }, { - "targets": [6], + "targets": [7], "width": "4%" }, { - "targets": [3, 4], + "targets": [4, 5], "width": "10%" }, { - "targets": [7], - "width": "7%", + "targets": [8], + "orderable": false, "className": 'text-center', + "width": '5%' }, { - "targets": [2], + "targets": [3], "width": "8%" }, { - "targets": [0], + "targets": [0, 1], "width": "3%" }, ], columns: [ + { + className: 'details-control', + defaultContent: "", + data: null, + orderable: false, + }, { data: function (row) { if (row.user) { @@ -102,7 +105,9 @@ let tbl = $('#timeEntryTable').DataTable({ name: 'end_time' }, { - data: 'duration', + data: function (row) { + return roundToQuarterHourAll(row.duration); + }, name: 'duration' }, { @@ -117,15 +122,6 @@ let tbl = $('#timeEntryTable').DataTable({ }, name: 'entry_type' }, - { - data: function (row) { - return row; - }, - render: function (row) { - return '' + format(row.created_at) + ''; - }, - name: 'created_at' - }, { data: function (row) { return '' + @@ -135,12 +131,13 @@ let tbl = $('#timeEntryTable').DataTable({ }, name: 'id' }, { - data: 'task.project.prefix', - name: 'task.project.prefix' - }, - { - data: 'task.task_number', - name: 'task.task_number' + data: function (row) { + return row; + }, + render: function (row) { + return '' + format(row.created_at) + ''; + }, + name: 'created_at' }, ], "fnInitComplete": function () { @@ -149,6 +146,21 @@ let tbl = $('#timeEntryTable').DataTable({ }); } }); + +$('#timeEntryTable tbody').off('click', 'tr td.details-control'); +$('#timeEntryTable tbody').on('click', 'tr td.details-control', function () { + var tr = $(this).closest('tr'); + var row = tbl.row(tr); + + if (row.child.isShown()) { + row.child.hide(); + tr.removeClass('shown'); + } else { + row.child('
' + nl2br(row.data().note) + '
').show(); + tr.addClass('shown'); + } +}); + if (!canManageEntries) { tbl.columns([0]).visible(false); } diff --git a/resources/views/tasks/time_tracking_modal.blade.php b/resources/views/tasks/time_tracking_modal.blade.php index 89aac68b6..809a8fd4b 100644 --- a/resources/views/tasks/time_tracking_modal.blade.php +++ b/resources/views/tasks/time_tracking_modal.blade.php @@ -23,7 +23,7 @@ {!! nl2br($entry->note) !!} {{$entry->activityType->name}} - {{$entry->duration}} + {{roundToQuarterHour($entry->duration)}} @endforeach diff --git a/resources/views/time_entries/table.blade.php b/resources/views/time_entries/table.blade.php index 362a6f4fc..0b31296ae 100644 --- a/resources/views/time_entries/table.blade.php +++ b/resources/views/time_entries/table.blade.php @@ -1,6 +1,7 @@ + @@ -8,8 +9,8 @@ - + From 220472b56fde090b6849aeb355289333fca5deb9 Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 14:40:17 +0530 Subject: [PATCH 05/23] fiz(profile): Hidden icon for passwords on profile screen (#348) --- resources/assets/js/profile/profile.js | 4 ++++ resources/assets/style/sass/style.scss | 4 ++++ resources/views/profile/edit_profile.blade.php | 8 ++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/resources/assets/js/profile/profile.js b/resources/assets/js/profile/profile.js index a01fd1513..fc242ed3e 100644 --- a/resources/assets/js/profile/profile.js +++ b/resources/assets/js/profile/profile.js @@ -126,8 +126,12 @@ $(".changeType").click(function () { let inputField = $(this).parent().siblings(); let oldType = inputField.attr('type'); if(oldType == 'password') { + $(this).children().addClass('icon-eye'); + $(this).children().removeClass('icon-ban'); inputField.attr('type', 'text'); } else { + $(this).children().removeClass('icon-eye'); + $(this).children().addClass('icon-ban'); inputField.attr('type', 'password'); } }); diff --git a/resources/assets/style/sass/style.scss b/resources/assets/style/sass/style.scss index 20e23ee10..20e29799e 100644 --- a/resources/assets/style/sass/style.scss +++ b/resources/assets/style/sass/style.scss @@ -578,3 +578,7 @@ table.dataTable { top: 23px!important; } + +.input-group__icon { + cursor: pointer; +} \ No newline at end of file diff --git a/resources/views/profile/edit_profile.blade.php b/resources/views/profile/edit_profile.blade.php index 33e8696d0..640d61b21 100644 --- a/resources/views/profile/edit_profile.blade.php +++ b/resources/views/profile/edit_profile.blade.php @@ -45,9 +45,9 @@ {!! Form::label('password', 'New Password') !!}*
-
+
- +
@@ -56,9 +56,9 @@ {!! Form::label('password_confirmation', 'Confirm Password') !!}*
-
+
- +
From 23776e76e7b7719b8826c0952046dfc5903154de Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 14:55:40 +0530 Subject: [PATCH 06/23] fix(task): assignee will be remain if change project (#345) --- resources/assets/js/task/task.js | 15 +++++++++++++-- resources/assets/js/task/task_detail.js | 7 +++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/resources/assets/js/task/task.js b/resources/assets/js/task/task.js index 6e2da1c1a..ff36476dc 100644 --- a/resources/assets/js/task/task.js +++ b/resources/assets/js/task/task.js @@ -79,6 +79,14 @@ $(function () { $('[data-toggle="tooltip"]').tooltip(); }); +let taskAssignees = []; + +function getRandomColor() { + let num = Math.floor(Math.random() * 12) + 1; + let coloCodes = ['0095ff', '9594fe', 'da4342', '8e751c', 'ac1f87', 'c86069', '370e1c', 'ca4e7d', 'c02bd8', '289e05', '3aad14', '0D8ABC', '511852']; + return coloCodes[num]; +} + var tbl = $('#task_table').DataTable({ processing: true, serverSide: true, @@ -233,11 +241,13 @@ $(document).on('click', '.edit-btn', function (event) { var tagsIds = []; var userIds = []; + taskAssignees = []; $(task.tags).each(function (i, e) { tagsIds.push(e.id); }); $(task.task_assignee).each(function (i, e) { userIds.push(e.id); + taskAssignees.push(e.id); }); $("#editTagIds").val(tagsIds).trigger('change'); @@ -265,8 +275,6 @@ $(document).on('click', '.delete-btn', function (event) { deleteItem(taskUrl + id, '#task_table', 'Task'); }); - - $('#addNewForm').submit(function (event) { event.preventDefault(); let loadingButton = jQuery(this).find("#btnTaskSave"); @@ -464,6 +472,9 @@ $(document).on('change', '#projectId', function (event) { $(document).on('change', '#editProjectId', function (event) { let projectId = $(this).val(); loadProjectAssignees(projectId, 'editAssignee') + setTimeout(function () { + $("#editAssignee").val(taskAssignees).trigger('change'); + }, 1500) }); function loadProjectAssignees(projectId, selector) { diff --git a/resources/assets/js/task/task_detail.js b/resources/assets/js/task/task_detail.js index 967912d91..3df10706a 100644 --- a/resources/assets/js/task/task_detail.js +++ b/resources/assets/js/task/task_detail.js @@ -59,6 +59,8 @@ $(function () { $('[data-toggle="tooltip"]').tooltip() }); +let taskAssignees = []; + // open edit user model $(document).on('click', '.edit-btn', function (event) { let id = $(event.currentTarget).data('id'); @@ -80,11 +82,13 @@ $(document).on('click', '.edit-btn', function (event) { $('#editStatus').val(task.status); var tagsIds = []; var userIds = []; + taskAssignees = []; $(task.tags).each(function (i, e) { tagsIds.push(e.id); }); $(task.task_assignee).each(function (i, e) { userIds.push(e.id); + taskAssignees.push(e.id); }); $("#editTagIds").val(tagsIds).trigger('change'); @@ -110,6 +114,9 @@ $(document).on('click', '.edit-btn', function (event) { $(document).on('change', '#editProjectId', function (event) { let projectId = $(this).val(); loadProjectAssignees(projectId, 'editAssignee') + setTimeout(function () { + $("#editAssignee").val(taskAssignees).trigger('change'); + }, 1500) }); function loadProjectAssignees(projectId, selector) { From c1426e1658054efa298ba3f3e3cff20da1c4a9fe Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 15:01:38 +0530 Subject: [PATCH 07/23] fix(report): in time entry pop up time entry will come between report start and end date only (#352) --- app/Repositories/TaskRepository.php | 20 ++++++++++++--- resources/assets/js/task/task.js | 9 ------- resources/assets/js/task/task_time_entry.js | 27 ++++++++++++--------- resources/views/reports/create.blade.php | 2 +- resources/views/reports/edit.blade.php | 2 +- resources/views/reports/show.blade.php | 4 ++- resources/views/tasks/index.blade.php | 2 ++ 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php index 821303be3..ee0712087 100644 --- a/app/Repositories/TaskRepository.php +++ b/app/Repositories/TaskRepository.php @@ -272,12 +272,26 @@ public function getTaskDetails($id, $input = []) if (isset($input['user_id']) && $input['user_id'] > 0) { $task = Task::with([ 'timeEntries' => function (HasMany $query) use ($input) { - $query->where('time_entries.user_id', '=', $input['user_id']) - ->with('user'); + $query->where('time_entries.user_id', '=', $input['user_id']); + if (isset($input['start_time']) && isset($input['end_time']) && !empty($input['start_time']) && !empty($input['end_time'])) { + $query->whereBetween('start_time', [$input['start_time'], $input['end_time']]); + } + $query->with('user'); }, ])->findOrFail($id); } else { - $task = Task::with('timeEntries.user')->findOrFail($id); + if (isset($input['start_time']) && isset($input['end_time']) && !empty($input['start_time']) && !empty($input['end_time'])) { + $task = Task::with([ + 'timeEntries' => function (HasMany $query) use ($input) { + if (isset($input['start_time']) && isset($input['end_time']) && !empty($input['start_time']) && !empty($input['end_time'])) { + $query->whereBetween('start_time', [$input['start_time'], $input['end_time']]); + } + $query->with('user'); + }, + ])->findOrFail($id); + } else { + $task = Task::with('timeEntries.user')->findOrFail($id); + } } $minutes = $task->timeEntries->pluck('duration')->sum(); diff --git a/resources/assets/js/task/task.js b/resources/assets/js/task/task.js index ff36476dc..e9c9a7ac8 100644 --- a/resources/assets/js/task/task.js +++ b/resources/assets/js/task/task.js @@ -376,15 +376,6 @@ $(function () { } }); -$(document).on('click', '.collapse-icon', function () { - let isShow = $(this).parent().parent().hasClass('shown'); - if(isShow) { - $(this).children().removeClass('fa-plus-circle').addClass("fa-minus-circle"); - } else { - $(this).children().removeClass('fa-minus-circle').addClass("fa-plus-circle"); - } -}); - window.manageCollapseIcon = function (id) { var isExpanded = $('#tdCollapse' + id).attr('aria-expanded'); if (isExpanded == 'true') { diff --git a/resources/assets/js/task/task_time_entry.js b/resources/assets/js/task/task_time_entry.js index 3f43964a6..44ee90f71 100644 --- a/resources/assets/js/task/task_time_entry.js +++ b/resources/assets/js/task/task_time_entry.js @@ -22,17 +22,6 @@ $(document).on('click', '.taskDetails', function (event) { }); } }); - - $.ajax({ - url: taskDetailUrl + '/' + id, - type: 'GET', - success: function (result) { - if (result.success) { - let data = result.data; - drawTaskDetailTable(data); - } - } - }); }); $(document).on('change', '#task_users', function () { @@ -44,9 +33,14 @@ $(document).on('change', '#task_users', function () { userId = taskUserId[0]; } let url = taskDetailUrl + '/' + taskId; + let startSymbol = '?'; if (userId !== 0) { + startSymbol = '&'; url = url + '?user_id=' + userId; } + if (reportStartDate != '' && reportEndDate != '') { + url = url + startSymbol + 'start_time=' + reportStartDate + '&end_time=' + reportEndDate; + } $.ajax({ url: url, type: 'GET', @@ -99,6 +93,8 @@ window.drawTaskDetailTable = function (data) { ], }); + $('#taskDetailsTable th:first').removeClass('sorting_asc'); + $('.time-entry-data').show(); $('#taskDetailsTable').show(); $('#user-drop-down-body').show(); @@ -124,3 +120,12 @@ window.drawTaskDetailTable = function (data) { $("#taskDetailsTable_wrapper").css('width', "100%"); $("#total-duration").html("Total duration: " + data.totalDuration + " || " + data.totalDurationMin + " Minutes"); }; + +$(document).on('click', '.collapse-icon', function () { + let isShow = $(this).parent().parent().hasClass('shown'); + if(isShow) { + $(this).children().removeClass('fa-plus-circle').addClass("fa-minus-circle"); + } else { + $(this).children().removeClass('fa-minus-circle').addClass("fa-plus-circle"); + } +}); diff --git a/resources/views/reports/create.blade.php b/resources/views/reports/create.blade.php index b9a808ac1..66a04c15d 100644 --- a/resources/views/reports/create.blade.php +++ b/resources/views/reports/create.blade.php @@ -14,7 +14,7 @@
diff --git a/resources/views/reports/edit.blade.php b/resources/views/reports/edit.blade.php index de8dcd4af..a89717c93 100644 --- a/resources/views/reports/edit.blade.php +++ b/resources/views/reports/edit.blade.php @@ -15,7 +15,7 @@
diff --git a/resources/views/reports/show.blade.php b/resources/views/reports/show.blade.php index 5da00202a..56363fb95 100644 --- a/resources/views/reports/show.blade.php +++ b/resources/views/reports/show.blade.php @@ -19,7 +19,7 @@ class="btn btn-primary filter-container__btn mr-1"> Edit - Back + Back
@@ -55,6 +55,8 @@ class="btn btn-primary filter-container__btn mr-1"> let taskUrl = '{{url('tasks')}}/'; let taskDetailUrl = '{{url('task-details')}}'; let taskDetailActionColumnIsVisible = false; + let reportStartDate = '{{$report->start_date->startOfDay()}}'; + let reportEndDate = '{{$report->end_date->endOfDay()}}'; diff --git a/resources/views/tasks/index.blade.php b/resources/views/tasks/index.blade.php index 39be2b106..843e23fb2 100644 --- a/resources/views/tasks/index.blade.php +++ b/resources/views/tasks/index.blade.php @@ -76,6 +76,8 @@ let taskBadgesJson = '{!! json_encode($taskBadges) !!}'; let taskBadges = $.parseJSON(taskBadgesJson); let taskDetailActionColumnIsVisible = true; + let reportStartDate = ''; + let reportEndDate = ''; From 5ec595fdc314ef609602d4d96ff0368a59598432 Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 15:03:56 +0530 Subject: [PATCH 08/23] fix(modal): fix allignment issue in modal (#350) --- resources/assets/style/sass/style.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/assets/style/sass/style.scss b/resources/assets/style/sass/style.scss index 20e29799e..c3336792c 100644 --- a/resources/assets/style/sass/style.scss +++ b/resources/assets/style/sass/style.scss @@ -578,7 +578,11 @@ table.dataTable { top: 23px!important; } +.modal-header .close { + padding: 19px; +} .input-group__icon { cursor: pointer; -} \ No newline at end of file +} + From 0cb28fc64f4bf1c96afc41080d3b9889dcb59f7a Mon Sep 17 00:00:00 2001 From: Monika vaghasiya Date: Wed, 11 Sep 2019 16:28:43 +0530 Subject: [PATCH 09/23] fix(time-entry): change column heading --- resources/views/tasks/index.blade.php | 1 - resources/views/tasks/time_tracking_modal.blade.php | 2 +- resources/views/time_entries/table.blade.php | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/views/tasks/index.blade.php b/resources/views/tasks/index.blade.php index 843e23fb2..ebf43cc2b 100644 --- a/resources/views/tasks/index.blade.php +++ b/resources/views/tasks/index.blade.php @@ -83,4 +83,3 @@ @endsection - diff --git a/resources/views/tasks/time_tracking_modal.blade.php b/resources/views/tasks/time_tracking_modal.blade.php index 809a8fd4b..fb031c7ae 100644 --- a/resources/views/tasks/time_tracking_modal.blade.php +++ b/resources/views/tasks/time_tracking_modal.blade.php @@ -14,7 +14,7 @@
- + diff --git a/resources/views/time_entries/table.blade.php b/resources/views/time_entries/table.blade.php index 0b31296ae..e03efea6f 100644 --- a/resources/views/time_entries/table.blade.php +++ b/resources/views/time_entries/table.blade.php @@ -7,7 +7,7 @@ - + From c68d81fa63bbeed47a3e0f834609bd284a37e5d4 Mon Sep 17 00:00:00 2001 From: Shailesh Ladumor Date: Wed, 11 Sep 2019 17:35:51 +0530 Subject: [PATCH 10/23] fix: remove label from chart --- resources/assets/js/dashboard/developers-daily-report.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/dashboard/developers-daily-report.js b/resources/assets/js/dashboard/developers-daily-report.js index a763e45cc..4380db1e6 100644 --- a/resources/assets/js/dashboard/developers-daily-report.js +++ b/resources/assets/js/dashboard/developers-daily-report.js @@ -84,7 +84,8 @@ window.prepareDeveloperWorkReport = function (result) { labelString: 'Hours' }, }] - } + }, + legend: { display: false } } }); }; From 4d737a90425a958f51bedfd66389ecab58a2bd7b Mon Sep 17 00:00:00 2001 From: Monika Vaghasiya <51854283+MonikaInfyOm@users.noreply.github.com> Date: Wed, 11 Sep 2019 17:48:38 +0530 Subject: [PATCH 11/23] fix(UI): added first focus for input fields only (#354) --- resources/assets/js/custom.js | 8 +++++--- resources/views/tasks/edit_modal.blade.php | 8 ++++---- resources/views/tasks/modal.blade.php | 8 ++++---- resources/views/time_entries/edit_modal.blade.php | 2 +- resources/views/time_entries/modal.blade.php | 2 +- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/resources/assets/js/custom.js b/resources/assets/js/custom.js index a3405368a..fe3103060 100644 --- a/resources/assets/js/custom.js +++ b/resources/assets/js/custom.js @@ -224,9 +224,11 @@ $(document).on('focus', '.select2-selection.select2-selection--single', function $(function () { $(".modal").on('shown.bs.modal', function () { - setTimeout(function () { - $(".modal").find('input:text, .select2-selection.select2-selection--single').first().focus(); - },150); + if($(this).find('.timeEntryAddForm').hasClass('timeEntryAddForm') || $(this).find('.editTimeEntryForm').hasClass('editTimeEntryForm')){ + $(this).find('textarea').first().focus(); + } else { + $(this).find('input:text').first().focus(); + } }); }); diff --git a/resources/views/tasks/edit_modal.blade.php b/resources/views/tasks/edit_modal.blade.php index 7c454cd54..8fe069df8 100644 --- a/resources/views/tasks/edit_modal.blade.php +++ b/resources/views/tasks/edit_modal.blade.php @@ -11,14 +11,14 @@ {!! Form::hidden('tag_id',null,['id'=>'tagId']) !!}
-
- {!! Form::label('project_id', 'Project') !!}* - {!! Form::select('project_id', $projects, null, ['class' => 'form-control','required', 'id' => 'editProjectId', 'placeholder'=>'Select Project']) !!} -
{!! Form::label('title', 'Title') !!}* {!! Form::text('title', null, ['id'=>'editTitle','class' => 'form-control','required']) !!}
+
+ {!! Form::label('project_id', 'Project') !!}* + {!! Form::select('project_id', $projects, null, ['class' => 'form-control','required', 'id' => 'editProjectId', 'placeholder'=>'Select Project']) !!} +
diff --git a/resources/views/tasks/modal.blade.php b/resources/views/tasks/modal.blade.php index 879a88e09..76b21d3e2 100644 --- a/resources/views/tasks/modal.blade.php +++ b/resources/views/tasks/modal.blade.php @@ -10,14 +10,14 @@
User Task ActivityEnd Time Duration (min) TypeCreated At ActionCreated At
Note Activity Tracked ByTime (Mins)Time
Activity Start Time End TimeDuration (min)Duration Type Action Created At