Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring

# Conflicts:
#	dmp-backend/core/src/main/java/eu/eudat/audit/AuditableAction.java
This commit is contained in:
Efstratios Giannopoulos 2024-03-11 15:03:04 +02:00
commit 097d2832be
33 changed files with 408 additions and 98 deletions

View File

@ -41,6 +41,7 @@ public class AuditableAction {
public static final EventId Dmp_Invite_Accept = new EventId(5009, "Dmp_Invite_Accept");
public static final EventId Dmp_PublicQuery = new EventId(5010, "Dmp_PublicQuery");
public static final EventId Dmp_Export = new EventId(5011, "Dmp_Export");
public static final EventId Dmp_PublicLookup = new EventId(5012, "Dmp_PublicLookup");
public static final EventId Description_Query = new EventId(6000, "Description_Query");
public static final EventId Description_Lookup = new EventId(6001, "Description_Lookup");

View File

@ -43,6 +43,10 @@ public class PublicDescription {
public static final String _descriptionTemplate = "descriptionTemplate";
private PublicDmp dmp;
public static final String _dmp = "dmp";
public UUID getId() {
return id;
@ -116,4 +120,12 @@ public class PublicDescription {
public void setDescriptionTemplate(PublicDescriptionTemplate descriptionTemplate) {
this.descriptionTemplate = descriptionTemplate;
}
public PublicDmp getDmp() {
return dmp;
}
public void setDmp(PublicDmp dmp) {
this.dmp = dmp;
}
}

View File

@ -26,6 +26,9 @@ public class PublicDmp {
public static final String _description = "description";
private Instant updatedAt;
public static final String _updatedAt = "updatedAt";
private Instant finalizedAt;
public static final String _finalizedAt = "finalizedAt";
@ -36,11 +39,14 @@ public class PublicDmp {
private List<PublicDmpUser> users;
public static final String _users = "users";
public static final String _dmpUsers = "dmpUsers";
private List<PublicDmpReference> dmpReferences;
public static final String _dmpReferences = "_dmpReferences";
public static final String _dmpReferences = "dmpReferences";
private List<PublicDescription> descriptions;
public static final String _descriptions = "descriptions";
public UUID getId() {
return id;
@ -74,6 +80,14 @@ public class PublicDmp {
this.description = description;
}
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
public Instant getFinalizedAt() {
return finalizedAt;
}
@ -105,4 +119,12 @@ public class PublicDmp {
public void setDmpReferences(List<PublicDmpReference> dmpReferences) {
this.dmpReferences = dmpReferences;
}
public List<PublicDescription> getDescriptions() {
return descriptions;
}
public void setDescriptions(List<PublicDescription> descriptions) {
this.descriptions = descriptions;
}
}

View File

@ -67,6 +67,7 @@ public class DmpUserBuilder extends BaseBuilder<DmpUser, DmpUserEntity>{
if (fields.hasField(this.asIndexer(DmpUser._sectionId))) m.setSectionId(d.getSectionId());
if (fields.hasField(this.asIndexer(DmpUser._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(DmpUser._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(DmpUser._isActive))) m.setIsActive(d.getIsActive());
if (fields.hasField(this.asIndexer(DmpReference._hash))) m.setHash(this.hashValue(d.getUpdatedAt()));
if (!userFields.isEmpty() && userItemsMap != null && userItemsMap.containsKey(d.getUserId())) m.setUser(userItemsMap.get(d.getUserId()));
if (!dmpFields.isEmpty() && dmpItemsMap != null && dmpItemsMap.containsKey(d.getDmpId())) m.setDmp(dmpItemsMap.get(d.getDmpId()));

View File

@ -6,6 +6,7 @@ import eu.eudat.data.DescriptionEntity;
import eu.eudat.model.*;
import eu.eudat.query.DescriptionTemplateQuery;
import eu.eudat.query.DmpDescriptionTemplateQuery;
import eu.eudat.query.DmpQuery;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
@ -56,9 +57,12 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
FieldSet dmpDescriptionTemplateFields = fields.extractPrefixed(this.asPrefix(PublicDescription._dmpDescriptionTemplate));
Map<UUID, PublicDmpDescriptionTemplate> dmpDescriptionTemplateItemsMap = this.collectDmpDescriptionTemplates(dmpDescriptionTemplateFields, data);
FieldSet descriptionTemplateFields = fields.extractPrefixed(this.asPrefix(Description._descriptionTemplate));
FieldSet descriptionTemplateFields = fields.extractPrefixed(this.asPrefix(PublicDescription._descriptionTemplate));
Map<UUID, PublicDescriptionTemplate> descriptionTemplateItemsMap = this.collectDescriptionTemplates(descriptionTemplateFields, data);
FieldSet dmpFields = fields.extractPrefixed(this.asPrefix(PublicDescription._dmp));
Map<UUID, PublicDmp> dmpItemsMap = this.collectDmps(dmpFields, data);
List<PublicDescription> models = new ArrayList<>();
for (DescriptionEntity d : data) {
PublicDescription m = new PublicDescription();
@ -69,6 +73,7 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
if (fields.hasField(this.asIndexer(PublicDescription._createdAt))) m.setCreatedAt(d.getCreatedAt());
if (fields.hasField(this.asIndexer(PublicDescription._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (fields.hasField(this.asIndexer(PublicDescription._finalizedAt))) m.setFinalizedAt(d.getFinalizedAt());
if (!dmpFields.isEmpty() && dmpItemsMap != null && dmpItemsMap.containsKey(d.getDmpId())) m.setDmp(dmpItemsMap.get(d.getDmpId()));
if (!dmpDescriptionTemplateFields.isEmpty() && dmpDescriptionTemplateItemsMap != null && dmpDescriptionTemplateItemsMap.containsKey(d.getDmpDescriptionTemplateId())) m.setDmpDescriptionTemplate(dmpDescriptionTemplateItemsMap.get(d.getDmpDescriptionTemplateId()));
if (!descriptionTemplateFields.isEmpty() && descriptionTemplateItemsMap != null && descriptionTemplateItemsMap.containsKey(d.getDescriptionTemplateId())) m.setDescriptionTemplate(descriptionTemplateItemsMap.get(d.getDescriptionTemplateId()));
models.add(m);
@ -139,4 +144,34 @@ public class PublicDescriptionBuilder extends BaseBuilder<PublicDescription, Des
return itemMap;
}
private Map<UUID, PublicDmp> collectDmps(FieldSet fields, List<DescriptionEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty())
return null;
this.logger.debug("checking related - {}", PublicDmp.class.getSimpleName());
Map<UUID, PublicDmp> itemMap;
if (!fields.hasOtherField(this.asIndexer(PublicDmp._id))) {
itemMap = this.asEmpty(
data.stream().map(DescriptionEntity::getDmpId).distinct().collect(Collectors.toList()),
x -> {
PublicDmp item = new PublicDmp();
item.setId(x);
return item;
},
PublicDmp::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicDmp._id);
DmpQuery q = this.queryFactory.query(DmpQuery.class).authorize(this.authorize).ids(data.stream().map(DescriptionEntity::getDmpId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicDmpBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicDmp::getId);
}
if (!fields.hasField(PublicDmp._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);
});
}
return itemMap;
}
}

View File

@ -1,11 +1,13 @@
package eu.eudat.model.builder;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.DmpEntity;
import eu.eudat.model.PublicDmp;
import eu.eudat.model.PublicDmpReference;
import eu.eudat.model.*;
import eu.eudat.query.DescriptionQuery;
import eu.eudat.query.DmpReferenceQuery;
import eu.eudat.query.DmpUserQuery;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
@ -58,6 +60,12 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
FieldSet dmpReferencesFields = fields.extractPrefixed(this.asPrefix(PublicDmp._dmpReferences));
Map<UUID, List<PublicDmpReference>> dmpReferenceMap = this.collectDmpReferences(dmpReferencesFields, data);
FieldSet dmpUsersFields = fields.extractPrefixed(this.asPrefix(PublicDmp._dmpUsers));
Map<UUID, List<PublicDmpUser>> dmpUsersMap = this.collectDmpUsers(dmpUsersFields, data);
FieldSet descriptionsFields = fields.extractPrefixed(this.asPrefix(PublicDmp._descriptions));
Map<UUID, List<PublicDescription>> descriptionsMap = this.collectDmpDescriptions(descriptionsFields, data);
for (DmpEntity d : data) {
PublicDmp m = new PublicDmp();
if (fields.hasField(this.asIndexer(PublicDmp._id))) m.setId(d.getId());
@ -65,8 +73,11 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
if (fields.hasField(this.asIndexer(PublicDmp._version))) m.setVersion(d.getVersion());
if (fields.hasField(this.asIndexer(PublicDmp._description))) m.setDescription(d.getDescription());
if (fields.hasField(this.asIndexer(PublicDmp._finalizedAt))) m.setFinalizedAt(d.getFinalizedAt());
if (fields.hasField(this.asIndexer(PublicDmp._updatedAt))) m.setUpdatedAt(d.getUpdatedAt());
if (dmpReferenceMap != null && !dmpReferenceMap.isEmpty() && dmpReferenceMap.containsKey(d.getId())) m.setDmpReferences(dmpReferenceMap.get(d.getId()));
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setUsers(dmpUsersMap.get(d.getId()));
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
models.add(m);
}
@ -93,4 +104,40 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
return itemMap;
}
private Map<UUID, List<PublicDmpUser>> collectDmpUsers(FieldSet fields, List<DmpEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", PublicDmpUser.class.getSimpleName());
Map<UUID, List<PublicDmpUser>> itemMap = null;
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(PublicDmpUser._user, PublicDmp._id));
DmpUserQuery query = this.queryFactory.query(DmpUserQuery.class).authorize(this.authorize).dmpIds(data.stream().map(DmpEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicDmpUserBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getDmp().getId());
if (!fields.hasField(this.asIndexer(PublicDmpUser._dmp, PublicDmp._id))) {
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null && x.getDmp() != null).peek(x -> {
x.getDmp().setId(null);
});
}
return itemMap;
}
private Map<UUID, List<PublicDescription>> collectDmpDescriptions(FieldSet fields, List<DmpEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", PublicDescription.class.getSimpleName());
Map<UUID, List<PublicDescription>> itemMap;
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(this.asIndexer(PublicDescription._dmp, PublicDescription._id));
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).authorize(this.authorize).dmpIds(data.stream().map(DmpEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicDescriptionBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getDmp().getId());
if (!fields.hasField(this.asIndexer(PublicDescription._dmp, PublicDescription._id))) {
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null && x.getDmp() != null).peek(x -> {
x.getDmp().setId(null);
});
}
return itemMap;
}
}

View File

@ -81,7 +81,7 @@ public class PublicDmpUserBuilder extends BaseBuilder<PublicDmpUser, DmpUserEnti
this.logger.debug("checking related - {}", User.class.getSimpleName());
Map<UUID, PublicUser> itemMap;
if (!fields.hasOtherField(this.asIndexer(User._id))) {
if (!fields.hasOtherField(this.asIndexer(PublicUser._id))) {
itemMap = this.asEmpty(
data.stream().map(DmpUserEntity::getUserId).distinct().collect(Collectors.toList()),
x -> {
@ -91,11 +91,11 @@ public class PublicDmpUserBuilder extends BaseBuilder<PublicDmpUser, DmpUserEnti
},
PublicUser::getId);
} else {
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(User._id);
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicUser._id);
UserQuery q = this.queryFactory.query(UserQuery.class).authorize(this.authorize).ids(data.stream().map(DmpUserEntity::getUserId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PublicUserBuilder.class).authorize(this.authorize).asForeignKey(q, clone, PublicUser::getId);
}
if (!fields.hasField(User._id)) {
if (!fields.hasField(PublicUser._id)) {
itemMap.forEach((id, item) -> {
if (item != null)
item.setId(null);

View File

@ -45,8 +45,8 @@ public class PublicUserBuilder extends BaseBuilder<PublicUser, UserEntity> {
for (UserEntity d : data) {
PublicUser m = new PublicUser();
if (fields.hasField(this.asIndexer(User._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(User._name))) m.setName(d.getName());
if (fields.hasField(this.asIndexer(PublicUser._id))) m.setId(d.getId());
if (fields.hasField(this.asIndexer(PublicUser._name))) m.setName(d.getName());
models.add(m);
}
this.logger.debug("build {} items", Optional.of(models).map(List::size).orElse(0));

View File

@ -40,7 +40,7 @@ public class PublicDmpCensor extends BaseCensor {
this.authService.authorizeForce(Permission.PublicBrowseDmp);
FieldSet dmpDescriptionsFields = fields.extractPrefixed(this.asIndexerPrefix(PublicDmp._users));
FieldSet dmpDescriptionsFields = fields.extractPrefixed(this.asIndexerPrefix(PublicDmp._dmpUsers));
this.censorFactory.censor(PublicDmpUserCensor.class).censor(dmpDescriptionsFields);
FieldSet dmpReferencesFields = fields.extractPrefixed(this.asIndexerPrefix(PublicDmp._dmpReferences));
this.censorFactory.censor(PublicDmpReferenceCensor.class).censor(dmpReferencesFields);

View File

@ -241,6 +241,7 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
item.setRole(QueryBase.convertSafe(tuple, columns, DmpUserEntity._role, DmpUserRole.class));
item.setCreatedAt(QueryBase.convertSafe(tuple, columns, DmpUserEntity._createdAt, Instant.class));
item.setUpdatedAt(QueryBase.convertSafe(tuple, columns, DmpUserEntity._updatedAt, Instant.class));
item.setIsActive(QueryBase.convertSafe(tuple, columns, DmpUserEntity._isActive, IsActive.class));
return item;
}
@ -253,6 +254,7 @@ public class DmpUserQuery extends QueryBase<DmpUserEntity> {
else if (item.match(DmpUser._sectionId)) return DmpUserEntity._sectionId;
else if (item.match(DmpUser._createdAt)) return DmpUserEntity._createdAt;
else if (item.match(DmpUser._updatedAt)) return DmpUserEntity._updatedAt;
else if (item.match(DmpUser._isActive)) return DmpUserEntity._isActive;
else if (item.match(DmpUser._hash)) return DmpUserEntity._updatedAt;
else return null;
}

View File

@ -213,7 +213,7 @@ public class UserQuery extends QueryBase<UserEntity> {
else throw new MyNotFoundException("Only user scoped allowed");
Subquery<UUID> dmpUserDmpQuery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
new BuildSubQueryInput.Builder<>(DmpUserQuery.class, UUID.class, queryContext)
new BuildSubQueryInput.Builder<>(DmpUserEntity.class, UUID.class, queryContext)
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DmpUserEntity._dmpId))
.filterFunc((subQueryRoot, cb) -> cb.and(
cb.equal(subQueryRoot.get(DmpUserEntity._userId), userId),
@ -222,7 +222,7 @@ public class UserQuery extends QueryBase<UserEntity> {
));
Subquery<UUID> dmpUserUserQuery = queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(
new BuildSubQueryInput.Builder<>(DmpUserQuery.class, UUID.class, queryContext)
new BuildSubQueryInput.Builder<>(DmpUserEntity.class, UUID.class, queryContext)
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(DmpUserEntity._userId))
.filterFunc((subQueryRoot, cb) -> cb.and(
cb.in(subQueryRoot.get(DmpUserEntity._dmpId)).value(dmpUserDmpQuery) ,

View File

@ -482,7 +482,7 @@ public class DmpServiceImpl implements DmpService {
updatedCreatedIds.add(dmpUserEntity.getUserId());
}
List<DmpUserEntity> toDelete = existingUsers.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getId()))).collect(Collectors.toList());
List<DmpUserEntity> toDelete = existingUsers.stream().filter(x-> updatedCreatedIds.stream().noneMatch(y-> y.equals(x.getUserId()))).collect(Collectors.toList());
if (!toDelete.isEmpty()) this.deleterFactory.deleter(DmpUserDeleter.class).delete(toDelete);
this.entityManager.flush();

View File

@ -10,6 +10,7 @@ import eu.eudat.commons.enums.StorageType;
import eu.eudat.convention.ConventionService;
import eu.eudat.data.StorageFileEntity;
import eu.eudat.model.StorageFile;
import eu.eudat.model.builder.PublicDescriptionBuilder;
import eu.eudat.model.persist.DescriptionFieldFilePersist;
import eu.eudat.model.persist.StorageFilePersist;
import eu.eudat.service.storage.StorageFileService;
@ -100,7 +101,7 @@ public class DescriptionController {
@PostMapping("public/query")
public QueryResult<PublicDescription> publicQuery(@RequestBody DescriptionLookup lookup) throws MyApplicationException, MyForbiddenException {
logger.debug("querying {}", Description.class.getSimpleName());
logger.debug("querying {}", PublicDescription.class.getSimpleName());
this.censorFactory.censor(PublicDescriptionCensor.class).censor(lookup.getProject());
@ -113,14 +114,14 @@ public class DescriptionController {
}
@GetMapping("public/{id}")
public Description publicGet(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + Description.class.getSimpleName()).And("id", id).And("fields", fieldSet));
public PublicDescription publicGet(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + PublicDescription.class.getSimpleName()).And("id", id).And("fields", fieldSet));
this.censorFactory.censor(PublicDescriptionCensor.class).censor(fieldSet);
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).authorize(EnumSet.of(Public)).ids(id).dmpSubQuery(this.queryFactory.query(DmpQuery.class).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public));
Description model = this.builderFactory.builder(DescriptionBuilder.class).authorize(EnumSet.of(Public)).build(fieldSet, query.firstAs(fieldSet));
PublicDescription model = this.builderFactory.builder(PublicDescriptionBuilder.class).authorize(EnumSet.of(Public)).build(fieldSet, query.firstAs(fieldSet));
if (model == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Description_PublicLookup, Map.ofEntries(

View File

@ -2,6 +2,14 @@ package eu.eudat.controllers;
import eu.eudat.audit.AuditableAction;
import eu.eudat.authorization.AuthorizationFlags;
import eu.eudat.commons.enums.DmpAccessType;
import eu.eudat.commons.enums.DmpStatus;
import eu.eudat.commons.enums.IsActive;
import eu.eudat.model.builder.DescriptionBuilder;
import eu.eudat.model.builder.PublicDmpBuilder;
import eu.eudat.model.censorship.PublicDescriptionCensor;
import eu.eudat.query.DescriptionQuery;
import eu.eudat.query.DmpDescriptionTemplateQuery;
import gr.cite.tools.validation.ValidationFilterAnnotation;
import eu.eudat.model.*;
import eu.eudat.model.builder.DmpBuilder;
@ -90,6 +98,25 @@ public class DmpController {
return queryResult;
}
@GetMapping("public/{id}")
public PublicDmp publicGet(@PathVariable("id") UUID id, FieldSet fieldSet, Locale locale) throws MyApplicationException, MyForbiddenException, MyNotFoundException {
logger.debug(new MapLogEntry("retrieving" + Dmp.class.getSimpleName()).And("id", id).And("fields", fieldSet));
this.censorFactory.censor(PublicDmpCensor.class).censor(fieldSet);
DmpQuery query = this.queryFactory.query(DmpQuery.class).authorize(EnumSet.of(Public)).ids(id).isActive(IsActive.Active).statuses(DmpStatus.Finalized).accessTypes(DmpAccessType.Public);
PublicDmp model = this.builderFactory.builder(PublicDmpBuilder.class).authorize(EnumSet.of(Public)).build(fieldSet, query.firstAs(fieldSet));
if (model == null) throw new MyNotFoundException(messageSource.getMessage("General_ItemNotFound", new Object[]{id, Dmp.class.getSimpleName()}, LocaleContextHolder.getLocale()));
this.auditService.track(AuditableAction.Dmp_PublicLookup, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("fields", fieldSet)
));
return model;
}
@PostMapping("query")
public QueryResult<Dmp> Query(@RequestBody DmpLookup lookup) throws MyApplicationException, MyForbiddenException {
logger.debug("querying {}", Dmp.class.getSimpleName());

View File

@ -2,7 +2,7 @@ import { DescriptionStatus } from "@app/core/common/enum/description-status";
import { BaseEntity, BaseEntityPersist } from "@common/base/base-entity.model";
import { Guid } from "@common/types/guid";
import { DescriptionTemplate } from "../description-template/description-template";
import { Dmp, DmpDescriptionTemplate } from "../dmp/dmp";
import { Dmp, DmpDescriptionTemplate, PublicDmp } from "../dmp/dmp";
import { Reference, ReferencePersist } from "../reference/reference";
import { Tag } from "../tag/tag";
import { User } from "../user/user";
@ -21,8 +21,6 @@ export interface Description extends BaseEntity {
dmp?: Dmp;
}
export interface PublicDescription extends BaseEntity {
}
export interface DescriptionPropertyDefinition {
fieldSets: Map<string, DescriptionPropertyDefinitionFieldSet>;
@ -119,3 +117,28 @@ export interface DescriptionStatusPersist {
status: DescriptionStatus;
hash: string;
}
//
// Public
//
export interface PublicDescription extends BaseEntity {
label?: string;
status?: DescriptionStatus;
description?: string;
finalizedAt?: Date;
descriptionTemplate?: PublicDescriptionTemplate;
dmpDescriptionTemplate?: PublicDmpDescriptionTemplate;
dmp?: PublicDmp;
}
export interface PublicDmpDescriptionTemplate {
id: Guid;
dmp: PublicDmp;
}
export interface PublicDescriptionTemplate {
id: Guid;
label: string;
description: string;
}

View File

@ -5,7 +5,7 @@ import { DmpVersionStatus } from '@app/core/common/enum/dmp-version-status';
import { BaseEntity, BaseEntityPersist } from '@common/base/base-entity.model';
import { Guid } from '@common/types/guid';
import { DescriptionTemplate } from '../description-template/description-template';
import { Description } from '../description/description';
import { Description, PublicDescription } from '../description/description';
import { DmpBlueprint } from '../dmp-blueprint/dmp-blueprint';
import { EntityDoi } from '../entity-doi/entity-doi';
import { ReferencePersist } from '../reference/reference';
@ -146,3 +146,58 @@ export interface DmpUserRemovePersist {
export interface DmpUserInvitePersist {
users: DmpUserPersist[];
}
//
// Public
//
export interface PublicDmp extends BaseEntity {
label?: string;
version?: number;
description?: string;
finalizedAt?: Date;
publishedAt?: Date;
dmpReferences: PublicDmpReference[];
users: PublicDmpUser[];
descriptions: PublicDescription[];
}
export interface PublicDmpReference {
id: Guid;
dmp: PublicDmp;
reference: PublicReference;
}
export interface PublicReference {
id: Guid;
label: string;
type: PublicReferenceType;
description?: string;
reference?: string;
}
export interface PublicReferenceType {
id: Guid;
name: string;
}
export interface PublicReference {
id: Guid;
label: string;
type: PublicUser;
role: DmpUserRole;
}
export interface PublicDmpUser {
id: Guid;
dmp: PublicDmp;
user: PublicUser;
role: DmpUserRole;
}
export interface PublicUser {
id: Guid;
name: string;
}

View File

@ -34,11 +34,7 @@ export class DescriptionService {
publicQuery(q: DescriptionLookup): Observable<QueryResult<PublicDescription>> {
const url = `${this.apiBase}/public/query`;
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.AuthToken]
};
return this.http.post<QueryResult<PublicDescription>>(url, q, { params: params }).pipe(catchError((error: any) => throwError(error)));
return this.http.post<QueryResult<PublicDescription>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
getSingle(id: Guid, reqFields: string[] = []): Observable<Description> {
@ -52,18 +48,12 @@ export class DescriptionService {
catchError((error: any) => throwError(error)));
}
getPublicSingle(id: Guid, reqFields: string[] = []): Observable<Description> {
getPublicSingle(id: Guid, reqFields: string[] = []): Observable<PublicDescription> {
const url = `${this.apiBase}/public/${id}`;
const options: HttpParamsOptions = { fromObject: { f: reqFields } };
let params: BaseHttpParams = new BaseHttpParams(options);
params.interceptorContext = {
excludedInterceptors: [InterceptorType.AuthToken]
};
const options = { params: { f: reqFields } };
return this.http
.get<Description>(url, { params: params }).pipe(
.get<PublicDescription>(url, options).pipe(
catchError((error: any) => throwError(error)));
}

View File

@ -15,7 +15,7 @@ import { catchError, map } from 'rxjs/operators';
import { nameof } from 'ts-simple-nameof';
import { BaseHttpParams } from '../../../../common/http/base-http-params';
import { InterceptorType } from '../../../../common/http/interceptors/interceptor-type';
import { CloneDmpPersist, Dmp, DmpPersist, DmpUser, DmpUserInvitePersist, DmpUserPersist, DmpUserRemovePersist, NewVersionDmpPersist } from '../../model/dmp/dmp';
import { CloneDmpPersist, Dmp, DmpPersist, DmpUser, DmpUserInvitePersist, DmpUserPersist, DmpUserRemovePersist, NewVersionDmpPersist, PublicDmp } from '../../model/dmp/dmp';
import { AuthService } from '../auth/auth.service';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
@ -41,6 +41,11 @@ export class DmpService {
return this.http.post<QueryResult<Dmp>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
publicQuery(q: DmpLookup): Observable<QueryResult<PublicDmp>> {
const url = `${this.apiBase}/public/query`;
return this.http.post<QueryResult<PublicDmp>>(url, q).pipe(catchError((error: any) => throwError(error)));
}
getSingle(id: Guid, reqFields: string[] = []): Observable<Dmp> {
const url = `${this.apiBase}/${id}`;
const options = { params: { f: reqFields } };
@ -50,17 +55,12 @@ export class DmpService {
catchError((error: any) => throwError(error)));
}
getPublicSingle(id: Guid, reqFields: string[] = []): Observable<Dmp> { //TODO: add this to backend.
getPublicSingle(id: Guid, reqFields: string[] = []): Observable<PublicDmp> {
const url = `${this.apiBase}/public/${id}`;
const options: HttpParamsOptions = { fromObject: { f: reqFields } };
let params: BaseHttpParams = new BaseHttpParams(options);
params.interceptorContext = {
excludedInterceptors: [InterceptorType.AuthToken]
};
const options = { params: { f: reqFields } };
return this.http
.get<Dmp>(url, { params: params }).pipe(
.get<PublicDmp>(url, options).pipe(
catchError((error: any) => throwError(error)));
}

View File

@ -291,10 +291,10 @@
<div class="floating-btn">
<button *ngIf="stepper?.selectedIndex > 0" [@previous_btn] mat-button class="navigate-btn" (click)="stepper?.previous()">
<mat-icon class="back-icon pointer">chevron_left</mat-icon>
{{'DMP-EDITOR.STEPPER.PREVIOUS' | translate}}
{{'DESCRIPTION-TEMPLATE-EDITOR.ACTIONS.PREVIOUS' | translate}}
</button>
<button *ngIf="stepper?.selectedIndex < (steps.length-1)" mat-button class="navigate-btn ml-3" [@next_btn] (click)="validateStep(stepper?.selectedIndex);stepper?.next();" [ngClass]="{'navigate-btn-disabled': !isStepCompleted(stepper?.selectedIndex)}">
<span>{{'DMP-EDITOR.STEPPER.NEXT' | translate}}</span>
<span>{{'DESCRIPTION-TEMPLATE-EDITOR.ACTIONS.NEXT' | translate}}</span>
<mat-icon class="back-icon pointer">chevron_right</mat-icon>
</button>
</div>

View File

@ -5,13 +5,13 @@
</div>
<div mat-dialog-content class="confirmation-message">
<mat-form-field class="col-12">
<app-single-auto-complete [formControl]="data.formControl" placeholder="{{'DESCRIPTION-COPY-DIALOG.PLACEHOLDER' | translate}}" [configuration]="dmpAutoCompleteConfiguration">
<app-single-auto-complete [formControl]="data.formGroup.get('dmpId')" placeholder="{{'DESCRIPTION-COPY-DIALOG.PLACEHOLDER' | translate}}" [configuration]="dmpAutoCompleteConfiguration">
</app-single-auto-complete>
</mat-form-field>
<!-- <mat-error *ngIf="data.formControl.hasError('incorrect')">{{getErrorMessage()}}</mat-error> -->
</div>
<div mat-dialog-actions class="row">
<div class="col-auto ml-auto"><button mat-button class="cancel-btn" type="button" (click)="cancel()">{{ data.cancelButton }}</button></div>
<div class="col-auto"><button mat-button class="confirm-btn" type="button" [disabled]="this.data.formControl.value == null" (click)="confirm()">{{ data.confirmButton }}</button></div>
<div class="col-auto"><button mat-button class="confirm-btn" type="button" [disabled]="!data.formGroup.valid" (click)="confirm()">{{ data.confirmButton }}</button></div>
</div>
</div>

View File

@ -6,11 +6,17 @@ import { Observable } from "rxjs";
import { Inject } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { Dmp } from '@app/core/model/dmp/dmp';
import { Dmp, DmpDescriptionTemplate } from '@app/core/model/dmp/dmp';
import { DmpService } from '@app/core/services/dmp/dmp.service';
import { DescriptionService } from '@app/core/services/description/description.service';
import { DmpDescriptionTemplateLookup } from '@app/core/query/dmp-description-template.lookup';
import { IsActive } from '@app/core/common/enum/is-active.enum';
import { DmpLookup } from '@app/core/query/dmp.lookup';
import { Guid } from '@common/types/guid';
import { DmpStatus } from '@app/core/common/enum/dmp-status';
import { nameof } from 'ts-simple-nameof';
import { FilterService } from '@common/modules/text-filter/filter-service';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
@Component({
selector: 'description-copy-dialog-component',
@ -22,12 +28,12 @@ export class DescriptionCopyDialogComponent {
dmpModel: Dmp;
descriptionDescriptionTemplateLabel: String;
dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration = { //TODO: add filter to only get DMPs that have connection with the same Description Template group.
initialItems: (data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(null,null,null,null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(searchQuery, null, null, null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.dmpService.query(this.dmpService.buildAutocompleteLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
initialItems: (data?: any) => this.dmpService.query(this.buildDmpLookup(null,null,null,null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
filterFn: (searchQuery: string, data?: any) => this.dmpService.query(this.buildDmpLookup(searchQuery, null, null, null, this.dmpDescriptionTemplateLookup)).pipe(map(x => x.items)),
getSelectedItem: (selectedItem: any) => this.dmpService.query(this.buildDmpLookup(null, null, [selectedItem])).pipe(map(x => x.items[0])),
displayFn: (item: Dmp) => item.label,
titleFn: (item: Dmp) => item.label,
valueAssign: (item: Dmp) => item.id,
valueAssign: (item: Dmp) => this.findSection(item),
};
dmpDescriptionTemplateLookup: DmpDescriptionTemplateLookup = {
@ -35,16 +41,48 @@ export class DescriptionCopyDialogComponent {
isActive: [IsActive.Active]
} as DmpDescriptionTemplateLookup;
private buildDmpLookup(like?: string, excludedIds?: Guid[], ids?: Guid[], statuses?: DmpStatus[], dmpDescriptionTemplateSubQuery?: DmpDescriptionTemplateLookup): DmpLookup {
const lookup: DmpLookup = new DmpLookup();
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.statuses = statuses;
lookup.project = {
fields: [
nameof<Dmp>(x => x.id),
nameof<Dmp>(x => x.label),
[nameof<Dmp>(x => x.dmpDescriptionTemplates), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
[nameof<Dmp>(x => x.dmpDescriptionTemplates), nameof<DmpDescriptionTemplate>(x => x.descriptionTemplateGroupId)].join('.'),
]
};
if (dmpDescriptionTemplateSubQuery != null) lookup.dmpDescriptionTemplateSubQuery = dmpDescriptionTemplateSubQuery;
lookup.order = { items: [nameof<Dmp>(x => x.label)] };
if (like) { lookup.like = this.filterService.transformLike(like); }
return lookup;
}
constructor(
public dialogRef: MatDialogRef<DescriptionCopyDialogComponent>,
public dmpService: DmpService,
public descriptionService: DescriptionService,
public language: TranslateService,
private filterService: FilterService,
@Inject(MAT_DIALOG_DATA) public data: any
) { }
ngOnInit() {
}
findSection(dmp: Dmp){
if(dmp.dmpDescriptionTemplates.length == 1){
this.data.formGroup.get('sectionId').setValue(dmp.dmpDescriptionTemplates[0].sectionId);
}else if(dmp.dmpDescriptionTemplates.length > 1){
//TODO
}
return dmp.id
}
cancel() {
@ -52,9 +90,7 @@ export class DescriptionCopyDialogComponent {
}
confirm() {
// TODO: create a backend service to copy the description
const newDmpId = this.data.formControl.value;
this.dialogRef.close(newDmpId);
this.dialogRef.close(this.data.formGroup);
}
getErrorMessage() {

View File

@ -4,12 +4,14 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
import { CommonFormsModule } from '@common/forms/common-forms.module';
import { DescriptionCopyDialogComponent } from './description-copy-dialog.component';
import { RouterModule } from '@angular/router';
@NgModule({
imports: [
CommonUiModule,
CommonFormsModule,
AutoCompleteModule
AutoCompleteModule,
RouterModule
],
declarations: [
DescriptionCopyDialogComponent

View File

@ -52,7 +52,7 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
status: Number;
totalCount: number;
dmpSearchEnabled = true;
listingItems: Description[] = [];
listingItems: any[] = [];
hasListingItems = null;
isPublic: boolean = false;
@ -216,7 +216,8 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
[nameof<Description>(x => x.dmpDescriptionTemplate), nameof<DmpDescriptionTemplate>(x => x.sectionId)].join('.'),
]
};
this.descriptionService.query(lookup).pipe(takeUntil(this._destroyed))
if(this.isPublic){
this.descriptionService.publicQuery(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
@ -224,6 +225,17 @@ export class DescriptionListingComponent extends BaseComponent implements OnInit
this.listingItems.push(...result.items);
this.hasListingItems = true;
});
}else{
this.descriptionService.query(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
if (lookup?.page?.offset === 0) this.listingItems = [];
this.listingItems.push(...result.items);
this.hasListingItems = true;
});
}
}
openFiltersDialog(): void {

View File

@ -1,6 +1,6 @@
import { Location } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { UntypedFormControl } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { DmpAccessType } from '@app/core/common/enum/dmp-access-type';
@ -61,7 +61,8 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
public dmpService: DmpService,
public referenceService: ReferenceService,
public referenceTypeService: ReferenceTypeService,
public fileTransformerService: FileTransformerService
public fileTransformerService: FileTransformerService,
private fb: UntypedFormBuilder,
) {
super();
}
@ -155,12 +156,15 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
}
copyToDmp(description: Description) {
const formControl = new UntypedFormControl();
const formGroup = this.fb.group({
dmpId: this.fb.control(null, Validators.required),
sectionId: this.fb.control(null, Validators.required),
})
const dialogRef = this.dialog.open(DescriptionCopyDialogComponent, {
width: '500px',
restoreFocus: false,
data: {
formControl: formControl,
formGroup: formGroup,
descriptionId: description.id,
descriptionTemplate: description.descriptionTemplate,
descriptionProfileExist: false,
@ -170,9 +174,9 @@ export class DescriptionListingItemComponent extends BaseComponent implements On
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed))
.subscribe(newDmpId => {
if (newDmpId) {
this.router.navigate(['/descriptions/copy/' + description.id], { queryParams: { newDmpId: newDmpId } });
.subscribe(formGroup => {
if (formGroup) {
this.router.navigate(['descriptions/edit/copy/' + description.id + '/' + formGroup.get('dmpId').value + '/' + formGroup.get('sectionId').value]);
}
});
}

View File

@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { BaseComponent } from '@common/base/base.component';
// import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { Location } from '@angular/common';
import { UntypedFormControl } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormControl, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DescriptionStatus } from '@app/core/common/enum/description-status';
@ -42,7 +42,7 @@ import { ReferenceType } from '@app/core/model/reference-type/reference-type';
})
export class DescriptionOverviewComponent extends BaseComponent implements OnInit {
description: Description;
description: any;
researchers: DmpReference[] = [];
isNew = true;
isFinalized = false;
@ -73,7 +73,8 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
private matomoService: MatomoService,
private fileUtils: FileUtils,
public fileTransformerService: FileTransformerService,
private referenceTypeService: ReferenceTypeService
private referenceTypeService: ReferenceTypeService,
private fb: UntypedFormBuilder,
) {
super();
}
@ -325,12 +326,15 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
}
openCopyToDmpDialog() {
const formControl = new UntypedFormControl();
const formGroup = this.fb.group({
dmpId: this.fb.control(null, Validators.required),
sectionId: this.fb.control(null, Validators.required),
})
const dialogRef = this.dialog.open(DescriptionCopyDialogComponent, {
width: '500px',
restoreFocus: false,
data: {
formControl: formControl,
formGroup: formGroup,
descriptionId: this.description.id,
descriptionTemplate: this.description.descriptionTemplate,
dmpDescriptionTemplate: this.description.dmpDescriptionTemplate,
@ -341,11 +345,9 @@ export class DescriptionOverviewComponent extends BaseComponent implements OnIni
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed))
.subscribe(newDmpId => {
if (newDmpId) {
this.router.navigate(['/descriptions/copy/' + this.description.id], { queryParams: { newDmpId: newDmpId } });
// let url = this.router.createUrlTree(['/descriptions/copy/', result.descriptionId, { newDmpId: newDmpId }])
// window.open(url.toString(), '_blank')
.subscribe(formGroup => {
if (formGroup) {
this.router.navigate(['descriptions/edit/copy/' + this.description.id + '/' + formGroup.get('dmpId').value + '/' + formGroup.get('sectionId').value]);
}
});
}

View File

@ -42,7 +42,7 @@ export class DmpEditorModel extends BaseEditorModel implements DmpPersist {
this.language = item.language;
this.blueprint = item.blueprint?.id;
this.accessType = item.accessType;
if (item?.dmpUsers) { item.dmpUsers.map(x => this.users.push(new DmpUserEditorModel(this.validationErrorModel).fromModel(x))); }
if (item?.dmpUsers) { item.dmpUsers.filter(x => x.isActive === IsActive.Active).map(x => this.users.push(new DmpUserEditorModel(this.validationErrorModel).fromModel(x))); }
item.blueprint.definition.sections.forEach(section => {
if (section.hasTemplates) {

View File

@ -60,6 +60,7 @@ export class DmpEditorResolver extends BaseEditorResolver {
[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.sectionId)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.isActive)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.isActive)].join('.'),

View File

@ -44,7 +44,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr
lookup: DmpLookup = new DmpLookup();
groupId: string;
totalCount: number;
listingItems: Dmp[] = [];
listingItems: any[] = [];
isPublic: boolean = false;
hasListingItems = null;
pageSize: number = 5;
@ -188,6 +188,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.isActive)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.label)].join('.'),
@ -201,6 +202,9 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr
[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.role)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.dmp.id)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.isActive)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.label)].join('.'),
@ -208,7 +212,9 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr
// [nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.reference)].join('.'),
]
};
this.dmpService.query(lookup).pipe(takeUntil(this._destroyed))
if(this.isPublic){
this.dmpService.publicQuery(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
@ -216,6 +222,22 @@ export class DmpListingComponent extends BaseComponent implements OnInit { //IBr
this.listingItems.push(...result.items);
this.hasListingItems = true;
});
}else{
this.dmpService.query(lookup).pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (!result) { return []; }
this.totalCount = result.count;
if (lookup?.page?.offset === 0) this.listingItems = [];
result.items.forEach(x=> {
x.descriptions = x.descriptions?.filter(x=> x.isActive === IsActive.Active);
x.dmpUsers = x.dmpUsers.filter(x=> x.isActive === IsActive.Active);
this.listingItems.push(x);
})
// this.listingItems.push(...result.items);
this.hasListingItems = true;
});
}
}
controlModified(): void {

View File

@ -223,11 +223,11 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
}
canCreateNewVersion(dmp: Dmp): boolean {
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.CreateNewVersionDmp);
return (this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.CreateNewVersionDmp)) && this.isPublic == false;
}
canDeleteDmp(dmp: Dmp): boolean {
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.DeleteDmp);
return (this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.DeleteDmp)) && this.isPublic == false;
}
canCloneDmp(dmp: Dmp): boolean {
@ -235,7 +235,7 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
}
canFinalizeDmp(dmp: Dmp): boolean {
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.FinalizeDmp);
return (this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.FinalizeDmp)) && this.isPublic == false;
}
canExportDmp(dmp: Dmp): boolean {
@ -243,10 +243,10 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
}
canInviteDmpUsers(dmp: Dmp): boolean {
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.InviteDmpUsers);
return (this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.InviteDmpUsers)) && this.isPublic == false;
}
canAssignDmpUsers(dmp: Dmp): boolean {
return this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.AssignDmpUsers);
return (this.isDmpOwner(dmp) || this.authentication.hasPermission(AppPermission.AssignDmpUsers)) && this.isPublic == false;
}
}

View File

@ -36,7 +36,7 @@
{{dmp.updatedAt | dateTimeCultureFormatter: "d MMMM y"}}
</div>
<div class="d-flex mr-4">
<div *ngIf="dmp.status" class="d-flex flex-row uppercase">
<div *ngIf="dmp.status== dmpStatusEnum.Finalized" class="d-flex flex-row uppercase">
<mat-icon class="status-icon">check</mat-icon>
{{'DMP-OVERVIEW.FINALISED' | translate}}
</div>

View File

@ -43,6 +43,7 @@ import { CloneDmpDialogComponent } from '../clone-dialog/dmp-clone-dialog.compon
import { NewVersionDmpDialogComponent } from '../new-version-dialog/dmp-new-version-dialog.component';
import { AppPermission } from '@app/core/common/enum/permission.enum';
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
import { IsActive } from '@app/core/common/enum/is-active.enum';
@Component({
selector: 'app-dmp-overview',
@ -51,7 +52,7 @@ import { ReferenceType } from '@app/core/model/reference-type/reference-type';
})
export class DmpOverviewComponent extends BaseComponent implements OnInit {
dmp: Dmp;
dmp: any;
selectedBlueprint: DmpBlueprint;
researchers: DmpReference[] = [];
isNew = true;
@ -114,6 +115,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = data;
this.dmp.dmpUsers = data.dmpUsers.filter(x=> x.isActive === IsActive.Active);
if(this.dmp.descriptions) this.dmp.descriptions = data.descriptions.filter(x=> x.isActive === IsActive.Active);
this.selectedBlueprint= data.blueprint;
this.researchers = this.referenceService.getReferencesForTypes(this.dmp?.dmpReferences, [this.referenceTypeService.getResearcherReferenceType()]);
if (!this.hasDoi()) {
@ -195,15 +198,15 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
}
canEditDmp(): boolean{
return (this.isDraftDmp()) && (this.isDmpOwner() || this.authentication.hasPermission(AppPermission.EditDmp));
return (this.isDraftDmp()) && (this.isDmpOwner() || this.authentication.hasPermission(AppPermission.EditDmp)) && this.isPublicView == false;
}
canCreateNewVersion(): boolean {
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.CreateNewVersionDmp);
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.CreateNewVersionDmp) && this.isPublicView == false;
}
canDeleteDmp(): boolean {
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.DeleteDmp);
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.DeleteDmp) && this.isPublicView == false;
}
canCloneDmp(): boolean {
@ -211,7 +214,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
}
canFinalizeDmp(): boolean {
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.FinalizeDmp);
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.FinalizeDmp) && this.isPublicView == false;
}
canExportDmp(): boolean {
@ -219,11 +222,11 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
}
canInviteDmpUsers(): boolean {
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.InviteDmpUsers);
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.InviteDmpUsers) && this.isPublicView == false;
}
canAssignDmpUsers(): boolean {
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.AssignDmpUsers);
return this.isDmpOwner() || this.authentication.hasPermission(AppPermission.AssignDmpUsers) && this.isPublicView == false;
}
editClicked() {
@ -769,10 +772,13 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.status)].join('.'),
[nameof<Dmp>(x => x.descriptions), nameof<Description>(x => x.isActive)].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.name)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.role)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.dmp.id)].join('.'),
[nameof<Dmp>(x => x.dmpUsers), nameof<DmpUser>(x => x.isActive)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.dmpReferences), nameof<DmpReference>(x => x.reference), nameof<Reference>(x => x.label)].join('.'),

View File

@ -220,6 +220,14 @@
"TOTAL": "Total",
"SELECTED": "Selected"
}
},
"PENDING-FORM-CHANGES-DIALOG": {
"TITLE": "You have unsaved changes!",
"MESSAGE": "If you leave, your changes will be lost.",
"ACTIONS": {
"CANCEL": "Cancel",
"LEAVE": "LEAVE"
}
}
},
"SETTINGS-PICKER": {
@ -2097,7 +2105,7 @@
"SELECT": "Select an option",
"LIKE": "Search"
},
"DATASET-EDITOR": {
"DATASET-EDITOR1": {
"TITLE": {
"NEW": "New Data Management Plan",
"EDIT": "Edit",

View File

@ -23,9 +23,10 @@ export class PendingChangesGuard implements CanDeactivate<BasePendingChangesComp
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px',
data: {
warning: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.TITLE'),
message: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.MESSAGE'),
cancelButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.NO'),
confirmButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.YES')
cancelButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.CANCEL'),
confirmButton: this.language.instant('COMMONS.PENDING-FORM-CHANGES-DIALOG.ACTIONS.LEAVE')
}
});
return dialogRef.afterClosed().pipe(map(x => x ? true : false));