Professor update
This commit is contained in:
@ -214,90 +214,82 @@ public class ProfessorServiceImpl implements ProfessorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public Professor updateProfessor(UUID professorId, ProfessorDto professorDto) {
|
public Professor updateProfessor(UUID professorId, ProfessorDto professorDto) {
|
||||||
Professor professor = professorRepository.findByProfessorId(professorId)
|
Professor professor = professorRepository.findByProfessorId(professorId)
|
||||||
.orElseThrow(() -> new RuntimeException("Professor not found with id: " + professorId));
|
.orElseThrow(() -> new RuntimeException("Professor not found with id: " + professorId));
|
||||||
|
|
||||||
validateUpdateEmail(professorId, professorDto.getEmail());
|
validateUpdateEmail(professorId, professorDto.getEmail());
|
||||||
|
|
||||||
// Update basic fields
|
// Update basic fields
|
||||||
professor.setFirstName(professorDto.getFirstName());
|
professor.setFirstName(professorDto.getFirstName());
|
||||||
professor.setLastName(professorDto.getLastName());
|
professor.setLastName(professorDto.getLastName());
|
||||||
professor.setEmail(professorDto.getEmail());
|
professor.setEmail(professorDto.getEmail());
|
||||||
professor.setDepartment(professorDto.getDepartment());
|
professor.setDepartment(professorDto.getDepartment());
|
||||||
professor.setPosition(professorDto.getPosition());
|
professor.setPosition(professorDto.getPosition());
|
||||||
professor.setOfficeLocation(professorDto.getOfficeLocation());
|
professor.setOfficeLocation(professorDto.getOfficeLocation());
|
||||||
professor.setStatus(professorDto.getStatus());
|
professor.setStatus(professorDto.getStatus());
|
||||||
professor.setCategory(professorDto.getCategory());
|
professor.setCategory(professorDto.getCategory());
|
||||||
|
|
||||||
// Update extended fields
|
// Update extended fields
|
||||||
professor.setPhone(professorDto.getPhone());
|
professor.setPhone(professorDto.getPhone());
|
||||||
professor.setSpecialty(professorDto.getSpecialty());
|
professor.setSpecialty(professorDto.getSpecialty());
|
||||||
professor.setCertification(professorDto.getCertification());
|
professor.setCertification(professorDto.getCertification());
|
||||||
professor.setTraining(professorDto.getTraining());
|
professor.setTraining(professorDto.getTraining());
|
||||||
professor.setExperience(professorDto.getExperience());
|
professor.setExperience(professorDto.getExperience());
|
||||||
professor.setDescription(professorDto.getDescription());
|
professor.setDescription(professorDto.getDescription());
|
||||||
professor.setDesignation(professorDto.getDesignation());
|
professor.setDesignation(professorDto.getDesignation());
|
||||||
professor.setWorkDays(professorDto.getWorkDays());
|
professor.setWorkDays(professorDto.getWorkDays());
|
||||||
|
|
||||||
if (professorDto.getJoinDate() != null) {
|
if (professorDto.getJoinDate() != null) {
|
||||||
professor.setJoinDate(professorDto.getJoinDate());
|
professor.setJoinDate(professorDto.getJoinDate());
|
||||||
}
|
|
||||||
|
|
||||||
// Create a final reference for lambda expressions
|
|
||||||
final Professor professorRef = professor;
|
|
||||||
|
|
||||||
// Update skills - clear existing and add new ones
|
|
||||||
if (professor.getSkills() != null) {
|
|
||||||
professor.getSkills().clear();
|
|
||||||
}
|
|
||||||
if (professorDto.getSkills() != null && !professorDto.getSkills().isEmpty()) {
|
|
||||||
Set<ProfessorSkill> skills = professorDto.getSkills().stream()
|
|
||||||
.filter(skillDto -> skillDto.getName() != null && !skillDto.getName().trim().isEmpty())
|
|
||||||
.map(skillDto -> ProfessorSkill.builder()
|
|
||||||
.name(skillDto.getName().trim())
|
|
||||||
.level(skillDto.getLevel())
|
|
||||||
.professor(professorRef)
|
|
||||||
.build())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if (professor.getSkills() == null) {
|
|
||||||
professor.setSkills(new HashSet<>());
|
|
||||||
}
|
|
||||||
professor.getSkills().addAll(skills);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update awards - clear existing and add new ones
|
|
||||||
if (professor.getAwards() != null) {
|
|
||||||
professor.getAwards().clear();
|
|
||||||
}
|
|
||||||
if (professorDto.getAwards() != null && !professorDto.getAwards().isEmpty()) {
|
|
||||||
Set<ProfessorAward> awards = professorDto.getAwards().stream()
|
|
||||||
.filter(awardDto -> awardDto.getTitle() != null && !awardDto.getTitle().trim().isEmpty())
|
|
||||||
.map(awardDto -> ProfessorAward.builder()
|
|
||||||
.title(awardDto.getTitle().trim())
|
|
||||||
.year(awardDto.getYear())
|
|
||||||
.description(awardDto.getDescription())
|
|
||||||
.imageUrl(awardDto.getImageUrl())
|
|
||||||
.professor(professorRef)
|
|
||||||
.build())
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
if (professor.getAwards() == null) {
|
|
||||||
professor.setAwards(new HashSet<>());
|
|
||||||
}
|
|
||||||
professor.getAwards().addAll(awards);
|
|
||||||
}
|
|
||||||
|
|
||||||
Professor savedProfessor = professorRepository.save(professor);
|
|
||||||
|
|
||||||
// Handle profile image if provided
|
|
||||||
if (professorDto.getProfileImage() != null) {
|
|
||||||
saveProfileImage(savedProfessor, professorDto.getProfileImage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return savedProfessor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a final reference for lambda expressions
|
||||||
|
final Professor professorRef = professor;
|
||||||
|
|
||||||
|
// Update skills - REPLACE the entire collection
|
||||||
|
if (professorDto.getSkills() != null && !professorDto.getSkills().isEmpty()) {
|
||||||
|
Set<ProfessorSkill> skills = professorDto.getSkills().stream()
|
||||||
|
.filter(skillDto -> skillDto.getName() != null && !skillDto.getName().trim().isEmpty())
|
||||||
|
.map(skillDto -> ProfessorSkill.builder()
|
||||||
|
.name(skillDto.getName().trim())
|
||||||
|
.level(skillDto.getLevel())
|
||||||
|
.professor(professorRef)
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
professor.setSkills(skills); // ✅ REPLACE instead of add
|
||||||
|
} else {
|
||||||
|
professor.setSkills(new HashSet<>()); // Clear if empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update awards - REPLACE the entire collection
|
||||||
|
if (professorDto.getAwards() != null && !professorDto.getAwards().isEmpty()) {
|
||||||
|
Set<ProfessorAward> awards = professorDto.getAwards().stream()
|
||||||
|
.filter(awardDto -> awardDto.getTitle() != null && !awardDto.getTitle().trim().isEmpty())
|
||||||
|
.map(awardDto -> ProfessorAward.builder()
|
||||||
|
.title(awardDto.getTitle().trim())
|
||||||
|
.year(awardDto.getYear())
|
||||||
|
.description(awardDto.getDescription())
|
||||||
|
.imageUrl(awardDto.getImageUrl())
|
||||||
|
.professor(professorRef)
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
professor.setAwards(awards); // ✅ REPLACE instead of add
|
||||||
|
} else {
|
||||||
|
professor.setAwards(new HashSet<>()); // Clear if empty
|
||||||
|
}
|
||||||
|
|
||||||
|
Professor savedProfessor = professorRepository.save(professor);
|
||||||
|
|
||||||
|
// Handle profile image if provided
|
||||||
|
if (professorDto.getProfileImage() != null) {
|
||||||
|
saveProfileImage(savedProfessor, professorDto.getProfileImage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return savedProfessor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteProfessor(UUID professorId) {
|
public void deleteProfessor(UUID professorId) {
|
||||||
Professor professorToBeDeleted = professorRepository
|
Professor professorToBeDeleted = professorRepository
|
||||||
|
|||||||
@ -88,6 +88,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
this.getProfessors(true);
|
this.getProfessors(true);
|
||||||
this.loggedInUser = this.authenticationService.getUserFromLocalStorage();
|
this.loggedInUser = this.authenticationService.getUserFromLocalStorage();
|
||||||
this.initializeAwards();
|
this.initializeAwards();
|
||||||
|
this.setupModalEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
@ -99,6 +100,55 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
this.selectedProfessorAwards = [];
|
this.selectedProfessorAwards = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup event listeners for Bootstrap modals to clear data when they close
|
||||||
|
*/
|
||||||
|
private setupModalEventListeners(): void {
|
||||||
|
// Listen for edit modal close event
|
||||||
|
const editModal = document.getElementById('editProfessorModal');
|
||||||
|
if (editModal) {
|
||||||
|
editModal.addEventListener('hidden.bs.modal', () => {
|
||||||
|
this.clearEditProfessorData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for add modal close event
|
||||||
|
const addModal = document.getElementById('addProfessorModal');
|
||||||
|
if (addModal) {
|
||||||
|
addModal.addEventListener('hidden.bs.modal', () => {
|
||||||
|
this.clearNewProfessorData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear only profile image related data (used after successful operations)
|
||||||
|
*/
|
||||||
|
private invalidateVariables(): void {
|
||||||
|
this.profileImage = null;
|
||||||
|
this.profileImageFileName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all data related to adding a new professor
|
||||||
|
*/
|
||||||
|
private clearNewProfessorData(): void {
|
||||||
|
this.profileImage = null;
|
||||||
|
this.profileImageFileName = null;
|
||||||
|
this.selectedWorkDays = {};
|
||||||
|
this.newProfessorAwards = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all data related to editing a professor
|
||||||
|
*/
|
||||||
|
private clearEditProfessorData(): void {
|
||||||
|
this.profileImage = null;
|
||||||
|
this.profileImageFileName = null;
|
||||||
|
this.selectedWorkDays = {};
|
||||||
|
this.selectedProfessorAwards = [];
|
||||||
|
}
|
||||||
|
|
||||||
// Award management methods
|
// Award management methods
|
||||||
public addNewAward(): void {
|
public addNewAward(): void {
|
||||||
this.newProfessorAwards.push({
|
this.newProfessorAwards.push({
|
||||||
@ -167,14 +217,21 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onSelectProfessor(selectedProfessor: Professor): void {
|
public onSelectProfessor(selectedProfessor: Professor): void {
|
||||||
this.selectedProfessor = selectedProfessor;
|
// Create a deep copy to avoid reference issues
|
||||||
this.selectedProfessorAwards = [...(selectedProfessor.awards || [])];
|
this.selectedProfessor = JSON.parse(JSON.stringify(selectedProfessor));
|
||||||
|
|
||||||
|
// Create a separate copy for awards to display
|
||||||
|
this.selectedProfessorAwards = selectedProfessor.awards
|
||||||
|
? JSON.parse(JSON.stringify(selectedProfessor.awards))
|
||||||
|
: [];
|
||||||
|
|
||||||
// Set up work days for viewing
|
// Set up work days for viewing
|
||||||
this.selectedWorkDays = {};
|
this.selectedWorkDays = {};
|
||||||
if (selectedProfessor.workDays && Array.isArray(selectedProfessor.workDays)) {
|
if (selectedProfessor.workDays && Array.isArray(selectedProfessor.workDays)) {
|
||||||
selectedProfessor.workDays.forEach(day => {
|
selectedProfessor.workDays.forEach(day => {
|
||||||
this.selectedWorkDays[day] = true;
|
if (this.availableDays.includes(day)) {
|
||||||
|
this.selectedWorkDays[day] = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,11 +276,9 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
(professor: Professor) => {
|
(professor: Professor) => {
|
||||||
this.clickButton('new-professor-close');
|
this.clickButton('new-professor-close');
|
||||||
this.getProfessors(false);
|
this.getProfessors(false);
|
||||||
this.invalidateVariables();
|
|
||||||
professorForm.reset();
|
professorForm.reset();
|
||||||
this.selectedWorkDays = {};
|
|
||||||
this.newProfessorAwards = [];
|
|
||||||
this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} added successfully`);
|
this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} added successfully`);
|
||||||
|
// Data will be cleared by modal close event listener
|
||||||
},
|
},
|
||||||
(errorResponse: HttpErrorResponse) => {
|
(errorResponse: HttpErrorResponse) => {
|
||||||
this.sendErrorNotification(errorResponse.error.message);
|
this.sendErrorNotification(errorResponse.error.message);
|
||||||
@ -231,14 +286,6 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private invalidateVariables(): void {
|
|
||||||
this.profileImage = null;
|
|
||||||
this.profileImageFileName = null;
|
|
||||||
this.selectedWorkDays = {};
|
|
||||||
this.newProfessorAwards = [];
|
|
||||||
this.selectedProfessorAwards = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public saveNewProfessor(): void {
|
public saveNewProfessor(): void {
|
||||||
this.clickButton('new-professor-save');
|
this.clickButton('new-professor-save');
|
||||||
}
|
}
|
||||||
@ -272,18 +319,23 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onEditProfessor(professor: Professor): void {
|
public onEditProfessor(professor: Professor): void {
|
||||||
this.selectedProfessor = { ...professor };
|
// Create a deep copy to avoid reference issues
|
||||||
|
this.selectedProfessor = JSON.parse(JSON.stringify(professor));
|
||||||
|
|
||||||
// Set up work days for editing
|
// Set up work days for editing with validation
|
||||||
this.selectedWorkDays = {};
|
this.selectedWorkDays = {};
|
||||||
if (professor.workDays && Array.isArray(professor.workDays)) {
|
if (professor.workDays && Array.isArray(professor.workDays)) {
|
||||||
professor.workDays.forEach(day => {
|
professor.workDays.forEach(day => {
|
||||||
this.selectedWorkDays[day] = true;
|
if (this.availableDays.includes(day)) {
|
||||||
|
this.selectedWorkDays[day] = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up awards for editing
|
// Set up awards for editing - create a deep copy
|
||||||
this.selectedProfessorAwards = [...(professor.awards || [])];
|
this.selectedProfessorAwards = professor.awards
|
||||||
|
? JSON.parse(JSON.stringify(professor.awards))
|
||||||
|
: [];
|
||||||
|
|
||||||
this.clickButton('openProfessorEdit');
|
this.clickButton('openProfessorEdit');
|
||||||
}
|
}
|
||||||
@ -294,14 +346,19 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Updating professor:', this.selectedProfessor);
|
||||||
|
console.log('Selected work days:', this.selectedWorkDays);
|
||||||
|
console.log('Selected awards:', this.selectedProfessorAwards);
|
||||||
|
|
||||||
const formData = this.createExtendedProfessorFormData(this.selectedProfessor, this.profileImage);
|
const formData = this.createExtendedProfessorFormData(this.selectedProfessor, this.profileImage);
|
||||||
|
|
||||||
this.subs.add(this.professorService.updateProfessor(this.selectedProfessor.professorId, formData).subscribe(
|
this.subs.add(this.professorService.updateProfessor(this.selectedProfessor.professorId, formData).subscribe(
|
||||||
(professor: Professor) => {
|
(professor: Professor) => {
|
||||||
this.clickButton('closeEditProfessorButton');
|
this.clickButton('closeEditProfessorButton');
|
||||||
this.getProfessors(false);
|
this.getProfessors(false);
|
||||||
this.invalidateVariables();
|
this.invalidateVariables(); // Only clear profile image related data
|
||||||
this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} updated successfully`);
|
this.notificationService.notify(NotificationType.SUCCESS, `Professor ${professor.firstName} updated successfully`);
|
||||||
|
// Other data will be cleared by modal close event listener
|
||||||
},
|
},
|
||||||
(errorResponse: HttpErrorResponse) => {
|
(errorResponse: HttpErrorResponse) => {
|
||||||
this.sendErrorNotification(errorResponse.error.message);
|
this.sendErrorNotification(errorResponse.error.message);
|
||||||
@ -331,7 +388,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
formData.append('certification', professor.certification || '');
|
formData.append('certification', professor.certification || '');
|
||||||
formData.append('training', professor.training || '');
|
formData.append('training', professor.training || '');
|
||||||
|
|
||||||
// Work days
|
// Work days - collect from selectedWorkDays object
|
||||||
const workDays = Object.keys(this.selectedWorkDays).filter(day => this.selectedWorkDays[day]);
|
const workDays = Object.keys(this.selectedWorkDays).filter(day => this.selectedWorkDays[day]);
|
||||||
if (workDays.length > 0) {
|
if (workDays.length > 0) {
|
||||||
workDays.forEach(day => {
|
workDays.forEach(day => {
|
||||||
@ -339,16 +396,19 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Awards - determine which awards array to use
|
// Awards - determine which awards array to use based on context
|
||||||
const awardsToSubmit = professor.professorId ? this.selectedProfessorAwards : this.newProfessorAwards;
|
const awardsToSubmit = professor.professorId ? this.selectedProfessorAwards : this.newProfessorAwards;
|
||||||
if (awardsToSubmit && awardsToSubmit.length > 0) {
|
if (awardsToSubmit && awardsToSubmit.length > 0) {
|
||||||
awardsToSubmit.forEach((award, index) => {
|
// Filter out empty awards and only include those with at least title and year
|
||||||
if (award.title && award.year) { // Only include awards with title and year
|
const validAwards = awardsToSubmit.filter(award =>
|
||||||
formData.append(`awards[${index}].title`, award.title);
|
award.title && award.title.trim() && award.year && award.year.trim()
|
||||||
formData.append(`awards[${index}].year`, award.year);
|
);
|
||||||
formData.append(`awards[${index}].description`, award.description || '');
|
|
||||||
formData.append(`awards[${index}].imageUrl`, award.imageUrl || '');
|
validAwards.forEach((award, index) => {
|
||||||
}
|
formData.append(`awards[${index}].title`, award.title.trim());
|
||||||
|
formData.append(`awards[${index}].year`, award.year.trim());
|
||||||
|
formData.append(`awards[${index}].description`, award.description || '');
|
||||||
|
formData.append(`awards[${index}].imageUrl`, award.imageUrl || '');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +417,12 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
formData.append('profileImage', profileImage);
|
formData.append('profileImage', profileImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log formData for debugging
|
||||||
|
console.log('FormData contents:');
|
||||||
|
formData.forEach((value, key) => {
|
||||||
|
console.log(`${key}:`, value);
|
||||||
|
});
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,6 +520,7 @@ export class ProfessorComponent implements OnInit, OnDestroy {
|
|||||||
workDays: [],
|
workDays: [],
|
||||||
awards: []
|
awards: []
|
||||||
};
|
};
|
||||||
this.invalidateVariables();
|
this.clearNewProfessorData();
|
||||||
|
this.clearEditProfessorData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user