update doing
This commit is contained in:
		
							parent
							
								
									cfe9ee5da9
								
							
						
					
					
						commit
						8c06526757
					
				| 
						 | 
				
			
			@ -246,4 +246,18 @@ class JiraController extends Controller
 | 
			
		|||
        // dd($tasksByUser);
 | 
			
		||||
        return $tasksByUser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function getAllUserDoing(Request $request)
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $doing = $this->jiraService->getAllUserDoing();
 | 
			
		||||
            return response()->json([
 | 
			
		||||
                'data' => $doing,
 | 
			
		||||
                'status' => true
 | 
			
		||||
            ], 200);
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return response()->json(['error' => $e->getMessage()], 500);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,6 +149,7 @@ class TimekeepingController extends Controller
 | 
			
		|||
 | 
			
		||||
        return response()->json(['status' => true, 'message' => 'Add successfully']);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function updateCacheMonth(Request $request)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,6 +103,7 @@ Route::middleware('api')
 | 
			
		|||
                Route::get('/all-project', [JiraController::class, 'getAllProject']);
 | 
			
		||||
                Route::get('/all-issue-by-project', [JiraController::class, 'fetchIssuesByProject']);
 | 
			
		||||
                Route::get('/worklogs', [JiraController::class, 'getAllUserWorkLogs'])->middleware('check.permission:admin.staff');
 | 
			
		||||
                Route::get('/allocation', [JiraController::class, 'getAllUserDoing'])->middleware('check.permission:admin.staff');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            Route::group([
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ class JiraService
 | 
			
		|||
            'expand' => ['names', 'schema', 'operations'],
 | 
			
		||||
            'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project'],
 | 
			
		||||
            'jql' => sprintf(
 | 
			
		||||
                "assignee = '%s' AND status IN ('backlog', 'todo', 'in progress')",
 | 
			
		||||
                "assignee = '%s' AND status IN ('backlog', 'to do', 'in progress')",
 | 
			
		||||
                $accountId
 | 
			
		||||
            ),
 | 
			
		||||
            'maxResults' => 50,
 | 
			
		||||
| 
						 | 
				
			
			@ -188,4 +188,64 @@ class JiraService
 | 
			
		|||
 | 
			
		||||
        return $workLogs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllUserDoing()
 | 
			
		||||
    {
 | 
			
		||||
        $users = $this->getAllUsers();
 | 
			
		||||
        // $projects = $this->getAllProjects();
 | 
			
		||||
        $groupedIssues = [];
 | 
			
		||||
        $users_data = [];
 | 
			
		||||
        foreach ($users as $user) {
 | 
			
		||||
            $users_data[$user['displayName']]['user'] = $user; 
 | 
			
		||||
            $users_data[$user['displayName']]['total_spent'] = 0; 
 | 
			
		||||
            $users_data[$user['displayName']]['total_est'] = 0; 
 | 
			
		||||
            $body = [
 | 
			
		||||
                'expand' => ['names', 'schema'],
 | 
			
		||||
                'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project'],
 | 
			
		||||
                'jql' => sprintf(
 | 
			
		||||
                    "assignee = '%s' AND status IN ('to do', 'in progress')",
 | 
			
		||||
                    $user['accountId']
 | 
			
		||||
                ),
 | 
			
		||||
                'maxResults' => 50,
 | 
			
		||||
                'startAt' => 0
 | 
			
		||||
            ];
 | 
			
		||||
    
 | 
			
		||||
            $response = $this->client->post('/rest/api/3/search', [
 | 
			
		||||
                'body' => json_encode($body)
 | 
			
		||||
            ]);
 | 
			
		||||
    
 | 
			
		||||
            $issues = json_decode($response->getBody()->getContents(), true);
 | 
			
		||||
 | 
			
		||||
            foreach ($issues['issues'] as $issue) {
 | 
			
		||||
                $projectName = $issue['fields']['project']['name'];
 | 
			
		||||
                $username = $issue['fields']['assignee']['displayName'];
 | 
			
		||||
        
 | 
			
		||||
                if (!isset($groupedIssues[$projectName])) {
 | 
			
		||||
                    $groupedIssues[$projectName] = [];
 | 
			
		||||
                    $groupedIssues[$projectName]['project'] = $issue['fields']['project'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!isset($groupedIssues[$projectName]['users'][$username])) {
 | 
			
		||||
                    $groupedIssues[$projectName]['users'][$username] = [];
 | 
			
		||||
                    $groupedIssues[$projectName]['users'][$username]['user'] = $issue['fields']['assignee'];
 | 
			
		||||
                    $groupedIssues[$projectName]['users'][$username]['p_total_spent'] = 0;
 | 
			
		||||
                    $groupedIssues[$projectName]['users'][$username]['p_total_est'] = 0;
 | 
			
		||||
                }
 | 
			
		||||
        
 | 
			
		||||
                $groupedIssues[$projectName]['users'][$username]['issues'][] = $issue;
 | 
			
		||||
                $groupedIssues[$projectName]['users'][$username]['p_total_spent'] = $groupedIssues[$projectName]['users'][$username]['p_total_spent'] + $issue['fields']['timespent'];
 | 
			
		||||
                $groupedIssues[$projectName]['users'][$username]['p_total_est'] = $groupedIssues[$projectName]['users'][$username]['p_total_est'] + ($issue['fields']['timeoriginalestimate'] ?? 0);
 | 
			
		||||
                
 | 
			
		||||
                $users_data[$user['displayName']]['total_spent'] = $users_data[$user['displayName']]['total_spent'] + $issue['fields']['timespent'];
 | 
			
		||||
                $users_data[$user['displayName']]['total_est'] = $users_data[$user['displayName']]['total_est'] + ($issue['fields']['timeoriginalestimate'] ?? 0); 
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        return ['projects' => $groupedIssues, 'users' => $users_data];
 | 
			
		||||
        // return $projects;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
<?php
 | 
			
		||||
 | 
			
		||||
use Illuminate\Database\Migrations\Migration;
 | 
			
		||||
use Illuminate\Database\Schema\Blueprint;
 | 
			
		||||
use Illuminate\Support\Facades\Schema;
 | 
			
		||||
 | 
			
		||||
return new class extends Migration
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * Run the migrations.
 | 
			
		||||
     */
 | 
			
		||||
    public function up(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::table('users', function (Blueprint $table) {
 | 
			
		||||
            $table->string('avatar');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reverse the migrations.
 | 
			
		||||
     */
 | 
			
		||||
    public function down(): void
 | 
			
		||||
    {
 | 
			
		||||
        Schema::table('users', function (Blueprint $table) {
 | 
			
		||||
            $table->dropColumn('avatar');
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ export const exportIssues = API_URL + 'v1/admin/jira/export-issues'
 | 
			
		|||
export const getAllProjects = API_URL + 'v1/admin/jira/all-project'
 | 
			
		||||
export const getAllIssuesByProject = API_URL + 'v1/admin/jira/all-issue-by-project'
 | 
			
		||||
export const getAllUserWorklogs = API_URL + 'v1/admin/jira/worklogs'
 | 
			
		||||
export const getAllUserDoing = API_URL + 'v1/admin/jira/allocation'
 | 
			
		||||
 | 
			
		||||
//Timekeeping
 | 
			
		||||
export const getTheTimesheet = API_URL + 'v1/admin/timekeeping'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,11 +20,13 @@ import {
 | 
			
		|||
} from '@mantine/core'
 | 
			
		||||
import { notifications } from '@mantine/notifications'
 | 
			
		||||
import {
 | 
			
		||||
  IconBinaryTree2,
 | 
			
		||||
  IconCalendar,
 | 
			
		||||
  IconCalendarClock,
 | 
			
		||||
  IconDevices,
 | 
			
		||||
  IconLayoutSidebarLeftExpand,
 | 
			
		||||
  IconLayoutSidebarRightExpand,
 | 
			
		||||
  IconListCheck,
 | 
			
		||||
  IconLogout,
 | 
			
		||||
  // IconMail,
 | 
			
		||||
  IconMoon,
 | 
			
		||||
| 
						 | 
				
			
			@ -35,13 +37,12 @@ import {
 | 
			
		|||
  IconSun,
 | 
			
		||||
  IconTicket,
 | 
			
		||||
  IconUsersGroup,
 | 
			
		||||
  IconZoomExclamation,
 | 
			
		||||
  IconZoomExclamation
 | 
			
		||||
} from '@tabler/icons-react'
 | 
			
		||||
import { useCallback, useEffect, useState } from 'react'
 | 
			
		||||
import { useLocation, useNavigate } from 'react-router-dom'
 | 
			
		||||
import PasswordRequirementInput from '../PasswordRequirementInput/PasswordRequirementInput'
 | 
			
		||||
import classes from './NavbarSimpleColored.module.css'
 | 
			
		||||
import { IconListCheck } from '@tabler/icons-react'
 | 
			
		||||
 | 
			
		||||
const data = [
 | 
			
		||||
  // { link: '/dashboard', label: 'Dashboard', icon: IconHome },
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +95,12 @@ const data = [
 | 
			
		|||
    icon: IconZoomExclamation,
 | 
			
		||||
    group: 'admin',
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    link: '/allocation',
 | 
			
		||||
    label: 'Personnel allocation',
 | 
			
		||||
    icon: IconBinaryTree2,
 | 
			
		||||
    group: 'admin',
 | 
			
		||||
  },
 | 
			
		||||
  // { link: '/jira', label: 'Jira', icon: IconSubtask },
 | 
			
		||||
  // { link: '/custom-theme', label: 'Custom Theme', icon: IconBrush },
 | 
			
		||||
  // { link: '/general-setting', label: 'General Setting', icon: IconSettings },
 | 
			
		||||
| 
						 | 
				
			
			@ -400,7 +407,7 @@ const Navbar = ({
 | 
			
		|||
            </span>
 | 
			
		||||
          </a>
 | 
			
		||||
          <div className={classes.footer}></div>
 | 
			
		||||
          <a href="#" className={classes.link} onClick={handleSetCompactMenu}>
 | 
			
		||||
          <a href="#" className={classes.link} onClick={handleSetCompactMenu} style={{margin:"0 20px", padding:"0 0 10px 0"}}>
 | 
			
		||||
            {isCompactMenu ? (
 | 
			
		||||
              <IconLayoutSidebarLeftExpand
 | 
			
		||||
                className={classes.linkIcon}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@
 | 
			
		|||
  font-size: var(--mantine-font-size-sm);
 | 
			
		||||
  color: rgb(161, 161, 161);
 | 
			
		||||
  padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm);
 | 
			
		||||
  margin: var(--mantine-spacing-xs);
 | 
			
		||||
  margin: 0 var(--mantine-spacing-xs);
 | 
			
		||||
  border-radius: var(--mantine-radius-sm);
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
import ResetPassword from '@/components/Authentication/ResetPassword'
 | 
			
		||||
import BasePage from '@/components/BasePage/BasePage'
 | 
			
		||||
import ProtectedRoute from '@/components/ProtectedRoute/ProtectedRoute'
 | 
			
		||||
import Allocation from '@/pages/Allocation/Allocation'
 | 
			
		||||
import PageLogin from '@/pages/Auth/Login/Login'
 | 
			
		||||
import LeaveManagement from '@/pages/LeaveManagement/LeaveManagement'
 | 
			
		||||
import PageNotFound from '@/pages/NotFound/NotFound'
 | 
			
		||||
| 
						 | 
				
			
			@ -174,6 +175,20 @@ const mainRoutes = [
 | 
			
		|||
      </ProtectedRoute>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/allocation',
 | 
			
		||||
    element: (
 | 
			
		||||
      <ProtectedRoute mode="route" permission="admin">
 | 
			
		||||
        <BasePage
 | 
			
		||||
          main={
 | 
			
		||||
            <>
 | 
			
		||||
              <Allocation />
 | 
			
		||||
            </>
 | 
			
		||||
          }
 | 
			
		||||
        ></BasePage>
 | 
			
		||||
      </ProtectedRoute>
 | 
			
		||||
    ),
 | 
			
		||||
  },
 | 
			
		||||
  // {
 | 
			
		||||
  //   path: '/packages',
 | 
			
		||||
  //   element: (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue