Commit c402ca8c by Tuomas Riihimäki

Merge branch 'placeQueueFixes' into 'master'

made some stuff for placequeue, some fixes also



See merge request !362
2 parents fc4dfef2 fc0bf8dc
...@@ -56,6 +56,8 @@ public interface PlaceBeanLocal { ...@@ -56,6 +56,8 @@ public interface PlaceBeanLocal {
boolean releasePlace(Place place); boolean releasePlace(Place place);
boolean userReleasePlace(Place place);
Place mergeChanges(Place place); Place mergeChanges(Place place);
PlaceGroup buySelectedPlaces(EventUser user) throws BortalCatchableException; PlaceGroup buySelectedPlaces(EventUser user) throws BortalCatchableException;
......
...@@ -7,6 +7,7 @@ import javax.ejb.Local; ...@@ -7,6 +7,7 @@ import javax.ejb.Local;
import fi.codecrew.moya.model.EventMap; import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser; import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.MapQueueRules;
import fi.codecrew.moya.model.map.MapReservationQueueEntry; import fi.codecrew.moya.model.map.MapReservationQueueEntry;
@Local @Local
...@@ -26,6 +27,10 @@ public interface QueueBeanLocal { ...@@ -26,6 +27,10 @@ public interface QueueBeanLocal {
MapQueueI getMapQueue(EventMap map); MapQueueI getMapQueue(EventMap map);
void saveQueue(MapQueueI queue, EventMap map);
MapQueueRules findRules(EventMap map);
public interface MapQueueI { public interface MapQueueI {
Collection<MapReservationQueueEntry> getQueue(); Collection<MapReservationQueueEntry> getQueue();
...@@ -46,6 +51,10 @@ public interface QueueBeanLocal { ...@@ -46,6 +51,10 @@ public interface QueueBeanLocal {
MapReservationQueueEntry getEntry(EventUser u); MapReservationQueueEntry getEntry(EventUser u);
boolean isBiggestFirst();
void setBiggestFirst(boolean biggestFirst);
} }
void forceAddToReserving(EventMap map, EventUser u, Date time); void forceAddToReserving(EventMap map, EventUser u, Date time);
......
...@@ -417,7 +417,6 @@ public class BootstrapBean implements BootstrapBeanLocal { ...@@ -417,7 +417,6 @@ public class BootstrapBean implements BootstrapBeanLocal {
}); });
dbUpdates.add(new String[] { dbUpdates.add(new String[] {
"ALTER TABLE products ADD COLUMN min_buy_count INTEGER default 0;" "ALTER TABLE products ADD COLUMN min_buy_count INTEGER default 0;"
}); });
...@@ -426,6 +425,17 @@ public class BootstrapBean implements BootstrapBeanLocal { ...@@ -426,6 +425,17 @@ public class BootstrapBean implements BootstrapBeanLocal {
"ALTER TABLE discounts ADD COLUMN sort INTEGER NOT NULL default 10;" "ALTER TABLE discounts ADD COLUMN sort INTEGER NOT NULL default 10;"
}); });
dbUpdates.add(new String[] {
"CREATE TABLE map_queue_rules (id SERIAL NOT NULL, meta json, reserving_size INTEGER, default_timeout_min INTEGER, minium_slots_in_queue INTEGER, map_id INTEGER NOT NULL , PRIMARY KEY (id))",
"ALTER TABLE map_queue_rules ADD CONSTRAINT FK_map_queue_rules_map_id FOREIGN KEY (map_id) REFERENCES maps (id)",
});
dbUpdates.add(new String[] {
"ALTER TABLE map_queue_rules ADD COLUMN biggest_first BOOLEAN default false",
});
} }
......
...@@ -494,6 +494,21 @@ public class PlaceBean implements PlaceBeanLocal { ...@@ -494,6 +494,21 @@ public class PlaceBean implements PlaceBeanLocal {
return releasePlacePriv(place) != null; return releasePlacePriv(place) != null;
} }
/**
* User release place
*
* @param place The place to be released
* @return true when successfull, on any erroro false.
*/
@Override
@RolesAllowed({ MapPermission.S_BUY_PLACES, MapPermission.S_MANAGE_OTHERS })
public boolean userReleasePlace(Place place) {
place = placeFacade.reload(place);
PlaceSlot s = releasePlacePriv(place);
return (s == null || s.getUsed() == null);
}
private PlaceSlot releasePlacePriv(Place place) { private PlaceSlot releasePlacePriv(Place place) {
EventUser user = permbean.getCurrentUser(); EventUser user = permbean.getCurrentUser();
if (place.getGroup() != null || place.getCurrentUser() == null if (place.getGroup() != null || place.getCurrentUser() == null
......
package fi.codecrew.moya.beans.map; package fi.codecrew.moya.beans.map;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import fi.codecrew.moya.model.MapQueueRules;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -24,9 +19,12 @@ public class MapQueue implements MapQueueI { ...@@ -24,9 +19,12 @@ public class MapQueue implements MapQueueI {
private int defaultTimeoutMin = 10; private int defaultTimeoutMin = 10;
private int minimumSlotsInQueue = 1; private int minimumSlotsInQueue = 1;
private int reservingSize = 5; private int reservingSize = 5;
private boolean biggestFirst = false;
// private final Set<MapReservationQueueEntry> reserving = new HashSet<>(); // private final Set<MapReservationQueueEntry> reserving = new HashSet<>();
private final Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>()); private final Set<EventUser> reserving = Collections.newSetFromMap(new ConcurrentHashMap<>());
private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>(); //private final PriorityQueue<MapReservationQueueEntry> queue = new PriorityQueue<>();
private final List<MapReservationQueueEntry> queue = Collections.synchronizedList(new ArrayList<>());
private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>(); private final ConcurrentMap<EventUser, MapReservationQueueEntry> queEntries = new ConcurrentHashMap<>();
private final Integer mapId; private final Integer mapId;
//private final Object reservingLock = new Object(); //private final Object reservingLock = new Object();
...@@ -35,10 +33,20 @@ public class MapQueue implements MapQueueI { ...@@ -35,10 +33,20 @@ public class MapQueue implements MapQueueI {
public MapQueue(EventMap map) { public MapQueue(EventMap map) {
this.mapId = map.getId(); this.mapId = map.getId();
}
public MapQueue(EventMap map, MapQueueRules rules) {
this(map);
if(rules != null) {
this.defaultTimeoutMin = rules.getDefaultTimeoutMin();
this.minimumSlotsInQueue = rules.getMinimumSlotsInQueue();
this.reservingSize = rules.getReservingSize();
this.biggestFirst = rules.getBiggestFirst();
}
} }
void timeoutEntries() { public void timeoutEntries() {
logger.info("Timeouting entries"); logger.info("Timeouting entries");
// give 10 seconds mercy ( and give us some time to go through all entries) // give 10 seconds mercy ( and give us some time to go through all entries)
Date now = new Date(System.currentTimeMillis() + 1000 * 15); Date now = new Date(System.currentTimeMillis() + 1000 * 15);
...@@ -81,13 +89,18 @@ public class MapQueue implements MapQueueI { ...@@ -81,13 +89,18 @@ public class MapQueue implements MapQueueI {
private final AtomicBoolean modifyReservers = new AtomicBoolean(false); private final AtomicBoolean modifyReservers = new AtomicBoolean(false);
private void checkReservingEntry() { private void checkReservingEntry() {
if (reserving.size() < getReservingSize() && modifyReservers.compareAndSet(false, true)) { if (reserving.size() < getReservingSize() && modifyReservers.compareAndSet(false, true)) {
try { try {
if (reserving.size() < getReservingSize()) { if (reserving.size() < getReservingSize() && !queue.isEmpty()) {
MapReservationQueueEntry queEntry = queue.poll();
MapReservationQueueEntry queEntry = queue.remove(0);
sortQueue();
if (queEntry != null) { if (queEntry != null) {
reserving.add(queEntry.getUser()); reserving.add(queEntry.getUser());
queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000)); queEntry.setReservationTimeout(new Date(System.currentTimeMillis() + getDefaultTimeoutMin() * 60 * 1000));
...@@ -112,16 +125,25 @@ public class MapQueue implements MapQueueI { ...@@ -112,16 +125,25 @@ public class MapQueue implements MapQueueI {
while (queue.remove(entry)) { while (queue.remove(entry)) {
} }
} }
sortQueue();
checkReservingEntry(); checkReservingEntry();
return ret; return ret;
} }
public void sortQueue() {
if(this.biggestFirst)
Collections.sort(queue);
}
public MapReservationQueueEntry enter(EventUser user, List<PlaceSlot> slots) { public MapReservationQueueEntry enter(EventUser user, List<PlaceSlot> slots) {
MapReservationQueueEntry ret = initEntry(user, slots); MapReservationQueueEntry ret = initEntry(user, slots);
if (!reserving.contains(user) && !queue.contains(ret)) { if (!reserving.contains(user) && !queue.contains(ret)) {
queue.add(ret); queue.add(ret);
sortQueue();
// Check if the user can be put to reservation queue immediately // Check if the user can be put to reservation queue immediately
checkReservingEntry(); checkReservingEntry();
...@@ -151,6 +173,7 @@ public class MapQueue implements MapQueueI { ...@@ -151,6 +173,7 @@ public class MapQueue implements MapQueueI {
ret.setUser(user); ret.setUser(user);
ret.setSeenTime(new Date()); ret.setSeenTime(new Date());
ret.setPlaceslotcount(slots.size()); ret.setPlaceslotcount(slots.size());
MapReservationQueueEntry old = queEntries.putIfAbsent(user, ret); MapReservationQueueEntry old = queEntries.putIfAbsent(user, ret);
if (old != null) { if (old != null) {
ret = old; ret = old;
...@@ -190,12 +213,22 @@ public class MapQueue implements MapQueueI { ...@@ -190,12 +213,22 @@ public class MapQueue implements MapQueueI {
return queEntries.get(user); return queEntries.get(user);
} }
@Override
public boolean isBiggestFirst() {
return this.biggestFirst;
}
@Override
public void setBiggestFirst(boolean biggestFirst) {
this.biggestFirst = biggestFirst;
}
public Collection<EventUser> getReserving() { public Collection<EventUser> getReserving() {
return reserving; return reserving;
} }
@Override @Override
public PriorityQueue<MapReservationQueueEntry> getQueue() { public List<MapReservationQueueEntry> getQueue() {
return queue; return queue;
} }
...@@ -223,4 +256,5 @@ public class MapQueue implements MapQueueI { ...@@ -223,4 +256,5 @@ public class MapQueue implements MapQueueI {
this.reservingSize = reservingSize; this.reservingSize = reservingSize;
} }
} }
...@@ -5,7 +5,6 @@ import java.util.List; ...@@ -5,7 +5,6 @@ import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.security.DeclareRoles; import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed; import javax.annotation.security.RolesAllowed;
import javax.ejb.Asynchronous; import javax.ejb.Asynchronous;
...@@ -17,6 +16,8 @@ import javax.ejb.Singleton; ...@@ -17,6 +16,8 @@ import javax.ejb.Singleton;
import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType; import javax.ejb.TransactionManagementType;
import fi.codecrew.moya.facade.MapQueueRulesFacade;
import fi.codecrew.moya.model.*;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -25,10 +26,6 @@ import fi.codecrew.moya.beans.PermissionBeanLocal; ...@@ -25,10 +26,6 @@ import fi.codecrew.moya.beans.PermissionBeanLocal;
import fi.codecrew.moya.beans.PlaceBeanLocal; import fi.codecrew.moya.beans.PlaceBeanLocal;
import fi.codecrew.moya.enums.apps.MapPermission; import fi.codecrew.moya.enums.apps.MapPermission;
import fi.codecrew.moya.facade.PlaceSlotFacade; import fi.codecrew.moya.facade.PlaceSlotFacade;
import fi.codecrew.moya.model.EventMap;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.LanEventPropertyKey;
import fi.codecrew.moya.model.PlaceSlot;
import fi.codecrew.moya.model.map.MapReservationQueueEntry; import fi.codecrew.moya.model.map.MapReservationQueueEntry;
/** /**
...@@ -62,6 +59,9 @@ public class QueueBean implements QueueBeanLocal { ...@@ -62,6 +59,9 @@ public class QueueBean implements QueueBeanLocal {
@EJB @EJB
private PermissionBeanLocal permbean; private PermissionBeanLocal permbean;
@EJB
private MapQueueRulesFacade mapQueueRulesFacade;
@Lock(LockType.READ) @Lock(LockType.READ)
@Override @Override
public boolean isReserving(EventMap map, EventUser user) { public boolean isReserving(EventMap map, EventUser user) {
...@@ -119,7 +119,9 @@ public class QueueBean implements QueueBeanLocal { ...@@ -119,7 +119,9 @@ public class QueueBean implements QueueBeanLocal {
MapQueue ret = mapqueues.get(map.getId()); MapQueue ret = mapqueues.get(map.getId());
if (ret == null) { if (ret == null) {
ret = new MapQueue(map);
ret = new MapQueue(map, mapQueueRulesFacade.findByMap(map));
MapQueue nret = mapqueues.putIfAbsent(map.getId(), ret); MapQueue nret = mapqueues.putIfAbsent(map.getId(), ret);
if (nret != null) { if (nret != null) {
ret = nret; ret = nret;
...@@ -231,6 +233,31 @@ public class QueueBean implements QueueBeanLocal { ...@@ -231,6 +233,31 @@ public class QueueBean implements QueueBeanLocal {
} }
@Override @Override
public void saveQueue(MapQueueI queue, EventMap map) {
MapQueueRules rules = mapQueueRulesFacade.findByMap(map);
if(rules == null) {
rules = new MapQueueRules();
rules.setMap(map);
mapQueueRulesFacade.create(rules);
rules = mapQueueRulesFacade.reload(rules);
}
rules.setDefaultTimeoutMin(queue.getDefaultTimeoutMin());
rules.setMinimumSlotsInQueue(queue.getMinimumSlotsInQueue());
rules.setReservingSize(queue.getReservingSize());
rules.setBiggestFirst(queue.isBiggestFirst());
mapQueueRulesFacade.merge(rules);
}
@Override
public MapQueueRules findRules(EventMap map) {
return mapQueueRulesFacade.findByMap(map);
}
@Override
@Lock(LockType.READ) @Lock(LockType.READ)
@RolesAllowed(MapPermission.S_MANAGE_MAPS) @RolesAllowed(MapPermission.S_MANAGE_MAPS)
public void forceRemove(EventMap e, EventUser u) { public void forceRemove(EventMap e, EventUser u) {
......
/*
* 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.EventMap;
import fi.codecrew.moya.model.MapQueueRules;
import fi.codecrew.moya.model.MapQueueRules_;
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 MapQueueRulesFacade extends IntegerPkGenericFacade<MapQueueRules> {
public MapQueueRulesFacade() {
super(MapQueueRules.class);
}
public MapQueueRules findByMap(EventMap map) {
if(map == null) {
throw new NullPointerException("Map must be given to MapQueueRules.findByMap");
}
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<MapQueueRules> cq = cb.createQuery(MapQueueRules.class);
Root<MapQueueRules> root = cq.from(MapQueueRules.class);
cq.where(cb.equal(root.get(MapQueueRules_.map), map));
return getSingleNullableResult(getEm().createQuery(cq).setMaxResults(1));
}
}
/*
* 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.
*
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package fi.codecrew.moya.model;
import javax.persistence.*;
import java.awt.*;
import java.util.Calendar;
/**
*
*/
@Entity
@Table(name = "map_queue_rules")
public class MapQueueRules extends GenericEntity {
private static final long serialVersionUID = 1L;
@Column(name = "reserving_size")
private Integer reservingSize = 5;
@Column(name = "default_timeout_min")
private Integer defaultTimeoutMin = 10;
@Column(name = "minium_slots_in_queue")
private Integer minimumSlotsInQueue = 1;
@Column(name = "biggest_first")
private Boolean biggestFirst = false;
@JoinColumn(name = "map_id", referencedColumnName = "id")
@ManyToOne
private EventMap map;
public MapQueueRules() {
super();
}
public Integer getReservingSize() {
return reservingSize;
}
public void setReservingSize(Integer reservingSize) {
this.reservingSize = reservingSize;
}
public Integer getDefaultTimeoutMin() {
return defaultTimeoutMin;
}
public void setDefaultTimeoutMin(Integer defaultTimeoutMin) {
this.defaultTimeoutMin = defaultTimeoutMin;
}
public Integer getMinimumSlotsInQueue() {
return minimumSlotsInQueue;
}
public void setMinimumSlotsInQueue(Integer minimumSlotsInQueue) {
this.minimumSlotsInQueue = minimumSlotsInQueue;
}
public EventMap getMap() {
return map;
}
public void setMap(EventMap map) {
this.map = map;
}
public Boolean getBiggestFirst() {
return biggestFirst;
}
public void setBiggestFirst(Boolean biggestFirst) {
this.biggestFirst = biggestFirst;
}
}
...@@ -92,9 +92,17 @@ public class MapReservationQueueEntry extends GenericEntity implements Comparabl ...@@ -92,9 +92,17 @@ public class MapReservationQueueEntry extends GenericEntity implements Comparabl
} }
@Override @Override
/**
* Smaller is bigger.
*
* Bigger first.
*/
public int compareTo(MapReservationQueueEntry o) { public int compareTo(MapReservationQueueEntry o) {
return getPlaceslotcount().compareTo(o.getPlaceslotcount()); if(o == null || o.getPlaceslotcount() == null)
return -1;
return o.getPlaceslotcount().compareTo(getPlaceslotcount());
} }
public Integer getPlaceslotcount() { public Integer getPlaceslotcount() {
......
...@@ -13,18 +13,35 @@ ...@@ -13,18 +13,35 @@
<ui:define name="content"> <ui:define name="content">
<h2>Queue properties</h2> <h2>Queue properties</h2>
<ui:fragment rendered="#{ajaxMapView.queueEnabled}">
<h:outputText value="#{i18n['queuemgmt.queueEnabled']}"/>
</ui:fragment>
<ui:fragment rendered="#{not ajaxMapView.queueEnabled}">
<h:outputText value="#{i18n['queuemgmt.queueDisabled']}: "/>
</ui:fragment>
<br />
<h:form> <h:form>
<p:panelGrid columns="2"> <p:panelGrid columns="3" id="queueGrid">
<p:outputLabel for="minslots" value="#{i18n['queuemgmt.minimumSlotsInQueue']}" /> <p:outputLabel for="minslots" value="#{i18n['queuemgmt.minimumSlotsInQueue']}" />
<p:inputText id="minslots" value="#{queueManageView.queue.minimumSlotsInQueue}" /> <p:inputText id="minslots" value="#{queueManageView.queue.minimumSlotsInQueue}" />
<h:outputText value="#{i18n['queuemgmt.inDatabase']}: #{queueManageView.defaultValues.minimumSlotsInQueue}" />
<p:outputLabel for="reservingsize" value="#{i18n['queuemgmt.reservingSize']}" /> <p:outputLabel for="reservingsize" value="#{i18n['queuemgmt.reservingSize']}" />
<p:inputText id="reservingsize" value="#{queueManageView.queue.reservingSize}" /> <p:inputText id="reservingsize" value="#{queueManageView.queue.reservingSize}" />
<h:outputText value="#{i18n['queuemgmt.inDatabase']}: #{queueManageView.defaultValues.reservingSize}" />
<p:outputLabel for="defaultTimeout" value="#{i18n['queuemgmt.defaultTimeoutMin']}" /> <p:outputLabel for="defaultTimeout" value="#{i18n['queuemgmt.defaultTimeoutMin']}" />
<p:inputText id="defaultTimeout" value="#{queueManageView.queue.defaultTimeoutMin}" /> <p:inputText id="defaultTimeout" value="#{queueManageView.queue.defaultTimeoutMin}" />
<h:outputText value="#{i18n['queuemgmt.inDatabase']}: #{queueManageView.defaultValues.defaultTimeoutMin}" />
<p:outputLabel for="biggestFirst" value="#{i18n['queuemgmt.biggestFirst']}" />
<p:selectBooleanCheckbox id="biggestFirst" value="#{queueManageView.queue.biggestFirst}" />
<h:outputText value="#{i18n['queuemgmt.inDatabase']}: #{queueManageView.defaultValues.biggestFirst}" />
</p:panelGrid> </p:panelGrid>
<p:commandButton ajax="false" value="#{i18n['queuemgmt.saveProperties']}"></p:commandButton> <p:commandButton value="#{i18n['queuemgmt.saveProperties']}" actionListener="#{queueManageView.saveToDatabase}" update="queueGrid" ></p:commandButton>
</h:form> </h:form>
......
...@@ -70,18 +70,24 @@ ...@@ -70,18 +70,24 @@
</p:column> </p:column>
</p:dataTable> </p:dataTable>
<br /><br />
<ui:fragment rendered="#{ajaxMapView.reserving}"> <ui:fragment rendered="#{ajaxMapView.reserving}">
<div style="margin: 5px;"> <div style="margin: 5px;">
<h:form id="placeselectform"> <h:form id="placeselectform">
<p:commandButton onclick="$(window).unbind('beforeunload');" rendered="#{ajaxMapView.canUserBuy()}" value="#{i18n['mapView.buyPlaces']}" actionListener="#{ajaxMapView.buySelectedPlaces()}" /> <p:commandButton onclick="$(window).unbind('beforeunload');" rendered="#{ajaxMapView.canUserBuy()}" value="#{i18n['mapView.buyPlaces']}" actionListener="#{ajaxMapView.buySelectedPlaces()}" />
</h:form> </h:form>
</div> </div>
<ui:fragment rendered="#{ajaxMapView.queueEnabled}">
<h:outputText value="#{i18n['mapView.reserveTimeLeft']}: "/>
<span id="reserveTimeLeft"/><br/>
</ui:fragment>
</ui:fragment> </ui:fragment>
<!-- Print queue status --> <!-- Print queue status -->
<ui:fragment rendered="#{ajaxMapView.queueEnabled and not ajaxMapView.reserving}"> <ui:fragment rendered="#{ajaxMapView.queueEnabled and not ajaxMapView.reserving}">
<h3><h:outputText value="#{i18n['mapView.youAreInQueue']}"/></h3> <h3><h:outputText value="#{i18n['mapView.youAreInQueue']}"/></h3>
<h4><h:outputText rendered="#{ajaxMapView.biggestFirst}" value="#{i18n['queuemgmt.biggestIsFirst']}" /> </h4>
<div style="margin: 1em;"> <div style="margin: 1em;">
<h:outputText value="#{i18n['mapView.queuePosition']}: "/> <h:outputText value="#{i18n['mapView.queuePosition']}: "/>
...@@ -98,6 +104,7 @@ ...@@ -98,6 +104,7 @@
<script type="text/javascript"> <script type="text/javascript">
// Queue is enabled and we are reserving. // Queue is enabled and we are reserving.
var queueReserving = #{(ajaxMapView.queueEnabled and not ajaxMapView.reserving)?"true":"false"}; var queueReserving = #{(ajaxMapView.queueEnabled and not ajaxMapView.reserving)?"true":"false"};
var queueSelectingPlaces = #{(ajaxMapView.queueEnabled and ajaxMapView.reserving)?"true":"false"};
function updateMap() { function updateMap() {
...@@ -114,6 +121,23 @@ ...@@ -114,6 +121,23 @@
}).fail(function () { }).fail(function () {
location.reload(); location.reload();
}); });
} else if(queueSelectingPlaces) {
$.getJSON("#{request.contextPath}/rest/placemap/v1/queueStillReserving/#{ajaxMapView.map.id}/#{ajaxMapView.eventuser.id}")
.done(function (data) {
if(data.value == 0) {
alert("#{i18n['reservequeue.reservingTimeIsUpAlert']}");
$(window).unbind('beforeunload');
location.href = "/";
}
var secsLeft = (#{ajaxMapView.reservingTimeslotEndtime}/1000) - ((new Date()).getTime()/1000 );
$("#reserveTimeLeft").text( Math.floor(secsLeft/60) + ":" + Math.round(secsLeft - (60 * Math.floor(secsLeft/60) ) ) );
}).fail(function () {
location.reload();
});
} }
} }
...@@ -130,7 +154,6 @@ ...@@ -130,7 +154,6 @@
location.reload(); location.reload();
} else { } else {
$("#queuepos").text(data.value); $("#queuepos").text(data.value);
var d = new Date();
$("#queueupdated").text(new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1")); $("#queueupdated").text(new Date().toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1"));
} }
} }
......
...@@ -181,6 +181,29 @@ public class PlacemapRestViewV1 { ...@@ -181,6 +181,29 @@ public class PlacemapRestViewV1 {
return root; return root;
} }
@GET
@Path("/queueStillReserving/{mapid}/{userid}")
public IntegerRoot getStillReserving(@PathParam("mapid") Integer mapid, @PathParam("userid") Integer userid) {
EventUser user = null;
if (userid != null) {
user = userbean.findByEventUserId(userid);
} else {
user = permbean.getCurrentUser();
}
if (user == null) {
return null;
}
EventMap map = placebean.findMap(mapid);
IntegerRoot root = new IntegerRoot();
root.setValue(quebean.isReserving(map, user)?1:0);
return root;
}
@POST @POST
@Path("/place/{place}") @Path("/place/{place}")
public Response togglePlaceReservation(@PathParam("place") Integer placeId) public Response togglePlaceReservation(@PathParam("place") Integer placeId)
...@@ -200,7 +223,7 @@ public class PlacemapRestViewV1 { ...@@ -200,7 +223,7 @@ public class PlacemapRestViewV1 {
boolean success = false; boolean success = false;
if (p.isReservedFor(user)) { if (p.isReservedFor(user)) {
success = placebean.releasePlace(p); success = placebean.userReleasePlace(p);
} else if (p.isBuyable() && !p.isTaken()) { } else if (p.isBuyable() && !p.isTaken()) {
logger.info("Rest Reserving place for place {}", p); logger.info("Rest Reserving place for place {}", p);
success = placebean.reservePlace(p, user); success = placebean.reservePlace(p, user);
...@@ -209,7 +232,7 @@ public class PlacemapRestViewV1 { ...@@ -209,7 +232,7 @@ public class PlacemapRestViewV1 {
ResponseBuilder resp = null; ResponseBuilder resp = null;
if (success) { if (success) {
p = placebean.find(placeId); p = placebean.find(placeId);
List<Place> thisplace = new ArrayList<Place>(); List<Place> thisplace = new ArrayList<>();
thisplace.add(p); thisplace.add(p);
resp = Response.ok(PojoUtils.parseSimplePlaces(thisplace, user, permbean.hasPermission(UserPermission.VIEW_ALL))); resp = Response.ok(PojoUtils.parseSimplePlaces(thisplace, user, permbean.hasPermission(UserPermission.VIEW_ALL)));
} else { } else {
...@@ -257,7 +280,7 @@ public class PlacemapRestViewV1 { ...@@ -257,7 +280,7 @@ public class PlacemapRestViewV1 {
} }
private ArrayList<PlaceCodePojo> makePlaceCodePojos(List<Place> places) { private ArrayList<PlaceCodePojo> makePlaceCodePojos(List<Place> places) {
ArrayList<PlaceCodePojo> ret = new ArrayList<PlaceCodePojo>(); ArrayList<PlaceCodePojo> ret = new ArrayList<>();
for (Place p : places) { for (Place p : places) {
if (p.getCode() == null || p.getCode().isEmpty()) { if (p.getCode() == null || p.getCode().isEmpty()) {
String newcode = null; String newcode = null;
......
package fi.codecrew.moya.web.cdiview.map; package fi.codecrew.moya.web.cdiview.map;
import java.util.Collection; import java.awt.*;
import java.util.HashMap; import java.util.*;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.ejb.EJB; import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
...@@ -232,6 +231,16 @@ public class AjaxMapView extends GenericCDIView { ...@@ -232,6 +231,16 @@ public class AjaxMapView extends GenericCDIView {
return reserving; return reserving;
} }
public long getReservingTimeslotEndtime() {
Date timeout = quebean.getReservationTimeout(initMap());
if(timeout == null)
return 0;
return timeout.getTime();
}
public boolean canUserBuy() { public boolean canUserBuy() {
return permbean.hasPermission(MapPermission.BUY_PLACES) && (permbean.hasPermission(MapPermission.MANAGE_OTHERS) return permbean.hasPermission(MapPermission.BUY_PLACES) && (permbean.hasPermission(MapPermission.MANAGE_OTHERS)
|| quebean.isReserving(initMap(), userview.getSelectedUser())); || quebean.isReserving(initMap(), userview.getSelectedUser()));
...@@ -320,4 +329,8 @@ public class AjaxMapView extends GenericCDIView { ...@@ -320,4 +329,8 @@ public class AjaxMapView extends GenericCDIView {
this.slotcount = slotcount; this.slotcount = slotcount;
} }
public boolean isBiggestFirst() {
return isQueueEnabled() && quebean.getMapQueue(initMap()).isBiggestFirst();
}
} }
...@@ -9,6 +9,7 @@ import javax.enterprise.context.ConversationScoped; ...@@ -9,6 +9,7 @@ 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.MapQueueRules;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -38,6 +39,8 @@ public class QueueManageView extends GenericCDIView { ...@@ -38,6 +39,8 @@ public class QueueManageView extends GenericCDIView {
private EventMap map; private EventMap map;
private MapQueueRules rules;
private fi.codecrew.moya.beans.map.QueueBeanLocal.MapQueueI queue; private fi.codecrew.moya.beans.map.QueueBeanLocal.MapQueueI queue;
private String username; private String username;
...@@ -59,6 +62,8 @@ public class QueueManageView extends GenericCDIView { ...@@ -59,6 +62,8 @@ public class QueueManageView extends GenericCDIView {
if (super.requirePermissions(MapPermission.MANAGE_MAPS) && map == null) { if (super.requirePermissions(MapPermission.MANAGE_MAPS) && map == null) {
map = placebean.findMap(mapId); map = placebean.findMap(mapId);
rules = quebean.findRules(map);
queue = quebean.getMapQueue(map); queue = quebean.getMapQueue(map);
logger.info("Got queue {} for map {} with id {} to manage", queue, map, mapId); logger.info("Got queue {} for map {} with id {} to manage", queue, map, mapId);
super.beginConversation(); super.beginConversation();
...@@ -154,4 +159,13 @@ public class QueueManageView extends GenericCDIView { ...@@ -154,4 +159,13 @@ public class QueueManageView extends GenericCDIView {
public void setTime(Date time) { public void setTime(Date time) {
this.time = time; this.time = time;
} }
public void saveToDatabase() {
quebean.saveQueue(queue, map);
rules = quebean.findRules(map); // refresh
}
public MapQueueRules getDefaultValues() {
return rules;
}
} }
...@@ -899,7 +899,7 @@ queuemgmt.defaultTimeoutMin = Reservation time ...@@ -899,7 +899,7 @@ queuemgmt.defaultTimeoutMin = Reservation time
queuemgmt.minimumSlotsInQueue = Minimum amount of places to enter queue queuemgmt.minimumSlotsInQueue = Minimum amount of places to enter queue
queuemgmt.remove = Remove user from queue queuemgmt.remove = Remove user from queue
queuemgmt.reservingSize = Number of people reserving at the same time queuemgmt.reservingSize = Number of people reserving at the same time
queuemgmt.saveProperties = Save properties queuemgmt.saveProperties = Save properties to Database
queuemgmt.time = Reservation time queuemgmt.time = Reservation time
queuemgmt.username = Login queuemgmt.username = Login
...@@ -1582,3 +1582,10 @@ yes = Yes ...@@ -1582,3 +1582,10 @@ yes = Yes
page.product.shopClosed.header=Shop is closed! page.product.shopClosed.header=Shop is closed!
page.product.shopClosed.notOpenYet=Shop is not opened. Try again later. page.product.shopClosed.notOpenYet=Shop is not opened. Try again later.
page.product.shopClosed.alreadyClosed=Shop is closed, welcome back in next event! page.product.shopClosed.alreadyClosed=Shop is closed, welcome back in next event!
queuemgmt.inDatabase=Value in database
queuemgmt.biggestFirst=Biggest group first
queuemgmt.biggestIsFirst=Bigger group automaticly rises up in queue.
reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has timeouted. Pleace go back to queue to continue.
mapView.reserveTimeLeft=Time to reserve places
queuemgmt.queueEnabled=Queue is ENABLED
queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page)
...@@ -1163,7 +1163,7 @@ queuemgmt.defaultTimeoutMin = Reservation time ...@@ -1163,7 +1163,7 @@ queuemgmt.defaultTimeoutMin = Reservation time
queuemgmt.minimumSlotsInQueue = Minimum amount of places to enter queue queuemgmt.minimumSlotsInQueue = Minimum amount of places to enter queue
queuemgmt.remove = Remove user from queue queuemgmt.remove = Remove user from queue
queuemgmt.reservingSize = Number of people reserving at the same time queuemgmt.reservingSize = Number of people reserving at the same time
queuemgmt.saveProperties = Save properties queuemgmt.saveProperties = Save properties to Database
queuemgmt.time = Reservation time queuemgmt.time = Reservation time
queuemgmt.username = Login queuemgmt.username = Login
...@@ -1860,3 +1860,10 @@ yes = Yes ...@@ -1860,3 +1860,10 @@ yes = Yes
page.product.shopClosed.header=Shop is closed! page.product.shopClosed.header=Shop is closed!
page.product.shopClosed.notOpenYet=Shop is not opened. Try again later. page.product.shopClosed.notOpenYet=Shop is not opened. Try again later.
page.product.shopClosed.alreadyClosed=Shop is closed, welcome back in next event! page.product.shopClosed.alreadyClosed=Shop is closed, welcome back in next event!
queuemgmt.inDatabase=Value in database
queuemgmt.biggestFirst=Biggest group first
queuemgmt.biggestIsFirst=Bigger group automaticly rises up in queue.
reservequeue.reservingTimeIsUpAlert=Timeslot for your place reservation has timeouted. Pleace go back to queue to continue.
mapView.reserveTimeLeft=Time to reserve places
queuemgmt.queueEnabled=Queue is ENABLED
queuemgmt.queueDisabled=Queue is DISABLED (enable from Edit event -page)
...@@ -1150,7 +1150,7 @@ queuemgmt.defaultTimeoutMin = Varausaika ...@@ -1150,7 +1150,7 @@ queuemgmt.defaultTimeoutMin = Varausaika
queuemgmt.minimumSlotsInQueue = Jonoonp\u00E4\u00E4syn v\u00E4himm\u00E4ispaikkam\u00E4\u00E4r\u00E4 queuemgmt.minimumSlotsInQueue = Jonoonp\u00E4\u00E4syn v\u00E4himm\u00E4ispaikkam\u00E4\u00E4r\u00E4
queuemgmt.remove = Poista k\u00E4ytt\u00E4j\u00E4 jonosta queuemgmt.remove = Poista k\u00E4ytt\u00E4j\u00E4 jonosta
queuemgmt.reservingSize = Samanaikaisesti varaamaan p\u00E4\u00E4sevien m\u00E4\u00E4r\u00E4 queuemgmt.reservingSize = Samanaikaisesti varaamaan p\u00E4\u00E4sevien m\u00E4\u00E4r\u00E4
queuemgmt.saveProperties = Tallenna arvot queuemgmt.saveProperties = Tallenna arvot tietokantaan
queuemgmt.time = Varausaika queuemgmt.time = Varausaika
queuemgmt.username = K\u00E4ytt\u00E4j\u00E4tunnus queuemgmt.username = K\u00E4ytt\u00E4j\u00E4tunnus
...@@ -1847,3 +1847,10 @@ yes = Kyll\u00E4 ...@@ -1847,3 +1847,10 @@ yes = Kyll\u00E4
page.product.shopClosed.header=Kauppa on kiinni! page.product.shopClosed.header=Kauppa on kiinni!
page.product.shopClosed.notOpenYet=Tapahtuman lipunmyynti ei ole viel\u00E4 alkanut, Kokeile uudelleen my\u00F6hemmin. page.product.shopClosed.notOpenYet=Tapahtuman lipunmyynti ei ole viel\u00E4 alkanut, Kokeile uudelleen my\u00F6hemmin.
page.product.shopClosed.alreadyClosed=Kauppa on suljettu, tervetuloa uudelleen tuleviin tapahtumiin. page.product.shopClosed.alreadyClosed=Kauppa on suljettu, tervetuloa uudelleen tuleviin tapahtumiin.
queuemgmt.inDatabase=Arvo tietokannassa
queuemgmt.biggestFirst=Isoin ryhm\u00E4 ensin
queuemgmt.biggestIsFirst=Isompi ryhm\u00E4 nousee automaattisesti jonossa edemm\u00E4ksi.
reservequeue.reservingTimeIsUpAlert=Sinulle varattu varausauka on kulunut loppuun! Palaa takaisin 'varaa paikkasi' -sivulle jatkaaksesi.
mapView.reserveTimeLeft=Aikaa varata paikkasi
queuemgmt.queueEnabled=Varausjono ON k\u00E4yt\u00F6ss\u00E4
queuemgmt.queueDisabled=K\u00E4ytt\u00E4j\u00E4jono EI OLE k\u00E4yt\u00F6ss\u00E4 (ota k\u00E4yttoon tapahtuman tiedot -sivulta)
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!