Commit bf475dd2 by Tuomas Riihimäki

Deploy-commit

1 parent 8930f7aa
Showing with 1984 additions and 721 deletions
...@@ -37,4 +37,14 @@ public interface ApiApplicationBeanLocal { ...@@ -37,4 +37,14 @@ public interface ApiApplicationBeanLocal {
ApiApplication findApplication(String appKey); ApiApplication findApplication(String appKey);
String findUsernameForApikey(String appkey, String userkey, String domain); String findUsernameForApikey(String appkey, String userkey, String domain);
ApiApplication createApiApplication(ApiApplication apiApp);
ApiApplication findApplication(Integer id);
ApiApplication saveApiApplication(ApiApplication apiApp);
List<ApiApplicationInstance> findInstances(ApiApplication apiApp);
ApiApplicationInstance saveApiInstance(ApiApplicationInstance selectedInstance);
} }
...@@ -24,6 +24,7 @@ import javax.resource.spi.IllegalStateException; ...@@ -24,6 +24,7 @@ import javax.resource.spi.IllegalStateException;
import fi.codecrew.moya.enums.apps.IAppPermission; import fi.codecrew.moya.enums.apps.IAppPermission;
import fi.codecrew.moya.enums.apps.SpecialPermission; import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.Role;
import fi.codecrew.moya.model.User; import fi.codecrew.moya.model.User;
@Local @Local
...@@ -61,6 +62,7 @@ public interface PermissionBeanLocal { ...@@ -61,6 +62,7 @@ public interface PermissionBeanLocal {
String getPrincipalName(); String getPrincipalName();
// boolean hasPermission(String perm); // boolean hasPermission(String perm);
} }
...@@ -147,6 +147,8 @@ public interface UserBeanLocal { ...@@ -147,6 +147,8 @@ public interface UserBeanLocal {
boolean isUserInRole(EventUser user, Integer roleId); boolean isUserInRole(EventUser user, Integer roleId);
boolean isUserInRole(EventUser user, Role role);
EventUser getOtherEventsEventuser(User user, LanEvent event); EventUser getOtherEventsEventuser(User user, LanEvent event);
/** /**
...@@ -219,4 +221,5 @@ public interface UserBeanLocal { ...@@ -219,4 +221,5 @@ public interface UserBeanLocal {
List<EventUser> findAllEventusers(User user); List<EventUser> findAllEventusers(User user);
Map<Role,List<String>> findUsersRolesWithReason(EventUser user); Map<Role,List<String>> findUsersRolesWithReason(EventUser user);
} }
...@@ -22,10 +22,7 @@ import java.util.List; ...@@ -22,10 +22,7 @@ import java.util.List;
import javax.ejb.Local; import javax.ejb.Local;
import fi.codecrew.moya.model.Compo; import fi.codecrew.moya.model.*;
import fi.codecrew.moya.model.CompoEntry;
import fi.codecrew.moya.model.CompoEntryFile;
import fi.codecrew.moya.model.Vote;
@Local @Local
public interface VotingBeanLocal { public interface VotingBeanLocal {
...@@ -59,4 +56,9 @@ public interface VotingBeanLocal { ...@@ -59,4 +56,9 @@ public interface VotingBeanLocal {
public List<CompoEntry> getEntriesForCurrentUser(); public List<CompoEntry> getEntriesForCurrentUser();
Compo saveFiletype(CompoFileType filetype);
Compo deleteFiletype(CompoFileType ft);
CompoEntryFileType findEntryFileType(Integer entryId, Integer typeId);
} }
...@@ -24,10 +24,8 @@ import java.util.List; ...@@ -24,10 +24,8 @@ import java.util.List;
import javax.annotation.security.DeclareRoles; import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB; import javax.ejb.*;
import javax.ejb.EJBException; import javax.security.jacc.EJBMethodPermission;
import javax.ejb.LocalBean;
import javax.ejb.Singleton;
import fi.codecrew.moya.enums.apps.SpecialPermission; import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.facade.ApiApplicationFacade; import fi.codecrew.moya.facade.ApiApplicationFacade;
...@@ -47,7 +45,7 @@ import org.slf4j.LoggerFactory; ...@@ -47,7 +45,7 @@ import org.slf4j.LoggerFactory;
*/ */
@Singleton @Singleton
@LocalBean @LocalBean
@DeclareRoles(SpecialPermission.S_SUPERADMIN) @DeclareRoles({SpecialPermission.S_SUPERADMIN, SpecialPermission.S_USER})
public class ApiApplicationBean implements ApiApplicationBeanLocal { public class ApiApplicationBean implements ApiApplicationBeanLocal {
@EJB @EJB
...@@ -71,6 +69,7 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal { ...@@ -71,6 +69,7 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal {
UserBean userBean; UserBean userBean;
private static final Logger logger = LoggerFactory.getLogger(ApiApplicationBean.class); private static final Logger logger = LoggerFactory.getLogger(ApiApplicationBean.class);
/** /**
* Default constructor. * Default constructor.
*/ */
...@@ -142,6 +141,69 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal { ...@@ -142,6 +141,69 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal {
@Override @Override
@RolesAllowed(SpecialPermission.S_USER) @RolesAllowed(SpecialPermission.S_USER)
public ApiApplication createApiApplication(ApiApplication apiApp) {
if (apiApp.getDeveloper() == null) {
apiApp.setDeveloper(permissionBean.getCurrentUser().getUser());
}
if (apiApp.getApplicationKey() == null || apiApp.getApplicationKey().isEmpty()) {
apiApp.setApplicationKey(PasswordFunctions.generateRandomString(20, PasswordFunctions.ALL_CHARS));
}
if (apiApp.getApplicationKey().length() < 8) {
throw new EJBException("Application key musst be at least 8 characters long");
}
if (!permissionBean.hasPermission(SpecialPermission.SUPERADMIN) && !permissionBean.isCurrentUser(apiApp.getDeveloper())) {
throw new EJBAccessException("Trying to create application for different user");
}
apiApp.setCreated(new Date());
applicationFacade.create(apiApp);
return apiApp;
}
@Override
@RolesAllowed(SpecialPermission.S_USER)
public ApiApplication findApplication(Integer id) {
ApiApplication ret = applicationFacade.find(id);
if (!permissionBean.isCurrentUser(ret.getDeveloper()) && !permissionBean.hasPermission(SpecialPermission.SUPERADMIN)) {
throw new EJBAccessException("Trying to return apiapp for wrong user");
}
return ret;
}
@Override
@RolesAllowed(SpecialPermission.S_USER)
public ApiApplication saveApiApplication(ApiApplication apiApp) {
if (!permissionBean.isCurrentUser(apiApp.getDeveloper()) && permissionBean.hasPermission(SpecialPermission.SUPERADMIN)) {
throw new EJBAccessException("Trying to save apiapp for another user");
}
return applicationFacade.merge(apiApp);
}
@Override
@RolesAllowed(SpecialPermission.S_USER)
public List<ApiApplicationInstance> findInstances(ApiApplication apiApp) {
return instanceFacade.findForUser(permissionBean.getCurrentUser(), apiApp);
}
@Override
@RolesAllowed(SpecialPermission.S_USER)
public ApiApplicationInstance saveApiInstance(ApiApplicationInstance instance) {
if (instance.getEventuser() == null) {
instance.setEventuser(permissionBean.getCurrentUser());
}
if (!permissionBean.isCurrentUser(instance.getEventuser()) && !permissionBean.hasPermission(SpecialPermission.SUPERADMIN)) {
throw new EJBAccessException("Trying to create apiInstance to foreign user");
}
if (instance.getId() == null) {
instanceFacade.create(instance);
return instance;
}
return instanceFacade.merge(instance);
}
@Override
@RolesAllowed(SpecialPermission.S_USER)
public List<ApiApplication> findMyApplications() { public List<ApiApplication> findMyApplications() {
EventUser curruser = permissionBean.getCurrentUser(); EventUser curruser = permissionBean.getCurrentUser();
return applicationFacade.findForUser(curruser); return applicationFacade.findForUser(curruser);
...@@ -153,4 +215,5 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal { ...@@ -153,4 +215,5 @@ public class ApiApplicationBean implements ApiApplicationBeanLocal {
return applicationFacade.findAll(); return applicationFacade.findAll();
} }
} }
...@@ -595,7 +595,37 @@ public class BootstrapBean implements BootstrapBeanLocal { ...@@ -595,7 +595,37 @@ public class BootstrapBean implements BootstrapBeanLocal {
"ALTER TABLE users_event_userproperties ADD CONSTRAINT FK_users_event_userproperties_property_id FOREIGN KEY (property_id) REFERENCES event_userproperties (id)", "ALTER TABLE users_event_userproperties ADD CONSTRAINT FK_users_event_userproperties_property_id FOREIGN KEY (property_id) REFERENCES event_userproperties (id)",
"ALTER TABLE users_event_userproperties ADD CONSTRAINT FK_users_event_userproperties_user_id FOREIGN KEY (user_id) REFERENCES event_users (id)" "ALTER TABLE users_event_userproperties ADD CONSTRAINT FK_users_event_userproperties_user_id FOREIGN KEY (user_id) REFERENCES event_users (id)"
}); });
dbUpdates.add(new String[]{
"ALTER TABLE compo_entry_files ADD COLUMN type_id INTEGER",
"CREATE TABLE compo_file_types (id SERIAL NOT NULL, description TEXT, filetype TEXT, meta jsonb, name TEXT, required BOOLEAN, SORT INTEGER NOT NULL, compo_id INTEGER NOT NULL, PRIMARY KEY (id))",
"ALTER TABLE compo_entry_files ADD CONSTRAINT FK_compo_entry_files_type_id FOREIGN KEY (type_id) REFERENCES compo_file_types (id)",
"ALTER TABLE compo_file_types ADD CONSTRAINT FK_compo_file_types_compo_id FOREIGN KEY (compo_id) REFERENCES compos (id)"
});
dbUpdates.add(new String[]{
"ALTER TABLE compo_entry_files RENAME TO old_compo_entry_file",
"CREATE TABLE compo_entry_files (id SERIAL NOT NULL, description TEXT, file_name TEXT, filepath TEXT NOT NULL, hash TEXT, meta jsonb, mime_type TEXT, uploaded TIMESTAMPTZ NOT NULL, entryfiletype_id INTEGER NOT NULL, PRIMARY KEY (id))",
"CREATE TABLE compo_entry_file_types (id SERIAL NOT NULL, meta jsonb, updated TIMESTAMPTZ NOT NULL, current_file_id INTEGER, entry_id INTEGER NOT NULL, type_id INTEGER NOT NULL, PRIMARY KEY (id))",
"ALTER TABLE compo_entry_file_types ADD CONSTRAINT UNQ_compo_entry_file_types_0 UNIQUE (entry_id, type_id)",
"ALTER TABLE compo_entry_file_types ADD CONSTRAINT FK_compo_entry_file_types_type_id FOREIGN KEY (type_id) REFERENCES compo_file_types (id)",
"ALTER TABLE compo_entry_file_types ADD CONSTRAINT FK_compo_entry_file_types_current_file_id FOREIGN KEY (current_file_id) REFERENCES compo_entry_files (id)",
"ALTER TABLE compo_entry_file_types ADD CONSTRAINT FK_compo_entry_file_types_entry_id FOREIGN KEY (entry_id) REFERENCES compo_entries (id)",
"ALTER TABLE compo_entry_files ADD CONSTRAINT FK_compo_entry_files_entryfiletype_id FOREIGN KEY (entryfiletype_id) REFERENCES compo_entry_file_types (id)",
});
dbUpdates.add(new String[]{
"CREATE TABLE compo_voting_schemes (id SERIAL NOT NULL, allow_recusal BOOLEAN NOT NULL, max_value DECIMAL(24,8), meta jsonb, min_value DECIMAL(24,8), name TEXT NOT NULL, type TEXT NOT NULL, value_increment DECIMAL(24,8), event_id INTEGER NOT NULL, PRIMARY KEY (id))",
"CREATE TABLE compo_voting_roles (id SERIAL NOT NULL, meta jsonb, multiplier DECIMAL(24,8) NOT NULL, override_max DECIMAL(24,8), override_min DECIMAL(24,8), override_others BOOLEAN NOT NULL, PRIORITY INTEGER NOT NULL, role_id INTEGER NOT NULL, scheme_id INTEGER NOT NULL, PRIMARY KEY (id))",
"ALTER TABLE COMPOS ADD COLUMN entrysubmit_role_id INTEGER, ADD COLUMN voting_scheme_id INTEGER",
"ALTER TABLE compo_voting_schemes ADD CONSTRAINT FK_compo_voting_schemes_event_id FOREIGN KEY (event_id) REFERENCES events (id)",
"ALTER TABLE compos ADD CONSTRAINT FK_compos_voting_scheme_id FOREIGN KEY (voting_scheme_id) REFERENCES compo_voting_schemes (id)",
"ALTER TABLE compo_voting_roles ADD CONSTRAINT UNQ_compo_voting_roles_0 UNIQUE (scheme_id, role_id)",
"ALTER TABLE compo_voting_roles ADD CONSTRAINT FK_compo_voting_roles_scheme_id FOREIGN KEY (scheme_id) REFERENCES compo_voting_schemes (id)",
"ALTER TABLE compo_voting_roles ADD CONSTRAINT FK_compo_voting_roles_role_id FOREIGN KEY (role_id) REFERENCES roles (id)",
});
} }
......
...@@ -28,6 +28,7 @@ import javax.resource.spi.IllegalStateException; ...@@ -28,6 +28,7 @@ import javax.resource.spi.IllegalStateException;
import fi.codecrew.moya.enums.apps.*; import fi.codecrew.moya.enums.apps.*;
import fi.codecrew.moya.facade.EventFacade; import fi.codecrew.moya.facade.EventFacade;
import fi.codecrew.moya.model.LanEvent; import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.Role;
import fi.codecrew.moya.utilities.UserLoginUtils; import fi.codecrew.moya.utilities.UserLoginUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -127,6 +128,8 @@ public class PermissionBean implements PermissionBeanLocal { ...@@ -127,6 +128,8 @@ public class PermissionBean implements PermissionBeanLocal {
@EJB @EJB
private EventBean eventbean; private EventBean eventbean;
@EJB
private UserBean userbean;
@Override @Override
......
...@@ -998,6 +998,12 @@ public class UserBean implements UserBeanLocal { ...@@ -998,6 +998,12 @@ public class UserBean implements UserBeanLocal {
} }
@Override @Override
public boolean isUserInRole(EventUser user, Role role) {
return role != null && isUserInRole(user, role.getId());
}
@Override
public User getUser(Integer id) { public User getUser(Integer id) {
User ret = userFacade.find(id); User ret = userFacade.find(id);
......
...@@ -48,47 +48,50 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat { ...@@ -48,47 +48,50 @@ public class BasicAuthPBean extends ApiAuth implements AuthenticationFormat {
AuthenticationResult ret = null; AuthenticationResult ret = null;
//String username = UserLoginUtils.getUsernameFromJaasString(jaasUsername); //String username = UserLoginUtils.getUsernameFromJaasString(jaasUsername);
if (password.startsWith(HEADER_PREFIX)) { if (!password.startsWith(HEADER_PREFIX)) {
ret = new AuthenticationResult(); return null;
ret.setUsertype(UserType.REST.name()); }
try { ret = new AuthenticationResult();
String domain = UserLoginUtils.getDomainFromJaasString(username); ret.setUsertype(UserType.REST.name());
LanEvent event = eventbean.getEventForHostname(domain);
String[] pwdsplit = password.split(" "); try {
if (pwdsplit.length != 2) { String domain = UserLoginUtils.getDomainFromJaasString(username);
logger.warn("Rest auth with Basic failed because pwdsplit != 2: user '{}''", username ); LanEvent event = eventbean.getEventForHostname(domain);
return null;
} String[] pwdsplit = password.split(" ");
// There is a possibility that user has a password that starts with "Basic ". To combat this, if (pwdsplit.length != 2) {
// we chech that the authdata is really a base64 string. If not, we continue trying with other methods logger.warn("Rest auth with Basic failed because pwdsplit != 2: user '{}''", username);
String authStr = null; return null;
try { }
authStr = new String(Base64.getDecoder().decode(pwdsplit[1]), UTF8); // There is a possibility that user has a password that starts with "Basic ". To combat this,
} catch (IllegalArgumentException ie) { // we check that the authdata is really a base64 string. If not, we continue trying with other methods
return null; String authStr = null;
} try {
String[] splitStr = authStr.split(PASSWORD_DELIMITER); authStr = new String(Base64.getDecoder().decode(pwdsplit[1]), UTF8);
if (splitStr.length != 4 || !PASSWORD_PREFIX.equals(splitStr[0])) { } catch (IllegalArgumentException ie) {
logger.warn( return null;
"Invalid Basic authentication string '{}'. Authstring must start with {}, followed by appid and app pass", }
authStr, PASSWORD_PREFIX); String[] splitStr = authStr.split(PASSWORD_DELIMITER);
return null; if (splitStr.length != 4 || !PASSWORD_PREFIX.equals(splitStr[0])) {
} logger.warn(
final String appId = splitStr[1]; "Invalid Basic authentication string '{}'. Authstring must start with {}, followed by appid and app pass",
final String userId = splitStr[2]; authStr, PASSWORD_PREFIX);
final String appKey = splitStr[3]; return null;
}
final String appId = splitStr[1];
final String userId = splitStr[2];
final String appKey = splitStr[3];
ApiApplicationInstance appInstance = verifyAppInstance(appId, userId, event); ApiApplicationInstance appInstance = verifyAppInstance(appId, userId, event);
if (appInstance != null && appKey != null && !appKey.isEmpty() && appKey.equals(appInstance.getSecretKey())) { if (appInstance != null && appKey != null && !appKey.isEmpty() && appKey.equals(appInstance.getSecretKey())) {
ret.setUsername(username); ret.setUsername(username);
}
} catch (Exception e) {
ret = null;
logger.warn("Invalid base64 string on Rest Basic auth: " + password, e);
} }
} catch (Exception e) {
ret = null;
logger.warn("Invalid base64 string on Rest Basic auth: " + password, e);
} }
return ret; return ret;
} }
......
...@@ -61,7 +61,7 @@ public class ApiApplicationFacade extends IntegerPkGenericFacade<ApiApplication> ...@@ -61,7 +61,7 @@ public class ApiApplicationFacade extends IntegerPkGenericFacade<ApiApplication>
CriteriaBuilder cb = getEm().getCriteriaBuilder(); CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<ApiApplication> q = cb.createQuery(ApiApplication.class); CriteriaQuery<ApiApplication> q = cb.createQuery(ApiApplication.class);
Root<ApiApplication> root = q.from(ApiApplication.class); Root<ApiApplication> root = q.from(ApiApplication.class);
q.where(cb.equal(root.get(ApiApplication_.developer), curruser)); q.where(cb.equal(root.get(ApiApplication_.developer), curruser.getUser()));
return getEm().createQuery(q).getResultList(); return getEm().createQuery(q).getResultList();
......
...@@ -26,6 +26,8 @@ import javax.persistence.criteria.Root; ...@@ -26,6 +26,8 @@ import javax.persistence.criteria.Root;
import fi.codecrew.moya.model.*; import fi.codecrew.moya.model.*;
import java.util.List;
@Stateless @Stateless
@LocalBean @LocalBean
public class ApiApplicationInstanceFacade extends IntegerPkGenericFacade<ApiApplicationInstance> { public class ApiApplicationInstanceFacade extends IntegerPkGenericFacade<ApiApplicationInstance> {
...@@ -57,4 +59,16 @@ public class ApiApplicationInstanceFacade extends IntegerPkGenericFacade<ApiAppl ...@@ -57,4 +59,16 @@ public class ApiApplicationInstanceFacade extends IntegerPkGenericFacade<ApiAppl
return super.getSingleNullableResult(getEm().createQuery(q)); return super.getSingleNullableResult(getEm().createQuery(q));
} }
public List<ApiApplicationInstance> findForUser(EventUser currentUser, ApiApplication apiApp) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<ApiApplicationInstance> q = cb.createQuery(ApiApplicationInstance.class);
Root<ApiApplicationInstance> root = q.from(ApiApplicationInstance.class);
q.where(
cb.equal(root.get(ApiApplicationInstance_.application), apiApp),
cb.equal(root.get(ApiApplicationInstance_.eventuser), currentUser)
);
return getEm().createQuery(q).getResultList();
}
} }
...@@ -38,7 +38,7 @@ public class CompoEntryFileFacade extends IntegerPkGenericFacade<CompoEntryFile> ...@@ -38,7 +38,7 @@ public class CompoEntryFileFacade extends IntegerPkGenericFacade<CompoEntryFile>
super(CompoEntryFile.class); super(CompoEntryFile.class);
} }
/*
public List<CompoEntryFile> findFor(CompoEntry entry) { public List<CompoEntryFile> findFor(CompoEntry entry) {
CriteriaBuilder cb = getEm().getCriteriaBuilder(); CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<CompoEntryFile> cq = cb.createQuery(CompoEntryFile.class); CriteriaQuery<CompoEntryFile> cq = cb.createQuery(CompoEntryFile.class);
...@@ -47,5 +47,6 @@ public class CompoEntryFileFacade extends IntegerPkGenericFacade<CompoEntryFile> ...@@ -47,5 +47,6 @@ public class CompoEntryFileFacade extends IntegerPkGenericFacade<CompoEntryFile>
cq.where(cb.equal(root.get(CompoEntryFile_.entry), entry)); cq.where(cb.equal(root.get(CompoEntryFile_.entry), entry));
return getEm().createQuery(cq).getResultList(); return getEm().createQuery(cq).getResultList();
} }
*/
} }
package fi.codecrew.moya.facade;
import fi.codecrew.moya.model.*;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
@Stateless
@LocalBean
public class CompoEntryFileTypeFacade extends IntegerPkGenericFacade<CompoEntryFileType> {
public CompoEntryFileTypeFacade() {
super(CompoEntryFileType.class);
}
public CompoEntryFileType findForEntryAndType(Integer entryId, Integer typeId) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<CompoEntryFileType> cq = cb.createQuery(CompoEntryFileType.class);
Root<CompoEntryFileType> root = cq.from(CompoEntryFileType.class);
cq.where(
cb.equal(root.get(CompoEntryFileType_.entry).get(CompoEntry_.id), entryId),
cb.equal(root.get(CompoEntryFileType_.type).get(CompoFileType_.id), typeId)
);
return getSingleNullableResult(getEm().createQuery(cq));
}
}
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.facade; package fi.codecrew.moya.facade;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.ejb.LocalBean; import javax.ejb.LocalBean;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import fi.codecrew.moya.beans.EventBeanLocal; import fi.codecrew.moya.beans.EventBeanLocal;
import fi.codecrew.moya.model.Compo; import fi.codecrew.moya.model.Compo;
import fi.codecrew.moya.model.Compo_; import fi.codecrew.moya.model.Compo_;
import fi.codecrew.moya.model.LanEvent;
@Stateless
@LocalBean @Stateless
public class CompoFacade extends IntegerPkGenericFacade<Compo> { @LocalBean
@EJB public class CompoFacade extends IntegerPkGenericFacade<Compo> {
private EventBeanLocal eventbean; @EJB
private EventBeanLocal eventbean;
public CompoFacade() {
super(Compo.class); public CompoFacade() {
} super(Compo.class);
}
public List<Compo> getList(boolean showHidden) {
CriteriaBuilder cb = getEm().getCriteriaBuilder(); public List<Compo> getList(boolean showHidden) {
CriteriaQuery<Compo> cq = cb.createQuery(Compo.class); CriteriaBuilder cb = getEm().getCriteriaBuilder();
Root<Compo> root = cq.from(Compo.class); CriteriaQuery<Compo> cq = cb.createQuery(Compo.class);
Root<Compo> root = cq.from(Compo.class);
ArrayList<Predicate> preds = new ArrayList<>();
preds.add(cb.equal(root.get(Compo_.event), eventbean.getCurrentEvent())); ArrayList<Predicate> preds = new ArrayList<>();
if (!showHidden) { preds.add(cb.equal(root.get(Compo_.event), eventbean.getCurrentEvent()));
preds.add(cb.isFalse(root.get(Compo_.hidden))); if (!showHidden) {
} preds.add(cb.isFalse(root.get(Compo_.hidden)));
cq.where(preds.toArray(new Predicate[preds.size()])); }
cq.orderBy(cb.desc(root.get(Compo_.startTime))); cq.where(preds.toArray(new Predicate[preds.size()]));
List<Compo> ret = getEm().createQuery(cq).getResultList(); cq.orderBy(cb.desc(root.get(Compo_.startTime)));
return ret; List<Compo> ret = getEm().createQuery(cq).getResultList();
} return ret;
} }
@Override
public Compo find(Integer id) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<Compo> cq = cb.createQuery(Compo.class);
Root<Compo> root = cq.from(Compo.class);
cq.where(cb.equal(root.get(Compo_.id), id), cb.equal(root.get(Compo_.event), eventbean.getCurrentEvent()));
return super.getSingleNullableResult(getEm().createQuery(cq));
}
}
/*
* Copyright Codecrew Ry
*
* All rights reserved.
*
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
*
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* copyright owner.
*
* A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in
* future versions of the Software.
*
*/
package fi.codecrew.moya.facade;
import fi.codecrew.moya.model.*;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
@Stateless
@LocalBean
public class CompoFileTypeFacade extends IntegerPkGenericFacade<CompoFileType> {
public CompoFileTypeFacade() {
super(CompoFileType.class);
}
}
...@@ -142,12 +142,12 @@ public class ApiApplication extends GenericEntity { ...@@ -142,12 +142,12 @@ public class ApiApplication extends GenericEntity {
this.readerType = readerType; this.readerType = readerType;
} }
public List<ApiApplicationInstance> getInstances() { private List<ApiApplicationInstance> getInstances() {
return instances; throw new RuntimeException("DO NOT USE. Only for metamodel generation");
} }
public void setInstances(List<ApiApplicationInstance> instances) { public void setInstances(List<ApiApplicationInstance> instances) {
this.instances = instances; throw new RuntimeException("DO NOT USE. Only for metamodel generation");
} }
} }
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
/* /*
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
...@@ -72,7 +72,7 @@ public class Compo extends GenericEntity { ...@@ -72,7 +72,7 @@ public class Compo extends GenericEntity {
/** /**
* When the voting should start * When the voting should start
* *
* @see {@link #holdVoting} * @see {@link #holdVoting}
*/ */
@Column(name = "vote_start") @Column(name = "vote_start")
...@@ -109,14 +109,6 @@ public class Compo extends GenericEntity { ...@@ -109,14 +109,6 @@ public class Compo extends GenericEntity {
@Column(name = "hidden", nullable = false) @Column(name = "hidden", nullable = false)
private boolean hidden = false; private boolean hidden = false;
public boolean isHidden() {
return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
/** /**
* Entries submitted to participate this compo. * Entries submitted to participate this compo.
*/ */
...@@ -124,6 +116,19 @@ public class Compo extends GenericEntity { ...@@ -124,6 +116,19 @@ public class Compo extends GenericEntity {
@OrderBy("sort") @OrderBy("sort")
private List<CompoEntry> compoEntries; private List<CompoEntry> compoEntries;
@OneToMany(mappedBy = "compo")
@OrderBy("sort")
private List<CompoFileType> filetypes;
@ManyToOne()
@JoinColumn(name = "entrysubmit_role_id",referencedColumnName = "id")
private Role entrysubmitRole;
@ManyToOne()
@JoinColumn(name = "voting_scheme_id", referencedColumnName = "id")
private CompoVotingScheme votingScheme;
public Compo(String compoName, boolean holdVoting) { public Compo(String compoName, boolean holdVoting) {
this(); this();
...@@ -131,18 +136,24 @@ public class Compo extends GenericEntity { ...@@ -131,18 +136,24 @@ public class Compo extends GenericEntity {
this.holdVoting = holdVoting; this.holdVoting = holdVoting;
} }
public boolean isSubmit() public boolean isHidden() {
{ return hidden;
}
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
public boolean isSubmit() {
Date now = new Date(); Date now = new Date();
return now.after(getSubmitStart()) && now.before(getSubmitEnd()); return now.after(getSubmitStart()) && now.before(getSubmitEnd());
} }
public boolean isVote() public boolean isVote() {
{
Date now = new Date(); Date now = new Date();
return !getHoldVoting() && return !getHoldVoting() &&
now.after(getVoteStart()) && now.after(getVoteStart()) &&
now.before(getVoteEnd()); now.before(getVoteEnd());
} }
public Compo() { public Compo() {
...@@ -229,8 +240,7 @@ public class Compo extends GenericEntity { ...@@ -229,8 +240,7 @@ public class Compo extends GenericEntity {
} }
/** /**
* @param maxParticipantCount * @param maxParticipantCount the maxParticipantCount to set
* the maxParticipantCount to set
*/ */
public void setMaxParticipantCount(int maxParticipantCount) { public void setMaxParticipantCount(int maxParticipantCount) {
this.maxParticipantCount = maxParticipantCount; this.maxParticipantCount = maxParticipantCount;
...@@ -252,4 +262,31 @@ public class Compo extends GenericEntity { ...@@ -252,4 +262,31 @@ public class Compo extends GenericEntity {
this.endTime = endTime; this.endTime = endTime;
} }
public boolean isHoldVoting() {
return holdVoting;
}
public List<CompoFileType> getFiletypes() {
return filetypes;
}
public void setFiletypes(List<CompoFileType> filetypes) {
this.filetypes = filetypes;
}
public Role getEntrysubmitRole() {
return entrysubmitRole;
}
public void setEntrysubmitRole(Role entrysubmitRole) {
this.entrysubmitRole = entrysubmitRole;
}
public CompoVotingScheme getVotingScheme() {
return votingScheme;
}
public void setVotingScheme(CompoVotingScheme votingScheme) {
this.votingScheme = votingScheme;
}
} }
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
/* /*
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
package fi.codecrew.moya.model; package fi.codecrew.moya.model;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
...@@ -39,7 +40,7 @@ import javax.persistence.Temporal; ...@@ -39,7 +40,7 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
/** /**
* *
*/ */
@Entity @Entity
@Table(name = "compo_entries") @Table(name = "compo_entries")
...@@ -74,9 +75,8 @@ public class CompoEntry extends GenericEntity { ...@@ -74,9 +75,8 @@ public class CompoEntry extends GenericEntity {
@Column(name = "final_position") @Column(name = "final_position")
private Integer finalPosition; private Integer finalPosition;
@JoinColumn(name = "current_file_id", referencedColumnName = CompoEntryFile.ID_COLUMN) @OneToMany(mappedBy = "entry")
@OneToOne private List<CompoEntryFileType> filetypes = new ArrayList<>();
private CompoEntryFile currentFile;
@OneToMany(mappedBy = "compoEntry") @OneToMany(mappedBy = "compoEntry")
private List<Vote> votes; private List<Vote> votes;
...@@ -93,8 +93,7 @@ public class CompoEntry extends GenericEntity { ...@@ -93,8 +93,7 @@ public class CompoEntry extends GenericEntity {
@ManyToOne @ManyToOne
private EventUser creator; private EventUser creator;
public Integer getVotetotal() public Integer getVotetotal() {
{
int votetotal = 0; int votetotal = 0;
for (Vote v : getVotes()) { for (Vote v : getVotes()) {
votetotal += v.getScore(); votetotal += v.getScore();
...@@ -151,7 +150,7 @@ public class CompoEntry extends GenericEntity { ...@@ -151,7 +150,7 @@ public class CompoEntry extends GenericEntity {
} }
public void setParticipants( public void setParticipants(
List<CompoEntryParticipant> compoEntryParticipantList) { List<CompoEntryParticipant> compoEntryParticipantList) {
this.participants = compoEntryParticipantList; this.participants = compoEntryParticipantList;
} }
...@@ -195,4 +194,11 @@ public class CompoEntry extends GenericEntity { ...@@ -195,4 +194,11 @@ public class CompoEntry extends GenericEntity {
this.author = author; this.author = author;
} }
public List<CompoEntryFileType> getFiletypes() {
return filetypes;
}
public void setFiletypes(List<CompoEntryFileType> filetypes) {
this.filetypes = filetypes;
}
} }
...@@ -26,6 +26,7 @@ package fi.codecrew.moya.model; ...@@ -26,6 +26,7 @@ package fi.codecrew.moya.model;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Column; import javax.persistence.Column;
...@@ -49,6 +50,9 @@ import org.slf4j.LoggerFactory; ...@@ -49,6 +50,9 @@ import org.slf4j.LoggerFactory;
@Table(name = "compo_entry_files") @Table(name = "compo_entry_files")
public class CompoEntryFile extends GenericEntity { public class CompoEntryFile extends GenericEntity {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(CompoEntryFile.class);
@Column(name = "mime_type") @Column(name = "mime_type")
private String mimeType; private String mimeType;
...@@ -62,28 +66,21 @@ public class CompoEntryFile extends GenericEntity { ...@@ -62,28 +66,21 @@ public class CompoEntryFile extends GenericEntity {
@Column(name = "hash", updatable = false) @Column(name = "hash", updatable = false)
private String hash; private String hash;
@Lob @Column(name="filepath", updatable = false, nullable = false)
@Column(name = "file_data", updatable = false) private String filepath;
@Basic(fetch = FetchType.LAZY)
private byte[] fileData;
@Column(name = "uploaded", nullable = false) @Column(name = "uploaded", nullable = false)
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
private Calendar uploaded = Calendar.getInstance(); private Date uploaded = new Date();
@ManyToOne(optional=false)
@JoinColumn(name="entryfiletype_id", referencedColumnName = "id", nullable = false, updatable = false)
private CompoEntryFileType filetype;
@JoinColumn(name = "entry_id", referencedColumnName = "id", nullable = false, updatable = false)
@ManyToOne(optional = false)
private CompoEntry entry;
private static final Logger logger = LoggerFactory.getLogger(CompoEntryFile.class);
public CompoEntryFile() { public CompoEntryFile() {
super(); super();
} }
public CompoEntryFile(CompoEntry entry) {
this.entry = entry;
}
public String getMimeType() { public String getMimeType() {
return mimeType; return mimeType;
} }
...@@ -116,42 +113,28 @@ public class CompoEntryFile extends GenericEntity { ...@@ -116,42 +113,28 @@ public class CompoEntryFile extends GenericEntity {
this.hash = hash; this.hash = hash;
} }
public byte[] getFileData() { public Date getUploaded() {
return fileData;
}
public void setFileData(byte[] fileData) {
this.fileData = fileData;
this.hash = getShaChecksum(fileData);
}
public Calendar getUploaded() {
return uploaded; return uploaded;
} }
public void setUploaded(Calendar uploaded) { public void setUploaded(Date uploaded) {
this.uploaded = uploaded; this.uploaded = uploaded;
} }
public CompoEntry getEntriesId() {
return entry; public CompoEntryFileType getFiletype() {
return filetype;
} }
public void setEntriesId(CompoEntry entriesId) { public void setFiletype(CompoEntryFileType filetype) {
this.entry = entriesId; this.filetype = filetype;
} }
public static String getShaChecksum(byte[] data) public String getFilepath() {
{ return filepath;
String ret = "ERROR CALCULATING CHECKSUM!";
try {
MessageDigest algo = MessageDigest.getInstance("SHA");
algo.update(data);
ret = new String(Hex.encodeHex(algo.digest())).toLowerCase();
} catch (NoSuchAlgorithmException e) {
logger.warn("Error calculating checksum", e);
}
return ret;
} }
public void setFilepath(String filepath) {
this.filepath = filepath;
}
} }
package fi.codecrew.moya.model;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
import static fi.codecrew.moya.model.CompoEntryFileType.ENTRY_ID_COLUMN;
import static fi.codecrew.moya.model.CompoEntryFileType.TYPE_ID_COLUMN;
@Entity
@Table(name = "compo_entry_file_types", uniqueConstraints = @UniqueConstraint(columnNames = {ENTRY_ID_COLUMN, TYPE_ID_COLUMN}))
public class CompoEntryFileType extends GenericEntity {
public static final String ENTRY_ID_COLUMN = "entry_id";
public static final String TYPE_ID_COLUMN = "type_id";
@ManyToOne(optional = false)
@JoinColumn(name = ENTRY_ID_COLUMN, nullable = false, updatable = false)
private CompoEntry entry;
@ManyToOne(optional = false)
@JoinColumn(name = TYPE_ID_COLUMN, nullable = false, updatable = false)
private CompoFileType type;
@ManyToOne(optional = false)
@JoinColumn(name = "current_file_id")
private CompoEntryFile currentFile;
@OneToMany(mappedBy = "filetype")
// This is here only for metamodel generation.
private List<CompoEntryFile> entryFiles;
@Temporal(TemporalType.TIMESTAMP)
@Column(name="updated", nullable = false)
private Date updated = new Date();
public CompoEntry getEntry() {
return entry;
}
public void setEntry(CompoEntry entry) {
this.entry = entry;
}
public CompoFileType getType() {
return type;
}
public void setType(CompoFileType type) {
this.type = type;
}
public CompoEntryFile getCurrentFile() {
return currentFile;
}
public void setCurrentFile(CompoEntryFile currentFile) {
this.currentFile = currentFile;
}
public Date getUpdated() {
return updated;
}
public void setUpdated(Date updated) {
this.updated = updated;
}
public List<CompoEntryFile> getEntryFiles() {
return entryFiles;
}
public void setEntryFiles(List<CompoEntryFile> entryFiles) {
this.entryFiles = entryFiles;
}
}
package fi.codecrew.moya.model;
import javax.persistence.*;
import java.util.List;
@Table(name = "compo_file_types")
@Entity
public class CompoFileType extends GenericEntity {
public enum FileType {
DATA, THUMBNAIL, MUSIC_PREVIEW
}
@ManyToOne(optional = false)
@JoinColumn(name = "compo_id", nullable = false, updatable = false)
private Compo compo;
/*
@OneToMany(mappedBy = "filetype")
// Only here for metamodel.. Do not create getter and setter!
private List<CompoEntryFile> entryfiles;
*/
@Lob
@Column(name = "name")
private String name;
@Lob
@Column(name = "description")
private String description;
@Column(nullable = false)
private int sort = 100;
@Column(name = "required")
private boolean required = false;
@Enumerated(EnumType.STRING)
@Column(name = "filetype")
private FileType filetype = FileType.DATA;
public Compo getCompo() {
return compo;
}
public void setCompo(Compo compo) {
this.compo = compo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public FileType getFiletype() {
return filetype;
}
public void setFiletype(FileType filetype) {
this.filetype = filetype;
}
}
package fi.codecrew.moya.model;
import javax.persistence.*;
import java.math.BigDecimal;
import static fi.codecrew.moya.model.CompoVotingRole.SCHEME_ID_COLUMN;
import static fi.codecrew.moya.model.CompoVotingRole.ROLE_ID_COLUMN;
@Table(name = "compo_voting_roles", uniqueConstraints = @UniqueConstraint(columnNames = {SCHEME_ID_COLUMN, ROLE_ID_COLUMN}))
@Entity
public class CompoVotingRole extends GenericEntity {
static final String SCHEME_ID_COLUMN = "scheme_id";
static final String ROLE_ID_COLUMN = "role_id";
@ManyToOne()
@JoinColumn(nullable = false, updatable = false, name = SCHEME_ID_COLUMN)
private CompoVotingScheme scheme;
@Column(nullable = false)
private int priority = 100;
@ManyToOne
@JoinColumn(nullable = false, updatable = false, name = ROLE_ID_COLUMN)
private Role role;
@Column(nullable = false, precision = 24, scale = 8, name = "multiplier")
private BigDecimal multiplier = BigDecimal.ONE;
@Column(name = "override_min", scale = 24, precision = 8)
private BigDecimal overrideMin;
@Column(name = "override_max", scale = 24, precision = 8)
private BigDecimal overrideMax;
@Column(nullable = false, name = "override_others")
private boolean overrideOthers = false;
public CompoVotingScheme getScheme() {
return scheme;
}
public void setScheme(CompoVotingScheme scheme) {
this.scheme = scheme;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public BigDecimal getMultiplier() {
return multiplier;
}
public void setMultiplier(BigDecimal multiplier) {
this.multiplier = multiplier;
}
public BigDecimal getOverrideMin() {
return overrideMin;
}
public void setOverrideMin(BigDecimal overrideMin) {
this.overrideMin = overrideMin;
}
public BigDecimal getOverrideMax() {
return overrideMax;
}
public void setOverrideMax(BigDecimal overrideMax) {
this.overrideMax = overrideMax;
}
public boolean isOverrideOthers() {
return overrideOthers;
}
public void setOverrideOthers(boolean overrideOthers) {
this.overrideOthers = overrideOthers;
}
}
package fi.codecrew.moya.model;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.List;
@Table(name = "compo_voting_schemes")
@Entity
public class CompoVotingScheme extends GenericEntity {
public enum SchemeType {
INT_TO_ALL_ENTRIES,
SORT_BEST_N,
}
@ManyToOne(optional = false)
@JoinColumn(nullable = false, updatable = false, name = "event_id")
private LanEvent event;
@Enumerated(EnumType.STRING)
@Column(nullable = false, name = "type")
private SchemeType type = SchemeType.INT_TO_ALL_ENTRIES;
@Column(nullable = false, name = "name")
private String name;
@OneToMany(mappedBy = "scheme")
@OrderBy("priority")
private List<CompoVotingRole> votingRoles;
@Column(name = "min_value", scale = 24, precision = 8)
private BigDecimal minValue = BigDecimal.ONE;
@Column(name = "max_value", scale = 24, precision = 8)
private BigDecimal maxValue = BigDecimal.TEN;
@Column(name = "value_increment", scale = 24, precision = 8)
private BigDecimal valueIncrement = BigDecimal.ONE;
@Column(name = "allow_recusal", nullable = false)
private boolean allowRecusal = false;
public LanEvent getEvent() {
return event;
}
public void setEvent(LanEvent event) {
this.event = event;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<CompoVotingRole> getVotingRoles() {
return votingRoles;
}
public void setVotingRoles(List<CompoVotingRole> votingRoles) {
this.votingRoles = votingRoles;
}
public BigDecimal getMinValue() {
return minValue;
}
public void setMinValue(BigDecimal minValue) {
this.minValue = minValue;
}
public BigDecimal getMaxValue() {
return maxValue;
}
public void setMaxValue(BigDecimal maxValue) {
this.maxValue = maxValue;
}
public BigDecimal getValueIncrement() {
return valueIncrement;
}
public void setValueIncrement(BigDecimal valueIncrement) {
this.valueIncrement = valueIncrement;
}
public boolean isAllowRecusal() {
return allowRecusal;
}
public void setAllowRecusal(boolean allowRecusal) {
this.allowRecusal = allowRecusal;
}
public SchemeType getType() {
return type;
}
public void setType(SchemeType type) {
this.type = type;
}
}
...@@ -39,10 +39,10 @@ public class GenericEntity extends EntityEquals implements ModelInterface, Entit ...@@ -39,10 +39,10 @@ public class GenericEntity extends EntityEquals implements ModelInterface, Entit
private static final long serialVersionUID = -9041737052951021560L; private static final long serialVersionUID = -9041737052951021560L;
@Id @Id
@Column(name = ID_COLUMN, nullable = false, updatable = false) @Column(name = ID_COLUMN, nullable = false, updatable = false, columnDefinition = "SERIAL NOT NULL")
private Integer id; private Integer id;
@Column(name = "meta", columnDefinition = "json") @Column(name = "meta", columnDefinition = "jsonb")
private JsonObject meta; private JsonObject meta;
@Override @Override
......
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
<property name="eclipselink.target-server" value="Glassfish" /> <property name="eclipselink.target-server" value="Glassfish" />
<property name="eclipselink.session.customizer" <property name="eclipselink.session.customizer"
value="fi.codecrew.moya.database.eclipselink.MoyaSessionCustomizer" /> value="fi.codecrew.moya.database.eclipselink.MoyaSessionCustomizer" />
<property name="eclipselink.ddl-generation" value="none"/> <property name="eclipselink.ddl-generation" value="create-tables"/>
<!--property name="eclipselink.ddl-generation" value="create-tables"/-->
<property name="eclipselink.ddl-generation.output-mode" value="sql-script"/> <property name="eclipselink.ddl-generation.output-mode" value="sql-script"/>
</properties> </properties>
......
...@@ -15,6 +15,7 @@ public enum SystemProperty { ...@@ -15,6 +15,7 @@ public enum SystemProperty {
MOYA_IRC_SERVER, MOYA_IRC_SERVER,
MOYA_IRC_CHANNEL("#moya-debug"), MOYA_IRC_CHANNEL("#moya-debug"),
MOYA_IRC_SERVERPASS(), MOYA_IRC_SERVERPASS(),
MOYA_COMPOFILE_DIR("/tmp/moya"),
; ;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<f:metadata> <f:metadata>
<f:event type="preRenderView" <f:event type="preRenderView"
listener="#{applicationApiView.initApplicationListView}" /> listener="#{applicationApiView.initSuperApplicationListView}" />
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<button></button> <button></button>
......
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="#{sessionHandler.template}">
<f:metadata>
<f:viewParam name="id" value="#{apiAppEditView.id}"/>
<f:event type="preRenderView"
listener="#{apiAppEditView.initEdit}"/>
</f:metadata>
<ui:define name="content">
<h1>#{i18n['apiapp.edit.applist']}</h1>
<h:form id="appedit">
<p:panelGrid columns="3">
<h:outputText for="appkey" value="#{i18n['apiapp.appkey']}"/>
<p:inplace>
<f:facet name="output">
******** (Click to view and edit)
</f:facet>
<f:facet name="input">
<p:inputText size="30" id="appkey" redisplay="true" value="#{apiAppEditView.apiApp.applicationKey}"/>
</f:facet>
</p:inplace>
<h:message for="appkey"/>
<h:outputText for="appname" value="#{i18n['apiapp.name']}"/>
<p:inputText size="30" id="appname" value="#{apiAppEditView.apiApp.name}"/>
<h:message for="appname"/>
<h:outputText for="appdesc" value="#{i18n['apiapp.description']}"/>
<p:inputText size="30" id="appdesc" value="#{apiAppEditView.apiApp.description}"/>
<h:message for="appdesc"/>
</p:panelGrid>
<p:commandButton ajax="false" action="#{apiAppEditView.save}" value="#{i18n['apiapp.save']}"/>
</h:form>
<h2><h:outputText value="#{i18n['apiInstance.my.header']}"/></h2>
<p:commandButton value="#{i18n['apiInstance.create']}" action="#{apiAppEditView.initCreateInstance}" type="button" onclick="PF('createInstanceDlg').show();"/>
<p:dialog header="Create api instance" widgetVar="createInstanceDlg" closable="true" dynamic="true">
<h:form>
<p:panelGrid columns="3">
<h:outputText for="appinstevent" value="#{i18n['apiapp.event']}"/>
<h:outputText size="30" id="appinstevent" value="#{apiAppEditView.selectedInstance.eventuser.event.name}"/>
<h:message for="appinstevent"/>
<h:outputText for="appinstuser" value="#{i18n['apiapp.event']}"/>
<h:outputText size="30" id="appinstuser" value="(#{apiAppEditView.selectedInstance.eventuser.user.id}) #{apiAppEditView.selectedInstance.eventuser.user.wholeName}"/>
<h:message for="appinstuser"/>
<h:outputText for="appinstcreated" value="#{i18n['apiapp.created']}"/>
<h:outputText size="30" id="appinstcreated" value="#{apiAppEditView.selectedInstance.created}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}"/>
</h:outputText>
<h:message for="appinstcreated"/>
<h:outputText for="appinstenabled" value="#{i18n['apiapp.enabled']}"/>
<p:selectBooleanCheckbox id="appinstenabled" value="#{apiAppEditView.selectedInstance.enabled}"/>
<h:message for="appinstenabled"/>
<h:outputText for="appinstname" value="#{i18n['apiapp.name']}"/>
<p:inputText size="30" id="appinstname" value="#{apiAppEditView.selectedInstance.name}"/>
<h:message for="appinstname"/>
<h:outputText for="appinstnotes" value="#{i18n['apiapp.notes']}"/>
<p:inputText size="30" id="appinstnotes" value="#{apiAppEditView.selectedInstance.notes}"/>
<h:message for="appinstnotes"/>
<h:outputText for="appinstkey" value="#{i18n['apiapp.secretKey']}"/>
<p:inputText size="40" id="appinstkey" value="#{apiAppEditView.selectedInstance.secretKey}"/>
<h:message for="appinstkey"/>
</p:panelGrid>
<p:commandButton value="#{i18n['apiapp.save']}" action="#{apiAppEditView.saveInstance}"/>
</h:form>
</p:dialog>
<p:dataTable value="#{apiAppEditView.apiInstances}" var="instance">
<p:column width="80" headerText="#{i18n['apiInstance.enabled']}"> <h:outputText value="#{instance.enabled}"/> </p:column>
<p:column headerText="#{i18n['apiInstance.created']}"> <h:outputText value="#{instance.created}"/> </p:column>
<p:column headerText="#{i18n['apiIntance.name']}"> <h:outputText value="#{instance.name}"/> </p:column>
<p:column headerText="#{i18n['apiInstance.userWholename']}"> <h:outputText value="#{instance.eventuser.wholeName}"/> </p:column>
<p:column headerText="#{i18n['apiInstance.event']}"><h:outputText value="#{instance.eventuser.event.name}"/></p:column>
<p:column><p:commandButton value="#{i18n['apiInstance.edit']}" action="#{apiAppEditView.selectInstance}" oncomplete="PF('createInstanceDlg').show();"/></p:column>
</p:dataTable>
</ui:define>
</ui:composition>
</h:body>
</html>
\ No newline at end of file
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core" xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"> xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:event type="preRenderView" <f:event type="preRenderView"
listener="#{applicationApiView.initApplicationListView}" /> listener="#{applicationApiView.initApplicationListView}"/>
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<button></button> <h:form>
<h:panelGrid columns="2">
<div style="display:none;" id="createApp"> <p:outputLabel for="newappName" value="#{i18n['apiapp.name']}" />
<p:inputText id="newappName" value="#{applicationApiView.newApplication.name}" required="true"/>
</div> </h:panelGrid>
<p:commandButton ajax="false" action="#{applicationApiView.createApp()}" value="#{i18n['apiapp.create']}"/>
</h:form>
<h1>#{i18n['apiapp.edit.applist']}</h1> <h1>#{i18n['apiapp.edit.applist']}</h1>
...@@ -27,20 +29,20 @@ ...@@ -27,20 +29,20 @@
<p:dataTable value="#{applicationApiView.applist}" var="app"> <p:dataTable value="#{applicationApiView.applist}" var="app">
<p:column headerText="#{i18n['apiapp.name']}"> <p:column headerText="#{i18n['apiapp.name']}">
<h:outputText value="#{app.name}" /> <h:link outcome="/api/edit?id=#{app.id}"><h:outputText value="#{app.name}"/></h:link>
</p:column> </p:column>
<p:column headerText="#{i18n['apiapp.description']"> <p:column headerText="#{i18n['apiapp.description']}">
<h:outputText value="#{app.description}" /> <h:outputText value="#{app.description}"/>
</p:column> </p:column>
<p:column> <p:column headerText="#{i18n['apiapp.created']}">
<h:outputText value="#{app.created}"> <h:outputText value="#{app.created}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}"
timeZone="#{sessionHandler.timezone}" /> timeZone="#{sessionHandler.timezone}"/>
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['apiapp.enabled']}"> <p:column headerText="#{i18n['apiapp.enabled']}">
<h:outputText value="#{app.enabled}" /> <h:outputText value="#{app.enabled}"/>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
......
...@@ -14,51 +14,59 @@ ...@@ -14,51 +14,59 @@
<h:form> <h:form>
<h:panelGrid columns="3"> <h:panelGrid columns="3">
<h:outputLabel value="#{i18n['voting.create.name']}:" for="name" /> <p:outputLabel value="#{i18n['voting.create.name']}:" for="name" />
<h:inputText value="#{compoMgmtView.compo.name}" id="name" /> <p:inputText value="#{compoMgmtView.compo.name}" id="name" />
<h:message for="name" /> <p:message for="name" />
<h:outputLabel value="#{i18n['voting.create.description']}:" for="desc" /> <p:outputLabel value="#{i18n['voting.create.description']}:" for="desc" />
<h:inputText value="#{compoMgmtView.compo.description}" id="desc" /> <p:inputText value="#{compoMgmtView.compo.description}" id="desc" />
<h:message for="desc" /> <p:message for="desc" />
<h:outputLabel value="#{i18n['voting.create.maxParticipants']}:" for="maxPar" /> <p:outputLabel for="entrysubmitrole" value="#{i18n['voting.create.entrysubmitrole']}:" />
<h:inputText value="#{compoMgmtView.compo.maxParticipantCount}" id="maxPar" /> <p:selectOneMenu id="entrysubmitrole" value="#{compoMgmtView.compo.entrysubmitRole}" converter="#{roleConverter}">
<h:message for="maxPar" /> <f:selectItem itemLabel="----" />
<f:selectItems value="#{roleDataView.roleList}" var="r" itemLabel="#{r.name}" />
<h:outputLabel value="#{i18n['voting.create.holdVoting']}:" for="holdVoting" /> </p:selectOneMenu>
<h:selectBooleanCheckbox value="#{compoMgmtView.compo.holdVoting}" id="holdVoting" /> <p:message for="entrysubmitrole" />
<h:message for="holdVoting" />
<h:outputLabel value="#{i18n['voting.create.hidden']}:" for="hidden" /> <p:outputLabel value="#{i18n['voting.create.maxParticipants']}:" for="maxPar" />
<h:selectBooleanCheckbox value="#{compoMgmtView.compo.hidden}" id="hidden" /> <p:inputText value="#{compoMgmtView.compo.maxParticipantCount}" id="maxPar" />
<h:message for="hidden" /> <p:message for="maxPar" />
<h:outputLabel value="#{i18n['voting.create.compoStart']}:" for="cStart" /> <p:outputLabel value="#{i18n['voting.create.holdVoting']}:" for="holdVoting" />
<p:selectBooleanCheckbox value="#{compoMgmtView.compo.holdVoting}" id="holdVoting" />
<p:message for="holdVoting" />
<p:outputLabel value="#{i18n['voting.create.hidden']}:" for="hidden" />
<p:selectBooleanCheckbox value="#{compoMgmtView.compo.hidden}" id="hidden" />
<p:message for="hidden" />
<p:outputLabel value="#{i18n['voting.create.compoStart']}:" for="cStart" />
<p:calendar validator="#{votingDateValidator.saveCStart}" value="#{compoMgmtView.compo.startTime}" pattern="dd/MM/yyyy HH:mm" id="cStart" /> <p:calendar validator="#{votingDateValidator.saveCStart}" value="#{compoMgmtView.compo.startTime}" pattern="dd/MM/yyyy HH:mm" id="cStart" />
<h:message for="cStart" /> <p:message for="cStart" />
<h:outputLabel value="#{i18n['voting.create.compoEnd']}:" for="cEnd" /> <p:outputLabel value="#{i18n['voting.create.compoEnd']}:" for="cEnd" />
<p:calendar validator="#{votingDateValidator.validateCompo}" value="#{compoMgmtView.compo.endTime}" pattern="dd/MM/yyyy HH:mm" id="cEnd" /> <p:calendar validator="#{votingDateValidator.validateCompo}" value="#{compoMgmtView.compo.endTime}" pattern="dd/MM/yyyy HH:mm" id="cEnd" />
<h:message for="cEnd" /> <p:message for="cEnd" />
<h:outputLabel value="#{i18n['voting.create.voteStart']}:" for="vStart" /> <p:outputLabel value="#{i18n['voting.create.voteStart']}:" for="vStart" />
<p:calendar validator="#{votingDateValidator.saveVStart}" value="#{compoMgmtView.compo.voteStart}" pattern="dd/MM/yyyy HH:mm" id="vStart" /> <p:calendar validator="#{votingDateValidator.saveVStart}" value="#{compoMgmtView.compo.voteStart}" pattern="dd/MM/yyyy HH:mm" id="vStart" />
<h:message for="vStart" /> <p:message for="vStart" />
<h:outputLabel value="#{i18n['voting.create.voteEnd']}:" for="vEnd" /> <p:outputLabel value="#{i18n['voting.create.voteEnd']}:" for="vEnd" />
<p:calendar validator="#{votingDateValidator.validateVote}" value="#{compoMgmtView.compo.voteEnd}" pattern="dd/MM/yyyy HH:mm" id="vEnd" /> <p:calendar validator="#{votingDateValidator.validateVote}" value="#{compoMgmtView.compo.voteEnd}" pattern="dd/MM/yyyy HH:mm" id="vEnd" />
<h:message for="vEnd" /> <p:message for="vEnd" />
<h:outputLabel value="#{i18n['voting.create.submitStart']}:" for="sStart" /> <p:outputLabel value="#{i18n['voting.create.submitStart']}:" for="sStart" />
<p:calendar validator="#{votingDateValidator.saveSStart}" value="#{compoMgmtView.compo.submitStart}" pattern="dd/MM/yyyy HH:mm" id="sStart" /> <p:calendar validator="#{votingDateValidator.saveSStart}" value="#{compoMgmtView.compo.submitStart}" pattern="dd/MM/yyyy HH:mm" id="sStart" />
<h:message for="sStart" /> <p:message for="sStart" />
<h:outputLabel value="#{i18n['voting.create.submitEnd']}:" for="sEnd" /> <p:outputLabel value="#{i18n['voting.create.submitEnd']}:" for="sEnd" />
<p:calendar validator="#{votingDateValidator.validateSubmit}" value="#{compoMgmtView.compo.submitEnd}" pattern="dd/MM/yyyy HH:mm" id="sEnd" /> <p:calendar validator="#{votingDateValidator.validateSubmit}" value="#{compoMgmtView.compo.submitEnd}" pattern="dd/MM/yyyy HH:mm" id="sEnd" />
<h:message for="sEnd" /> <p:message for="sEnd" />
<h:commandButton action="#{cc.attrs.commitAction}" id="commitbutton" value="#{cc.attrs.commitValue}" /> <p:commandButton ajax="false" action="#{cc.attrs.commitAction}" id="commitbutton" value="#{cc.attrs.commitValue}" />
</h:panelGrid> </h:panelGrid>
</h:form> </h:form>
......
...@@ -36,20 +36,22 @@ ...@@ -36,20 +36,22 @@
</div> </div>
<p:commandButton ajax="false" action="#{userView.saveRoles}" value="#{i18n['user.saveRoles']}"/> <p:commandButton ajax="false" action="#{userView.saveRoles}" value="#{i18n['user.saveRoles']}"/>
</h:form> </h:form>
<div style="margin-left: 4em;"> <ui:fragment rendered="#{roleView.canReadRoles}">
<h2>All users roles</h2> <div style="margin-left: 4em;">
<p:dataTable style="max-width: 600px;" var="r" value="#{userView.allUsersRoles}"> <h2><h:outputText value="#{i18n['user.allroles']}"/></h2>
<p:column style="width: 30%;"><f:facet name="header"><h:outputText value="#{i18n['role.name']}"/></f:facet><h:outputText value="#{r.key.name}"/></p:column> <p:dataTable style="max-width: 600px;" var="r" value="#{userView.allUsersRoles}">
<p:column> <p:column style="width: 30%;"><f:facet name="header"><h:outputText value="#{i18n['role.name']}"/></f:facet><h:outputText value="#{r.key.name}"/></p:column>
<f:facet name="header"> <p:column>
<h:outputText value="#{i18n['role.source']}"/> <f:facet name="header">
</f:facet> <h:outputText value="#{i18n['role.source']}"/>
<ul><ui:repeat var="src" value="#{r.value}"> </f:facet>
<li>#{i18n['role.source.'+=src]}</li> <ul><ui:repeat var="src" value="#{r.value}">
</ui:repeat></ul> <li>#{i18n['role.source.'+=src]}</li>
</p:column> </ui:repeat></ul>
</p:dataTable> </p:column>
</div> </p:dataTable>
</div>
</ui:fragment>
</div> </div>
</ui:define> </ui:define>
</ui:composition> </ui:composition>
......
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user"
xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:event type="preRenderView" listener="#{compoView.initAdminListView()}" /> <f:event type="preRenderView" listener="#{compoView.initAdminListView()}"/>
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<h:form id="admincompolist" styleClass="moya_datatable2"> <h:form id="admincompolist" styleClass="moya_datatable2">
<h1>#{i18n['voting.allcompos.header']}</h1> <h1>#{i18n['voting.allcompos.header']}</h1>
<p>#{i18n['voting.allcompos.description']}</p> <p>#{i18n['voting.allcompos.description']}</p>
<p:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoView.compos}" var="compo"> <p:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoView.compos}" var="compo">
<p:column headerText="#{i18n['voting.allcompos.name']}"> <p:column headerText="#{i18n['voting.allcompos.name']}">
<h:outputText value="#{compo.name}" /> <h:outputText value="#{compo.compo.name}"/>
</p:column> </p:column>
<!-- <h:column rendered="#{compoView.curEntries}"> --> <!-- <h:column rendered="#{compoView.curEntries}"> -->
...@@ -30,41 +30,40 @@ ...@@ -30,41 +30,40 @@
<!-- <f:facet name="header"> --> <!-- <f:facet name="header"> -->
<!-- <h:outputText value="#{i18n['voting.allcompos.maxParts']}" /> --> <!-- <h:outputText value="#{i18n['voting.allcompos.maxParts']}" /> -->
<!-- </f:facet> --> <!-- </f:facet> -->
<!-- <h:outputText value="#{compo.maxParticipantCount}" /> --> <!-- <h:outputText value="#{compo.compo.maxParticipantCount}" /> -->
<!-- </h:column> --> <!-- </h:column> -->
<p:column headerText="#{i18n['voting.allcompos.startTime']}"> <p:column headerText="#{i18n['voting.allcompos.startTime']}">
<h:outputText value="#{compo.startTime.time}"> <h:outputText value="#{compo.compo.startTime.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}"/>
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['voting.allcompos.voteEnd']}"> <p:column headerText="#{i18n['voting.allcompos.voteEnd']}">
<h:outputText value="#{compo.voteEnd.time}"> <h:outputText value="#{compo.compo.voteEnd.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}"/>
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['voting.allcompos.submitEnd']}"> <p:column headerText="#{i18n['voting.allcompos.submitEnd']}">
<h:outputText value="#{compo.submitEnd.time}"> <h:outputText value="#{compo.compo.submitEnd.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}"/>
</h:outputText> </h:outputText>
</p:column> </p:column>
<p:column headerText="#{i18n['voting.allcompos.holdVoting']}"> <p:column headerText="#{i18n['voting.allcompos.holdVoting']}">
<h:outputText value="#{compo.holdVoting}" /> <h:outputText value="#{compo.compo.holdVoting}"/>
</p:column> </p:column>
<p:column headerText="#{i18n['voting.allcompos.hidden']}"> <p:column headerText="#{i18n['voting.allcompos.hidden']}">
<h:outputText value="#{compo.hidden}" /> <h:outputText value="#{compo.compo.hidden}"/>
</p:column> </p:column>
<p:column> <p:column>
<h:commandButton rendered="#{compo.vote or compoView.manage}" action="#{compoView.startVote()}" value="#{i18n['voting.compo.vote']}" /> <p:commandButton ajax="false" action="#{compoView.startVote()}" value="#{i18n['voting.compo.vote']}"/><br/>
</p:column> <p:link rendered="#{compo.canSubmit}" outcome="/voting/submitEntry" value="#{i18n['voting.compo.submit']}">
<p:column> <f:param name="compoId" value="#{compo.compo.id}"/>
<h:commandButton rendered="#{compo.submit or compoView.manage}" action="#{compoView.submitEntry()}" value="#{i18n['voting.compo.submit']}" /> </p:link>
</p:column> </p:column>
<p:column rendered="#{compoView.manage}"> <p:column rendered="#{compoView.manage}">
<h:link outcome="details" value="#{i18n['compo.edit']}"> <h:link outcome="details" value="#{i18n['compo.edit']}">
<f:param name="compoId" value="#{compo.id}" /> <f:param name="compoId" value="#{compo.compo.id}"/>
</h:link> </h:link>
</p:column> </p:column>
</p:dataTable> </p:dataTable>
......
...@@ -10,70 +10,69 @@ ...@@ -10,70 +10,69 @@
<f:event type="preRenderView" listener="#{compoView.initListView()}" /> <f:event type="preRenderView" listener="#{compoView.initListView()}" />
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<h:outputStylesheet library="style" name="insomnia2/css/actionlog.css" />
<h1>#{i18n['voting.allcompos.header']}</h1>
<p>#{i18n['voting.allcompos.description']}</p>
<h1>#{i18n['voting.allcompos.header']}</h1>
<h:form id="compolist" styleClass="moya_datatable2"> <h:form id="compolist" styleClass="moya_datatable2">
<h:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoView.compos}" var="compo"> <p:dataTable styleClass="bordertable" tableStyle="width: auto;" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoView.compos}" var="compo">
<h:column> <p:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['voting.allcompos.name']}" /> <h:outputText value="#{i18n['voting.allcompos.name']}" />
</f:facet> </f:facet>
<h:outputText value="#{compo.name}" /> <h:outputText value="#{compo.compo.name}" />
</h:column> </p:column>
<!-- <h:column rendered="#{compoView.curEntries}"> --> <!-- <p:column rendered="#{compoView.curEntries}"> -->
<!-- <f:facet name="header"> --> <!-- <f:facet name="header"> -->
<!-- <h:outputText value="#{i18n['voting.allcompos.curEntries']}" /> --> <!-- <h:outputText value="#{i18n['voting.allcompos.curEntries']}" /> -->
<!-- </f:facet> --> <!-- </f:facet> -->
<!-- <h:outputText value="#{compoEntries.size()}" /> --> <!-- <h:outputText value="#{compoEntries.size()}" /> -->
<!-- </h:column> --> <!-- </p:column> -->
<!-- <h:column rendered="#{compoView.maxParts}"> --> <!-- <p:column rendered="#{compoView.maxParts}"> -->
<!-- <f:facet name="header"> --> <!-- <f:facet name="header"> -->
<!-- <h:outputText value="#{i18n['voting.allcompos.maxParts']}" /> --> <!-- <h:outputText value="#{i18n['voting.allcompos.maxParts']}" /> -->
<!-- </f:facet> --> <!-- </f:facet> -->
<!-- <h:outputText value="#{compo.maxParticipantCount}" /> --> <!-- <h:outputText value="#{compo.maxParticipantCount}" /> -->
<!-- </h:column> --> <!-- </p:column> -->
<h:column> <p:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['voting.allcompos.startTime']}" /> <h:outputText value="#{i18n['voting.allcompos.startTime']}" />
</f:facet> </f:facet>
<h:outputText value="#{compo.startTime.time}"> <h:outputText value="#{compo.compo.startTime.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" />
</h:outputText> </h:outputText>
</h:column> </p:column>
<h:column> <p:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['voting.allcompos.voteEnd']}" /> <h:outputText value="#{i18n['voting.allcompos.voteEnd']}" />
</f:facet> </f:facet>
<h:outputText value="#{compo.voteEnd.time}"> <h:outputText value="#{compo.compo.voteEnd.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" />
</h:outputText> </h:outputText>
</h:column> </p:column>
<h:column> <p:column>
<f:facet name="header"> <f:facet name="header">
<h:outputText value="#{i18n['voting.allcompos.submitEnd']}" /> <h:outputText value="#{i18n['voting.allcompos.submitEnd']}" />
</f:facet> </f:facet>
<h:outputText value="#{compo.submitEnd.time}"> <h:outputText value="#{compo.compo.submitEnd.time}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" /> <f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}" />
</h:outputText> </h:outputText>
</h:column> </p:column>
<h:column>
<h:commandButton rendered="#{compo.vote or compoView.manage}" action="#{compoView.startVote()}" value="#{i18n['voting.compo.vote']}" /> <p:column>
</h:column> <p:commandButton rendered="#{compo.canVote}" action="#{compoView.startVote()}" value="#{i18n['voting.compo.vote']}" />
<h:column> <p:link rendered="#{compo.canSubmit}" outcome="/voting/submitEntry" value="#{i18n['voting.compo.submit']}" >
<h:commandButton rendered="#{compo.submit or compoView.manage}" action="#{compoView.submitEntry()}" value="#{i18n['voting.compo.submit']}" /> <f:param name="compoId" value="#{compo.compo.id}" />
</p:link>
</h:column> </p:column>
<h:column rendered="#{compoView.manage}"> <p:column rendered="#{compoView.manage}">
<h:link outcome="details" value="#{i18n['compo.edit']}"> <h:link outcome="details" value="#{i18n['compo.edit']}">
<f:param name="compoId" value="#{compo.id}" /> <f:param name="compoId" value="#{compo.compo.id}" />
</h:link> </h:link>
</h:column> </p:column>
</h:dataTable> </p:dataTable>
</h:form> </h:form>
......
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user"
xmlns:compo="http://java.sun.com/jsf/composite/cditools/compo" xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> xmlns:compo="http://java.sun.com/jsf/composite/cditools/compo" xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:viewParam name="compoId" value="#{compoMgmtView.compoId}" /> <f:viewParam name="compoId" value="#{compoMgmtView.compoId}"/>
<!-- <f:viewParam name="compoId" value="#{compoMgmtView.compoId2}" /> --> <!-- <f:viewParam name="compoId" value="#{compoMgmtView.compoId2}" /> -->
<f:event type="preRenderView" listener="#{compoMgmtView.initView}" /> <f:event type="preRenderView" listener="#{compoMgmtView.initView}"/>
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<!-- <h:outputStylesheet library="style" name="insomnia2/css/actionlog.css" /> --> <!-- <h:outputStylesheet library="style" name="insomnia2/css/actionlog.css" /> -->
<h1>Compo: #{compoMgmtView.compo.name}</h1> <h1>Compo: #{compoMgmtView.compo.name}</h1>
<p>Infoa compon entryistä</p> <p>Infoa compon entryistä</p>
<compo:editCompo commitAction="#{compoMgmtView.saveCompo}" commitValue="#{i18n['voting.create.saveCompo']}" /> <compo:editCompo commitAction="#{compoMgmtView.saveCompo}" commitValue="#{i18n['voting.create.saveCompo']}"/>
<h2>#{i18n['compoMgmtView.compo.entries']}</h2> <h2>Compo filetypes</h2>
<h:form id="filetypeEditform">
<h:form> <p:panelGrid columns="2">
<p:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoMgmtView.entries}" var="entry"> <p:outputLabel for="filetypeid" rendered="#{not empty compoMgmtView.filetype.id}" value="#{i18n['compo.filetype.id']}"/>
<p:column headerText="Title"> <h:outputText id="filetypeid" rendered="#{not empty compoMgmtView.filetype.id}" value="#{compoMgmtView.filetype.id}"/>
<h:outputText value="#{entry.title}" />
</p:column> <p:outputLabel for="filetypename" value="#{i18n['compo.filetype.name']}"/>
<p:column headerText="Author"> <p:inputText id="filetypename" value="#{compoMgmtView.filetype.name}"/>
<h:outputText value="#{entry.author}" />
</p:column> <p:outputLabel for="filetypesort" value="#{i18n['compo.filetype.sort']}"/>
<p:column headerText="Notes"> <p:inputText id="filetypesort" value="#{compoMgmtView.filetype.sort}"/>
<h:outputText value="#{entry.notes}" />
</p:column> <p:outputLabel for="filetypetype" value="#{i18n['compo.filetype.filetype']}"/>
<p:column headerText="Screenmessage"> <p:selectOneMenu id="filetypetype" value="#{compoMgmtView.filetype.filetype}">
<h:outputText value="#{entry.screenMessage}" /> <f:selectItems value="#{compoMgmtView.filetypeTypes}" val="t"/>
</p:column> </p:selectOneMenu>
<p:column headerText="creator"> </p:panelGrid>
<h:link outcome="/useradmin/edit" value="#{entry.creator.user.nick}"> <p:commandButton update="filetypelist,filetypeEditform" action="#{compoMgmtView.saveFiletype}" value="#{i18n['save']}"/>
<f:param name="userid" value="#{entry.creator.user.id}" /> </h:form>
</h:link> <br/>
</p:column>
<p:column headerText="Sort"> <p:dataTable id="filetypelist" value="#{compoMgmtView.compo.filetypes}" var="ft">
<h:inputText value="#{entry.sort}" size="4" /> <p:column> <h:outputText value="#{ft.name}"/> </p:column>
</p:column> <p:column> <h:outputText value="#{ft.filetype}"/> </p:column>
<p:column headerText="Vote total"> <p:column>
<h:outputText value="#{entry.votetotal}" /> <p:commandButton value="Edit" update="filetypeEditform" action="#{compoMgmtView.editFiletype(ft.id)}" />
</p:column> &nbsp;<p:commandButton value="Delete" update="filetypelist" action="#{compoMgmtView.deleteFiletype(ft.id)}" />
<p:column headerText="Vote count">
<h:outputText value="#{entry.votes.size()}" /> </p:column>
</p:column>
</p:dataTable>
<p:column>
<h:link outcome="/voting/submitEntry" value="#{i18n['entry.edit']}"> <h2>#{i18n['compoMgmtView.compo.entries']}</h2>
<f:param name="entryId" value="#{entry.id}" />
</h:link> <h:form>
</p:column> <p:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{compoMgmtView.entries}" var="entry">
<p:column headerText="Title">
</p:dataTable> <h:outputText value="#{entry.title}"/>
<h:commandButton action="#{compoMgmtView.saveSort}" value="#{i18n['compo.savesort']}" /> </p:column>
</h:form> <p:column headerText="Author">
<h:outputText value="#{entry.author}"/>
</p:column>
</ui:define> <p:column headerText="Notes">
</ui:composition> <h:outputText value="#{entry.notes}"/>
</h:body> </p:column>
<p:column headerText="Screenmessage">
<h:outputText value="#{entry.screenMessage}"/>
</p:column>
<p:column headerText="creator">
<h:link outcome="/useradmin/edit" value="#{entry.creator.user.nick}">
<f:param name="userid" value="#{entry.creator.user.id}"/>
</h:link>
</p:column>
<p:column headerText="Sort">
<h:inputText value="#{entry.sort}" size="4"/>
</p:column>
<p:column headerText="Vote total">
<h:outputText value="#{entry.votetotal}"/>
</p:column>
<p:column headerText="Vote count">
<h:outputText value="#{entry.votes.size()}"/>
</p:column>
<p:column>
<h:link outcome="/voting/submitEntry" value="#{i18n['entry.edit']}">
<f:param name="entryId" value="#{entry.id}"/>
</h:link>
</p:column>
</p:dataTable>
<p:commandButton ajax="false" action="#{compoMgmtView.saveSort}" value="#{i18n['compo.savesort']}"/>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html> </html>
\ No newline at end of file
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user"
xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:event type="preRenderView" listener="#{voteListView.initView}" /> <f:event type="preRenderView" listener="#{voteListView.initView}" />
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<h1>My entries</h1> <h1>My entries</h1>
<h:form id="myEntries" styleClass="moya_datatable2"> <h:form id="myEntries" styleClass="moya_datatable2">
<h:dataTable styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{voteListView.entries}" var="entry"> <p:dataTable tableStyle="width: auto;" styleClass="bordertable" rowClasses="roweven,rowodd" id="compolisttable" value="#{voteListView.entries}" var="entry">
<h:column> <p:column headerText="Title">
<f:facet name="header"> <h:outputText value="#{entry.title}" />
<h:outputText value="Title" /> </p:column>
</f:facet> <p:column headerText="Author">
<h:outputText value="#{entry.title}" /> <h:outputText value="#{entry.author}" />
</h:column> </p:column>
<h:column> <p:column headerText="Notes">
<f:facet name="header"> <h:outputText value="#{entry.notes}" />
<h:outputText value="Author" /> </p:column>
</f:facet> <p:column headerText="Screen message">
<h:outputText value="#{entry.author}" /> <h:outputText value="#{entry.screenMessage}" />
</h:column> </p:column>
<h:column>
<f:facet name="header"> <p:column>
<h:outputText value="Notes" /> <h:link outcome="/voting/submitEntry" value="#{i18n['entry.edit']}">
</f:facet> <f:param name="entryId" value="#{entry.id}" />
<h:outputText value="#{entry.notes}" /> </h:link>
</h:column> </p:column>
<h:column>
<f:facet name="header"> </p:dataTable>
<h:outputText value="Screen message" />
</f:facet> </h:form>
<h:outputText value="#{entry.screenMessage}" />
</h:column>
</ui:define>
<h:column> </ui:composition>
<h:link outcome="/voting/submitEntry" value="#{i18n['entry.edit']}"> </h:body>
<f:param name="entryId" value="#{entry.id}" />
</h:link>
</h:column>
</h:dataTable>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html> </html>
\ No newline at end of file
<!DOCTYPE html <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user" <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:users="http://java.sun.com/jsf/composite/cditools/user"
xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"> xmlns:tools="http://java.sun.com/jsf/composite/cditools" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui">
<h:body> <h:body>
<ui:composition template="#{sessionHandler.template}"> <ui:composition template="#{sessionHandler.template}">
<f:metadata> <f:metadata>
<f:viewParam name="compoId" value="#{compoView.compoId}" /> <f:viewParam name="compoId" value="#{entryEditView.compoId}"/>
<f:viewParam name="entryId" value="#{compoView.entryId}" /> <f:viewParam name="entryId" value="#{entryEditView.entryId}"/>
<f:event type="preRenderView" listener="#{compoView.initEntryView}" /> <f:event type="preRenderView" listener="#{entryEditView.initEntryView}"/>
</f:metadata> </f:metadata>
<ui:define name="content"> <ui:define name="content">
<!-- <h:outputStylesheet library="style" name="insomnia2/css/actionlog.css" /> --> <!-- <h:outputStylesheet library="style" name="insomnia2/css/actionlog.css" /> -->
<h1>#{i18n['voting.compoentryadd.title']}</h1> <h1>#{i18n['voting.compoentryadd.title']}</h1>
<p> <p>
#{i18n['voting.compoentryadd.description']} #{i18n['voting.compoentryadd.description']}
<h:outputText value="#{compoView.compo.name}" /> <h:outputText value="#{entryEditView.compo.name}"/>
</p> </p>
<p> <p>
<h:outputText value="#{compoView.compo.description}" /> <h:outputText value="#{entryEditView.compo.description}"/>
</p> </p>
<h:form> <h:form>
<h:panelGrid columns="3"> <h:outputText value="#{entryEditView.entry.id}"/>
<h:outputLabel value="Title" for="name" /> <h:panelGrid columns="3">
<h:inputText value="#{compoView.entry.title}" id="name" /> <h:outputLabel value="Title" for="name"/>
<h:message for="name" /> <p:inputText value="#{entryEditView.entry.title}" id="name"/>
<h:message for="name"/>
<h:outputLabel value="Author" for="author" />
<h:inputText value="#{compoView.entry.author}" id="author" /> <h:outputLabel value="Author" for="author"/>
<h:message for="author" /> <p:inputText value="#{entryEditView.entry.author}" id="author"/>
<h:message for="author"/>
<h:outputLabel value="#{i18n['voting.compoentryadd.notes']}" for="notes" />
<h:inputTextarea value="#{compoView.entry.notes}" id="notes" /> <h:outputLabel value="#{i18n['voting.compoentryadd.notes']}" for="notes"/>
<h:message for="notes" /> <p:inputTextarea value="#{entryEditView.entry.notes}" id="notes"/>
<h:message for="notes"/>
<h:outputLabel value="#{i18n['voting.compoentryadd.screenmessage']}" for="screenmessage" />
<h:inputTextarea value="#{compoView.entry.screenMessage}" id="screenmessage" /> <h:outputLabel value="#{i18n['voting.compoentryadd.screenmessage']}" for="screenmessage"/>
<h:message for="screenmessage" /> <p:inputTextarea value="#{entryEditView.entry.screenMessage}" id="screenmessage"/>
<h:commandButton rendered="#{empty compoView.entry.id}" action="#{compoView.createEntry()}" value="#{i18n['voting.compoentryadd.button']}" /> <h:message for="screenmessage"/>
<h:commandButton rendered="#{!empty compoView.entry.id}" action="#{compoView.saveEntry()}" value="#{i18n['voting.compoentrysave.button']}" />
</h:panelGrid>
</h:panelGrid> <p:commandButton ajax="false" rendered="#{empty entryEditView.entry.id}" action="#{entryEditView.createEntry()}" value="#{i18n['voting.compoentryadd.button']}"/>
<p:commandButton ajax="false" rendered="#{not empty entryEditView.entry.id}" action="#{entryEditView.saveEntry()}" value="#{i18n['voting.compoentrysave.button']}"/>
</h:form>
<h:commandButton rendered="#{empty compoView.entry.id}" action="#{compoView.createEntry()}" value="Ilmoittaudu kilpailuun" />
</h:form> <ui:fragment rendered="#{!empty entryEditView.entry.id}">
<h2>
<ui:fragment rendered="#{!empty compoView.entry.id}"> <h:outputText value="#{i18n['compofile.download.header']}"/>
<h:form enctype="multipart/form-data"> </h2>
<p:fileUpload value="#{compoView.uploadedFile}" id="uploadedfile" mode="simple" />
<h:commandButton action="#{compoView.submitEntryfile}" value="#{i18n['compofile.upload']}" /> <p:dataTable style="width: auto;" value="#{entryEditView.entryFiletypes}" var="ft">
</h:form> <p:column headerText="">
<h:form rendered="#{!empty compoFileDownloadView.files}"> <h:outputText value="#{ft.filetype.name}"/>
<h2> </p:column>
<h:outputText value="#{i18n['compofile.download.header']}" /> <p:column headerText="Current file">
</h2> <p:commandButton rendered="#{not empty ft.entryfiletype.currentFile}" update=":fileInfoForm:fileInfoDialog" oncomplete="PF('fileInfoDialog').show()" icon="ui-icon-search"
<p:dataTable value="#{compoFileDownloadView.files}" var="fi"> title="View files">
<p:column headerText="#{i18n['compofile.fileName']}"> <f:setPropertyActionListener value="#{ft.entryfiletype}" target="#{entryEditView.selectedFiletype}"/>
<h:outputText value="#{fi.fileName}" /> </p:commandButton>
</p:column> </p:column>
<p:column headerText="#{i18n['compofile.uploadTime']}"> <p:column>
<h:outputText value="#{fi.uploaded.time}"> <form id="filesubmit-#{ft.filetype.id}" action="#{request.contextPath}/EntryFile" method="post" enctype="multipart/form-data">
<f:convertDateTime pattern="#{sessionHandler.shortDatetimeFormat}" /> <div>
</h:outputText> <input type="file" name="file"/>
</p:column> <input type="hidden" name="entryId" value="#{entryEditView.entry.id}"/>
<p:column headerText="#{i18n['compofile.shaChecksum']}"> <input type="hidden" name="typeId" value="#{ft.filetype.id}"/>
<h:outputText value="#{fi.hash}" />
</p:column> <button type="submit">Submit</button>
<p:column> </div>
<p:commandButton ajax="false" value="#{i18n['compofile.download']}" actionListener="#{compoFileDownloadView.selectDownloadedFile}"> </form>
<p:fileDownload value="#{compoFileDownloadView.dlfile}" /> </p:column>
</p:commandButton> </p:dataTable>
</p:column>
</p:dataTable> <h:form id="fileInfoForm">
</h:form> <p:dialog id="fileInfoDialog" widgetVar="fileInfoDialog" modal="true" appendTo="@(body)">
</ui:fragment>
<p:dataTable tableStyle="width: auto;" value="#{entryEditView.selectedFiletype.entryFiles}" var="file">
</ui:define> <p:column headerText="CurrentFile">
</ui:composition> <h:outputText value="X" rendered="#{entryEditView.selectedFiletype.currentFile==file}"/>
</h:body> </p:column>
<p:column headerText="#{i18n['compofile.fileName']}">
<a href="#{request.contextPath}/EntryFile/#{file.id}">
<h:outputText value="#{file.fileName}"/>
</a>
</p:column>
<p:column headerText="#{i18n['compofile.uploadTime']}">
<h:outputText value="#{file.uploaded}">
<f:convertDateTime pattern="#{sessionHandler.datetimeFormat}" timeZone="#{sessionHandler.timezone}"/>
</h:outputText>
</p:column>
<p:column headerText="#{i18n['compofile.shaChecksum']}">
<h:outputText value="#{file.hash}"/>
</p:column>
</p:dataTable>
</p:dialog>
</h:form>
<!--
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{compoView.uploadedFile}" id="uploadedfile" mode="simple"/>
<p:commandButton ajax="false" action="#{compoView.submitEntryfile}" value="#{i18n['compofile.upload']}"/>
</h:form>
<br/>
<h:form rendered="#{!empty compoFileDownloadView.files}">
<p:dataTable value="#{compoView.compo.filetypes}" var="type">
<p:column> <h:outputText value="#{type.name}"/> </p:column>
<p:column> <h:outputText value="#{type.filetype}"/> </p:column>
</p:dataTable>
<p:dataTable value="#{compoFileDownloadView.files}" var="fi">
<p:column headerText="#{i18n['compofile.fileName']}">
<h:outputText value="#{fi.fileName}"/>
</p:column>
<p:column headerText="#{i18n['compofile.uploadTime']}">
<h:outputText value="#{fi.uploaded.time}"> <f:convertDateTime pattern="#{sessionHandler.shortDatetimeFormat}"/> </h:outputText>
</p:column>
<p:column headerText="#{i18n['compofile.shaChecksum']}">
<h:outputText value="#{fi.hash}"/>
</p:column>
<p:column>
<p:commandButton ajax="false" value="#{i18n['compofile.download']}" actionListener="#{compoFileDownloadView.selectDownloadedFile}">
<p:fileDownload value="#{compoFileDownloadView.dlfile}"/>
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
-->
</ui:fragment>
</ui:define>
</ui:composition>
</h:body>
</html> </html>
\ No newline at end of file
...@@ -68,7 +68,7 @@ public class MoyaGraphQLServlet extends HttpServlet { ...@@ -68,7 +68,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
private VotingBeanLocal votebean; private VotingBeanLocal votebean;
@EJB @EJB
private UserPropertyBeanLocal eventUserPropertyBean; private UserPropertyBeanLocal eventUserPropertyBean;
private static final Comparator<? super GenericEntity> ENTITY_ID_SORTER = (Comparator<GenericEntity>) (o1, o2) -> o1.getId().compareTo(o2.getId().compareTo()); private static final Comparator<? super GenericEntity> ENTITY_ID_SORTER = (Comparator<GenericEntity>) (o1, o2) -> o1.getId().compareTo(o2.getId());
@Override @Override
public void init(ServletConfig config) throws ServletException { public void init(ServletConfig config) throws ServletException {
...@@ -284,8 +284,8 @@ public class MoyaGraphQLServlet extends HttpServlet { ...@@ -284,8 +284,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b.addField(EventUser_.event).type(builder.typeFor(SIMPLE_EVENT_TYPE_NAME)); b.addField(EventUser_.event).type(builder.typeFor(SIMPLE_EVENT_TYPE_NAME));
b.addField(EventUser_.eventuserCreated); b.addField(EventUser_.eventuserCreated);
b.addField(EventUser_.id); b.addField(EventUser_.id);
b.addListField(Role.class).dataFetcher(environment -> {userbean.findUsersRoles(environment.getSource())); b.addListField(Role.class).dataFetcher(environment -> userbean.findUsersRoles(environment.getSource()));
b.addListField(UsersEventUserproperty.class).dataFetcher(environment -> eventUserPropertyBean.getUserPropertiesForUser(environment.getSource()).stream().sorted(ENTITY_ID_SORTER).collect(toList()); b.addListField(UsersEventUserproperty.class).dataFetcher(environment -> eventUserPropertyBean.getUserPropertiesForUser(environment.getSource()).stream().sorted(ENTITY_ID_SORTER).collect(toList()));
b.addField(EventUser_.currentPlaces); b.addField(EventUser_.currentPlaces);
} }
...@@ -499,7 +499,6 @@ public class MoyaGraphQLServlet extends HttpServlet { ...@@ -499,7 +499,6 @@ public class MoyaGraphQLServlet extends HttpServlet {
b.addField(CompoEntry_.screenMessage); b.addField(CompoEntry_.screenMessage);
b.addField(CompoEntry_.sort); b.addField(CompoEntry_.sort);
b.addField(CompoEntry_.compo); b.addField(CompoEntry_.compo);
b.addField(CompoEntry_.currentFile);
b.addField(CompoEntry_.meta); b.addField(CompoEntry_.meta);
} }
...@@ -513,8 +512,6 @@ public class MoyaGraphQLServlet extends HttpServlet { ...@@ -513,8 +512,6 @@ public class MoyaGraphQLServlet extends HttpServlet {
b.addField(CompoEntryFile_.fileName); b.addField(CompoEntryFile_.fileName);
b.addField(CompoEntryFile_.description); b.addField(CompoEntryFile_.description);
b.addField(CompoEntryFile_.uploaded); b.addField(CompoEntryFile_.uploaded);
b.addField(CompoEntryFile_.fileData);
b.addField(CompoEntryFile_.entry);
b.addField(CompoEntryFile_.hash).description("SHA1 hash of the file data"); b.addField(CompoEntryFile_.hash).description("SHA1 hash of the file data");
b.addField(CompoEntryFile_.meta); b.addField(CompoEntryFile_.meta);
...@@ -549,11 +546,11 @@ public class MoyaGraphQLServlet extends HttpServlet { ...@@ -549,11 +546,11 @@ public class MoyaGraphQLServlet extends HttpServlet {
b.addField(LanEvent_.meta); b.addField(LanEvent_.meta);
b.addListField(EventMap.class).dataFetcher(environment -> placebean.getMaps().stream().sorted(ENTITY_ID_SORTER).collect(toList()); b.addListField(EventMap.class).dataFetcher(environment -> placebean.getMaps().stream().sorted(ENTITY_ID_SORTER).collect(toList()));
b.addListField(Role.class).dataFetcher(environment -> rolebean.listRoles().stream().sorted(ENTITY_ID_SORTER).collect(toList()); b.addListField(Role.class).dataFetcher(environment -> rolebean.listRoles().stream().sorted(ENTITY_ID_SORTER).collect(toList()));
b.addListField(Product.class).dataFetcher(environment -> productbean.findProductsForEvent().stream().sorted(ENTITY_ID_SORTER).collect(toList()); b.addListField(Product.class).dataFetcher(environment -> productbean.findProductsForEvent().stream().sorted(ENTITY_ID_SORTER).collect(toList()));
b.addListField(Compo.class).dataFetcher(environment -> votebean.getCompoList(true).stream().sorted(ENTITY_ID_SORTER).collect(toList()); b.addListField(Compo.class).dataFetcher(environment -> votebean.getCompoList(true).stream().sorted(ENTITY_ID_SORTER).collect(toList()));
b.addField(LanEvent_.id); b.addField(LanEvent_.id);
} }
......
...@@ -33,7 +33,7 @@ import fi.codecrew.moya.model.CardTemplate; ...@@ -33,7 +33,7 @@ import fi.codecrew.moya.model.CardTemplate;
/** /**
* Servlet implementation class UploadServlet * Servlet implementation class UploadServlet
*/ */
@WebServlet("/CardTemplate") @WebServlet(value="/CardTemplate")
public class CardTemplateServlet extends GenericImageServlet { public class CardTemplateServlet extends GenericImageServlet {
/** /**
......
package fi.codecrew.moya.servlet;
import fi.codecrew.moya.beans.VotingBeanLocal;
import fi.codecrew.moya.model.*;
import fi.codecrew.moya.utilities.SystemProperty;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@WebServlet(value = "/EntryFile/*")
public class CompoEntryFileServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(CompoEntryFileServlet.class);
/**
* @see HttpServlet#HttpServlet()
*/
public CompoEntryFileServlet() {
super();
logger.warn("Initializing StreamingUploadServlet");
}
@EJB
private VotingBeanLocal votebean;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int fileId = Integer.parseUnsignedInt(req.getPathInfo().substring(1));
CompoEntryFile entry = votebean.findEntryFile(fileId);
if (entry == null) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
resp.getWriter().write("Entity not found");
return;
}
File file = new File(new File(SystemProperty.MOYA_COMPOFILE_DIR.getValueOrDefault()), entry.getFilepath());
resp.setContentType(entry.getMimeType());
resp.setHeader("Content-Disposition", "filename=\"" + entry.getFileName() + "\"");
resp.setContentLength((int) file.length());
FileInputStream inStream = new FileInputStream(file);
ServletOutputStream oStream = resp.getOutputStream();
final byte[] buff = new byte[8192];
while (true) {
int len = inStream.read(buff);
if (len < 1) {
break;
}
oStream.write(buff, 0, len);
}
oStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
File dir = new File(SystemProperty.MOYA_COMPOFILE_DIR.getValueOrDefault());
if (!dir.isDirectory()) {
dir.mkdirs();
}
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (!isMultipart) {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Expected multipart upload");
return;
}
ServletFileUpload upload = new ServletFileUpload();
try {
FileItemIterator iter = upload.getItemIterator(req);
final byte[] buff = new byte[8192];
File tmpFile = File.createTempFile("moya-file", "tmp", dir);
CompoEntryFile entryfile = new CompoEntryFile();
Integer entryId = 0;
Integer typeId = 0;
while (iter.hasNext()) {
FileItemStream item = iter.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
if (item.isFormField()) {
final String data = Streams.asString(stream);
logger.warn("Streaming upload form field " + name + " with value " + data + " detected.");
switch (name) {
case "entryId": {
entryId = Integer.parseInt(data);
break;
}
case "typeId": {
typeId = Integer.parseInt(data);
break;
}
}
} else {
logger.warn("File field " + name + " with file name " + item.getName() + " detected." + item.getContentType());
MessageDigest algo = MessageDigest.getInstance("SHA");
FileOutputStream ostream = new FileOutputStream(tmpFile);
while (true) {
int len = stream.read(buff);
if (len < 1) {
break;
}
ostream.write(buff, 0, len);
algo.update(buff, 0, len);
}
String shasum = new String(Hex.encodeHex(algo.digest())).toLowerCase();
logger.warn("File shasum " + shasum);
ostream.close();
entryfile.setFileName(item.getName());
entryfile.setMimeType(item.getContentType());
entryfile.setHash(shasum);
}
stream.close();
}
CompoEntryFileType ft = votebean.findEntryFileType(entryId, typeId);
String ftPath = mkEntryFiletypePath(ft);
File filetypepath = new File(dir, ftPath);
if (!filetypepath.isDirectory()) {
filetypepath.mkdirs();
}
String filePath = ftPath + mkPath(entryfile.getUploaded().getTime() + "_" + entryfile.getFileName()) + ".dat";
logger.warn("Target file: {}, ftpath {}", filePath, ftPath);
entryfile.setFilepath(filePath);
if (!tmpFile.renameTo(new File(dir, filePath))) {
throw new RuntimeException("Error moving file to " + filePath);
}
entryfile.setFiletype(ft);
votebean.create(entryfile);
resp.setStatus(HttpServletResponse.SC_SEE_OTHER);
resp.setHeader("Location", "/MoyaWeb/voting/submitEntry.jsf?entryId=" + entryId);
} catch (FileUploadException e) {
logger.warn("Error uploading streaming file", e);
} catch (NoSuchAlgorithmException e) {
logger.warn("Error calculating checksum", e);
}
}
String asString(InputStream stream) throws IOException {
final byte[] buff = new byte[100];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true) {
int len = stream.read(buff);
if (len < 1) {
break;
}
baos.write(buff, 0, len);
}
return baos.toString();
}
public static void main(String[] asd) {
logger.warn("asda {}", mkPath("Foo", "[]{}äöherp", "1239KKKKK"));
}
public static String mkPath(Object... paths) {
StringBuilder ret = new StringBuilder();
for (Object p : paths) {
ret.append("/");
ret.append(p.toString().toLowerCase().replaceAll("[^a-z0-9]", "_"));
}
return ret.toString().replaceAll("_+", "_");
}
public static String mkEntryFiletypePath(CompoEntryFileType type) {
final CompoEntry entry = type.getEntry();
;
final Compo compo = entry.getCompo();
final LanEvent event = compo.getEvent();
return mkPath(
event.getId() + "_ " + event.getName(),
compo.getId() + "_" + compo.getName(),
entry.getId() + "_" + entry.getTitle(),
type.getId() + "_" + type.getType().getName()
);
}
}
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.servlet; package fi.codecrew.moya.servlet;
...@@ -83,7 +83,6 @@ public class UploadServlet extends HttpServlet { ...@@ -83,7 +83,6 @@ public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// boolean isMultipart = ServletFileUpload.isMultipartContent(request); // boolean isMultipart = ServletFileUpload.isMultipartContent(request);
FileItemFactory factory = new DiskFileItemFactory(); FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request // Parse the request
CharSequence retmsg = "Tiedosto tallennettu onnistuneesti."; CharSequence retmsg = "Tiedosto tallennettu onnistuneesti.";
...@@ -106,6 +105,9 @@ public class UploadServlet extends HttpServlet { ...@@ -106,6 +105,9 @@ public class UploadServlet extends HttpServlet {
destId = null; destId = null;
} }
} }
ServletFileUpload upload = new ServletFileUpload(factory);
for (Object ti : upload.parseRequest(request)) { for (Object ti : upload.parseRequest(request)) {
if (ti instanceof FileItem) { if (ti instanceof FileItem) {
......
package fi.codecrew.moya.web.api;
import fi.codecrew.moya.beans.ApiApplicationBeanLocal;
import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.enums.apps.SpecialPermission;
import fi.codecrew.moya.model.ApiApplication;
import fi.codecrew.moya.model.ApiApplicationInstance;
import fi.codecrew.moya.utilities.PasswordFunctions;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.faces.model.ListDataModel;
import javax.inject.Named;
import java.util.List;
@Named
@ConversationScoped
public class ApiAppEditView extends GenericCDIView {
private static final long serialVersionUID = -5137452386861332063L;
@EJB
private ApiApplicationBeanLocal apibean;
@EJB
private PermissionBeanLocal permbean;
private ApiApplication apiApp;
private Integer id;
private ApiApplicationInstance selectedInstance;
private ListDataModel<ApiApplicationInstance> apiInstances;
public void initEdit() {
if (super.requirePermissions(permbean.isLoggedIn()) && apiApp == null) {
super.beginConversation();
apiApp = apibean.findApplication(id);
apiInstances = new ListDataModel<>(apibean.findInstances(apiApp));
}
}
public void initCreateInstance() {
selectedInstance = apibean.createApplicationInstance(apiApp);
}
public void selectInstance(){
selectedInstance = apiInstances.getRowData();
}
public void saveInstance() {
apibean.saveApiInstance(selectedInstance);
}
public String save() {
apiApp = apibean.saveApiApplication(apiApp);
return null;
}
public ApiApplication getApiApp() {
return apiApp;
}
public void setApiApp(ApiApplication apiApp) {
this.apiApp = apiApp;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ApiApplicationInstance getSelectedInstance() {
return selectedInstance;
}
public void setSelectedInstance(ApiApplicationInstance selectedInstance) {
this.selectedInstance = selectedInstance;
}
public ListDataModel<ApiApplicationInstance> getApiInstances() {
return apiInstances;
}
public void setApiInstances(ListDataModel<ApiApplicationInstance> apiInstances) {
this.apiInstances = apiInstances;
}
}
...@@ -39,17 +39,24 @@ public class ApplicationApiView extends GenericCDIView { ...@@ -39,17 +39,24 @@ public class ApplicationApiView extends GenericCDIView {
private static final Logger logger = LoggerFactory.getLogger(ApplicationApiView.class); private static final Logger logger = LoggerFactory.getLogger(ApplicationApiView.class);
public void initApplicationListView() { public void initApplicationListView() {
if (super.requirePermissions(permbean.isLoggedIn()) && applist == null) { if (super.requirePermissions(permbean.isLoggedIn()) && applist == null) {
EventUser curruser = permbean.getCurrentUser(); applist = apibean.findMyApplications();
if (permbean.hasPermission(SpecialPermission.SUPERADMIN)) { }
applist = apibean.findAllApplications(); }
} else {
applist = apibean.findMyApplications(); public void initSuperApplicationListView() {
} if (super.requirePermissions(permbean.hasPermission(SpecialPermission.SUPERADMIN)) && applist == null) {
applist = apibean.findAllApplications();
} }
} }
public String createApp() {
apibean.createApiApplication(newApplication);
return "/api/edit?faces-redirect=true&id=" + newApplication.getId();
}
public List<ApiApplication> getApplist() { public List<ApiApplication> getApplist() {
return applist; return applist;
} }
......
...@@ -55,7 +55,7 @@ public class CompoFileDownloadView extends GenericCDIView { ...@@ -55,7 +55,7 @@ public class CompoFileDownloadView extends GenericCDIView {
{ {
if (files == null) if (files == null)
{ {
files = new ListDataModel<CompoEntryFile>(votebean.getEntryFiles(entry)); //files = new ListDataModel<CompoEntryFile>(votebean.getEntryFiles(entry));
} }
return files; return files;
} }
...@@ -64,19 +64,17 @@ public class CompoFileDownloadView extends GenericCDIView { ...@@ -64,19 +64,17 @@ public class CompoFileDownloadView extends GenericCDIView {
return file; return file;
} }
public void selectDownloadedFile()
{
file = files.getRowData();
dlfile = new DefaultStreamedContent(new ByteArrayInputStream(file.getFileData()), file.getMimeType(), file.getFileName());
}
public void setFile(CompoEntryFile file) { public void setFile(CompoEntryFile file) {
this.file = file; this.file = file;
if (file != null) if (file != null)
{ {
/*
dlfile = new DefaultStreamedContent(new ByteArrayInputStream(file.getFileData()), file.getMimeType(), file.getFileName()); dlfile = new DefaultStreamedContent(new ByteArrayInputStream(file.getFileData()), file.getMimeType(), file.getFileName());
logger.info("Uploading file {}, length {}", file.getFileName(), file.getFileData().length); logger.info("Uploading file {}, length {}", file.getFileName(), file.getFileData().length);
*/
} }
} }
......
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.web.cdiview.voting; package fi.codecrew.moya.web.cdiview.voting;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped; import javax.enterprise.context.ConversationScoped;
import javax.faces.model.ListDataModel; import javax.faces.model.ListDataModel;
import javax.inject.Named; import javax.inject.Named;
import fi.codecrew.moya.model.CompoFileType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -39,7 +42,7 @@ import fi.codecrew.moya.web.cdiview.GenericCDIView; ...@@ -39,7 +42,7 @@ import fi.codecrew.moya.web.cdiview.GenericCDIView;
public class CompoMgmtView extends GenericCDIView { public class CompoMgmtView extends GenericCDIView {
/** /**
* *
*/ */
private static final long serialVersionUID = -8373473936336396427L; private static final long serialVersionUID = -8373473936336396427L;
...@@ -53,6 +56,8 @@ public class CompoMgmtView extends GenericCDIView { ...@@ -53,6 +56,8 @@ public class CompoMgmtView extends GenericCDIView {
private ListDataModel<CompoEntry> entries; private ListDataModel<CompoEntry> entries;
private CompoFileType filetype = new CompoFileType();
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(CompoMgmtView.class); private static final Logger logger = LoggerFactory.getLogger(CompoMgmtView.class);
...@@ -60,10 +65,8 @@ public class CompoMgmtView extends GenericCDIView { ...@@ -60,10 +65,8 @@ public class CompoMgmtView extends GenericCDIView {
return compoId; return compoId;
} }
public void initCreate() public void initCreate() {
{ if (super.requirePermissions(fi.codecrew.moya.enums.apps.CompoPermission.MANAGE) && compo == null) {
if (super.requirePermissions(fi.codecrew.moya.enums.apps.CompoPermission.MANAGE) && compo == null)
{
compo = new Compo(); compo = new Compo();
Date now = new Date(); Date now = new Date();
compo.setStartTime(now); compo.setStartTime(now);
...@@ -82,16 +85,13 @@ public class CompoMgmtView extends GenericCDIView { ...@@ -82,16 +85,13 @@ public class CompoMgmtView extends GenericCDIView {
return "details"; return "details";
} }
public String saveCompo() public String saveCompo() {
{
compo = votingBean.saveCompo(compo); compo = votingBean.saveCompo(compo);
return null; return null;
} }
public String saveSort() public String saveSort() {
{ for (CompoEntry e : entries) {
for (CompoEntry e : entries)
{
setCompo(votingBean.saveSort(e).getCompo()); setCompo(votingBean.saveSort(e).getCompo());
} }
entries = new ListDataModel<CompoEntry>(getCompo().getCompoEntries()); entries = new ListDataModel<CompoEntry>(getCompo().getCompoEntries());
...@@ -108,8 +108,7 @@ public class CompoMgmtView extends GenericCDIView { ...@@ -108,8 +108,7 @@ public class CompoMgmtView extends GenericCDIView {
} }
public void initView() { public void initView() {
if (super.requirePermissions(CompoPermission.MANAGE) && entries == null) if (super.requirePermissions(CompoPermission.MANAGE) && entries == null) {
{
setCompo(votingBean.getCompoById(compoId)); setCompo(votingBean.getCompoById(compoId));
entries = new ListDataModel<CompoEntry>(getCompo().getCompoEntries()); entries = new ListDataModel<CompoEntry>(getCompo().getCompoEntries());
super.beginConversation(); super.beginConversation();
...@@ -132,4 +131,40 @@ public class CompoMgmtView extends GenericCDIView { ...@@ -132,4 +131,40 @@ public class CompoMgmtView extends GenericCDIView {
this.compo = compo; this.compo = compo;
} }
public CompoFileType getFiletype() {
return filetype;
}
public void setFiletype(CompoFileType filetype) {
this.filetype = filetype;
}
public List<CompoFileType.FileType> getFiletypeTypes() {
return Arrays.asList(CompoFileType.FileType.values());
}
public void saveFiletype() {
filetype.setCompo(compo);
compo = votingBean.saveFiletype(filetype);
filetype = new CompoFileType();
}
public void editFiletype(Integer id) {
for (CompoFileType ft : compo.getFiletypes()) {
if (ft.getId().equals(id)) {
this.filetype = ft;
return;
}
}
}
public void deleteFiletype(Integer id) {
for (CompoFileType ft : compo.getFiletypes()) {
if (ft.getId().equals(id)) {
compo = votingBean.deleteFiletype(ft);
return;
}
}
}
} }
package fi.codecrew.moya.web.cdiview.voting;
import fi.codecrew.moya.model.CompoEntryFileType;
import fi.codecrew.moya.model.CompoFileType;
public class CompoTypeWrapper {
private final CompoFileType filetype;
private CompoEntryFileType entryfiletype;
public CompoTypeWrapper(CompoFileType ft) {
this.filetype = ft;
}
public void setEntryType(CompoEntryFileType eft) {
this.entryfiletype = eft;
}
public CompoFileType getFiletype() {
return filetype;
}
public CompoEntryFileType getEntryfiletype() {
return entryfiletype;
}
}
/* /*
* Copyright Codecrew Ry * Copyright Codecrew Ry
* *
* All rights reserved. * All rights reserved.
* *
* This license applies to any software containing a notice placed by the * This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software. * copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software. * This license covers modification, distribution and use of the Software.
* *
* Any distribution and use in source and binary forms, with or without * Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the * modification is not permitted without explicit written permission from the
* copyright owner. * copyright owner.
* *
* A non-exclusive royalty-free right is granted to the copyright owner of the * A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in * Software to use, modify and distribute all modifications to the Software in
* future versions of the Software. * future versions of the Software.
* *
*/ */
package fi.codecrew.moya.web.cdiview.voting; package fi.codecrew.moya.web.cdiview.voting;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped; import javax.enterprise.context.ConversationScoped;
...@@ -26,6 +31,9 @@ import javax.enterprise.inject.Produces; ...@@ -26,6 +31,9 @@ import javax.enterprise.inject.Produces;
import javax.faces.model.ListDataModel; import javax.faces.model.ListDataModel;
import javax.inject.Named; import javax.inject.Named;
import fi.codecrew.moya.beans.RoleBeanLocal;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.model.*;
import fi.codecrew.moya.web.helpers.FileUploadUtils; import fi.codecrew.moya.web.helpers.FileUploadUtils;
import org.primefaces.event.RateEvent; import org.primefaces.event.RateEvent;
import org.primefaces.model.UploadedFile; import org.primefaces.model.UploadedFile;
...@@ -35,9 +43,6 @@ import org.slf4j.LoggerFactory; ...@@ -35,9 +43,6 @@ import org.slf4j.LoggerFactory;
import fi.codecrew.moya.beans.PermissionBeanLocal; import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.VotingBeanLocal; import fi.codecrew.moya.beans.VotingBeanLocal;
import fi.codecrew.moya.enums.apps.CompoPermission; import fi.codecrew.moya.enums.apps.CompoPermission;
import fi.codecrew.moya.model.Compo;
import fi.codecrew.moya.model.CompoEntry;
import fi.codecrew.moya.model.CompoEntryFile;
import fi.codecrew.moya.web.cdiview.GenericCDIView; import fi.codecrew.moya.web.cdiview.GenericCDIView;
@Named @Named
...@@ -50,11 +55,14 @@ public class CompoView extends GenericCDIView { ...@@ -50,11 +55,14 @@ public class CompoView extends GenericCDIView {
private VotingBeanLocal votbean; private VotingBeanLocal votbean;
@EJB @EJB
private PermissionBeanLocal permbean; private PermissionBeanLocal permbean;
@EJB
private UserBeanLocal userbean;
private boolean manage; private boolean manage;
private ListDataModel<Compo> compolist; private ListDataModel<CompoWrapper> compolist;
@Produces @Produces
private CompoEntry entry; private CompoEntry entry;
...@@ -70,57 +78,26 @@ public class CompoView extends GenericCDIView { ...@@ -70,57 +78,26 @@ public class CompoView extends GenericCDIView {
private ListDataModel<EntryWrapper> voteEntries; private ListDataModel<EntryWrapper> voteEntries;
public ListDataModel<Compo> getCompos() {
public ListDataModel<CompoWrapper> getCompos() {
return compolist; return compolist;
} }
public void initEntryView()
{
if (super.requirePermissions(CompoPermission.SUBMIT_ENTRY) && entry == null)
{
if (entryId == null)
{
entry = new CompoEntry();
if (compo == null && compoId != null) {
compo = votbean.getCompoById(compoId);
entry.setCompo(compo);
}
super.beginConversation();
} else {
entry = votbean.findEntry(entryId);
if (entry == null ||
!super.requirePermissions(
super.hasPermission(CompoPermission.MANAGE) ||
permbean.isCurrentUser(entry.getCreator()))) {
entry = null;
compo = null;
} else {
compo = entry.getCompo();
super.beginConversation();
}
}
}
logger.info("Initializing entry view {} {}", entry, compo);
}
public String startVote()
{ public String startVote() {
compo = compolist.getRowData(); compo = compolist.getRowData().getCompo();
setVoteEntries(EntryWrapper.init(compo.getCompoEntries(), votbean, false)); setVoteEntries(EntryWrapper.init(compo.getCompoEntries(), votbean, false));
logger.info("Initializing voting with entries {}, {}", compo.getCompoEntries().size(), voteEntries.getRowCount()); logger.info("Initializing voting with entries {}, {}", compo.getCompoEntries().size(), voteEntries.getRowCount());
super.beginConversation(); super.beginConversation();
return "/voting/vote"; return "/voting/vote";
} }
public void handleVoteRate(RateEvent rateEvent) public void handleVoteRate(RateEvent rateEvent) {
{
EntryWrapper row = voteEntries.getRowData(); EntryWrapper row = voteEntries.getRowData();
Integer vote = (Integer) rateEvent.getRating() - 3; Integer vote = (Integer) rateEvent.getRating() - 3;
if (vote < -2 || vote > 2) if (vote < -2 || vote > 2) {
{
vote = 0; vote = 0;
} }
votbean.saveVote(row.getEntry(), vote); votbean.saveVote(row.getEntry(), vote);
...@@ -128,76 +105,22 @@ public class CompoView extends GenericCDIView { ...@@ -128,76 +105,22 @@ public class CompoView extends GenericCDIView {
} }
public String saveVotes() { public String saveVotes() {
for (EntryWrapper vw : voteEntries) for (EntryWrapper vw : voteEntries) {
{
votbean.saveVote(vw.getEntry(), vw.getVote()); votbean.saveVote(vw.getEntry(), vw.getVote());
} }
super.addFaceMessage("compo.votesSaved"); super.addFaceMessage("compo.votesSaved");
return null; return null;
} }
public String submitEntry()
{
setCompo(compolist.getRowData());
setEntry(new CompoEntry());
getEntry().setCompo(getCompo());
return "/voting/submitEntry";
}
public String createEntry()
{
compo = votbean.addEntry(getEntry());
return null;
}
public String saveEntry()
{
setEntry(votbean.saveEntry(getEntry()));
return null;
}
public String submitEntryfile()
{
UploadedFile file = getUploadedFile();
if (file == null)
{
super.addFaceMessage("compo.fileuploadFailed");
return null;
}
byte[] contents = FileUploadUtils.getFileContents(file);
if (contents == null || contents.length == 0) {
super.addFaceMessage("compo.fileuploadFailed");
return null;
}
CompoEntryFile cef = new CompoEntryFile(getEntry());
cef.setFileData(contents);
logger.info("Got file name {} length {}", getUploadedFile().getFileName(), cef.getFileData().length);
cef.setFileName(getUploadedFile().getFileName());
cef.setMimeType(getUploadedFile().getContentType());
// getEntry().setCurrentFile(cef);
votbean.create(cef);
return null;
}
public void initAdminListView() { public void initAdminListView() {
if (requirePermissions(CompoPermission.MANAGE) && compolist == null) { if (requirePermissions(CompoPermission.MANAGE) && compolist == null) {
compolist = new ListDataModel<Compo>(votbean.getCompoList(true)); compolist = new ListDataModel<>(votbean.getCompoList(true).stream().map(c -> new CompoWrapper(c)).collect(Collectors.toList()));
setManage(hasPermission(CompoPermission.MANAGE)); setManage(hasPermission(CompoPermission.MANAGE));
logger.info("Permission to view full compo listing."); logger.info("Permission to view full compo listing.");
super.beginConversation(); super.beginConversation();
} } else {
else {
logger.info("Not enough rights to view full compo listing."); logger.info("Not enough rights to view full compo listing.");
} }
...@@ -206,12 +129,11 @@ public class CompoView extends GenericCDIView { ...@@ -206,12 +129,11 @@ public class CompoView extends GenericCDIView {
public void initListView() { public void initListView() {
if (requirePermissions(CompoPermission.VIEW_COMPOS) && compolist == null) { if (requirePermissions(CompoPermission.VIEW_COMPOS) && compolist == null) {
compolist = new ListDataModel<Compo>(votbean.getCompoList(false)); compolist = new ListDataModel<>(votbean.getCompoList(false).stream().map(c -> new CompoWrapper(c)).collect(Collectors.toList()));
setManage(hasPermission(CompoPermission.MANAGE)); setManage(hasPermission(CompoPermission.MANAGE));
logger.info("Permission to view full compo listing."); logger.info("Permission to view full compo listing.");
super.beginConversation(); super.beginConversation();
} } else {
else {
logger.info("Not enough rights to view full compo listing."); logger.info("Not enough rights to view full compo listing.");
} }
...@@ -274,4 +196,25 @@ public class CompoView extends GenericCDIView { ...@@ -274,4 +196,25 @@ public class CompoView extends GenericCDIView {
this.compoId = compoId; this.compoId = compoId;
} }
public class CompoWrapper {
private final Compo compo;
public CompoWrapper(Compo c) {
this.compo = c;
}
public Compo getCompo() {
return compo;
}
public boolean isCanVote() {
return compo.isVote();
}
public boolean isCanSubmit() {
return compo.isSubmit() && (compo.getEntrysubmitRole() == null || userbean.isUserInRole(permbean.getCurrentUser(), compo.getEntrysubmitRole()));
}
}
} }
package fi.codecrew.moya.web.cdiview.voting;
import fi.codecrew.moya.beans.UserBeanLocal;
import fi.codecrew.moya.beans.VotingBeanLocal;
import fi.codecrew.moya.enums.apps.CompoPermission;
import fi.codecrew.moya.model.*;
import fi.codecrew.moya.web.cdiview.GenericCDIView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@Named
@ConversationScoped
public class EntryEditView extends GenericCDIView {
private static final Logger logger = LoggerFactory.getLogger(EntryEditView.class);
@EJB
private VotingBeanLocal votbean;
@EJB
private UserBeanLocal userbean;
private Integer compoId;
private Integer entryId;
private Compo compo;
private CompoEntry entry;
private CompoEntryFileType selectedFiletype;
public String createEntry() {
compo = votbean.addEntry(entry);
return null;
}
public String saveEntry() {
entry = votbean.saveEntry(entry);
return null;
}
public void initEntryView() {
if (!super.requirePermissions(CompoPermission.SUBMIT_ENTRY) || entry != null) {
return;
}
if (entryId == null) {
if (compo == null && compoId != null) {
compo = votbean.getCompoById(compoId);
}
if (compo == null) {
throw new RuntimeException("Compo not found.");
}
if (compo.getEntrysubmitRole() != null && !userbean.isUserInRole(permbean.getCurrentUser(), compo.getEntrysubmitRole())) {
super.addFaceMessage("You do not have correct permissions to submit an entry to this compo.");
navihandler.forward("/permissionDenied");
return;
}
entry = new CompoEntry();
entry.setCompo(compo);
} else {
entry = votbean.findEntry(entryId);
compo = entry.getCompo();
if (entry == null || !super.requirePermissions(super.hasPermission(CompoPermission.MANAGE) || permbean.isCurrentUser(entry.getCreator()))) {
entry = null;
compo = null;
return;
}
}
super.beginConversation();
logger.info("Initializing entry view {} {}", entry, compo);
}
public List<CompoTypeWrapper> getEntryFiletypes() {
HashMap<CompoFileType, CompoTypeWrapper> ret = new HashMap<>();
for (CompoFileType ft : entry.getCompo().getFiletypes()) {
ret.put(ft, new CompoTypeWrapper(ft));
}
for (CompoEntryFileType eft : entry.getFiletypes()) {
ret.get(eft.getType()).setEntryType(eft);
}
// (x < y) ? -1 : ((x == y) ? 0 : 1);
ArrayList<CompoTypeWrapper> retList = new ArrayList<>(ret.values());
retList.sort(Comparator.comparingInt(o -> o.getFiletype().getSort()));
return retList;
}
public Integer getCompoId() {
return compoId;
}
public void setCompoId(Integer compoId) {
this.compoId = compoId;
}
public Integer getEntryId() {
return entryId;
}
public void setEntryId(Integer entryId) {
this.entryId = entryId;
}
public Compo getCompo() {
return compo;
}
public void setCompo(Compo compo) {
this.compo = compo;
}
public CompoEntry getEntry() {
return entry;
}
public void setEntry(CompoEntry entry) {
this.entry = entry;
}
public CompoEntryFileType getSelectedFiletype() {
return selectedFiletype;
}
public void setSelectedFiletype(CompoEntryFileType selectedFiletype) {
this.selectedFiletype = selectedFiletype;
}
}
...@@ -126,8 +126,8 @@ public class VotingCompoAddEntryView extends GenericCDIView { ...@@ -126,8 +126,8 @@ public class VotingCompoAddEntryView extends GenericCDIView {
compoEntry.setNotes(notes); compoEntry.setNotes(notes);
compoEntry.setScreenMessage(screenMessage); compoEntry.setScreenMessage(screenMessage);
compoEntry.setCompo(votingBean.getCompoById(compoId)); compoEntry.setCompo(votingBean.getCompoById(compoId));
CompoEntryFile cef = new CompoEntryFile(compoEntry); CompoEntryFile cef = new CompoEntryFile();
cef.setFileData(contents); //cef.setFileData(contents);
cef.setFileName(uploadedFile.getFileName()); cef.setFileName(uploadedFile.getFileName());
votingBean.addEntry(compoEntry, cef); votingBean.addEntry(compoEntry, cef);
return null; return null;
......
...@@ -1604,7 +1604,7 @@ voting.allcompos.holdVoting = Hold voting ...@@ -1604,7 +1604,7 @@ voting.allcompos.holdVoting = Hold voting
voting.allcompos.maxParts = Max participants voting.allcompos.maxParts = Max participants
voting.allcompos.name = Name voting.allcompos.name = Name
voting.allcompos.startTime = Start time voting.allcompos.startTime = Start time
voting.allcompos.submitEnd = End submitting voting.allcompos.submitEnd =
voting.allcompos.submitEntry = Submit entry voting.allcompos.submitEntry = Submit entry
voting.allcompos.submitStart = Start submitting voting.allcompos.submitStart = Start submitting
voting.allcompos.voteEnd = End voting voting.allcompos.voteEnd = End voting
...@@ -1686,4 +1686,8 @@ role.source.PLACE = ...@@ -1686,4 +1686,8 @@ role.source.PLACE =
role.source.ACCOUNTEVENT = role.source.ACCOUNTEVENT =
role.source.PLACE_PRODUCT = role.source.PLACE_PRODUCT =
role.source.EVENT_DEFAULT = role.source.EVENT_DEFAULT =
user.allroles = user.allroles =
\ No newline at end of file voting.create.entrysubmitrole =
compo.filetype.name =
compo.filetype.sort =
compo.filetype.filetype =
\ No newline at end of file
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
acc_line.eventuser = Customer acc_line.eventuser = Customer
acc_line.nick = Nick acc_line.nick = Nick
acc_line.place = Place
acc_line.product = Product acc_line.product = Product
acc_line.quantity = Quantity acc_line.quantity = Quantity
acc_line.time = Transaction Date acc_line.time = Transaction Date
...@@ -1842,7 +1843,7 @@ voting.allcompos.holdVoting = Hold voti ...@@ -1842,7 +1843,7 @@ voting.allcompos.holdVoting = Hold voti
voting.allcompos.maxParts = Max participants voting.allcompos.maxParts = Max participants
voting.allcompos.name = Name voting.allcompos.name = Name
voting.allcompos.startTime = Start time voting.allcompos.startTime = Start time
voting.allcompos.submitEnd = End submitting voting.allcompos.submitEnd = Compo submit deadline
voting.allcompos.submitEntry = Submit entry voting.allcompos.submitEntry = Submit entry
voting.allcompos.submitStart = Start submitting voting.allcompos.submitStart = Start submitting
voting.allcompos.voteEnd = End voting voting.allcompos.voteEnd = End voting
...@@ -1923,4 +1924,8 @@ role.source.PLACE = Place ...@@ -1923,4 +1924,8 @@ role.source.PLACE = Place
role.source.ACCOUNTEVENT = Accountevent (Bought product) role.source.ACCOUNTEVENT = Accountevent (Bought product)
role.source.PLACE_PRODUCT = Product via place role.source.PLACE_PRODUCT = Product via place
role.source.EVENT_DEFAULT = Event default role role.source.EVENT_DEFAULT = Event default role
user.allroles = All users roles user.allroles = All users roles
\ No newline at end of file voting.create.entrysubmitrole = Role needed to submit entries
compo.filetype.name = Filetype name
compo.filetype.sort = Sort number
compo.filetype.filetype = Type
\ No newline at end of file
...@@ -1833,7 +1833,7 @@ voting.allcompos.holdVoting = Hold voti ...@@ -1833,7 +1833,7 @@ voting.allcompos.holdVoting = Hold voti
voting.allcompos.maxParts = Max osallistujam\u00E4\u00E4r\u00E4 voting.allcompos.maxParts = Max osallistujam\u00E4\u00E4r\u00E4
voting.allcompos.name = Nimi voting.allcompos.name = Nimi
voting.allcompos.startTime = Aloitusaika voting.allcompos.startTime = Aloitusaika
voting.allcompos.submitEnd = Lis\u00E4ys kiinni voting.allcompos.submitEnd = Ilmoittautumisen m\u00E4\u00E4r\u00E4aika
voting.allcompos.submitEntry = L\u00E4het\u00E4 entry voting.allcompos.submitEntry = L\u00E4het\u00E4 entry
voting.allcompos.submitStart = Lis\u00E4ys auki voting.allcompos.submitStart = Lis\u00E4ys auki
voting.allcompos.voteEnd = \u00C4\u00E4nestys kiinni voting.allcompos.voteEnd = \u00C4\u00E4nestys kiinni
...@@ -1915,4 +1915,8 @@ role.source.PLACE = Paikka ...@@ -1915,4 +1915,8 @@ role.source.PLACE = Paikka
role.source.ACCOUNTEVENT = Tilitapahtuma (Ostettu tuote) role.source.ACCOUNTEVENT = Tilitapahtuma (Ostettu tuote)
role.source.PLACE_PRODUCT = Tuote paikan kautta role.source.PLACE_PRODUCT = Tuote paikan kautta
role.source.EVENT_DEFAULT = Tapahtuman oletusrooli role.source.EVENT_DEFAULT = Tapahtuman oletusrooli
user.allroles = Kaikki k\u00E4yttäj\u00E4n roolit user.allroles = Kaikki k\u00E4ytt\u00E4j\u00E4n roolit
\ No newline at end of file voting.create.entrysubmitrole = Teosten lhettmiseen tarvittava rooli
compo.filetype.name = Tiedostotyypin nimi
compo.filetype.sort = Jrjestysnumero
compo.filetype.filetype = Tyyppi
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!