tags field changes

This commit is contained in:
Efstratios Giannopoulos 2024-05-21 18:08:27 +03:00
parent dadef8297c
commit 0a4cef782e
28 changed files with 248 additions and 94 deletions

View File

@ -68,10 +68,14 @@ public enum FieldType implements DatabaseEnum<String> {
} }
public static boolean isTextListType(FieldType fieldType){ public static boolean isTextListType(FieldType fieldType){
return fieldType.equals(FieldType.SELECT) || fieldType.equals(FieldType.TAGS) || fieldType.equals(FieldType.INTERNAL_ENTRIES_DMPS) || return fieldType.equals(FieldType.SELECT) || fieldType.equals(FieldType.INTERNAL_ENTRIES_DMPS) ||
fieldType.equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS); fieldType.equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS);
} }
public static boolean isTagType(FieldType fieldType){
return fieldType.equals(FieldType.TAGS);
}
public static boolean isDateType(FieldType fieldType){ public static boolean isDateType(FieldType fieldType){
return fieldType.equals(FieldType.DATE_PICKER); return fieldType.equals(FieldType.DATE_PICKER);
} }

View File

@ -1,16 +1,15 @@
package org.opencdmp.data; package org.opencdmp.data;
import jakarta.persistence.*;
import org.opencdmp.commons.enums.DescriptionStatus; import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.data.converters.enums.DescriptionStatusConverter; import org.opencdmp.data.converters.enums.DescriptionStatusConverter;
import org.opencdmp.data.converters.enums.IsActiveConverter; import org.opencdmp.data.converters.enums.IsActiveConverter;
import org.opencdmp.data.tenant.TenantScopedBaseEntity; import org.opencdmp.data.tenant.TenantScopedBaseEntity;
import jakarta.persistence.*;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.UUID;
@Entity @Entity
@ -86,7 +85,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
public UUID getId() { public UUID getId() {
return id; return this.id;
} }
public void setId(UUID id) { public void setId(UUID id) {
@ -94,7 +93,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public String getLabel() { public String getLabel() {
return label; return this.label;
} }
public void setLabel(String label) { public void setLabel(String label) {
@ -102,7 +101,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public String getProperties() { public String getProperties() {
return properties; return this.properties;
} }
public void setProperties(String properties) { public void setProperties(String properties) {
@ -110,7 +109,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public DescriptionStatus getStatus() { public DescriptionStatus getStatus() {
return status; return this.status;
} }
public void setStatus(DescriptionStatus status) { public void setStatus(DescriptionStatus status) {
@ -118,7 +117,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public String getDescription() { public String getDescription() {
return description; return this.description;
} }
public void setDescription(String description) { public void setDescription(String description) {
@ -126,7 +125,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public Instant getCreatedAt() { public Instant getCreatedAt() {
return createdAt; return this.createdAt;
} }
public void setCreatedAt(Instant createdAt) { public void setCreatedAt(Instant createdAt) {
@ -134,7 +133,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public Instant getUpdatedAt() { public Instant getUpdatedAt() {
return updatedAt; return this.updatedAt;
} }
public void setUpdatedAt(Instant updatedAt) { public void setUpdatedAt(Instant updatedAt) {
@ -142,7 +141,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public IsActive getIsActive() { public IsActive getIsActive() {
return isActive; return this.isActive;
} }
public void setIsActive(IsActive isActive) { public void setIsActive(IsActive isActive) {
@ -150,7 +149,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public Instant getFinalizedAt() { public Instant getFinalizedAt() {
return finalizedAt; return this.finalizedAt;
} }
public void setFinalizedAt(Instant finalizedAt) { public void setFinalizedAt(Instant finalizedAt) {
@ -158,7 +157,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public UUID getCreatedById() { public UUID getCreatedById() {
return createdById; return this.createdById;
} }
public void setCreatedById(UUID createdById) { public void setCreatedById(UUID createdById) {
@ -166,7 +165,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public UUID getDmpDescriptionTemplateId() { public UUID getDmpDescriptionTemplateId() {
return dmpDescriptionTemplateId; return this.dmpDescriptionTemplateId;
} }
public void setDmpDescriptionTemplateId(UUID dmpDescriptionTemplateId) { public void setDmpDescriptionTemplateId(UUID dmpDescriptionTemplateId) {
@ -174,7 +173,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public UUID getDmpId() { public UUID getDmpId() {
return dmpId; return this.dmpId;
} }
public void setDmpId(UUID dmpId) { public void setDmpId(UUID dmpId) {
@ -182,7 +181,7 @@ public class DescriptionEntity extends TenantScopedBaseEntity {
} }
public UUID getDescriptionTemplateId() { public UUID getDescriptionTemplateId() {
return descriptionTemplateId; return this.descriptionTemplateId;
} }
public void setDescriptionTemplateId(UUID descriptionTemplateId) { public void setDescriptionTemplateId(UUID descriptionTemplateId) {

View File

@ -18,7 +18,7 @@ public class Prefilling {
public static final String _tag = "tag"; public static final String _tag = "tag";
public String getId() { public String getId() {
return id; return this.id;
} }
public void setId(String id) { public void setId(String id) {
@ -26,7 +26,7 @@ public class Prefilling {
} }
public String getLabel() { public String getLabel() {
return label; return this.label;
} }
public void setLabel(String label) { public void setLabel(String label) {
@ -34,7 +34,7 @@ public class Prefilling {
} }
public Map<String, String> getData() { public Map<String, String> getData() {
return data; return this.data;
} }
public void setData(Map<String, String> data) { public void setData(Map<String, String> data) {
@ -42,7 +42,7 @@ public class Prefilling {
} }
public String getKey() { public String getKey() {
return key; return this.key;
} }
public void setKey(String key) { public void setKey(String key) {
@ -50,7 +50,7 @@ public class Prefilling {
} }
public String getTag() { public String getTag() {
return tag; return this.tag;
} }
public void setTag(String tag) { public void setTag(String tag) {

View File

@ -13,11 +13,14 @@ import org.opencdmp.commons.types.description.FieldEntity;
import org.opencdmp.commons.types.descriptiontemplate.fielddata.LabelAndMultiplicityDataEntity; import org.opencdmp.commons.types.descriptiontemplate.fielddata.LabelAndMultiplicityDataEntity;
import org.opencdmp.commons.types.descriptiontemplate.fielddata.SelectDataEntity; import org.opencdmp.commons.types.descriptiontemplate.fielddata.SelectDataEntity;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.model.Tag;
import org.opencdmp.model.builder.BaseBuilder; import org.opencdmp.model.builder.BaseBuilder;
import org.opencdmp.model.builder.TagBuilder;
import org.opencdmp.model.builder.reference.ReferenceBuilder; import org.opencdmp.model.builder.reference.ReferenceBuilder;
import org.opencdmp.model.description.Field; import org.opencdmp.model.description.Field;
import org.opencdmp.model.reference.Reference; import org.opencdmp.model.reference.Reference;
import org.opencdmp.query.ReferenceQuery; import org.opencdmp.query.ReferenceQuery;
import org.opencdmp.query.TagQuery;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -67,6 +70,9 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(Field._references)); FieldSet referenceFields = fields.extractPrefixed(this.asPrefix(Field._references));
Map<UUID, Reference> referenceItemsMap = FieldType.isReferenceType(fieldType) ? this.collectReferences(referenceFields, data) : null; Map<UUID, Reference> referenceItemsMap = FieldType.isReferenceType(fieldType) ? this.collectReferences(referenceFields, data) : null;
FieldSet tagFields = fields.extractPrefixed(this.asPrefix(Field._tags));
Map<UUID, Tag> tagsItemsMap = FieldType.isTagType(fieldType) ? this.collectTags(tagFields, data) : null;
List<Field> models = new ArrayList<>(); List<Field> models = new ArrayList<>();
for (FieldEntity d : data) { for (FieldEntity d : data) {
Field m = new Field(); Field m = new Field();
@ -75,7 +81,9 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
if (fields.hasField(this.asIndexer(Field._textValue)) && FieldType.isTextType(fieldType)) m.setTextValue(d.getTextValue()); if (fields.hasField(this.asIndexer(Field._textValue)) && FieldType.isTextType(fieldType)) m.setTextValue(d.getTextValue());
if (fields.hasField(this.asIndexer(Field._textListValue)) && FieldType.isTextListType(fieldType)) { if (fields.hasField(this.asIndexer(Field._textListValue)) && FieldType.isTextListType(fieldType)) {
boolean isMultiSelect = true; boolean isMultiSelect = true;
if(this.fieldEntity != null && this.fieldEntity.getData() != null && (this.fieldEntity.getData().getFieldType().equals(FieldType.SELECT) || this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DMPS) || this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS))){ if(this.fieldEntity != null && this.fieldEntity.getData() != null && (this.fieldEntity.getData().getFieldType().equals(FieldType.SELECT)
|| this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DMPS)
|| this.fieldEntity.getData().getFieldType().equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS))){
if (this.fieldEntity.getData() instanceof SelectDataEntity) isMultiSelect = ((SelectDataEntity) this.fieldEntity.getData()).getMultipleSelect(); if (this.fieldEntity.getData() instanceof SelectDataEntity) isMultiSelect = ((SelectDataEntity) this.fieldEntity.getData()).getMultipleSelect();
else if (this.fieldEntity.getData() instanceof LabelAndMultiplicityDataEntity) isMultiSelect = ((LabelAndMultiplicityDataEntity) this.fieldEntity.getData()).getMultipleSelect(); else if (this.fieldEntity.getData() instanceof LabelAndMultiplicityDataEntity) isMultiSelect = ((LabelAndMultiplicityDataEntity) this.fieldEntity.getData()).getMultipleSelect();
@ -94,6 +102,13 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
if (referenceItemsMap.containsKey(referenceId)) m.getReferences().add(referenceItemsMap.get(referenceId)); if (referenceItemsMap.containsKey(referenceId)) m.getReferences().add(referenceItemsMap.get(referenceId));
} }
} }
if (!tagFields.isEmpty() && FieldType.isTagType(fieldType) && tagsItemsMap != null && d.getTextListValue() != null && !d.getTextListValue().isEmpty()) {
m.setTags(new ArrayList<>());
for (UUID tagId : d.getTextListValue().stream().map(UUID::fromString).toList()){
if (tagsItemsMap.containsKey(tagId)) m.getTags().add(tagsItemsMap.get(tagId));
}
}
if (!externalIdentifierFields.isEmpty() && d.getExternalIdentifier() != null && FieldType.isExternalIdentifierType(fieldType)) m.setExternalIdentifier(this.builderFactory.builder(ExternalIdentifierBuilder.class).authorize(this.authorize).build(externalIdentifierFields, d.getExternalIdentifier())); if (!externalIdentifierFields.isEmpty() && d.getExternalIdentifier() != null && FieldType.isExternalIdentifierType(fieldType)) m.setExternalIdentifier(this.builderFactory.builder(ExternalIdentifierBuilder.class).authorize(this.authorize).build(externalIdentifierFields, d.getExternalIdentifier()));
models.add(m); models.add(m);
@ -122,7 +137,7 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
for (FieldEntity field: data) { for (FieldEntity field: data) {
if (field.getTextListValue() != null) { if (field.getTextListValue() != null) {
for (String value: field.getTextListValue()) { for (String value: field.getTextListValue()) {
if (value != null && !ids.contains(value)) ids.add(UUID.fromString(value)); if (value != null && !ids.contains(UUID.fromString(value))) ids.add(UUID.fromString(value));
} }
} }
} }
@ -140,4 +155,43 @@ public class FieldBuilder extends BaseBuilder<Field, FieldEntity> {
return itemMap; return itemMap;
} }
private Map<UUID, Tag> collectTags(FieldSet fields, List<FieldEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", Tag.class.getSimpleName());
Map<UUID, Tag> itemMap;
if (!fields.hasOtherField(this.asIndexer(Tag._id))) {
itemMap = this.asEmpty(
data.stream().map(FieldEntity::getTextListValue).flatMap(List::stream).map(UUID::fromString).distinct().collect(Collectors.toList()),
x -> {
Tag item = new Tag();
item.setId(x);
return item;
},
Tag::getId);
} else {
List<UUID> ids = new ArrayList<>();
for (FieldEntity field: data) {
if (field.getTextListValue() != null) {
for (String value: field.getTextListValue()) {
if (value != null && !ids.contains(UUID.fromString(value))) ids.add(UUID.fromString(value));
}
}
}
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(Tag._id);
TagQuery q = this.queryFactory.query(TagQuery.class).disableTracking().authorize(this.authorize).ids(ids);
itemMap = this.builderFactory.builder(TagBuilder.class).authorize(this.authorize).asForeignKey(q, clone, Tag::getId);
}
if (!fields.hasField(Tag._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
} }

View File

@ -1,6 +1,7 @@
package org.opencdmp.model.description; package org.opencdmp.model.description;
import org.opencdmp.model.Tag;
import org.opencdmp.model.reference.Reference; import org.opencdmp.model.reference.Reference;
import java.time.Instant; import java.time.Instant;
@ -23,6 +24,9 @@ public class Field {
private List<Reference> references; private List<Reference> references;
public static final String _references = "references"; public static final String _references = "references";
private List<Tag> tags;
public static final String _tags = "tags";
private ExternalIdentifier externalIdentifier; private ExternalIdentifier externalIdentifier;
public static final String _externalIdentifier = "externalIdentifier"; public static final String _externalIdentifier = "externalIdentifier";
@ -66,6 +70,14 @@ public class Field {
this.references = references; this.references = references;
} }
public List<Tag> getTags() {
return this.tags;
}
public void setTags(List<Tag> tags) {
this.tags = tags;
}
public ExternalIdentifier getExternalIdentifier() { public ExternalIdentifier getExternalIdentifier() {
return this.externalIdentifier; return this.externalIdentifier;
} }

View File

@ -1,8 +1,8 @@
package org.opencdmp.model.persist; package org.opencdmp.model.persist;
import org.opencdmp.commons.validation.BaseValidator;
import gr.cite.tools.validation.specification.Specification; import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.TagEntity; import org.opencdmp.data.TagEntity;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
@ -22,7 +22,7 @@ public class TagPersist {
public final static String _id = "id"; public final static String _id = "id";
private String label = null; private String label;
public final static String _label = "label"; public final static String _label = "label";
@ -31,7 +31,7 @@ public class TagPersist {
public final static String _hash = "hash"; public final static String _hash = "hash";
public UUID getId() { public UUID getId() {
return id; return this.id;
} }
public void setId(UUID id) { public void setId(UUID id) {
@ -39,7 +39,7 @@ public class TagPersist {
} }
public String getLabel() { public String getLabel() {
return label; return this.label;
} }
public void setLabel(String label) { public void setLabel(String label) {
@ -47,7 +47,7 @@ public class TagPersist {
} }
public String getHash() { public String getHash() {
return hash; return this.hash;
} }
public void setHash(String hash) { public void setHash(String hash) {
@ -55,7 +55,7 @@ public class TagPersist {
} }
@Component(TagPersistValidator.ValidatorName) @Component(TagPersistValidator.ValidatorName)
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public static class TagPersistValidator extends BaseValidator<TagPersist> { public static class TagPersistValidator extends BaseValidator<TagPersist> {
public static final String ValidatorName = "TagPersistValidator"; public static final String ValidatorName = "TagPersistValidator";
@ -77,18 +77,18 @@ public class TagPersist {
this.spec() this.spec()
.iff(() -> this.isValidGuid(item.getId())) .iff(() -> this.isValidGuid(item.getId()))
.must(() -> this.isValidHash(item.getHash())) .must(() -> this.isValidHash(item.getHash()))
.failOn(TagPersist._hash).failWith(messageSource.getMessage("Validation_Required", new Object[]{TagPersist._hash}, LocaleContextHolder.getLocale())), .failOn(TagPersist._hash).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{TagPersist._hash}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(() -> !this.isValidGuid(item.getId())) .iff(() -> !this.isValidGuid(item.getId()))
.must(() -> !this.isValidHash(item.getHash())) .must(() -> !this.isValidHash(item.getHash()))
.failOn(TagPersist._hash).failWith(messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())), .failOn(TagPersist._hash).failWith(this.messageSource.getMessage("Validation_OverPosting", new Object[]{}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.must(() -> !this.isEmpty(item.getLabel())) .must(() -> !this.isEmpty(item.getLabel()))
.failOn(TagPersist._label).failWith(messageSource.getMessage("Validation_Required", new Object[]{TagPersist._label}, LocaleContextHolder.getLocale())), .failOn(TagPersist._label).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{TagPersist._label}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(() -> !this.isEmpty(item.getLabel())) .iff(() -> !this.isEmpty(item.getLabel()))
.must(() -> this.lessEqualLength(item.getLabel(), TagEntity._labelLength)) .must(() -> this.lessEqualLength(item.getLabel(), TagEntity._labelLength))
.failOn(TagPersist._label).failWith(messageSource.getMessage("Validation_MaxLength", new Object[]{TagPersist._label}, LocaleContextHolder.getLocale())) .failOn(TagPersist._label).failWith(this.messageSource.getMessage("Validation_MaxLength", new Object[]{TagPersist._label}, LocaleContextHolder.getLocale()))
); );
} }
} }

View File

@ -10,6 +10,7 @@ import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.persist.ReferencePersist; import org.opencdmp.model.persist.ReferencePersist;
import org.opencdmp.model.persist.TagPersist;
import org.opencdmp.service.visibility.VisibilityService; import org.opencdmp.service.visibility.VisibilityService;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.context.i18n.LocaleContextHolder;
@ -42,6 +43,9 @@ public class FieldPersist {
private ReferencePersist reference; private ReferencePersist reference;
public static final String _reference = "reference"; public static final String _reference = "reference";
private List<String> tags;
public static final String _tags = "tags";
private ExternalIdentifierPersist externalIdentifier; private ExternalIdentifierPersist externalIdentifier;
public static final String _externalIdentifier = "externalIdentifier"; public static final String _externalIdentifier = "externalIdentifier";
@ -101,6 +105,14 @@ public class FieldPersist {
this.externalIdentifier = externalIdentifier; this.externalIdentifier = externalIdentifier;
} }
public List<String> getTags() {
return this.tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
@Component(PersistValidator.ValidatorName) @Component(PersistValidator.ValidatorName)
public static class PersistValidator extends BaseValidator<FieldPersist> { public static class PersistValidator extends BaseValidator<FieldPersist> {
@ -153,12 +165,12 @@ public class FieldPersist {
.must(() -> !this.isNull(item.getExternalIdentifier())) .must(() -> !this.isNull(item.getExternalIdentifier()))
.failOn(FieldPersist._externalIdentifier).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._externalIdentifier}, LocaleContextHolder.getLocale())), .failOn(FieldPersist._externalIdentifier).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._externalIdentifier}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(()-> FieldType.isTextListType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required && !fieldType.equals(FieldType.TAGS)) .iff(()-> FieldType.isTextListType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
.must(() -> !this.isListNullOrEmpty(item.getTextListValue()) || !this.isEmpty(item.getTextValue())) .must(() -> !this.isListNullOrEmpty(item.getTextListValue()) || !this.isEmpty(item.getTextValue()))
.failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())), .failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(()-> fieldType.equals(FieldType.TAGS) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required) .iff(()-> FieldType.isTagType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
.must(() -> !this.isListNullOrEmpty(item.getTextListValue())) .must(() -> !this.isListNullOrEmpty(item.getTags()))
.failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())), .failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())),
this.spec() this.spec()
.iff(()-> FieldType.isReferenceType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required) .iff(()-> FieldType.isReferenceType(fieldType) && DescriptionStatus.Finalized.equals(this.status) && isVisible && required)
@ -168,6 +180,11 @@ public class FieldPersist {
.iff(()-> !this.isNull(item.getTextListValue()) && (fieldType.equals(FieldType.INTERNAL_ENTRIES_DMPS) || fieldType.equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS))) .iff(()-> !this.isNull(item.getTextListValue()) && (fieldType.equals(FieldType.INTERNAL_ENTRIES_DMPS) || fieldType.equals(FieldType.INTERNAL_ENTRIES_DESCRIPTIONS)))
.must(() -> item.getTextListValue().stream().allMatch(this::isUUID)) .must(() -> item.getTextListValue().stream().allMatch(this::isUUID))
.failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_UnexpectedValue", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())), .failOn(FieldPersist._textListValue).failWith(this.messageSource.getMessage("Validation_UnexpectedValue", new Object[]{FieldPersist._textListValue}, LocaleContextHolder.getLocale())),
this.navSpec()
.iff(() -> FieldType.isTagType(fieldType) && !this.isListNullOrEmpty(item.getTags()))
.on(FieldPersist._tags)
.over(item.getTags())
.using((itm) -> this.validatorFactory.validator(TagPersist.TagPersistValidator.class)),
this.navSpec() this.navSpec()
.iff(() -> FieldType.isReferenceType(fieldType) && !this.isListNullOrEmpty(item.getReferences())) .iff(() -> FieldType.isReferenceType(fieldType) && !this.isListNullOrEmpty(item.getReferences()))
.on(FieldPersist._references) .on(FieldPersist._references)

View File

@ -30,7 +30,8 @@ import org.opencdmp.commons.types.descriptionreference.DescriptionReferenceDataE
import org.opencdmp.commons.types.descriptiontemplate.FieldSetEntity; import org.opencdmp.commons.types.descriptiontemplate.FieldSetEntity;
import org.opencdmp.commons.types.descriptiontemplate.fielddata.ReferenceTypeDataEntity; import org.opencdmp.commons.types.descriptiontemplate.fielddata.ReferenceTypeDataEntity;
import org.opencdmp.commons.types.descriptiontemplate.fielddata.UploadDataEntity; import org.opencdmp.commons.types.descriptiontemplate.fielddata.UploadDataEntity;
import org.opencdmp.commons.types.descriptiontemplate.importexport.*; import org.opencdmp.commons.types.descriptiontemplate.importexport.DescriptionTemplateFieldImportExport;
import org.opencdmp.commons.types.descriptiontemplate.importexport.DescriptionTemplateImportExport;
import org.opencdmp.commons.types.descriptiontemplate.importexport.fielddata.ReferenceTypeDataImportExport; import org.opencdmp.commons.types.descriptiontemplate.importexport.fielddata.ReferenceTypeDataImportExport;
import org.opencdmp.commons.types.notification.*; import org.opencdmp.commons.types.notification.*;
import org.opencdmp.commons.types.reference.DefinitionEntity; import org.opencdmp.commons.types.reference.DefinitionEntity;
@ -43,10 +44,7 @@ import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEn
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
import org.opencdmp.model.DescriptionValidationResult; import org.opencdmp.model.*;
import org.opencdmp.model.DmpDescriptionTemplate;
import org.opencdmp.model.StorageFile;
import org.opencdmp.model.UserContactInfo;
import org.opencdmp.model.builder.description.DescriptionBuilder; import org.opencdmp.model.builder.description.DescriptionBuilder;
import org.opencdmp.model.deleter.DescriptionDeleter; import org.opencdmp.model.deleter.DescriptionDeleter;
import org.opencdmp.model.deleter.DescriptionReferenceDeleter; import org.opencdmp.model.deleter.DescriptionReferenceDeleter;
@ -68,6 +66,7 @@ import org.opencdmp.service.filetransformer.FileTransformerService;
import org.opencdmp.service.responseutils.ResponseUtilsService; import org.opencdmp.service.responseutils.ResponseUtilsService;
import org.opencdmp.service.storage.StorageFileProperties; import org.opencdmp.service.storage.StorageFileProperties;
import org.opencdmp.service.storage.StorageFileService; import org.opencdmp.service.storage.StorageFileService;
import org.opencdmp.service.tag.TagService;
import org.opencdmp.service.visibility.VisibilityService; import org.opencdmp.service.visibility.VisibilityService;
import org.opencdmp.service.visibility.VisibilityServiceImpl; import org.opencdmp.service.visibility.VisibilityServiceImpl;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -128,6 +127,7 @@ public class DescriptionServiceImpl implements DescriptionService {
private final TenantScope tenantScope; private final TenantScope tenantScope;
private final ResponseUtilsService responseUtilsService; private final ResponseUtilsService responseUtilsService;
private final DescriptionTemplateService descriptionTemplateService; private final DescriptionTemplateService descriptionTemplateService;
private final TagService tagService;
@Autowired @Autowired
public DescriptionServiceImpl( public DescriptionServiceImpl(
@ -142,7 +142,7 @@ public class DescriptionServiceImpl implements DescriptionService {
QueryFactory queryFactory, QueryFactory queryFactory,
JsonHandlingService jsonHandlingService, JsonHandlingService jsonHandlingService,
UserScope userScope, UserScope userScope,
XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService) { XmlHandlingService xmlHandlingService, NotifyIntegrationEventHandler eventHandler, NotificationProperties notificationProperties, FileTransformerService fileTransformerService, ElasticService elasticService, ValidatorFactory validatorFactory, StorageFileProperties storageFileConfig, StorageFileService storageFileService, AuthorizationContentResolver authorizationContentResolver, AnnotationEntityTouchedIntegrationEventHandler annotationEntityTouchedIntegrationEventHandler, AnnotationEntityRemovalIntegrationEventHandler annotationEntityRemovalIntegrationEventHandler, TenantScope tenantScope, ResponseUtilsService responseUtilsService, DescriptionTemplateService descriptionTemplateService, TagService tagService) {
this.entityManager = entityManager; this.entityManager = entityManager;
this.authorizationService = authorizationService; this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory; this.deleterFactory = deleterFactory;
@ -168,6 +168,7 @@ public class DescriptionServiceImpl implements DescriptionService {
this.tenantScope = tenantScope; this.tenantScope = tenantScope;
this.responseUtilsService = responseUtilsService; this.responseUtilsService = responseUtilsService;
this.descriptionTemplateService = descriptionTemplateService; this.descriptionTemplateService = descriptionTemplateService;
this.tagService = tagService;
} }
@Override @Override
@ -574,13 +575,28 @@ public class DescriptionServiceImpl implements DescriptionService {
} }
if (fieldType.equals(FieldType.SELECT) && this.conventionService.isListNullOrEmpty(persist.getTextListValue()) && !this.conventionService.isNullOrEmpty(persist.getTextValue())){ if (fieldType.equals(FieldType.SELECT) && this.conventionService.isListNullOrEmpty(persist.getTextListValue()) && !this.conventionService.isNullOrEmpty(persist.getTextValue())){
data.setTextListValue(List.of(persist.getTextValue())); data.setTextListValue(List.of(persist.getTextValue()));
} else if (fieldType.equals(FieldType.SELECT) || fieldType.equals(FieldType.TAGS)){ } else if (fieldType.equals(FieldType.SELECT)){
data.setTextListValue(persist.getTextListValue()); data.setTextListValue(persist.getTextListValue());
} }
} } else if (FieldType.isReferenceType(fieldType) && fieldEntity != null ) {
else if (FieldType.isReferenceType(fieldType) && fieldEntity != null ) {
List<UUID> referenceIds = fieldToReferenceMap.getOrDefault(fieldEntity.getId(), null); List<UUID> referenceIds = fieldToReferenceMap.getOrDefault(fieldEntity.getId(), null);
if (referenceIds != null) data.setTextListValue(referenceIds.stream().map(UUID::toString).toList()); if (referenceIds != null) data.setTextListValue(referenceIds.stream().map(UUID::toString).toList());
} else if (FieldType.isTagType(fieldType)) {
if (!this.conventionService.isListNullOrEmpty(persist.getTags())){
List<TagEntity> existingTags = this.queryFactory.query(TagQuery.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).disableTracking().tags(persist.getTags().stream().distinct().toList()).collectAs(new BaseFieldSet().ensure(Tag._id).ensure(Tag._label));
List<String> values = new ArrayList<>();
for (String tag : persist.getTags().stream().distinct().toList()){
TagEntity existingTag = existingTags.stream().filter(x-> x.getLabel().equalsIgnoreCase(tag)).findFirst().orElse(null);
if (existingTag == null) {
TagPersist tagPersist = new TagPersist();
tagPersist.setLabel(tag);
values.add(this.tagService.persist(tagPersist, new BaseFieldSet().ensure(Tag._id)).getId().toString());
} else values.add(existingTag.getId().toString());
}
if (!this.conventionService.isListNullOrEmpty(values)) data.setTextListValue(values);
}
} }
else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue()); else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue());
else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue()); else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue());
@ -1032,6 +1048,18 @@ public class DescriptionServiceImpl implements DescriptionService {
} }
} }
} }
else if (FieldType.isTagType(fieldType) && fieldEntity != null ) {
if (!this.conventionService.isListNullOrEmpty(data.getTextListValue()) && !this.conventionService.isListNullOrEmpty(references)){
List<UUID> tagIdsInField = data.getTextListValue().stream().filter(x -> this.conventionService.isValidGuid(UUID.fromString(x))).toList().stream().map(UUID::fromString).collect(Collectors.toList());
if (!this.conventionService.isListNullOrEmpty(tagIdsInField)){
List<TagEntity> tagsInField = this.queryFactory.query(TagQuery.class).isActive(IsActive.Active).ids(tagIdsInField).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).collect();
if (!this.conventionService.isListNullOrEmpty(tagsInField)){
persist.setTags(tagsInField.stream().map(TagEntity::getLabel).toList());
}
}
}
}
return persist; return persist;
} }
@ -1107,7 +1135,7 @@ public class DescriptionServiceImpl implements DescriptionService {
descriptionTagQuery.isActive(IsActive.Active); descriptionTagQuery.isActive(IsActive.Active);
List<TagEntity> tagsEntities = this.queryFactory.query(TagQuery.class).disableTracking().descriptionTagSubQuery(descriptionTagQuery).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).isActive(IsActive.Active).collect(); List<TagEntity> tagsEntities = this.queryFactory.query(TagQuery.class).disableTracking().descriptionTagSubQuery(descriptionTagQuery).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).isActive(IsActive.Active).collect();
if (!this.conventionService.isListNullOrEmpty(tagsEntities)) xml.setTags(tagsEntities.stream().map(x -> x.getLabel()).collect(Collectors.toList())); if (!this.conventionService.isListNullOrEmpty(tagsEntities)) xml.setTags(tagsEntities.stream().map(TagEntity::getLabel).collect(Collectors.toList()));
DescriptionTemplateEntity descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().ids(data.getDescriptionTemplateId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).isActive(IsActive.Active).first(); DescriptionTemplateEntity descriptionTemplateEntity = this.queryFactory.query(DescriptionTemplateQuery.class).disableTracking().ids(data.getDescriptionTemplateId()).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).isActive(IsActive.Active).first();
if (descriptionTemplateEntity != null) { if (descriptionTemplateEntity != null) {
@ -1358,7 +1386,7 @@ public class DescriptionServiceImpl implements DescriptionService {
} }
} }
} }
}else { } else {
persist.setBooleanValue(importXml.getBooleanValue()); persist.setBooleanValue(importXml.getBooleanValue());
persist.setDateValue(importXml.getDateValue()); persist.setDateValue(importXml.getDateValue());
persist.setTextValue(importXml.getTextValue()); persist.setTextValue(importXml.getTextValue());

View File

@ -396,13 +396,15 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
if (FieldType.UPLOAD.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("Upload not supported"); if (FieldType.UPLOAD.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("Upload not supported");
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("dmps not supported"); if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("dmps not supported");
if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("descriptions not supported"); if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("descriptions not supported");
if (FieldType.TAGS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("tags not supported");
data.setTextValue(persist.getTextValue()); data.setTextValue(persist.getTextValue());
} }
else if (FieldType.isReferenceType(fieldType) ) { else if (FieldType.isReferenceType(fieldType) ) {
throw new NotImplementedException("reference not supported"); throw new NotImplementedException("reference not supported");
} }
else if (FieldType.isTagType(fieldType) ) {
throw new NotImplementedException("tags not supported");
}
else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue()); else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue());
else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue()); else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue());
else if (FieldType.isExternalIdentifierType(fieldType)) throw new NotImplementedException("ExternalIdentifier not supported"); else if (FieldType.isExternalIdentifierType(fieldType)) throw new NotImplementedException("ExternalIdentifier not supported");
@ -419,13 +421,15 @@ public class DescriptionTemplateServiceImpl implements DescriptionTemplateServic
if (FieldType.UPLOAD.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("Upload not supported"); if (FieldType.UPLOAD.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("Upload not supported");
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("dmps not supported"); if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("dmps not supported");
if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("descriptions not supported"); if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("descriptions not supported");
if (FieldType.TAGS.equals(fieldType) && !this.conventionService.isNullOrEmpty(persist.getTextValue())) throw new NotImplementedException("tags not supported");
data.setTextValue(persist.getTextValue()); data.setTextValue(persist.getTextValue());
} }
else if (FieldType.isReferenceType(fieldType) ) { else if (FieldType.isReferenceType(fieldType) ) {
throw new NotImplementedException("reference not supported"); throw new NotImplementedException("reference not supported");
} }
else if (FieldType.isTagType(fieldType) ) {
throw new NotImplementedException("tags not supported");
}
else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue()); else if (FieldType.isDateType(fieldType)) data.setDateValue(persist.getDateValue());
else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue()); else if (FieldType.isBooleanType(fieldType)) data.setBooleanValue(persist.getBooleanValue());
else if (FieldType.isExternalIdentifierType(fieldType)){ else if (FieldType.isExternalIdentifierType(fieldType)){

View File

@ -32,6 +32,7 @@ import org.opencdmp.commons.types.prefillingsource.PrefillingSourceDefinitionFix
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionTemplateEntity; import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.PrefillingSourceEntity; import org.opencdmp.data.PrefillingSourceEntity;
import org.opencdmp.data.TagEntity;
import org.opencdmp.data.TenantEntityManager; import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.errorcode.ErrorThesaurusProperties; import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.DescriptionTag; import org.opencdmp.model.DescriptionTag;
@ -57,6 +58,7 @@ import org.opencdmp.model.reference.Definition;
import org.opencdmp.model.reference.Reference; import org.opencdmp.model.reference.Reference;
import org.opencdmp.model.referencetype.ReferenceType; import org.opencdmp.model.referencetype.ReferenceType;
import org.opencdmp.query.PrefillingSourceQuery; import org.opencdmp.query.PrefillingSourceQuery;
import org.opencdmp.query.TagQuery;
import org.opencdmp.query.lookup.ReferenceSearchLookup; import org.opencdmp.query.lookup.ReferenceSearchLookup;
import org.opencdmp.service.externalfetcher.ExternalFetcherService; import org.opencdmp.service.externalfetcher.ExternalFetcherService;
import org.opencdmp.service.externalfetcher.criteria.ExternalReferenceCriteria; import org.opencdmp.service.externalfetcher.criteria.ExternalReferenceCriteria;
@ -542,7 +544,24 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService {
} }
case TAGS -> { case TAGS -> {
String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value); String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value);
field.setTextListValue(valuesParsed == null ? List.of(value) : Arrays.stream(valuesParsed).toList()); //TODO Tags, Currency is ids List<String> finalValue = valuesParsed == null ? List.of(value) : Arrays.stream(valuesParsed).toList();
List<TagEntity> existingTags = this.queryFactory.query(TagQuery.class).isActive(IsActive.Active).tags(finalValue).disableTracking().authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermissionOrPublic).collect();
List<Tag> tags = new ArrayList<>();
for (String like : finalValue) {
Tag tag = new Tag();
tag.setLabel(like);
TagEntity existingTag = existingTags.stream().filter(x-> like.equalsIgnoreCase(x.getLabel())).findFirst().orElse(null);
if (existingTag != null) {
tag.setId(existingTag.getId());
tag.setCreatedAt(existingTag.getCreatedAt());
tag.setIsActive(IsActive.Active);
tag.setUpdatedAt(existingTag.getUpdatedAt());
tag.setHash(this.conventionService.hashValue(existingTag.getUpdatedAt()));
}
tags.add(tag);
}
field.setTags(tags);
} }
case REFERENCE_TYPES -> { case REFERENCE_TYPES -> {
String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value); String[] valuesParsed = this.tryParseJsonAsObjectString(String[].class, value);
@ -551,7 +570,7 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService {
ReferenceTypeDataEntity selectDataEntity = (ReferenceTypeDataEntity) fieldEntity.getData(); ReferenceTypeDataEntity selectDataEntity = (ReferenceTypeDataEntity) fieldEntity.getData();
if (selectDataEntity == null) throw new MyApplicationException("Can not cast fieldEntity data"); if (selectDataEntity == null) throw new MyApplicationException("Can not cast fieldEntity data");
field.setReferences(new ArrayList<>()); field.setReferences(new ArrayList<>());
for (String like : finalValue){ for (String like : finalValue) {
ReferenceSearchLookup externalReferenceCriteria = new ReferenceSearchLookup(); ReferenceSearchLookup externalReferenceCriteria = new ReferenceSearchLookup();
externalReferenceCriteria.setLike(like); externalReferenceCriteria.setLike(like);
externalReferenceCriteria.setTypeId(selectDataEntity.getReferenceTypeId()); externalReferenceCriteria.setTypeId(selectDataEntity.getReferenceTypeId());
@ -575,7 +594,7 @@ public class PrefillingSourceServiceImpl implements PrefillingSourceService {
); );
List<Reference> references = this.referenceService.searchReferenceData(externalReferenceCriteria); List<Reference> references = this.referenceService.searchReferenceData(externalReferenceCriteria);
for (Reference reference : references){ for (Reference reference : references) {
if (reference.getReference().equals(like) || reference.getLabel().toUpperCase(Locale.ROOT).contains(like.toUpperCase(Locale.ROOT))) { if (reference.getReference().equals(like) || reference.getLabel().toUpperCase(Locale.ROOT).contains(like.toUpperCase(Locale.ROOT))) {
field.getReferences().add(reference); field.getReferences().add(reference);
DescriptionReference descriptionReference = new DescriptionReference(); DescriptionReference descriptionReference = new DescriptionReference();

View File

@ -55,6 +55,9 @@ public class Field {
} }
if (persist.getReferences() != null && !persist.getReferences().isEmpty()){ if (persist.getReferences() != null && !persist.getReferences().isEmpty()){
tempTextListValue = persist.getReferences().stream().filter(x-> x.getId() != null).map(x-> x.getId().toString()).toList(); tempTextListValue = persist.getReferences().stream().filter(x-> x.getId() != null).map(x-> x.getId().toString()).toList();
}
if (persist.getTags() != null && !persist.getTags().isEmpty()){
tempTextListValue = persist.getTags();
} }
this.textListValue = tempTextListValue; this.textListValue = tempTextListValue;
} }

View File

@ -422,13 +422,15 @@ public class VisibilityServiceImpl implements VisibilityService {
else if (rule.getTextValue() != null &&org.opencdmp.commons.enums.FieldType.isTextListType(fieldType) && field.getTextListValue() != null && !field.getTextListValue().isEmpty()) { else if (rule.getTextValue() != null &&org.opencdmp.commons.enums.FieldType.isTextListType(fieldType) && field.getTextListValue() != null && !field.getTextListValue().isEmpty()) {
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType)) throw new NotImplementedException("dmps not supported"); if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType)) throw new NotImplementedException("dmps not supported");
if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType)) throw new NotImplementedException("descriptions not supported"); if (FieldType.INTERNAL_ENTRIES_DESCRIPTIONS.equals(fieldType)) throw new NotImplementedException("descriptions not supported");
if (FieldType.TAGS.equals(fieldType)) throw new NotImplementedException("tags not supported");
return new HashSet<>(field.getTextListValue()).contains(rule.getTextValue()); return new HashSet<>(field.getTextListValue()).contains(rule.getTextValue());
} }
else if (org.opencdmp.commons.enums.FieldType.isReferenceType(fieldType)) { else if (org.opencdmp.commons.enums.FieldType.isReferenceType(fieldType)) {
throw new NotImplementedException("Reference rule not supported"); throw new NotImplementedException("Reference rule not supported");
} }
else if (org.opencdmp.commons.enums.FieldType.isTagType(fieldType)) {
throw new NotImplementedException("tags not supported");
}
else if (org.opencdmp.commons.enums.FieldType.isDateType(fieldType) && field.getDateValue() != null) return field.getDateValue().equals(rule.getDateValue()); else if (org.opencdmp.commons.enums.FieldType.isDateType(fieldType) && field.getDateValue() != null) return field.getDateValue().equals(rule.getDateValue());
else if (org.opencdmp.commons.enums.FieldType.isBooleanType(fieldType) && field.getBooleanValue() != null) return field.getBooleanValue().equals(rule.getBooleanValue()); else if (org.opencdmp.commons.enums.FieldType.isBooleanType(fieldType) && field.getBooleanValue() != null) return field.getBooleanValue().equals(rule.getBooleanValue());
else if (org.opencdmp.commons.enums.FieldType.isExternalIdentifierType(fieldType) && field.getExternalIdentifier() != null) { else if (org.opencdmp.commons.enums.FieldType.isExternalIdentifierType(fieldType) && field.getExternalIdentifier() != null) {

View File

@ -4,7 +4,7 @@ import { Guid } from "@common/types/guid";
import { DescriptionTemplate } from "../description-template/description-template"; import { DescriptionTemplate } from "../description-template/description-template";
import { Dmp, DmpDescriptionTemplate, PublicDmp } from "../dmp/dmp"; import { Dmp, DmpDescriptionTemplate, PublicDmp } from "../dmp/dmp";
import { Reference, ReferencePersist } from "../reference/reference"; import { Reference, ReferencePersist } from "../reference/reference";
import { Tag } from "../tag/tag"; import { Tag, TagPersist } from "../tag/tag";
import { User } from "../user/user"; import { User } from "../user/user";
import { AppPermission } from "@app/core/common/enum/permission.enum"; import { AppPermission } from "@app/core/common/enum/permission.enum";
@ -45,6 +45,7 @@ export interface DescriptionField {
booleanValue: boolean; booleanValue: boolean;
externalIdentifier?: DescriptionExternalIdentifier; externalIdentifier?: DescriptionExternalIdentifier;
references: Reference[]; references: Reference[];
tags: Tag[];
} }
export interface DescriptionExternalIdentifier { export interface DescriptionExternalIdentifier {
@ -103,6 +104,7 @@ export interface DescriptionFieldPersist {
references: ReferencePersist[]; references: ReferencePersist[];
reference: ReferencePersist; reference: ReferencePersist;
externalIdentifier?: DescriptionExternalIdentifierPersist; externalIdentifier?: DescriptionExternalIdentifierPersist;
tags: string[];
} }
export interface DescriptionExternalIdentifierPersist { export interface DescriptionExternalIdentifierPersist {

View File

@ -4,7 +4,6 @@ import { DescriptionTemplateFieldType } from "../common/enum/description-templat
import { DescriptionTemplateField, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateRadioBoxData, DescriptionTemplateReferenceTypeData, DescriptionTemplateSelectData } from "../model/description-template/description-template"; import { DescriptionTemplateField, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateRadioBoxData, DescriptionTemplateReferenceTypeData, DescriptionTemplateSelectData } from "../model/description-template/description-template";
import { DescriptionFieldPersist } from "../model/description/description"; import { DescriptionFieldPersist } from "../model/description/description";
import { Observable, map, of } from "rxjs"; import { Observable, map, of } from "rxjs";
import { TagService } from "../services/tag/tag.service";
import { Guid } from "@common/types/guid"; import { Guid } from "@common/types/guid";
import { DmpService } from "../services/dmp/dmp.service"; import { DmpService } from "../services/dmp/dmp.service";
import { DescriptionService } from "../services/description/description.service"; import { DescriptionService } from "../services/description/description.service";
@ -19,7 +18,6 @@ import { TranslateService } from "@ngx-translate/core";
export class FieldValuePipe implements PipeTransform { export class FieldValuePipe implements PipeTransform {
constructor(private date: DatePipe, constructor(private date: DatePipe,
private tagService: TagService,
private dmpService: DmpService, private dmpService: DmpService,
private storageFileService: StorageFileService, private storageFileService: StorageFileService,
private descriptionService: DescriptionService, private descriptionService: DescriptionService,
@ -70,8 +68,8 @@ export class FieldValuePipe implements PipeTransform {
break; break;
} }
case DescriptionTemplateFieldType.TAGS: { case DescriptionTemplateFieldType.TAGS: {
if (controlValue.textListValue && controlValue.textListValue.length > 0) { if (controlValue.tags) {
return this.tagService.query(this.tagService.buildAutocompleteLookup(null, null, controlValue.textListValue.map(x => Guid.parse(x)))).pipe(map(x => x.items?.map(y=> y.label).join(','))); return of(controlValue.tags.join(','));
} }
break; break;
} }

View File

@ -74,8 +74,8 @@ export class TagService {
initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)), initialItems: (excludedItems: any[], data?: any) => this.query(this.buildAutocompleteLookup(null, excludedItems ? excludedItems : null)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)), filterFn: (searchQuery: string, excludedItems: any[]) => this.query(this.buildAutocompleteLookup(searchQuery, excludedItems)).pipe(map(x => x.items)),
getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)), getSelectedItems: (selectedItems: any[]) => this.query(this.buildAutocompleteLookup(null, null, selectedItems)).pipe(map(x => x.items)),
displayFn: (item: Tag) => item.label, displayFn: (item: Tag) => JSON.stringify(item),
titleFn: (item: Tag) => item.label, titleFn: (item: Tag) => JSON.stringify(item),
valueAssign: (item: Tag) => item.id, valueAssign: (item: Tag) => item.id,
}; };

View File

@ -46,7 +46,7 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
} }
isTextListType(type: DescriptionTemplateFieldType){ isTextListType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.TAGS || type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS || return type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DMPS ||
type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS || type == DescriptionTemplateFieldType.SELECT; type == DescriptionTemplateFieldType.INTERNAL_ENTRIES_DESCRIPTIONS || type == DescriptionTemplateFieldType.SELECT;
} }
@ -62,6 +62,10 @@ export class DescriptionTemplateEditorRuleComponent implements OnInit {
return type == DescriptionTemplateFieldType.REFERENCE_TYPES; return type == DescriptionTemplateFieldType.REFERENCE_TYPES;
} }
isTagType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.TAGS;
}
isExternalIdentifierType(type: DescriptionTemplateFieldType){ isExternalIdentifierType(type: DescriptionTemplateFieldType){
return type == DescriptionTemplateFieldType.VALIDATION || type == DescriptionTemplateFieldType.DATASET_IDENTIFIER;; return type == DescriptionTemplateFieldType.VALIDATION || type == DescriptionTemplateFieldType.DATASET_IDENTIFIER;;
} }

View File

@ -38,7 +38,7 @@
<div class="col-12"> <div class="col-12">
<div class="heading">{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS' | translate}}</div> <div class="heading">{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS' | translate}}</div>
<div class="profile-form"> <div class="profile-form">
<app-tags-field-component [form]="formGroup.get('tags')"></app-tags-field-component> <app-tags-field-component label="{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS' | translate}}" placeholder="{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS-PLACEHOLDER' | translate}}" [form]="formGroup.get('tags')"></app-tags-field-component>
</div> </div>
</div> </div>
</div> </div>

View File

@ -225,7 +225,8 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp
dateValue: definitionField.defaultValue ? definitionField.defaultValue.dateValue : undefined, dateValue: definitionField.defaultValue ? definitionField.defaultValue.dateValue : undefined,
booleanValue: definitionField.defaultValue ? definitionField.defaultValue.booleanValue : undefined, booleanValue: definitionField.defaultValue ? definitionField.defaultValue.booleanValue : undefined,
externalIdentifier: undefined, externalIdentifier: undefined,
references: undefined references: undefined,
tags: undefined
}); });
}) })
fieldSetValue.items = [{ fieldSetValue.items = [{
@ -247,7 +248,8 @@ export class DescriptionPropertyDefinitionEditorModel implements DescriptionProp
dateValue: undefined, dateValue: undefined,
booleanValue: undefined, booleanValue: undefined,
externalIdentifier: undefined, externalIdentifier: undefined,
references: undefined references: undefined,
tags: undefined
}; };
} }
} }
@ -437,6 +439,7 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist {
booleanValue: boolean; booleanValue: boolean;
references: ReferencePersist[] = []; references: ReferencePersist[] = [];
reference: ReferencePersist; reference: ReferencePersist;
tags: string[] = [];
externalIdentifier?: DescriptionExternalIdentifierEditorModel = new DescriptionExternalIdentifierEditorModel(this.validationErrorModel); externalIdentifier?: DescriptionExternalIdentifierEditorModel = new DescriptionExternalIdentifierEditorModel(this.validationErrorModel);
protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); protected formBuilder: UntypedFormBuilder = new UntypedFormBuilder();
@ -451,6 +454,7 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist {
this.textListValue = item.textListValue; this.textListValue = item.textListValue;
this.dateValue = item.dateValue; this.dateValue = item.dateValue;
this.booleanValue = item.booleanValue; this.booleanValue = item.booleanValue;
this.tags = item.tags?.map(x => x.label);
const references = descriptionReferences?.filter(x => x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active).map(x => { const references = descriptionReferences?.filter(x => x.data?.fieldId == descriptionTemplateField?.id && x.isActive == IsActive.Active).map(x => {
return { return {
@ -501,6 +505,7 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist {
booleanValue: [{ value: this.booleanValue, disabled: disabled }, context.getValidation('booleanValue').validators], booleanValue: [{ value: this.booleanValue, disabled: disabled }, context.getValidation('booleanValue').validators],
references: [{ value: this.references, disabled: disabled }, context.getValidation('references').validators], references: [{ value: this.references, disabled: disabled }, context.getValidation('references').validators],
reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators],
tags: [{ value: this.tags, disabled: disabled }, context.getValidation('tags').validators],
externalIdentifier: this.externalIdentifier.buildForm({ externalIdentifier: this.externalIdentifier.buildForm({
rootPath: `${rootPath}externalIdentifier.` rootPath: `${rootPath}externalIdentifier.`
}), }),
@ -521,6 +526,7 @@ export class DescriptionFieldEditorModel implements DescriptionFieldPersist {
baseValidationArray.push({ key: 'booleanValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}booleanValue`)] }); baseValidationArray.push({ key: 'booleanValue', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}booleanValue`)] });
baseValidationArray.push({ key: 'references', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); baseValidationArray.push({ key: 'references', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] });
baseValidationArray.push({ key: 'reference', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] }); baseValidationArray.push({ key: 'reference', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}references`)] });
baseValidationArray.push({ key: 'tags', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}tags`)] });
baseValidationArray.push({ key: 'externalIdentifier', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}externalIdentifier`)] }); baseValidationArray.push({ key: 'externalIdentifier', validators: [BackendErrorValidator(validationErrorModel, `${rootPath}externalIdentifier`)] });
baseContext.validation = baseValidationArray; baseContext.validation = baseValidationArray;
return baseContext; return baseContext;
@ -748,7 +754,7 @@ export class DescriptionFieldIndicator {
else this.type = "textValue"; else this.type = "textValue";
break; break;
case DescriptionTemplateFieldType.TAGS: case DescriptionTemplateFieldType.TAGS:
this.type = "textListValue"; this.type = "tags";
break; break;
} }
} }

View File

@ -75,6 +75,10 @@ export class DescriptionEditorResolver extends BaseEditorResolver {
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.type), nameof<ReferenceType>(x => x.id)].join('.'), [nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.type), nameof<ReferenceType>(x => x.id)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.reference)].join('.'), [nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.reference)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.isActive)].join('.'), [nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.references), nameof<Reference>(x => x.isActive)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.tags), nameof<Tag>(x => x.id)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.tags), nameof<Tag>(x => x.label)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.tags), nameof<Tag>(x => x.isActive)].join('.'),
[nameof<Description>(x => x.properties), nameof<DescriptionPropertyDefinition>(x => x.fieldSets), nameof<DescriptionPropertyDefinitionFieldSet>(x => x.items), nameof<DescriptionPropertyDefinitionFieldSetItem>(x => x.fields), nameof<DescriptionField>(x => x.tags), nameof<Tag>(x => x.hash)].join('.'),
[nameof<Description>(x => x.descriptionTags), nameof<DescriptionTag>(x => x.id),].join('.'), [nameof<Description>(x => x.descriptionTags), nameof<DescriptionTag>(x => x.id),].join('.'),
[nameof<Description>(x => x.descriptionTags), nameof<DescriptionTag>(x => x.tag), nameof<Tag>(x => x.label)].join('.'), [nameof<Description>(x => x.descriptionTags), nameof<DescriptionTag>(x => x.tag), nameof<Tag>(x => x.label)].join('.'),

View File

@ -164,13 +164,7 @@
</mat-form-field> </mat-form-field>
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.TAGS" class="col-12"> <div *ngSwitchCase="descriptionTemplateFieldTypeEnum.TAGS" class="col-12">
<div class="row"> <app-tags-field-component [label]="field.data.label" [placeholder]="(field.data.label | translate) + (isRequired? ' *': '')" [form]="propertiesFormGroup?.get(field.id).get('tags')"></app-tags-field-component>
<mat-form-field class="col-md-12">
<mat-label>{{ field.data.label }}</mat-label>
<app-multiple-auto-complete [configuration]="tagService.multipleAutocompleteConfiguration" [formControl]="propertiesFormGroup?.get(field.id).get('textListValue')" placeholder="{{ (field.data.label | translate) + (isRequired? ' *': '') }}"></app-multiple-auto-complete>
<mat-error *ngIf="propertiesFormGroup?.get(field.id).get('textListValue').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div> </div>
<div *ngSwitchCase="descriptionTemplateFieldTypeEnum.DATASET_IDENTIFIER" class="col-12"> <div *ngSwitchCase="descriptionTemplateFieldTypeEnum.DATASET_IDENTIFIER" class="col-12">

View File

@ -1,12 +1,10 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, SimpleChanges } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit, SimpleChanges } from '@angular/core';
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { MatDialog } from "@angular/material/dialog"; import { MatDialog } from "@angular/material/dialog";
import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type'; import { DescriptionTemplateFieldType } from '@app/core/common/enum/description-template-field-type';
import { DescriptionTemplateFieldValidationType } from '@app/core/common/enum/description-template-field-validation-type'; import { DescriptionTemplateFieldValidationType } from '@app/core/common/enum/description-template-field-validation-type';
import { ValidatorURL } from '@app/core/common/enum/validation-type';
import { DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateUploadData } from '@app/core/model/description-template/description-template'; import { DescriptionTemplateField, DescriptionTemplateFieldSet, DescriptionTemplateLabelAndMultiplicityData, DescriptionTemplateUploadData } from '@app/core/model/description-template/description-template';
import { StorageFile } from '@app/core/model/storage-file/storage-file'; import { StorageFile } from '@app/core/model/storage-file/storage-file';
import { DescriptionService } from '@app/core/services/description/description.service'; import { DescriptionService } from '@app/core/services/description/description.service';
@ -24,8 +22,7 @@ import { FormValidationErrorsDialogComponent } from '@common/forms/form-validati
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 * as FileSaver from 'file-saver'; import * as FileSaver from 'file-saver';
import { Observable } from 'rxjs'; import { distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { distinctUntilChanged, map, takeUntil } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof'; import { nameof } from 'ts-simple-nameof';
@Component({ @Component({

View File

@ -14,6 +14,7 @@ import { DescriptionFormFieldComponent } from './components/form-field/form-fiel
import { DescriptionFormSectionComponent } from './components/form-section/form-section.component'; import { DescriptionFormSectionComponent } from './components/form-section/form-section.component';
import { DescriptionFormComponent } from './description-form.component'; import { DescriptionFormComponent } from './description-form.component';
import { DescriptionFormAnnotationService } from './description-form-annotation.service'; import { DescriptionFormAnnotationService } from './description-form-annotation.service';
import { TagsFieldModule } from '@app/ui/tag/tags-field/tags-field.module';
@NgModule({ @NgModule({
@ -25,7 +26,8 @@ import { DescriptionFormAnnotationService } from './description-form-annotation.
NgxDropzoneModule, NgxDropzoneModule,
FormattingModule, FormattingModule,
ReferenceFieldModule, ReferenceFieldModule,
AnnotationDialogModule AnnotationDialogModule,
TagsFieldModule
], ],
declarations: [ declarations: [
DescriptionFormComponent, DescriptionFormComponent,

View File

@ -19,7 +19,7 @@ export class FormProgressIndicationComponent extends BaseComponent implements On
progressSoFar: number; progressSoFar: number;
total: number; total: number;
percent: number; percent: number;
fieldTypes: string[] = ['dateValue', 'booleanValue', 'externalIdentifier.identifier', 'externalIdentifier.type', 'reference', 'references', 'textListValue', 'textValue']; fieldTypes: string[] = ['dateValue', 'booleanValue', 'externalIdentifier.identifier', 'externalIdentifier.type', 'reference', 'references' , 'tags', 'textListValue', 'textValue'];
constructor(private visibilityRulesService: VisibilityRulesService) { super(); } constructor(private visibilityRulesService: VisibilityRulesService) { super(); }

View File

@ -1,5 +1,5 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { UntypedFormArray, UntypedFormGroup } from '@angular/forms'; import { UntypedFormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { ReferenceType } from '@app/core/model/reference-type/reference-type'; import { ReferenceType } from '@app/core/model/reference-type/reference-type';
import { ReferenceService } from '@app/core/services/reference/reference.service'; import { ReferenceService } from '@app/core/services/reference/reference.service';
@ -10,9 +10,7 @@ import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { ReferenceDialogEditorComponent } from './editor/reference-dialog-editor.component'; import { ReferenceDialogEditorComponent } from './editor/reference-dialog-editor.component';
import { Reference, ReferencePersist } from '@app/core/model/reference/reference'; import { Reference, ReferencePersist } from '@app/core/model/reference/reference';
import { ReferenceSearchLookup } from '@app/core/query/reference-search.lookup';
import { Guid } from '@common/types/guid'; import { Guid } from '@common/types/guid';
import { nameof } from 'ts-simple-nameof';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { FormService } from '@common/forms/form-service'; import { FormService } from '@common/forms/form-service';

View File

@ -1,5 +1,5 @@
<mat-form-field class="w-100"> <mat-form-field class="w-100">
<mat-label>{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS' | translate}}</mat-label> <mat-label>{{label}}</mat-label>
<mat-chip-grid #chipGrid [disabled]="form.disabled"> <mat-chip-grid #chipGrid [disabled]="form.disabled">
<mat-chip-row *ngFor="let tag of tags" (removed)="remove(tag)"> <mat-chip-row *ngFor="let tag of tags" (removed)="remove(tag)">
{{tag}} {{tag}}
@ -8,10 +8,13 @@
</button> </button>
</mat-chip-row> </mat-chip-row>
</mat-chip-grid> </mat-chip-grid>
<input placeholder="{{'DESCRIPTION-EDITOR.BASE-INFO.FIELDS.TAGS-PLACEHOLDER' | translate}}" #tagInput [formControl]="form" [matChipInputFor]="chipGrid" [matAutocomplete]="auto" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" (matChipInputTokenEnd)="add($event)" [readOnly]="form.disabled"/> <input placeholder="{{placeholder}}" #tagInput [formControl]="tagsCtrl" [matChipInputFor]="chipGrid" [matAutocomplete]="auto" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" (matChipInputTokenEnd)="add($event)" [readOnly]="form.disabled"/>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)"> <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let tag of filteredTags | async" [value]="tag"> <mat-option *ngFor="let tag of filteredTags | async" [value]="tag">
{{tag}} {{tag}}
</mat-option> </mat-option>
</mat-autocomplete> </mat-autocomplete>
<mat-error *ngIf="form.hasError('backendError')">{{ form.getError('backendError')?.message}}</mat-error>
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>

View File

@ -1,6 +1,6 @@
import { COMMA, ENTER } from '@angular/cdk/keycodes'; import { COMMA, ENTER } from '@angular/cdk/keycodes';
import { Component, ElementRef, Input, OnInit, SimpleChanges, ViewChild } from '@angular/core'; import { Component, ElementRef, Input, OnInit, SimpleChanges, ViewChild } from '@angular/core';
import { UntypedFormControl } from '@angular/forms'; import { FormControl, UntypedFormBuilder, UntypedFormControl } from '@angular/forms';
import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
import { MatChipInputEvent } from '@angular/material/chips'; import { MatChipInputEvent } from '@angular/material/chips';
import { Tag } from '@app/core/model/tag/tag'; import { Tag } from '@app/core/model/tag/tag';
@ -18,6 +18,8 @@ import { map, mergeMap, startWith } from 'rxjs/operators';
export class TagsComponent extends BaseComponent implements OnInit { export class TagsComponent extends BaseComponent implements OnInit {
@Input() form: UntypedFormControl = null; @Input() form: UntypedFormControl = null;
@Input() label: string;
@Input() placeholder: string;
separatorKeysCodes: number[] = [ENTER, COMMA]; separatorKeysCodes: number[] = [ENTER, COMMA];
filteredTags: Observable<string[]>; filteredTags: Observable<string[]>;
@ -25,6 +27,8 @@ export class TagsComponent extends BaseComponent implements OnInit {
@ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement>; @ViewChild('tagInput') tagInput: ElementRef<HTMLInputElement>;
tagsCtrl = new FormControl();
constructor( constructor(
private tagService: TagService private tagService: TagService
) { ) {
@ -40,7 +44,7 @@ export class TagsComponent extends BaseComponent implements OnInit {
applyTags(){ applyTags(){
this.tags = this.form.value || []; this.tags = this.form.value || [];
this.filteredTags = this.form.valueChanges.pipe( this.filteredTags = this.tagsCtrl.valueChanges.pipe(
startWith(null), startWith(null),
mergeMap((tag: string | null) => (this.tagService.query(this.tagService.buildAutocompleteLookup(tag)))), mergeMap((tag: string | null) => (this.tagService.query(this.tagService.buildAutocompleteLookup(tag)))),
map((queryResult: QueryResult<Tag>) => queryResult.items.map(x => x.label)), map((queryResult: QueryResult<Tag>) => queryResult.items.map(x => x.label)),