no message

This commit is contained in:
Ioannis Kalyvas 2018-08-30 14:09:36 +03:00
parent 42f6cfd273
commit b34c96b264
67 changed files with 4296 additions and 322 deletions

View File

@ -58,8 +58,11 @@ public class DatasetDaoImpl extends DatabaseAccess<Dataset> implements DatasetDa
@Override @Override
public QueryableList<Dataset> getAuthenticated(QueryableList<Dataset> query, UserInfo principal) { public QueryableList<Dataset> getAuthenticated(QueryableList<Dataset> query, UserInfo principal) {
query.where((builder, root) -> builder.or(builder.equal(root.get("dmp").get("creator"), principal), builder.isMember(principal, root.get("dmp").get("users")) if (principal.getId() == null) query.where((builder, root) -> builder.equal(root.get("isPublic"), true));
, builder.equal(root.get("isPublic"), true))); else {
query.where((builder, root) -> builder.or(builder.equal(root.get("dmp").get("creator"), principal), builder.isMember(principal, root.get("dmp").get("users"))
, builder.equal(root.get("isPublic"), true)));
}
return query; return query;
} }

View File

@ -19,9 +19,9 @@ public abstract class AbstractBatchLogger {
private Map<String, Object> concurrentHashMap = new ConcurrentHashMap<String, Object>(); private Map<String, Object> concurrentHashMap = new ConcurrentHashMap<String, Object>();
public AbstractBatchLogger(Environment environment) { public AbstractBatchLogger(Environment environment) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); //ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> this.outputData(), Long.parseLong(environment.getProperty("http-logger.initial-delay")), Long.parseLong(environment.getProperty("http-logger.delay")), TimeUnit.SECONDS); //executor.scheduleAtFixedRate(() -> this.outputData(), Long.parseLong(environment.getProperty("http-logger.initial-delay")), Long.parseLong(environment.getProperty("http-logger.delay")), TimeUnit.SECONDS);
} }
public abstract LoggingOutputType logOutputType(); public abstract LoggingOutputType logOutputType();

View File

@ -15,5 +15,9 @@ public class Main {
queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("id").greaterThan(5) ); queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("id").greaterThan(5) );
queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("label").equal("mitsos") ); queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("label").equal("mitsos") );
queryBuilder.toList(); queryBuilder.toList();
QueryBuilder<DataRepository> queryBuilder2 = new QueryBuilderImpl<>(DataRepository.class);
queryBuilder2.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("id").lessOrEqualThan(11111) );
queryBuilder2.toList();
} }
} }

View File

@ -1,17 +1,18 @@
package eu.eudat.controllers; package eu.eudat.controllers;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.Dataset;
import eu.eudat.data.query.items.item.dataset.DatasetWizardAutocompleteRequest;
import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileWizardAutocompleteRequest;
import eu.eudat.logic.managers.DatasetManager; import eu.eudat.logic.managers.DatasetManager;
import eu.eudat.logic.managers.DatasetWizardManager; import eu.eudat.logic.managers.DatasetWizardManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
import eu.eudat.models.data.datasetwizard.DataManagentPlanListingModel; import eu.eudat.models.data.datasetwizard.DataManagentPlanListingModel;
import eu.eudat.data.query.items.item.datasetprofile.DatasetProfileWizardAutocompleteRequest;
import eu.eudat.data.query.items.item.dataset.DatasetWizardAutocompleteRequest;
import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel;
import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.dmp.AssociatedProfile;
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;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.ApiMessageCode; import eu.eudat.types.ApiMessageCode;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -30,6 +31,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import static eu.eudat.types.Authorities.ANONYMOUS;
@RestController @RestController
@CrossOrigin @CrossOrigin
@ -59,7 +62,7 @@ public class DatasetWizardController extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = {"/getAvailableProfiles"}, produces = "application/json") @RequestMapping(method = RequestMethod.POST, value = {"/getAvailableProfiles"}, produces = "application/json")
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<List<AssociatedProfile>>> getAvailableProfiles(@RequestBody DatasetProfileWizardAutocompleteRequest datasetProfileWizardAutocompleteRequest, Principal principal) { ResponseEntity<ResponseItem<List<AssociatedProfile>>> getAvailableProfiles(@RequestBody DatasetProfileWizardAutocompleteRequest datasetProfileWizardAutocompleteRequest, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) {
try { try {
List<AssociatedProfile> dataManagementPlans = DatasetWizardManager.getAvailableProfiles(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetProfileWizardAutocompleteRequest); List<AssociatedProfile> dataManagementPlans = DatasetWizardManager.getAvailableProfiles(this.getApiContext().getOperationsContext().getDatabaseRepository().getDmpDao(), datasetProfileWizardAutocompleteRequest);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<AssociatedProfile>>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<AssociatedProfile>>().status(ApiMessageCode.NO_MESSAGE).payload(dataManagementPlans));
@ -72,10 +75,10 @@ public class DatasetWizardController extends BaseController {
@RequestMapping(method = RequestMethod.GET, value = {"/getSingle/{id}"}, produces = "application/json") @RequestMapping(method = RequestMethod.GET, value = {"/getSingle/{id}"}, produces = "application/json")
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, Principal principal) { ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) {
try { try {
DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(),this.getApiContext().getOperationsContext().getDatasetRepository() DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), this.getApiContext().getOperationsContext().getDatasetRepository()
,id); , id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -1,14 +1,16 @@
package eu.eudat.controllers; package eu.eudat.controllers;
import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.Dataset;
import eu.eudat.logic.managers.DatasetManager;
import eu.eudat.data.query.items.table.dataset.DatasetTableRequest; import eu.eudat.data.query.items.table.dataset.DatasetTableRequest;
import eu.eudat.logic.managers.DatasetManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.common.DataTableData;
import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.listingmodels.DatasetListingModel; import eu.eudat.models.data.listingmodels.DatasetListingModel;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.ApiMessageCode; import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.Authorities;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -31,7 +33,7 @@ public class Datasets extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = {"/datasets/getPaged"}, consumes = "application/json", produces = "application/json") @RequestMapping(method = RequestMethod.POST, value = {"/datasets/getPaged"}, consumes = "application/json", produces = "application/json")
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<DataTableData<DatasetListingModel>>> getPaged(@RequestBody DatasetTableRequest datasetTableRequest, Principal principal) { ResponseEntity<ResponseItem<DataTableData<DatasetListingModel>>> getPaged(@RequestBody DatasetTableRequest datasetTableRequest, @ClaimedAuthorities(claims = {Authorities.ANONYMOUS}) Principal principal) {
try { try {
DataTableData<DatasetListingModel> dataTable = new DatasetManager().getPaged(this.getApiContext(), datasetTableRequest, principal); DataTableData<DatasetListingModel> dataTable = new DatasetManager().getPaged(this.getApiContext(), datasetTableRequest, principal);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DataTableData<DatasetListingModel>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable)); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DataTableData<DatasetListingModel>>().status(ApiMessageCode.NO_MESSAGE).payload(dataTable));

View File

@ -1,13 +1,13 @@
package eu.eudat.controllers; package eu.eudat.controllers;
import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
import eu.eudat.logic.managers.UserManager; import eu.eudat.logic.managers.UserManager;
import eu.eudat.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.helpers.common.DataTableData; import eu.eudat.models.data.helpers.common.DataTableData;
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;
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.services.ApiContext;
import eu.eudat.models.data.userinfo.UserProfile; 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;
@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static eu.eudat.types.Authorities.ADMIN; import static eu.eudat.types.Authorities.ADMIN;
@ -70,6 +70,19 @@ public class Users extends BaseController {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<UserProfile>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage())); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<UserProfile>().status(ApiMessageCode.DEFAULT_ERROR_MESSAGE).message(ex.getMessage()));
} }
} }
@Transactional
@RequestMapping(method = RequestMethod.POST, value = {"/settings"}, produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<UserProfile>> saveSettings(@RequestBody Map<String, Object> settings, Principal principal) {
try {
UserManager.updateSettings(this.getApiContext(), settings, principal);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<UserProfile>().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

@ -19,6 +19,9 @@ public class PrincipalBuilder extends Builder<Principal> {
private Date expiresAt; private Date expiresAt;
private String avatarUrl; private String avatarUrl;
private Set<Authorities> authorities; private Set<Authorities> authorities;
private String culture;
private String language;
private String timezone;
public PrincipalBuilder id(UUID id) { public PrincipalBuilder id(UUID id) {
this.id = id; this.id = id;
@ -50,6 +53,21 @@ public class PrincipalBuilder extends Builder<Principal> {
return this; return this;
} }
public PrincipalBuilder culture(String culture) {
this.culture = culture;
return this;
}
public PrincipalBuilder language(String language) {
this.language = language;
return this;
}
public PrincipalBuilder timezone(String timezone) {
this.timezone = timezone;
return this;
}
@Override @Override
public Principal build() { public Principal build() {
Principal principal = new Principal(); Principal principal = new Principal();
@ -59,6 +77,9 @@ public class PrincipalBuilder extends Builder<Principal> {
principal.setToken(token); principal.setToken(token);
principal.setId(id); principal.setId(id);
principal.setAvatarUrl(avatarUrl); principal.setAvatarUrl(avatarUrl);
principal.setCulture(culture);
principal.setLanguage(language);
principal.setTimezone(timezone);
return principal; return principal;
} }
} }

View File

@ -32,7 +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 && claimList.size() == 1 && 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 {
@ -43,7 +43,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
Principal principal = this.authenticationService.Touch(authToken); Principal principal = this.authenticationService.Touch(authToken);
if (principal == null) throw new UnauthorisedException("Authentication Information Missing"); if (principal == null) throw new UnauthorisedException("Authentication Information Missing");
if (!principal.isAuthorized(claimList)) if (!claimList.contains(Authorities.ANONYMOUS) && !principal.isAuthorized(claimList))
throw new UnauthorisedException("You are not Authorized For this Action"); throw new UnauthorisedException("You are not Authorized For this Action");
return principal; return principal;
} }

View File

@ -1,5 +1,6 @@
package eu.eudat.logic.managers; package eu.eudat.logic.managers;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.UserRole; import eu.eudat.data.entities.UserRole;
import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem; import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
@ -16,10 +17,14 @@ import eu.eudat.models.data.security.Principal;
import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.models.data.userinfo.UserListingModel;
import eu.eudat.models.data.userinfo.UserProfile; import eu.eudat.models.data.userinfo.UserProfile;
import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.QueryableList;
import org.json.JSONObject;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import java.io.IOException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -60,6 +65,17 @@ public class UserManager {
} }
} }
public static void updateSettings(ApiContext apiContext, Map<String, Object> settings, Principal principal) throws IOException {
eu.eudat.data.entities.UserInfo userInfo = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(principal.getId());
apiContext.getOperationsContext().getDatabaseRepository().detachEntity(userInfo);
HashMap<String, Object> result =
new ObjectMapper().readValue(userInfo.getAdditionalinfo(), HashMap.class);
result.putAll(settings);
userInfo.setAdditionalinfo(new JSONObject(result).toString());
apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao()
.createOrUpdate(userInfo);
}
public static Principal authenticate(AuthenticationServiceImpl authenticationServiceImpl, Credentials credentials) { public static Principal authenticate(AuthenticationServiceImpl authenticationServiceImpl, Credentials credentials) {
Principal principal = authenticationServiceImpl.Touch(credentials); Principal principal = authenticationServiceImpl.Touch(credentials);
if (principal == null) throw new UnauthorisedException("Could not Sign In User"); if (principal == null) throw new UnauthorisedException("Could not Sign In User");

View File

@ -1,11 +1,16 @@
package eu.eudat.logic.security.validators; package eu.eudat.logic.security.validators;
import eu.eudat.logic.security.customproviders.B2AccessCustomProvider;
import eu.eudat.logic.security.validators.b2access.B2AccessTokenValidator; import eu.eudat.logic.security.validators.b2access.B2AccessTokenValidator;
import eu.eudat.logic.security.validators.facebook.FacebookTokenValidator; import eu.eudat.logic.security.validators.facebook.FacebookTokenValidator;
import eu.eudat.logic.security.validators.google.GoogleTokenValidator; import eu.eudat.logic.security.validators.google.GoogleTokenValidator;
import eu.eudat.logic.security.validators.linkedin.LinkedInTokenValidator; import eu.eudat.logic.security.validators.linkedin.LinkedInTokenValidator;
import eu.eudat.logic.security.validators.twitter.TwitterTokenValidator; import eu.eudat.logic.security.validators.twitter.TwitterTokenValidator;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.AuthenticationService;
import eu.eudat.logic.services.operations.AuthenticationServiceImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -44,34 +49,31 @@ public class TokenValidatorFactoryImpl implements TokenValidatorFactory {
} }
} }
private GoogleTokenValidator googleTokenValidator; private ApiContext apiContext;
private FacebookTokenValidator facebookTokenValidator; private Environment environment;
private LinkedInTokenValidator linkedInTokenValidator; private AuthenticationServiceImpl authenticationService;
private TwitterTokenValidator twitterTokenValidator; private B2AccessCustomProvider b2AccessCustomProvider;
private B2AccessTokenValidator b2AccessTokenValidator;
@Autowired @Autowired
public TokenValidatorFactoryImpl(GoogleTokenValidator googleTokenValidator, FacebookTokenValidator facebookTokenValidator, public TokenValidatorFactoryImpl(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationService, B2AccessCustomProvider b2AccessCustomProvider) {
LinkedInTokenValidator linkedInTokenValidator, TwitterTokenValidator twitterTokenValidator, B2AccessTokenValidator b2AccessTokenValidator) { this.apiContext = apiContext;
this.googleTokenValidator = googleTokenValidator; this.environment = environment;
this.facebookTokenValidator = facebookTokenValidator; this.authenticationService = authenticationService;
this.linkedInTokenValidator = linkedInTokenValidator; this.b2AccessCustomProvider = b2AccessCustomProvider;
this.twitterTokenValidator = twitterTokenValidator;
this.b2AccessTokenValidator = b2AccessTokenValidator;
} }
public TokenValidator getProvider(LoginProvider provider) { public TokenValidator getProvider(LoginProvider provider) {
switch (provider) { switch (provider) {
case GOOGLE: case GOOGLE:
return this.googleTokenValidator; return new GoogleTokenValidator(this.apiContext, this.environment, this.authenticationService);
case FACEBOOK: case FACEBOOK:
return this.facebookTokenValidator; return new FacebookTokenValidator(this.apiContext, this.environment, this.authenticationService);
case LINKEDIN: case LINKEDIN:
return this.linkedInTokenValidator; return new LinkedInTokenValidator(this.apiContext, this.environment, this.authenticationService);
case TWITTER: case TWITTER:
return this.twitterTokenValidator; return new TwitterTokenValidator(this.apiContext, this.environment, this.authenticationService);
case B2_ACCESS: case B2_ACCESS:
return this.b2AccessTokenValidator; return new B2AccessTokenValidator(this.environment, this.authenticationService, this.b2AccessCustomProvider);
default: default:
throw new RuntimeException("Login Provider Not Implemented"); throw new RuntimeException("Login Provider Not Implemented");
} }

View File

@ -28,7 +28,7 @@ public class B2AccessTokenValidator implements TokenValidator {
private Environment environment; private Environment environment;
@Autowired @Autowired
public B2AccessTokenValidator(AuthenticationServiceImpl authenticationServiceImpl, Environment environment, B2AccessCustomProvider b2AccessCustomProvider) { public B2AccessTokenValidator(Environment environment, AuthenticationServiceImpl authenticationServiceImpl, B2AccessCustomProvider b2AccessCustomProvider) {
this.authenticationServiceImpl = authenticationServiceImpl; this.authenticationServiceImpl = authenticationServiceImpl;
this.environment = environment; this.environment = environment;
this.b2AccessCustomProvider = b2AccessCustomProvider; this.b2AccessCustomProvider = b2AccessCustomProvider;

View File

@ -31,7 +31,7 @@ public class FacebookTokenValidator implements TokenValidator {
private FacebookServiceProvider facebookServiceProvider; private FacebookServiceProvider facebookServiceProvider;
@Autowired @Autowired
public FacebookTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) { public FacebookTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment; this.environment = environment;
this.apiContext = apiContext; this.apiContext = apiContext;
this.authenticationServiceImpl = authenticationServiceImpl; this.authenticationServiceImpl = authenticationServiceImpl;

View File

@ -2,13 +2,13 @@ package eu.eudat.logic.security.validators.linkedin;
import eu.eudat.exceptions.security.NonValidTokenException; import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.security.validators.TokenValidator; import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl; import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
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;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.social.linkedin.api.LinkedIn; import org.springframework.social.linkedin.api.LinkedIn;
@ -30,7 +30,7 @@ public class LinkedInTokenValidator implements TokenValidator {
private LinkedInServiceProvider linkedInServiceProvider; private LinkedInServiceProvider linkedInServiceProvider;
@Autowired @Autowired
public LinkedInTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) { public LinkedInTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment; this.environment = environment;
this.apiContext = apiContext; this.apiContext = apiContext;
this.authenticationServiceImpl = authenticationServiceImpl; this.authenticationServiceImpl = authenticationServiceImpl;

View File

@ -2,13 +2,13 @@ package eu.eudat.logic.security.validators.twitter;
import eu.eudat.exceptions.security.NonValidTokenException; import eu.eudat.exceptions.security.NonValidTokenException;
import eu.eudat.exceptions.security.UnauthorisedException; import eu.eudat.exceptions.security.UnauthorisedException;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.security.validators.TokenValidator; import eu.eudat.logic.security.validators.TokenValidator;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl; import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
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;
import eu.eudat.models.data.login.LoginInfo;
import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.social.oauth1.AuthorizedRequestToken; import org.springframework.social.oauth1.AuthorizedRequestToken;
@ -32,7 +32,7 @@ public class TwitterTokenValidator implements TokenValidator {
private TwitterServiceProvider twitterServiceProvider; private TwitterServiceProvider twitterServiceProvider;
@Autowired @Autowired
public TwitterTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) { public TwitterTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment; this.environment = environment;
this.apiContext = apiContext; this.apiContext = apiContext;
this.authenticationServiceImpl = authenticationServiceImpl; this.authenticationServiceImpl = authenticationServiceImpl;
@ -55,7 +55,7 @@ public class TwitterTokenValidator implements TokenValidator {
user.setEmail((String) values.get("email")); user.setEmail((String) values.get("email"));
user.setAvatarUrl(profile.getProfileImageUrl()); user.setAvatarUrl(profile.getProfileImageUrl());
user.setIsVerified(true); //TODO user.setIsVerified(true); //TODO
user.setId(""+profile.getId()); user.setId("" + profile.getId());
user.setName(profile.getName()); user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.TWITTER); user.setProvider(TokenValidatorFactoryImpl.LoginProvider.TWITTER);
user.setSecret(finalOauthToken.getValue()); user.setSecret(finalOauthToken.getValue());

View File

@ -1,21 +1,22 @@
package eu.eudat.logic.services.operations; package eu.eudat.logic.services.operations;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.builders.entity.CredentialBuilder;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.builders.entity.UserTokenBuilder;
import eu.eudat.logic.builders.model.models.PrincipalBuilder;
import eu.eudat.data.dao.criteria.UserInfoCriteria; import eu.eudat.data.dao.criteria.UserInfoCriteria;
import eu.eudat.data.entities.Credential; import eu.eudat.data.entities.Credential;
import eu.eudat.data.entities.UserInfo; import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole; import eu.eudat.data.entities.UserRole;
import eu.eudat.data.entities.UserToken; import eu.eudat.data.entities.UserToken;
import eu.eudat.logic.builders.entity.CredentialBuilder;
import eu.eudat.logic.builders.entity.UserInfoBuilder;
import eu.eudat.logic.builders.entity.UserTokenBuilder;
import eu.eudat.logic.builders.model.models.PrincipalBuilder;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.login.Credentials; import eu.eudat.models.data.login.Credentials;
import eu.eudat.models.data.loginprovider.LoginProviderUser; import eu.eudat.models.data.loginprovider.LoginProviderUser;
import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.security.validators.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.Authorities; import eu.eudat.types.Authorities;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -53,17 +54,39 @@ public class AuthenticationServiceImpl implements AuthenticationService {
UserInfo user = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(token.getUser().getId()); UserInfo user = this.apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(token.getUser().getId());
if (user == null) return null; if (user == null) return null;
String json; String avatarUrl;
try { try {
json = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("data").get("avatar").get("url").asText() : ""; avatarUrl = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("avatarUrl").asText() : "";
} catch (IOException e) { } catch (Exception e) {
json = ""; avatarUrl = "";
}
String culture;
try {
culture = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("culture").get("name").asText() : "";
} catch (Exception e) {
culture = "";
}
String language;
try {
language = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("language").get("value").asText() : "";
} catch (Exception e) {
language = "";
}
String timezone;
try {
timezone = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("timezone").asText() : "";
} catch (Exception e) {
timezone = "";
} }
Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class) Principal principal = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(PrincipalBuilder.class)
.id(user.getId()).token(token.getToken()) .id(user.getId()).token(token.getToken())
.expiresAt(token.getExpiresAt()).name(user.getName()) .expiresAt(token.getExpiresAt()).name(user.getName())
.avatarUrl(json) .avatarUrl(avatarUrl)
.culture(culture)
.language(language)
.timezone(timezone)
.build(); .build();
List<UserRole> userRoles = apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user); List<UserRole> userRoles = apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user);
for (UserRole item : userRoles) { for (UserRole item : userRoles) {
if (principal.getAuthz() == null) principal.setAuthorities(new HashSet<>()); if (principal.getAuthz() == null) principal.setAuthorities(new HashSet<>());
@ -120,7 +143,7 @@ public class AuthenticationServiceImpl implements AuthenticationService {
userInfo = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class) userInfo = this.apiContext.getOperationsContext().getBuilderFactory().getBuilder(UserInfoBuilder.class)
.name(profile.getName()).verified_email(profile.getIsVerified()) .name(profile.getName()).verified_email(profile.getIsVerified())
.email(profile.getEmail()).created(new Date()).lastloggedin(new Date()) .email(profile.getEmail()).created(new Date()).lastloggedin(new Date())
.additionalinfo("{\"data\":{\"avatar\":{\"url\":\""+profile.getAvatarUrl()+"\"}}}") .additionalinfo("{\"data\":{\"avatar\":{\"url\":\"" + profile.getAvatarUrl() + "\"}}}")
.authorization_level((short) 1).usertype((short) 1) .authorization_level((short) 1).usertype((short) 1)
.build(); .build();
@ -135,8 +158,11 @@ public class AuthenticationServiceImpl implements AuthenticationService {
apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(role); apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(role);
} else { } else {
Map<String, Object> additionalInfo = userInfo.getAdditionalinfo() != null ?
new JSONObject(userInfo.getAdditionalinfo()).toMap() : new HashMap<>();
additionalInfo.put("avatarUrl", profile.getAvatarUrl());
userInfo.setLastloggedin(new Date()); userInfo.setLastloggedin(new Date());
userInfo.setAdditionalinfo("{\"data\":{\"avatar\":{\"url\":\""+profile.getAvatarUrl()+"\"}}}"); userInfo.setAdditionalinfo(new JSONObject(additionalInfo).toString());
Set<Credential> credentials = userInfo.getCredentials(); Set<Credential> credentials = userInfo.getCredentials();
if (credentials.contains(credential)) { if (credentials.contains(credential)) {
Credential oldCredential = credentials.stream().filter(item -> credential.getProvider().equals(item.getProvider())).findFirst().get(); Credential oldCredential = credentials.stream().filter(item -> credential.getProvider().equals(item.getProvider())).findFirst().get();

View File

@ -45,4 +45,6 @@ public interface DatabaseRepository {
DatasetExternalDatasetDao getDatasetExternalDatasetDao(); DatasetExternalDatasetDao getDatasetExternalDatasetDao();
DatasetServiceDao getDatasetServiceDao(); DatasetServiceDao getDatasetServiceDao();
<T> void detachEntity(T entity);
} }

View File

@ -239,4 +239,8 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
public void setDatasetServiceDao(DatasetServiceDao datasetServiceDao) { public void setDatasetServiceDao(DatasetServiceDao datasetServiceDao) {
this.datasetServiceDao = datasetServiceDao; this.datasetServiceDao = datasetServiceDao;
} }
public <T> void detachEntity(T entity) {
this.entityManager.detach(entity);
}
} }

View File

@ -23,7 +23,7 @@ public class OperationsContextImpl implements OperationsContext {
@Autowired @Autowired
public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher
, BuilderFactory builderFactory, FileStorageService fileStorageService,DatasetRepository datasetRepository) { , BuilderFactory builderFactory, FileStorageService fileStorageService, DatasetRepository datasetRepository) {
this.databaseRepository = databaseRepository; this.databaseRepository = databaseRepository;
this.applicationContext = applicationContext; this.applicationContext = applicationContext;
this.remoteFetcher = remoteFetcher; this.remoteFetcher = remoteFetcher;

View File

@ -6,6 +6,7 @@ import eu.eudat.data.dao.entities.InvitationDao;
import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.Invitation; import eu.eudat.data.entities.Invitation;
import javax.mail.MessagingException;
import java.util.List; import java.util.List;
@ -14,7 +15,7 @@ public interface InvitationService {
void assignToDmp(DMPDao dmpDao, eu.eudat.data.entities.UserInfo user, DMP dmp); void assignToDmp(DMPDao dmpDao, eu.eudat.data.entities.UserInfo user, DMP dmp);
void createInvitations(InvitationDao invitationDao, MailService mailService, List<eu.eudat.data.entities.UserInfo> users, DMP dmp, eu.eudat.data.entities.UserInfo creator); void createInvitations(InvitationDao invitationDao, MailService mailService, List<eu.eudat.data.entities.UserInfo> users, DMP dmp, eu.eudat.data.entities.UserInfo creator) throws MessagingException;
void sendInvitation(DMP dmp, Invitation invitation, MailService mailService); void sendInvitation(DMP dmp, Invitation invitation, String recipient, MailService mailService) throws MessagingException;
} }

View File

@ -7,6 +7,7 @@ import eu.eudat.data.entities.Invitation;
import eu.eudat.models.data.mail.SimpleMail; import eu.eudat.models.data.mail.SimpleMail;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -28,7 +29,7 @@ public class InvitationServiceImpl implements InvitationService {
} }
@Override @Override
public void createInvitations(InvitationDao invitationDao, MailService mailService, List<eu.eudat.data.entities.UserInfo> users, DMP dmp, eu.eudat.data.entities.UserInfo creator) { public void createInvitations(InvitationDao invitationDao, MailService mailService, List<eu.eudat.data.entities.UserInfo> users, DMP dmp, eu.eudat.data.entities.UserInfo creator) throws MessagingException {
for (eu.eudat.data.entities.UserInfo userInfo : users) { for (eu.eudat.data.entities.UserInfo userInfo : users) {
Invitation invitation = new Invitation(); Invitation invitation = new Invitation();
invitation.setDmp(dmp); invitation.setDmp(dmp);
@ -37,15 +38,15 @@ public class InvitationServiceImpl implements InvitationService {
invitation.setToken(UUID.randomUUID()); invitation.setToken(UUID.randomUUID());
invitation.setAcceptedInvitation(false); invitation.setAcceptedInvitation(false);
invitationDao.createOrUpdate(invitation); invitationDao.createOrUpdate(invitation);
sendInvitation(dmp, invitation, mailService); sendInvitation(dmp, invitation, userInfo.getName(), mailService);
} }
} }
@Override @Override
public void sendInvitation(DMP dmp, Invitation invitation, MailService mailService) { public void sendInvitation(DMP dmp, Invitation invitation, String recipient, MailService mailService) throws MessagingException {
SimpleMail mail = new SimpleMail(); SimpleMail mail = new SimpleMail();
mail.setSubject(createSubject(dmp, mailService.getMailTemplateSubject())); mail.setSubject(createSubject(dmp, mailService.getMailTemplateSubject()));
mail.setContent(createContent(invitation.getId(), dmp, mailService.getMailTemplateContent())); mail.setContent(createContent(invitation.getId(), dmp, recipient, mailService.getMailTemplateContent()));
mail.setTo(invitation.getInvitationEmail()); mail.setTo(invitation.getInvitationEmail());
mailService.sendSimpleMail(mail); mailService.sendSimpleMail(mail);
} }
@ -55,9 +56,11 @@ public class InvitationServiceImpl implements InvitationService {
return subject; return subject;
} }
private String createContent(UUID invitationID, DMP dmp, String templateContent) { private String createContent(UUID invitationID, DMP dmp, String recipient, String templateContent) {
String content = templateContent.replace("{dmpname}", dmp.getLabel()); String content = templateContent.replace("{dmpname}", dmp.getLabel());
content = content.replace("{invitationID}", invitationID.toString()); content = content.replace("{invitationID}", invitationID.toString());
content = content.replace("{recipient}", recipient);
return content; return content;
} }
} }

View File

@ -2,9 +2,11 @@ package eu.eudat.logic.services.utilities;
import eu.eudat.models.data.mail.SimpleMail; import eu.eudat.models.data.mail.SimpleMail;
import javax.mail.MessagingException;
public interface MailService { public interface MailService {
void sendSimpleMail(SimpleMail mail); void sendSimpleMail(SimpleMail mail) throws MessagingException;
String getMailTemplateContent(); String getMailTemplateContent();

View File

@ -1,27 +1,42 @@
package eu.eudat.logic.services.utilities; package eu.eudat.logic.services.utilities;
import eu.eudat.models.data.mail.SimpleMail; import eu.eudat.models.data.mail.SimpleMail;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.mail.SimpleMailMessage; import org.springframework.core.io.Resource;
import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
@Service("mailService") @Service("mailService")
public class MailServiceImpl implements MailService { public class MailServiceImpl implements MailService {
@Autowired
private Environment env; private Environment env;
@Autowired
private JavaMailSender emailSender; private JavaMailSender emailSender;
private ApplicationContext applicationContext;
@Autowired
public MailServiceImpl(Environment env, JavaMailSender emailSender, ApplicationContext applicationContext) {
this.env = env;
this.emailSender = emailSender;
this.applicationContext = applicationContext;
}
@Override @Override
public void sendSimpleMail(SimpleMail mail) { public void sendSimpleMail(SimpleMail mail) throws MessagingException {
SimpleMailMessage message = new SimpleMailMessage(); MimeMessage message = this.emailSender.createMimeMessage();
message.setSubject(mail.getSubject()); message.setSubject(mail.getSubject());
message.setText(mail.getContent()); message.setText(mail.getContent(), "utf-8", "html");
message.setTo(mail.getTo()); message.addRecipients(Message.RecipientType.TO, mail.getTo());
message.setFrom(env.getProperty("mail.from")); message.setFrom(env.getProperty("mail.from"));
this.emailSender.send(message); this.emailSender.send(message);
} }
@ -31,8 +46,17 @@ public class MailServiceImpl implements MailService {
} }
@Override @Override
public String getMailTemplateContent() { public String getMailTemplateContent() {
return env.getProperty("mail.content"); Resource resource = applicationContext.getResource("classpath:email.html");
try {
InputStream inputStream = resource.getInputStream();
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
return writer.toString();
} catch (IOException e) {
e.printStackTrace();
}
return "";
} }
@Override @Override

View File

@ -14,6 +14,9 @@ public class Principal {
private Date expiresAt; private Date expiresAt;
private String avatarUrl; private String avatarUrl;
private Set<Authorities> authorities; private Set<Authorities> authorities;
private String culture;
private String language;
private String timezone;
public UUID getId() { public UUID getId() {
return id; return id;
@ -59,6 +62,30 @@ public class Principal {
return authorities.stream().map(authz -> authz.getValue()).collect(Collectors.toSet()); return authorities.stream().map(authz -> authz.getValue()).collect(Collectors.toSet());
} }
public String getCulture() {
return culture;
}
public void setCulture(String culture) {
this.culture = culture;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
@JsonIgnore @JsonIgnore
public Set<Authorities> getAuthz() { public Set<Authorities> getAuthz() {
return this.authorities; return this.authorities;

View File

@ -0,0 +1,28 @@
package eu.eudat.models.validators.fluentvalidator;
import eu.eudat.models.validators.fluentvalidator.predicates.FieldSelector;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
/**
* Created by ikalyvas on 8/28/2018.
*/
public class FluentValidator<T> implements Validator {
private T item;
public <R> void ruleFor(FieldSelector<T, R> selector) {
selector.apply(this.item);
}
@Override
public boolean supports(Class<?> clazz) {
return this.item.getClass().equals(clazz);
}
@Override
public void validate(Object target, Errors errors) {
this.item = (T) target;
}
}

View File

@ -0,0 +1,8 @@
package eu.eudat.models.validators.fluentvalidator.predicates;
/**
* Created by ikalyvas on 8/28/2018.
*/
public interface FieldSelector<T,R> {
R apply(T item);
}

View File

@ -30,7 +30,7 @@ spring.mail.test-connection=false
spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.enable=true
mail.subject=Invitation to DMP Plan {dmpname} mail.subject=Invitation to DMP Plan {dmpname}
mail.content=You have been invited to {dmpname} data management plan.Follow the link http://dl043.madgik.di.uoa.gr/invitation/{invitationID} to submit it mail.content=You have been invited to {dmpname} data management plan.Follow the link http://dl043.madgik.di.uoa.gr/dmps/invitation/{invitationID} to submit it
mail.from=citesagrdev@gmail.com mail.from=citesagrdev@gmail.com
########################FACEBOOK LOGIN Properties############################# ########################FACEBOOK LOGIN Properties#############################
facebook.login.clientId=110586756143149 facebook.login.clientId=110586756143149

View File

@ -0,0 +1,305 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Simple Transactional Email</title>
<style>
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%; }
body {
background-color: #f6f6f6;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%; }
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%; }
table td {
font-family: sans-serif;
font-size: 14px;
vertical-align: top; }
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: #f6f6f6;
width: 100%; }
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
.container {
display: block;
Margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px; }
/* This should also be a block element, so that it will fill 100% of the .container */
.content {
box-sizing: border-box;
display: block;
Margin: 0 auto;
max-width: 580px;
padding: 10px; }
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border-radius: 3px;
width: 100%; }
.wrapper {
box-sizing: border-box;
padding: 20px; }
.content-block {
padding-bottom: 10px;
padding-top: 10px;
}
.footer {
clear: both;
Margin-top: 10px;
text-align: center;
width: 100%; }
.footer td,
.footer p,
.footer span,
.footer a {
color: #999999;
font-size: 12px;
text-align: center; }
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3,
h4 {
color: #000000;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
Margin-bottom: 30px; }
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize; }
p,
ul,
ol {
font-family: sans-serif;
font-size: 14px;
font-weight: normal;
margin: 0;
Margin-bottom: 15px; }
p li,
ul li,
ol li {
list-style-position: inside;
margin-left: 5px; }
a {
color: #3498db;
text-decoration: underline; }
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%; }
.btn > tbody > tr > td {
padding-bottom: 15px; }
.btn table {
width: auto; }
.btn table td {
background-color: #ffffff;
border-radius: 5px;
text-align: center; }
.btn a {
background-color: #ffffff;
border: solid 1px #3498db;
border-radius: 5px;
box-sizing: border-box;
color: #3498db;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 25px;
text-decoration: none;
text-transform: capitalize; }
.btn-primary table td {
background-color: #3498db; }
.btn-primary a {
background-color: #3498db;
border-color: #3498db;
color: #ffffff; }
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0; }
.first {
margin-top: 0; }
.align-center {
text-align: center; }
.align-right {
text-align: right; }
.align-left {
text-align: left; }
.clear {
clear: both; }
.mt0 {
margin-top: 0; }
.mb0 {
margin-bottom: 0; }
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0; }
.powered-by a {
text-decoration: none; }
hr {
border: 0;
border-bottom: 1px solid #f6f6f6;
Margin: 20px 0; }
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important; }
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important; }
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important; }
table[class=body] .content {
padding: 0 !important; }
table[class=body] .container {
padding: 0 !important;
width: 100% !important; }
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important; }
table[class=body] .btn table {
width: 100% !important; }
table[class=body] .btn a {
width: 100% !important; }
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important; }}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%; }
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%; }
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important; }
.btn-primary table td:hover {
background-color: #34495e !important; }
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important; } }
</style>
</head>
<body class="">
<table border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">This is preheader text. Some clients will show this text as a preview.</span>
<table class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<p>Dear {recipient},</p>
<p>You have been invited to collaborate to Data Management plan {dmpname}.</p>
<p>Click the button to redirect to {dmpname}.</p>
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="left">
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="http://dl043.madgik.di.uoa.gr/dmps/invitation/{invitationID}" target="_blank">Join</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>

View File

@ -587,9 +587,26 @@
"dev": true "dev": true
}, },
"@angular/material": { "@angular/material": {
"version": "6.1.0", "version": "6.4.6",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@angular/material/-/material-6.4.6.tgz",
"integrity": "sha512-9FLWjVnHFzAoGSWU5dz8X/QYeBtZGijMJIp1k94QDYz+2xA10IbesEgnv8I5Ri3EPnjV/gCspeSkt1ClLc95CA==", "integrity": "sha512-SUSg9MhLv4IZj6Nh8qoCLDImZugCQ+Jvvt+/cDIaTn6TrT6ZenDHc6jOhbGFesU6FuBDBFIXMiuBPD9kBr7vaA==",
"requires": {
"parse5": "^5.0.0",
"tslib": "^1.7.1"
},
"dependencies": {
"parse5": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
"integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
"optional": true
}
}
},
"@angular/material-moment-adapter": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-6.4.6.tgz",
"integrity": "sha512-Bvj/zwtEjF1bqOF1z/M0VcWYOwlRjmCBjvPVmNZ1Bxf7HE8yyRf8B+AAv46sn/EhhAv/eMNU9bzFcxrR/vEHAg==",
"requires": { "requires": {
"tslib": "^1.7.1" "tslib": "^1.7.1"
} }
@ -716,9 +733,9 @@
"dev": true "dev": true
}, },
"@types/selenium-webdriver": { "@types/selenium-webdriver": {
"version": "2.53.43", "version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz", "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz",
"integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==", "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==",
"dev": true "dev": true
}, },
"@types/strip-bom": { "@types/strip-bom": {
@ -1027,9 +1044,9 @@
"optional": true "optional": true
}, },
"adm-zip": { "adm-zip": {
"version": "0.4.4", "version": "0.4.11",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
"integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=", "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
"dev": true "dev": true
}, },
"after": { "after": {
@ -1953,6 +1970,15 @@
"electron-to-chromium": "^1.3.47" "electron-to-chromium": "^1.3.47"
} }
}, },
"browserstack": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.1.tgz",
"integrity": "sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg==",
"dev": true,
"requires": {
"https-proxy-agent": "^2.2.1"
}
},
"buffer": { "buffer": {
"version": "4.9.1", "version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@ -4065,8 +4091,7 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -4087,14 +4112,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -4109,20 +4132,17 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -4239,8 +4259,7 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -4252,7 +4271,6 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -4267,7 +4285,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -4275,14 +4292,12 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -4301,7 +4316,6 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -4382,8 +4396,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -4395,7 +4408,6 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -4481,8 +4493,7 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -4518,7 +4529,6 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -4538,7 +4548,6 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -4582,14 +4591,12 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
} }
} }
}, },
@ -7903,6 +7910,19 @@
"minimist": "0.0.8" "minimist": "0.0.8"
} }
}, },
"moment": {
"version": "2.22.2",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
"integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y="
},
"moment-timezone": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz",
"integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==",
"requires": {
"moment": ">= 2.9.0"
}
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -8597,12 +8617,6 @@
} }
} }
}, },
"options": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz",
"integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=",
"dev": true
},
"original": { "original": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz", "resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz",
@ -9147,15 +9161,16 @@
} }
}, },
"protractor": { "protractor": {
"version": "5.3.2", "version": "5.4.0",
"resolved": "https://registry.npmjs.org/protractor/-/protractor-5.3.2.tgz", "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.0.tgz",
"integrity": "sha512-pw4uwwiy5lHZjIguxNpkEwJJa7hVz+bJsvaTI+IbXlfn2qXwzbF8eghW/RmrZwE2sGx82I8etb8lVjQ+JrjejA==", "integrity": "sha512-6TSYqMhUUzxr4/wN0ttSISqPMKvcVRXF4k8jOEpGWD8OioLak4KLgfzHK9FJ49IrjzRrZ+Mx1q2Op8Rk0zEcnQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "^6.0.46", "@types/node": "^6.0.46",
"@types/q": "^0.0.32", "@types/q": "^0.0.32",
"@types/selenium-webdriver": "~2.53.39", "@types/selenium-webdriver": "^3.0.0",
"blocking-proxy": "^1.0.0", "blocking-proxy": "^1.0.0",
"browserstack": "^1.5.1",
"chalk": "^1.1.3", "chalk": "^1.1.3",
"glob": "^7.0.3", "glob": "^7.0.3",
"jasmine": "2.8.0", "jasmine": "2.8.0",
@ -9165,15 +9180,21 @@
"saucelabs": "^1.5.0", "saucelabs": "^1.5.0",
"selenium-webdriver": "3.6.0", "selenium-webdriver": "3.6.0",
"source-map-support": "~0.4.0", "source-map-support": "~0.4.0",
"webdriver-js-extender": "^1.0.0", "webdriver-js-extender": "2.0.0",
"webdriver-manager": "^12.0.6" "webdriver-manager": "^12.0.6"
}, },
"dependencies": { "dependencies": {
"adm-zip": { "ajv": {
"version": "0.4.11", "version": "5.5.2",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"dev": true "dev": true,
"requires": {
"co": "^4.6.0",
"fast-deep-equal": "^1.0.0",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.3.0"
}
}, },
"ansi-styles": { "ansi-styles": {
"version": "2.2.1", "version": "2.2.1",
@ -9181,6 +9202,24 @@
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true "dev": true
}, },
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"dev": true
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
"dev": true
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
"dev": true
},
"chalk": { "chalk": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@ -9209,6 +9248,23 @@
"rimraf": "^2.2.8" "rimraf": "^2.2.8"
} }
}, },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"dev": true
},
"form-data": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "1.0.6",
"mime-types": "^2.1.12"
}
},
"globby": { "globby": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
@ -9223,38 +9279,148 @@
"pinkie-promise": "^2.0.0" "pinkie-promise": "^2.0.0"
} }
}, },
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
"dev": true
},
"har-validator": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
"dev": true,
"requires": {
"ajv": "^5.3.0",
"har-schema": "^2.0.0"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"dev": true,
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"mime-db": {
"version": "1.36.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
"integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
"dev": true
},
"mime-types": {
"version": "2.1.20",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
"integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
"dev": true,
"requires": {
"mime-db": "~1.36.0"
}
},
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true "dev": true
}, },
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"dev": true
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
"dev": true
},
"pify": { "pify": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"dev": true "dev": true
}, },
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
"dev": true
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"dev": true
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"dev": true,
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"supports-color": { "supports-color": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true "dev": true
}, },
"webdriver-manager": { "tough-cookie": {
"version": "12.0.6", "version": "2.4.3",
"resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.0.6.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha1-PfGkgZdwELTL+MnYXHpXeCjA5ws=", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"adm-zip": "^0.4.7", "psl": "^1.1.24",
"punycode": "^1.4.1"
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
"dev": true
},
"webdriver-manager": {
"version": "12.1.0",
"resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.0.tgz",
"integrity": "sha512-oEc5fmkpz6Yh6udhwir5m0eN5mgRPq9P/NU5YWuT3Up5slt6Zz+znhLU7q4+8rwCZz/Qq3Fgpr/4oao7NPCm2A==",
"dev": true,
"requires": {
"adm-zip": "^0.4.9",
"chalk": "^1.1.1", "chalk": "^1.1.1",
"del": "^2.2.0", "del": "^2.2.0",
"glob": "^7.0.3", "glob": "^7.0.3",
"ini": "^1.3.4", "ini": "^1.3.4",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"q": "^1.4.1", "q": "^1.4.1",
"request": "^2.78.0", "request": "^2.87.0",
"rimraf": "^2.5.2", "rimraf": "^2.5.2",
"semver": "^5.3.0", "semver": "^5.3.0",
"xml2js": "^0.4.17" "xml2js": "^0.4.17"
@ -9320,6 +9486,12 @@
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true "dev": true
}, },
"psl": {
"version": "1.1.29",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
"dev": true
},
"public-encrypt": { "public-encrypt": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
@ -12170,66 +12342,13 @@
} }
}, },
"webdriver-js-extender": { "webdriver-js-extender": {
"version": "1.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.0.0.tgz",
"integrity": "sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=", "integrity": "sha512-fbyKiVu3azzIc5d4+26YfuPQcFTlgFQV5yQ/0OQj4Ybkl4g1YQuIPskf5v5wqwRJhHJnPHthB6tqCjWHOKLWag==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/selenium-webdriver": "^2.53.35", "@types/selenium-webdriver": "^3.0.0",
"selenium-webdriver": "^2.53.2" "selenium-webdriver": "^3.0.1"
},
"dependencies": {
"sax": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-0.6.1.tgz",
"integrity": "sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk=",
"dev": true
},
"selenium-webdriver": {
"version": "2.53.3",
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz",
"integrity": "sha1-0p/1qVff8aG0ncRXdW5OS/vc4IU=",
"dev": true,
"requires": {
"adm-zip": "0.4.4",
"rimraf": "^2.2.8",
"tmp": "0.0.24",
"ws": "^1.0.1",
"xml2js": "0.4.4"
}
},
"tmp": {
"version": "0.0.24",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.24.tgz",
"integrity": "sha1-1qXhmNFKmDXMby18PZ4wJCjIzxI=",
"dev": true
},
"ultron": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz",
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=",
"dev": true
},
"ws": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz",
"integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==",
"dev": true,
"requires": {
"options": ">=0.0.5",
"ultron": "1.0.x"
}
},
"xml2js": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.4.tgz",
"integrity": "sha1-MREBAAMAiuGSQOuhdJe1fHKcVV0=",
"dev": true,
"requires": {
"sax": "0.6.x",
"xmlbuilder": ">=1.0.0"
}
}
} }
}, },
"webpack": { "webpack": {

View File

@ -20,7 +20,8 @@
"@angular/flex-layout": "6.0.0-beta.16", "@angular/flex-layout": "6.0.0-beta.16",
"@angular/forms": "6.0.7", "@angular/forms": "6.0.7",
"@angular/http": "6.0.7", "@angular/http": "6.0.7",
"@angular/material": "6.1.0", "@angular/material": "6.4.6",
"@angular/material-moment-adapter": "6.4.6",
"@angular/platform-browser": "6.0.7", "@angular/platform-browser": "6.0.7",
"@angular/platform-browser-dynamic": "6.0.7", "@angular/platform-browser-dynamic": "6.0.7",
"@angular/router": "6.0.7", "@angular/router": "6.0.7",
@ -32,6 +33,8 @@
"bootstrap": "^4.1.2", "bootstrap": "^4.1.2",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"file-saver": "1.3.3", "file-saver": "1.3.3",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"rxjs": "^6.2.1", "rxjs": "^6.2.1",
"rxjs-compat": "^6.1.0", "rxjs-compat": "^6.1.0",
"zone.js": "^0.8.26" "zone.js": "^0.8.26"
@ -51,7 +54,7 @@
"karma-coverage-istanbul-reporter": "^1.2.1", "karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0", "karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2", "karma-jasmine-html-reporter": "^0.2.2",
"protractor": "^5.3.2", "protractor": "5.4.0",
"ts-node": "~4.1.0", "ts-node": "~4.1.0",
"tslint": "~5.9.1", "tslint": "~5.9.1",
"typescript": "2.7.2", "typescript": "2.7.2",

View File

@ -12,7 +12,7 @@ const appRoutes: Routes = [
data: { data: {
breadcrumb: true breadcrumb: true
}, },
canActivate: [AuthGuard] //canActivate: [AuthGuard]
}, },
{ {
path: 'about', path: 'about',

View File

@ -5,6 +5,8 @@ import { LanguageResolverService } from './services/language-resolver/language-r
import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service'; import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { AuthService } from './services/auth/auth.service'; import { AuthService } from './services/auth/auth.service';
import { CultureService } from './utilities/culture/culture-service';
import { environment } from '../environments/environment';
declare const gapi: any; declare const gapi: any;
@ -28,12 +30,10 @@ export class AppComponent implements OnInit {
private authentication: AuthService, private authentication: AuthService,
private translate: TranslateService, private translate: TranslateService,
private languageService: LanguageResolverService, private languageService: LanguageResolverService,
private breadCrumbResolverService: BreadCrumbResolverService private breadCrumbResolverService: BreadCrumbResolverService,
private cultureService: CultureService
) { ) {
// this language will be used as a fallback when a translation isn't found in the current language this.initializeServices()
translate.setDefaultLang('en');
// the lang to use, if the lang isn't available, it will use the current loader to get them
translate.use('en');
} }
onActivate(event: any) { onActivate(event: any) {
@ -73,5 +73,14 @@ export class AppComponent implements OnInit {
goToProjects() { goToProjects() {
this.router.navigate(['/projects'], { queryParams: { /*refresh : Math.random() ,returnUrl: this.state.url*/ } }); this.router.navigate(['/projects'], { queryParams: { /*refresh : Math.random() ,returnUrl: this.state.url*/ } });
} }
initializeServices() {
// this language will be used as a fallback when a translation isn't found in the current language
this.translate.setDefaultLang('en');
this.cultureService.cultureSelected(environment.defaultCulture);
//this.setupChangeListeners();
}
} }

View File

@ -21,7 +21,7 @@ import { BrowserModule } from '@angular/platform-browser';
import { HomepageComponent } from './homepage/homepage.component'; import { HomepageComponent } from './homepage/homepage.component';
import { PageNotFoundComponent } from './not-found.component'; import { PageNotFoundComponent } from './not-found.component';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { NgModule } from '@angular/core'; import { NgModule, LOCALE_ID } from '@angular/core';
import { WelcomepageComponent } from './welcomepage/welcomepage.component'; import { WelcomepageComponent } from './welcomepage/welcomepage.component';
import { HelpContentService } from './services/help-content/help-content.service'; import { HelpContentService } from './services/help-content/help-content.service';
import { B2AccessLoginComponent } from './user-management/login/b2access/b2access-login.component'; import { B2AccessLoginComponent } from './user-management/login/b2access/b2access-login.component';
@ -32,6 +32,8 @@ import { HelpContentComponent, AsideHelpContentComponent } from './shared/help-c
import { AuthGuard } from './shared/guards/auth.guard'; import { AuthGuard } from './shared/guards/auth.guard';
import { UrlUtilities } from './utilities/UrlUtilities'; import { UrlUtilities } from './utilities/UrlUtilities';
import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service'; import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service';
import { MAT_DATE_LOCALE } from '@angular/material';
import { CultureService } from './utilities/culture/culture-service';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -103,7 +105,18 @@ import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-reso
HelpContentService, HelpContentService,
LanguageService, LanguageService,
LanguageResolverService, LanguageResolverService,
BreadCrumbResolverService BreadCrumbResolverService,
CultureService,
{
provide: MAT_DATE_LOCALE,
deps: [CultureService],
useFactory: (cultureService) => cultureService.getCurrentCulture().name
},
{
provide: LOCALE_ID,
deps: [CultureService],
useFactory: (cultureService) => cultureService.getCurrentCulture().name
},
], ],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })

View File

@ -0,0 +1,84 @@
<div>
<h3>{{'DATASET-LISTING.TITLE' | translate}} {{titlePrefix}}</h3>
<app-datasets-criteria-component [isPublic]='true'></app-datasets-criteria-component>
<mat-card class="mat-card">
<mat-card-header>
<mat-progress-bar *ngIf="dataSource?.isLoadingResults" mode="query"></mat-progress-bar>
</mat-card-header>
<mat-table [dataSource]="dataSource" matSort (matSortChange)="refresh()">
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="label">
<mat-header-cell *matHeaderCellDef mat-sort-header="label">{{'DATASET-LISTING.COLUMNS.NAME' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.label}}</mat-cell>
</ng-container>
<!-- Column Definition: Dmp -->
<ng-container cdkColumnDef="dmp">
<mat-header-cell *matHeaderCellDef mat-sort-header="|join|dmp:label">{{'DATASET-LISTING.COLUMNS.DMP' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.dmp}} </mat-cell>
</ng-container>
<!-- Column Definition: Profile -->
<ng-container cdkColumnDef="profile">
<mat-header-cell *matHeaderCellDef mat-sort-header="|join|profile:label">{{'DATASET-LISTING.COLUMNS.PROFILE' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.profile}} </mat-cell>
</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 -->
<!-- <ng-container cdkColumnDef="dataRepositories">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.DATAREPOSITORIES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.dataRepositories}} </mat-cell>
</ng-container> -->
<!-- Column Definition: DataRepositories -->
<!-- <ng-container cdkColumnDef="registries">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.REGISTRIES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.registries}} </mat-cell>
</ng-container> -->
<!-- Column Definition: DataRepositories -->
<!-- <ng-container cdkColumnDef="services">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.SERVICES' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.services}} </mat-cell>
</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: Description -->
<ng-container cdkColumnDef="description">
<mat-header-cell *matHeaderCellDef>{{'DATASET-LISTING.COLUMNS.DESCRIPTION' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.description}} </mat-cell>
</ng-container>
<!-- Column Definition: Created -->
<ng-container cdkColumnDef="created">
<mat-header-cell *matHeaderCellDef mat-sort-header="created">{{'DATASET-LISTING.COLUMNS.CREATED' | translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.created | date:'shortDate'}}</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns" (click)="rowClick(row.id)"></mat-row>
<!-- (click)="rowClick(row.id)" -->
</mat-table>
<mat-paginator #paginator [length]="dataSource?.totalCount" [pageSizeOptions]="[10, 25, 100]">
</mat-paginator>
</mat-card>
</div>

View File

@ -0,0 +1,151 @@
import { OnInit, Component, ViewChild } from "@angular/core";
import { MatSort, MatPaginator, PageEvent, MatSnackBar } from "@angular/material";
import { DatasetCriteriaComponent } from "../../shared/components/criteria/datasets/datasets-criteria.component";
import { Observable } from "rxjs";
import { BreadcrumbItem } from "../../shared/components/breadcrumb/definition/breadcrumb-item";
import { DatasetService } from "../../services/dataset/dataset.service";
import { Router, ActivatedRoute, Params } from "@angular/router";
import { TranslateService } from "@ngx-translate/core";
import { DataManagementPlanService } from "../../services/data-management-plan/data-management-plan.service";
import { DatasetCriteria } from "../../models/criteria/dataset/DatasetCriteria";
import { DataSource } from "@angular/cdk/table";
import { DatasetListingModel } from "../../models/datasets/DatasetListingModel";
import { DataTableRequest } from "../../models/data-table/DataTableRequest";
@Component({
selector: 'app-dataset-public-listing-component',
templateUrl: 'dataset-public-listing.component.html',
styleUrls: ['./dataset-public-listing.component.scss'],
})
export class DatasetPublicListingComponent implements OnInit {
@ViewChild(MatPaginator) _paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
@ViewChild(DatasetCriteriaComponent) criteria: DatasetCriteriaComponent;
dataSource: DatasetDataSource | null;
displayedColumns: String[] = ['label', 'dmp', 'profile', 'status', 'description', 'created'];
pageEvent: PageEvent;
titlePrefix: String;
dmpId: string;
statuses = [
{ value: '0', viewValue: 'Active' },
{ value: '1', viewValue: 'Inactive' }
];
constructor(
private datasetService: DatasetService,
private router: Router,
private languageService: TranslateService,
public snackBar: MatSnackBar,
public route: ActivatedRoute,
public dataManagementPlanService: DataManagementPlanService
) {
}
ngOnInit() {
this.route.params.subscribe(async (params: Params) => {
this.dmpId = params['dmpId'];
this.criteria.setCriteria(this.getDefaultCriteria(this.dmpId));
this.refresh();
this.criteria.setRefreshCallback(() => this.refresh());
if (this.dmpId != null) {
let dmp = await this.dataManagementPlanService.getSingle(this.dmpId).toPromise()
if (params['dmpLabel'] != undefined)
this.titlePrefix = "for " + params['dmpLabel'];
}
});
}
refresh() {
this.dataSource = new DatasetDataSource(this.datasetService, this._paginator, this.sort, this.languageService, this.snackBar, this.criteria, this.dmpId);
}
rowClick(rowId: String) {
this.router.navigate(['/datasets/edit/' + rowId]);
}
getDefaultCriteria(dmpId: String): DatasetCriteria {
const defaultCriteria = new DatasetCriteria();
if (dmpId != null) {
defaultCriteria.dmpIds.push(dmpId);
}
return defaultCriteria;
}
makeItPublic(id: String) {
this.datasetService.makeDatasetPublic(id).subscribe();
}
}
export class DatasetDataSource extends DataSource<DatasetListingModel> {
totalCount = 0;
isLoadingResults = false;
constructor(
private _service: DatasetService,
private _paginator: MatPaginator,
private _sort: MatSort,
private _languageService: TranslateService,
private _snackBar: MatSnackBar,
private _criteria: DatasetCriteriaComponent,
private dmpId: String
) {
super();
}
connect(): Observable<DatasetListingModel[]> {
const displayDataChanges = [
this._paginator.page
//this._sort.matSortChange
];
return Observable.merge(...displayDataChanges)
.startWith(null)
.switchMap(() => {
setTimeout(() => {
this.isLoadingResults = true;
});
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
let fields: Array<string> = new Array()
if (this._sort.active) fields = this._sort.direction === "asc" ? ["+" + this._sort.active] : ["-" + this._sort.active];
const request = new DataTableRequest<DatasetCriteria>(startIndex, this._paginator.pageSize, { fields: fields });
request.criteria = this._criteria.criteria;
if (this.dmpId) request.criteria.allVersions = true;
return this._service.getPaged(request);
})
/*.catch((error: any) => {
this._snackBar.openFromComponent(SnackBarNotificationComponent, {
data: { message: 'GENERAL.SNACK-BAR.FORMS-BAD-REQUEST', language: this._languageService },
duration: 3000,
extraClasses: ['snackbar-warning']
});
//this._criteria.criteria.onCallbackError(error);
return Observable.of(null);
})*/
.map(result => {
setTimeout(() => {
this.isLoadingResults = false;
});
return result;
})
.map(result => {
if (!result) { return []; }
if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
return result.data;
});
}
disconnect() {
// No-op
}
}

View File

@ -20,6 +20,7 @@ import { DataManagementPlanService } from '../services/data-management-plan/data
import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.service'; import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.service';
import { ExternalSourcesService } from '../services/external-sources/external-sources.service'; import { ExternalSourcesService } from '../services/external-sources/external-sources.service';
import { ExternalSourcesConfigurationService } from '../services/external-sources/external-sources-configuration.service'; import { ExternalSourcesConfigurationService } from '../services/external-sources/external-sources-configuration.service';
import { DatasetPublicListingComponent } from './dataset-public/dataset-public-listing.component';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
@ -43,13 +44,15 @@ import { ExternalSourcesConfigurationService } from '../services/external-source
declarations: [ declarations: [
DatasetListingComponent, DatasetListingComponent,
DatasetEditorComponent, DatasetEditorComponent,
DatasetWizardComponent DatasetWizardComponent,
DatasetPublicListingComponent
], ],
exports: [ exports: [
DatasetListingComponent, DatasetListingComponent,
DatasetEditorComponent, DatasetEditorComponent,
DatasetWizardComponent, DatasetWizardComponent,
DatasetPublicListingComponent,
RouterModule RouterModule
], ],
providers: [ providers: [

View File

@ -2,6 +2,7 @@ import { DatasetWizardComponent } from './dataset-wizard/dataset-wizard.componen
import { DatasetListingComponent } from './listing/dataset-listing.component'; import { DatasetListingComponent } from './listing/dataset-listing.component';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { AuthGuard } from '../shared/guards/auth.guard'; import { AuthGuard } from '../shared/guards/auth.guard';
import { DatasetPublicListingComponent } from './dataset-public/dataset-public-listing.component';
export const DatasetRoutes: Routes = [ export const DatasetRoutes: Routes = [
{ {
@ -15,7 +16,7 @@ export const DatasetRoutes: Routes = [
{ {
path: "edit/:id", path: "edit/:id",
component: DatasetWizardComponent, component: DatasetWizardComponent,
canActivate: [AuthGuard], //canActivate: [AuthGuard],
data: { data: {
breadcrumb: true breadcrumb: true
}, },
@ -31,15 +32,20 @@ export const DatasetRoutes: Routes = [
{ {
path: '', path: '',
component: DatasetListingComponent, component: DatasetListingComponent,
canActivate: [AuthGuard], //canActivate: [AuthGuard],
data: { data: {
breadcrumb: true breadcrumb: true
}, },
}, },
{
path: 'public',
component: DatasetPublicListingComponent,
//canActivate: [AuthGuard],
},
{ {
path: "dmp/:dmpId", path: "dmp/:dmpId",
component: DatasetListingComponent, component: DatasetListingComponent,
canActivate: [AuthGuard], //canActivate: [AuthGuard],
data: { data: {
breadcrumb: true breadcrumb: true
}, },

View File

@ -21,6 +21,8 @@
<mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}</button> <mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}</button>
<button mat-menu-item (click)="clone(this.dataManagementPlan.id)"> <button mat-menu-item (click)="clone(this.dataManagementPlan.id)">
<mat-icon>filter_none</mat-icon>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</button> <mat-icon>filter_none</mat-icon>{{'DMP-LISTING.ACTIONS.CLONE' | translate}}</button>
<button mat-menu-item (click)="viewVersions(this.dataManagementPlan.groupId, this.dataManagementPlan.label)">
<mat-icon>library_books</mat-icon>{{'DMP-LISTING.ACTIONS.VIEW-VERSION' | translate}}</button>
</mat-menu> </mat-menu>
<div> <div>
<button mat-icon-button type="button" [matMenuTriggerFor]="actionsMenu"> <button mat-icon-button type="button" [matMenuTriggerFor]="actionsMenu">

View File

@ -325,5 +325,7 @@ export class DataManagementPlanEditorComponent implements AfterViewInit, IBreadC
clone(id: String) { clone(id: String) {
this.router.navigate(['/dmps/clone/' + id]); this.router.navigate(['/dmps/clone/' + id]);
} }
viewVersions(rowId: String, rowLabel: String) {
this.router.navigate(['/dmps/viewversions/' + rowId], { queryParams: { groupLabel: rowLabel } });
}
} }

View File

@ -7,14 +7,21 @@ export class Principal implements Serializable<Principal> {
name: string; name: string;
expiresAt: Date; expiresAt: Date;
appRoles: Principal.AppRole[]; appRoles: Principal.AppRole[];
avatarUrl: string; avatarUrl: string;
timezone: string;
language: string;
culture: string;
fromJSONObject(item: any): Principal { fromJSONObject(item: any): Principal {
this.id = item.id; this.id = item.id;
this.token = item.token; this.token = item.token;
this.name = item.name; this.name = item.name;
this.expiresAt = item.expiresAt; this.expiresAt = item.expiresAt;
this.appRoles = item.authorities; this.appRoles = item.authorities;
this.avatarUrl = item.avatarUrl; this.avatarUrl = item.avatarUrl;
this.language = item.language;
this.culture = item.culture;
this.timezone = item.timezone;
return this; return this;
} }
} }

View File

@ -1,6 +1,6 @@
import { Serializable } from '../Serializable'; import { Serializable } from '../Serializable';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Principal } from 'app/models/login/Principal'; import { Principal } from '../login/Principal';
export class UserListingModel implements Serializable<UserListingModel> { export class UserListingModel implements Serializable<UserListingModel> {
public id: String; public id: String;

View File

@ -9,7 +9,7 @@ import { Observable } from 'rxjs/Observable';
import { DataTableRequest } from '../../models/data-table/DataTableRequest'; import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { DataTableData } from '../../models/data-table/DataTableData'; import { DataTableData } from '../../models/data-table/DataTableData';
import { HostConfiguration } from 'app/app.constants'; import { HostConfiguration } from '../../app.constants';
@Injectable() @Injectable()
export class UserReferenceService { export class UserReferenceService {
@ -51,4 +51,8 @@ export class UserReferenceService {
getRecentActivity(): Observable<any[]> { getRecentActivity(): Observable<any[]> {
return this.http.get<any[]>(this.actionUrl + "recentActivity", { headers: this.headers }); return this.http.get<any[]>(this.actionUrl + "recentActivity", { headers: this.headers });
} }
updateUserSettings(value: any): Observable<any[]> {
return this.http.post<any[]>(this.actionUrl + "settings", value, { headers: this.headers });
}
} }

View File

@ -20,15 +20,15 @@
<mat-datepicker #periodStartPicker></mat-datepicker> <mat-datepicker #periodStartPicker></mat-datepicker>
</mat-form-field> </mat-form-field>
</div> --> </div> -->
<div class="col-md-4"> <div [ngClass]="isPublic ? 'col-md-6' : 'col-md-4'">
<mat-form-field> <mat-form-field>
<input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="datasetCriteriaName" [(ngModel)]="criteria.like" <input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="datasetCriteriaName" [(ngModel)]="criteria.like"
(ngModelChange)="controlModified()"> (ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel['name']">{{baseErrorModel['Criteria.like']}}</mat-error> <mat-error *ngIf="baseErrorModel['name']">{{baseErrorModel['Criteria.like']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-4"> <div *ngIf="!isPublic" class="col-md-4">
<mat-form-field> <mat-form-field >
<mat-select placeholder=" {{'CRITERIA.DATA-SETS.STATUS'| translate}}" name="datasetCriteriastatus" [(ngModel)]="criteria.status" <mat-select placeholder=" {{'CRITERIA.DATA-SETS.STATUS'| translate}}" name="datasetCriteriastatus" [(ngModel)]="criteria.status"
(ngModelChange)="controlModified()"> (ngModelChange)="controlModified()">
<mat-option *ngFor="let status of statuses" [value]="status.value"> <mat-option *ngFor="let status of statuses" [value]="status.value">
@ -38,7 +38,7 @@
<mat-error *ngIf="baseErrorModel['status']">{{baseErrorModel['Criteria.status']}}</mat-error> <mat-error *ngIf="baseErrorModel['status']">{{baseErrorModel['Criteria.status']}}</mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-4"> <div [ngClass]="isPublic ? 'col-md-6' : 'col-md-4'">
<td-chips color="accent" [items]="filteredTags" [(ngModel)]="criteria.tags" (ngModelChange)="controlModified()" placeholder="{{'CRITERIA.DATA-SETS.TAGS' | translate}}" <td-chips color="accent" [items]="filteredTags" [(ngModel)]="criteria.tags" (ngModelChange)="controlModified()" placeholder="{{'CRITERIA.DATA-SETS.TAGS' | translate}}"
(inputChange)="filterTags($event)" name="tags" requireMatch> (inputChange)="filterTags($event)" name="tags" requireMatch>
<ng-template td-chip let-chip="chip"> <ng-template td-chip let-chip="chip">

View File

@ -1,5 +1,5 @@
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms'; import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { BaseCriteriaComponent } from '../base/base-criteria.component'; import { BaseCriteriaComponent } from '../base/base-criteria.component';
import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext'; import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext';
@ -25,6 +25,8 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
// public form: ProjectType; // public form: ProjectType;
// public formStatus: ProjectStatus; // public formStatus: ProjectStatus;
@Input()
public isPublic = false;
public criteria: DatasetCriteria = new DatasetCriteria(); public criteria: DatasetCriteria = new DatasetCriteria();
public filteringTagsAsync: boolean = false; public filteringTagsAsync: boolean = false;
public filteredTags: ExternalSourcesItemModel[]; public filteredTags: ExternalSourcesItemModel[];

View File

@ -1,5 +1,5 @@
<div class="figure-card card"> <div class="figure-card card">
<div class="card-header" (click)="navigateToUrl()" [ngStyle]="{ 'background': linearColor, 'box-shadow': boxShadow }"> <div class="card-header" [class.clickable]="isAuthenticated()" (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">

View File

@ -19,7 +19,10 @@
border-radius: 3px; border-radius: 3px;
padding: 15px; padding: 15px;
position: relative; position: relative;
cursor: pointer; }
.clickable{
cursor: pointer;
} }
.card-header i { .card-header i {

View File

@ -5,7 +5,7 @@ import { AuthService } from '../../../services/auth/auth.service';
@Component({ @Component({
selector: 'app-figurecard', selector: 'app-figurecard',
templateUrl: './figurecard.component.html', templateUrl: './figurecard.component.html',
styleUrls: ['./figurecard.component.css'] styleUrls: ['./figurecard.component.scss']
}) })
export class FigurecardComponent implements OnInit { export class FigurecardComponent implements OnInit {
@Input() headerIcon: string; @Input() headerIcon: string;
@ -26,6 +26,7 @@ export class FigurecardComponent implements OnInit {
} }
navigateToUrl() { navigateToUrl() {
if(!this.isAuthenticated()) return;
this.router.navigate([this.routelLink]); this.router.navigate([this.routelLink]);
} }

View File

@ -8,7 +8,11 @@
<button mat-button class="navbar-button" routerLink="/datasets">{{'NAV-BAR.DATASETS' | translate}}</button> <button mat-button class="navbar-button" routerLink="/datasets">{{'NAV-BAR.DATASETS' | translate}}</button>
<button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/users">{{'NAV-BAR.USERS' | translate}}</button> <button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/users">{{'NAV-BAR.USERS' | translate}}</button>
<button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/dmp-profiles">{{'NAV-BAR.DMP-PROFILES' | translate}}</button> <button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/dmp-profiles">{{'NAV-BAR.DMP-PROFILES' | translate}}</button>
<button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/datasetsProfiles">{{'NAV-BAR.DATASETS-ADMIN' | translate}}</button> <button *ngIf="isAdmin()" mat-button class="navbar-button" routerLink="/datasetsProfiles">{{'NAV-BAR.DATASETS-ADMIN'
| translate}}</button>
</div>
<div *ngIf="!isAuthenticated()">
<button mat-button class="navbar-button" routerLink="/datasets/public">{{'NAV-BAR.PUBLIC-DATASETS' | translate}}</button>
</div> </div>
<!--<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>-->

View File

@ -1,92 +1,97 @@
import { NgModule } from '@angular/core'; import { NgModule, LOCALE_ID } from '@angular/core';
import { import {
MatToolbarModule, MatToolbarModule,
MatIconModule, MatIconModule,
MatSidenavModule, MatSidenavModule,
MatButtonModule, MatButtonModule,
MatTableModule, MatTableModule,
MatPaginatorModule, MatPaginatorModule,
MatSortModule, MatSortModule,
MatDialogModule, MatDialogModule,
MatDatepickerModule, MatDatepickerModule,
MatNativeDateModule, MatNativeDateModule,
MatInputModule, MatInputModule,
MatFormFieldModule, MatFormFieldModule,
MatSnackBarModule, MatSnackBarModule,
MatAutocompleteModule, MatAutocompleteModule,
MatExpansionModule, MatExpansionModule,
MatSelectModule, MatSelectModule,
MatOptionModule, MatOptionModule,
MatCardModule, MatCardModule,
MatProgressBarModule, MatProgressBarModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
DateAdapter, DateAdapter,
MatTooltipModule, MatTooltipModule,
MatCheckboxModule, MatCheckboxModule,
MatTabsModule, MatTabsModule,
MatStepperModule, MatStepperModule,
MatRadioModule, MatRadioModule,
MatMenuModule, MatMenuModule,
MatListModule, MatListModule,
MatChipsModule, MatChipsModule,
MatBadgeModule MatBadgeModule,
MAT_DATE_LOCALE,
MAT_DATE_FORMATS
} 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';
import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, CovalentFileModule } from '@covalent/core'; import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, CovalentFileModule } from '@covalent/core';
import { CultureService } from '../../utilities/culture/culture-service';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
@NgModule({ @NgModule({
imports: [ imports: [
], ],
exports: [ exports: [
MatToolbarModule, MatToolbarModule,
MatIconModule, MatIconModule,
MatSidenavModule, MatSidenavModule,
MatButtonModule, MatButtonModule,
MatTableModule, MatTableModule,
MatPaginatorModule, MatPaginatorModule,
CdkTableModule, CdkTableModule,
MatSortModule, MatSortModule,
MatDialogModule, MatDialogModule,
MatDatepickerModule, MatDatepickerModule,
MatNativeDateModule, MatNativeDateModule,
MatInputModule, MatInputModule,
MatFormFieldModule, MatFormFieldModule,
MatSnackBarModule, MatSnackBarModule,
MatAutocompleteModule, MatAutocompleteModule,
MatExpansionModule, MatExpansionModule,
MatSelectModule, MatSelectModule,
MatOptionModule, MatOptionModule,
MatCardModule, MatCardModule,
MatProgressBarModule, MatProgressBarModule,
MatProgressSpinnerModule, MatProgressSpinnerModule,
MatTooltipModule, MatTooltipModule,
MatCheckboxModule, MatCheckboxModule,
MatTabsModule, MatTabsModule,
CovalentLayoutModule, CovalentLayoutModule,
CovalentChipsModule, CovalentChipsModule,
CovalentDialogsModule, CovalentDialogsModule,
CovalentFileModule, CovalentFileModule,
MatStepperModule, MatStepperModule,
MatRadioModule, MatRadioModule,
MatMenuModule, MatMenuModule,
MatListModule, MatListModule,
MatChipsModule, MatChipsModule,
MatBadgeModule MatBadgeModule,
],
providers: [ ],
//{ provide: DateAdapter, useClass: LocalizedDateAdapter },
],
entryComponents: [ providers: [
SnackBarNotificationComponent
] ],
entryComponents: [
SnackBarNotificationComponent
]
}) })
export class MaterialModule { export class MaterialModule {
// constructor(dateAdapter: DateAdapter<LocalizedDateAdapter>) { // constructor(dateAdapter: DateAdapter<LocalizedDateAdapter>) {
// dateAdapter.setLocale('el-GR'); // dateAdapter.setLocale('el-GR');
// } // }
} }

View File

@ -25,6 +25,7 @@ import { SingleAutoCompleteComponent } from './components/autocompletes/single/s
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'; import { UserDialogComponent } from './components/user-dialog/user-dialog.component';
import { SearchBarComponent } from './components/search-bar/search-bar.component'; import { SearchBarComponent } from './components/search-bar/search-bar.component';
import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe';
@NgModule({ @NgModule({
imports: [ imports: [

View File

@ -19,7 +19,7 @@
<i class="fa fa-twitter"></i> <i class="fa fa-twitter"></i>
</button> </button>
</div> </div>
<button *ngIf="hasB2AccessOauth()" class="mat-icon-button" (click)="b2AccessLogin()"> <button *ngIf="hasB2AccessOauth()" mat-icon-button (click)="b2AccessLogin()">
<span class="iconmedium"></span> <span class="iconmedium"></span>
<span></span> <span></span>
</button> </button>

View File

@ -12,6 +12,7 @@ import { SnackBarNotificationComponent } from '../../shared/components/notificai
import { Router, ActivatedRoute, Params } from '@angular/router'; import { Router, ActivatedRoute, Params } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { CultureService } from '../../utilities/culture/culture-service';
declare const gapi: any; declare const gapi: any;
declare const FB: any; declare const FB: any;
@ -30,6 +31,7 @@ export class LoginService {
public language: TranslateService, public language: TranslateService,
private zone: NgZone, private zone: NgZone,
private httpClient: HttpClient, private httpClient: HttpClient,
private cultureService: CultureService,
@Optional() private config: LoginServiceConfiguration @Optional() private config: LoginServiceConfiguration
) { ) {
if (config) { if (config) {
@ -218,6 +220,7 @@ export class LoginService {
data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN', language: this.language }, data: { message: 'GENERAL.SNACK-BAR.SUCCESSFUL-LOGIN', language: this.language },
duration: 3000, duration: 3000,
}); });
this.cultureService.cultureSelected(this.authService.current().culture)
let params = this.router["rawUrlTree"].queryParams; let params = this.router["rawUrlTree"].queryParams;
let redirectUrl = params['returnUrl'] ? params['returnUrl'] : '/'; let redirectUrl = params['returnUrl'] ? params['returnUrl'] : '/';
this.zone.run(() => this.router.navigate([redirectUrl])); this.zone.run(() => this.router.navigate([redirectUrl]));

View File

@ -3,7 +3,7 @@
<mat-card-content> <mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center"> <div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex> <div fxFlex>
<img mat-card-avatar [src]="userProfile.additionalinfo.data.avatar.url"> <img mat-card-avatar [src]="userProfile.additionalinfo.avatarUrl">
</div> </div>
<mat-card-title>{{userProfile.name}}</mat-card-title> <mat-card-title>{{userProfile.name}}</mat-card-title>
<mat-card-subtitle>{{userProfile.email}}</mat-card-subtitle> <mat-card-subtitle>{{userProfile.email}}</mat-card-subtitle>
@ -18,7 +18,8 @@
</div> </div>
<div> <div>
<mat-list> <mat-list>
<mat-list-item class="clickable" (click)="navigateToDmp(dmp)" *ngFor="let dmp of userProfile.associatedDmps" fxLayout="row" fxLayoutAlign="start center"> <mat-list-item class="clickable" (click)="navigateToDmp(dmp)" *ngFor="let dmp of userProfile.associatedDmps" fxLayout="row"
fxLayoutAlign="start center">
<div> <div>
{{ dmp.label }} {{ dmp.label }}
</div> </div>
@ -35,15 +36,55 @@
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
<mat-card> <mat-card>
<mat-card-header>
<mat-card-title>
<h4>{{ 'USER-PROFILE.SETTINGS.TITLE' | translate}}</h4>
<button *ngIf="!editMode" mat-icon-button (click)="unlock()">
<mat-icon class="mat-24">edit</mat-icon>
</button>
<button *ngIf="editMode" mat-icon-button (click)="lock()">
<mat-icon class="mat-24">lock</mat-icon>
</button>
</mat-card-title>
</mat-card-header>
<mat-card-content> <mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center"> <div class="container">
<div fxFlex> <div class="row">
<h4>{{ 'USER-PROFILE.SETTINGS' | translate}}</h4> <div class="col-md-4">
<mat-form-field class="full-width">
<input type="text" placeholder="{{'USER-PROFILE.SETTINGS.TIMEZONE' | translate}}" [formControl]="this.formGroup.get('timezone')"
matInput [matAutocomplete]="timezone">
<mat-autocomplete #timezone="matAutocomplete">
<mat-option *ngFor="let timezone of timezones | async" [value]="timezone">
{{ timezone | timezoneInfoDisplay }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div class="col-md-4">
<mat-form-field class="full-width">
<input type="text" placeholder="{{'USER-PROFILE.SETTINGS.CULTURE' | translate}}" [formControl]="this.formGroup.get('culture')"
matInput [matAutocomplete]="culture">
<mat-autocomplete #culture="matAutocomplete" [displayWith]="displayFn">
<mat-option *ngFor="let culture of cultures | async" [value]="culture">
{{ culture.displayName }} - {{ culture.nativeName }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
<div class="col-md-4">
<mat-form-field class="full-width">
<mat-select placeholder="{{'USER-PROFILE.SETTINGS.LANGUAGE' | translate}}" [formControl]="this.formGroup.get('language')">
<mat-option *ngFor="let language of languages" [value]="language">
{{ language.label }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div> </div>
</div> </div>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
</div> </div>
<ng-template #loading> <ng-template #loading>
Loading stuff...
</ng-template> </ng-template>

View File

@ -1,3 +1,10 @@
.clickable{ .clickable{
cursor: pointer; cursor: pointer;
} }
.two-line-mat-option {
height: 3.5em;
line-height: 1.2em;
}
.full-width{
width: 100%
}

View File

@ -16,34 +16,62 @@ import { DataSource } from '@angular/cdk/table';
import { RecentActivityTypes } from '../../users/activity/RecentActivityTypes'; import { RecentActivityTypes } from '../../users/activity/RecentActivityTypes';
import { AuthService } from '../../services/auth/auth.service'; import { AuthService } from '../../services/auth/auth.service';
import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel'; import { DataManagementPlanModel } from '../../models/data-managemnt-plans/DataManagementPlanModel';
import { CultureInfo } from '../../utilities/culture/models/culture-info';
import { CultureService } from '../../utilities/culture/culture-service';
import { FormControl, FormBuilder, FormGroup } from '@angular/forms';
import * as moment from 'moment-timezone';
import { User } from '../../models/invitation/User';
const availableLanguages: any[] = require('../../../assets/resources/language.json');
@Component({ @Component({
selector: 'app-user-profile', selector: 'app-user-profile',
templateUrl: './user-profile.component.html', templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss'], styleUrls: ['./user-profile.component.scss'],
providers: [ providers: [
UserReferenceService UserReferenceService,
CultureService
] ]
}) })
export class UserProfileComponent implements OnInit { export class UserProfileComponent implements OnInit {
user: Observable<UserListingModel>; user: Observable<UserListingModel>;
currentUserId: string; currentUserId: string;
cultures: Observable<CultureInfo[]>;
timezones: Observable<any[]>;
editMode = false;
languages = availableLanguages;
formGroup: FormGroup;
constructor( constructor(
private userReferenceService: UserReferenceService, private userReferenceService: UserReferenceService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private authService: AuthService, private authService: AuthService,
private language: TranslateService private language: TranslateService,
private cultureService: CultureService,
private translate: TranslateService,
) { } ) { }
ngOnInit() { ngOnInit() {
this.route.params.subscribe((params: Params) => { this.route.params.subscribe((params: Params) => {
this.currentUserId = params['id']; this.currentUserId = params['id'];
let userId = params['id'] === this.authService.current().id ? 'me' : params['id'] 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 }) this.user = this.userReferenceService.getUser(userId).map(result => {
result["additionalinfo"] = JSON.parse(result["additionalinfo"]);
this.formGroup = new FormBuilder().group({
language: new FormControl(result["additionalinfo"]["language"] ? availableLanguages.filter(x => x.value === result["additionalinfo"]["language"]["value"]).pop() : ''),
timezone: new FormControl(result["additionalinfo"]["timezone"]),
culture: new FormControl(result["additionalinfo"]["culture"])
})
this.formGroup.get('language').valueChanges.subscribe(x => { if (x) this.translate.use(x.value) })
this.formGroup.get('timezone').valueChanges.subscribe(x => { if (x) this.timezones = this._filterTimezone(x) });
this.formGroup.get('culture').valueChanges.subscribe(x => { if (x) this.cultures = this._filterCulture(x) });
this.formGroup.disable()
return result;
})
}) })
} }
getUserRole(dmp: DataManagementPlanModel) { getUserRole(dmp: DataManagementPlanModel) {
@ -60,4 +88,46 @@ export class UserProfileComponent implements OnInit {
this.router.navigate(["/dmps/edit/" + dmp.id]) this.router.navigate(["/dmps/edit/" + dmp.id])
} }
private _filterTimezone(value: string): Observable<any[]> {
if (value && typeof value === 'string') {
const filterValue = value.toLowerCase();
return Observable.of(moment.tz.names().filter(option => option.toLowerCase().includes(filterValue)));
} else {
return Observable.of(moment.tz.names());
}
}
private _filterCulture(value: string): Observable<any[]> {
if (value && typeof value === 'string') {
const filterValue = value.toLowerCase();
return Observable.of(this.cultureService.getCultureValues().filter(option => option.displayName.toLowerCase().includes(filterValue)));
} else {
return Observable.of(this.cultureService.getCultureValues());
}
}
displayFn(culture?: CultureInfo): string | undefined {
return culture ? culture.displayName + '-' + culture.nativeName : undefined;
}
save() {
}
public unlock() {
this.editMode = true;
this.formGroup.enable()
}
public lock() {
this.userReferenceService.updateUserSettings(this.formGroup.value).subscribe(
x => {
this.editMode = false;
this.formGroup.disable();
},
error => {
console.log(error)
})
}
} }

View File

@ -17,6 +17,7 @@ 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'; import { UserProfileComponent } from './profile/user-profile.component';
import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe';
@NgModule({ @NgModule({
imports: [ imports: [
@ -40,12 +41,12 @@ import { UserProfileComponent } from './profile/user-profile.component';
UsersComponent, UsersComponent,
UsersCriteriaComponent, UsersCriteriaComponent,
UserRoleEditorComponent, UserRoleEditorComponent,
UserProfileComponent UserProfileComponent,
TimezoneInfoDisplayPipe
], ],
providers: [ providers: [
BaseHttpService, BaseHttpService,
UserReferenceService UserReferenceService
], ],
exports: [ exports: [
UsersComponent UsersComponent

View File

@ -0,0 +1,69 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { CultureInfo } from './models/culture-info';
import { registerLocaleData } from '@angular/common';
const availableCultures: CultureInfo[] = require('../../../assets/resources/available-cultures.json');
@Injectable()
export class CultureService {
private cultureValues = new Map<string, CultureInfo>(); // cultures by name
private cultureChangeSubject = new Subject<CultureInfo>();
private currentCulture: CultureInfo;
constructor(
) {
if (availableCultures) {
this.cultureValues = new Map<string, CultureInfo>();
availableCultures.forEach(culture => {
this.cultureValues.set(culture.name, culture);
});
}
}
getCultureValues(): CultureInfo[] {
const values: CultureInfo[] = [];
this.cultureValues.forEach((value) => values.push(value));
return values;
}
getCultureValue(culture: string): CultureInfo | undefined {
return this.cultureValues.get(culture);
}
cultureSelected(culture: string | CultureInfo) {
let newCultureName: string;
if (typeof culture == 'string') {
if (this.currentCulture && this.currentCulture.name === culture) { return; }
newCultureName = culture;
} else {
if (this.currentCulture && this.currentCulture.name === culture.name) { return; }
newCultureName = culture.name;
}
const newCulture = this.cultureValues.get(newCultureName);
if (!newCulture) {
console.error(`unsupported culture given: ${newCultureName}`); //TODO: throw error?
return;
}
this.currentCulture = newCulture;
this.cultureChangeSubject.next(newCulture);
// Set angular locale based on user selection.
const locale = newCulture.name.split('-')[0];
import(`@angular/common/locales/${locale}.js`).catch(reason => {
console.error('Could not load locale: ' + locale);
}).then(selectedLocale => {
registerLocaleData(selectedLocale.default);
});
}
getCultureChangeObservable(): Observable<CultureInfo> {
return this.cultureChangeSubject.asObservable();
}
getCurrentCulture(): CultureInfo {
return this.currentCulture;
}
}

View File

@ -0,0 +1,5 @@
export class CultureInfo {
public name: string;
public displayName: string;
public nativeName: string;
}

View File

@ -0,0 +1,12 @@
import { Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
import 'moment-timezone';
@Pipe({ name: 'timezoneInfoDisplay' })
export class TimezoneInfoDisplayPipe implements PipeTransform {
constructor() { }
public transform(value): any {
return value + ' (GMT' + moment["tz"](value).format('Z') + ')';
}
}

View File

@ -26,6 +26,7 @@
"PROJECTS": "Projects", "PROJECTS": "Projects",
"DMPS": "DMPs", "DMPS": "DMPs",
"DATASETS": "Datasets", "DATASETS": "Datasets",
"PUBLIC-DATASETS": "Public Datasets",
"USERS": "Users", "USERS": "Users",
"DATASETS-ADMIN": "Dataset Profiles", "DATASETS-ADMIN": "Dataset Profiles",
"DMP-PROFILES": "DMP Profiles", "DMP-PROFILES": "DMP Profiles",
@ -181,7 +182,7 @@
"PERIOD-TO": "Project End", "PERIOD-TO": "Project End",
"PROJECT-STATE-TYPE": "Project Status", "PROJECT-STATE-TYPE": "Project Status",
"TYPES": { "TYPES": {
"ON-GOING": "OnGoing", "ON-GOING": "On Going",
"FINISHED": "Finished" "FINISHED": "Finished"
} }
}, },
@ -324,7 +325,12 @@
"EXIT": "Exit " "EXIT": "Exit "
}, },
"USER-PROFILE": { "USER-PROFILE": {
"SETTINGS": "Settings", "SETTINGS": {
"TITLE": "Settings",
"TIMEZONE": "Time Zone",
"CULTURE": "Culture",
"LANGUAGE": "Language"
},
"ASSOCIATED-DMPS": "Associated DMPs", "ASSOCIATED-DMPS": "Associated DMPs",
"DMPS": { "DMPS": {
"SHOW-ALL": "Show All", "SHOW-ALL": "Show All",

View File

@ -0,0 +1,21 @@
{
"GENERAL": {
"VALIDATION": {
"REQUIRED": "Required"
}
},
"USER-PROFILE": {
"SETTINGS": {
"TITLE": "Ρυθμίσεις",
"TIMEZONE": "Ζώνη Ώρας",
"CULTURE": "Κουλτούρα",
"LANGUAGE": "Γλώσσα"
},
"ASSOCIATED-DMPS": "Συσχετιζόμενα DMPs",
"DMPS": {
"SHOW-ALL": "Όλα",
"CREATOR": "Δημιουργός",
"MEMBER": "Μέλος"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
[
{
"label": "English",
"value": "en"
},
{
"label": "Greek",
"value": "gr"
}
]

View File

@ -1,6 +1,6 @@
export const environment = { export const environment = {
production: true, production: true,
Server: 'http://localhost:8080/api/', Server: 'http://dl043.madgik.di.uoa.gr:8080/api/',
App: 'http://dl043.madgik.di.uoa.gr/', App: 'http://dl043.madgik.di.uoa.gr/',
HelpServiceUrl: 'http://dl043.madgik.di.uoa.gr:5555/' HelpServiceUrl: 'http://dl043.madgik.di.uoa.gr:5555/'
}; };

View File

@ -7,5 +7,6 @@ export const environment = {
production: false, production: false,
Server: 'http://devel-21.local.cite.gr:8080/api/', Server: 'http://devel-21.local.cite.gr:8080/api/',
App: 'http://localhost:4200/', App: 'http://localhost:4200/',
HelpServiceUrl: 'localhost:5000/' HelpServiceUrl: 'localhost:5000/',
defaultCulture: "en-GB"
}; };

View File

@ -3,7 +3,6 @@
"compilerOptions": { "compilerOptions": {
"outDir": "../out-tsc/app", "outDir": "../out-tsc/app",
"baseUrl": "./", "baseUrl": "./",
"module": "es2015",
"types": ["node"], "types": ["node"],
"typeRoots": [ "../node_modules/@types" ] "typeRoots": [ "../node_modules/@types" ]
}, },