Create a workflow statistics page from Jira
This commit is contained in:
		
							parent
							
								
									010fe6e650
								
							
						
					
					
						commit
						9b630fe1e1
					
				| 
						 | 
					@ -76,7 +76,7 @@ class JiraService
 | 
				
			||||||
                "assignee = '%s' AND status IN ('backlog', 'todo', 'in progress')",
 | 
					                "assignee = '%s' AND status IN ('backlog', 'todo', 'in progress')",
 | 
				
			||||||
                $accountId
 | 
					                $accountId
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            'maxResults' => 10,
 | 
					            'maxResults' => 50,
 | 
				
			||||||
            'startAt' => $startAt
 | 
					            'startAt' => $startAt
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,7 @@ class JiraService
 | 
				
			||||||
        $body = [
 | 
					        $body = [
 | 
				
			||||||
            'jql' => "worklogAuthor = '{$accountId}'AND worklogDate >= '{$startDate}' AND worklogDate <= '{$endDate}'",
 | 
					            'jql' => "worklogAuthor = '{$accountId}'AND worklogDate >= '{$startDate}' AND worklogDate <= '{$endDate}'",
 | 
				
			||||||
            'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'project'],
 | 
					            'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'project'],
 | 
				
			||||||
            'maxResults' => 50
 | 
					            'maxResults' => 100
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $response = $this->client->post('/rest/api/3/search', [
 | 
					        $response = $this->client->post('/rest/api/3/search', [
 | 
				
			||||||
| 
						 | 
					@ -134,7 +134,7 @@ class JiraService
 | 
				
			||||||
                ]
 | 
					                ]
 | 
				
			||||||
            ])->then(function ($checkApiResponse) use ($issueId, $index) {
 | 
					            ])->then(function ($checkApiResponse) use ($issueId, $index) {
 | 
				
			||||||
                $checkApi = json_decode($checkApiResponse->getBody()->getContents(), true);
 | 
					                $checkApi = json_decode($checkApiResponse->getBody()->getContents(), true);
 | 
				
			||||||
                $maxResults = 50;
 | 
					                $maxResults = 100;
 | 
				
			||||||
                $totalWorklogs = $checkApi['total'];
 | 
					                $totalWorklogs = $checkApi['total'];
 | 
				
			||||||
                return $this->client->getAsync("/rest/api/3/issue/{$issueId}/worklog", [
 | 
					                return $this->client->getAsync("/rest/api/3/issue/{$issueId}/worklog", [
 | 
				
			||||||
                    'query' => [
 | 
					                    'query' => [
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,8 +116,13 @@ const Tracking = () => {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(()=>{
 | 
					  useEffect(()=>{
 | 
				
			||||||
    setInterval(()=>{
 | 
					    if(listTracking.data.length === 0){
 | 
				
			||||||
      getAllTracking()
 | 
					      getAllTracking()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    setInterval(()=>{
 | 
				
			||||||
 | 
					      if(window.location.pathname.includes('tracking')){
 | 
				
			||||||
 | 
					        getAllTracking()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }, 7000)
 | 
					    }, 7000)
 | 
				
			||||||
  }, [])
 | 
					  }, [])
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ const Worklogs = () => {
 | 
				
			||||||
    startDate:
 | 
					    startDate:
 | 
				
			||||||
      localStorage.getItem('data') !== null
 | 
					      localStorage.getItem('data') !== null
 | 
				
			||||||
        ? JSON.parse(localStorage.getItem('data')!).date.startDate
 | 
					        ? JSON.parse(localStorage.getItem('data')!).date.startDate
 | 
				
			||||||
        : moment(Date.now()).format('YYYY-MM-DD'),
 | 
					        : moment(Date.now()-604800000).format('YYYY-MM-DD'),
 | 
				
			||||||
    endDate:
 | 
					    endDate:
 | 
				
			||||||
      localStorage.getItem('data') !== null
 | 
					      localStorage.getItem('data') !== null
 | 
				
			||||||
        ? JSON.parse(localStorage.getItem('data')!).date.endDate
 | 
					        ? JSON.parse(localStorage.getItem('data')!).date.endDate
 | 
				
			||||||
| 
						 | 
					@ -172,65 +172,88 @@ const Worklogs = () => {
 | 
				
			||||||
    </Box>
 | 
					    </Box>
 | 
				
			||||||
  ) : (
 | 
					  ) : (
 | 
				
			||||||
    <div style={{ display: 'flex', flexFlow: 'column' }}>
 | 
					    <div style={{ display: 'flex', flexFlow: 'column' }}>
 | 
				
			||||||
      <div className={classes.title}>
 | 
					    <div className={classes.title}>
 | 
				
			||||||
        <h3>
 | 
					      <h3>
 | 
				
			||||||
          <Text>Admin/</Text>Worklogs
 | 
					        <Text>Admin/</Text>Worklogs
 | 
				
			||||||
          {!updating ? (
 | 
					        {!updating ? (
 | 
				
			||||||
            <Text fs={'italic'} fz={'xs'} c={'gray'}>
 | 
					          <Text fs={'italic'} fz={'xs'} c={'gray'}>
 | 
				
			||||||
              Updating data in the background ...
 | 
					            Updating data in the background ...
 | 
				
			||||||
            </Text>
 | 
					          </Text>
 | 
				
			||||||
          ) : (
 | 
					        ) : (
 | 
				
			||||||
            ''
 | 
					          ''
 | 
				
			||||||
          )}
 | 
					        )}
 | 
				
			||||||
        </h3>
 | 
					      </h3>
 | 
				
			||||||
      </div>
 | 
					    </div>
 | 
				
			||||||
      <Box
 | 
					    <Box
 | 
				
			||||||
        display={'flex'}
 | 
					      display={'flex'}
 | 
				
			||||||
        w={'30%'}
 | 
					      style={{
 | 
				
			||||||
        style={{
 | 
					        flexFlow: 'column',
 | 
				
			||||||
          float: 'right',
 | 
					      }}
 | 
				
			||||||
          // margin: '10px',
 | 
					    >
 | 
				
			||||||
          alignItems: 'end',
 | 
					      <Text fz={12} fs={'italic'} c={'red'} fw={600} mt={'md'}>
 | 
				
			||||||
          justifyContent: 'space-between',
 | 
					        {`* The current data is from ${JSON.parse(localStorage.getItem('data')!).date.startDate} to ${JSON.parse(localStorage.getItem('data')!).date.endDate}`}
 | 
				
			||||||
        }}
 | 
					      </Text>
 | 
				
			||||||
      >
 | 
					      <Text fz={12} fs={'italic'} c={'red'} fw={600}>
 | 
				
			||||||
        <DateInput
 | 
					        {`* If you need data outside this time period, please select a date and click "Search" to update the latest data.`}
 | 
				
			||||||
          size="xs"
 | 
					      </Text>
 | 
				
			||||||
          label="From date:"
 | 
					      <Box w={'100%'} display={'flex'} style={{ flexFlow: 'column' }}>
 | 
				
			||||||
          value={new Date(date.startDate)}
 | 
					        <Box
 | 
				
			||||||
          w={'40%'}
 | 
					          w={'100%'}
 | 
				
			||||||
          clearable
 | 
					          display={'flex'}
 | 
				
			||||||
          onChange={(e) => {
 | 
					          style={{
 | 
				
			||||||
            setDate({ ...date, startDate: moment(e).format('YYYY-MM-DD') })
 | 
					            alignItems: 'end',
 | 
				
			||||||
          }}
 | 
					            // justifyContent: 'space-between',
 | 
				
			||||||
        />
 | 
					            flexWrap: 'wrap',
 | 
				
			||||||
        <DateInput
 | 
					 | 
				
			||||||
          size="xs"
 | 
					 | 
				
			||||||
          label="To date:"
 | 
					 | 
				
			||||||
          value={new Date(date.endDate)}
 | 
					 | 
				
			||||||
          clearable
 | 
					 | 
				
			||||||
          w={'40%'}
 | 
					 | 
				
			||||||
          onChange={(e) => {
 | 
					 | 
				
			||||||
            setDate({ ...date, endDate: moment(e).format('YYYY-MM-DD') })
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
        <Button
 | 
					 | 
				
			||||||
          size="xs"
 | 
					 | 
				
			||||||
          onClick={() => {
 | 
					 | 
				
			||||||
            getAllWorklogs()
 | 
					 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          Search
 | 
					          <DateInput
 | 
				
			||||||
        </Button>
 | 
					            size="xs"
 | 
				
			||||||
 | 
					            label="From date:"
 | 
				
			||||||
 | 
					            value={new Date(date.startDate)}
 | 
				
			||||||
 | 
					            w={'20%'}
 | 
				
			||||||
 | 
					            clearable
 | 
				
			||||||
 | 
					            onChange={(e) => {
 | 
				
			||||||
 | 
					              setDate({ ...date, startDate: moment(e).format('YYYY-MM-DD') });
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <DateInput
 | 
				
			||||||
 | 
					            size="xs"
 | 
				
			||||||
 | 
					            label="To date:"
 | 
				
			||||||
 | 
					            value={new Date(date.endDate)}
 | 
				
			||||||
 | 
					            clearable
 | 
				
			||||||
 | 
					            m={"0 10px"}
 | 
				
			||||||
 | 
					            w={'20%'}
 | 
				
			||||||
 | 
					            onChange={(e) => {
 | 
				
			||||||
 | 
					              setDate({ ...date, endDate: moment(e).format('YYYY-MM-DD') });
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					          <Button
 | 
				
			||||||
 | 
					            size="xs"
 | 
				
			||||||
 | 
					            onClick={() => {
 | 
				
			||||||
 | 
					              getAllWorklogs();
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Search
 | 
				
			||||||
 | 
					          </Button>
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
      {/* Box main content */}
 | 
					    </Box>
 | 
				
			||||||
      <Box display={'flex'} mt={'lg'}>
 | 
					    {/* Box main content */}
 | 
				
			||||||
        <Box w={'10%'} >
 | 
					    <Box display={'flex'} mt={'lg'} style={{ flexWrap: 'wrap' }}>
 | 
				
			||||||
          <Text fw={700} fz={14}>
 | 
					      <Box w={{ base: '100%', md: '15%' }} mb={'lg'}>
 | 
				
			||||||
            Members
 | 
					        <Text fw={700} fz={14}>
 | 
				
			||||||
          </Text>
 | 
					          Members
 | 
				
			||||||
          <Box style={{border:"solid 1px gray", padding:"10px", marginRight:"10px", borderRadius:"5px", boxShadow: '1px 1px 5px 1px gray',}}>
 | 
					        </Text>
 | 
				
			||||||
            {worklogs.map((w) => (
 | 
					        <Box
 | 
				
			||||||
 | 
					          style={{
 | 
				
			||||||
 | 
					            border: 'solid 1px gray',
 | 
				
			||||||
 | 
					            padding: '10px 20px',
 | 
				
			||||||
 | 
					            marginRight: '10px',
 | 
				
			||||||
 | 
					            borderRadius: '5px',
 | 
				
			||||||
 | 
					            boxShadow: '1px 1px 5px 1px gray',
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          {worklogs.map((w) => (
 | 
				
			||||||
            <Box
 | 
					            <Box
 | 
				
			||||||
              key={w.username}
 | 
					              key={w.username}
 | 
				
			||||||
              style={{
 | 
					              style={{
 | 
				
			||||||
| 
						 | 
					@ -251,309 +274,259 @@ const Worklogs = () => {
 | 
				
			||||||
              </a>
 | 
					              </a>
 | 
				
			||||||
            </Box>
 | 
					            </Box>
 | 
				
			||||||
          ))}
 | 
					          ))}
 | 
				
			||||||
          </Box>
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
        <Box
 | 
					      </Box>
 | 
				
			||||||
          w={'90%'}
 | 
					      <Box
 | 
				
			||||||
          h={'85vh'}
 | 
					        w={{ base: '100%', md: '85%' }}
 | 
				
			||||||
          display={'flex'}
 | 
					        h={'85vh'}
 | 
				
			||||||
          style={{ overflowX: 'auto', flexFlow: 'column' }}
 | 
					        display={'flex'}
 | 
				
			||||||
        >
 | 
					        style={{ overflowX: 'auto', flexFlow: 'column' }}
 | 
				
			||||||
          {worklogs?.map((user, index) => (
 | 
					      >
 | 
				
			||||||
            // Box user
 | 
					        {worklogs?.map((user, index) => (
 | 
				
			||||||
            <Box
 | 
					          // Box user
 | 
				
			||||||
              id={user.username}
 | 
					          <Box
 | 
				
			||||||
              key={index}
 | 
					            id={user.username}
 | 
				
			||||||
              p={'sm'}
 | 
					            key={index}
 | 
				
			||||||
              style={{
 | 
					            p={'sm'}
 | 
				
			||||||
                border: 'solid 1px gray',
 | 
					            style={{
 | 
				
			||||||
                borderRadius: '5px',
 | 
					              border: 'solid 1px gray',
 | 
				
			||||||
                borderColor: '#afafaf',
 | 
					              borderRadius: '5px',
 | 
				
			||||||
                marginBottom: '10px',
 | 
					              borderColor: '#afafaf',
 | 
				
			||||||
                backgroundColor:
 | 
					              marginBottom: '10px',
 | 
				
			||||||
                  index % 2 === 0 ? 'rgb(201 201 201 / 28%)' : 'white',
 | 
					              backgroundColor: index % 2 === 0 ? 'rgb(201 201 201 / 28%)' : 'white',
 | 
				
			||||||
              }}
 | 
					            }}
 | 
				
			||||||
            >
 | 
					          >
 | 
				
			||||||
              <Text ta={'left'} mb={'xs'} fw={800} display={'flex'}>
 | 
					            <Text ta={'left'} mb={'xs'} fw={800} display={'flex'}>
 | 
				
			||||||
                <Avatar
 | 
					              <Avatar src={user.user.avatarUrls['48x48']} size={'sm'} m={'0 5px'} />
 | 
				
			||||||
                  src={user.user.avatarUrls['48x48']}
 | 
					              {user.username}(
 | 
				
			||||||
                  size={'sm'}
 | 
					              {user?.information.issues.reduce((total, issue) => {
 | 
				
			||||||
                  m={'0 5px'}
 | 
					                const totalSpent = issue.fields.worklog.worklogs?.reduce(
 | 
				
			||||||
                />
 | 
					                  (accumulator, currentValue) => {
 | 
				
			||||||
                {user.username}(
 | 
					                    if (
 | 
				
			||||||
                {user?.information.issues.reduce(
 | 
					                      parseInt(moment(date.startDate).format('YYYYMMDD')) <=
 | 
				
			||||||
                  (total: number, issue: Issue) => {
 | 
					                        parseInt(moment(currentValue.started).format('YYYYMMDD')) &&
 | 
				
			||||||
                    var totalSpent = issue.fields.worklog.worklogs?.reduce(
 | 
					                      parseInt(moment(currentValue.started).format('YYYYMMDD')) <=
 | 
				
			||||||
                      (accumulator: number, currentValue: WorkLog) => {
 | 
					                        parseInt(moment(date.endDate).format('YYYYMMDD')) &&
 | 
				
			||||||
                        if (
 | 
					                      currentValue.updateAuthor.displayName === user.username
 | 
				
			||||||
                          parseInt(moment(date.startDate).format('YYYYMMDD')) <=
 | 
					                    ) {
 | 
				
			||||||
                            parseInt(
 | 
					                      return accumulator + currentValue.timeSpentSeconds;
 | 
				
			||||||
                              moment(currentValue.started).format('YYYYMMDD'),
 | 
					                    }
 | 
				
			||||||
                            ) &&
 | 
					                    return accumulator;
 | 
				
			||||||
                          parseInt(
 | 
					 | 
				
			||||||
                            moment(currentValue.started).format('YYYYMMDD'),
 | 
					 | 
				
			||||||
                          ) <=
 | 
					 | 
				
			||||||
                            parseInt(moment(date.endDate).format('YYYYMMDD')) &&
 | 
					 | 
				
			||||||
                          currentValue.updateAuthor.displayName ===
 | 
					 | 
				
			||||||
                            user.username
 | 
					 | 
				
			||||||
                        ) {
 | 
					 | 
				
			||||||
                          return accumulator + currentValue.timeSpentSeconds
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        return accumulator
 | 
					 | 
				
			||||||
                      },
 | 
					 | 
				
			||||||
                      0,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    return total + totalSpent
 | 
					 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  0,
 | 
					                  0,
 | 
				
			||||||
                ) /
 | 
					                );
 | 
				
			||||||
                  60 /
 | 
					                return total + totalSpent;
 | 
				
			||||||
                  60}
 | 
					              }, 0) /
 | 
				
			||||||
                h)
 | 
					                60 /
 | 
				
			||||||
              </Text>
 | 
					                60}
 | 
				
			||||||
              {/* Box issue-todo */}
 | 
					              h)
 | 
				
			||||||
              <Box display={'flex'} style={{ justifyContent: 'space-between' }}>
 | 
					            </Text>
 | 
				
			||||||
                {/* Box issue */}
 | 
					            {/* Box issue-todo */}
 | 
				
			||||||
                <Box
 | 
					            <Box display={'flex'} style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}>
 | 
				
			||||||
                  w={'50%'}
 | 
					              {/* Box issue */}
 | 
				
			||||||
                  style={{
 | 
					              <Box
 | 
				
			||||||
                    border: 'solid 1px gray',
 | 
					                w={{ base: '100%', md: '50%' }}
 | 
				
			||||||
                    borderRadius: '5px',
 | 
					                style={{
 | 
				
			||||||
                    padding: '10px',
 | 
					                  border: 'solid 1px gray',
 | 
				
			||||||
                    marginBottom: '5px',
 | 
					                  borderRadius: '5px',
 | 
				
			||||||
                    overflowX: 'hidden',
 | 
					                  padding: '10px',
 | 
				
			||||||
                    color: '#412d2d',
 | 
					                  marginBottom: '5px',
 | 
				
			||||||
                    backgroundColor: '#d1cdce',
 | 
					                  overflowX: 'hidden',
 | 
				
			||||||
                  }}
 | 
					                  color: '#412d2d',
 | 
				
			||||||
                >
 | 
					                  backgroundColor: '#d1cdce',
 | 
				
			||||||
                  <Text fw={700} ta={'center'} mb={'5px'}>
 | 
					                }}
 | 
				
			||||||
                    WORKLOG
 | 
					              >
 | 
				
			||||||
                  </Text>
 | 
					                <Text fw={700} ta={'center'} mb={'5px'}>
 | 
				
			||||||
                  {user.information.issues.map((iss) => {
 | 
					                  WORKLOG
 | 
				
			||||||
                    if (
 | 
					                </Text>
 | 
				
			||||||
                      iss.fields.worklog.worklogs.filter(
 | 
					                {user.information.issues.map((iss) => {
 | 
				
			||||||
                        (w) =>
 | 
					                  if (
 | 
				
			||||||
                          parseInt(moment(date.startDate).format('YYYYMMDD')) <=
 | 
					                    iss.fields.worklog.worklogs.filter(
 | 
				
			||||||
                            parseInt(moment(w.started).format('YYYYMMDD')) &&
 | 
					                      (w) =>
 | 
				
			||||||
                          parseInt(moment(date.endDate).format('YYYYMMDD')) >=
 | 
					                        parseInt(moment(date.startDate).format('YYYYMMDD')) <=
 | 
				
			||||||
                            parseInt(moment(w.started).format('YYYYMMDD')) &&
 | 
					                          parseInt(moment(w.started).format('YYYYMMDD')) &&
 | 
				
			||||||
                          w.updateAuthor.displayName === user.username,
 | 
					                        parseInt(moment(date.endDate).format('YYYYMMDD')) >=
 | 
				
			||||||
                      ).length > 0
 | 
					                          parseInt(moment(w.started).format('YYYYMMDD')) &&
 | 
				
			||||||
                    ) {
 | 
					                        w.updateAuthor.displayName === user.username,
 | 
				
			||||||
                      return (
 | 
					                    ).length > 0
 | 
				
			||||||
                        <Box
 | 
					                  ) {
 | 
				
			||||||
                          key={iss.id}
 | 
					 | 
				
			||||||
                          style={{
 | 
					 | 
				
			||||||
                            border: 'solid 1px gray',
 | 
					 | 
				
			||||||
                            borderRadius: '5px',
 | 
					 | 
				
			||||||
                            boxShadow: '1px 1px 5px 1px gray',
 | 
					 | 
				
			||||||
                            padding: '10px',
 | 
					 | 
				
			||||||
                            marginBottom: '8px',
 | 
					 | 
				
			||||||
                            maxHeight: '90vh',
 | 
					 | 
				
			||||||
                            overflowX: 'hidden',
 | 
					 | 
				
			||||||
                            color: '#412d2d',
 | 
					 | 
				
			||||||
                            backgroundColor: 'white',
 | 
					 | 
				
			||||||
                          }}
 | 
					 | 
				
			||||||
                        >
 | 
					 | 
				
			||||||
                          {/* Box information issue */}
 | 
					 | 
				
			||||||
                          <Box>
 | 
					 | 
				
			||||||
                            <Text
 | 
					 | 
				
			||||||
                              fz={14}
 | 
					 | 
				
			||||||
                              display={'flex'}
 | 
					 | 
				
			||||||
                              style={{ alignItems: 'start' }}
 | 
					 | 
				
			||||||
                            >
 | 
					 | 
				
			||||||
                              <b>Summary:</b>{' '}
 | 
					 | 
				
			||||||
                              <Box
 | 
					 | 
				
			||||||
                                display={'flex'}
 | 
					 | 
				
			||||||
                                style={{ alignItems: 'center' }}
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                                <Avatar
 | 
					 | 
				
			||||||
                                  src={iss.fields.project?.avatarUrls['16x16']}
 | 
					 | 
				
			||||||
                                  size={'xs'}
 | 
					 | 
				
			||||||
                                  m={'0 5px'}
 | 
					 | 
				
			||||||
                                />
 | 
					 | 
				
			||||||
                                <Text fz={14} mr={'xs'}>
 | 
					 | 
				
			||||||
                                  {iss.fields.project.name}
 | 
					 | 
				
			||||||
                                </Text>
 | 
					 | 
				
			||||||
                              </Box>
 | 
					 | 
				
			||||||
                              <a
 | 
					 | 
				
			||||||
                                href={`https://apactechvn.atlassian.net/browse/${iss.key}`}
 | 
					 | 
				
			||||||
                                target="_blank"
 | 
					 | 
				
			||||||
                              >
 | 
					 | 
				
			||||||
                                {iss.fields.summary}
 | 
					 | 
				
			||||||
                              </a>
 | 
					 | 
				
			||||||
                            </Text>
 | 
					 | 
				
			||||||
                            <Text fz={14}>
 | 
					 | 
				
			||||||
                              <b>Estimate:</b>{' '}
 | 
					 | 
				
			||||||
                              {iss.fields.timeoriginalestimate / 60 / 60}h
 | 
					 | 
				
			||||||
                            </Text>
 | 
					 | 
				
			||||||
                            <Text fz={14}>
 | 
					 | 
				
			||||||
                              <b>Total time spent:</b>{' '}
 | 
					 | 
				
			||||||
                              {iss.fields.timespent / 60 / 60}h
 | 
					 | 
				
			||||||
                            </Text>
 | 
					 | 
				
			||||||
                            <Text fz={14}>
 | 
					 | 
				
			||||||
                              <b>Time spent <span style={{fontSize:"11px"}}>({date.startDate === date.endDate ? date.startDate : date.startDate+" to "+date.endDate})</span>:</b>
 | 
					 | 
				
			||||||
                              {' '}{iss.fields.worklog.worklogs?.reduce(
 | 
					 | 
				
			||||||
                                (
 | 
					 | 
				
			||||||
                                  accumulator: number,
 | 
					 | 
				
			||||||
                                  currentValue: WorkLog,
 | 
					 | 
				
			||||||
                                ) => {
 | 
					 | 
				
			||||||
                                  if (
 | 
					 | 
				
			||||||
                                    parseInt(
 | 
					 | 
				
			||||||
                                      moment(date.startDate).format('YYYYMMDD'),
 | 
					 | 
				
			||||||
                                    ) <=
 | 
					 | 
				
			||||||
                                      parseInt(
 | 
					 | 
				
			||||||
                                        moment(currentValue.started).format(
 | 
					 | 
				
			||||||
                                          'YYYYMMDD',
 | 
					 | 
				
			||||||
                                        ),
 | 
					 | 
				
			||||||
                                      ) &&
 | 
					 | 
				
			||||||
                                    parseInt(
 | 
					 | 
				
			||||||
                                      moment(currentValue.started).format(
 | 
					 | 
				
			||||||
                                        'YYYYMMDD',
 | 
					 | 
				
			||||||
                                      ),
 | 
					 | 
				
			||||||
                                    ) <=
 | 
					 | 
				
			||||||
                                      parseInt(
 | 
					 | 
				
			||||||
                                        moment(date.endDate).format('YYYYMMDD'),
 | 
					 | 
				
			||||||
                                      ) &&
 | 
					 | 
				
			||||||
                                    currentValue.updateAuthor.displayName ===
 | 
					 | 
				
			||||||
                                      user.username
 | 
					 | 
				
			||||||
                                  ) {
 | 
					 | 
				
			||||||
                                    return (
 | 
					 | 
				
			||||||
                                      accumulator +
 | 
					 | 
				
			||||||
                                      currentValue.timeSpentSeconds
 | 
					 | 
				
			||||||
                                    )
 | 
					 | 
				
			||||||
                                  }
 | 
					 | 
				
			||||||
                                  return accumulator
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                                0,
 | 
					 | 
				
			||||||
                              ) /
 | 
					 | 
				
			||||||
                                60 /
 | 
					 | 
				
			||||||
                                60}
 | 
					 | 
				
			||||||
                              h
 | 
					 | 
				
			||||||
                            </Text>
 | 
					 | 
				
			||||||
                          </Box>
 | 
					 | 
				
			||||||
                          {iss.fields.worklog.worklogs?.map((log, index) => {
 | 
					 | 
				
			||||||
                            if (
 | 
					 | 
				
			||||||
                              moment(date.startDate).format('YYYYMMDD') <=
 | 
					 | 
				
			||||||
                                moment(log.started).format('YYYYMMDD') &&
 | 
					 | 
				
			||||||
                              moment(log.started).format('YYYYMMDD') <=
 | 
					 | 
				
			||||||
                                moment(date.endDate).format('YYYYMMDD') &&
 | 
					 | 
				
			||||||
                              log.updateAuthor.displayName === user.username
 | 
					 | 
				
			||||||
                            ) {
 | 
					 | 
				
			||||||
                              return (
 | 
					 | 
				
			||||||
                                // Box worklog
 | 
					 | 
				
			||||||
                                <Box
 | 
					 | 
				
			||||||
                                  key={index}
 | 
					 | 
				
			||||||
                                  style={{
 | 
					 | 
				
			||||||
                                    padding: '4px 8px',
 | 
					 | 
				
			||||||
                                    marginBottom: '5px',
 | 
					 | 
				
			||||||
                                    marginLeft: '10px',
 | 
					 | 
				
			||||||
                                    backgroundColor: '#d9d9d9',
 | 
					 | 
				
			||||||
                                  }}
 | 
					 | 
				
			||||||
                                >
 | 
					 | 
				
			||||||
                                  <Text fz={13}>
 | 
					 | 
				
			||||||
                                    <b>Start date:</b>{' '}
 | 
					 | 
				
			||||||
                                    {moment(log.started).format(
 | 
					 | 
				
			||||||
                                      'HH:mm YYYY/MM/DD',
 | 
					 | 
				
			||||||
                                    )}
 | 
					 | 
				
			||||||
                                  </Text>
 | 
					 | 
				
			||||||
                                  <Text fz={13}>
 | 
					 | 
				
			||||||
                                    <b>Time spent:</b> {log.timeSpent}
 | 
					 | 
				
			||||||
                                  </Text>
 | 
					 | 
				
			||||||
                                  {log?.comment &&
 | 
					 | 
				
			||||||
                                    log?.comment?.content[0]?.content[0]
 | 
					 | 
				
			||||||
                                      ?.text && (
 | 
					 | 
				
			||||||
                                      <Text fz={13}>
 | 
					 | 
				
			||||||
                                        <b>Comment:</b>{' '}
 | 
					 | 
				
			||||||
                                        {log?.comment &&
 | 
					 | 
				
			||||||
                                          log?.comment?.content[0]?.content[0]
 | 
					 | 
				
			||||||
                                            ?.text}
 | 
					 | 
				
			||||||
                                      </Text>
 | 
					 | 
				
			||||||
                                    )}
 | 
					 | 
				
			||||||
                                </Box>
 | 
					 | 
				
			||||||
                              )
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                          })}
 | 
					 | 
				
			||||||
                        </Box>
 | 
					 | 
				
			||||||
                      )
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                  })}
 | 
					 | 
				
			||||||
                </Box>
 | 
					 | 
				
			||||||
                {/* Box todo */}
 | 
					 | 
				
			||||||
                <Box
 | 
					 | 
				
			||||||
                  w={'49%'}
 | 
					 | 
				
			||||||
                  style={{
 | 
					 | 
				
			||||||
                    border: 'solid 1px gray',
 | 
					 | 
				
			||||||
                    borderRadius: '5px',
 | 
					 | 
				
			||||||
                    padding: '10px',
 | 
					 | 
				
			||||||
                    marginBottom: '5px',
 | 
					 | 
				
			||||||
                    overflowX: 'hidden',
 | 
					 | 
				
			||||||
                    color: '#412d2d',
 | 
					 | 
				
			||||||
                    backgroundColor: '#f9ffa47a',
 | 
					 | 
				
			||||||
                  }}
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                  <Text fw={700} ta={'center'} mb={'5px'}>
 | 
					 | 
				
			||||||
                    ASSIGNMENT
 | 
					 | 
				
			||||||
                  </Text>
 | 
					 | 
				
			||||||
                  {user.tasksAssign.issues?.map((iss, index) => {
 | 
					 | 
				
			||||||
                    return (
 | 
					                    return (
 | 
				
			||||||
                      <Box
 | 
					                      <Box
 | 
				
			||||||
                        key={index}
 | 
					                        key={iss.id}
 | 
				
			||||||
                        style={{
 | 
					                        style={{
 | 
				
			||||||
                          border: 'solid 1px gray',
 | 
					                          border: 'solid 1px gray',
 | 
				
			||||||
                          borderRadius: '5px',
 | 
					                          borderRadius: '5px',
 | 
				
			||||||
                          boxShadow: '1px 1px 5px 1px gray',
 | 
					                          boxShadow: '1px 1px 5px 1px gray',
 | 
				
			||||||
                          padding: '10px',
 | 
					                          padding: '10px',
 | 
				
			||||||
                          marginBottom: '5px',
 | 
					                          marginBottom: '8px',
 | 
				
			||||||
 | 
					                          maxHeight: '90vh',
 | 
				
			||||||
                          overflowX: 'hidden',
 | 
					                          overflowX: 'hidden',
 | 
				
			||||||
                          color: '#412d2d',
 | 
					                          color: '#412d2d',
 | 
				
			||||||
                          backgroundColor: 'white',
 | 
					                          backgroundColor: 'white',
 | 
				
			||||||
                        }}
 | 
					                        }}
 | 
				
			||||||
                      >
 | 
					                      >
 | 
				
			||||||
                        <Box display={'flex'} style={{ alignItems: 'center' }}>
 | 
					                        {/* Box information issue */}
 | 
				
			||||||
                          <Avatar
 | 
					                        <Box>
 | 
				
			||||||
                            src={iss.fields.project?.avatarUrls['16x16']}
 | 
					                          <Text fz={14} c={iss.fields.status.statusCategory.colorName}>
 | 
				
			||||||
                            size={'xs'}
 | 
					                            <b>{iss.fields.status.name}</b>
 | 
				
			||||||
                            m={'0 5px 0 0'}
 | 
					                          </Text>
 | 
				
			||||||
                          />
 | 
					                          <Text fz={14} display={'flex'} style={{ alignItems: 'start' }}>
 | 
				
			||||||
                          <Text fz={14} mr={'xs'}>
 | 
					                            <b>Summary:</b>{' '}
 | 
				
			||||||
                            {iss.fields.project.name}
 | 
					                            <Box display={'flex'} style={{ alignItems: 'center' }}>
 | 
				
			||||||
 | 
					                              <Avatar
 | 
				
			||||||
 | 
					                                src={iss.fields.project?.avatarUrls['16x16']}
 | 
				
			||||||
 | 
					                                size={'xs'}
 | 
				
			||||||
 | 
					                                m={'0 5px'}
 | 
				
			||||||
 | 
					                              />
 | 
				
			||||||
 | 
					                              <Text fz={14} mr={'xs'}>
 | 
				
			||||||
 | 
					                                {iss.fields.project.name}
 | 
				
			||||||
 | 
					                              </Text>
 | 
				
			||||||
 | 
					                            </Box>
 | 
				
			||||||
 | 
					                            <a href={`https://apactechvn.atlassian.net/browse/${iss.key}`} target="_blank">
 | 
				
			||||||
 | 
					                              {iss.fields.summary}
 | 
				
			||||||
 | 
					                            </a>
 | 
				
			||||||
 | 
					                          </Text>
 | 
				
			||||||
 | 
					                          <Text fz={14}>
 | 
				
			||||||
 | 
					                            <b>Estimate:</b> {iss.fields.timeoriginalestimate / 60 / 60}h
 | 
				
			||||||
 | 
					                          </Text>
 | 
				
			||||||
 | 
					                          <Text fz={14}>
 | 
				
			||||||
 | 
					                            <b>Total time spent:</b> {iss.fields.timespent / 60 / 60}h
 | 
				
			||||||
 | 
					                          </Text>
 | 
				
			||||||
 | 
					                          <Text fz={14}>
 | 
				
			||||||
 | 
					                            <b>
 | 
				
			||||||
 | 
					                              Time spent{' '}
 | 
				
			||||||
 | 
					                              <span style={{ fontSize: '11px' }}>
 | 
				
			||||||
 | 
					                                (
 | 
				
			||||||
 | 
					                                {date.startDate === date.endDate
 | 
				
			||||||
 | 
					                                  ? date.startDate
 | 
				
			||||||
 | 
					                                  : date.startDate + ' to ' + date.endDate}
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					                              </span>
 | 
				
			||||||
 | 
					                              :
 | 
				
			||||||
 | 
					                            </b>{' '}
 | 
				
			||||||
 | 
					                            {iss.fields.worklog.worklogs?.reduce(
 | 
				
			||||||
 | 
					                              (accumulator, currentValue) => {
 | 
				
			||||||
 | 
					                                if (
 | 
				
			||||||
 | 
					                                  parseInt(moment(date.startDate).format('YYYYMMDD')) <=
 | 
				
			||||||
 | 
					                                    parseInt(moment(currentValue.started).format('YYYYMMDD')) &&
 | 
				
			||||||
 | 
					                                  parseInt(moment(currentValue.started).format('YYYYMMDD')) <=
 | 
				
			||||||
 | 
					                                    parseInt(moment(date.endDate).format('YYYYMMDD')) &&
 | 
				
			||||||
 | 
					                                  currentValue.updateAuthor.displayName === user.username
 | 
				
			||||||
 | 
					                                ) {
 | 
				
			||||||
 | 
					                                  return accumulator + currentValue.timeSpentSeconds;
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                                return accumulator;
 | 
				
			||||||
 | 
					                              },
 | 
				
			||||||
 | 
					                              0,
 | 
				
			||||||
 | 
					                            ) /
 | 
				
			||||||
 | 
					                              60 /
 | 
				
			||||||
 | 
					                              60}
 | 
				
			||||||
 | 
					                            h
 | 
				
			||||||
                          </Text>
 | 
					                          </Text>
 | 
				
			||||||
                        </Box>
 | 
					                        </Box>
 | 
				
			||||||
                        <Text
 | 
					                        {iss.fields.worklog.worklogs?.map((log, index) => {
 | 
				
			||||||
                          fz={14}
 | 
					                          if (
 | 
				
			||||||
                          display={'flex'}
 | 
					                            moment(date.startDate).format('YYYYMMDD') <= moment(log.started).format('YYYYMMDD') &&
 | 
				
			||||||
                          style={{ alignItems: 'start' }}
 | 
					                            moment(log.started).format('YYYYMMDD') <= moment(date.endDate).format('YYYYMMDD') &&
 | 
				
			||||||
                        >
 | 
					                            log.updateAuthor.displayName === user.username
 | 
				
			||||||
                          <b style={{ marginRight: '5px' }}>Summary:</b>
 | 
					                          ) {
 | 
				
			||||||
                          <a
 | 
					                            return (
 | 
				
			||||||
                            href={`https://apactechvn.atlassian.net/browse/${iss.key}`}
 | 
					                              // Box worklog
 | 
				
			||||||
                            target="_blank"
 | 
					                              <Box
 | 
				
			||||||
                          >
 | 
					                                key={index}
 | 
				
			||||||
                            {iss.fields.summary}
 | 
					                                style={{
 | 
				
			||||||
                          </a>
 | 
					                                  padding: '4px 8px',
 | 
				
			||||||
                        </Text>
 | 
					                                  marginBottom: '5px',
 | 
				
			||||||
                        <Text fz={13}>
 | 
					                                  marginLeft: '10px',
 | 
				
			||||||
                          <b>Time spent:</b> {iss.fields.timespent / 60 / 60}h
 | 
					                                  backgroundColor: '#d9d9d9',
 | 
				
			||||||
                        </Text>
 | 
					                                }}
 | 
				
			||||||
                        <Text fz={13}>
 | 
					                              >
 | 
				
			||||||
                          <b>Estimate:</b> {iss.fields.timeoriginalestimate / 60 / 60}h
 | 
					                                <Text fz={13}>
 | 
				
			||||||
                        </Text>
 | 
					                                  <b>Start date:</b> {moment(log.started).format('HH:mm YYYY/MM/DD')}
 | 
				
			||||||
                        <Text fz={'14'}>
 | 
					                                </Text>
 | 
				
			||||||
                          <b style={{ marginRight: '5px' }}>Status:</b>
 | 
					                                <Text fz={13}>
 | 
				
			||||||
                          {iss.fields.status.name}
 | 
					                                  <b>Time spent:</b> {log.timeSpent}
 | 
				
			||||||
 | 
					                                </Text>
 | 
				
			||||||
 | 
					                                {log?.comment && log?.comment?.content[0]?.content[0]?.text && (
 | 
				
			||||||
 | 
					                                  <Text fz={13}>
 | 
				
			||||||
 | 
					                                    <b>Comment:</b> {log?.comment?.content[0]?.content[0]?.text}
 | 
				
			||||||
 | 
					                                  </Text>
 | 
				
			||||||
 | 
					                                )}
 | 
				
			||||||
 | 
					                              </Box>
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					                          }
 | 
				
			||||||
 | 
					                        })}
 | 
				
			||||||
 | 
					                      </Box>
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                })}
 | 
				
			||||||
 | 
					              </Box>
 | 
				
			||||||
 | 
					              {/* Box todo */}
 | 
				
			||||||
 | 
					              <Box
 | 
				
			||||||
 | 
					                w={{ base: '100%', md: '49%' }}
 | 
				
			||||||
 | 
					                style={{
 | 
				
			||||||
 | 
					                  border: 'solid 1px gray',
 | 
				
			||||||
 | 
					                  borderRadius: '5px',
 | 
				
			||||||
 | 
					                  padding: '10px',
 | 
				
			||||||
 | 
					                  marginBottom: '5px',
 | 
				
			||||||
 | 
					                  overflowX: 'hidden',
 | 
				
			||||||
 | 
					                  color: '#412d2d',
 | 
				
			||||||
 | 
					                  backgroundColor: '#f9ffa47a',
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                <Text fw={700} ta={'center'} mb={'5px'}>
 | 
				
			||||||
 | 
					                  ASSIGNMENT
 | 
				
			||||||
 | 
					                </Text>
 | 
				
			||||||
 | 
					                {user.tasksAssign.issues?.map((iss, index) => {
 | 
				
			||||||
 | 
					                  return (
 | 
				
			||||||
 | 
					                    <Box
 | 
				
			||||||
 | 
					                      key={index}
 | 
				
			||||||
 | 
					                      style={{
 | 
				
			||||||
 | 
					                        border: 'solid 1px gray',
 | 
				
			||||||
 | 
					                        borderRadius: '5px',
 | 
				
			||||||
 | 
					                        boxShadow: '1px 1px 5px 1px gray',
 | 
				
			||||||
 | 
					                        padding: '10px',
 | 
				
			||||||
 | 
					                        marginBottom: '5px',
 | 
				
			||||||
 | 
					                        overflowX: 'hidden',
 | 
				
			||||||
 | 
					                        color: '#412d2d',
 | 
				
			||||||
 | 
					                        backgroundColor: 'white',
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      <Box display={'flex'} style={{ alignItems: 'center' }}>
 | 
				
			||||||
 | 
					                        <Avatar
 | 
				
			||||||
 | 
					                          src={iss.fields.project?.avatarUrls['16x16']}
 | 
				
			||||||
 | 
					                          size={'xs'}
 | 
				
			||||||
 | 
					                          m={'0 5px 0 0'}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                        <Text fz={14} mr={'xs'}>
 | 
				
			||||||
 | 
					                          {iss.fields.project.name}
 | 
				
			||||||
                        </Text>
 | 
					                        </Text>
 | 
				
			||||||
                      </Box>
 | 
					                      </Box>
 | 
				
			||||||
                    )
 | 
					                      <Text fz={14} display={'flex'} style={{ alignItems: 'start' }}>
 | 
				
			||||||
                  })}
 | 
					                        <b style={{ marginRight: '5px' }}>Summary:</b>
 | 
				
			||||||
                </Box>
 | 
					                        <a href={`https://apactechvn.atlassian.net/browse/${iss.key}`} target="_blank">
 | 
				
			||||||
 | 
					                          {iss.fields.summary}
 | 
				
			||||||
 | 
					                        </a>
 | 
				
			||||||
 | 
					                      </Text>
 | 
				
			||||||
 | 
					                      <Text fz={13}>
 | 
				
			||||||
 | 
					                        <b>Time spent:</b> {iss.fields.timespent / 60 / 60}h
 | 
				
			||||||
 | 
					                      </Text>
 | 
				
			||||||
 | 
					                      <Text fz={13}>
 | 
				
			||||||
 | 
					                        <b>Estimate:</b> {iss.fields.timeoriginalestimate / 60 / 60}h
 | 
				
			||||||
 | 
					                      </Text>
 | 
				
			||||||
 | 
					                      <Text fz={14} c={iss.fields.status.statusCategory.colorName}>
 | 
				
			||||||
 | 
					                        <b>{iss.fields.status.name}</b>
 | 
				
			||||||
 | 
					                      </Text>
 | 
				
			||||||
 | 
					                    </Box>
 | 
				
			||||||
 | 
					                  );
 | 
				
			||||||
 | 
					                })}
 | 
				
			||||||
              </Box>
 | 
					              </Box>
 | 
				
			||||||
            </Box>
 | 
					            </Box>
 | 
				
			||||||
          ))}
 | 
					          </Box>
 | 
				
			||||||
        </Box>
 | 
					        ))}
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
    </div>
 | 
					    </Box>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue