no message

This commit is contained in:
Ioannis Kalyvas 2018-08-24 18:21:02 +03:00
parent 46db0d4184
commit 3ad1c1c8f2
72 changed files with 1092 additions and 274 deletions

View File

@ -1,6 +1,7 @@
package eu.eudat.data.dao.criteria; package eu.eudat.data.dao.criteria;
import eu.eudat.data.entities.Project; import eu.eudat.data.entities.Project;
import eu.eudat.types.project.ProjectStateType;
import java.util.Date; import java.util.Date;
@ -8,6 +9,7 @@ public class ProjectCriteria extends Criteria<Project> {
private Date periodStart; private Date periodStart;
private Date periodEnd; private Date periodEnd;
private String reference; private String reference;
private Integer projectStateType;
public Date getPeriodStart() { public Date getPeriodStart() {
return periodStart; return periodStart;
@ -32,4 +34,12 @@ public class ProjectCriteria extends Criteria<Project> {
public void setReference(String reference) { public void setReference(String reference) {
this.reference = reference; this.reference = reference;
} }
public Integer getProjectStateType() {
return projectStateType;
}
public void setProjectStateType(Integer projectStateType) {
this.projectStateType = projectStateType;
}
} }

View File

@ -6,10 +6,12 @@ import eu.eudat.data.dao.databaselayer.service.DatabaseService;
import eu.eudat.data.entities.Project; import eu.eudat.data.entities.Project;
import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserInfo;
import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.QueryableList;
import eu.eudat.types.project.ProjectStateType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.persistence.criteria.JoinType; import javax.persistence.criteria.JoinType;
import java.util.Date;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -32,6 +34,14 @@ public class ProjectDaoImpl extends DatabaseAccess<Project> implements ProjectDa
query.where((builder, root) -> builder.greaterThan(root.get("startdate"), criteria.getPeriodStart())); query.where((builder, root) -> builder.greaterThan(root.get("startdate"), criteria.getPeriodStart()));
if (criteria.getReference() != null) if (criteria.getReference() != null)
query.where((builder, root) -> builder.equal(root.get("reference"), criteria.getReference())); query.where((builder, root) -> builder.equal(root.get("reference"), criteria.getReference()));
if (criteria.getProjectStateType() != null) {
if (criteria.getProjectStateType().equals(ProjectStateType.FINISHED.getValue()))
query.where((builder, root) -> builder.lessThan(root.get("enddate"), new Date()));
if (criteria.getProjectStateType().equals(ProjectStateType.ONGOING.getValue()))
query.where((builder, root) ->
builder.or(builder.greaterThan(root.get("enddate"), new Date())
, builder.isNull(root.get("enddate"))));
}
query.where((builder, root) -> builder.notEqual(root.get("status"), Project.Status.DELETED.getValue())); query.where((builder, root) -> builder.notEqual(root.get("status"), Project.Status.DELETED.getValue()));
return query; return query;
} }

View File

@ -0,0 +1,29 @@
package eu.eudat.types.project;
/**
* Created by ikalyvas on 8/24/2018.
*/
public enum ProjectStateType {
ONGOING(0), FINISHED(1);
private Integer value;
private ProjectStateType(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
public static ProjectStateType fromInteger(Integer value) {
switch (value) {
case 0:
return ONGOING;
case 1:
return FINISHED;
default:
throw new RuntimeException("Unsupported Project State Type");
}
}
}

View File

@ -111,7 +111,7 @@ public class DMPs extends BaseController {
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<List<DataManagementPlan>>> getWithCriteria(@RequestBody DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) { ResponseEntity<ResponseItem<List<DataManagementPlan>>> getWithCriteria(@RequestBody DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) {
try { try {
List<DataManagementPlan> dataTable = new DataManagementPlanManager().getWithCriteria(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), dataManagementPlanCriteria); List<DataManagementPlan> dataTable = new DataManagementPlanManager().getWithCriteria(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), dataManagementPlanCriteria, principal);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<DataManagementPlan>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<DataManagementPlan>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -2,6 +2,7 @@ package eu.eudat.controllers;
import eu.eudat.logic.managers.DashBoardManager; import eu.eudat.logic.managers.DashBoardManager;
import eu.eudat.models.data.dashboard.recent.RecentActivity; import eu.eudat.models.data.dashboard.recent.RecentActivity;
import eu.eudat.models.data.dashboard.searchbar.SearchBarItem;
import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics;
import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
@ -12,6 +13,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController @RestController
@CrossOrigin @CrossOrigin
@RequestMapping(value = {"/api"}) @RequestMapping(value = {"/api"})
@ -57,4 +60,16 @@ public class DashBoardController extends BaseController {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<RecentActivity>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage())); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<RecentActivity>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage()));
} }
} }
@RequestMapping(method = RequestMethod.GET, value = {"/dashboard/search"}, produces = "application/json")
public ResponseEntity<ResponseItem<List<SearchBarItem>>> search(@RequestParam(name = "like") String like, Principal principal) {
try {
List<SearchBarItem> searchBarItemList = new DashBoardManager().searchUserData(like,this.getApiContext(), this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao()
, this.getApiContext().getOperationsContext().getDatabaseRepository().getProjectDao(), principal);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<SearchBarItem>>().status(ApiMessageCode.NO_MESSAGE).payload(searchBarItemList));
} catch (Exception ex) {
ex.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<List<SearchBarItem>>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage()));
}
}
} }

View File

@ -8,6 +8,7 @@ import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserListingModel;
import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.userinfo.UserProfile;
import eu.eudat.types.ApiMessageCode; import eu.eudat.types.ApiMessageCode;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -17,6 +18,8 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.UUID;
import static eu.eudat.types.Authorities.ADMIN; import static eu.eudat.types.Authorities.ADMIN;
@ -54,6 +57,19 @@ public class Users extends BaseController {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<UserListingModel>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage())); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<UserListingModel>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage()));
} }
} }
@RequestMapping(method = RequestMethod.GET, value = {"/{id}"}, produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<UserProfile>> get(@PathVariable String id, Principal principal) {
try {
UUID userId = id.equals("me") ? principal.getId() : UUID.fromString(id);
UserProfile user = UserManager.getSingle(this.getApiContext(), userId);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<UserProfile>().payload(user).status(ApiMessageCode.NO_MESSAGE));
} catch (Exception ex) {
ex.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<UserProfile>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage()));
}
}
} }

View File

@ -32,6 +32,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
String token = nativeWebRequest.getHeader("AuthToken"); String token = nativeWebRequest.getHeader("AuthToken");
Optional<Annotation> claimsAnnotation = Arrays.stream(methodParameter.getParameterAnnotations()).filter(annotation -> annotation.annotationType().equals(ClaimedAuthorities.class)).findAny(); Optional<Annotation> claimsAnnotation = Arrays.stream(methodParameter.getParameterAnnotations()).filter(annotation -> annotation.annotationType().equals(ClaimedAuthorities.class)).findAny();
List<Authorities> claimList = claimsAnnotation.map(annotation -> Arrays.asList(((ClaimedAuthorities) annotation).claims())).orElse(Authorities.all()); List<Authorities> claimList = claimsAnnotation.map(annotation -> Arrays.asList(((ClaimedAuthorities) annotation).claims())).orElse(Authorities.all());
if(claimList.size() == 0 && claimList.get(0).equals(Authorities.ANONYMOUS)) return new Principal();
if (token == null) throw new UnauthorisedException("Authentication Information Is Missing"); if (token == null) throw new UnauthorisedException("Authentication Information Is Missing");
UUID authToken; UUID authToken;
try { try {

View File

@ -1,18 +1,21 @@
package eu.eudat.logic.managers; package eu.eudat.logic.managers;
import eu.eudat.logic.builders.model.models.RecentActivityDataBuilder; import eu.eudat.data.dao.criteria.DataManagementPlanCriteria;
import eu.eudat.data.dao.criteria.DatasetCriteria;
import eu.eudat.data.dao.entities.DMPDao; import eu.eudat.data.dao.entities.DMPDao;
import eu.eudat.data.dao.entities.DatasetDao; import eu.eudat.data.dao.entities.DatasetDao;
import eu.eudat.data.dao.entities.ProjectDao; import eu.eudat.data.dao.entities.ProjectDao;
import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.dao.criteria.DataManagementPlanCriteria; import eu.eudat.logic.builders.model.models.RecentActivityDataBuilder;
import eu.eudat.data.dao.criteria.DatasetCriteria; import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.dashboard.recent.RecentActivity; import eu.eudat.models.data.dashboard.recent.RecentActivity;
import eu.eudat.models.data.dashboard.recent.RecentActivityData; import eu.eudat.models.data.dashboard.recent.RecentActivityData;
import eu.eudat.models.data.dashboard.searchbar.SearchBarItem;
import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics; import eu.eudat.models.data.dashboard.statistics.DashBoardStatistics;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.services.ApiContext; import eu.eudat.types.searchbar.SearchBarItemType;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -87,4 +90,35 @@ public class DashBoardManager {
return activity; return activity;
} }
public List<SearchBarItem> searchUserData(String like, ApiContext apiContext, DatasetDao datasetRepository, DMPDao dataManagementPlanRepository, ProjectDao projectRepository, Principal principal) {
RecentActivity activity = new RecentActivity();
UserInfo user = new UserInfo();
user.setId(principal.getId());
List<SearchBarItem> searchBarItems = new LinkedList<>();
CompletableFuture<List<SearchBarItem>> dmps = dataManagementPlanRepository.getAuthenticated(dataManagementPlanRepository.asQueryable(), user)
.withHint("dmpRecentActivity")
.where((builder, root) -> builder.like(root.get("label"), "%" + like + "%"))
.orderBy((builder, root) -> builder.desc(root.get("modified")))
.selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DMP.getValue()))
.whenComplete((dmpItems, throwable) -> searchBarItems.addAll(dmpItems));
CompletableFuture<List<SearchBarItem>> datasets = datasetRepository.getAuthenticated(datasetRepository.asQueryable(), user)
.withHint("datasetRecentActivity")
.where((builder, root) -> builder.like(root.get("label"), "%" + like + "%"))
.orderBy((builder, root) -> builder.desc(root.get("modified")))
.selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.DATASET.getValue()))
.whenComplete((dataSetItems, throwable) -> searchBarItems.addAll(dataSetItems));
CompletableFuture<List<SearchBarItem>> projects = projectRepository.getAuthenticated(projectRepository.asQueryable(), user)
.withHint("projectRecentActivity")
.where((builder, root) -> builder.like(root.get("label"), "%" + like + "%"))
.orderBy((builder, root) -> builder.desc(root.get("modified")))
.selectAsync(item -> new SearchBarItem(item.getId().toString(), item.getLabel(), SearchBarItemType.PROJECT.getValue()))
.whenComplete((projectItems, throwable) -> searchBarItems.addAll(projectItems));
CompletableFuture.allOf(projects, dmps, datasets).join();
return searchBarItems;
}
} }

View File

@ -88,9 +88,12 @@ public class DataManagementPlanManager {
return datamanagementPlan; return datamanagementPlan;
} }
public List<DataManagementPlan> getWithCriteria(DMPDao dmpsRepository, DataManagementPlanCriteriaRequest dataManagementPlanCriteria) throws IllegalAccessException, InstantiationException { public List<DataManagementPlan> getWithCriteria(DMPDao dmpsRepository, DataManagementPlanCriteriaRequest dataManagementPlanCriteria, Principal principal) throws IllegalAccessException, InstantiationException {
QueryableList<DMP> items = dmpsRepository.getWithCriteria(dataManagementPlanCriteria.getCriteria()); UserInfo userInfo = new UserInfo();
List<eu.eudat.models.data.dmp.DataManagementPlan> datamanagementPlans = items.select(item -> new DataManagementPlan().fromDataModel(item)); userInfo.setId(principal.getId());
QueryableList<DMP> items = dmpsRepository.getWithCriteria(dataManagementPlanCriteria.getCriteria()).withHint(HintedModelFactory.getHint(DataManagementPlan.class));
QueryableList<DMP> authenticatedItems = dmpsRepository.getAuthenticated(items, userInfo);
List<eu.eudat.models.data.dmp.DataManagementPlan> datamanagementPlans = authenticatedItems.select(item -> new DataManagementPlan().fromDataModel(item));
return datamanagementPlans; return datamanagementPlans;
} }

View File

@ -4,11 +4,13 @@ import eu.eudat.logic.builders.entity.UserRoleBuilder;
import eu.eudat.logic.builders.model.models.DataTableDataBuilder; import eu.eudat.logic.builders.model.models.DataTableDataBuilder;
import eu.eudat.data.entities.UserRole; import eu.eudat.data.entities.UserRole;
import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.models.data.dmp.DataManagementPlan;
import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.common.DataTableData;
import eu.eudat.models.data.login.Credentials; import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem; import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserListingModel;
import eu.eudat.models.data.userinfo.UserProfile;
import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.QueryableList;
import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.AuthenticationServiceImpl; import eu.eudat.logic.services.operations.AuthenticationServiceImpl;
@ -17,6 +19,8 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
public class UserManager { public class UserManager {
public static eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(eu.eudat.data.entities.DatasetProfile profile) { public static eu.eudat.models.data.user.composite.DatasetProfile generateDatasetProfileModel(eu.eudat.data.entities.DatasetProfile profile) {
@ -38,6 +42,13 @@ public class UserManager {
return apiContext.getOperationsContext().getBuilderFactory().getBuilder(DataTableDataBuilder.class).totalCount(users.count()).data(modelUsers).build(); return apiContext.getOperationsContext().getBuilderFactory().getBuilder(DataTableDataBuilder.class).totalCount(users.count()).data(modelUsers).build();
} }
public static UserProfile getSingle(ApiContext apiContext, UUID userId) throws Exception {
eu.eudat.data.entities.UserInfo user = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userId);
UserProfile profile = new UserProfile().fromDataModel(user);
profile.setAssociatedDmps(user.getDmps().stream().map(x-> new DataManagementPlan().fromDataModel(x)).collect(Collectors.toList()));
return profile;
}
public static void editRoles(ApiContext apiContext, UserListingModel user) { public static void editRoles(ApiContext apiContext, UserListingModel user) {
eu.eudat.data.entities.UserInfo userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(user.getId()); eu.eudat.data.entities.UserInfo userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(user.getId());
userInfo.getUserRoles().stream().forEach(item -> apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().delete(item)); userInfo.getUserRoles().stream().forEach(item -> apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().delete(item));

View File

@ -0,0 +1,40 @@
package eu.eudat.models.data.dashboard.searchbar;
/**
* Created by ikalyvas on 7/26/2018.
*/
public class SearchBarItem {
private String id;
private String label;
private int type;
public SearchBarItem(String id, String label, int type) {
this.id = id;
this.label = label;
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}

View File

@ -198,7 +198,9 @@ public class DatasetWizardModel implements DataModel<Dataset, DatasetWizardModel
entity.setReference(this.reference); entity.setReference(this.reference);
entity.setUri(this.uri); entity.setUri(this.uri);
entity.setStatus(this.status); entity.setStatus(this.status);
entity.setDmp(dmp.toDataModel()); DMP dmp = new DMP();
dmp.setId(this.dmp.getId());
entity.setDmp(dmp);
entity.setDescription(this.description); entity.setDescription(this.description);
entity.setCreated(this.created != null ? this.created : new Date()); entity.setCreated(this.created != null ? this.created : new Date());
entity.setModified(new Date()); entity.setModified(new Date());

View File

@ -2,13 +2,13 @@ package eu.eudat.models.data.dmp;
import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.DMPProfile; import eu.eudat.data.entities.DMPProfile;
import eu.eudat.logic.utilities.builders.XmlBuilder;
import eu.eudat.models.DataModel; import eu.eudat.models.DataModel;
import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue;
import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile;
import eu.eudat.models.data.helpermodels.Tuple; import eu.eudat.models.data.helpermodels.Tuple;
import eu.eudat.models.data.project.Project; import eu.eudat.models.data.project.Project;
import eu.eudat.models.data.userinfo.UserInfo; import eu.eudat.models.data.userinfo.UserInfo;
import eu.eudat.logic.utilities.builders.XmlBuilder;
import net.minidev.json.JSONObject; import net.minidev.json.JSONObject;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -247,14 +247,14 @@ public class DataManagementPlan implements DataModel<DMP, DataManagementPlan> {
dataManagementPlanEntity.setProperties(this.properties != null ? JSONObject.toJSONString(this.properties) : null); dataManagementPlanEntity.setProperties(this.properties != null ? JSONObject.toJSONString(this.properties) : null);
dataManagementPlanEntity.setGroupId(this.groupId != null ? this.groupId : UUID.randomUUID()); dataManagementPlanEntity.setGroupId(this.groupId != null ? this.groupId : UUID.randomUUID());
dataManagementPlanEntity.setCreated(this.created != null ? this.created : new Date()); dataManagementPlanEntity.setCreated(this.created != null ? this.created : new Date());
dataManagementPlanEntity.setDmpProperties(JSONObject.toJSONString(this.dynamicFields.stream().filter(item -> item.getValue() != null).collect(Collectors.toMap(DynamicFieldWithValue::getId, DynamicFieldWithValue::getValue)))); if (this.dynamicFields != null)
dataManagementPlanEntity.setDmpProperties(JSONObject.toJSONString(this.dynamicFields.stream().filter(item -> item.getValue() != null).collect(Collectors.toMap(DynamicFieldWithValue::getId, DynamicFieldWithValue::getValue)))); dataManagementPlanEntity.setDmpProperties(JSONObject.toJSONString(this.dynamicFields.stream().filter(item -> item.getValue() != null).collect(Collectors.toMap(DynamicFieldWithValue::getId, DynamicFieldWithValue::getValue))));
dataManagementPlanEntity.setUsers(new HashSet<>(this.associatedUsers.stream().map(item -> item.toDataModel()).collect(Collectors.toList()))); dataManagementPlanEntity.setUsers(new HashSet<>(this.associatedUsers.stream().map(item -> item.toDataModel()).collect(Collectors.toList())));
return dataManagementPlanEntity; return dataManagementPlanEntity;
} }
@Override @Override
public String getHint() { public String getHint() {
return null; return "fullyDetailed";
} }
} }

View File

@ -0,0 +1,102 @@
package eu.eudat.models.data.userinfo;
import eu.eudat.data.entities.*;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.models.DataModel;
import eu.eudat.models.data.dmp.DataManagementPlan;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Created by ikalyvas on 8/24/2018.
*/
public class UserProfile implements DataModel<eu.eudat.data.entities.UserInfo, UserProfile> {
private UUID id;
private String email;
private Short usertype;
private String name;
private Date lastloggedin;
private String additionalinfo;
private List<DataManagementPlan> associatedDmps;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Short getUsertype() {
return usertype;
}
public void setUsertype(Short usertype) {
this.usertype = usertype;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getLastloggedin() {
return lastloggedin;
}
public void setLastloggedin(Date lastloggedin) {
this.lastloggedin = lastloggedin;
}
public String getAdditionalinfo() {
return additionalinfo;
}
public void setAdditionalinfo(String additionalinfo) {
this.additionalinfo = additionalinfo;
}
public List<DataManagementPlan> getAssociatedDmps() {
return associatedDmps;
}
public void setAssociatedDmps(List<DataManagementPlan> associatedDmps) {
this.associatedDmps = associatedDmps;
}
@Override
public UserProfile fromDataModel(UserInfo entity) {
this.id = entity.getId();
this.email = entity.getEmail();
this.usertype = entity.getUsertype();
this.name = entity.getName();
this.lastloggedin = entity.getLastloggedin();
this.additionalinfo = entity.getAdditionalinfo();
return this;
}
@Override
public UserInfo toDataModel() throws Exception {
return null;
}
@Override
public String getHint() {
return null;
}
}

View File

@ -5,7 +5,7 @@ import java.util.List;
public enum Authorities { public enum Authorities {
USER(0), MANAGER(1), ADMIN(2); USER(0), MANAGER(1), ADMIN(2), ANONYMOUS(99);
private Integer value; private Integer value;
@ -25,6 +25,8 @@ public enum Authorities {
return MANAGER; return MANAGER;
case 2: case 2:
return ADMIN; return ADMIN;
case 99:
return ANONYMOUS;
default: default:
throw new RuntimeException("Unsupported Authority Type"); throw new RuntimeException("Unsupported Authority Type");
} }

View File

@ -0,0 +1,32 @@
package eu.eudat.types.searchbar;
/**
* Created by ikalyvas on 7/26/2018.
*/
public enum SearchBarItemType {
DATASET(0), DMP(1), PROJECT(2);
private Integer value;
private SearchBarItemType(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
public static SearchBarItemType fromInteger(Integer value) {
switch (value) {
case 0:
return DATASET;
case 1:
return DMP;
case 2:
return PROJECT;
default:
throw new RuntimeException("Unsupported Search bar item Code");
}
}
}

View File

@ -71,5 +71,5 @@ http-logger.initial-delay = 0
http-logger.delay = 10 http-logger.delay = 10
http-logger.server-address = http://logstash:31311 http-logger.server-address = http://logstash:31311
#############################Elastic Search###################################### #############################Elastic Search######################################
elasticsearch.host = elasticsearch-dmp elasticsearch.host = localhost
elasticsearch.port = 9200 elasticsearch.port = 9201

View File

@ -1,6 +1,6 @@
<app-navigation></app-navigation> <app-navigation class="fixed"></app-navigation>
<div class="container-fluid"> <div class="container-fluid main-container">
<div class="row"> <div class="row">
<help-content position="top"></help-content> <help-content position="top"></help-content>
</div> </div>

View File

@ -1,6 +1,6 @@
<div class="dataset-wizard"> <div class="dataset-wizard">
<h3 *ngIf="isNew">New Dataset</h3> <h3 *ngIf="isNew">New Dataset</h3>
<h3 *ngIf="!isNew">{{datasetWizardModel.label}} Dataset</h3> <h3 *ngIf="!isNew">{{datasetWizardModel?.label}} Dataset</h3>
<div class="flex-container"> <div class="flex-container">
<button mat-raised-button color="primary" *ngIf="datasetWizardModel&&datasetWizardModel?.status != 1" style="margin-top: 15px;margin-bottom: 15px;margin-right: 15px;" <button mat-raised-button color="primary" *ngIf="datasetWizardModel&&datasetWizardModel?.status != 1" style="margin-top: 15px;margin-bottom: 15px;margin-right: 15px;"
@ -22,6 +22,9 @@
<mat-horizontal-stepper [linear]="isLinear" #stepper> <mat-horizontal-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="formGroup"> <mat-step [stepControl]="formGroup">
<form *ngIf="formGroup" [formGroup]="formGroup"> <form *ngIf="formGroup" [formGroup]="formGroup">
<app-single-auto-complete [reactiveFormControl]="formGroup.get('dmp')" placeholder="{{'DATASET-EDITOR.FIELDS.DMP' | translate}}"
[configuration]="dmpAutoCompleteConfiguration">
</app-single-auto-complete>
<ng-template matStepLabel>{{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}}</ng-template> <ng-template matStepLabel>{{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}}</ng-template>
<mat-form-field formGroupName="profile"> <mat-form-field formGroupName="profile">
<mat-select placeholder=" {{'DATASET-WIZARD.FIRST-STEP.PROFILE'| translate}}" formControlName="id"> <mat-select placeholder=" {{'DATASET-WIZARD.FIRST-STEP.PROFILE'| translate}}" formControlName="id">

View File

@ -35,6 +35,8 @@ import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/br
import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria'; import { TagsCriteria } from '../../models/criteria/tags/TagsCriteria';
import { TagModel } from '../../models/tags/TagModel'; import { TagModel } from '../../models/tags/TagModel';
import { AutoCompleteConfiguration } from '../../shared/components/auto-complete/AutoCompleteConfiguration'; import { AutoCompleteConfiguration } from '../../shared/components/auto-complete/AutoCompleteConfiguration';
import { SingleAutoCompleteConfiguration } from '../../shared/components/autocompletes/single/single-auto-complete-configuration';
import { DataManagementPlanListingModel } from '../../models/data-managemnt-plans/DataManagementPlanListingModel';
@Component({ @Component({
selector: 'app-dataset-wizard-component', selector: 'app-dataset-wizard-component',
@ -67,6 +69,8 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
dataRepositoriesAutoCompleteConfiguration: AutoCompleteConfiguration; dataRepositoriesAutoCompleteConfiguration: AutoCompleteConfiguration;
servicesAutoCompleteConfiguration: AutoCompleteConfiguration; servicesAutoCompleteConfiguration: AutoCompleteConfiguration;
tagsAutoCompleteConfiguration: AutoCompleteConfiguration; tagsAutoCompleteConfiguration: AutoCompleteConfiguration;
dmpAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
externalSourcesConfiguration: ExternalSourcesConfiguration; externalSourcesConfiguration: ExternalSourcesConfiguration;
datasetWizardModel: DatasetWizardModel; datasetWizardModel: DatasetWizardModel;
@ -127,7 +131,16 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
this.externalSourcesConfiguration.services.push({ key: '', label: "All" }) this.externalSourcesConfiguration.services.push({ key: '', label: "All" })
this.externalSourcesConfiguration.tags.push({ key: '', label: "All" }) this.externalSourcesConfiguration.tags.push({ key: '', label: "All" })
}) })
let dmpAutoCompleteConfiguration = {}
this.dmpAutoCompleteConfiguration = {
filterFn: this.searchDmp.bind(this),
items: this.searchDmp(''),
displayFn: (item) => item["label"],
titleFn: (item) => item["label"],
//mapFn: (item) => new JsonSerializer<ProjectReference>().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()),
loadDataOnStart: true
};
this.route.params.subscribe((params: Params) => { this.route.params.subscribe((params: Params) => {
this.itemId = params['id']; this.itemId = params['id'];
const dmpId = params['dmpId']; const dmpId = params['dmpId'];
@ -187,11 +200,13 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
}); });
}); });
} else { } else {
this.datasetWizardModel = new DatasetWizardModel();
this.formGroup = this.datasetWizardModel.buildForm()
this.formGroup.get('dmp').valueChanges.subscribe(x => {
this.loadDatasetProfiles();
})
} }
}); });
} }
ngAfterViewInit() { ngAfterViewInit() {
@ -201,12 +216,18 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
}) })
} }
searchDmp(query: string): Observable<DataManagementPlanListingModel[]> {
let dmpRequestItem: RequestItem<DataManagementPlanCriteria> = new RequestItem();
dmpRequestItem.criteria = new DataManagementPlanCriteria();
dmpRequestItem.criteria.like = query;
return this.dataManagementPlanService.get(dmpRequestItem);
}
loadDatasetProfiles() { loadDatasetProfiles() {
let datasetProfileRequestItem: RequestItem<DatasetProfileCriteria> = new RequestItem(); let datasetProfileRequestItem: RequestItem<DatasetProfileCriteria> = new RequestItem();
datasetProfileRequestItem.criteria = new DatasetProfileCriteria(); datasetProfileRequestItem.criteria = new DatasetProfileCriteria();
datasetProfileRequestItem.criteria.id = this.datasetWizardModel.dmp.id; datasetProfileRequestItem.criteria.id = this.formGroup.get("dmp").value.id;
this.datasetWizardService.getAvailableProfiles(datasetProfileRequestItem).subscribe(items => { if (datasetProfileRequestItem.criteria.id) this.datasetWizardService.getAvailableProfiles(datasetProfileRequestItem).subscribe(items => {
this.availableProfiles = JsonSerializer.fromJSONArray(items, DatasetProfileModel); this.availableProfiles = JsonSerializer.fromJSONArray(items, DatasetProfileModel);
}); });
} }
@ -251,7 +272,7 @@ export class DatasetWizardComponent implements OnInit, IBreadCrumbComponent {
submit() { submit() {
this.datasetWizardService.createDataset(this.formGroup.value).subscribe(data => { this.datasetWizardService.createDataset(this.formGroup.value).subscribe(data => {
this.router.navigateByUrl("/datasets/dmp/" + this.datasetWizardModel.dmp.id); this.router.navigateByUrl("/datasets/dmp/" + this.formGroup.get("dmp").value.id);
}); });
} }

View File

@ -27,23 +27,29 @@
<mat-cell *matCellDef="let row"> {{row.profile}} </mat-cell> <mat-cell *matCellDef="let row"> {{row.profile}} </mat-cell>
</ng-container> </ng-container>
<!-- Column Definition: Status -->
<ng-container cdkColumnDef="status">
<mat-header-cell *matHeaderCellDef >{{'DATASET-LISTING.COLUMNS.STATUS' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.status}} </mat-cell>
</ng-container>
<!-- Column Definition: DataRepositories --> <!-- Column Definition: DataRepositories -->
<ng-container cdkColumnDef="dataRepositories"> <!-- <ng-container cdkColumnDef="dataRepositories">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.DATAREPOSITORIES' | translate}}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.DATAREPOSITORIES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.dataRepositories}} </mat-cell> <mat-cell *matCellDef="let row"> {{row.dataRepositories}} </mat-cell>
</ng-container> </ng-container> -->
<!-- Column Definition: DataRepositories --> <!-- Column Definition: DataRepositories -->
<ng-container cdkColumnDef="registries"> <!-- <ng-container cdkColumnDef="registries">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.REGISTRIES' | translate}}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.REGISTRIES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.registries}} </mat-cell> <mat-cell *matCellDef="let row"> {{row.registries}} </mat-cell>
</ng-container> </ng-container> -->
<!-- Column Definition: DataRepositories --> <!-- Column Definition: DataRepositories -->
<ng-container cdkColumnDef="services"> <!-- <ng-container cdkColumnDef="services">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.SERVICES' | translate}}</mat-header-cell> <mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.SERVICES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.services}} </mat-cell> <mat-cell *matCellDef="let row"> {{row.services}} </mat-cell>
</ng-container> </ng-container> -->
<!-- Column Definition: Status --> <!-- Column Definition: Status -->
<!-- <ng-container cdkColumnDef="status"> <!-- <ng-container cdkColumnDef="status">
@ -93,4 +99,7 @@
<button *ngIf="dmpId" mat-fab class="mat-fab-bottom-right" color="primary" [routerLink]="['/datasets/new/'+dmpId] "> <button *ngIf="dmpId" mat-fab class="mat-fab-bottom-right" color="primary" [routerLink]="['/datasets/new/'+dmpId] ">
<mat-icon class="mat-24">add</mat-icon> <mat-icon class="mat-24">add</mat-icon>
</button> </button>
<button *ngIf="!dmpId" mat-fab class="mat-fab-bottom-right" color="primary" [routerLink]="['/datasets/new'] ">
<mat-icon class="mat-24">add</mat-icon>
</button>
</div> </div>

View File

@ -32,7 +32,7 @@ export class DatasetListingComponent implements OnInit, IBreadCrumbComponent {
breadCrumbs: Observable<BreadcrumbItem[]>; breadCrumbs: Observable<BreadcrumbItem[]>;
dataSource: DatasetDataSource | null; dataSource: DatasetDataSource | null;
displayedColumns: String[] = ['label', 'dmp', 'profile', 'dataRepositories', 'registries', 'services', 'description', 'created', 'actions']; displayedColumns: String[] = ['label', 'dmp', 'profile', 'status', 'description', 'created', 'actions'];
pageEvent: PageEvent; pageEvent: PageEvent;
titlePrefix: String; titlePrefix: String;
dmpId: string; dmpId: string;

View File

@ -45,14 +45,14 @@
</mat-form-field> </mat-form-field>
<div class="col-md-6"> <div class="col-md-6">
<app-single-auto-complete [reactiveFormControl]="formGroup.get('project')" placeholder="{{this.languageResolverService.getBy('dmpEditor') | translate}}" <app-single-auto-complete required='true' [reactiveFormControl]="formGroup.get('project')" placeholder="{{this.languageResolverService.getBy('dmpEditor') | translate}}"
[configuration]="projectAutoCompleteConfiguration"> [configuration]="projectAutoCompleteConfiguration">
</app-single-auto-complete> </app-single-auto-complete>
</div> </div>
<!-- <app-dynamic-fields-project [formGroup]="formGroup"></app-dynamic-fields-project> --> <!-- <app-dynamic-fields-project [formGroup]="formGroup"></app-dynamic-fields-project> -->
<div class="col-md-6"> <div class="col-md-6">
<div class="row"> <div class="row">
<app-multiple-auto-complete class="col-md-10" [reactiveFormControl]="formGroup.get('profiles')" placeholder="{{'DMP-EDITOR.FIELDS.PROFILES' | translate}}" <app-multiple-auto-complete required='true' class="col-md-10" [reactiveFormControl]="formGroup.get('profiles')" placeholder="{{'DMP-EDITOR.FIELDS.PROFILES' | translate}}"
[configuration]="profilesAutoCompleteConfiguration"> [configuration]="profilesAutoCompleteConfiguration">
</app-multiple-auto-complete> </app-multiple-auto-complete>
<div class="col-md-2"> <div class="col-md-2">
@ -111,11 +111,13 @@
</mat-list> </mat-list>
</div> </div>
<div class="col-md-12 float-right"> <div class="col-md-12">
<button mat-raised-button color="primary" (click)="cancel()" type="button">{{'DMP-EDITOR.ACTIONS.CANCEL' | translate}}</button> <div class="right-button">
<!-- <button *ngIf="!isNew" mat-raised-button color="primary" (click)="invite()" type="button">{{'DMP-EDITOR.ACTIONS.INVITE' | translate}}</button> --> <button mat-raised-button color="primary" (click)="cancel()" type="button">{{'DMP-EDITOR.ACTIONS.CANCEL' | translate}}</button>
<button mat-raised-button color="primary" type="submit">{{'DMP-EDITOR.ACTIONS.SAVE' | translate}}</button> <!-- <button *ngIf="!isNew" mat-raised-button color="primary" (click)="invite()" type="button">{{'DMP-EDITOR.ACTIONS.INVITE' | translate}}</button> -->
<button *ngIf="!isNew" mat-raised-button color="primary" type="button" (click)="openConfirm(formGroup.get('label').value, formGroup.get('id').value)">{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}</button> <button mat-raised-button color="primary" type="submit">{{'DMP-EDITOR.ACTIONS.SAVE' | translate}}</button>
<button *ngIf="!isNew" mat-raised-button color="primary" type="button" (click)="openConfirm(formGroup.get('label').value, formGroup.get('id').value)">{{'DMP-EDITOR.ACTIONS.DELETE' | translate}}</button>
</div>
</div> </div>
</div> </div>
</mat-card-content> </mat-card-content>

View File

@ -18,6 +18,9 @@
} }
.left-button { .left-button {
float: left; float: left;
}
.right-button {
float: right;
} }
.description-area { .description-area {
height: 100px; height: 100px;

View File

@ -158,7 +158,7 @@ export class DataManagementPlanDataSource extends DataSource<DataManagementPlanL
let fields: Array<string> = new Array() let fields: Array<string> = new Array()
if (this._sort.active) fields = this._sort.direction === "asc" ? ["+" + this._sort.active] : ["-" + this._sort.active]; if (this._sort.active) fields = this._sort.direction === "asc" ? ["+" + this._sort.active] : ["-" + this._sort.active];
const request = new DataTableRequest<DataManagementPlanCriteria>(startIndex, this._paginator.pageSize, { fields: fields }); const request = new DataTableRequest<DataManagementPlanCriteria>(startIndex, this._paginator.pageSize, { fields: fields });
request.criteria = this._criteria.criteria; request.criteria = this._criteria.formGroup.value;
if (this.itemId) { if (this.itemId) {
request.criteria.groupIds = [this.itemId]; request.criteria.groupIds = [this.itemId];
request.criteria.allVersions = true; request.criteria.allVersions = true;

View File

@ -30,7 +30,7 @@ import { MultipleAutoCompleteConfiguration } from '../../../shared/components/au
styleUrls: ['./dmp-wizard-editor.component.scss'], styleUrls: ['./dmp-wizard-editor.component.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class DataManagementPlanWizardEditorComponent implements AfterViewInit { export class DataManagementPlanWizardEditorComponent implements OnInit {
isNew = true; isNew = true;

View File

@ -1,32 +1,88 @@
<div class="main-panel" id="main-panel"> <div class="main-panel" id="main-panel">
<div class="container"> <div>
<div class="row" style="margin-top: 30px"> <div class="row" style="margin-top: 30px">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-md-offset-1"> <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-md-offset-1">
<h3 *ngIf="!this.isAuthenticated()">{{ 'HOMEPAGE.OPEN-DMPS.STATS' | translate }}</h3> <h3 *ngIf="!this.isAuthenticated()">{{ 'HOMEPAGE.OPEN-DMPS.STATS' | translate }}</h3>
<h3 *ngIf="this.isAuthenticated()">{{ 'HOMEPAGE.MY-DMPS.STATS' | translate }}</h3> <h3 *ngIf="this.isAuthenticated()">{{ 'HOMEPAGE.MY-DMPS.STATS' | translate }}</h3>
</div> </div>
</div> </div>
<div class="row" style="margin-top: 30px">
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 col-md-offset-1"> </div>
<app-figurecard title={{dashboardStatisticsData.totalDataManagementPlanCount}} headerIcon="mode_edit" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-DMPS' : 'DASHBOARD.DMPS' " <div class="row" style="margin-top: 30px">
routelLink='/dmps' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #ef5350, #e53935)" boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(244, 67, 54, 0.4)"> <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 col-md-offset-1">
</app-figurecard> <app-figurecard title={{dashboardStatisticsData.totalDataManagementPlanCount}} headerIcon="mode_edit" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-DMPS' : 'DASHBOARD.DMPS' "
</div> routelLink='/dmps' buttonRedirectLink="/dmps/new" buttonTitle="Create New DMP" footerIcon="open_in_new" linearColor="linear-gradient(60deg, #ef5350, #e53935)"
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 "> boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(244, 67, 54, 0.4)">
<app-figurecard title={{dashboardStatisticsData.totalProjectCount}} headerIcon="list" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-PROJECTS' : 'DASHBOARD.PROJECTS' " </app-figurecard>
routelLink='/projects' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #ffa726, #fb8c00)" boxShadow="0 4px 20px 0 rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(255, 152, 0, 0.4)"> <mat-card *ngIf="this.isAuthenticated()" class="example-card">
</app-figurecard> <mat-card-header>
</div> <mat-card-title>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12"> {{'RECENT-ACTIVITY.MY-TITLE-DMP' | translate}}
<app-figurecard title={{dashboardStatisticsData.totalDataSetCount}} headerIcon="subject" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-DATASETS' : 'DASHBOARD.DATASETS'" </mat-card-title>
routelLink='/datasets' footerIcon="open_in_new" linearColor="linear-gradient(60deg, #26c6da, #00acc1)" boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(0, 188, 212, 0.4)"> </mat-card-header>
</app-figurecard> <mat-card-content>
</div> <mat-nav-list *ngIf="dmpActivities!=null">
<mat-list-item (click)="redirect(activity.id,RecentActivityTypes.DMP)" *ngFor="let activity of dmpActivities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div> </div>
<div *ngIf="this.isAuthenticated()" class="row"> <div class="col-lg-3 col-md-3 col-sm-6 col-xs-12 ">
<div class="col-lg-9 col-md-12 col-sm-12 col-xs-12 col-md-offset-1"> <app-figurecard title={{dashboardStatisticsData.totalProjectCount}} headerIcon="list" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-PROJECTS' : 'DASHBOARD.PROJECTS' "
<app-recent-activity></app-recent-activity> routelLink='/projects' buttonRedirectLink="/projects/new" buttonTitle="Create New Project" footerIcon="open_in_new"
</div> linearColor="linear-gradient(60deg, #ffa726, #fb8c00)" boxShadow="0 4px 20px 0 rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(255, 152, 0, 0.4)">
</app-figurecard>
<mat-card *ngIf="this.isAuthenticated()" class="example-card">
<mat-card-header>
<mat-card-title>
{{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-nav-list *ngIf="projectActivities!=null">
<mat-list-item (click)="redirect(activity.id,RecentActivityTypes.PROJECT)" *ngFor="let activity of projectActivities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div>
<div class="col-lg-3 col-md-3 col-sm-6 col-xs-12">
<app-figurecard title={{dashboardStatisticsData.totalDataSetCount}} headerIcon="subject" [category]="this.isAuthenticated() ? 'DASHBOARD.MY-DATASETS' : 'DASHBOARD.DATASETS'"
routelLink='/datasets' buttonRedirectLink="/datasets/new" buttonTitle="Create New Dataset" footerIcon="open_in_new"
linearColor="linear-gradient(60deg, #26c6da, #00acc1)" boxShadow="0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(0, 188, 212, 0.4)">
</app-figurecard>
<mat-card *ngIf="this.isAuthenticated()" class="example-card">
<mat-card-header>
<mat-card-title>
{{'RECENT-ACTIVITY.MY-TITLE-DATASET' | translate}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-nav-list *ngIf="datasetActivities!=null">
<mat-list-item (click)="redirect(activity.id,RecentActivityTypes.DATASET)" *ngFor="let activity of datasetActivities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div> </div>
</div> </div>
</div> </div>

View File

@ -54,21 +54,6 @@
box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2); box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.42), 0 4px 25px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(0, 0, 0, 0.2);
} }
@media screen and (max-width: 990px) { .full-width {
#sidebar, width: 100%;
#nav-right, }
#nav-left-button {
display: none;
}
#menu {
display: inline;
}
#main-panel {
padding-left: 0;
-webkit-transition: all 400ms;
-moz-transition: all 400ms;
-ms-transition: all 400ms;
-o-transition: all 400ms;
transition: all 400ms;
}
}

View File

@ -4,22 +4,45 @@ import { DashboardService } from '../../app/services/dashboard/dashboard.service
import { DashboardStatisticsModel } from '../models/dashboard/DashboardStatisticsModel'; import { DashboardStatisticsModel } from '../models/dashboard/DashboardStatisticsModel';
import { JsonSerializer } from '../utilities/JsonSerializer'; import { JsonSerializer } from '../utilities/JsonSerializer';
import { AuthService } from '../services/auth/auth.service'; import { AuthService } from '../services/auth/auth.service';
import { FormControl } from '@angular/forms';
import { RequestItem } from '../models/criteria/RequestItem';
import { ProjectCriteria } from '../models/criteria/project/ProjectCriteria';
import { ProjectService } from '../services/project/project.service';
import { SingleAutoCompleteConfiguration } from '../shared/components/autocompletes/single/single-auto-complete-configuration';
import { UserReferenceService } from '../services/user-reference/user-reference-data.service';
import { RecentActivityTypes } from '../users/activity/RecentActivityTypes';
import { Observable } from 'rxjs/internal/Observable';
import { SearchBarItem } from '../models/dashboard/SearchBarItem';
import { SearchBarType } from '../shared/components/search-bar/types/search-bar-type';
@Component({ @Component({
selector: 'homepage', selector: 'homepage',
templateUrl: './homepage.component.html', templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.css'], styleUrls: ['./homepage.component.scss'],
providers: [ProjectService, UserReferenceService]
}) })
export class HomepageComponent implements OnInit { export class HomepageComponent implements OnInit {
public userInfo: any; public userInfo: any;
datasetActivities: any[];
projectActivities: any[];
dmpActivities: any[];
public dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel(); public dashboardStatisticsData: DashboardStatisticsModel = new DashboardStatisticsModel();
public formControl = new FormControl();
projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
public searchControl = new FormControl();
filteredOptions: Observable<SearchBarItem[]>;
RecentActivityTypes = RecentActivityTypes
public search = false;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private projectService: ProjectService,
private dashBoardService: DashboardService, private dashBoardService: DashboardService,
private authentication: AuthService private authentication: AuthService,
private userReferenceService: UserReferenceService
) { ) {
this.dashboardStatisticsData.totalDataManagementPlanCount = 0; this.dashboardStatisticsData.totalDataManagementPlanCount = 0;
this.dashboardStatisticsData.totalDataSetCount = 0; this.dashboardStatisticsData.totalDataSetCount = 0;
@ -29,6 +52,21 @@ export class HomepageComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.userReferenceService.getRecentActivity().subscribe(response => {
this.datasetActivities = response["recentDatasetActivities"];
this.dmpActivities = response["recentDmpActivities"];
this.projectActivities = response["recentProjectActivities"];
})
this.projectAutoCompleteConfiguration = {
filterFn: this.searchProject.bind(this),
items: this.searchProject(''),
displayFn: (item) => item["label"],
titleFn: (item) => item["label"],
//mapFn: (item) => new JsonSerializer<ProjectReference>().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()),
loadDataOnStart: true
};
if (!this.isAuthenticated()) { if (!this.isAuthenticated()) {
this.dashBoardService.getStatistics().subscribe(results => { this.dashBoardService.getStatistics().subscribe(results => {
//let data = results['payload']; //let data = results['payload'];
@ -40,6 +78,9 @@ export class HomepageComponent implements OnInit {
}) })
} }
this.filteredOptions = this.searchControl.valueChanges.flatMap(x => {
return this.dashBoardService.searchUserItems(x);
})
} }
@ -47,4 +88,36 @@ export class HomepageComponent implements OnInit {
return !(!this.authentication.current()) return !(!this.authentication.current())
} }
searchProject(query: string) {
let projectRequestItem: RequestItem<ProjectCriteria> = new RequestItem();
projectRequestItem.criteria = new ProjectCriteria();
projectRequestItem.criteria.like = query;
return this.projectService.getWithExternal(projectRequestItem);
}
redirect(id: string, type: RecentActivityTypes) {
switch (type) {
case RecentActivityTypes.PROJECT: {
this.router.navigate(["projects/edit/" + id]);
return;
}
case RecentActivityTypes.DATASET: {
this.router.navigate(["datasets/edit/" + id]);
return;
}
case RecentActivityTypes.DMP: {
this.router.navigate(["dmps/edit/" + id]);
return;
}
default: throw new Error("Unsupported Activity Type ")
}
}
onOptionSelected(event: any) {
let selectedSearchBarItem = event.option.value;
if (selectedSearchBarItem.type == SearchBarType.DATASET) this.router.navigate(["datasets/edit/" + selectedSearchBarItem.id])
if (selectedSearchBarItem.type == SearchBarType.PROJECT) this.router.navigate(["projects/edit/" + selectedSearchBarItem.id])
if (selectedSearchBarItem.type == SearchBarType.DATAMANAGEMENTPLAN) this.router.navigate(["dmps/edit/" + selectedSearchBarItem.id])
}
} }

View File

@ -1,6 +1,8 @@
import { BaseCriteria } from "../BaseCriteria"; import { BaseCriteria } from "../BaseCriteria";
import { ProjectStateType } from "../../projects/ProjectStateType";
export class ProjectCriteria extends BaseCriteria { export class ProjectCriteria extends BaseCriteria {
public periodStart: Date; public periodStart: Date;
public periodEnd: Date; public periodEnd: Date;
public projectStateType: ProjectStateType
} }

View File

@ -0,0 +1,4 @@
export class SearchBarItem {
public id: string;
public label: string;
}

View File

@ -0,0 +1,4 @@
export enum ProjectStateType {
OnGoing = 0,
Finished = 1
}

View File

@ -4,6 +4,18 @@
<form *ngIf="formGroup" (ngSubmit)="formSubmit()" [formGroup]="formGroup"> <form *ngIf="formGroup" (ngSubmit)="formSubmit()" [formGroup]="formGroup">
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<table class="logo-table col-md-12">
<tr>
<td>
<img mat-card-avatar (click)='imgFileInput.click()' *ngIf="!formGroup.get('files') || !formGroup.get('files').value" [src]="host+'files/any?type=jpg'">
<img mat-card-avatar (click)='imgFileInput.click()' *ngIf="formGroup.get('files') && formGroup.get('files').value" [src]="host+'files/'+formGroup.get('files').value[0].id+'?location='+formGroup.get('files').value[0].location+'&type='+formGroup.get('files').value[0].type">
</td>
<td>
<input class="hidden" type="file" #imgFileInput (change)="previewImage($event)" accept="image/*" />
<!-- <app-fileuploader-component [form]="formGroup.get('files')" [label]="'FILE-UPLOADER.PROJECT'" [fileUploader]="uploaderService"></app-fileuploader-component> -->
</td>
</tr>
</table>
<div class="fill-space"></div> <div class="fill-space"></div>
<div *ngIf="!isNew"> <div *ngIf="!isNew">
<button *ngIf="!editMode && !isExternalProject()" mat-icon-button (click)="enableForm()"> <button *ngIf="!editMode && !isExternalProject()" mat-icon-button (click)="enableForm()">
@ -20,6 +32,9 @@
</mat-card-header> </mat-card-header>
<mat-card-content> <mat-card-content>
<div class="row"> <div class="row">
<mat-form-field class="col-md-12"> <mat-form-field class="col-md-12">
<input matInput placeholder="{{'PROJECT-EDITOR.FIELDS.LABEL' | translate}}" type="text" name="label" formControlName="label" <input matInput placeholder="{{'PROJECT-EDITOR.FIELDS.LABEL' | translate}}" type="text" name="label" formControlName="label"
required> required>
@ -62,28 +77,16 @@
<mat-error *ngIf="formGroup.get('description').errors?.backendError">{{errorModel.description}}</mat-error> <mat-error *ngIf="formGroup.get('description').errors?.backendError">{{errorModel.description}}</mat-error>
<mat-error *ngIf="formGroup.get('description').errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="formGroup.get('description').errors?.required">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<p>{{this.languageResolverService.getBy('editorLogo') | translate}}</p>
<table class="logo-table col-md-12">
<tr>
<td>
<img mat-card-avatar *ngIf="!formGroup.get('files') || !formGroup.get('files').value" [src]="host+'files/any?type=jpg'">
<img mat-card-avatar *ngIf="formGroup.get('files') && formGroup.get('files').value" [src]="host+'files/'+formGroup.get('files').value[0].id+'?location='+formGroup.get('files').value[0].location+'&type='+formGroup.get('files').value[0].type">
</td>
<td>
<app-fileuploader-component [form]="formGroup.get('files')" [label]="'FILE-UPLOADER.PROJECT'" [fileUploader]="uploaderService"></app-fileuploader-component>
</td>
</tr>
</table>
<div class="col-md-12"> <div class="col-md-12">
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto right-button">
<button mat-raised-button color="primary" (click)="cancel()" type="button">{{'PROJECT-EDITOR.ACTIONS.CANCEL' | translate}}</button> <button mat-raised-button color="primary" (click)="cancel()" type="button">{{'PROJECT-EDITOR.ACTIONS.CANCEL' | translate}}</button>
</div> </div>
<div class="col-auto"> <div class="col-auto right-button">
<button *ngIf="isNew || editMode" mat-raised-button color="primary" type="submit">{{'PROJECT-EDITOR.ACTIONS.SAVE' | translate}}</button> <button *ngIf="isNew || editMode" mat-raised-button color="primary" type="submit">{{'PROJECT-EDITOR.ACTIONS.SAVE' | translate}}</button>
</div> </div>
<div class="col-auto"> <div class="col-auto right-button">
<button *ngIf="!isNew && editMode" mat-raised-button color="primary" type="button" (click)="delete()">{{'PROJECT-EDITOR.ACTIONS.DELETE' | translate}}</button> <button *ngIf="!isNew && editMode" mat-raised-button color="primary" type="button" (click)="delete()">{{'PROJECT-EDITOR.ACTIONS.DELETE' | translate}}</button>
</div> </div>
</div> </div>

View File

@ -42,3 +42,8 @@
h3{ h3{
margin-top: 0px; margin-top: 0px;
} }
.hidden {
display: none !important;
}

View File

@ -185,4 +185,19 @@ export class ProjectEditorComponent implements OnInit, IBreadCrumbComponent {
public isExternalProject() { public isExternalProject() {
return this.project.type === ProjectType.External; return this.project.type === ProjectType.External;
} }
public previewImage(event): void {
let fileList: FileList | File = event.target.files;
let formdata: FormData = new FormData();
if (fileList instanceof FileList) {
for (let i: number = 0; i < fileList.length; i++) {
formdata.append('file', fileList[i]);
}
} else {
formdata.append('file', fileList);
}
this.uploaderService.uploadFile(formdata).subscribe(files => this.formGroup.get('files').patchValue(files));
}
} }

View File

@ -14,6 +14,7 @@ import { LanguageService } from '../../services/language/language.service';
import { LanguageResolverService } from '../../services/language-resolver/language-resolver.service'; import { LanguageResolverService } from '../../services/language-resolver/language-resolver.service';
import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item'; import { BreadcrumbItem } from '../../shared/components/breadcrumb/definition/breadcrumb-item';
import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent'; import { IBreadCrumbComponent } from '../../shared/components/breadcrumb/definition/IBreadCrumbComponent';
import { ProjectStateType } from '../../models/projects/ProjectStateType';
@Component({ @Component({
selector: 'app-project-listing-component', selector: 'app-project-listing-component',
@ -61,6 +62,7 @@ export class ProjectListingComponent implements OnInit, IBreadCrumbComponent {
getDefaultCriteria(): ProjectCriteria { getDefaultCriteria(): ProjectCriteria {
const defaultCriteria = new ProjectCriteria(); const defaultCriteria = new ProjectCriteria();
defaultCriteria.projectStateType = ProjectStateType.OnGoing;
return defaultCriteria; return defaultCriteria;
} }
} }

View File

@ -5,6 +5,7 @@ import { HostConfiguration } from './../../app.constants';
import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service'; import { BaseHttpService } from '../../utilities/cite-http-service-module/base-http.service';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { DashboardStatisticsModel } from '../../models/dashboard/DashboardStatisticsModel'; import { DashboardStatisticsModel } from '../../models/dashboard/DashboardStatisticsModel';
import { SearchBarItem } from '../../models/dashboard/SearchBarItem';
@ -12,24 +13,28 @@ import { DashboardStatisticsModel } from '../../models/dashboard/DashboardStatis
@Injectable() @Injectable()
export class DashboardService { export class DashboardService {
private actionUrl: string; private actionUrl: string;
private headers: HttpHeaders; private headers: HttpHeaders;
constructor(private http: BaseHttpService) { constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'dashboard/'; this.actionUrl = HostConfiguration.Server + 'dashboard/';
this.headers = new HttpHeaders(); this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json'); this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json'); this.headers = this.headers.set('Accept', 'application/json');
} }
getStatistics(): Observable<DashboardStatisticsModel> { getStatistics(): Observable<DashboardStatisticsModel> {
return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'getStatistics', { headers: this.headers }); return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'getStatistics', { headers: this.headers });
} }
getStatisticsSpecificuser(): Observable<DashboardStatisticsModel> { getStatisticsSpecificuser(): Observable<DashboardStatisticsModel> {
return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'me/getStatistics', { headers: this.headers }); return this.http.get<DashboardStatisticsModel>(this.actionUrl + 'me/getStatistics', { headers: this.headers });
} }
searchUserItems(like: string): Observable<SearchBarItem[]> {
return this.http.get<SearchBarItem[]>(this.actionUrl + 'search?like=' + like, { headers: this.headers });
}
} }

View File

@ -17,51 +17,55 @@ import { DatasetProfileModel } from '../../models/datasets/DatasetProfileModel';
@Injectable() @Injectable()
export class DataManagementPlanService { export class DataManagementPlanService {
private actionUrl: string; private actionUrl: string;
private headers: HttpHeaders; private headers: HttpHeaders;
constructor(private http: BaseHttpService) { constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'dmps/'; this.actionUrl = HostConfiguration.Server + 'dmps/';
this.headers = new HttpHeaders(); this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json'); this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json'); this.headers = this.headers.set('Accept', 'application/json');
} }
getPaged(dataTableRequest: DataTableRequest<DataManagementPlanCriteria>): Observable<DataTableData<DataManagementPlanListingModel>> { getPaged(dataTableRequest: DataTableRequest<DataManagementPlanCriteria>): Observable<DataTableData<DataManagementPlanListingModel>> {
return this.http.post<DataTableData<DataManagementPlanListingModel>>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); return this.http.post<DataTableData<DataManagementPlanListingModel>>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers });
} }
getSingle(id: String): Observable<DataManagementPlanModel> { getSingle(id: String): Observable<DataManagementPlanModel> {
return this.http.get<DataManagementPlanModel>(this.actionUrl + 'getSingle/' + id, { headers: this.headers }); return this.http.get<DataManagementPlanModel>(this.actionUrl + 'getSingle/' + id, { headers: this.headers });
} }
createDataManagementPlan(dataManagementPlanModel: DataManagementPlanModel): Observable<DataManagementPlanModel> { createDataManagementPlan(dataManagementPlanModel: DataManagementPlanModel): Observable<DataManagementPlanModel> {
return this.http.post<DataManagementPlanModel>(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers }); return this.http.post<DataManagementPlanModel>(this.actionUrl + 'createOrUpdate', dataManagementPlanModel, { headers: this.headers });
} }
inactivate(id: String): Observable<DataManagementPlanModel> { inactivate(id: String): Observable<DataManagementPlanModel> {
return this.http.delete<DataManagementPlanModel>(this.actionUrl + 'inactivate/' + id, { headers: this.headers }); return this.http.delete<DataManagementPlanModel>(this.actionUrl + 'inactivate/' + id, { headers: this.headers });
} }
searchDMPProfiles(dataSetProfileRequest: RequestItem<DatasetProfileCriteria>): Observable<DatasetProfileModel[]> { searchDMPProfiles(dataSetProfileRequest: RequestItem<DatasetProfileCriteria>): Observable<DatasetProfileModel[]> {
return this.http.post<DatasetProfileModel[]>(this.actionUrl + "datasetprofiles/get", dataSetProfileRequest, { headers: this.headers }); return this.http.post<DatasetProfileModel[]>(this.actionUrl + "datasetprofiles/get", dataSetProfileRequest, { headers: this.headers });
} }
newVersion(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable<DataManagementPlanModel> { newVersion(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable<DataManagementPlanModel> {
return this.http.post<DataManagementPlanModel>(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers }); return this.http.post<DataManagementPlanModel>(this.actionUrl + 'new/' + id, dataManagementPlanModel, { headers: this.headers });
} }
clone(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable<DataManagementPlanModel> { clone(dataManagementPlanModel: DataManagementPlanModel, id: String): Observable<DataManagementPlanModel> {
return this.http.post<DataManagementPlanModel>(this.actionUrl + 'clone/' + id, dataManagementPlanModel, { headers: this.headers }); return this.http.post<DataManagementPlanModel>(this.actionUrl + 'clone/' + id, dataManagementPlanModel, { headers: this.headers });
} }
delete(id: String): Observable<DataManagementPlanModel> { delete(id: String): Observable<DataManagementPlanModel> {
return this.http.delete<DataManagementPlanModel>(this.actionUrl + 'delete/' + id, { headers: this.headers }); return this.http.delete<DataManagementPlanModel>(this.actionUrl + 'delete/' + id, { headers: this.headers });
} }
getDynamicField(requestItem: RequestItem<DatasetProfileCriteria>): any { getDynamicField(requestItem: RequestItem<DatasetProfileCriteria>): any {
return this.http.post<any>(this.actionUrl + "dynamic", requestItem, { headers: this.headers }) return this.http.post<any>(this.actionUrl + "dynamic", requestItem, { headers: this.headers })
} }
get(requestItem: RequestItem<DataManagementPlanCriteria>): Observable<DataManagementPlanListingModel[]> {
return this.http.post<DataManagementPlanListingModel[]>(this.actionUrl + 'get', requestItem, { headers: this.headers });
}
} }

View File

@ -36,6 +36,10 @@ export class UserReferenceService {
return this.http.post<DataTableData<UserListingModel>>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers }); return this.http.post<DataTableData<UserListingModel>>(this.actionUrl + 'getPaged', JSON.stringify(dataTableRequest), { headers: this.headers });
} }
getUser(id: String): Observable<UserListingModel> {
return this.http.get<UserListingModel>(this.actionUrl + id, { headers: this.headers });
}
updateRoles(itemToUpdate: UserListingModel): Observable<UserListingModel> { updateRoles(itemToUpdate: UserListingModel): Observable<UserListingModel> {
return this.http.post<UserListingModel>(this.actionUrl + 'updateRoles', JSON.stringify(itemToUpdate), { headers: this.headers }); return this.http.post<UserListingModel>(this.actionUrl + 'updateRoles', JSON.stringify(itemToUpdate), { headers: this.headers });
} }

View File

@ -1,5 +1,5 @@
<mat-form-field class="multiple-auto-complete"> <mat-form-field class="multiple-auto-complete">
<mat-chip-list #chipList ngDefaultControl [disabled]="reactiveFormControl.disabled" [formControl]="reactiveFormControl"> <mat-chip-list #chipList ngDefaultControl [required]='required' [disabled]="reactiveFormControl.disabled" [formControl]="reactiveFormControl">
<mat-chip *ngFor="let selectedItem of _chipItems()" [disabled]="reactiveFormControl.disabled" [selectable]="selectable" [removable]="removable" (removed)="_removeSelectedItem(selectedItem)"> <mat-chip *ngFor="let selectedItem of _chipItems()" [disabled]="reactiveFormControl.disabled" [selectable]="selectable" [removable]="removable" (removed)="_removeSelectedItem(selectedItem)">
{{this._displayFn(selectedItem)}} {{this._displayFn(selectedItem)}}
<mat-icon matChipRemove *ngIf="!reactiveFormControl.disabled && removable">cancel</mat-icon> <mat-icon matChipRemove *ngIf="!reactiveFormControl.disabled && removable">cancel</mat-icon>

View File

@ -22,7 +22,7 @@ export class MultipleAutoCompleteComponent implements OnInit {
@Input() placeholder: string; @Input() placeholder: string;
@Input() validationErrorString: string; @Input() validationErrorString: string;
@Input() configuration: MultipleAutoCompleteConfiguration; @Input() configuration: MultipleAutoCompleteConfiguration;
@Input() required: boolean;
// Selected Option Event // Selected Option Event
@Output() optionSelected: EventEmitter<any> = new EventEmitter(); @Output() optionSelected: EventEmitter<any> = new EventEmitter();
@ -135,9 +135,11 @@ export class MultipleAutoCompleteComponent implements OnInit {
} }
_removeSelectedItem(item: any): void { _removeSelectedItem(item: any): void {
const index = this.reactiveFormControl.value.indexOf(item); let autocompleteValue = this.reactiveFormControl.value;
const index = autocompleteValue.indexOf(item);
if (index >= 0) { if (index >= 0) {
this.reactiveFormControl.value.splice(index, 1); autocompleteValue.splice(index, 1);
this.reactiveFormControl.patchValue(autocompleteValue)
} }
} }

View File

@ -1,5 +1,5 @@
<mat-form-field class="auto-complete"> <mat-form-field class="auto-complete">
<input matInput [placeholder]="placeholder" [matAutocomplete]="auto" [formControl]="reactiveFormControl" (focus)="_onInputFocus()"> <input matInput [placeholder]="placeholder" [matAutocomplete]="auto" [required]='required' [formControl]="reactiveFormControl" (focus)="_onInputFocus()">
<mat-error *ngIf="validationErrorString">{{validationErrorString}}</mat-error> <mat-error *ngIf="validationErrorString">{{validationErrorString}}</mat-error>
<mat-error *ngIf="reactiveFormControl.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="reactiveFormControl.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="reactiveFormControl.hasError('invalidJson')">{{'GENERAL.VALIDATION.INVALID-JSON' | translate}}</mat-error> <mat-error *ngIf="reactiveFormControl.hasError('invalidJson')">{{'GENERAL.VALIDATION.INVALID-JSON' | translate}}</mat-error>

View File

@ -16,7 +16,7 @@ export class SingleAutoCompleteComponent implements OnInit {
@Input() reactiveFormControl: FormControl; @Input() reactiveFormControl: FormControl;
@Input() placeholder: string; @Input() placeholder: string;
@Input() validationErrorString: string; @Input() validationErrorString: string;
@Input() required: boolean;
@Input() configuration: SingleAutoCompleteConfiguration; @Input() configuration: SingleAutoCompleteConfiguration;
// Selected Option Event // Selected Option Event

View File

@ -1,5 +1,5 @@
<mat-selection-list #datasetsprofiles> <mat-selection-list #datasetsprofiles [ngModel]="selectedOptions">
<mat-list-option *ngFor="let profile of profiles" [value]="profile"> <mat-list-option *ngFor="let profile of profiles" [value]="profile" [selected]='isOptionSelected(profile)'>
{{profile.label}} {{profile.label}}
</mat-list-option> </mat-list-option>
</mat-selection-list> </mat-selection-list>

View File

@ -18,7 +18,7 @@ export class AvailableProfilesComponent implements OnInit {
public formGroup: FormGroup; public formGroup: FormGroup;
public profiles: DatasetProfileModel[] = []; public profiles: DatasetProfileModel[] = [];
public selectedProfiles: DatasetProfileModel[] = []; public selectedProfiles: DatasetProfileModel[] = [];
public selectedOptions: any
constructor( constructor(
private datasetService: DatasetService, private datasetService: DatasetService,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -27,20 +27,14 @@ export class AvailableProfilesComponent implements OnInit {
@Inject(MAT_DIALOG_DATA) public data: any @Inject(MAT_DIALOG_DATA) public data: any
) { } ) { }
ngOnInit(): void { ngOnInit(): void {
this.formGroup = this.data["profiles"]; this.formGroup = this.data["profiles"];
this.datasetService.getDatasetProfiles().subscribe(data => { this.datasetService.getDatasetProfiles().subscribe(data => {
this.profiles = JsonSerializer.fromJSONArray(data, DatasetProfileModel) this.profiles = JsonSerializer.fromJSONArray(data, DatasetProfileModel)
} })
)
} }
addProfiles(profiles) { addProfiles(profiles) {
// profiles.selectedOptions.forEach(element => {
// selectedProfiles.push(element.value)
// });
profiles.selectedOptions.selected.forEach(element => { profiles.selectedOptions.selected.forEach(element => {
let selectedElement = new DatasetProfileModel(); let selectedElement = new DatasetProfileModel();
selectedElement.id = element.value.id; selectedElement.id = element.value.id;
@ -50,4 +44,8 @@ export class AvailableProfilesComponent implements OnInit {
this.formGroup.setValue(this.selectedProfiles) this.formGroup.setValue(this.selectedProfiles)
this.dialogRef.close(); this.dialogRef.close();
} }
isOptionSelected(profile: any){
return this.formGroup.value.map(x=> x.id).indexOf(profile.id) !== -1
}
} }

View File

@ -8,24 +8,14 @@
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<mat-form-field> <mat-form-field>
<input matInput placeholder="{{'CRITERIA.DMP.LIKE'| translate}}" name="projectCriteriaLike" [(ngModel)]="criteria.like" (ngModelChange)="controlModified()"> <input matInput placeholder="{{'CRITERIA.DMP.LIKE'| translate}}" name="projectCriteriaLike" [formControl]="formGroup.get('like')" (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel?.like">{{baseErrorModel['Criteria.like']}}</mat-error> <mat-error *ngIf="baseErrorModel?.like">{{baseErrorModel['Criteria.like']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div *ngIf="showProject" class="col-md-6"> <div *ngIf="showProject" class="col-md-6">
<td-chips color="accent" [items]="filteredProjects" [(ngModel)]="criteria.projects" (ngModelChange)="controlModified()" placeholder="{{'CRITERIA.DMP.PROJECTS' | translate}}" <app-multiple-auto-complete class="col-md-10" [reactiveFormControl]="formGroup.get('projects')" placeholder="{{'CRITERIA.DMP.PROJECTS' | translate}}"
(inputChange)="filterProjects($event)" requireMatch> [configuration]="projectAutoCompleteConfiguration">
<ng-template td-chip let-chip="chip"> </app-multiple-auto-complete>
<div class="tc-grey-100 bgc-teal-700" td-chip-avatar>{{chip.label.substring(0, 1).toUpperCase()}}</div>
{{chip.label}}
</ng-template>
<ng-template td-autocomplete-option let-option="option">
<div layout="row" layout-align="start center">
{{option.label}}
</div>
</ng-template>
<mat-progress-bar [style.height.px]="2" *ngIf="filteringProjectsAsync" mode="indeterminate"></mat-progress-bar>
</td-chips>
</div> </div>
</div> </div>
</mat-card> </mat-card>

View File

@ -11,6 +11,7 @@ import { ProjectService } from '../../../../services/project/project.service';
import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria'; import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria';
import { RequestItem } from '../../../../models/criteria/RequestItem'; import { RequestItem } from '../../../../models/criteria/RequestItem';
import { create } from 'domain'; import { create } from 'domain';
import { MultipleAutoCompleteConfiguration } from '../../autocompletes/multiple/multiple-auto-complete-configuration';
@Component({ @Component({
selector: 'app-dmp-criteria-component', selector: 'app-dmp-criteria-component',
@ -22,9 +23,13 @@ export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent i
@Input() @Input()
showProject: boolean; showProject: boolean;
public criteria: DataManagementPlanCriteria = new DataManagementPlanCriteria();
filteringProjectsAsync: boolean = false; filteringProjectsAsync: boolean = false;
filteredProjects: ProjectModel[]; filteredProjects: ProjectModel[];
projectAutoCompleteConfiguration: MultipleAutoCompleteConfiguration;
public formGroup = new FormBuilder().group({
like: new FormControl(),
projects: new FormControl()
});
constructor( constructor(
public language: TranslateService, public language: TranslateService,
@ -36,11 +41,24 @@ export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent i
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
if (this.criteria == null) { this.criteria = new DataManagementPlanCriteria(); }
this.projectAutoCompleteConfiguration = {
filterFn: this.filterProject.bind(this),
initialItems: (excludedItems: any[]) => this.filterProject('').map(result => result.filter(x => excludedItems.map(x => x.id).indexOf(x.id) == -1)),
displayFn: (item) => item["label"],
titleFn: (item) => item["label"],
//mapFn: (item) => new JsonSerializer<ProjectReference>().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()),
loadDataOnStart: true
};
this.formGroup.get('projects').valueChanges.subscribe(x => this.controlModified())
this.formGroup.get('like').valueChanges.subscribe(x => this.controlModified())
//if (this.criteria == null) { this.criteria = new DataManagementPlanCriteria(); }
} }
setCriteria(criteria: DataManagementPlanCriteria): void { setCriteria(criteria: DataManagementPlanCriteria): void {
this.criteria = criteria; this.formGroup.get('like').patchValue(criteria.like)
this.formGroup.get('projects').patchValue(criteria.projects)
} }
onCallbackError(error: any) { onCallbackError(error: any) {
@ -50,26 +68,16 @@ export class DataManagementPlanCriteriaComponent extends BaseCriteriaComponent i
controlModified(): void { controlModified(): void {
this.clearErrorModel(); this.clearErrorModel();
if (this.refreshCallback != null && if (this.refreshCallback != null &&
(this.criteria.like == null || this.criteria.like.length == 0 || this.criteria.like.length > 2) (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length == 0 || this.formGroup.get('like').value.length > 2)
) { ) {
this.refreshCallback(); this.refreshCallback();
} }
} }
filterProjects(value: string): void { filterProject(query: string) {
let projectRequestItem: RequestItem<ProjectCriteria> = new RequestItem();
this.filteredProjects = undefined; projectRequestItem.criteria = new ProjectCriteria();
if (value) { projectRequestItem.criteria.like = query;
this.filteringProjectsAsync = true; return this.projectService.getWithExternal(projectRequestItem);
let requestItem: RequestItem<ProjectCriteria> = new RequestItem();
let criteria: ProjectCriteria = new ProjectCriteria();
criteria.like = value;
requestItem.criteria = criteria;
this.projectService.get(requestItem).subscribe(items => {
this.filteredProjects = items;
this.filteringProjectsAsync = false;
});
}
} }
} }

View File

@ -1,11 +1,11 @@
<div class="row"> <div class="row">
<!-- <h4 class="col-md-12">{{'CRITERIA.FILTERS'| translate}}</h4> --> <!-- <h4 class="col-md-12">{{'CRITERIA.FILTERS'| translate}}</h4> -->
<mat-form-field class="col-md-4"> <mat-form-field class="col-md-3">
<input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="projectCriteriaLike" [(ngModel)]="criteria.like" <input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="projectCriteriaLike" [(ngModel)]="criteria.like"
(ngModelChange)="controlModified()"> (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel?.like">{{baseErrorModel['criteria.like']}}</mat-error> <mat-error *ngIf="baseErrorModel?.like">{{baseErrorModel['criteria.like']}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-4"> <mat-form-field class="col-md-3">
<input matInput (focus)="periodStartPicker.open()" (click)="periodStartPicker.open()" placeholder=" {{this.languageResolver.getBy('criteriaStart')| translate}}" <input matInput (focus)="periodStartPicker.open()" (click)="periodStartPicker.open()" placeholder=" {{this.languageResolver.getBy('criteriaStart')| translate}}"
[matDatepicker]="periodStartPicker" name="projectCriteriaPeriodStart" [(ngModel)]="criteria.periodStart" (ngModelChange)="controlModified()"> [matDatepicker]="periodStartPicker" name="projectCriteriaPeriodStart" [(ngModel)]="criteria.periodStart" (ngModelChange)="controlModified()">
<mat-datepicker-toggle matSuffix [for]="periodStartPicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="periodStartPicker"></mat-datepicker-toggle>
@ -13,11 +13,22 @@
</mat-form-field> </mat-form-field>
<mat-error *ngIf="baseErrorModel['criteria.periodStart']">{{baseErrorModel['criteria.periodStart']}}</mat-error> <mat-error *ngIf="baseErrorModel['criteria.periodStart']">{{baseErrorModel['criteria.periodStart']}}</mat-error>
<mat-form-field class="col-md-4"> <mat-form-field class="col-md-3">
<input matInput (focus)="periodEndPicker.open()" (click)="periodEndPicker.open()" name="projectCriteriaPeriodEnd" placeholder=" {{this.languageResolver.getBy('criteriaEnd')| translate}}" <input matInput (focus)="periodEndPicker.open()" (click)="periodEndPicker.open()" name="projectCriteriaPeriodEnd" placeholder=" {{this.languageResolver.getBy('criteriaEnd')| translate}}"
[matDatepicker]="periodEndPicker" [(ngModel)]="criteria.periodEnd" (ngModelChange)="controlModified()"> [matDatepicker]="periodEndPicker" [(ngModel)]="criteria.periodEnd" (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel['criteria.periodEnd']">{{baseErrorModel['criteria.periodEnd']}}</mat-error> <mat-error *ngIf="baseErrorModel['criteria.periodEnd']">{{baseErrorModel['criteria.periodEnd']}}</mat-error>
<mat-datepicker-toggle matSuffix [for]="periodEndPicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="periodEndPicker"></mat-datepicker-toggle>
<mat-datepicker #periodEndPicker></mat-datepicker> <mat-datepicker #periodEndPicker></mat-datepicker>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3">
<mat-select placeholder=" {{ 'CRITERIA.PROJECTS.PROJECT-STATE-TYPE' | translate}}" [(ngModel)]="criteria.projectStateType" (ngModelChange)="controlModified()" >
<mat-option [value]="ProjectStateType.OnGoing">
{{ 'CRITERIA.PROJECTS.TYPES.ON-GOING' | translate}}
</mat-option>
<mat-option [value]="ProjectStateType.Finished">
{{ 'CRITERIA.PROJECTS.TYPES.FINISHED' | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div> </div>

View File

@ -7,6 +7,7 @@ import { BackendErrorValidator } from '../../../../utilities/validators/BackendE
import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria'; import { ProjectCriteria } from '../../../../models/criteria/project/ProjectCriteria';
import { ProjectCriteriaErrorModel } from '../../../../models/criteria/project/ProjectCriteriaErrorModel'; import { ProjectCriteriaErrorModel } from '../../../../models/criteria/project/ProjectCriteriaErrorModel';
import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service';
import { ProjectStateType } from '../../../../models/projects/ProjectStateType';
@Component({ @Component({
selector: 'app-projects-criteria-component', selector: 'app-projects-criteria-component',
@ -19,7 +20,7 @@ import { LanguageResolverService } from '../../../../services/language-resolver/
export class ProjectCriteriaComponent extends BaseCriteriaComponent implements OnInit { export class ProjectCriteriaComponent extends BaseCriteriaComponent implements OnInit {
// public form: ProjectType; // public form: ProjectType;
// public formStatus: ProjectStatus; public ProjectStateType = ProjectStateType;
public criteria: ProjectCriteria = new ProjectCriteria(); public criteria: ProjectCriteria = new ProjectCriteria();
constructor( constructor(

View File

@ -1,17 +1,21 @@
<div> <div>
<div class="suggestions"> <div class="container">
<div fxLayout="row"> <div class="row">
<mat-form-field class="fxItems"> <div class="col-md-5">
<mat-select placeholder="Sources" [(ngModel)]="choice" (selectionChange)="selectionChange($event)"> <mat-form-field >
<mat-option *ngFor="let option of options" [value]="option.key"> <mat-select placeholder="Sources" [(ngModel)]="choice" (selectionChange)="selectionChange($event)">
{{ option.label }} <mat-option *ngFor="let option of options" [value]="option.key">
</mat-option> {{ option.label }}
</mat-select> </mat-option>
</mat-form-field> </mat-select>
<app-external-item class="fxItems" [autoCompleteConfiguration]="autoCompleteConfiguration" [formGroup]="formGroup" [displayFunction]="displayFunction" </mat-form-field>
[placeholder]="placeholder" [subtitleFunction]="subtitleFunction" (onItemChange)="this.onItemChangeFunc($event)" [formCtrl]="formControl" </div>
[disabled]="disabled"> <div>
</app-external-item> <app-external-item class="col-md-7" [autoCompleteConfiguration]="autoCompleteConfiguration" [formGroup]="formGroup" [displayFunction]="displayFunction"
[placeholder]="placeholder" [subtitleFunction]="subtitleFunction" (onItemChange)="this.onItemChangeFunc($event)" [formCtrl]="formControl"
[disabled]="disabled">
</app-external-item>
</div>
</div> </div>
<div fxLayout="row" *ngFor="let suggestion of formGroup['controls']; let i = index"> <div fxLayout="row" *ngFor="let suggestion of formGroup['controls']; let i = index">
<ng-container *ngTemplateOutlet="parentTemplate; context: { $implicit: suggestion, index: i,function: this.deleteItem.bind(this) }"> <ng-container *ngTemplateOutlet="parentTemplate; context: { $implicit: suggestion, index: i,function: this.deleteItem.bind(this) }">

View File

@ -3,11 +3,10 @@
position: relative; position: relative;
width: 100%; width: 100%;
margin: 25px 0; margin: 25px 0;
cursor: pointer;
} }
.card-content { .card-content {
text-align: right; text-align: center;
padding: 15px 20px 13px 20px; padding: 15px 20px 13px 20px;
} }
@ -20,6 +19,7 @@
border-radius: 3px; border-radius: 3px;
padding: 15px; padding: 15px;
position: relative; position: relative;
cursor: pointer;
} }
.card-header i { .card-header i {
@ -62,4 +62,4 @@
border-radius: 6px; border-radius: 6px;
color: rgba(0, 0, 0, 0.87); color: rgba(0, 0, 0, 0.87);
background: #fff; background: #fff;
} }

View File

@ -1,10 +1,11 @@
<div class="figure-card card" (click)="navigateToUrl()"> <div class="figure-card card">
<div class="card-header" [ngStyle]="{ 'background': linearColor, 'box-shadow': boxShadow }"> <div class="card-header" (click)="navigateToUrl()" [ngStyle]="{ 'background': linearColor, 'box-shadow': boxShadow }">
<i class="material-icons">{{ headerIcon }}</i> <i class="material-icons">{{ headerIcon }}</i>
</div> </div>
<div class="card-content"> <div class="card-content">
<p class="category">{{ category | translate }}</p> <p class="category">{{ category | translate }}</p>
<h3 class="title">{{ title }}</h3> <h3 class="title">{{ title }}</h3>
<button mat-raised-button color="primary" (click)="createNew()" >{{buttonTitle}}</button>
</div> </div>
<div *ngIf="hasFootContent" class="card-footer"> <div *ngIf="hasFootContent" class="card-footer">
</div> </div>

View File

@ -16,6 +16,8 @@ export class FigurecardComponent implements OnInit {
@Input() boxShadow: string; @Input() boxShadow: string;
@Input() routelLink: string; @Input() routelLink: string;
@Input() hasFootContent = true; @Input() hasFootContent = true;
@Input() buttonTitle: string;
@Input() buttonRedirectLink: string;
constructor(private router: Router) { } constructor(private router: Router) { }
@ -24,7 +26,10 @@ export class FigurecardComponent implements OnInit {
navigateToUrl() { navigateToUrl() {
this.router.navigate([this.routelLink]); this.router.navigate([this.routelLink]);
}
} createNew(){
this.router.navigate([this.buttonRedirectLink]);
}
} }

View File

@ -1,5 +1,5 @@
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<a [fxLayoutAlign]="'center'" class="app-logo" routerLink="/"> <a class="app-logo" routerLink="/">
<img [src]="'/assets/images/openDmps.png'" alt="openDMPS"> <img [src]="'/assets/images/openDmps.png'" alt="openDMPS">
</a> </a>
<div *ngIf="isAuthenticated()"> <div *ngIf="isAuthenticated()">
@ -13,15 +13,33 @@
<!--<button mat-button class="navbar-button" routerLink="/about">{{'NAV-BAR.ABOUT' | translate}}</button>--> <!--<button mat-button class="navbar-button" routerLink="/about">{{'NAV-BAR.ABOUT' | translate}}</button>-->
<span class="navbar-spacer"></span> <span class="navbar-spacer"></span>
<div *ngIf="isAuthenticated();else loginoption"> <div fxFlex *ngIf="search">
<img mat-card-avatar *ngIf="this.principalHasAvatar()" [src]="this.getPrincipalAvatar()"> <mat-form-field class="full-width">
<span class="user-label">{{this.getPrincipalName()}}</span> <input type="text" placeholder="{{'DASHBOARD.SEARCH' | translate}}" matInput [formControl]="searchControl" [matAutocomplete]="auto">
<button mat-icon-button (click)="logout()"> <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete" (optionSelected)="onOptionSelected($event)">
<mat-icon>exit_to_app</mat-icon> <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
</button> {{option.label}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div> </div>
<div fxLayout="row">
<div fxFlex *ngIf="!search">
<button mat-button (click)="this.search = true">
<mat-icon>search</mat-icon>
</button>
</div>
<div fxFlex *ngIf="search">
<button mat-button (click)="this.search = false">
<mat-icon>close</mat-icon>
</button>
</div>
<div fxFlex *ngIf="isAuthenticated();else loginoption">
<img mat-card-avatar *ngIf="this.principalHasAvatar()" [src]="this.getPrincipalAvatar()" (click)="openProfile()">
</div>
</div>
<ng-template #loginoption> <ng-template #loginoption>
<button mat-button [routerLink]=" ['/login'] "> <button mat-button [routerLink]=" ['/login'] ">
<span class="login-label">Log in</span> <span class="login-label">Log in</span>

View File

@ -28,4 +28,12 @@
.logo { .logo {
width: 38px; width: 38px;
height: 38px; height: 38px;
} }
.user-profile{
width: 10%;
}
.full-width {
width: 100%;
}

View File

@ -3,19 +3,65 @@ import { Component, EventEmitter, Input, Output, ElementRef } from '@angular/cor
import { Principal } from '../../../models/login/Principal'; import { Principal } from '../../../models/login/Principal';
import { AuthService } from '../../../services/auth/auth.service'; import { AuthService } from '../../../services/auth/auth.service';
import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service'; import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service';
import { MatSidenav } from '@angular/material'; import { MatSidenav, MatDialog } from '@angular/material';
import { UserDialogComponent } from '../user-dialog/user-dialog.component';
import { SingleAutoCompleteConfiguration } from '../autocompletes/single/single-auto-complete-configuration';
import { ProjectCriteria } from '../../../models/criteria/project/ProjectCriteria';
import { RequestItem } from '../../../models/criteria/RequestItem';
import { ProjectService } from '../../../services/project/project.service';
import { FormControl } from '@angular/forms';
import { DashboardService } from '../../../services/dashboard/dashboard.service';
import { Observable } from 'rxjs/Observable';
import { SearchBarItem } from '../../../models/dashboard/SearchBarItem';
import { SearchBarType } from '../search-bar/types/search-bar-type';
import { Router } from '@angular/router';
@Component({ @Component({
selector: 'app-navigation', selector: 'app-navigation',
templateUrl: 'navigation.component.html', templateUrl: 'navigation.component.html',
styleUrls: ['./navigation.component.css'], styleUrls: ['./navigation.component.scss'],
providers: [ProjectService]
}) })
export class NavigationComponent { export class NavigationComponent {
invert = false; invert = false;
public search = false;
projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
public searchControl = new FormControl();
filteredOptions: Observable<SearchBarItem[]>;
constructor(private authentication: AuthService, private languageResolver: LanguageResolverService) { constructor(
private authentication: AuthService,
private languageResolver: LanguageResolverService,
public dialog: MatDialog,
private projectService: ProjectService,
private dashBoardService: DashboardService,
private router: Router,
) {
}
ngOnInit() {
this.projectAutoCompleteConfiguration = {
filterFn: this.searchProject.bind(this),
items: this.searchProject(''),
displayFn: (item) => item["label"],
titleFn: (item) => item["label"],
//mapFn: (item) => new JsonSerializer<ProjectReference>().fromJSONArray(item, ProjectReference).map(item => item.toDropdownList()),
loadDataOnStart: true
};
this.filteredOptions = this.searchControl.valueChanges.flatMap(x => {
return this.dashBoardService.searchUserItems(x);
})
}
searchProject(query: string) {
let projectRequestItem: RequestItem<ProjectCriteria> = new RequestItem();
projectRequestItem.criteria = new ProjectCriteria();
projectRequestItem.criteria.like = query;
return this.projectService.getWithExternal(projectRequestItem);
} }
public logout(): void { public logout(): void {
@ -46,12 +92,6 @@ export class NavigationComponent {
return false; return false;
} }
public getPrincipalName(): string {
const principal: Principal = this.authentication.current();
if (principal) { return principal.name; }
return '';
}
public principalHasAvatar(): boolean { public principalHasAvatar(): boolean {
return this.authentication.current().avatarUrl != null; return this.authentication.current().avatarUrl != null;
} }
@ -63,4 +103,23 @@ export class NavigationComponent {
onSideNavClick() { onSideNavClick() {
this.sideNav.toggle(); this.sideNav.toggle();
} }
openProfile() {
let dialogRef = this.dialog.open(UserDialogComponent, {
hasBackdrop: true,
closeOnNavigation: true,
disableClose: false,
position: { top: "64px", left: "85%" }
});
}
onOptionSelected(event: any) {
this.search = false;
this.searchControl.patchValue(null);
let selectedSearchBarItem = event.option.value;
if (selectedSearchBarItem.type == SearchBarType.DATASET) this.router.navigate(["datasets/edit/" + selectedSearchBarItem.id])
if (selectedSearchBarItem.type == SearchBarType.PROJECT) this.router.navigate(["projects/edit/" + selectedSearchBarItem.id])
if (selectedSearchBarItem.type == SearchBarType.DATAMANAGEMENTPLAN) this.router.navigate(["dmps/edit/" + selectedSearchBarItem.id])
}
} }

View File

@ -0,0 +1,17 @@
import { sample } from 'rxjs/operators';
import { Component, EventEmitter, Input, Output, ElementRef } from '@angular/core';
import { Principal } from '../../../models/login/Principal';
import { AuthService } from '../../../services/auth/auth.service';
import { LanguageResolverService } from '../../../services/language-resolver/language-resolver.service';
import { MatSidenav, MatDialog } from '@angular/material';
import { UserDialogComponent } from '../user-dialog/user-dialog.component';
@Component({
selector: 'app-search',
templateUrl: 'navigation.component.html',
styleUrls: ['./navigation.component.scss'],
})
export class SearchBarComponent {
}

View File

@ -0,0 +1,5 @@
export enum SearchBarType {
DATASET = 0,
DATAMANAGEMENTPLAN = 1,
PROJECT = 2
}

View File

@ -0,0 +1,24 @@
<form>
<div mat-dialog-title>
<img mat-card-avatar *ngIf="this.principalHasAvatar()" [src]="this.getPrincipalAvatar()">
<span class="user-label">{{this.getPrincipalName()}}</span>
</div>
<div mat-dialog-content>
<mat-divider></mat-divider>
{{'USER-DIALOG.USER-PROFILE' | translate}}
<button mat-icon-button (click)="navigateToProfile()">
<mat-icon>person</mat-icon>
</button>
<mat-divider></mat-divider>
</div>
<div mat-dialog-actions>
<div layout="row" class="full-width text-right" align="end">
{{'USER-DIALOG.EXIT' | translate}}
<button mat-icon-button (click)="logout()">
<mat-icon>exit_to_app</mat-icon>
</button>
</div>
</div>
</form>

View File

@ -0,0 +1,54 @@
import { JsonSerializer } from '../../../utilities/JsonSerializer';
import { RequestItem } from '../../../models/criteria/RequestItem';
import { Component, OnInit, Inject } from "@angular/core";
import { FormGroup } from '@angular/forms';
import { Params, ActivatedRoute, Router } from '@angular/router';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { ResearcherModel } from '../../../models/researcher/ResearcherModel';
import { ResearcherService } from '../../../services/researchers/researchers.service';
import { AuthService } from '../../../services/auth/auth.service';
import { Principal } from '../../../models/login/Principal';
@Component({
selector: 'user-dialog-component',
templateUrl: 'user-dialog.component.html',
})
export class UserDialogComponent implements OnInit {
public formGroup: FormGroup;
constructor(
private route: ActivatedRoute,
private authentication: AuthService,
public router: Router,
public dialogRef: MatDialogRef<UserDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) { }
ngOnInit(): void {
}
public logout(): void {
this.dialogRef.close();
this.authentication.logout();
}
public getPrincipalName(): string {
const principal: Principal = this.authentication.current();
if (principal) { return principal.name; }
return '';
}
public principalHasAvatar(): boolean {
return this.authentication.current().avatarUrl != null;
}
public getPrincipalAvatar(): string {
return this.authentication.current().avatarUrl;
}
public navigateToProfile() {
this.router.navigate(["/users/" + this.authentication.current().id]);
}
}

View File

@ -28,7 +28,8 @@ import {
MatRadioModule, MatRadioModule,
MatMenuModule, MatMenuModule,
MatListModule, MatListModule,
MatChipsModule MatChipsModule,
MatBadgeModule
} from '@angular/material'; } from '@angular/material';
import { CdkTableModule } from '@angular/cdk/table'; import { CdkTableModule } from '@angular/cdk/table';
import { SnackBarNotificationComponent } from '../components/notificaiton/snack-bar-notification.component'; import { SnackBarNotificationComponent } from '../components/notificaiton/snack-bar-notification.component';
@ -71,7 +72,8 @@ import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, Coval
MatRadioModule, MatRadioModule,
MatMenuModule, MatMenuModule,
MatListModule, MatListModule,
MatChipsModule MatChipsModule,
MatBadgeModule
], ],
providers: [ providers: [

View File

@ -23,6 +23,7 @@ import { ExternalItemComponent } from './components/external-items/external-item
import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component'; import { BreadcrumbComponent } from './components/breadcrumb/breadcrumb.component';
import { SingleAutoCompleteComponent } from './components/autocompletes/single/single-auto-complete.component'; import { SingleAutoCompleteComponent } from './components/autocompletes/single/single-auto-complete.component';
import { MultipleAutoCompleteComponent } from './components/autocompletes/multiple/multiple-auto-complete.component'; import { MultipleAutoCompleteComponent } from './components/autocompletes/multiple/multiple-auto-complete.component';
import { UserDialogComponent } from './components/user-dialog/user-dialog.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -52,7 +53,8 @@ import { MultipleAutoCompleteComponent } from './components/autocompletes/multip
ExternalItemComponent, ExternalItemComponent,
BreadcrumbComponent, BreadcrumbComponent,
SingleAutoCompleteComponent, SingleAutoCompleteComponent,
MultipleAutoCompleteComponent MultipleAutoCompleteComponent,
UserDialogComponent
], ],
exports: [ exports: [
@ -75,9 +77,11 @@ import { MultipleAutoCompleteComponent } from './components/autocompletes/multip
ExternalItemComponent, ExternalItemComponent,
BreadcrumbComponent, BreadcrumbComponent,
SingleAutoCompleteComponent, SingleAutoCompleteComponent,
MultipleAutoCompleteComponent MultipleAutoCompleteComponent,
UserDialogComponent
], ],
entryComponents: [ entryComponents: [
UserDialogComponent
] ]
}) })

View File

@ -1,27 +1,4 @@
<div class="container row"> <div class="container row">
<div class="col-md-3">
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>
{{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-nav-list *ngIf="projectActivities!=null">
<mat-list-item (click)="redirect(activity.id,RecentActivityTypes.PROJECT)" *ngFor="let activity of projectActivities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div>
<div class="col-md-3"> <div class="col-md-3">
<mat-card class="example-card"> <mat-card class="example-card">
<mat-card-header> <mat-card-header>
@ -43,6 +20,28 @@
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div> </div>
<div class="col-md-3">
<mat-card class="example-card">
<mat-card-header>
<mat-card-title>
{{'RECENT-ACTIVITY.MY-TITLE-PROJECT' | translate}}
</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-nav-list *ngIf="projectActivities!=null">
<mat-list-item (click)="redirect(activity.id,RecentActivityTypes.PROJECT)" *ngFor="let activity of projectActivities">
<p mat-line>
{{activity.label}}
</p>
<p mat-line>
{{activity.timestamp | date:'shortDate'}}
</p>
</mat-list-item>
</mat-nav-list>
</mat-card-content>
</mat-card>
</div>
<div class="col-md-3"> <div class="col-md-3">
<mat-card class="example-card"> <mat-card class="example-card">
<mat-card-header> <mat-card-header>

View File

@ -0,0 +1,37 @@
<div *ngIf="user | async as userProfile; else loading">
<mat-card class="example-card">
<mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex>
<img mat-card-avatar [src]="userProfile.additionalinfo.data.avatar.url">
</div>
<mat-card-title>{{userProfile.name}}</mat-card-title>
<mat-card-subtitle>{{userProfile.email}}</mat-card-subtitle>
</div>
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex>
<h4>{{ 'USER-PROFILE.ASSOCIATED-DMPS' | translate}}</h4>
</div>
<div>
{{userProfile.associatedDmps}}
</div>
</div>
</mat-card-content>
</mat-card>
<mat-card>
<mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex>
<h4>{{ 'USER-PROFILE.SETTINGS' | translate}}</h4>
</div>
</div>
</mat-card-content>
</mat-card>
</div>
<ng-template #loading>
Loading stuff...
</ng-template>

View File

@ -0,0 +1,46 @@
import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { UserErrorModel } from '../../models/users/UserErrorModel';
import { UserReferenceService } from '../../services/user-reference/user-reference-data.service';
import { UserListingModel } from '../../models/users/UserListingModel';
import { SnackBarNotificationComponent } from '../../shared/components/notificaiton/snack-bar-notification.component';
import { UserCriteria } from '../../models/criteria/users/UserCriteria';
import { UserCriteriaErrorModel } from '../../models/criteria/users/UserCriteriaErrorModel';
import { Observable } from 'rxjs/Rx';
import { Component, OnInit, AfterViewInit, ViewChild } from '@angular/core';
import { UsersCriteriaComponent } from '../../shared/components/criteria/users/users-criteria.component';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { Principal } from '../../models/login/Principal';
import { MatPaginator, MatSort, MatSnackBar } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { DataSource } from '@angular/cdk/table';
import { RecentActivityTypes } from '../../users/activity/RecentActivityTypes';
import { AuthService } from '../../services/auth/auth.service';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss'],
providers: [
UserReferenceService
]
})
export class UserProfileComponent implements OnInit {
user: Observable<UserListingModel>;
constructor(
private userReferenceService: UserReferenceService,
private route: ActivatedRoute,
private authService: AuthService
) { }
ngOnInit() {
this.route.params.subscribe((params: Params) => {
let userId = params['id'] === this.authService.current().id ? 'me' : params['id']
this.user = this.userReferenceService.getUser(userId).map(result => { result["additionalinfo"] = JSON.parse(result["additionalinfo"]); return result })
})
}
}

View File

@ -16,6 +16,7 @@ import { RouterModule } from '@angular/router';
import { UsersRoutes } from './users.routes'; import { UsersRoutes } from './users.routes';
import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module'; import { BaseHttpModule } from '../utilities/cite-http-service-module/cite-http.module';
import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service'; import { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service';
import { UserProfileComponent } from './profile/user-profile.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -39,6 +40,7 @@ import { BaseHttpService } from '../utilities/cite-http-service-module/base-http
UsersComponent, UsersComponent,
UsersCriteriaComponent, UsersCriteriaComponent,
UserRoleEditorComponent, UserRoleEditorComponent,
UserProfileComponent
], ],
providers: [ providers: [
BaseHttpService, BaseHttpService,

View File

@ -1,6 +1,8 @@
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { UsersComponent } from './components/users.component'; import { UsersComponent } from './components/users.component';
import { UserProfileComponent } from './profile/user-profile.component';
export const UsersRoutes: Routes = [ export const UsersRoutes: Routes = [
{ path: '', component: UsersComponent } { path: '', component: UsersComponent },
{ path: ':id', component: UserProfileComponent }
]; ];

View File

@ -40,7 +40,7 @@
"START": "Start", "START": "Start",
"END": "End", "END": "End",
"ACTIONS": "Actions", "ACTIONS": "Actions",
"DMPS": "Dmps" "DMPS": "DMPs"
} }
}, },
"DMP-LISTING": { "DMP-LISTING": {
@ -160,7 +160,7 @@
"DESCRIPTION": "Description", "DESCRIPTION": "Description",
"ORGANISATIONS": "Organisations", "ORGANISATIONS": "Organisations",
"RESEARCHERS": "Researchers", "RESEARCHERS": "Researchers",
"PROFILES": "Available Profiles", "PROFILES": "Available Dataset Profiles",
"PROFILE": "DMP Profile", "PROFILE": "DMP Profile",
"GRANT": "Grant", "GRANT": "Grant",
"FUNDER": "Funder" "FUNDER": "Funder"
@ -178,7 +178,12 @@
"PROJECTS": { "PROJECTS": {
"LIKE": "Search", "LIKE": "Search",
"PERIOD-FROM": "Project Start", "PERIOD-FROM": "Project Start",
"PERIOD-TO": "Project End" "PERIOD-TO": "Project End",
"PROJECT-STATE-TYPE": "Project Status",
"TYPES": {
"ON-GOING": "OnGoing",
"FINISHED": "Finished"
}
}, },
"DATA-SETS": { "DATA-SETS": {
"LIKE": "Search", "LIKE": "Search",
@ -281,7 +286,7 @@
}, },
"RECENT-ACTIVITY": { "RECENT-ACTIVITY": {
"MY-TITLE-PROJECT": "My Recent Project Activity", "MY-TITLE-PROJECT": "My Recent Project Activity",
"MY-TITLE-DMP": "My Recent Dmp Activity", "MY-TITLE-DMP": "My Recent DMP Activity",
"MY-TITLE-DATASET": "My Recent Dataset Activity" "MY-TITLE-DATASET": "My Recent Dataset Activity"
}, },
"FILE-UPLOADER": { "FILE-UPLOADER": {
@ -311,6 +316,15 @@
"MY-DMPS": "My DMPs", "MY-DMPS": "My DMPs",
"DMPS": "DMPs", "DMPS": "DMPs",
"MY-DATASETS": "My Datasets", "MY-DATASETS": "My Datasets",
"DATASETS": "Datasets" "DATASETS": "Datasets",
"SEARCH": "Search"
},
"USER-DIALOG": {
"USER-PROFILE": "My Profile",
"EXIT": "Exit "
},
"USER-PROFILE": {
"SETTINGS": "Settings",
"ASSOCIATED-DMPS": "Associated DMPs"
} }
} }