create common dmpUser component for dmp ui and dmp overview popup invite
This commit is contained in:
parent
add1bb582f
commit
a387349aad
|
@ -1,6 +1,5 @@
|
||||||
package eu.eudat.model.persist;
|
package eu.eudat.model.persist;
|
||||||
|
|
||||||
import eu.eudat.commons.enums.DmpUserRole;
|
|
||||||
import eu.eudat.commons.validation.BaseValidator;
|
import eu.eudat.commons.validation.BaseValidator;
|
||||||
import gr.cite.tools.validation.ValidatorFactory;
|
import gr.cite.tools.validation.ValidatorFactory;
|
||||||
import gr.cite.tools.validation.specification.Specification;
|
import gr.cite.tools.validation.specification.Specification;
|
||||||
|
@ -17,30 +16,18 @@ import java.util.List;
|
||||||
|
|
||||||
public class DmpUserInvitePersist {
|
public class DmpUserInvitePersist {
|
||||||
|
|
||||||
private List<DmpUserInviteTypePersist> users;
|
private List<DmpUserPersist> users;
|
||||||
|
|
||||||
public static final String _users = "users";
|
public static final String _users = "users";
|
||||||
|
|
||||||
private DmpUserRole role;
|
public List<DmpUserPersist> getUsers() {
|
||||||
|
|
||||||
public static final String _role = "role";
|
|
||||||
|
|
||||||
public List<DmpUserInviteTypePersist> getUsers() {
|
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUsers(List<DmpUserInviteTypePersist> users) {
|
public void setUsers(List<DmpUserPersist> users) {
|
||||||
this.users = users;
|
this.users = users;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DmpUserRole getRole() {
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRole(DmpUserRole role) {
|
|
||||||
this.role = role;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component(DmpUserInvitePersistValidator.ValidatorName)
|
@Component(DmpUserInvitePersistValidator.ValidatorName)
|
||||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
public static class DmpUserInvitePersistValidator extends BaseValidator<DmpUserInvitePersist> {
|
public static class DmpUserInvitePersistValidator extends BaseValidator<DmpUserInvitePersist> {
|
||||||
|
@ -65,10 +52,6 @@ public class DmpUserInvitePersist {
|
||||||
@Override
|
@Override
|
||||||
protected List<Specification> specifications(DmpUserInvitePersist item) {
|
protected List<Specification> specifications(DmpUserInvitePersist item) {
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
this.spec()
|
|
||||||
.must(() -> !this.isNull(item.getRole()))
|
|
||||||
.failOn(DmpUserInvitePersist._role).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpUserInvitePersist._role}, LocaleContextHolder.getLocale())),
|
|
||||||
|
|
||||||
this.spec()
|
this.spec()
|
||||||
.must(() -> !this.isListNullOrEmpty(item.getUsers()))
|
.must(() -> !this.isListNullOrEmpty(item.getUsers()))
|
||||||
.failOn(DmpUserInvitePersist._users).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpUserInvitePersist._users}, LocaleContextHolder.getLocale())),
|
.failOn(DmpUserInvitePersist._users).failWith(messageSource.getMessage("Validation_Required", new Object[]{DmpUserInvitePersist._users}, LocaleContextHolder.getLocale())),
|
||||||
|
@ -76,7 +59,7 @@ public class DmpUserInvitePersist {
|
||||||
.iff(() -> !this.isListNullOrEmpty(item.getUsers()))
|
.iff(() -> !this.isListNullOrEmpty(item.getUsers()))
|
||||||
.on(DmpUserInvitePersist._users)
|
.on(DmpUserInvitePersist._users)
|
||||||
.over(item.getUsers())
|
.over(item.getUsers())
|
||||||
.using((itm) -> this.validatorFactory.validator(DmpUserInviteTypePersist.DmpUserInviteTypePersistValidator.class))
|
.using((itm) -> this.validatorFactory.validator(DmpUserPersist.DmpUserPersistValidator.class))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.UUID;
|
||||||
|
|
||||||
public interface DmpService {
|
public interface DmpService {
|
||||||
|
|
||||||
Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException;
|
Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException;
|
||||||
|
|
||||||
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;
|
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException, IOException;
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ public interface DmpService {
|
||||||
|
|
||||||
ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException;
|
ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException;
|
||||||
|
|
||||||
void inviteUsers(UUID id, DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException, IOException;
|
void inviteUsers(UUID id, List<DmpUserPersist> users) throws InvalidApplicationException, JAXBException, IOException;
|
||||||
|
|
||||||
void dmpInvitationAccept(String token) throws InvalidApplicationException, IOException;
|
void dmpInvitationAccept(String token) throws InvalidApplicationException, IOException;
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,7 @@ public class DmpServiceImpl implements DmpService {
|
||||||
this.dmpTouchedIntegrationEventHandler = dmpTouchedIntegrationEventHandler;
|
this.dmpTouchedIntegrationEventHandler = dmpTouchedIntegrationEventHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, IOException {
|
public Dmp persist(DmpPersist model, FieldSet fields) throws MyForbiddenException, MyValidationException, MyApplicationException, MyNotFoundException, InvalidApplicationException, JAXBException, IOException {
|
||||||
this.authorizationService.authorizeForce(Permission.EditDmp);
|
this.authorizationService.authorizeForce(Permission.EditDmp);
|
||||||
|
|
||||||
DmpEntity data = this.patchAndSave(model);
|
DmpEntity data = this.patchAndSave(model);
|
||||||
|
@ -188,6 +188,10 @@ public class DmpServiceImpl implements DmpService {
|
||||||
|
|
||||||
this.elasticService.persistDmp(data);
|
this.elasticService.persistDmp(data);
|
||||||
|
|
||||||
|
if (!this.conventionService.isListNullOrEmpty(model.getUsers())){
|
||||||
|
this.inviteUsers(data.getId(), model.getUsers());
|
||||||
|
}
|
||||||
|
|
||||||
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
|
return this.builderFactory.builder(DmpBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).build(BaseFieldSet.build(fields, Dmp._id, Dmp._hash), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,7 +781,7 @@ public class DmpServiceImpl implements DmpService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// invites
|
// invites
|
||||||
public void inviteUsers(UUID id, DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException, IOException {
|
public void inviteUsers(UUID id, List<DmpUserPersist> users) throws InvalidApplicationException, JAXBException, IOException {
|
||||||
|
|
||||||
this.authorizationService.authorizeForce(Permission.InviteDmpUsers);
|
this.authorizationService.authorizeForce(Permission.InviteDmpUsers);
|
||||||
|
|
||||||
|
@ -786,15 +790,22 @@ public class DmpServiceImpl implements DmpService {
|
||||||
throw new InvalidApplicationException("Dmp does not exist!");
|
throw new InvalidApplicationException("Dmp does not exist!");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DmpUserInviteTypePersist type :model.getUsers()) {
|
for (DmpUserPersist user :users) {
|
||||||
if (type.getUserId() != null){
|
UUID userId = null;
|
||||||
DmpUserPersist dmpUserPersist = new DmpUserPersist();
|
if (user.getUser() != null){
|
||||||
dmpUserPersist.setUser(type.getUserId());
|
userId = user.getUser();
|
||||||
dmpUserPersist.setRole(model.getRole());
|
} else if (user.getEmail() != null) {
|
||||||
this.assignUsers(id, List.of(dmpUserPersist), null);
|
UserContactInfoEntity contactInfoEntity = this.queryFactory.query(UserContactInfoQuery.class).values(user.getEmail()).types(ContactInfoType.Email).first();
|
||||||
this.sendDmpInvitationExistingUser(type.getUserId(), dmp, model.getRole());
|
if (contactInfoEntity != null){
|
||||||
} else if (type.getEmail() != null) {
|
userId = contactInfoEntity.getUserId();
|
||||||
this.sendDmpInvitationExternalUser(type.getEmail(),dmp, model.getRole());
|
}
|
||||||
|
}
|
||||||
|
if (userId != null){
|
||||||
|
user.setUser(userId);
|
||||||
|
this.assignUsers(id, List.of(user), null);
|
||||||
|
this.sendDmpInvitationExistingUser(user.getUser(), dmp, user.getRole());
|
||||||
|
}else if (user.getEmail() != null) {
|
||||||
|
this.sendDmpInvitationExternalUser(user.getEmail(),dmp, user.getRole());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ public class DmpController {
|
||||||
@PostMapping("persist")
|
@PostMapping("persist")
|
||||||
@Transactional
|
@Transactional
|
||||||
@ValidationFilterAnnotation(validator = DmpPersist.DmpPersistValidator.ValidatorName, argumentName = "model")
|
@ValidationFilterAnnotation(validator = DmpPersist.DmpPersistValidator.ValidatorName, argumentName = "model")
|
||||||
public Dmp Persist(@RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException {
|
public Dmp Persist(@RequestBody DmpPersist model, FieldSet fieldSet) throws MyApplicationException, MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException, JAXBException {
|
||||||
logger.debug(new MapLogEntry("persisting" + Dmp.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
|
logger.debug(new MapLogEntry("persisting" + Dmp.class.getSimpleName()).And("model", model).And("fieldSet", fieldSet));
|
||||||
|
|
||||||
Dmp persisted = this.dmpService.persist(model, fieldSet);
|
Dmp persisted = this.dmpService.persist(model, fieldSet);
|
||||||
|
@ -228,7 +228,7 @@ public class DmpController {
|
||||||
public boolean inviteUsers(@PathVariable("id") UUID id, @RequestBody DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException, IOException {
|
public boolean inviteUsers(@PathVariable("id") UUID id, @RequestBody DmpUserInvitePersist model) throws InvalidApplicationException, JAXBException, IOException {
|
||||||
logger.debug(new MapLogEntry("inviting users to dmp").And("model", model));
|
logger.debug(new MapLogEntry("inviting users to dmp").And("model", model));
|
||||||
|
|
||||||
this.dmpService.inviteUsers(id, model);
|
this.dmpService.inviteUsers(id, model.getUsers());
|
||||||
|
|
||||||
this.auditService.track(AuditableAction.Dmp_Invite_Users, Map.ofEntries(
|
this.auditService.track(AuditableAction.Dmp_Invite_Users, Map.ofEntries(
|
||||||
new AbstractMap.SimpleEntry<String, Object>("model", model)
|
new AbstractMap.SimpleEntry<String, Object>("model", model)
|
||||||
|
|
|
@ -143,12 +143,5 @@ export interface DmpUserRemovePersist {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DmpUserInvitePersist {
|
export interface DmpUserInvitePersist {
|
||||||
users: DmpUserInviteTypePersist[];
|
users: DmpUserPersist[];
|
||||||
role: DmpUserRole;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DmpUserInviteTypePersist {
|
|
||||||
userId: Guid;
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -243,76 +243,8 @@
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="field.systemFieldType == dmpBlueprintSystemFieldTypeEnum.User">
|
<div *ngIf="field.systemFieldType == dmpBlueprintSystemFieldTypeEnum.User">
|
||||||
<div cdkDropList class="col-12" (cdkDropListDropped)="dropUsers($event)">
|
<div>
|
||||||
<div *ngFor="let user of formGroup.get('users').controls; let userIndex=index;" cdkDrag class="row align-items-center" [cdkDragDisabled]="formGroup.disabled">
|
<app-user-field-component [form]="formGroup" [validationErrorModel]="editorModel.validationErrorModel" [sections]="selectedBlueprint.definition.sections"></app-user-field-component>
|
||||||
<div class="col-auto">
|
|
||||||
<span style="font-size: 15px;">{{userIndex + 1}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto d-flex"><mat-icon [ngClass]="{'drag-handle-disabled': formGroup.disabled}" cdkDragHandle class="drag-handle">drag_indicator</mat-icon></div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<mat-button-toggle-group name="fontStyle" aria-label="Font Style" [formControl]="user.get('userType')">
|
|
||||||
<div *ngFor="let userType of dmpUserTypeEnumValues">
|
|
||||||
<mat-button-toggle class="lang-button" [value]="userType">{{enumUtils.toDmpUserTypeString(userType)}}</mat-button-toggle>
|
|
||||||
</div>
|
|
||||||
</mat-button-toggle-group>
|
|
||||||
</div>
|
|
||||||
<div class="col pt-4">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col" *ngIf="user.get('userType').value == dmpUserTypeEnum.Internal">
|
|
||||||
<mat-form-field class="w-100">
|
|
||||||
<mat-label>{{'DMP-EDITOR.FIELDS1.USER' | translate}}*</mat-label>
|
|
||||||
<app-single-auto-complete [formControl]="user.get('user')" [hidePlaceholder]="true" [configuration]="userService.singleAutocompleteConfiguration"></app-single-auto-complete>
|
|
||||||
<mat-error *ngIf="user.get('user').hasError('backendError')">{{user.get('user').getError('backendError').message}}</mat-error>
|
|
||||||
<mat-error *ngIf="user.get('user').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<div class="col" *ngIf="user.get('userType').value == dmpUserTypeEnum.External">
|
|
||||||
<mat-form-field class="w-100">
|
|
||||||
<mat-label>{{'DMP-EDITOR.FIELDS1.EMAIL' | translate}}*</mat-label>
|
|
||||||
<input matInput type="text" name="email" [formControl]="user.get('email')">
|
|
||||||
<mat-error *ngIf="user.get('email').hasError('backendError')">{{user.get('email').getError('backendError').message}}</mat-error>
|
|
||||||
<mat-error *ngIf="user.get('email').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<mat-form-field class="w-100">
|
|
||||||
<mat-label>{{'DMP-EDITOR.FIELDS1.USER-ROLE' | translate}}</mat-label>
|
|
||||||
<mat-select [formControl]="user.get('role')">
|
|
||||||
<mat-option *ngFor="let userRole of dmpUserRoleEnumValues" [value]="userRole">{{enumUtils.toDmpUserRoleString(userRole)}}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
<mat-error *ngIf="user.get('role').hasError('backendError')">{{user.get('role').getError('backendError').message}}</mat-error>
|
|
||||||
<mat-error *ngIf="user.get('role').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<mat-form-field class="w-100">
|
|
||||||
<mat-label>{{'DMP-EDITOR.FIELDS1.SECTION' | translate}}</mat-label>
|
|
||||||
<mat-select [formControl]="user.get('sectionId')">
|
|
||||||
<mat-option *ngFor="let section of selectedBlueprint.definition.sections" [value]="section.id">
|
|
||||||
{{ section.label }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
<mat-error *ngIf="user.get('sectionId').hasError('backendError')">{{user.get('sectionId').getError('backendError').message}}</mat-error>
|
|
||||||
<mat-error *ngIf="user.get('sectionId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |translate}}</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-auto">
|
|
||||||
<button mat-icon-button class="action-list-icon" matTooltip="{{'DMP-EDITOR.ACTIONS1.REMOVE-USER' | translate}}" (click)="removeUser(userIndex)" [disabled]="formGroup.disabled">
|
|
||||||
<mat-icon>delete</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<mat-error *ngIf="formGroup.get('users').hasError('backendError')">{{formGroup.get('users').getError('backendError').message}}</mat-error>
|
|
||||||
<mat-error *ngIf="formGroup.get('users').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<button mat-icon-button (click)="addUser()" [disabled]="formGroup.disabled">
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -196,7 +196,7 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
buildForm() {
|
buildForm() {
|
||||||
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditDescription));
|
this.formGroup = this.editorModel.buildForm(null, this.isDeleted || !this.authService.hasPermission(AppPermission.EditDmp));
|
||||||
|
|
||||||
if (this.editorModel.status == DmpStatus.Finalized || this.isDeleted) {
|
if (this.editorModel.status == DmpStatus.Finalized || this.isDeleted) {
|
||||||
this.formGroup.disable();
|
this.formGroup.disable();
|
||||||
|
@ -372,42 +372,6 @@ export class DmpEditorComponent extends BaseEditor<DmpEditorModel, Dmp> implemen
|
||||||
this.formGroup.get('properties').get('contacts').markAsDirty();
|
this.formGroup.get('properties').get('contacts').markAsDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Dmp Users
|
|
||||||
//
|
|
||||||
//
|
|
||||||
addUser(): void {
|
|
||||||
const userArray = this.formGroup.get('users') as FormArray;
|
|
||||||
(this.formGroup.get('users') as FormArray).push(this.editorModel.createChildUser(userArray.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
removeUser(userIndex: number): void {
|
|
||||||
(this.formGroup.get('users') as FormArray).removeAt(userIndex);
|
|
||||||
|
|
||||||
DmpEditorModel.reApplyPropertiesValidators(
|
|
||||||
{
|
|
||||||
formGroup: this.formGroup,
|
|
||||||
validationErrorModel: this.editorModel.validationErrorModel
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.formGroup.get('users').markAsDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
dropUsers(event: CdkDragDrop<string[]>) {
|
|
||||||
const usersFormArray = (this.formGroup.get('users') as FormArray);
|
|
||||||
|
|
||||||
moveItemInArray(usersFormArray.controls, event.previousIndex, event.currentIndex);
|
|
||||||
usersFormArray.updateValueAndValidity();
|
|
||||||
|
|
||||||
DmpEditorModel.reApplyPropertiesValidators(
|
|
||||||
{
|
|
||||||
formGroup: this.formGroup,
|
|
||||||
validationErrorModel: this.editorModel.validationErrorModel
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.formGroup.get('users').markAsDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -139,10 +139,6 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist {
|
||||||
return contact.buildForm({ rootPath: 'properties.contacts[' + index + '].' });
|
return contact.buildForm({ rootPath: 'properties.contacts[' + index + '].' });
|
||||||
}
|
}
|
||||||
|
|
||||||
createChildUser(index: number): UntypedFormGroup {
|
|
||||||
const user: DmpUserEditorModel = new DmpUserEditorModel(this.validationErrorModel);
|
|
||||||
return user.buildForm({ rootPath: 'users[' + index + '].' });
|
|
||||||
}
|
|
||||||
|
|
||||||
static reApplyPropertiesValidators(params: {
|
static reApplyPropertiesValidators(params: {
|
||||||
formGroup: UntypedFormGroup,
|
formGroup: UntypedFormGroup,
|
||||||
|
@ -500,8 +496,8 @@ export class DmpUserEditorModel implements DmpUserPersist {
|
||||||
return this.formBuilder.group({
|
return this.formBuilder.group({
|
||||||
user: [{ value: this.user, disabled: disabled }, context.getValidation('user').validators],
|
user: [{ value: this.user, disabled: disabled }, context.getValidation('user').validators],
|
||||||
role: [{ value: this.role, disabled: disabled }, context.getValidation('role').validators],
|
role: [{ value: this.role, disabled: disabled }, context.getValidation('role').validators],
|
||||||
email: [{ value: this.role, disabled: disabled }, context.getValidation('email').validators],
|
email: [{ value: this.email, disabled: disabled }, context.getValidation('email').validators],
|
||||||
sectionId: [{ value: this.role, disabled: disabled }, context.getValidation('sectionId').validators],
|
sectionId: [{ value: this.sectionId, disabled: disabled }, context.getValidation('sectionId').validators],
|
||||||
userType: [{ value: this.userType, disabled: disabled }, context.getValidation('userType').validators],
|
userType: [{ value: this.userType, disabled: disabled }, context.getValidation('userType').validators],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { DmpEditorRoutingModule } from './dmp-editor.routing';
|
||||||
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
|
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
|
||||||
import { ReferenceFieldModule } from '@app/ui/reference/reference-field/reference-field.module';
|
import { ReferenceFieldModule } from '@app/ui/reference/reference-field/reference-field.module';
|
||||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
import { UserFieldModule } from '../user-field/user-field.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -21,6 +22,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
AutoCompleteModule,
|
AutoCompleteModule,
|
||||||
ReferenceFieldModule,
|
ReferenceFieldModule,
|
||||||
DragDropModule,
|
DragDropModule,
|
||||||
|
UserFieldModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
DmpEditorComponent,
|
DmpEditorComponent,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||||
import { Description } from '@app/core/model/description/description';
|
import { Description } from '@app/core/model/description/description';
|
||||||
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, ExtraFieldInSection, FieldInSection, ReferenceTypeFieldInSection, SystemFieldInSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection, ExtraFieldInSection, FieldInSection, ReferenceTypeFieldInSection, SystemFieldInSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
||||||
import { Dmp, DmpBlueprintValue, DmpContact, DmpDescriptionTemplate, DmpProperties } from '@app/core/model/dmp/dmp';
|
import { Dmp, DmpBlueprintValue, DmpContact, DmpDescriptionTemplate, DmpProperties, DmpUser } from '@app/core/model/dmp/dmp';
|
||||||
import { DmpReference, DmpReferenceData } from '@app/core/model/dmp/dmp-reference';
|
import { DmpReference, DmpReferenceData } from '@app/core/model/dmp/dmp-reference';
|
||||||
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
|
||||||
import { Reference } from '@app/core/model/reference/reference';
|
import { Reference } from '@app/core/model/reference/reference';
|
||||||
|
@ -54,10 +54,12 @@ export class DmpEditorResolver extends BaseEditorResolver {
|
||||||
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
|
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.id)].join('.'),
|
||||||
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
|
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
|
||||||
|
|
||||||
// [nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
|
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.id)].join('.'),
|
||||||
// [nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
|
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.id)].join('.'),
|
||||||
// [nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.name)].join('.'),
|
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.user.name)].join('.'),
|
||||||
// [nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.role)].join('.'),
|
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.role)].join('.'),
|
||||||
|
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.sectionId)].join('.'),
|
||||||
|
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.isActive)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.isActive)].join('.'),
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.data), nameof<DmpReferenceData>(x => x.blueprintFieldId)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.data), nameof<DmpReferenceData>(x => x.blueprintFieldId)].join('.'),
|
||||||
|
|
|
@ -8,25 +8,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-content class="row content">
|
<div mat-dialog-content class="row content">
|
||||||
<mat-form-field class="col pt-0 pb-2 mb-4 search">
|
<div>
|
||||||
<app-multiple-auto-complete [formControl]="formGroup.get('users')" placeholder="{{'DMP-USER-INVITATION-DIALOG.FIELDS.USERS-PLACEHOLDER' | translate}}" [configuration]="usersAutoCompleteConfiguration" [showNoResultsLabel]="false" [separatorKeysCodes]="separatorKeysCodes" [minLength]="3">
|
<app-user-field-component [form]="formGroup" [validationErrorModel]="editorModel.validationErrorModel" [sections]="selectedBlueprint.definition.sections"></app-user-field-component>
|
||||||
</app-multiple-auto-complete>
|
</div>
|
||||||
</mat-form-field>
|
<div class="col mt-2">
|
||||||
<p class="d-flex m-0 hint">
|
<button mat-raised-button *ngIf="hasValue()" (click)="send()" type="button" class="invite-btn">{{'DMP-USER-INVITATION-DIALOG.ACTIONS.INVITE' | translate}}</button>
|
||||||
<mat-icon class="align-self-center mr-1">info_outlined</mat-icon>
|
<mat-error *ngIf="formGroup.get('users').hasError('backendError')">{{formGroup.get('users').getError('backendError').message}}</mat-error>
|
||||||
{{'DMP-USER-INVITATION-DIALOG.FIELDS.USERS-HINT' | translate}}
|
<mat-error *ngIf="formGroup.get('users').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</p>
|
|
||||||
<div class="col-12 d-flex justify-content-end align-items-center row m-0 pt-1 pb-1">
|
|
||||||
<div class="col">
|
|
||||||
<mat-form-field class="select-role">
|
|
||||||
<mat-select [formControl]="formGroup.get('role')">
|
|
||||||
<mat-option [value]="dmpUserRoleEnum.Owner">{{enumUtils.toDmpUserRoleString(dmpUserRoleEnum.Owner)}}</mat-option>
|
|
||||||
<mat-option [value]="dmpUserRoleEnum.User">{{enumUtils.toDmpUserRoleString(dmpUserRoleEnum.User)}}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<div class="col mt-2">
|
|
||||||
<button mat-raised-button *ngIf="hasValue()" (click)="send()" type="button" class="invite-btn">{{'DMP-USER-INVITATION-DIALOG.ACTIONS.INVITE' | translate}}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
|
@ -5,23 +5,18 @@ import { UntypedFormGroup } from '@angular/forms';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
|
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
|
||||||
import { IsActive } from '@app/core/common/enum/is-active.enum';
|
import { DmpUserPersist } from '@app/core/model/dmp/dmp';
|
||||||
import { DmpUserInvitePersist, DmpUserInviteTypePersist } from '@app/core/model/dmp/dmp';
|
|
||||||
import { DmpAssociatedUser, User } from '@app/core/model/user/user';
|
|
||||||
import { UserLookup } from '@app/core/query/user.lookup';
|
|
||||||
import { DmpService } from '@app/core/services/dmp/dmp.service';
|
import { DmpService } from '@app/core/services/dmp/dmp.service';
|
||||||
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||||
import { UserService } from '@app/core/services/user/user.service';
|
import { UserService } from '@app/core/services/user/user.service';
|
||||||
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||||
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
|
||||||
import { BaseComponent } from '@common/base/base.component';
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
import { FilterService } from '@common/modules/text-filter/filter-service';
|
import { FilterService } from '@common/modules/text-filter/filter-service';
|
||||||
import { Guid } from '@common/types/guid';
|
import { Guid } from '@common/types/guid';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { Observable } from 'rxjs';
|
import { DmpEditorModel } from '../../dmp-editor-blueprint/dmp-editor.model';
|
||||||
import { map, takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { DmpBlueprint } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
||||||
import { DmpInvitationDialogEditorModel } from './dmp-invitation-dialog.editor.model';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-invitation-dialog-component',
|
selector: 'app-invitation-dialog-component',
|
||||||
|
@ -31,31 +26,12 @@ import { DmpInvitationDialogEditorModel } from './dmp-invitation-dialog.editor.m
|
||||||
export class DmpInvitationDialogComponent extends BaseComponent implements OnInit {
|
export class DmpInvitationDialogComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
dmpId: Guid;
|
dmpId: Guid;
|
||||||
editorModel: DmpInvitationDialogEditorModel;
|
editorModel: DmpEditorModel;
|
||||||
formGroup: UntypedFormGroup;
|
formGroup: UntypedFormGroup;
|
||||||
dmpUserRoleEnum = DmpUserRole;
|
dmpUserRoleEnum = DmpUserRole;
|
||||||
|
selectedBlueprint: DmpBlueprint;
|
||||||
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
|
readonly separatorKeysCodes: number[] = [ENTER, COMMA];
|
||||||
|
|
||||||
usersAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = {
|
|
||||||
filterFn: this.filterUsers.bind(this),
|
|
||||||
initialItems: (excludedItems: any[]) => this.filterUsers('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
|
|
||||||
displayFn: (item) => typeof (item) === 'string' ? item : item.name,
|
|
||||||
titleFn: (item) => typeof (item) === 'string' ? item : item.name,
|
|
||||||
subtitleFn: (item) => item.email,
|
|
||||||
valueAssign: (item) => {
|
|
||||||
const result = typeof (item) === 'string' ? item : item.id;
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
autoSelectFirstOptionOnBlur: true,
|
|
||||||
appendClassToItem: [{
|
|
||||||
class: 'invalid-email', applyFunc: (item) => {
|
|
||||||
const val = typeof (item) === 'string' ? item : item.email;
|
|
||||||
const regexp = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
|
|
||||||
return !regexp.test(val);
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public enumUtils: EnumUtils,
|
public enumUtils: EnumUtils,
|
||||||
public route: ActivatedRoute,
|
public route: ActivatedRoute,
|
||||||
|
@ -70,42 +46,19 @@ export class DmpInvitationDialogComponent extends BaseComponent implements OnIni
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.dmpId = data.dmpId;
|
this.dmpId = data.dmpId;
|
||||||
|
this.editorModel = data ? new DmpEditorModel().fromModel(data) : new DmpEditorModel();
|
||||||
|
this.selectedBlueprint = data?.blueprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.editorModel = new DmpInvitationDialogEditorModel();
|
|
||||||
this.formGroup = this.editorModel.buildForm();
|
this.formGroup = this.editorModel.buildForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
send() {
|
send() {
|
||||||
if (!this.formGroup.valid) { return; }
|
if (!this.formGroup.get("users").valid) { return; }
|
||||||
let inviteTypeValues: DmpUserInviteTypePersist[] = [];
|
const userFormData = this.formGroup.get("users").value as DmpUserPersist[];
|
||||||
this.formGroup.get('users').value.forEach(x => {
|
|
||||||
let inviteType: DmpUserInviteTypePersist;
|
|
||||||
if (!(/^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$/).test(x)) {
|
|
||||||
inviteType = {
|
|
||||||
userId: null,
|
|
||||||
email: x
|
|
||||||
};
|
|
||||||
}else{
|
|
||||||
inviteType = {
|
|
||||||
userId: Guid.parse(x),
|
|
||||||
email: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
inviteTypeValues.push(inviteType)
|
|
||||||
})
|
|
||||||
const value: DmpUserInvitePersist = {
|
|
||||||
role: this.formGroup.get('role').value,
|
|
||||||
users: inviteTypeValues
|
|
||||||
}
|
|
||||||
// invitationObject.users.push(...(<any[]>this.formGroup.get('users').value).filter(user => typeof (user) === 'string').map(email => ({ email: email, name: email })));
|
|
||||||
// invitationObject.users.push(...(<any[]>this.formGroup.get('users').value).filter(user => typeof (user) !== 'string'));
|
|
||||||
// this.emails.forEach(email => {
|
|
||||||
// invitationObject.users.push({ email: email, name: email });
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.dmpService.inviteUsers(this.dmpId, value)
|
this.dmpService.inviteUsers(this.dmpId, {users: userFormData})
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(
|
.subscribe(
|
||||||
complete => {
|
complete => {
|
||||||
|
@ -120,23 +73,6 @@ export class DmpInvitationDialogComponent extends BaseComponent implements OnIni
|
||||||
this.dialogRef.close();
|
this.dialogRef.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
filterUsers(like: string): Observable<DmpAssociatedUser[]> {
|
|
||||||
const lookup: UserLookup = new UserLookup();
|
|
||||||
lookup.page = { size: 100, offset: 0 };
|
|
||||||
// if (excludedIds && excludedIds.length > 0) { lookup.excludedIds = excludedIds; }
|
|
||||||
// if (ids && ids.length > 0) { lookup.ids = ids; }
|
|
||||||
lookup.isActive = [IsActive.Active];
|
|
||||||
lookup.project = {
|
|
||||||
fields: [
|
|
||||||
nameof<User>(x => x.id),
|
|
||||||
nameof<User>(x => x.name)
|
|
||||||
]
|
|
||||||
};
|
|
||||||
lookup.order = { items: [nameof<User>(x => x.name)] };
|
|
||||||
if (like) { lookup.like = this.filterService.transformLike(like); }
|
|
||||||
return this.userService.queryDmpAssociated(lookup).pipe(takeUntil(this._destroyed), map(x => x.items));
|
|
||||||
}
|
|
||||||
|
|
||||||
hasValue(): boolean {
|
hasValue(): boolean {
|
||||||
return this.formGroup.get('users') && this.formGroup.get('users').value && this.formGroup.get('users').value.length > 0;
|
return this.formGroup.get('users') && this.formGroup.get('users').value && this.formGroup.get('users').value.length > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from "@angular/forms";
|
|
||||||
import { DmpUserRole } from "@app/core/common/enum/dmp-user-role";
|
|
||||||
import { DmpUserInvitePersist, DmpUserInviteTypePersist } from "@app/core/model/dmp/dmp";
|
|
||||||
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
|
||||||
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
|
|
||||||
import { Validation, ValidationContext } from '@common/forms/validation/validation-context';
|
|
||||||
|
|
||||||
export class DmpInvitationDialogEditorModel implements DmpUserInvitePersist {
|
|
||||||
users: DmpUserInviteTypePersist[];
|
|
||||||
role: DmpUserRole = DmpUserRole.User;
|
|
||||||
|
|
||||||
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
|
||||||
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
|
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
buildForm(context: ValidationContext = null, disabled: boolean = false): UntypedFormGroup {
|
|
||||||
if (context == null) { context = this.createValidationContext(); }
|
|
||||||
|
|
||||||
return this.formBuilder.group({
|
|
||||||
users: [{ value: this.users, disabled: disabled }, context.getValidation('users').validators],
|
|
||||||
role: [{ value: this.role, disabled: disabled }, context.getValidation('role').validators],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
createValidationContext(): ValidationContext {
|
|
||||||
const baseContext: ValidationContext = new ValidationContext();
|
|
||||||
const baseValidationArray: Validation[] = new Array<Validation>();
|
|
||||||
baseValidationArray.push({ key: 'users', validators: [BackendErrorValidator(this.validationErrorModel, 'users')] });
|
|
||||||
baseValidationArray.push({ key: 'role', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'role')] });
|
|
||||||
baseContext.validation = baseValidationArray;
|
|
||||||
return baseContext;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,9 +4,10 @@ import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.mod
|
||||||
import { RichTextEditorModule } from "@app/library/rich-text-editor/rich-text-editor.module";
|
import { RichTextEditorModule } from "@app/library/rich-text-editor/rich-text-editor.module";
|
||||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||||
import { DmpInvitationDialogComponent } from './dmp-invitation-dialog.component';
|
import { DmpInvitationDialogComponent } from './dmp-invitation-dialog.component';
|
||||||
|
import { UserFieldModule } from '../../user-field/user-field.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonUiModule, FormsModule, ReactiveFormsModule, AutoCompleteModule, RichTextEditorModule],
|
imports: [CommonUiModule, FormsModule, ReactiveFormsModule, AutoCompleteModule, RichTextEditorModule, UserFieldModule],
|
||||||
declarations: [DmpInvitationDialogComponent],
|
declarations: [DmpInvitationDialogComponent],
|
||||||
exports: [DmpInvitationDialogComponent]
|
exports: [DmpInvitationDialogComponent]
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { takeUntil } from 'rxjs/operators';
|
||||||
import { nameof } from 'ts-simple-nameof';
|
import { nameof } from 'ts-simple-nameof';
|
||||||
import { DmpInvitationDialogComponent } from '../invitation/dialog/dmp-invitation-dialog.component';
|
import { DmpInvitationDialogComponent } from '../invitation/dialog/dmp-invitation-dialog.component';
|
||||||
import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service';
|
import { ReferenceTypeService } from '@app/core/services/reference-type/reference-type.service';
|
||||||
|
import { DmpBlueprint, DmpBlueprintDefinition, DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dmp-overview',
|
selector: 'app-dmp-overview',
|
||||||
|
@ -47,6 +48,7 @@ import { ReferenceTypeService } from '@app/core/services/reference-type/referenc
|
||||||
export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
dmp: Dmp;
|
dmp: Dmp;
|
||||||
|
selectedBlueprint: DmpBlueprint;
|
||||||
researchers: DmpReference[] = [];
|
researchers: DmpReference[] = [];
|
||||||
isNew = true;
|
isNew = true;
|
||||||
isFinalized = false;
|
isFinalized = false;
|
||||||
|
@ -108,6 +110,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
||||||
.pipe(takeUntil(this._destroyed))
|
.pipe(takeUntil(this._destroyed))
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
this.dmp = data;
|
this.dmp = data;
|
||||||
|
this.selectedBlueprint= data.blueprint;
|
||||||
this.researchers = this.referenceService.getReferencesForTypes(this.dmp?.dmpReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
this.researchers = this.referenceService.getReferencesForTypes(this.dmp?.dmpReferences, [this.referenceTypeService.getResearcherReferenceType()]);
|
||||||
if (!this.hasDoi()) {
|
if (!this.hasDoi()) {
|
||||||
this.selectedModel = this.dmp.entityDois[0];
|
this.selectedModel = this.dmp.entityDois[0];
|
||||||
|
@ -566,7 +569,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
||||||
restoreFocus: false,
|
restoreFocus: false,
|
||||||
data: {
|
data: {
|
||||||
dmpId: rowId,
|
dmpId: rowId,
|
||||||
dmpName: rowName
|
dmpName: rowName,
|
||||||
|
blueprint: this.selectedBlueprint
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -738,6 +742,11 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.type)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.type)].join('.'),
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.source)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.source)].join('.'),
|
||||||
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
|
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
|
||||||
|
|
||||||
|
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.id)].join('.'),
|
||||||
|
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition)].join('.'),
|
||||||
|
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.id)].join('.'),
|
||||||
|
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.label)].join('.'),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<div cdkDropList class="col-12" (cdkDropListDropped)="dropUsers($event)">
|
||||||
|
<div *ngFor="let user of form.get('users').controls; let userIndex=index;" cdkDrag class="row align-items-center" [cdkDragDisabled]="form.disabled">
|
||||||
|
<div class="col-auto">
|
||||||
|
<span style="font-size: 15px;">{{userIndex + 1}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto d-flex"><mat-icon [ngClass]="{'drag-handle-disabled': form.disabled}" cdkDragHandle class="drag-handle">drag_indicator</mat-icon></div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<mat-button-toggle-group name="fontStyle" aria-label="Font Style" [formControl]="user.get('userType')">
|
||||||
|
<div *ngFor="let userType of dmpUserTypeEnumValues">
|
||||||
|
<mat-button-toggle class="lang-button" [value]="userType">{{enumUtils.toDmpUserTypeString(userType)}}</mat-button-toggle>
|
||||||
|
</div>
|
||||||
|
</mat-button-toggle-group>
|
||||||
|
</div>
|
||||||
|
<div class="col pt-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" *ngIf="user.get('userType').value == dmpUserTypeEnum.Internal">
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>{{'DMP-EDITOR.FIELDS1.USER' | translate}}*</mat-label>
|
||||||
|
<app-single-auto-complete [formControl]="user.get('user')" [hidePlaceholder]="true" [configuration]="userService.singleAutoCompleteDmpAssociatedUserConfiguration"></app-single-auto-complete>
|
||||||
|
<mat-error *ngIf="user.get('user').hasError('backendError')">{{user.get('user').getError('backendError').message}}</mat-error>
|
||||||
|
<mat-error *ngIf="user.get('user').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col" *ngIf="user.get('userType').value == dmpUserTypeEnum.External">
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>{{'DMP-EDITOR.FIELDS1.EMAIL' | translate}}*</mat-label>
|
||||||
|
<input matInput type="text" name="email" [formControl]="user.get('email')">
|
||||||
|
<mat-error *ngIf="user.get('email').hasError('backendError')">{{user.get('email').getError('backendError').message}}</mat-error>
|
||||||
|
<mat-error *ngIf="user.get('email').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>{{'DMP-EDITOR.FIELDS1.USER-ROLE' | translate}}</mat-label>
|
||||||
|
<mat-select [formControl]="user.get('role')">
|
||||||
|
<mat-option *ngFor="let userRole of dmpUserRoleEnumValues" [value]="userRole">{{enumUtils.toDmpUserRoleString(userRole)}}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="user.get('role').hasError('backendError')">{{user.get('role').getError('backendError').message}}</mat-error>
|
||||||
|
<mat-error *ngIf="user.get('role').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col" *ngIf="sections">
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<mat-label>{{'DMP-EDITOR.FIELDS1.SECTION' | translate}}</mat-label>
|
||||||
|
<mat-select [formControl]="user.get('sectionId')">
|
||||||
|
<mat-option *ngFor="let section of sections" [value]="section.id">
|
||||||
|
{{ section.label }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="user.get('sectionId').hasError('backendError')">{{user.get('sectionId').getError('backendError').message}}</mat-error>
|
||||||
|
<mat-error *ngIf="user.get('sectionId').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button mat-icon-button class="action-list-icon" matTooltip="{{'DMP-EDITOR.ACTIONS1.REMOVE-USER' | translate}}" (click)="removeUser(userIndex)" [disabled]="form.disabled">
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-error *ngIf="form.get('users').dirty && form.get('users').hasError('required')">{{'DMP-EDITOR.USERS-REQUIRED' | translate}}</mat-error>
|
||||||
|
<mat-error *ngIf="form.get('users').hasError('backendError')">{{form.get('users').getError('backendError').message}}</mat-error>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<button mat-icon-button (click)="addUser()" [disabled]="form.disabled">
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,9 @@
|
||||||
|
.drag-handle {
|
||||||
|
cursor: move;
|
||||||
|
color: var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-handle-disabled {
|
||||||
|
cursor: auto;
|
||||||
|
color: rgba(0, 0, 0, 0.38);;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
import { FormArray, UntypedFormArray, UntypedFormGroup } from '@angular/forms';
|
||||||
|
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
|
||||||
|
import { MultipleAutoCompleteConfiguration } from '@app/library/auto-complete/multiple/multiple-auto-complete-configuration';
|
||||||
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { DmpEditorModel, DmpUserEditorModel } from '../dmp-editor-blueprint/dmp-editor.model';
|
||||||
|
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
|
||||||
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
import { DmpUserType } from '@app/core/common/enum/dmp-user-type';
|
||||||
|
import { DmpUserRole } from '@app/core/common/enum/dmp-user-role';
|
||||||
|
import { UserService } from '@app/core/services/user/user.service';
|
||||||
|
import { DmpBlueprintDefinitionSection } from '@app/core/model/dmp-blueprint/dmp-blueprint';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-user-field-component',
|
||||||
|
templateUrl: 'user-field.component.html',
|
||||||
|
styleUrls: ['./user-field.component.scss']
|
||||||
|
})
|
||||||
|
export class UserFieldComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() form;
|
||||||
|
@Input() validationErrorModel: ValidationErrorModel;
|
||||||
|
@Input() label: string = null;
|
||||||
|
@Input() required: boolean = false;
|
||||||
|
@Input() placeholder: string;
|
||||||
|
@Input() sections: DmpBlueprintDefinitionSection[] = null;
|
||||||
|
|
||||||
|
dmpUserTypeEnum = DmpUserType;
|
||||||
|
dmpUserTypeEnumValues = this.enumUtils.getEnumValues<DmpUserType>(DmpUserType);
|
||||||
|
dmpUserRoleEnumValues = this.enumUtils.getEnumValues<DmpUserRole>(DmpUserRole);
|
||||||
|
|
||||||
|
multipleAutoCompleteSearchConfiguration: MultipleAutoCompleteConfiguration;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public enumUtils: EnumUtils,
|
||||||
|
public userService: UserService
|
||||||
|
) { super(); }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
addUser(): void {
|
||||||
|
const userArray = this.form.get('users') as FormArray;
|
||||||
|
const dmpUser: DmpUserEditorModel = new DmpUserEditorModel(this.validationErrorModel);
|
||||||
|
userArray.push(dmpUser.buildForm({rootPath: "users[" + userArray.length + "]."}));
|
||||||
|
}
|
||||||
|
|
||||||
|
removeUser(userIndex: number): void {
|
||||||
|
(this.form.get('users') as FormArray).removeAt(userIndex);
|
||||||
|
|
||||||
|
DmpEditorModel.reApplyPropertiesValidators(
|
||||||
|
{
|
||||||
|
formGroup: this.form,
|
||||||
|
validationErrorModel: this.validationErrorModel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.form.get('users').markAsDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
dropUsers(event: CdkDragDrop<string[]>) {
|
||||||
|
const usersFormArray = (this.form.get('users') as FormArray);
|
||||||
|
|
||||||
|
moveItemInArray(usersFormArray.controls, event.previousIndex, event.currentIndex);
|
||||||
|
usersFormArray.updateValueAndValidity();
|
||||||
|
|
||||||
|
DmpEditorModel.reApplyPropertiesValidators(
|
||||||
|
{
|
||||||
|
formGroup: this.form,
|
||||||
|
validationErrorModel: this.validationErrorModel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.form.get('users').markAsDirty();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FormattingModule } from '@app/core/formatting.module';
|
||||||
|
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
|
||||||
|
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||||
|
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||||
|
import { UserFieldComponent } from './user-field.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonUiModule,
|
||||||
|
CommonFormsModule,
|
||||||
|
FormattingModule,
|
||||||
|
AutoCompleteModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
UserFieldComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
UserFieldComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class UserFieldModule { }
|
Loading…
Reference in New Issue