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
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"))
, builder.equal(root.get("isPublic"), true)));
if (principal.getId() == null) query.where((builder, root) -> 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;
}

View File

@ -19,9 +19,9 @@ public abstract class AbstractBatchLogger {
private Map<String, Object> concurrentHashMap = new ConcurrentHashMap<String, Object>();
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();

View File

@ -15,5 +15,9 @@ public class Main {
queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("id").greaterThan(5) );
queryBuilder.<ComparisonPredicate>where((comparisonExpression) -> comparisonExpression.field("label").equal("mitsos") );
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;
import eu.eudat.logic.utilities.documents.helpers.FileEnvelope;
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.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.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.dmp.AssociatedProfile;
import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.ApiMessageCode;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -30,6 +31,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import static eu.eudat.types.Authorities.ANONYMOUS;
@RestController
@CrossOrigin
@ -59,7 +62,7 @@ public class DatasetWizardController extends BaseController {
@RequestMapping(method = RequestMethod.POST, value = {"/getAvailableProfiles"}, produces = "application/json")
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 {
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));
@ -72,10 +75,10 @@ public class DatasetWizardController extends BaseController {
@RequestMapping(method = RequestMethod.GET, value = {"/getSingle/{id}"}, produces = "application/json")
public @ResponseBody
ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, Principal principal) {
ResponseEntity<ResponseItem<DatasetWizardModel>> getSingle(@PathVariable String id, @ClaimedAuthorities(claims = {ANONYMOUS}) Principal principal) {
try {
DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(),this.getApiContext().getOperationsContext().getDatasetRepository()
,id);
DatasetWizardModel dataset = new DatasetManager().getSingle(this.getApiContext().getOperationsContext().getDatabaseRepository().getDatasetDao(), this.getApiContext().getOperationsContext().getDatasetRepository()
, id);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<DatasetWizardModel>().status(ApiMessageCode.NO_MESSAGE).payload(dataset));
} catch (Exception ex) {
ex.printStackTrace();

View File

@ -1,14 +1,16 @@
package eu.eudat.controllers;
import eu.eudat.data.entities.Dataset;
import eu.eudat.logic.managers.DatasetManager;
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.responses.ResponseItem;
import eu.eudat.models.data.listingmodels.DatasetListingModel;
import eu.eudat.models.data.security.Principal;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.types.ApiMessageCode;
import eu.eudat.types.Authorities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
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")
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 {
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));

View File

@ -1,13 +1,13 @@
package eu.eudat.controllers;
import eu.eudat.data.query.items.table.userinfo.UserInfoTableRequestItem;
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.responses.ResponseItem;
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.logic.security.claims.ClaimedAuthorities;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.models.data.userinfo.UserProfile;
import eu.eudat.types.ApiMessageCode;
import org.springframework.beans.factory.annotation.Autowired;
@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Map;
import java.util.UUID;
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()));
}
}
@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 String avatarUrl;
private Set<Authorities> authorities;
private String culture;
private String language;
private String timezone;
public PrincipalBuilder id(UUID id) {
this.id = id;
@ -50,6 +53,21 @@ public class PrincipalBuilder extends Builder<Principal> {
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
public Principal build() {
Principal principal = new Principal();
@ -59,6 +77,9 @@ public class PrincipalBuilder extends Builder<Principal> {
principal.setToken(token);
principal.setId(id);
principal.setAvatarUrl(avatarUrl);
principal.setCulture(culture);
principal.setLanguage(language);
principal.setTimezone(timezone);
return principal;
}
}

View File

@ -32,7 +32,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
String token = nativeWebRequest.getHeader("AuthToken");
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());
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");
UUID authToken;
try {
@ -43,7 +43,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
Principal principal = this.authenticationService.Touch(authToken);
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");
return principal;
}

View File

@ -1,5 +1,6 @@
package eu.eudat.logic.managers;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.UserRole;
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.UserProfile;
import eu.eudat.queryable.QueryableList;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
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) {
Principal principal = authenticationServiceImpl.Touch(credentials);
if (principal == null) throw new UnauthorisedException("Could not Sign In User");

View File

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

View File

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

View File

@ -31,7 +31,7 @@ public class FacebookTokenValidator implements TokenValidator {
private FacebookServiceProvider facebookServiceProvider;
@Autowired
public FacebookTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) {
public FacebookTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment;
this.apiContext = apiContext;
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.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.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
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.core.env.Environment;
import org.springframework.social.linkedin.api.LinkedIn;
@ -30,7 +30,7 @@ public class LinkedInTokenValidator implements TokenValidator {
private LinkedInServiceProvider linkedInServiceProvider;
@Autowired
public LinkedInTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) {
public LinkedInTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment;
this.apiContext = apiContext;
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.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.TokenValidatorFactoryImpl;
import eu.eudat.logic.services.ApiContext;
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.core.env.Environment;
import org.springframework.social.oauth1.AuthorizedRequestToken;
@ -32,7 +32,7 @@ public class TwitterTokenValidator implements TokenValidator {
private TwitterServiceProvider twitterServiceProvider;
@Autowired
public TwitterTokenValidator(Environment environment, ApiContext apiContext, AuthenticationServiceImpl authenticationServiceImpl) {
public TwitterTokenValidator(ApiContext apiContext, Environment environment, AuthenticationServiceImpl authenticationServiceImpl) {
this.environment = environment;
this.apiContext = apiContext;
this.authenticationServiceImpl = authenticationServiceImpl;
@ -55,7 +55,7 @@ public class TwitterTokenValidator implements TokenValidator {
user.setEmail((String) values.get("email"));
user.setAvatarUrl(profile.getProfileImageUrl());
user.setIsVerified(true); //TODO
user.setId(""+profile.getId());
user.setId("" + profile.getId());
user.setName(profile.getName());
user.setProvider(TokenValidatorFactoryImpl.LoginProvider.TWITTER);
user.setSecret(finalOauthToken.getValue());

View File

@ -1,21 +1,22 @@
package eu.eudat.logic.services.operations;
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.entities.Credential;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.data.entities.UserRole;
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.loginprovider.LoginProviderUser;
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 org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
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());
if (user == null) return null;
String json;
String avatarUrl;
try {
json = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("data").get("avatar").get("url").asText() : "";
} catch (IOException e) {
json = "";
avatarUrl = user.getAdditionalinfo() != null ? new ObjectMapper().readTree(user.getAdditionalinfo()).get("avatarUrl").asText() : "";
} catch (Exception e) {
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)
.id(user.getId()).token(token.getToken())
.expiresAt(token.getExpiresAt()).name(user.getName())
.avatarUrl(json)
.avatarUrl(avatarUrl)
.culture(culture)
.language(language)
.timezone(timezone)
.build();
List<UserRole> userRoles = apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().getUserRoles(user);
for (UserRole item : userRoles) {
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)
.name(profile.getName()).verified_email(profile.getIsVerified())
.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)
.build();
@ -135,8 +158,11 @@ public class AuthenticationServiceImpl implements AuthenticationService {
apiContext.getOperationsContext().getDatabaseRepository().getUserRoleDao().createOrUpdate(role);
} 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.setAdditionalinfo("{\"data\":{\"avatar\":{\"url\":\""+profile.getAvatarUrl()+"\"}}}");
userInfo.setAdditionalinfo(new JSONObject(additionalInfo).toString());
Set<Credential> credentials = userInfo.getCredentials();
if (credentials.contains(credential)) {
Credential oldCredential = credentials.stream().filter(item -> credential.getProvider().equals(item.getProvider())).findFirst().get();

View File

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

View File

@ -239,4 +239,8 @@ public class DatabaseRepositoryImpl implements DatabaseRepository {
public void setDatasetServiceDao(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
public OperationsContextImpl(DatabaseRepository databaseRepository, ApplicationContext applicationContext, RemoteFetcher remoteFetcher
, BuilderFactory builderFactory, FileStorageService fileStorageService,DatasetRepository datasetRepository) {
, BuilderFactory builderFactory, FileStorageService fileStorageService, DatasetRepository datasetRepository) {
this.databaseRepository = databaseRepository;
this.applicationContext = applicationContext;
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.Invitation;
import javax.mail.MessagingException;
import java.util.List;
@ -14,7 +15,7 @@ public interface InvitationService {
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 org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import java.util.List;
import java.util.UUID;
@ -28,7 +29,7 @@ public class InvitationServiceImpl implements InvitationService {
}
@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) {
Invitation invitation = new Invitation();
invitation.setDmp(dmp);
@ -37,15 +38,15 @@ public class InvitationServiceImpl implements InvitationService {
invitation.setToken(UUID.randomUUID());
invitation.setAcceptedInvitation(false);
invitationDao.createOrUpdate(invitation);
sendInvitation(dmp, invitation, mailService);
sendInvitation(dmp, invitation, userInfo.getName(), mailService);
}
}
@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();
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());
mailService.sendSimpleMail(mail);
}
@ -55,9 +56,11 @@ public class InvitationServiceImpl implements InvitationService {
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());
content = content.replace("{invitationID}", invitationID.toString());
content = content.replace("{recipient}", recipient);
return content;
}
}

View File

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

View File

@ -1,27 +1,42 @@
package eu.eudat.logic.services.utilities;
import eu.eudat.models.data.mail.SimpleMail;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
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.stereotype.Service;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
@Service("mailService")
public class MailServiceImpl implements MailService {
@Autowired
private Environment env;
@Autowired
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
public void sendSimpleMail(SimpleMail mail) {
SimpleMailMessage message = new SimpleMailMessage();
public void sendSimpleMail(SimpleMail mail) throws MessagingException {
MimeMessage message = this.emailSender.createMimeMessage();
message.setSubject(mail.getSubject());
message.setText(mail.getContent());
message.setTo(mail.getTo());
message.setText(mail.getContent(), "utf-8", "html");
message.addRecipients(Message.RecipientType.TO, mail.getTo());
message.setFrom(env.getProperty("mail.from"));
this.emailSender.send(message);
}
@ -31,8 +46,17 @@ public class MailServiceImpl implements MailService {
}
@Override
public String getMailTemplateContent() {
return env.getProperty("mail.content");
public String getMailTemplateContent() {
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

View File

@ -14,6 +14,9 @@ public class Principal {
private Date expiresAt;
private String avatarUrl;
private Set<Authorities> authorities;
private String culture;
private String language;
private String timezone;
public UUID getId() {
return id;
@ -59,6 +62,30 @@ public class Principal {
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
public Set<Authorities> getAuthz() {
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.starttls.enable=true
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
########################FACEBOOK LOGIN Properties#############################
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
},
"@angular/material": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-6.1.0.tgz",
"integrity": "sha512-9FLWjVnHFzAoGSWU5dz8X/QYeBtZGijMJIp1k94QDYz+2xA10IbesEgnv8I5Ri3EPnjV/gCspeSkt1ClLc95CA==",
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@angular/material/-/material-6.4.6.tgz",
"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": {
"tslib": "^1.7.1"
}
@ -716,9 +733,9 @@
"dev": true
},
"@types/selenium-webdriver": {
"version": "2.53.43",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-2.53.43.tgz",
"integrity": "sha512-UBYHWph6P3tutkbXpW6XYg9ZPbTKjw/YC2hGG1/GEvWwTbvezBUv3h+mmUFw79T3RFPnmedpiXdOBbXX+4l0jg==",
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz",
"integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==",
"dev": true
},
"@types/strip-bom": {
@ -1027,9 +1044,9 @@
"optional": true
},
"adm-zip": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.4.tgz",
"integrity": "sha1-ph7VrmkFw66lizplfSUDMJEFJzY=",
"version": "0.4.11",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
"integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
"dev": true
},
"after": {
@ -1953,6 +1970,15 @@
"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": {
"version": "4.9.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
@ -4065,8 +4091,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"aproba": {
"version": "1.2.0",
@ -4087,14 +4112,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -4109,20 +4132,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"core-util-is": {
"version": "1.0.2",
@ -4239,8 +4259,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"ini": {
"version": "1.3.5",
@ -4252,7 +4271,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -4267,7 +4285,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -4275,14 +4292,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -4301,7 +4316,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -4382,8 +4396,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"object-assign": {
"version": "4.1.1",
@ -4395,7 +4408,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -4481,8 +4493,7 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"safer-buffer": {
"version": "2.1.2",
@ -4518,7 +4529,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4538,7 +4548,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -4582,14 +4591,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
"dev": true,
"optional": true
"dev": true
}
}
},
@ -7903,6 +7910,19 @@
"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": {
"version": "1.0.1",
"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": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/original/-/original-1.0.1.tgz",
@ -9147,15 +9161,16 @@
}
},
"protractor": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/protractor/-/protractor-5.3.2.tgz",
"integrity": "sha512-pw4uwwiy5lHZjIguxNpkEwJJa7hVz+bJsvaTI+IbXlfn2qXwzbF8eghW/RmrZwE2sGx82I8etb8lVjQ+JrjejA==",
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.0.tgz",
"integrity": "sha512-6TSYqMhUUzxr4/wN0ttSISqPMKvcVRXF4k8jOEpGWD8OioLak4KLgfzHK9FJ49IrjzRrZ+Mx1q2Op8Rk0zEcnQ==",
"dev": true,
"requires": {
"@types/node": "^6.0.46",
"@types/q": "^0.0.32",
"@types/selenium-webdriver": "~2.53.39",
"@types/selenium-webdriver": "^3.0.0",
"blocking-proxy": "^1.0.0",
"browserstack": "^1.5.1",
"chalk": "^1.1.3",
"glob": "^7.0.3",
"jasmine": "2.8.0",
@ -9165,15 +9180,21 @@
"saucelabs": "^1.5.0",
"selenium-webdriver": "3.6.0",
"source-map-support": "~0.4.0",
"webdriver-js-extender": "^1.0.0",
"webdriver-js-extender": "2.0.0",
"webdriver-manager": "^12.0.6"
},
"dependencies": {
"adm-zip": {
"version": "0.4.11",
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
"integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
"dev": true
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"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": {
"version": "2.2.1",
@ -9181,6 +9202,24 @@
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"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": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
@ -9209,6 +9248,23 @@
"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": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
@ -9223,38 +9279,148 @@
"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": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"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": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
"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": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
},
"webdriver-manager": {
"version": "12.0.6",
"resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.0.6.tgz",
"integrity": "sha1-PfGkgZdwELTL+MnYXHpXeCjA5ws=",
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"dev": true,
"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",
"del": "^2.2.0",
"glob": "^7.0.3",
"ini": "^1.3.4",
"minimist": "^1.2.0",
"q": "^1.4.1",
"request": "^2.78.0",
"request": "^2.87.0",
"rimraf": "^2.5.2",
"semver": "^5.3.0",
"xml2js": "^0.4.17"
@ -9320,6 +9486,12 @@
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"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": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
@ -12170,66 +12342,13 @@
}
},
"webdriver-js-extender": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz",
"integrity": "sha1-gcUzqeM9W/tZe05j4s2yW1R3dRU=",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.0.0.tgz",
"integrity": "sha512-fbyKiVu3azzIc5d4+26YfuPQcFTlgFQV5yQ/0OQj4Ybkl4g1YQuIPskf5v5wqwRJhHJnPHthB6tqCjWHOKLWag==",
"dev": true,
"requires": {
"@types/selenium-webdriver": "^2.53.35",
"selenium-webdriver": "^2.53.2"
},
"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"
}
}
"@types/selenium-webdriver": "^3.0.0",
"selenium-webdriver": "^3.0.1"
}
},
"webpack": {

View File

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

View File

@ -12,7 +12,7 @@ const appRoutes: Routes = [
data: {
breadcrumb: true
},
canActivate: [AuthGuard]
//canActivate: [AuthGuard]
},
{
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 { Observable } from 'rxjs/Observable';
import { AuthService } from './services/auth/auth.service';
import { CultureService } from './utilities/culture/culture-service';
import { environment } from '../environments/environment';
declare const gapi: any;
@ -28,12 +30,10 @@ export class AppComponent implements OnInit {
private authentication: AuthService,
private translate: TranslateService,
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
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');
this.initializeServices()
}
onActivate(event: any) {
@ -73,5 +73,14 @@ export class AppComponent implements OnInit {
goToProjects() {
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 { PageNotFoundComponent } from './not-found.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 { HelpContentService } from './services/help-content/help-content.service';
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 { UrlUtilities } from './utilities/UrlUtilities';
import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-resolver.service';
import { MAT_DATE_LOCALE } from '@angular/material';
import { CultureService } from './utilities/culture/culture-service';
@NgModule({
declarations: [
@ -103,7 +105,18 @@ import { BreadCrumbResolverService } from './services/breadcrumb/breadcrumb-reso
HelpContentService,
LanguageService,
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]
})

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 { ExternalSourcesService } from '../services/external-sources/external-sources.service';
import { ExternalSourcesConfigurationService } from '../services/external-sources/external-sources-configuration.service';
import { DatasetPublicListingComponent } from './dataset-public/dataset-public-listing.component';
@NgModule({
imports: [
CommonModule,
@ -43,13 +44,15 @@ import { ExternalSourcesConfigurationService } from '../services/external-source
declarations: [
DatasetListingComponent,
DatasetEditorComponent,
DatasetWizardComponent
DatasetWizardComponent,
DatasetPublicListingComponent
],
exports: [
DatasetListingComponent,
DatasetEditorComponent,
DatasetWizardComponent,
DatasetPublicListingComponent,
RouterModule
],
providers: [

View File

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

View File

@ -21,6 +21,8 @@
<mat-icon>queue</mat-icon>{{'DMP-LISTING.ACTIONS.NEW-VERSION' | translate}}</button>
<button mat-menu-item (click)="clone(this.dataManagementPlan.id)">
<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>
<div>
<button mat-icon-button type="button" [matMenuTriggerFor]="actionsMenu">

View File

@ -325,5 +325,7 @@ export class DataManagementPlanEditorComponent implements AfterViewInit, IBreadC
clone(id: String) {
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;
expiresAt: Date;
appRoles: Principal.AppRole[];
avatarUrl: string;
avatarUrl: string;
timezone: string;
language: string;
culture: string;
fromJSONObject(item: any): Principal {
this.id = item.id;
this.token = item.token;
this.name = item.name;
this.expiresAt = item.expiresAt;
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;
}
}

View File

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

View File

@ -9,7 +9,7 @@ import { Observable } from 'rxjs/Observable';
import { DataTableRequest } from '../../models/data-table/DataTableRequest';
import { DataTableData } from '../../models/data-table/DataTableData';
import { HostConfiguration } from 'app/app.constants';
import { HostConfiguration } from '../../app.constants';
@Injectable()
export class UserReferenceService {
@ -51,4 +51,8 @@ export class UserReferenceService {
getRecentActivity(): Observable<any[]> {
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-form-field>
</div> -->
<div class="col-md-4">
<div [ngClass]="isPublic ? 'col-md-6' : 'col-md-4'">
<mat-form-field>
<input matInput placeholder=" {{'CRITERIA.PROJECTS.LIKE'| translate}}" name="datasetCriteriaName" [(ngModel)]="criteria.like"
(ngModelChange)="controlModified()">
<mat-error *ngIf="baseErrorModel['name']">{{baseErrorModel['Criteria.like']}}</mat-error>
</mat-form-field>
</div>
<div class="col-md-4">
<mat-form-field>
<div *ngIf="!isPublic" class="col-md-4">
<mat-form-field >
<mat-select placeholder=" {{'CRITERIA.DATA-SETS.STATUS'| translate}}" name="datasetCriteriastatus" [(ngModel)]="criteria.status"
(ngModelChange)="controlModified()">
<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-form-field>
</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}}"
(inputChange)="filterTags($event)" name="tags" requireMatch>
<ng-template td-chip let-chip="chip">

View File

@ -1,5 +1,5 @@
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 { BaseCriteriaComponent } from '../base/base-criteria.component';
import { ValidationContext, Validation } from '../../../../utilities/validators/ValidationContext';
@ -25,6 +25,8 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
// public form: ProjectType;
// public formStatus: ProjectStatus;
@Input()
public isPublic = false;
public criteria: DatasetCriteria = new DatasetCriteria();
public filteringTagsAsync: boolean = false;
public filteredTags: ExternalSourcesItemModel[];

View File

@ -1,5 +1,5 @@
<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>
</div>
<div class="card-content">

View File

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

View File

@ -5,7 +5,7 @@ import { AuthService } from '../../../services/auth/auth.service';
@Component({
selector: 'app-figurecard',
templateUrl: './figurecard.component.html',
styleUrls: ['./figurecard.component.css']
styleUrls: ['./figurecard.component.scss']
})
export class FigurecardComponent implements OnInit {
@Input() headerIcon: string;
@ -26,6 +26,7 @@ export class FigurecardComponent implements OnInit {
}
navigateToUrl() {
if(!this.isAuthenticated()) return;
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 *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="/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>
<!--<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 {
MatToolbarModule,
MatIconModule,
MatSidenavModule,
MatButtonModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatDialogModule,
MatDatepickerModule,
MatNativeDateModule,
MatInputModule,
MatFormFieldModule,
MatSnackBarModule,
MatAutocompleteModule,
MatExpansionModule,
MatSelectModule,
MatOptionModule,
MatCardModule,
MatProgressBarModule,
MatProgressSpinnerModule,
DateAdapter,
MatTooltipModule,
MatCheckboxModule,
MatTabsModule,
MatStepperModule,
MatRadioModule,
MatMenuModule,
MatListModule,
MatChipsModule,
MatBadgeModule
MatToolbarModule,
MatIconModule,
MatSidenavModule,
MatButtonModule,
MatTableModule,
MatPaginatorModule,
MatSortModule,
MatDialogModule,
MatDatepickerModule,
MatNativeDateModule,
MatInputModule,
MatFormFieldModule,
MatSnackBarModule,
MatAutocompleteModule,
MatExpansionModule,
MatSelectModule,
MatOptionModule,
MatCardModule,
MatProgressBarModule,
MatProgressSpinnerModule,
DateAdapter,
MatTooltipModule,
MatCheckboxModule,
MatTabsModule,
MatStepperModule,
MatRadioModule,
MatMenuModule,
MatListModule,
MatChipsModule,
MatBadgeModule,
MAT_DATE_LOCALE,
MAT_DATE_FORMATS
} from '@angular/material';
import { CdkTableModule } from '@angular/cdk/table';
import { SnackBarNotificationComponent } from '../components/notificaiton/snack-bar-notification.component';
import { CovalentLayoutModule, CovalentChipsModule, CovalentDialogsModule, CovalentFileModule } from '@covalent/core';
import { CultureService } from '../../utilities/culture/culture-service';
import { MomentDateAdapter } from '@angular/material-moment-adapter';
@NgModule({
imports: [
],
imports: [
],
exports: [
MatToolbarModule,
MatIconModule,
MatSidenavModule,
MatButtonModule,
MatTableModule,
MatPaginatorModule,
CdkTableModule,
MatSortModule,
MatDialogModule,
MatDatepickerModule,
MatNativeDateModule,
MatInputModule,
MatFormFieldModule,
MatSnackBarModule,
MatAutocompleteModule,
MatExpansionModule,
MatSelectModule,
MatOptionModule,
MatCardModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatTooltipModule,
MatCheckboxModule,
MatTabsModule,
CovalentLayoutModule,
CovalentChipsModule,
CovalentDialogsModule,
CovalentFileModule,
MatStepperModule,
MatRadioModule,
MatMenuModule,
MatListModule,
exports: [
MatToolbarModule,
MatIconModule,
MatSidenavModule,
MatButtonModule,
MatTableModule,
MatPaginatorModule,
CdkTableModule,
MatSortModule,
MatDialogModule,
MatDatepickerModule,
MatNativeDateModule,
MatInputModule,
MatFormFieldModule,
MatSnackBarModule,
MatAutocompleteModule,
MatExpansionModule,
MatSelectModule,
MatOptionModule,
MatCardModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatTooltipModule,
MatCheckboxModule,
MatTabsModule,
CovalentLayoutModule,
CovalentChipsModule,
CovalentDialogsModule,
CovalentFileModule,
MatStepperModule,
MatRadioModule,
MatMenuModule,
MatListModule,
MatChipsModule,
MatBadgeModule
],
MatBadgeModule,
providers: [
//{ provide: DateAdapter, useClass: LocalizedDateAdapter },
],
],
entryComponents: [
SnackBarNotificationComponent
]
providers: [
],
entryComponents: [
SnackBarNotificationComponent
]
})
export class MaterialModule {
// constructor(dateAdapter: DateAdapter<LocalizedDateAdapter>) {
// dateAdapter.setLocale('el-GR');
// }
// constructor(dateAdapter: DateAdapter<LocalizedDateAdapter>) {
// 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 { UserDialogComponent } from './components/user-dialog/user-dialog.component';
import { SearchBarComponent } from './components/search-bar/search-bar.component';
import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe';
@NgModule({
imports: [

View File

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

View File

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

View File

@ -3,7 +3,7 @@
<mat-card-content>
<div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex>
<img mat-card-avatar [src]="userProfile.additionalinfo.data.avatar.url">
<img mat-card-avatar [src]="userProfile.additionalinfo.avatarUrl">
</div>
<mat-card-title>{{userProfile.name}}</mat-card-title>
<mat-card-subtitle>{{userProfile.email}}</mat-card-subtitle>
@ -18,7 +18,8 @@
</div>
<div>
<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>
{{ dmp.label }}
</div>
@ -35,15 +36,55 @@
</mat-card-content>
</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>
<div fxLayout="column" fxLayoutAlign="center center">
<div fxFlex>
<h4>{{ 'USER-PROFILE.SETTINGS' | translate}}</h4>
<div class="container">
<div class="row">
<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>
</mat-card-content>
</mat-card>
</div>
<ng-template #loading>
Loading stuff...
</ng-template>

View File

@ -1,3 +1,10 @@
.clickable{
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 { AuthService } from '../../services/auth/auth.service';
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({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss'],
providers: [
UserReferenceService
UserReferenceService,
CultureService
]
})
export class UserProfileComponent implements OnInit {
user: Observable<UserListingModel>;
currentUserId: string;
cultures: Observable<CultureInfo[]>;
timezones: Observable<any[]>;
editMode = false;
languages = availableLanguages;
formGroup: FormGroup;
constructor(
private userReferenceService: UserReferenceService,
private route: ActivatedRoute,
private router: Router,
private authService: AuthService,
private language: TranslateService
private language: TranslateService,
private cultureService: CultureService,
private translate: TranslateService,
) { }
ngOnInit() {
this.route.params.subscribe((params: Params) => {
this.currentUserId = 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) {
@ -60,4 +88,46 @@ export class UserProfileComponent implements OnInit {
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 { BaseHttpService } from '../utilities/cite-http-service-module/base-http.service';
import { UserProfileComponent } from './profile/user-profile.component';
import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfoDisplayPipe';
@NgModule({
imports: [
@ -40,12 +41,12 @@ import { UserProfileComponent } from './profile/user-profile.component';
UsersComponent,
UsersCriteriaComponent,
UserRoleEditorComponent,
UserProfileComponent
UserProfileComponent,
TimezoneInfoDisplayPipe
],
providers: [
BaseHttpService,
UserReferenceService
],
exports: [
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",
"DMPS": "DMPs",
"DATASETS": "Datasets",
"PUBLIC-DATASETS": "Public Datasets",
"USERS": "Users",
"DATASETS-ADMIN": "Dataset Profiles",
"DMP-PROFILES": "DMP Profiles",
@ -181,7 +182,7 @@
"PERIOD-TO": "Project End",
"PROJECT-STATE-TYPE": "Project Status",
"TYPES": {
"ON-GOING": "OnGoing",
"ON-GOING": "On Going",
"FINISHED": "Finished"
}
},
@ -324,7 +325,12 @@
"EXIT": "Exit "
},
"USER-PROFILE": {
"SETTINGS": "Settings",
"SETTINGS": {
"TITLE": "Settings",
"TIMEZONE": "Time Zone",
"CULTURE": "Culture",
"LANGUAGE": "Language"
},
"ASSOCIATED-DMPS": "Associated DMPs",
"DMPS": {
"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 = {
production: true,
Server: 'http://localhost:8080/api/',
Server: 'http://dl043.madgik.di.uoa.gr:8080/api/',
App: 'http://dl043.madgik.di.uoa.gr/',
HelpServiceUrl: 'http://dl043.madgik.di.uoa.gr:5555/'
};

View File

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

View File

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