update allocation

This commit is contained in:
JOSEPH LE 2024-09-17 16:31:09 +07:00
parent fe75a08c3d
commit a855787a47
5 changed files with 80 additions and 11 deletions

View File

@ -260,4 +260,14 @@ class JiraController extends Controller
return response()->json(['error' => $e->getMessage()], 500);
}
}
public function getDetailIssueById(Request $request)
{
$data = $this->jiraService->getDetailIssueByKey($request->issueKey);
return response()->json([
'data' => $data,
'status' => true
], 200);
}
}

View File

@ -104,6 +104,7 @@ Route::middleware('api')
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::get('/issue/detail', [JiraController::class, 'getDetailIssueById'])->middleware('check.permission:admin.staff');
});
Route::group([

View File

@ -238,9 +238,9 @@ class JiraService
$users_data[$user['displayName']]['total_est'] = 0;
$body = [
'expand' => ['names', 'schema'],
'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project'],
'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project', 'updated'],
'jql' => sprintf(
"assignee = '%s' AND status IN ('to do', 'in progress')",
"assignee = '%s' AND status IN ('to do', 'in progress') ORDER BY updated DESC",
$user['accountId']
),
'maxResults' => 50,
@ -289,4 +289,11 @@ class JiraService
return ['projects' => $groupedIssues, 'users' => $users_data, 'warningList' => $user_warning];
// return $projects;
}
public function getDetailIssueByKey($issueKey)
{
$issueResponse = $this->client->get("/rest/api/3/issue/{$issueKey}?expand=changelog");
$issueDetail = json_decode($issueResponse->getBody()->getContents(), true);
return $issueDetail;
}
}

View File

@ -15,6 +15,7 @@ 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'
export const getDetailIssByKey = API_URL + 'v1/admin/jira/issue/detail'
//Timekeeping
export const getTheTimesheet = API_URL + 'v1/admin/timekeeping'

View File

@ -1,16 +1,20 @@
import {
Avatar,
Badge,
Box,
Card,
Loader,
Modal,
Popover,
Text
Text,
Tooltip
} from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { useEffect, useState } from 'react'
import classes from './Allocation.module.css'
import { get } from '@/rtk/helpers/apiService'
import { getAllUserDoing } from '@/api/Admin'
import { getAllUserDoing, getDetailIssByKey } from '@/api/Admin'
import moment from 'moment'
interface UserInfo {
self: string
accountId: string
@ -42,6 +46,7 @@ interface IssueFields {
timeoriginalestimate: number
project: ProjectInfo
status: StatusInfo
updated: string
}
interface ProjectInfo {
@ -71,7 +76,9 @@ interface StatusInfo {
}
const Allocation = () => {
const [loading, { toggle }] = useDisclosure(true)
const [loading, setLoading] = useState(true)
const [opened, setOpened] = useState(false)
const [issDetail, setIssDetail] = useState("")
// const [data, setData] = useState<any>({
// projects: {
// IPS_Pro: {
@ -3281,7 +3288,7 @@ const Allocation = () => {
try {
const res = await get(getAllUserDoing)
if (res.status) {
toggle()
setLoading(false)
setData(res.data)
}
} catch (error) {
@ -3289,6 +3296,30 @@ const Allocation = () => {
}
}
// console.log(data)
const getStateChanges = (changelog:any) => {
return changelog.histories.map((history:any) => {
const author = history.author.displayName;
const created = history.created;
const changes = history.items.map((item:any) => {
return `${item.field} changed from ${item.fromString}${item.toString}`;
}).join(', ');
return changes ? `${author} made changes on ${created}: ${changes}` : null;
}).filter(Boolean).join('\n');
};
const getDetailIssueByKey = async(key:string) =>{
try {
const res = await get(getDetailIssByKey, {issueKey: key})
if(res.status){
setIssDetail(getStateChanges(res?.data?.changelog))
setOpened(true)
}
} catch (error) {
console.log(error)
}
}
useEffect(() => {
getAll()
}, [])
@ -3436,10 +3467,19 @@ const Allocation = () => {
</Box>
</Popover.Target>
<Popover.Dropdown>
<Text size="xs">
<Text size="xs" style={{maxHeight:'50vh', overflow:'auto'}}>
{userData.issues?.map((iss: Issue) => {
const date = new Date(iss.fields.updated)
return (
<Box>
<Tooltip label='Click to view history'>
<Box className={ Date.now() - date.getTime() > 172800000*5 ? classes['blinking-background']: ''}
style={{margin:'10px 0', borderRadius:'10px', cursor:'pointer'}}
onClick={async()=>{
setLoading(true)
await getDetailIssueByKey(iss.key)
setLoading(false)}}
>
<Text fw={600}>
<a
href={
@ -3464,18 +3504,24 @@ const Allocation = () => {
</Text>
<Text fw={600} ml={'50px'}>
Time spent:{' '}
{iss.fields.timespent / 60 / 60}
<Badge size='xs' bg={'orange'}>{iss.fields.timespent / 60 / 60}h</Badge>
</Text>
<Text fw={600} ml={'50px'}>
EST:{' '}
{iss.fields.timeoriginalestimate /
<Badge size='xs'>{iss.fields.timeoriginalestimate /
60 /
60}
60}h</Badge>
</Text>
<Text fw={600} ml={'50px'}>
Updated:{' '}
<Badge size='xs'>{iss.fields.updated}</Badge>
</Text>
</Box>
</Tooltip>
)
})}
</Text>
</Popover.Dropdown>
</Popover>
</Box>
@ -3549,7 +3595,11 @@ const Allocation = () => {
</Box>
</Box>
</div>
<Modal title={<b>HISTORY</b>} onClose={()=>setOpened(false) } opened={opened} fullScreen>
<pre>{issDetail}</pre>
</Modal>
</div>
)
}