|
|
|
|
@ -92,77 +92,94 @@ export class SetupUserComponent implements OnInit {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Submit for creating new user
|
|
|
|
|
onSubmit() {
|
|
|
|
|
if (this.userForm.invalid) {
|
|
|
|
|
onSubmit() {
|
|
|
|
|
// For create mode, check if password is required
|
|
|
|
|
if (this.mode === 'create') {
|
|
|
|
|
const passwordControl = this.userForm.get('defaultPassword');
|
|
|
|
|
if (!passwordControl?.value) {
|
|
|
|
|
passwordControl?.setErrors({ required: true });
|
|
|
|
|
this.userForm.markAllAsTouched();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.userForm.invalid) {
|
|
|
|
|
this.userForm.markAllAsTouched();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newUser: SetupUser = {
|
|
|
|
|
userId: this.userForm.value.userId.trim().toLowerCase(),
|
|
|
|
|
userFullname: this.userForm.value.userFullname.trim(),
|
|
|
|
|
email: this.userForm.value.email.trim(),
|
|
|
|
|
role: this.userForm.value.userRole,
|
|
|
|
|
porOrgacode: this.storageService.getItem('POR_ORGACODE'),
|
|
|
|
|
password: this.userForm.value.defaultPassword
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
this.httpService.requestPOST<SetupUser>(URIKey.CREATE_USER, newUser).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (!(response instanceof HttpErrorResponse)) {
|
|
|
|
|
this.i18nService.success(SuccessMessages.USER_CREATED_SUCCESS, []);
|
|
|
|
|
this.resetForm();
|
|
|
|
|
this.loadUsersDirect();
|
|
|
|
|
}
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
},
|
|
|
|
|
error: (error) => {
|
|
|
|
|
console.error('Error creating user:', error);
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
const newUser: SetupUser = {
|
|
|
|
|
userId: this.userForm.value.userId.trim().toLowerCase(),
|
|
|
|
|
userFullname: this.userForm.value.userFullname.trim(),
|
|
|
|
|
email: this.userForm.value.email.trim(),
|
|
|
|
|
role: this.userForm.value.userRole,
|
|
|
|
|
porOrgacode: this.storageService.getItem('POR_ORGACODE'),
|
|
|
|
|
password: this.userForm.value.defaultPassword
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
this.httpService.requestPOST<SetupUser>(URIKey.CREATE_USER, newUser).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (!(response instanceof HttpErrorResponse)) {
|
|
|
|
|
this.i18nService.success(SuccessMessages.USER_CREATED_SUCCESS, []);
|
|
|
|
|
this.resetForm();
|
|
|
|
|
this.loadUsersDirect();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
},
|
|
|
|
|
error: (error) => {
|
|
|
|
|
console.error('Error creating user:', error);
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update existing user
|
|
|
|
|
onUpdate() {
|
|
|
|
|
if (this.userForm.invalid) {
|
|
|
|
|
this.userForm.markAllAsTouched();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
onUpdate() {
|
|
|
|
|
// Clear any pattern errors if password is empty in edit mode
|
|
|
|
|
const passwordControl = this.userForm.get('defaultPassword');
|
|
|
|
|
if (passwordControl && !passwordControl.value && this.mode === 'edit') {
|
|
|
|
|
passwordControl.setErrors(null); // Clear errors for empty password in edit mode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.userForm.invalid) {
|
|
|
|
|
this.userForm.markAllAsTouched();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const updatedUser: any = {
|
|
|
|
|
userId: this.selectedUserIdForEdit,
|
|
|
|
|
userFullname: this.userForm.value.userFullname.trim(),
|
|
|
|
|
email: this.userForm.value.email.trim(),
|
|
|
|
|
role: this.userForm.value.userRole,
|
|
|
|
|
porOrgacode: this.storageService.getItem('POR_ORGACODE')
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Only include password if it was provided
|
|
|
|
|
if (this.userForm.value.defaultPassword && this.userForm.value.defaultPassword.trim()) {
|
|
|
|
|
updatedUser.password = this.userForm.value.defaultPassword;
|
|
|
|
|
}
|
|
|
|
|
const updatedUser: any = {
|
|
|
|
|
userId: this.selectedUserIdForEdit,
|
|
|
|
|
userFullname: this.userForm.value.userFullname.trim(),
|
|
|
|
|
email: this.userForm.value.email.trim(),
|
|
|
|
|
role: this.userForm.value.userRole,
|
|
|
|
|
porOrgacode: this.storageService.getItem('POR_ORGACODE')
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Only include password if it was provided AND is valid
|
|
|
|
|
if (this.userForm.value.defaultPassword &&
|
|
|
|
|
this.userForm.value.defaultPassword.trim() &&
|
|
|
|
|
this.userForm.get('defaultPassword')?.valid) {
|
|
|
|
|
updatedUser.password = this.userForm.value.defaultPassword.trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let params = new HttpParams().set('userId', this.selectedUserIdForEdit!);
|
|
|
|
|
let params = new HttpParams().set('userId', this.selectedUserIdForEdit!);
|
|
|
|
|
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
this.httpService.requestPUT<SetupUser>(URIKey.UPDATE_USER, updatedUser, undefined, params).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (!(response instanceof HttpErrorResponse)) {
|
|
|
|
|
this.i18nService.success(SuccessMessages.USER_UPDATED_SUCCESS, []);
|
|
|
|
|
this.resetForm();
|
|
|
|
|
this.loadUsersDirect();
|
|
|
|
|
}
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
},
|
|
|
|
|
error: (error) => {
|
|
|
|
|
console.error('Error updating user:', error);
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
this.httpService.requestPUT<SetupUser>(URIKey.UPDATE_USER, updatedUser, undefined, params).subscribe({
|
|
|
|
|
next: (response) => {
|
|
|
|
|
if (!(response instanceof HttpErrorResponse)) {
|
|
|
|
|
this.i18nService.success(SuccessMessages.USER_UPDATED_SUCCESS, []);
|
|
|
|
|
this.resetForm();
|
|
|
|
|
this.loadUsersDirect();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
},
|
|
|
|
|
error: (error) => {
|
|
|
|
|
console.error('Error updating user:', error);
|
|
|
|
|
this.isLoading = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// Cancel edit mode
|
|
|
|
|
cancelEdit() {
|
|
|
|
|
this.resetForm();
|
|
|
|
|
@ -234,42 +251,59 @@ export class SetupUserComponent implements OnInit {
|
|
|
|
|
this.loadUsersDirect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initializeForm(): void {
|
|
|
|
|
this.userForm = this.fb.group({
|
|
|
|
|
userId: ['', [
|
|
|
|
|
Validators.required,
|
|
|
|
|
Validators.minLength(3),
|
|
|
|
|
Validators.pattern('^[a-zA-Z0-9]*$')
|
|
|
|
|
]],
|
|
|
|
|
userFullname: ['', [
|
|
|
|
|
Validators.required,
|
|
|
|
|
Validators.minLength(3),
|
|
|
|
|
Validators.maxLength(500)
|
|
|
|
|
]],
|
|
|
|
|
defaultPassword: ['', [
|
|
|
|
|
// Make password optional for edit mode, required for create
|
|
|
|
|
(control: AbstractControl) => {
|
|
|
|
|
if (this.mode === 'create' && !control.value) {
|
|
|
|
|
return { required: true };
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
},
|
|
|
|
|
Validators.pattern(
|
|
|
|
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/
|
|
|
|
|
)
|
|
|
|
|
]],
|
|
|
|
|
email: ['', [Validators.required, Validators.email]],
|
|
|
|
|
userRole: [null, Validators.required]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Update password validation when mode changes
|
|
|
|
|
this.userForm.get('defaultPassword')?.valueChanges.subscribe(() => {
|
|
|
|
|
const passwordControl = this.userForm.get('defaultPassword');
|
|
|
|
|
if (passwordControl) {
|
|
|
|
|
passwordControl.updateValueAndValidity();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
initializeForm(): void {
|
|
|
|
|
this.userForm = this.fb.group({
|
|
|
|
|
userId: ['', [
|
|
|
|
|
Validators.required,
|
|
|
|
|
Validators.minLength(3),
|
|
|
|
|
Validators.pattern('^[a-zA-Z0-9]*$')
|
|
|
|
|
]],
|
|
|
|
|
userFullname: ['', [
|
|
|
|
|
Validators.required,
|
|
|
|
|
Validators.minLength(3),
|
|
|
|
|
Validators.maxLength(500)
|
|
|
|
|
]],
|
|
|
|
|
defaultPassword: ['', [
|
|
|
|
|
// For edit mode, password is optional
|
|
|
|
|
// For create mode, handle required validation separately
|
|
|
|
|
this.passwordValidator.bind(this)
|
|
|
|
|
]],
|
|
|
|
|
email: ['', [Validators.required, Validators.email]],
|
|
|
|
|
userRole: [null, Validators.required]
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Custom validator for password
|
|
|
|
|
private passwordValidator(control: AbstractControl): { [key: string]: any } | null {
|
|
|
|
|
const value = control.value;
|
|
|
|
|
|
|
|
|
|
// If empty and we're in edit mode, it's valid (optional)
|
|
|
|
|
if (!value || value.trim() === '') {
|
|
|
|
|
if (this.mode === 'edit') {
|
|
|
|
|
return null; // Password is optional in edit mode
|
|
|
|
|
}
|
|
|
|
|
// For create mode, we'll handle required validation in onSubmit
|
|
|
|
|
return null; // Don't show pattern error for empty field
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there's a value, check the pattern
|
|
|
|
|
const pattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$/;
|
|
|
|
|
if (!pattern.test(value)) {
|
|
|
|
|
return { pattern: true };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Separate validator function
|
|
|
|
|
private createPasswordValidator(mode: 'create' | 'edit'): Validators {
|
|
|
|
|
return (control: AbstractControl) => {
|
|
|
|
|
if (mode === 'create' && !control.value) {
|
|
|
|
|
return { required: true };
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loadUsersDirect(): void {
|
|
|
|
|
this.isLoading = true;
|
|
|
|
|
|