mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 13:20:57 +00:00
Merge branch 'master' into bug3855
This commit is contained in:
commit
74e6bcdefd
36 files changed
+574
-510
No files matched your search
+2
@@ -2,6 +2,8 @@ package com.sap.sailing.domain.common.tracking;
|
||||
|
||||
/**
|
||||
* Specific {@link SensorFix} for bravo devices (http://www.bravosystems.es/).
|
||||
*
|
||||
* <p><b>NOTE:</b> This fix type is currently used to track ESS foiling data, only.</p>
|
||||
*/
|
||||
public interface BravoFix extends SensorFix {
|
||||
|
||||
|
||||
+13
@@ -232,6 +232,19 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
|
||||
return ((Number) result.get(FieldNames.NUM_FIXES.name())).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a service implementing specified type of objects interface using the {@link #fixServiceFinder}.
|
||||
* <p>
|
||||
* To support an additional fix type, an implementation of {@link FixMongoHandler} is required, which specifies how to
|
||||
* transform a fix forth to and back from database. This implementation needs to be
|
||||
* registered during OSGi bundle activator startup, providing respective type mapping properties.
|
||||
* </p>
|
||||
*
|
||||
* @param type type object to find service for
|
||||
* @return the registered {@link FixMongoHandler} implementation
|
||||
*
|
||||
* @see TypeBasedServiceFinder#findService(String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <FixT extends Timed> FixMongoHandler<FixT> findService(String type) {
|
||||
return (FixMongoHandler<FixT>) fixServiceFinder.findService(type);
|
||||
|
||||
+2
-2
@@ -3,12 +3,12 @@ package com.sap.sailing.domain.racelogsensortracking;
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixMapper;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
public interface SensorFixMapperFactory {
|
||||
|
||||
<FixT extends Timed, TrackT extends Track<?>> SensorFixMapper<FixT, TrackT, Competitor>
|
||||
<FixT extends Timed, TrackT extends DynamicTrack<FixT>> SensorFixMapper<FixT, TrackT, Competitor>
|
||||
createCompetitorMapper(Class<? extends RegattaLogDeviceMappingEvent<?>> eventType);
|
||||
|
||||
// <FixT extends Timed, TrackT extends Track<?>> SensorFixMapper<FixT, TrackT, Mark>
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMapping
|
||||
import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.racelog.tracking.SensorFixMapper;
|
||||
import com.sap.sailing.domain.racelogsensortracking.SensorFixMapperFactory;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
public class SensorFixMapperFactoryImpl implements SensorFixMapperFactory {
|
||||
@@ -20,7 +20,7 @@ public class SensorFixMapperFactoryImpl implements SensorFixMapperFactory {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <FixT extends Timed, TrackT extends Track<?>> SensorFixMapper<FixT, TrackT, Competitor>
|
||||
public <FixT extends Timed, TrackT extends DynamicTrack<FixT>> SensorFixMapper<FixT, TrackT, Competitor>
|
||||
createCompetitorMapper(Class<? extends RegattaLogDeviceMappingEvent<?>> eventType) {
|
||||
for (ServiceReference<SensorFixMapper<?, ?, ?>> serviceReference : tracker.getServiceReferences()) {
|
||||
SensorFixMapper<?, ?, ?> service = tracker.getService(serviceReference);
|
||||
|
||||
+5
-6
@@ -13,20 +13,19 @@ import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.impl.BravoFixTrackImpl;
|
||||
|
||||
/**
|
||||
* {@link SensorFixMapper} to handle {@link BravoFix}es.
|
||||
*
|
||||
* {@link SensorFixMapper} implementation to handle {@link BravoFix}es.
|
||||
*/
|
||||
public class BravoDataFixMapper implements SensorFixMapper<DoubleVectorFix, DynamicSensorFixTrack<Competitor, BravoFix>, Competitor> {
|
||||
public class BravoDataFixMapper implements SensorFixMapper<BravoFix, DynamicSensorFixTrack<Competitor, BravoFix>, Competitor> {
|
||||
|
||||
@Override
|
||||
public DynamicSensorFixTrack<Competitor, BravoFix> getTrack(DynamicTrackedRace race, Competitor key) {
|
||||
return race.getOrCreateSensorTrack(key, BravoFixTrack.TRACK_NAME,
|
||||
() -> new BravoFixTrackImpl<Competitor>(key, BravoFixTrack.TRACK_NAME));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addFix(DynamicSensorFixTrack<Competitor, BravoFix> track, DoubleVectorFix fix) {
|
||||
track.add(new BravoFixImpl(fix));
|
||||
public BravoFix map(DoubleVectorFix fix) {
|
||||
return new BravoFixImpl(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-4
@@ -30,9 +30,9 @@ import com.sap.sailing.domain.racelogtracking.DeviceMapping;
|
||||
import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent;
|
||||
import com.sap.sailing.domain.tracking.DynamicGPSFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.RaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sailing.domain.tracking.TrackingDataLoader;
|
||||
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
|
||||
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
|
||||
@@ -102,7 +102,7 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
if (preemptiveStopRequested.get()) {
|
||||
return;
|
||||
}
|
||||
SensorFixMapper<DoubleVectorFix, DynamicSensorFixTrack<Competitor, SensorFix>, Competitor> mapper = sensorFixMapperFactory
|
||||
SensorFixMapper<SensorFix, DynamicSensorFixTrack<Competitor, SensorFix>, Competitor> mapper = sensorFixMapperFactory
|
||||
.createCompetitorMapper(event.getClass());
|
||||
DynamicSensorFixTrack<Competitor, SensorFix> track = mapper.getTrack(trackedRace,
|
||||
event.getMappedTo());
|
||||
@@ -171,9 +171,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
|
||||
mapping.getRegattaLogEvent().accept(new MappingEventVisitor() {
|
||||
@Override
|
||||
public void visit(RegattaLogDeviceCompetitorSensorDataMappingEvent event) {
|
||||
SensorFixMapper<Timed, Track<?>, Competitor> mapper = sensorFixMapperFactory
|
||||
SensorFixMapper<Timed, DynamicTrack<Timed>, Competitor> mapper = sensorFixMapperFactory
|
||||
.createCompetitorMapper(event.getClass());
|
||||
Track<?> track = mapper.getTrack(trackedRace, event.getMappedTo());
|
||||
DynamicTrack<Timed> track = mapper.getTrack(trackedRace, event.getMappedTo());
|
||||
try {
|
||||
sensorFixStore.loadFixes((DoubleVectorFix fix) -> mapper.addFix(track, fix), mapping.getDevice(),
|
||||
timeRangeToLoad.from(), timeRangeToLoad.to(), true);
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
/**
|
||||
* {@link Track} specialization, which is mapped to a specific type of items.
|
||||
*
|
||||
* @param <ItemType>
|
||||
* the type of item this track is mapped to
|
||||
* @param <FixType>
|
||||
* the type of fix that is contained in this track
|
||||
*/
|
||||
public interface MappedTrack<ItemType, FixType extends Timed> extends Track<FixType> {
|
||||
|
||||
/**
|
||||
* @return the item this track is mapped to.
|
||||
*/
|
||||
ItemType getTrackedItem();
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import com.sap.sailing.domain.tracking.MappedTrack;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link MappedTrack} interface.
|
||||
*
|
||||
* @param <ItemType>
|
||||
* the type of item this track is mapped to
|
||||
* @param <FixType>
|
||||
* the type of fix that is contained in this track
|
||||
*/
|
||||
public class MappedTrackImpl<ItemType, FixType extends Timed> extends TrackImpl<FixType>
|
||||
implements MappedTrack<ItemType, FixType> {
|
||||
|
||||
private static final long serialVersionUID = 6165693342087329096L;
|
||||
|
||||
private final ItemType trackedItem;
|
||||
|
||||
/** @see TrackImpl#TrackImpl(String) */
|
||||
public MappedTrackImpl(ItemType trackedItem, String nameForReadWriteLock) {
|
||||
super(nameForReadWriteLock);
|
||||
this.trackedItem = trackedItem;
|
||||
}
|
||||
|
||||
/** @see TrackImpl#TrackImpl(ArrayListNavigableSet, String) */
|
||||
protected MappedTrackImpl(ItemType trackedItem, ArrayListNavigableSet<Timed> fixes, String nameForReadWriteLock) {
|
||||
super(fixes, nameForReadWriteLock);
|
||||
this.trackedItem = trackedItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getTrackedItem() {
|
||||
return trackedItem;
|
||||
}
|
||||
|
||||
}
|
||||
+19
-4
@@ -1,20 +1,24 @@
|
||||
package com.sap.sailing.domain.racelog.tracking;
|
||||
|
||||
import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDeviceMappingEvent;
|
||||
import com.sap.sailing.domain.common.tracking.DoubleVectorFix;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.Track;
|
||||
import com.sap.sse.common.Timed;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
/**
|
||||
* This is used by the fix tracking mechanism to make fixes available in a track.
|
||||
* This makes it possible to e.g. map fixes to another type before adding them to the track.
|
||||
* <p>
|
||||
*
|
||||
* Implementations need to be registered as OSGi service to be correctly found.
|
||||
*
|
||||
* @param <FixT> the type of fix this mapper handles
|
||||
* @param <TrackT> the type of track this mapper adds the fixes to
|
||||
* @param <K> the type of item the track is mapped to
|
||||
*/
|
||||
public interface SensorFixMapper<FixT extends Timed, TrackT extends Track<?>, K extends WithID> {
|
||||
public interface SensorFixMapper<FixT extends Timed, TrackT extends DynamicTrack<FixT>, K extends WithID> {
|
||||
|
||||
/**
|
||||
* Extracts the track from the TrackedRace or creates a new one if it doesn't already exist.
|
||||
@@ -26,12 +30,23 @@ public interface SensorFixMapper<FixT extends Timed, TrackT extends Track<?>, K
|
||||
TrackT getTrack(DynamicTrackedRace race, K key);
|
||||
|
||||
/**
|
||||
* Adds a fix to the given Track. This can also be used to map fixes to another type if necessary.
|
||||
* This default implementation maps the given {@link DoubleVectorFix} using the {@link #map(DoubleVectorFix)} method
|
||||
* first. Afterwards, the mapped fix will be added to the given track.
|
||||
*
|
||||
* @param track the track to add the fix to
|
||||
* @param fix the fix to add
|
||||
*/
|
||||
void addFix(TrackT track, FixT fix);
|
||||
default void addFix(TrackT track, DoubleVectorFix fix) {
|
||||
track.add(map(fix));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method maps the given {@link DoubleVectorFix} to the required fix type.
|
||||
*
|
||||
* @param fix the {@link DoubleVectorFix} to map
|
||||
* @return the mapped fix type instance
|
||||
*/
|
||||
FixT map(DoubleVectorFix fix);
|
||||
|
||||
/**
|
||||
* Checks if this mapper can be used for tracks/fixes that are associated to a given RegattaLog device mapping event.
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
/**
|
||||
* Extension of {@link MappedTrack} interface, which also implements {@link DynamicTrack} interface.
|
||||
*
|
||||
* @param <ItemType>
|
||||
* the type of item this track is mapped to
|
||||
* @param <FixType>
|
||||
* the type of fix that is contained in this track
|
||||
*/
|
||||
public interface DynamicMappedTrack<ItemType, FixType extends Timed>
|
||||
extends MappedTrack<ItemType, FixType>, DynamicTrack<FixType> {
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import com.sap.sse.common.Util;
|
||||
*
|
||||
* @param <ItemType>
|
||||
*/
|
||||
public interface GPSFixTrack<ItemType, FixType extends GPSFix> extends Track<FixType> {
|
||||
public interface GPSFixTrack<ItemType, FixType extends GPSFix> extends MappedTrack<ItemType, FixType> {
|
||||
static final long DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_SPEED = 10000; // makes for a 5s half-side interval
|
||||
static final Speed DEFAULT_MAX_SPEED_FOR_SMOOTHING = new KnotSpeedImpl(40);
|
||||
|
||||
@@ -40,8 +40,6 @@ public interface GPSFixTrack<ItemType, FixType extends GPSFix> extends Track<Fix
|
||||
|
||||
void removeListener(GPSTrackListener<ItemType, FixType> listener);
|
||||
|
||||
ItemType getTrackedItem();
|
||||
|
||||
/**
|
||||
* Computes the distance traveled on the smoothened track between the
|
||||
* {@link #getEstimatedPosition(TimePoint, boolean) estimated positions} at <code>from</code> and <code>to</code>.
|
||||
|
||||
@@ -27,6 +27,10 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
* A tracker may be {@link #stop(boolean) stopped}. In this case, it will no longer receive any data at all. Stopping a tracker
|
||||
* will not modify the {@link Regatta} and the {@link TrackedRegatta} with regards to their ownership of their
|
||||
* {@link RaceDefiniion} and {@link TrackedRace}, respectively.
|
||||
* <p>
|
||||
*
|
||||
* A {@link RaceTracker} controls the lifecycle of a {@link TrackedRace} in contrast to a {@link TrackingDataLoader} which just
|
||||
* contributes to the composite status but does not control the lifecycle.
|
||||
*
|
||||
* @author Axel Uhl (d043530)
|
||||
*
|
||||
|
||||
@@ -13,7 +13,8 @@ import com.sap.sse.common.WithID;
|
||||
* @param <ItemType> the type of item this track is mapped to
|
||||
* @param <FixT> the type of fix that is contained in this track
|
||||
*/
|
||||
public interface SensorFixTrack<ItemType extends WithID & Serializable, FixT extends SensorFix> extends Track<FixT> {
|
||||
public interface SensorFixTrack<ItemType extends WithID & Serializable, FixT extends SensorFix>
|
||||
extends MappedTrack<ItemType, FixT> {
|
||||
|
||||
/**
|
||||
* Value names to be used when reading values from {@link SensorFix}es by calling {@link SensorFix#get(String)}.
|
||||
@@ -26,11 +27,6 @@ public interface SensorFixTrack<ItemType extends WithID & Serializable, FixT ext
|
||||
|
||||
void removeListener(SensorFixTrackListener<ItemType, FixT> listener);
|
||||
|
||||
/**
|
||||
* @return the item this tracked is mapped to.
|
||||
*/
|
||||
ItemType getTrackedItem();
|
||||
|
||||
/**
|
||||
* @return the associated track name by which this track can be obtained from the {@link TrackedRace}.
|
||||
*/
|
||||
|
||||
+6
@@ -1,4 +1,10 @@
|
||||
package com.sap.sailing.domain.tracking;
|
||||
|
||||
/**
|
||||
* Marker interface for classes that load data for a {@link TrackedRace} and therefore contribute to the composite
|
||||
* status of a tracked race. A {@link TrackingDataLoader} must update it's state in the associated {@link TrackedRace}
|
||||
* by calling {@link DynamicTrackedRace#onStatusChanged(TrackingDataLoader, TrackedRaceStatus)} with a self-reference
|
||||
* and the actual status.
|
||||
*/
|
||||
public interface TrackingDataLoader {
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.sap.sailing.domain.tracking.impl;
|
||||
|
||||
import com.sap.sailing.domain.tracking.DynamicMappedTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sse.common.Timed;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link DynamicMappedTrack} interface.
|
||||
*
|
||||
* @param <ItemType>
|
||||
* the type of item this track is mapped to
|
||||
* @param <FixType>
|
||||
* the type of fix that is contained in this track
|
||||
*/
|
||||
public class DynamicMappedTrackImpl<ItemType, FixType extends Timed> extends MappedTrackImpl<ItemType, FixType>
|
||||
implements DynamicMappedTrack<ItemType, FixType> {
|
||||
|
||||
private static final long serialVersionUID = -8705397260656473352L;
|
||||
|
||||
public DynamicMappedTrackImpl(ItemType trackedItem, String nameForReadWriteLock) {
|
||||
super(trackedItem, nameForReadWriteLock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply makes the superclass method public as now we need to expose it via the {@link DynamicTrack} interface.
|
||||
*/
|
||||
@Override
|
||||
public boolean add(FixType fix) {
|
||||
return super.add(fix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(FixType fix, boolean replace) {
|
||||
return super.add(fix, replace);
|
||||
}
|
||||
}
|
||||
+5
-10
@@ -45,12 +45,12 @@ import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.common.impl.TimeRangeImpl;
|
||||
import com.sap.sse.util.impl.ArrayListNavigableSet;
|
||||
|
||||
public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl<FixType> implements GPSFixTrack<ItemType, FixType> {
|
||||
public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends MappedTrackImpl<ItemType, FixType>
|
||||
implements GPSFixTrack<ItemType, FixType> {
|
||||
private static final Logger logger = Logger.getLogger(GPSFixTrackImpl.class.getName());
|
||||
private static final long serialVersionUID = 2115321069242514378L;
|
||||
protected final Speed maxSpeedForSmoothing;
|
||||
|
||||
private final ItemType trackedItem;
|
||||
private long millisecondsOverWhichToAverage;
|
||||
|
||||
private final TrackListenerCollection<ItemType, FixType, GPSTrackListener<ItemType, FixType>> listeners;
|
||||
@@ -131,8 +131,8 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
* inferred speed can be matched.
|
||||
*/
|
||||
public GPSFixTrackImpl(ItemType trackedItem, long millisecondsOverWhichToAverage, Speed maxSpeedForSmoothening) {
|
||||
super(/* nameForReadWriteLock */ GPSFixTrackImpl.class.getSimpleName()+(trackedItem==null?"":(" for "+trackedItem.toString())));
|
||||
this.trackedItem = trackedItem;
|
||||
super(trackedItem, /* nameForReadWriteLock */ GPSFixTrackImpl.class.getSimpleName()
|
||||
+ (trackedItem == null ? "" : (" for " + trackedItem.toString())));
|
||||
this.millisecondsOverWhichToAverage = millisecondsOverWhichToAverage;
|
||||
this.maxSpeedForSmoothing = maxSpeedForSmoothening;
|
||||
this.listeners = new TrackListenerCollection<ItemType, FixType, GPSTrackListener<ItemType,FixType>>();
|
||||
@@ -166,7 +166,7 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
|
||||
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||
ois.defaultReadObject();
|
||||
distanceCache = new DistanceCache(trackedItem.toString());
|
||||
distanceCache = new DistanceCache(getTrackedItem().toString());
|
||||
maxSpeedCache = createMaxSpeedCache();
|
||||
}
|
||||
|
||||
@@ -247,11 +247,6 @@ public class GPSFixTrackImpl<ItemType, FixType extends GPSFix> extends TrackImpl
|
||||
FixType result = (FixType) new DummyGPSFix(timePoint);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getTrackedItem() {
|
||||
return trackedItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMillisecondsOverWhichToAverageSpeed() {
|
||||
|
||||
+3
-10
@@ -17,12 +17,11 @@ import com.sap.sse.common.WithID;
|
||||
* @param <FixT> the type of fix this track holds
|
||||
*/
|
||||
public class SensorFixTrackImpl<ItemType extends WithID & Serializable, FixT extends SensorFix> extends
|
||||
DynamicTrackImpl<FixT> implements DynamicSensorFixTrack<ItemType, FixT> {
|
||||
DynamicMappedTrackImpl<ItemType, FixT> implements DynamicSensorFixTrack<ItemType, FixT> {
|
||||
|
||||
private static final long serialVersionUID = 6383421895429843002L;
|
||||
|
||||
private final Iterable<String> valueNames;
|
||||
private final ItemType trackedItem;
|
||||
private final String trackName;
|
||||
private final TrackListenerCollection<ItemType, FixT, SensorFixTrackListener<ItemType, FixT>> listeners;
|
||||
|
||||
@@ -34,8 +33,7 @@ public class SensorFixTrackImpl<ItemType extends WithID & Serializable, FixT ext
|
||||
*/
|
||||
public SensorFixTrackImpl(ItemType trackedItem, String trackName, Iterable<String> valueNames,
|
||||
String nameForReadWriteLock) {
|
||||
super(nameForReadWriteLock);
|
||||
this.trackedItem = trackedItem;
|
||||
super(trackedItem, nameForReadWriteLock);
|
||||
this.trackName = trackName;
|
||||
this.valueNames = valueNames;
|
||||
this.listeners = new TrackListenerCollection<>();
|
||||
@@ -48,7 +46,7 @@ public class SensorFixTrackImpl<ItemType extends WithID & Serializable, FixT ext
|
||||
try {
|
||||
final boolean firstFixInTrack = getRawFixes().isEmpty();
|
||||
result = addWithoutLocking(fix, replace);
|
||||
this.notifyListeners((listener) -> listener.fixReceived(fix, trackedItem, trackName, firstFixInTrack));
|
||||
this.notifyListeners((listener) -> listener.fixReceived(fix, getTrackedItem(), trackName, firstFixInTrack));
|
||||
} finally {
|
||||
unlockAfterWrite();
|
||||
}
|
||||
@@ -74,11 +72,6 @@ public class SensorFixTrackImpl<ItemType extends WithID & Serializable, FixT ext
|
||||
this.listeners.removeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemType getTrackedItem() {
|
||||
return trackedItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTrackName() {
|
||||
return trackName;
|
||||
|
||||
+6
@@ -119,6 +119,7 @@ import com.sap.sailing.domain.ranking.OneDesignRankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric;
|
||||
import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo;
|
||||
import com.sap.sailing.domain.ranking.RankingMetricConstructor;
|
||||
import com.sap.sailing.domain.tracking.BravoFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrack;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
@@ -298,6 +299,11 @@ public abstract class TrackedRaceImpl extends TrackedRaceWithWindEssentials impl
|
||||
|
||||
private final ConcurrentMap<Mark, GPSFixTrack<Mark, GPSFix>> markTracks;
|
||||
|
||||
/**
|
||||
* Mapping of {@link Competitor} to generic {@link DynamicTrack} implementation. Because the same competitor could
|
||||
* be mapped to several different tracks, a combined key of competitor object and track name identifier string is
|
||||
* used. This identifier is usually defined within the track interface (e.g. see {@link BravoFixTrack#TRACK_NAME}).
|
||||
*/
|
||||
private final Map<Pair<Competitor, String>, DynamicTrack<?>> sensorTracks;
|
||||
|
||||
private final Map<String, Sideline> courseSidelines;
|
||||
|
||||
+1
-1
@@ -36,8 +36,8 @@ public abstract class RaceviewerLaunchPad extends Composite {
|
||||
}
|
||||
if (data.isRunning() || data.isFinished()) {
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.START_ANALYSIS);
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.WINNING_LANES);
|
||||
}
|
||||
addItem(data, RaceviewerLaunchPadMenuItem.WINNING_LANES);
|
||||
sinkEvents(Event.ONCLICK);
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -3,8 +3,6 @@
|
||||
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
</ui:style>
|
||||
<um:AuthorizedContentDecoratorDesktop ui:field="decoratorUi">
|
||||
<um:content>
|
||||
<ud:UserAccountDetails ui:field="accountDetailsUi"
|
||||
|
||||
+13
-103
@@ -1,133 +1,43 @@
|
||||
package com.sap.sailing.gwt.home.desktop.places.user.profile.preferencestab;
|
||||
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.CompetitorSuggestionResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteBoatClassesDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteCompetitorsDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoritesResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetCompetitorSuggestionAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetFavoritesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteBoatClassesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteCompetitorsAction;
|
||||
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileClientFactory;
|
||||
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileView;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.VoidResult;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesPresenter;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView.Presenter;
|
||||
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
|
||||
|
||||
public class UserProfilePreferencesPresenter implements UserProfilePreferencesView.Presenter {
|
||||
|
||||
private final UserProfilePreferencesView view;
|
||||
private final UserProfileView.Presenter userProfilePresenter;
|
||||
private final SuggestedMultiSelectionCompetitorDataProvider competitorDataProvider =
|
||||
new SuggestedMultiSelectionCompetitorDataProviderImpl();
|
||||
private final SuggestedMultiSelectionBoatClassDataProvider boatClassDataProvider =
|
||||
new SuggestedMultiSelectionBoatClassDataProviderImpl();
|
||||
private final UserPreferencesView.Presenter userPreferencesPresenter;
|
||||
|
||||
public UserProfilePreferencesPresenter(final UserProfilePreferencesView view,
|
||||
final UserProfileView.Presenter userProfilePresenter) {
|
||||
this.view = view;
|
||||
this.userProfilePresenter = userProfilePresenter;
|
||||
this.userPreferencesPresenter = new UserPreferencesPresenter<UserProfileClientFactory>(
|
||||
userProfilePresenter.getClientFactory());
|
||||
view.setPresenter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Presenter getUserPreferencesPresenter() {
|
||||
return userPreferencesPresenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
|
||||
view.getDecorator().setAuthenticationContext(authenticationContext);
|
||||
if (authenticationContext.isLoggedIn()) {
|
||||
userProfilePresenter.getClientFactory().getDispatch().execute(new GetFavoritesAction(),
|
||||
new AsyncCallback<FavoritesResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
userProfilePresenter.getClientFactory()
|
||||
.createErrorView("Error while loading notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(FavoritesResult result) {
|
||||
initFavoriteCompetitors(result.getFavoriteCompetitors());
|
||||
initFavoriteBoatClasses(result.getFavoriteBoatClasses());
|
||||
}
|
||||
});
|
||||
userPreferencesPresenter.loadPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
private void initFavoriteCompetitors(FavoriteCompetitorsDTO favoriteCompetitors) {
|
||||
competitorDataProvider.initNotifications(favoriteCompetitors.isNotifyAboutResults());
|
||||
competitorDataProvider.initSelectedItems(favoriteCompetitors.getSelectedCompetitors());
|
||||
}
|
||||
|
||||
private void initFavoriteBoatClasses(FavoriteBoatClassesDTO favoriteBoatClasses) {
|
||||
boatClassDataProvider.initNotifications(favoriteBoatClasses.isNotifyAboutUpcomingRaces(),
|
||||
favoriteBoatClasses.isNotifyAboutResults());
|
||||
boatClassDataProvider.initSelectedItems(favoriteBoatClasses.getSelectedBoatClasses());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTriggerLoginForm() {
|
||||
userProfilePresenter.doTriggerLoginForm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider() {
|
||||
return boatClassDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider() {
|
||||
return competitorDataProvider;
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionBoatClassDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionBoatClassDataProvider {
|
||||
@Override
|
||||
protected void persist(FavoriteBoatClassesDTO favorites) {
|
||||
userProfilePresenter.getClientFactory().getDispatch().execute(
|
||||
new SaveFavoriteBoatClassesAction(favorites), new SaveAsyncCallback());
|
||||
}
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionCompetitorDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionCompetitorDataProvider {
|
||||
|
||||
@Override
|
||||
protected void getSuggestions(Iterable<String> queryTokens, int limit,
|
||||
final SuggestionItemsCallback<SimpleCompetitorWithIdDTO> callback) {
|
||||
userProfilePresenter.getClientFactory().getDispatch().execute(
|
||||
new GetCompetitorSuggestionAction(queryTokens, limit),
|
||||
new AsyncCallback<CompetitorSuggestionResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
Window.alert("Error while loading competitor suggestion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompetitorSuggestionResult result) {
|
||||
callback.setSuggestionItems(result.getValues());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void persist(FavoriteCompetitorsDTO favorites) {
|
||||
userProfilePresenter.getClientFactory().getDispatch().execute(new SaveFavoriteCompetitorsAction(favorites),
|
||||
new SaveAsyncCallback());
|
||||
}
|
||||
}
|
||||
|
||||
private class SaveAsyncCallback implements AsyncCallback<VoidResult> {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
userProfilePresenter.getClientFactory().createErrorView(
|
||||
"Error while saving notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -1,8 +1,7 @@
|
||||
package com.sap.sailing.gwt.home.desktop.places.user.profile.preferencestab;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView;
|
||||
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
|
||||
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
|
||||
|
||||
@@ -13,7 +12,6 @@ public interface UserProfilePreferencesView extends IsWidget {
|
||||
NeedsAuthenticationContext getDecorator();
|
||||
|
||||
public interface Presenter extends NotLoggedInPresenter, NeedsAuthenticationContext {
|
||||
SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider();
|
||||
SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider();
|
||||
UserPreferencesView.Presenter getUserPreferencesPresenter();
|
||||
}
|
||||
}
|
||||
+3
-83
@@ -1,22 +1,12 @@
|
||||
package com.sap.sailing.gwt.home.desktop.places.user.profile.preferencestab;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HasEnabled;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.dto.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection.NotificationCallback;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferences;
|
||||
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.AuthorizedContentDecoratorDesktop;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
|
||||
|
||||
public class UserProfilePreferencesViewImpl extends Composite implements UserProfilePreferencesView {
|
||||
@@ -27,88 +17,18 @@ public class UserProfilePreferencesViewImpl extends Composite implements UserPro
|
||||
private static MyBinder uiBinder = GWT.create(MyBinder.class);
|
||||
|
||||
@UiField(provided = true) AuthorizedContentDecoratorDesktop decoratorUi;
|
||||
@UiField(provided = true) SuggestedMultiSelection<SimpleCompetitorWithIdDTO> favoriteCompetitorsSelctionUi;
|
||||
@UiField(provided = true) SuggestedMultiSelection<BoatClassDTO> favoriteBoatClassesSelctionUi;
|
||||
@UiField DivElement notificationsTextUi;
|
||||
@UiField(provided = true) UserPreferences userPreferencesUi;
|
||||
|
||||
@Override
|
||||
public void setPresenter(Presenter presenter) {
|
||||
decoratorUi = new AuthorizedContentDecoratorDesktop(presenter);
|
||||
favoriteCompetitorsSelctionUi = new CompetitorDisplayImpl(
|
||||
presenter.getFavoriteCompetitorsDataProvider()).selectionUi;
|
||||
favoriteBoatClassesSelctionUi = new BoatClassDisplayImpl(
|
||||
presenter.getFavoriteBoatClassesDataProvider()).selectionUi;
|
||||
userPreferencesUi = new UserPreferences(presenter.getUserPreferencesPresenter());
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
// TODO hide notificationsTextUi if the user's mail address is already verified
|
||||
}
|
||||
|
||||
@Override
|
||||
public NeedsAuthenticationContext getDecorator() {
|
||||
return decoratorUi;
|
||||
}
|
||||
|
||||
private class CompetitorDisplayImpl implements SuggestedMultiSelectionCompetitorDataProvider.Display {
|
||||
private final SuggestedMultiSelection<SimpleCompetitorWithIdDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private CompetitorDisplayImpl(final SuggestedMultiSelectionCompetitorDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forCompetitors(dataProvider, StringMessages.INSTANCE.favoriteCompetitors());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<SimpleCompetitorWithIdDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
|
||||
private class BoatClassDisplayImpl implements SuggestedMultiSelectionBoatClassDataProvider.Display {
|
||||
private final SuggestedMultiSelection<BoatClassDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutUpcomingRacesUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private BoatClassDisplayImpl(final SuggestedMultiSelectionBoatClassDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forBoatClasses(dataProvider, StringMessages.INSTANCE.favoriteBoatClasses());
|
||||
notifyAboutUpcomingRacesUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutUpcomingRaces(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutUpcomingRaces());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<BoatClassDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutUpcomingRaces(boolean notifyAboutUpcomingRaces) {
|
||||
notifyAboutUpcomingRacesUi.setEnabled(notifyAboutUpcomingRaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+2
-15
@@ -1,24 +1,11 @@
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui'
|
||||
xmlns:ud="urn:import:com.sap.sse.security.ui.userprofile.desktop.userdetails"
|
||||
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator"
|
||||
xmlns:ms="urn:import:com.sap.sailing.gwt.home.shared.partials.multiselection">
|
||||
xmlns:up="urn:import:com.sap.sailing.gwt.home.shared.places.user.profile.preferences">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
</ui:style>
|
||||
<um:AuthorizedContentDecoratorDesktop ui:field="decoratorUi">
|
||||
<um:content>
|
||||
<g:HTMLPanel addStyleNames="{res.mediaCss.grid} {res.mainCss.spacermarginbottommediumsmall}">
|
||||
<div ui:field="notificationsTextUi" class="{res.mediaCss.column} {res.mediaCss.medium12} {res.mainCss.spacermargintopsmall} {res.mainCss.spacermarginbottomsmall}">
|
||||
<ui:text from="{i18n.userNotificationsOnlyIfMailAddressIsVerified}" />
|
||||
</div>
|
||||
<div class="{res.mediaCss.column} {res.mediaCss.small12} {res.mediaCss.medium6} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection ui:field="favoriteCompetitorsSelctionUi"/>
|
||||
</div>
|
||||
<div class="{res.mediaCss.column} {res.mediaCss.small12} {res.mediaCss.medium6} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection ui:field="favoriteBoatClassesSelctionUi"/>
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
<up:UserPreferences ui:field="userPreferencesUi"/>
|
||||
</um:content>
|
||||
</um:AuthorizedContentDecoratorDesktop>
|
||||
</ui:UiBinder>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.sap.sailing.gwt.home.mobile.places.user.profile;
|
||||
|
||||
import com.google.gwt.activity.shared.AbstractActivity;
|
||||
import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory;
|
||||
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
|
||||
|
||||
public abstract class AbstractUserProfileActivity extends AbstractActivity implements UserProfileViewBase.Presenter{
|
||||
|
||||
protected final MobileApplicationClientFactory clientFactory;
|
||||
|
||||
protected AbstractUserProfileActivity(MobileApplicationClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTriggerLoginForm() {
|
||||
clientFactory.getNavigator().getSignInNavigation().goToPlace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserProfileNavigation() {
|
||||
return clientFactory.getNavigator().getUserProfileNavigation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserPreferencesNavigation() {
|
||||
return clientFactory.getNavigator().getUserPreferencesNavigation();
|
||||
}
|
||||
|
||||
}
|
||||
+3
-21
@@ -1,24 +1,20 @@
|
||||
package com.sap.sailing.gwt.home.mobile.places.user.profile.details;
|
||||
|
||||
import com.google.gwt.activity.shared.AbstractActivity;
|
||||
import com.google.gwt.event.shared.EventBus;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory;
|
||||
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
|
||||
import com.sap.sailing.gwt.home.mobile.places.user.profile.AbstractUserProfileActivity;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
|
||||
import com.sap.sse.security.ui.authentication.AuthenticationContextEvent;
|
||||
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsPresenter;
|
||||
|
||||
public class UserProfileDetailsActivity extends AbstractActivity implements UserProfileDetailsView.Presenter {
|
||||
public class UserProfileDetailsActivity extends AbstractUserProfileActivity implements UserProfileDetailsView.Presenter {
|
||||
|
||||
private final MobileApplicationClientFactory clientFactory;
|
||||
|
||||
private final UserProfileDetailsView currentView;
|
||||
|
||||
private UserDetailsPresenter userDetailsPresenter;
|
||||
|
||||
public UserProfileDetailsActivity(AbstractUserProfilePlace place, MobileApplicationClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
super(clientFactory);
|
||||
this.currentView = new UserProfileDetailsViewImpl(this);
|
||||
}
|
||||
|
||||
@@ -40,18 +36,4 @@ public class UserProfileDetailsActivity extends AbstractActivity implements User
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTriggerLoginForm() {
|
||||
clientFactory.getNavigator().getSignInNavigation().goToPlace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserProfileNavigation() {
|
||||
return clientFactory.getNavigator().getUserProfileNavigation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserPreferencesNavigation() {
|
||||
return clientFactory.getNavigator().getUserPreferencesNavigation();
|
||||
}
|
||||
}
|
||||
+13
-115
@@ -1,42 +1,24 @@
|
||||
package com.sap.sailing.gwt.home.mobile.places.user.profile.preferences;
|
||||
|
||||
import com.google.gwt.activity.shared.AbstractActivity;
|
||||
import com.google.gwt.event.shared.EventBus;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwt.user.client.ui.AcceptsOneWidget;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.CompetitorSuggestionResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteBoatClassesDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteCompetitorsDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoritesResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetCompetitorSuggestionAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetFavoritesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteBoatClassesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteCompetitorsAction;
|
||||
import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory;
|
||||
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
|
||||
import com.sap.sailing.gwt.home.mobile.places.user.profile.AbstractUserProfileActivity;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesPresenter;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView.Presenter;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserProfilePreferencesPlace;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.VoidResult;
|
||||
import com.sap.sse.security.ui.authentication.AuthenticationContextEvent;
|
||||
|
||||
public class UserProfilePreferencesActivity extends AbstractActivity implements UserProfilePreferencesView.Presenter {
|
||||
public class UserProfilePreferencesActivity extends AbstractUserProfileActivity implements UserProfilePreferencesView.Presenter {
|
||||
|
||||
private final MobileApplicationClientFactory clientFactory;
|
||||
private final UserProfilePreferencesView currentView;;
|
||||
private final SuggestedMultiSelectionCompetitorDataProvider competitorDataProvider =
|
||||
new SuggestedMultiSelectionCompetitorDataProviderImpl();
|
||||
private final SuggestedMultiSelectionBoatClassDataProvider boatClassDataProvider =
|
||||
new SuggestedMultiSelectionBoatClassDataProviderImpl();
|
||||
private final UserPreferencesView.Presenter userPreferencesPresenter;
|
||||
private final UserProfilePreferencesView currentView;
|
||||
|
||||
public UserProfilePreferencesActivity(UserProfilePreferencesPlace place,
|
||||
MobileApplicationClientFactory clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
super(clientFactory);
|
||||
this.userPreferencesPresenter = new UserPreferencesPresenter<MobileApplicationClientFactory>(clientFactory);
|
||||
this.currentView = new UserProfilePreferencesViewImpl(this);
|
||||
}
|
||||
|
||||
@@ -50,98 +32,14 @@ public class UserProfilePreferencesActivity extends AbstractActivity implements
|
||||
currentView.setAuthenticationContext(event.getCtx());
|
||||
}
|
||||
});
|
||||
clientFactory.getDispatch().execute(new GetFavoritesAction(), new AsyncCallback<FavoritesResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
clientFactory.createErrorView("Error while loading notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(FavoritesResult result) {
|
||||
initFavoriteCompetitors(result.getFavoriteCompetitors());
|
||||
initFavoriteBoatClasses(result.getFavoriteBoatClasses());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initFavoriteCompetitors(FavoriteCompetitorsDTO favoriteCompetitors) {
|
||||
competitorDataProvider.initNotifications(favoriteCompetitors.isNotifyAboutResults());
|
||||
competitorDataProvider.initSelectedItems(favoriteCompetitors.getSelectedCompetitors());
|
||||
}
|
||||
|
||||
private void initFavoriteBoatClasses(FavoriteBoatClassesDTO favoriteBoatClasses) {
|
||||
boatClassDataProvider.initNotifications(favoriteBoatClasses.isNotifyAboutUpcomingRaces(),
|
||||
favoriteBoatClasses.isNotifyAboutResults());
|
||||
boatClassDataProvider.initSelectedItems(favoriteBoatClasses.getSelectedBoatClasses());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doTriggerLoginForm() {
|
||||
clientFactory.getNavigator().getSignInNavigation().goToPlace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider() {
|
||||
return boatClassDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider() {
|
||||
return competitorDataProvider;
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionBoatClassDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionBoatClassDataProvider {
|
||||
@Override
|
||||
protected void persist(FavoriteBoatClassesDTO favorites) {
|
||||
clientFactory.getDispatch().execute(new SaveFavoriteBoatClassesAction(favorites), new SaveAsyncCallback());
|
||||
}
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionCompetitorDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionCompetitorDataProvider {
|
||||
|
||||
@Override
|
||||
protected void getSuggestions(Iterable<String> queryTokens, int limit,
|
||||
final SuggestionItemsCallback<SimpleCompetitorWithIdDTO> callback) {
|
||||
clientFactory.getDispatch().execute(new GetCompetitorSuggestionAction(queryTokens, limit),
|
||||
new AsyncCallback<CompetitorSuggestionResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
Window.alert("Error while loading competitor suggestion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompetitorSuggestionResult result) {
|
||||
callback.setSuggestionItems(result.getValues());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void persist(FavoriteCompetitorsDTO favorites) {
|
||||
clientFactory.getDispatch().execute(new SaveFavoriteCompetitorsAction(favorites), new SaveAsyncCallback());
|
||||
if (clientFactory.getAuthenticationManager().getAuthenticationContext().isLoggedIn()) {
|
||||
userPreferencesPresenter.loadPreferences();
|
||||
}
|
||||
}
|
||||
|
||||
private class SaveAsyncCallback implements AsyncCallback<VoidResult> {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
clientFactory.createErrorView("Error while saving notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserProfileNavigation() {
|
||||
return clientFactory.getNavigator().getUserProfileNavigation();
|
||||
public Presenter getUserPreferencesPresenter() {
|
||||
return userPreferencesPresenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceNavigation<? extends AbstractUserProfilePlace> getUserPreferencesNavigation() {
|
||||
return clientFactory.getNavigator().getUserPreferencesNavigation();
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -1,14 +1,12 @@
|
||||
package com.sap.sailing.gwt.home.mobile.places.user.profile.preferences;
|
||||
|
||||
import com.sap.sailing.gwt.home.mobile.places.user.profile.UserProfileViewBase;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView;
|
||||
|
||||
public interface UserProfilePreferencesView extends UserProfileViewBase {
|
||||
|
||||
public interface Presenter extends UserProfileViewBase.Presenter {
|
||||
SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider();
|
||||
SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider();
|
||||
UserPreferencesView.Presenter getUserPreferencesPresenter();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-89
@@ -1,101 +1,18 @@
|
||||
package com.sap.sailing.gwt.home.mobile.places.user.profile.preferences;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.HasEnabled;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.dto.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.mobile.places.user.profile.AbstractUserProfileView;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection.NotificationCallback;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferences;
|
||||
import com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferencesView;
|
||||
|
||||
public class UserProfilePreferencesViewImpl extends AbstractUserProfileView implements UserProfilePreferencesView {
|
||||
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
|
||||
|
||||
interface MyUiBinder extends UiBinder<Widget, UserProfilePreferencesViewImpl> {
|
||||
}
|
||||
|
||||
@UiField(provided = true) SuggestedMultiSelection<SimpleCompetitorWithIdDTO> favoriteCompetitorsSelctionUi;
|
||||
@UiField(provided = true) SuggestedMultiSelection<BoatClassDTO> favoriteBoatClassesSelctionUi;
|
||||
@UiField DivElement notificationsTextUi;
|
||||
private final UserPreferencesView userPreferencesView;
|
||||
|
||||
public UserProfilePreferencesViewImpl(UserProfilePreferencesView.Presenter presenter) {
|
||||
super(presenter);
|
||||
favoriteCompetitorsSelctionUi = new CompetitorDisplayImpl(
|
||||
presenter.getFavoriteCompetitorsDataProvider()).selectionUi;
|
||||
favoriteBoatClassesSelctionUi = new BoatClassDisplayImpl(
|
||||
presenter.getFavoriteBoatClassesDataProvider()).selectionUi;
|
||||
setViewContent(uiBinder.createAndBindUi(this));
|
||||
this.userPreferencesView = new UserPreferences(presenter.getUserPreferencesPresenter());
|
||||
this.userPreferencesView.setEdgeToEdge(true);
|
||||
this.setViewContent(userPreferencesView);
|
||||
}
|
||||
|
||||
private class CompetitorDisplayImpl implements SuggestedMultiSelectionCompetitorDataProvider.Display {
|
||||
private final SuggestedMultiSelection<SimpleCompetitorWithIdDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private CompetitorDisplayImpl(final SuggestedMultiSelectionCompetitorDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forCompetitors(dataProvider, i18n.favoriteCompetitors());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, i18n.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<SimpleCompetitorWithIdDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
|
||||
private class BoatClassDisplayImpl implements SuggestedMultiSelectionBoatClassDataProvider.Display {
|
||||
private final SuggestedMultiSelection<BoatClassDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutUpcomingRacesUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private BoatClassDisplayImpl(final SuggestedMultiSelectionBoatClassDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forBoatClasses(dataProvider, i18n.favoriteBoatClasses());
|
||||
notifyAboutUpcomingRacesUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutUpcomingRaces(enabled);
|
||||
}
|
||||
}, i18n.notificationAboutUpcomingRaces());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, i18n.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<BoatClassDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutUpcomingRaces(boolean notifyAboutUpcomingRaces) {
|
||||
notifyAboutUpcomingRacesUi.setEnabled(notifyAboutUpcomingRaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
|
||||
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator"
|
||||
xmlns:ms="urn:import:com.sap.sailing.gwt.home.shared.partials.multiselection">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style>
|
||||
.edgeToEdge {
|
||||
border-radius: 0;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
</ui:style>
|
||||
<g:HTMLPanel addStyleNames="{res.mediaCss.grid} {res.mainCss.spacermarginbottommediumsmall}">
|
||||
<div ui:field="notificationsTextUi" class="{res.mediaCss.column} {res.mediaCss.small12} {res.mainCss.spacermargintopsmall} {res.mainCss.spacermarginbottomsmall}">
|
||||
<ui:text from="{i18n.userNotificationsOnlyIfMailAddressIsVerified}" />
|
||||
</div>
|
||||
<div class="{res.mediaCss.small12} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection addStyleNames="{style.edgeToEdge}" ui:field="favoriteCompetitorsSelctionUi"/>
|
||||
</div>
|
||||
<div class="{res.mediaCss.small12} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection addStyleNames="{style.edgeToEdge}" ui:field="favoriteBoatClassesSelctionUi"/>
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.user.profile.preferences;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.DivElement;
|
||||
import com.google.gwt.resources.client.CssResource;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.HasEnabled;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.domain.common.dto.BoatClassDTO;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelection.NotificationCallback;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
|
||||
/**
|
||||
* Implementation of {@link UserPreferencesView} where users can change their preferred selections and notifications.
|
||||
*/
|
||||
public class UserPreferences extends Composite implements UserPreferencesView {
|
||||
|
||||
private static UserPreferencesUiBinder uiBinder = GWT.create(UserPreferencesUiBinder.class);
|
||||
|
||||
interface UserPreferencesUiBinder extends UiBinder<Widget, UserPreferences> {
|
||||
}
|
||||
|
||||
interface Style extends CssResource {
|
||||
String edgeToEdge();
|
||||
}
|
||||
|
||||
@UiField Style style;
|
||||
@UiField SharedResources res;
|
||||
@UiField(provided = true) SuggestedMultiSelection<SimpleCompetitorWithIdDTO> favoriteCompetitorsSelctionUi;
|
||||
@UiField(provided = true) SuggestedMultiSelection<BoatClassDTO> favoriteBoatClassesSelctionUi;
|
||||
@UiField DivElement notificationsTextUi;
|
||||
|
||||
public UserPreferences(UserPreferencesView.Presenter presenter) {
|
||||
favoriteCompetitorsSelctionUi = new CompetitorDisplayImpl(
|
||||
presenter.getFavoriteCompetitorsDataProvider()).selectionUi;
|
||||
favoriteBoatClassesSelctionUi = new BoatClassDisplayImpl(
|
||||
presenter.getFavoriteBoatClassesDataProvider()).selectionUi;
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
// TODO hide notificationsTextUi if the user's mail address is already verified
|
||||
}
|
||||
|
||||
public void setEdgeToEdge(boolean edgeToEdge) {
|
||||
favoriteBoatClassesSelctionUi.setStyleName(style.edgeToEdge(), edgeToEdge);
|
||||
favoriteCompetitorsSelctionUi.setStyleName(style.edgeToEdge(), edgeToEdge);
|
||||
favoriteBoatClassesSelctionUi.getElement().getParentElement().removeClassName(res.mediaCss().column());
|
||||
favoriteCompetitorsSelctionUi.getElement().getParentElement().removeClassName(res.mediaCss().column());
|
||||
}
|
||||
|
||||
private class CompetitorDisplayImpl implements SuggestedMultiSelectionCompetitorDataProvider.Display {
|
||||
private final SuggestedMultiSelection<SimpleCompetitorWithIdDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private CompetitorDisplayImpl(final SuggestedMultiSelectionCompetitorDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forCompetitors(dataProvider, StringMessages.INSTANCE.favoriteCompetitors());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<SimpleCompetitorWithIdDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
|
||||
private class BoatClassDisplayImpl implements SuggestedMultiSelectionBoatClassDataProvider.Display {
|
||||
private final SuggestedMultiSelection<BoatClassDTO> selectionUi;
|
||||
private final HasEnabled notifyAboutUpcomingRacesUi;
|
||||
private final HasEnabled notifyAboutResultsUi;
|
||||
|
||||
private BoatClassDisplayImpl(final SuggestedMultiSelectionBoatClassDataProvider dataProvider) {
|
||||
selectionUi = SuggestedMultiSelection.forBoatClasses(dataProvider, StringMessages.INSTANCE.favoriteBoatClasses());
|
||||
notifyAboutUpcomingRacesUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutUpcomingRaces(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutUpcomingRaces());
|
||||
notifyAboutResultsUi = selectionUi.addNotificationToggle(new NotificationCallback() {
|
||||
@Override
|
||||
public void onNotificationToggled(boolean enabled) {
|
||||
dataProvider.setNotifyAboutResults(enabled);
|
||||
}
|
||||
}, StringMessages.INSTANCE.notificationAboutNewResults());
|
||||
dataProvider.addDisplay(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectedItems(Collection<BoatClassDTO> selectedItems) {
|
||||
selectionUi.setSelectedItems(selectedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutUpcomingRaces(boolean notifyAboutUpcomingRaces) {
|
||||
notifyAboutUpcomingRacesUi.setEnabled(notifyAboutUpcomingRaces);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotifyAboutResults(boolean notifyAboutResults) {
|
||||
notifyAboutResultsUi.setEnabled(notifyAboutResults);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
|
||||
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator"
|
||||
xmlns:ms="urn:import:com.sap.sailing.gwt.home.shared.partials.multiselection">
|
||||
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
|
||||
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
|
||||
<ui:style type="com.sap.sailing.gwt.home.shared.places.user.profile.preferences.UserPreferences.Style">
|
||||
.edgeToEdge {
|
||||
border-radius: 0;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
</ui:style>
|
||||
<g:HTMLPanel addStyleNames="{res.mediaCss.grid} {res.mainCss.spacermarginbottommediumsmall}">
|
||||
<div ui:field="notificationsTextUi" class="{res.mediaCss.column} {res.mediaCss.medium12} {res.mainCss.spacermargintopsmall} {res.mainCss.spacermarginbottomsmall}">
|
||||
<ui:text from="{i18n.userNotificationsOnlyIfMailAddressIsVerified}" />
|
||||
</div>
|
||||
<div class="{res.mediaCss.column} {res.mediaCss.small12} {res.mediaCss.medium6} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection ui:field="favoriteCompetitorsSelctionUi"/>
|
||||
</div>
|
||||
<div class="{res.mediaCss.column} {res.mediaCss.small12} {res.mediaCss.medium6} {res.mainCss.spacermargintopmediumsmall}">
|
||||
<ms:SuggestedMultiSelection ui:field="favoriteBoatClassesSelctionUi"/>
|
||||
</div>
|
||||
</g:HTMLPanel>
|
||||
</ui:UiBinder>
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.user.profile.preferences;
|
||||
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.sap.sailing.gwt.home.communication.event.SimpleCompetitorWithIdDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.CompetitorSuggestionResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteBoatClassesDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoriteCompetitorsDTO;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.FavoritesResult;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetCompetitorSuggestionAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.GetFavoritesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteBoatClassesAction;
|
||||
import com.sap.sailing.gwt.home.communication.user.profile.SaveFavoriteCompetitorsAction;
|
||||
import com.sap.sailing.gwt.home.shared.app.ClientFactoryWithDispatch;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.AbstractSuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.ui.client.refresh.ErrorAndBusyClientFactory;
|
||||
import com.sap.sse.gwt.dispatch.shared.commands.VoidResult;
|
||||
|
||||
/**
|
||||
* Reusable implementation of {@link UserPreferencesView.Presenter} which handles the selections and notification
|
||||
* toggles of a {@link UserPreferencesView}. It only require an appropriate client factory which implements
|
||||
* {@link ClientFactoryWithDispatch} and {@link ErrorAndBusyClientFactory}.
|
||||
*
|
||||
* @param <C>
|
||||
* the provided client factory type
|
||||
*/
|
||||
public class UserPreferencesPresenter<C extends ClientFactoryWithDispatch & ErrorAndBusyClientFactory>
|
||||
implements UserPreferencesView.Presenter {
|
||||
|
||||
private final SuggestedMultiSelectionCompetitorDataProvider competitorDataProvider =
|
||||
new SuggestedMultiSelectionCompetitorDataProviderImpl();
|
||||
private final SuggestedMultiSelectionBoatClassDataProvider boatClassDataProvider =
|
||||
new SuggestedMultiSelectionBoatClassDataProviderImpl();
|
||||
private final C clientFactory;
|
||||
|
||||
public UserPreferencesPresenter(C clientFactory) {
|
||||
this.clientFactory = clientFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadPreferences() {
|
||||
clientFactory.getDispatch().execute(new GetFavoritesAction(), new AsyncCallback<FavoritesResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
clientFactory.createErrorView("Error while loading notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(FavoritesResult result) {
|
||||
initFavoriteCompetitors(result.getFavoriteCompetitors());
|
||||
initFavoriteBoatClasses(result.getFavoriteBoatClasses());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider() {
|
||||
return competitorDataProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider() {
|
||||
return boatClassDataProvider;
|
||||
}
|
||||
|
||||
private void initFavoriteCompetitors(FavoriteCompetitorsDTO favoriteCompetitors) {
|
||||
competitorDataProvider.initNotifications(favoriteCompetitors.isNotifyAboutResults());
|
||||
competitorDataProvider.initSelectedItems(favoriteCompetitors.getSelectedCompetitors());
|
||||
}
|
||||
|
||||
private void initFavoriteBoatClasses(FavoriteBoatClassesDTO favoriteBoatClasses) {
|
||||
boatClassDataProvider.initNotifications(favoriteBoatClasses.isNotifyAboutUpcomingRaces(),
|
||||
favoriteBoatClasses.isNotifyAboutResults());
|
||||
boatClassDataProvider.initSelectedItems(favoriteBoatClasses.getSelectedBoatClasses());
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionBoatClassDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionBoatClassDataProvider {
|
||||
@Override
|
||||
protected void persist(FavoriteBoatClassesDTO favorites) {
|
||||
clientFactory.getDispatch().execute(new SaveFavoriteBoatClassesAction(favorites), new SaveAsyncCallback());
|
||||
}
|
||||
}
|
||||
|
||||
private class SuggestedMultiSelectionCompetitorDataProviderImpl
|
||||
extends AbstractSuggestedMultiSelectionCompetitorDataProvider {
|
||||
|
||||
@Override
|
||||
protected void getSuggestions(Iterable<String> queryTokens, int limit,
|
||||
final SuggestionItemsCallback<SimpleCompetitorWithIdDTO> callback) {
|
||||
clientFactory.getDispatch().execute(new GetCompetitorSuggestionAction(queryTokens, limit),
|
||||
new AsyncCallback<CompetitorSuggestionResult>() {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
Window.alert("Error while loading competitor suggestion");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(CompetitorSuggestionResult result) {
|
||||
callback.setSuggestionItems(result.getValues());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void persist(FavoriteCompetitorsDTO favorites) {
|
||||
clientFactory.getDispatch().execute(new SaveFavoriteCompetitorsAction(favorites), new SaveAsyncCallback());
|
||||
}
|
||||
}
|
||||
|
||||
private class SaveAsyncCallback implements AsyncCallback<VoidResult> {
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
clientFactory.createErrorView("Error while saving notification preferences!", caught);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(VoidResult result) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.user.profile.preferences;
|
||||
|
||||
import com.google.gwt.user.client.ui.IsWidget;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionBoatClassDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionCompetitorDataProvider;
|
||||
import com.sap.sailing.gwt.home.shared.partials.multiselection.SuggestedMultiSelectionDataProvider;
|
||||
|
||||
/**
|
||||
* Interface for the user preferences UI. To support desktop as well as mobile version, an
|
||||
* {@link #setEdgeToEdge(boolean) edge-to-edge} flag can be provided, in order to meet the respective layout
|
||||
* requirements.
|
||||
*/
|
||||
public interface UserPreferencesView extends IsWidget {
|
||||
|
||||
/**
|
||||
* Defines whether or not the {@link UserPreferencesView} should be optimized to fill the whole display width.
|
||||
*
|
||||
* @param edgeToEdge
|
||||
* <code>true</code> if this view is used in an edge-to-edge layout (usually in mobile version),
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public void setEdgeToEdge(boolean edgeToEdge);
|
||||
|
||||
/**
|
||||
* Presenter interface for the user preferences UI, providing methods to load preferences and to access the
|
||||
* required {@link SuggestedMultiSelectionDataProvider}s.
|
||||
*/
|
||||
public interface Presenter {
|
||||
void loadPreferences();
|
||||
SuggestedMultiSelectionBoatClassDataProvider getFavoriteBoatClassesDataProvider();
|
||||
SuggestedMultiSelectionCompetitorDataProvider getFavoriteCompetitorsDataProvider();
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -4,9 +4,16 @@ import com.sap.sailing.domain.base.Competitor;
|
||||
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
|
||||
import com.sap.sailing.domain.tracking.DynamicSensorFixTrack;
|
||||
import com.sap.sailing.domain.tracking.DynamicTrackedRace;
|
||||
import com.sap.sailing.domain.tracking.GPSFixTrack;
|
||||
import com.sap.sailing.server.RacingEventService;
|
||||
import com.sap.sailing.server.RacingEventServiceOperation;
|
||||
|
||||
/**
|
||||
* This replicates a whole {@link DynamicSensorFixTrack}. Other tracks like {@link GPSFixTrack} are created on the
|
||||
* replica on the fly when the first fix is replicated. For sensor tracks there could be several different
|
||||
* {@link DynamicSensorFixTrack} implementations for different named tracks. This makes it necessary to serialize the
|
||||
* whole track to the replica to ensure that the track provides the correct functionality.
|
||||
*/
|
||||
public class RecordCompetitorSensorFixTrack extends AbstractRaceOperation<Void> {
|
||||
private static final long serialVersionUID = -7092704633177037511L;
|
||||
private DynamicSensorFixTrack<Competitor, ?> track;
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ If you are working with a linux-system and you get the error message `error whil
|
||||
|
||||
#### Using Android Studio for Development
|
||||
|
||||
The Android Apps can be build in Android Studio or gradle command line. Android Studio is build on top of IntelliJ IDEA, so it is possible to use IntelliJ IDEA as well.
|
||||
The Android Apps can be built in Android Studio or gradle command line. Android Studio is built on top of IntelliJ IDEA, so it is possible to use IntelliJ IDEA as well.
|
||||
|
||||
1. On the "Welcome Screen" choose "Import Project (Eclipse, ADT, Gradle, etc.)"
|
||||
2. Navigate to the project root folder and select the "build.gradle" file (all used modules are defined in "settings.gradle")
|
||||
|
||||
Reference in new issue
Block a user