Merge branch 'master' of https://gitea.nswteam.net/joseph/ManagementSystem into Sprint-4/MS-36-FE-Technical
This commit is contained in:
		
						commit
						885dd40dd9
					
				| 
						 | 
					@ -119,6 +119,7 @@ class TechnicalController extends Controller
 | 
				
			||||||
            ->where('user_id', $userId)
 | 
					            ->where('user_id', $userId)
 | 
				
			||||||
            ->where('point', '>', 0)
 | 
					            ->where('point', '>', 0)
 | 
				
			||||||
            ->orderBy('point', 'desc')
 | 
					            ->orderBy('point', 'desc')
 | 
				
			||||||
 | 
					            ->orderBy('updated_at', 'desc')
 | 
				
			||||||
            ->get();
 | 
					            ->get();
 | 
				
			||||||
        if ($technicals->isEmpty()) {
 | 
					        if ($technicals->isEmpty()) {
 | 
				
			||||||
            return [];
 | 
					            return [];
 | 
				
			||||||
| 
						 | 
					@ -221,16 +222,25 @@ class TechnicalController extends Controller
 | 
				
			||||||
            'technicals.*.point' => 'required|integer|min:0|max:3', // Điểm trong khoảng [0-3]
 | 
					            'technicals.*.point' => 'required|integer|min:0|max:3', // Điểm trong khoảng [0-3]
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Xóa hết các bản ghi hiện có của user trong bảng technical_users
 | 
					        $existingTechnicals = TechnicalUser::where('user_id', $userInfo->id)->get()->keyBy('technical_id');
 | 
				
			||||||
        TechnicalUser::where('user_id', $userInfo->id)->delete();
 | 
					        
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Duyệt qua mảng technicals và thêm mới dữ liệu
 | 
					 | 
				
			||||||
        foreach ($validatedData['technicals'] as $technical) {
 | 
					        foreach ($validatedData['technicals'] as $technical) {
 | 
				
			||||||
            TechnicalUser::create([
 | 
					            $existingTechnical = $existingTechnicals->get($technical['technical_id']);
 | 
				
			||||||
                'user_id' => $userInfo->id,
 | 
					            if ($existingTechnical) {
 | 
				
			||||||
                'technical_id' => $technical['technical_id'],
 | 
					                // Nếu technical_id đã tồn tại và point khác, thì update
 | 
				
			||||||
                'point' => $technical['point']
 | 
					                if ($existingTechnical->point !== $technical['point']) {
 | 
				
			||||||
            ]);
 | 
					                    $existingTechnical->update([
 | 
				
			||||||
 | 
					                        'point' => $technical['point']
 | 
				
			||||||
 | 
					                    ]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // Nếu technical_id chưa tồn tại, tạo mới
 | 
				
			||||||
 | 
					                TechnicalUser::create([
 | 
				
			||||||
 | 
					                    'user_id' => $userInfo->id,
 | 
				
			||||||
 | 
					                    'technical_id' => $technical['technical_id'],
 | 
				
			||||||
 | 
					                    'point' => $technical['point']
 | 
				
			||||||
 | 
					                ]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return AbstractController::ResultSuccess('Technicals for user updated successfully.');
 | 
					        return AbstractController::ResultSuccess('Technicals for user updated successfully.');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,8 +107,8 @@ Route::middleware('api')
 | 
				
			||||||
                Route::get('/fetch-issues', [JiraController::class, 'fetchAllIssues']);
 | 
					                Route::get('/fetch-issues', [JiraController::class, 'fetchAllIssues']);
 | 
				
			||||||
                Route::get('/all-project', [JiraController::class, 'getAllProject']);
 | 
					                Route::get('/all-project', [JiraController::class, 'getAllProject']);
 | 
				
			||||||
                Route::get('/get-detail-project-by-id', [JiraController::class, 'getDetailsProjectsById']);
 | 
					                Route::get('/get-detail-project-by-id', [JiraController::class, 'getDetailsProjectsById']);
 | 
				
			||||||
                Route::get('/get-all-board-by-id-project', [JiraController::class, 'getAllBoardByIdProjects']);
 | 
					                Route::get('/get-all-board-by-id-project', [JiraController::class, 'getAllBoardByIdProjects'])->middleware('check.permission:admin.tester');
 | 
				
			||||||
                Route::get('/get-all-sprint-by-id-board', [JiraController::class, 'getAllSprintByIdBoard']);
 | 
					                Route::get('/get-all-sprint-by-id-board', [JiraController::class, 'getAllSprintByIdBoard'])->middleware('check.permission:admin.tester');
 | 
				
			||||||
                Route::get('/get-all-issue-by-id-sprint', [JiraController::class, 'getAllIssueByIdSprint']);
 | 
					                Route::get('/get-all-issue-by-id-sprint', [JiraController::class, 'getAllIssueByIdSprint']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Route::get('/all-issue-by-project', [JiraController::class, 'fetchIssuesByProject']);
 | 
					                Route::get('/all-issue-by-project', [JiraController::class, 'fetchIssuesByProject']);
 | 
				
			||||||
| 
						 | 
					@ -168,9 +168,9 @@ Route::middleware('api')
 | 
				
			||||||
                Route::get('/getAll', [CriteriasController::class, 'getAllCriterias'])->middleware('check.permission:admin');
 | 
					                Route::get('/getAll', [CriteriasController::class, 'getAllCriterias'])->middleware('check.permission:admin');
 | 
				
			||||||
                Route::post('/sprints/{sprintId}', [CriteriasController::class, 'updateCriteriasForSprint'])->middleware('check.permission:admin');
 | 
					                Route::post('/sprints/{sprintId}', [CriteriasController::class, 'updateCriteriasForSprint'])->middleware('check.permission:admin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Route::get('/test-cases/getAll/{sprintId}', [TestCaseForSprintController::class, 'getAllReportsForSprint'])->middleware('check.permission:admin,tester');
 | 
					                Route::get('/test-cases/getAll/{sprintId}', [TestCaseForSprintController::class, 'getAllReportsForSprint'])->middleware('check.permission:admin.tester');
 | 
				
			||||||
                Route::post('/test-cases/{sprintId}', [TestCaseForSprintController::class, 'createTestReport'])->middleware('check.permission:admin,tester');
 | 
					                Route::post('/test-cases/{sprintId}', [TestCaseForSprintController::class, 'createTestReport'])->middleware('check.permission:admin.tester');
 | 
				
			||||||
                Route::get('/test-cases/delete', [TestCaseForSprintController::class, 'deleteTestReport'])->middleware('check.permission:admin,tester');
 | 
					                Route::get('/test-cases/delete', [TestCaseForSprintController::class, 'deleteTestReport'])->middleware('check.permission:admin.tester');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Route::get('/profiles-data', [ProfileController::class, 'getProfilesData'])->middleware('check.permission:admin.hr.staff.tester');
 | 
					                Route::get('/profiles-data', [ProfileController::class, 'getProfilesData'])->middleware('check.permission:admin.hr.staff.tester');
 | 
				
			||||||
                Route::post('/profiles-data/update', [ProfileController::class, 'updateProfilesData'])->middleware('check.permission:admin.hr.staff.tester');
 | 
					                Route::post('/profiles-data/update', [ProfileController::class, 'updateProfilesData'])->middleware('check.permission:admin.hr.staff.tester');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ class JiraService
 | 
				
			||||||
            $users_data[$user['displayName']]['total_spent'] = 0;
 | 
					            $users_data[$user['displayName']]['total_spent'] = 0;
 | 
				
			||||||
            $users_data[$user['displayName']]['total_est'] = 0;
 | 
					            $users_data[$user['displayName']]['total_est'] = 0;
 | 
				
			||||||
            $body = [
 | 
					            $body = [
 | 
				
			||||||
                'expand' => ['names', 'schema'],
 | 
					                'expand' => ['names', 'schema','changelog'],
 | 
				
			||||||
                'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project', 'updated'],
 | 
					                'fields' => ['summary', 'status', 'timeoriginalestimate', 'timespent', 'assignee', 'project', 'updated'],
 | 
				
			||||||
                'jql' => sprintf(
 | 
					                'jql' => sprintf(
 | 
				
			||||||
                    "assignee = '%s' AND status IN ('to do', 'todo', 'in progress') ORDER BY updated DESC",
 | 
					                    "assignee = '%s' AND status IN ('to do', 'todo', 'in progress') ORDER BY updated DESC",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,13 +5,13 @@
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  @keyframes blinkBackground {
 | 
					  @keyframes blinkBackground {
 | 
				
			||||||
    0% {
 | 
					    0% {
 | 
				
			||||||
      background-color: #ffa200; /* Màu vàng */
 | 
					      background-color: #ff5100; /* Màu vàng */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    50% {
 | 
					    50% {
 | 
				
			||||||
      background-color: #ffffff; /* Màu xanh */
 | 
					      background-color: #ffffff; /* Màu xanh */
 | 
				
			||||||
      color: rgb(0, 0, 0);
 | 
					      color: rgb(0, 0, 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    100% {
 | 
					    100% {
 | 
				
			||||||
      background-color: #ffa200; /* Màu vàng */
 | 
					      background-color: #ff5100; /* Màu vàng */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
					@ -478,7 +478,9 @@ const SprintReview = () => {
 | 
				
			||||||
            criteriaSprint.length == 0 || loading ? { display: 'none' } : {}
 | 
					            criteriaSprint.length == 0 || loading ? { display: 'none' } : {}
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          Criteria for Sprint:
 | 
					          Criteria for Sprint: <Box fs={'italic'} fz={'sm'}>
 | 
				
			||||||
 | 
					            <a href={`/test-report?projectID=${filter.projectID}&sprintID=${filter.sprintID}`} target='_blank'>Sprint test report</a>
 | 
				
			||||||
 | 
					          </Box>
 | 
				
			||||||
        </Title>
 | 
					        </Title>
 | 
				
			||||||
        <Box
 | 
					        <Box
 | 
				
			||||||
          style={{
 | 
					          style={{
 | 
				
			||||||
| 
						 | 
					@ -506,17 +508,17 @@ const SprintReview = () => {
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <Table.Thead>
 | 
					          <Table.Thead>
 | 
				
			||||||
            <Table.Tr bg="#228be66b" style={rowStyle}>
 | 
					            <Table.Tr bg="#228be66b" style={rowStyle}>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '15%' }}>
 | 
				
			||||||
                Criteria
 | 
					                Criteria
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '25%' }}>
 | 
				
			||||||
                Expect Result
 | 
					                Expect Result
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '25%' }}>
 | 
				
			||||||
                Actual Result
 | 
					                Actual Result
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center' }}>Note</Table.Th>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '30%' }}>Note</Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '100px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '5%' }}>
 | 
				
			||||||
                Point
 | 
					                Point
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
            </Table.Tr>
 | 
					            </Table.Tr>
 | 
				
			||||||
| 
						 | 
					@ -599,6 +601,7 @@ const SprintReview = () => {
 | 
				
			||||||
                    value={finalPoint}
 | 
					                    value={finalPoint}
 | 
				
			||||||
                    onChange={(value) => setFinalPoint(value ?? '')}
 | 
					                    onChange={(value) => setFinalPoint(value ?? '')}
 | 
				
			||||||
                    size="xs"
 | 
					                    size="xs"
 | 
				
			||||||
 | 
					                    w={'40%'}
 | 
				
			||||||
                    styles={() => ({
 | 
					                    styles={() => ({
 | 
				
			||||||
                      input: {
 | 
					                      input: {
 | 
				
			||||||
                        color: 'red',
 | 
					                        color: 'red',
 | 
				
			||||||
| 
						 | 
					@ -639,17 +642,17 @@ const SprintReview = () => {
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
          <Table.Thead>
 | 
					          <Table.Thead>
 | 
				
			||||||
            <Table.Tr bg="#228be66b" style={rowStyle}>
 | 
					            <Table.Tr bg="#228be66b" style={rowStyle}>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '15%' }}>
 | 
				
			||||||
                User
 | 
					                User
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '25%' }}>
 | 
				
			||||||
                Criteria
 | 
					                Criteria
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center' }}>Note</Table.Th>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '40%' }}>Note</Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '250px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '15%' }}>
 | 
				
			||||||
                Created by
 | 
					                Created by
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
              <Table.Th style={{ textAlign: 'center', width: '100px' }}>
 | 
					              <Table.Th style={{ textAlign: 'center', width: '5%' }}>
 | 
				
			||||||
                Point
 | 
					                Point
 | 
				
			||||||
              </Table.Th>
 | 
					              </Table.Th>
 | 
				
			||||||
            </Table.Tr>
 | 
					            </Table.Tr>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -304,10 +304,11 @@ const StaffEvaluation = () => {
 | 
				
			||||||
            User:
 | 
					            User:
 | 
				
			||||||
          </Text>
 | 
					          </Text>
 | 
				
			||||||
          <Select
 | 
					          <Select
 | 
				
			||||||
            style={{ width: '50%' }}
 | 
					            style={{ width: '30%' }}
 | 
				
			||||||
            label={''}
 | 
					            label={''}
 | 
				
			||||||
            placeholder="Select user"
 | 
					            placeholder="Select user"
 | 
				
			||||||
            maxLength={255}
 | 
					            maxLength={255}
 | 
				
			||||||
 | 
					            size={'xs'}
 | 
				
			||||||
            required
 | 
					            required
 | 
				
			||||||
            data={listUsers.map((i: User) => ({
 | 
					            data={listUsers.map((i: User) => ({
 | 
				
			||||||
              value: i.id.toString(),
 | 
					              value: i.id.toString(),
 | 
				
			||||||
| 
						 | 
					@ -338,7 +339,6 @@ const StaffEvaluation = () => {
 | 
				
			||||||
            w="100%"
 | 
					            w="100%"
 | 
				
			||||||
            display={'flex'}
 | 
					            display={'flex'}
 | 
				
			||||||
            mt={15}
 | 
					            mt={15}
 | 
				
			||||||
            style={{ justifyContent: 'space-evenly' }}
 | 
					 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            <Box display={'flex'} mr={10}>
 | 
					            <Box display={'flex'} mr={10}>
 | 
				
			||||||
              <Text
 | 
					              <Text
 | 
				
			||||||
| 
						 | 
					@ -353,6 +353,7 @@ const StaffEvaluation = () => {
 | 
				
			||||||
              <DateInput
 | 
					              <DateInput
 | 
				
			||||||
                placeholder="Select date"
 | 
					                placeholder="Select date"
 | 
				
			||||||
                clearable
 | 
					                clearable
 | 
				
			||||||
 | 
					                size='xs'
 | 
				
			||||||
                required
 | 
					                required
 | 
				
			||||||
                label={''}
 | 
					                label={''}
 | 
				
			||||||
                value={filter.fromDate ? new Date(filter.fromDate) : null}
 | 
					                value={filter.fromDate ? new Date(filter.fromDate) : null}
 | 
				
			||||||
| 
						 | 
					@ -373,6 +374,7 @@ const StaffEvaluation = () => {
 | 
				
			||||||
              <DateInput
 | 
					              <DateInput
 | 
				
			||||||
                placeholder="Select date"
 | 
					                placeholder="Select date"
 | 
				
			||||||
                clearable
 | 
					                clearable
 | 
				
			||||||
 | 
					                size='xs'
 | 
				
			||||||
                required
 | 
					                required
 | 
				
			||||||
                label={''}
 | 
					                label={''}
 | 
				
			||||||
                value={filter.toDate ? new Date(filter.toDate) : null}
 | 
					                value={filter.toDate ? new Date(filter.toDate) : null}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ const UsersManagement = () => {
 | 
				
			||||||
            <MultiSelect
 | 
					            <MultiSelect
 | 
				
			||||||
              label={'Permission(s)'}
 | 
					              label={'Permission(s)'}
 | 
				
			||||||
              required
 | 
					              required
 | 
				
			||||||
              data={['staff', 'admin', 'hr']}
 | 
					              data={['staff', 'admin', 'hr', 'tester']}
 | 
				
			||||||
              value={
 | 
					              value={
 | 
				
			||||||
                typeof form.values.permission === 'string'
 | 
					                typeof form.values.permission === 'string'
 | 
				
			||||||
                  ? form.values.permission
 | 
					                  ? form.values.permission
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue