update allocation
This commit is contained in:
parent
fe75a08c3d
commit
a855787a47
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue