Merge branch 'master' into bug5239

This commit is contained in:
Dennis Aulenbacher
2020-09-18 12:12:38 +02:00
229 changed files with 4207 additions and 3742 deletions
@@ -1,7 +1,6 @@
package com.sap.sailing.domain.persistence.racelog.tracking.impl;
import static com.sap.sailing.shared.persistence.impl.MongoObjectFactoryImpl.storeDeviceId;
import static com.sap.sailing.domain.persistence.impl.MongoObjectFactoryImpl.storeTimeRange;
import java.util.ArrayList;
import java.util.Collections;
@@ -43,6 +42,7 @@ import com.sap.sse.common.Timed;
import com.sap.sse.common.TypeBasedServiceFinder;
import com.sap.sse.common.TypeBasedServiceFinderFactory;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.TimeRangeImpl;
import com.sap.sse.concurrent.LockUtil;
import com.sap.sse.concurrent.NamedReentrantReadWriteLock;
@@ -185,11 +185,15 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
/**
* Store fixes in batches, reducing metadata storage update.
*
* @return the identifiers of those races in which new maneuvers have been discovered since the last update for the
* competitor / boat to which the device is mapped and/or information about the race's live delay, if
* requested; always a valid, non-{@code null} but potentially empty collection.
*/
@Override
public <FixT extends Timed> Iterable<RegattaAndRaceIdentifier> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes) {
Set<RegattaAndRaceIdentifier> maneuverChanged = new HashSet<>();
public <FixT extends Timed> Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes, boolean returnManeuverChanges, boolean returnLiveDelay) {
final Set<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> racesWithManeuverChangesOrLiveDelay = new HashSet<>();
if (!Util.isEmpty(fixes)) {
try {
final Object dbDeviceId = storeDeviceId(deviceServiceFinder, device);
@@ -217,7 +221,7 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
if (latestFix != null) {
newMetadata.put(FieldNames.LAST_FIX_RECEIVED.name(), storeFixToDocument(new Document(), latestFix));
}
storeTimeRange(newTimeRange, newMetadata, FieldNames.TIMERANGE);
MongoObjectFactoryImpl.storeTimeRange(newTimeRange, newMetadata, FieldNames.TIMERANGE);
updateOperation.append("$set", newMetadata);
updateOperation.append("$inc", new Document(FieldNames.NUM_FIXES.name(), nrOfTotalFixes));
metadataCollection.withWriteConcern(WriteConcern.UNACKNOWLEDGED).updateOne(getDeviceQuery(device), updateOperation, new UpdateOptions().upsert(true));
@@ -225,9 +229,9 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
logger.log(Level.WARNING, "Could not store fix in MongoDB");
e.printStackTrace();
}
Util.addAll(notifyListeners(device, fixes), maneuverChanged);
Util.addAll(notifyListeners(device, fixes, returnManeuverChanges, returnLiveDelay), racesWithManeuverChangesOrLiveDelay);
}
return maneuverChanged;
return racesWithManeuverChangesOrLiveDelay;
}
/**
@@ -246,12 +250,12 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
@Override
public <FixT extends Timed> void storeFix(DeviceIdentifier device, FixT fix) {
storeFixes(device, Collections.singletonList(fix));
storeFixes(device, Collections.singletonList(fix), /* returnManeuverUpdate */ false, /* returnLiveDelay */ false);
}
private <FixT extends Timed> Iterable<RegattaAndRaceIdentifier> notifyListeners(DeviceIdentifier device,
Iterable<FixT> fixes) {
Set<RegattaAndRaceIdentifier> raceWithChangedManeuver = new HashSet<>();
private <FixT extends Timed> Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> notifyListeners(DeviceIdentifier device,
Iterable<FixT> fixes, boolean returnManeuverChanges, boolean returnLiveDelay) {
final Set<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> raceWithChangedManeuver = new HashSet<>();
@SuppressWarnings({ "unchecked", "rawtypes" })
final Map<DeviceIdentifier, Set<FixReceivedListener<FixT>>> listenersWithFixType = (Map) listeners;
final Set<FixReceivedListener<FixT>> listenersToInform = LockUtil.executeWithReadLockAndResult(listenersLock, () -> {
@@ -260,7 +264,7 @@ public class MongoSensorFixStoreImpl implements MongoSensorFixStore {
});
for (FixT fix : fixes) {
for (FixReceivedListener<FixT> listener : listenersToInform) {
final Iterable<RegattaAndRaceIdentifier> racesWithManeuverChangeFromListener = listener.fixReceived(device, fix);
final Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> racesWithManeuverChangeFromListener = listener.fixReceived(device, fix, returnManeuverChanges, returnLiveDelay);
Util.addAll(racesWithManeuverChangeFromListener, raceWithChangedManeuver);
}
}
@@ -47,7 +47,7 @@ public class DeviceMappingsAndSensorFixStoreLockingTest extends AbstractGPSFixSt
} catch (Exception e) {
throw new RuntimeException(e);
}
store.addListener((device, fix) -> {
store.addListener((device, fix, returnManeuverChanges, returnLiveDelay) -> {
return null;
}, deviceIdentifier);
}
@@ -61,7 +61,7 @@ public class DeviceMappingsAndSensorFixStoreLockingTest extends AbstractGPSFixSt
Map<RegattaLogDeviceMappingEvent<WithID>, MultiTimeRange> newlyCoveredTimeRanges) {
}
};
store.addListener((dev, fix)-> {
store.addListener((dev, fix, returnManeuverChanges, returnLiveDelay)-> {
try {
barrier.await();
} catch (Exception e) {
@@ -15,6 +15,8 @@ import com.sap.sailing.domain.common.tracking.GPSFixMoving;
import com.sap.sailing.domain.persistence.racelog.tracking.impl.MongoSensorFixStoreImpl;
import com.sap.sailing.domain.racelog.tracking.FixReceivedListener;
import com.sap.sailing.domain.racelogtracking.test.AbstractGPSFixStoreTest;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util.Triple;
public class GPSFixStoreListenerTest extends AbstractGPSFixStoreTest {
@Rule
@@ -43,7 +45,7 @@ public class GPSFixStoreListenerTest extends AbstractGPSFixStoreTest {
barrier.await(100, TimeUnit.MILLISECONDS);
// During iteration in the main thread this causes a modification that makes the iterator throw a
// ConcurrentModificationException on next()
store.addListener((DeviceIdentifier device, GPSFixMoving fix) -> {
store.addListener((DeviceIdentifier device, GPSFixMoving fix, boolean returnManeuverChanges, boolean returnLiveDelay) -> {
return null;
}, device);
barrier.await(100, TimeUnit.MILLISECONDS);
@@ -72,7 +74,7 @@ public class GPSFixStoreListenerTest extends AbstractGPSFixStoreTest {
}
@Override
public Iterable<RegattaAndRaceIdentifier> fixReceived(DeviceIdentifier device, GPSFixMoving fix) {
public Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> fixReceived(DeviceIdentifier device, GPSFixMoving fix, boolean returnManeuverChanges, boolean returnLiveDelay) {
try {
barrier.await(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
@@ -197,7 +197,7 @@ public class SensorFixStoreTest {
store.addListener(listener, device);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
}
@Test
@@ -208,8 +208,8 @@ public class SensorFixStoreTest {
store.addListener(listener2, device);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
}
@Test
@@ -229,7 +229,7 @@ public class SensorFixStoreTest {
store.addListener(listener2, device2);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener1, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyZeroInteractions(listener2);
}
@@ -240,8 +240,8 @@ public class SensorFixStoreTest {
DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
DoubleVectorFix doubleVectorFix2 = addBravoFix(device, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix2, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyNoMoreInteractions(listener);
}
@@ -269,7 +269,7 @@ public class SensorFixStoreTest {
store.addListener(listener, device);
store.removeListener(listener, device2);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
}
@Test
@@ -279,8 +279,8 @@ public class SensorFixStoreTest {
store.addListener(listener, device2);
DoubleVectorFix doubleVectorFix1 = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device, doubleVectorFix1, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyNoMoreInteractions(listener);
}
@@ -303,7 +303,7 @@ public class SensorFixStoreTest {
store.removeListener(listener, device);
addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
DoubleVectorFix doubleVectorFix2 = addBravoFix(device2, FIX_TIMESTAMP2, FIX_RIDE_HEIGHT2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2);
Mockito.verify(listener, Mockito.times(1)).fixReceived(device2, doubleVectorFix2, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyNoMoreInteractions(listener);
}
@@ -315,7 +315,7 @@ public class SensorFixStoreTest {
store.addListener(listener2, device);
store.removeListener(listener1);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyNoMoreInteractions(listener2);
Mockito.verifyZeroInteractions(listener1);
}
@@ -328,7 +328,7 @@ public class SensorFixStoreTest {
store.addListener(listener2, device);
store.removeListener(listener1, device);
DoubleVectorFix doubleVectorFix = addBravoFix(device, FIX_TIMESTAMP, FIX_RIDE_HEIGHT);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix);
Mockito.verify(listener2, Mockito.times(1)).fixReceived(device, doubleVectorFix, /* returnManeuverChanges */ false, /* returnLiveDelay */ false);
Mockito.verifyNoMoreInteractions(listener2);
Mockito.verifyZeroInteractions(listener1);
}
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.racelogtracking.impl.fixtracker;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -56,13 +57,17 @@ import com.sap.sailing.domain.tracking.TrackingDataLoader;
import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener;
import com.sap.sailing.domain.tracking.impl.TimedComparator;
import com.sap.sailing.domain.tracking.impl.TrackedRaceStatusImpl;
import com.sap.sse.common.Duration;
import com.sap.sse.common.MultiTimeRange;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.WithID;
import com.sap.sse.common.impl.MillisecondsDurationImpl;
import com.sap.sse.common.impl.TimeRangeImpl;
import com.sap.sse.util.ThreadPoolUtil;
@@ -189,8 +194,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
};
private final FixReceivedListener<Timed> listener = new FixReceivedListener<Timed>() {
@Override
public Iterable<RegattaAndRaceIdentifier> fixReceived(DeviceIdentifier device, Timed fix) {
Set<RegattaAndRaceIdentifier> maneuverChanged = new HashSet<>();
public Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> fixReceived(DeviceIdentifier device, Timed fix, boolean returnManeuverChanges, boolean returnLiveDelay) {
final Set<RegattaAndRaceIdentifier> maneuverChanged = new HashSet<>();
final Map<RegattaAndRaceIdentifier, Duration> delayToLive = new HashMap<>();
if (!preemptiveStopRequested.get() && trackedRace.getStartOfTracking() != null) {
final TimePoint timePoint = fix.getTimePoint();
deviceMappings.forEachMappingOfDeviceIncludingTimePoint(device, fix.getTimePoint(),
@@ -224,6 +230,9 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
DynamicSensorFixTrack<Competitor, SensorFix> track = mapper.getTrack(trackedRace, competitor);
if (track != null && trackedRace.isWithinStartAndEndOfTracking(fix.getTimePoint())) {
mapper.addFix(track, (DoubleVectorFix) fix);
if (returnLiveDelay) {
delayToLive.put(trackedRace.getRaceIdentifier(), new MillisecondsDurationImpl(trackedRace.getDelayToLiveInMillis()));
}
}
}
}
@@ -254,9 +263,14 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
// by the race or the track, e.g., because the race's end-of-tracking
// comes before the fix's time point
if (trackedRace.recordFix(comp, (GPSFixMoving) fix)) {
RegattaAndRaceIdentifier maneuverChangedAnswer = detectIfManeuverChanged(comp);
if (maneuverChangedAnswer != null) {
maneuverChanged.add(maneuverChangedAnswer);
if (returnManeuverChanges) {
RegattaAndRaceIdentifier maneuverChangedAnswer = detectIfManeuverChanged(comp);
if (maneuverChangedAnswer != null) {
maneuverChanged.add(maneuverChangedAnswer);
}
}
if (returnLiveDelay) {
delayToLive.put(trackedRace.getRaceIdentifier(), new MillisecondsDurationImpl(trackedRace.getDelayToLiveInMillis()));
}
}
} else {
@@ -328,18 +342,34 @@ public class FixLoaderAndTracker implements TrackingDataLoader {
}
}
trackedRace.recordFix(mark, (GPSFix) fix, /* only when in tracking interval */ !forceFix);
if (returnLiveDelay) {
delayToLive.put(trackedRace.getRaceIdentifier(), new MillisecondsDurationImpl(trackedRace.getDelayToLiveInMillis()));
}
}
}
});
}
});
}
return maneuverChanged;
return mergeManeuverChangedAndLiveDelayResult(maneuverChanged, delayToLive);
}
private Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> mergeManeuverChangedAndLiveDelayResult(
Set<RegattaAndRaceIdentifier> maneuverChanged, Map<RegattaAndRaceIdentifier, Duration> delayToLive) {
final Map<RegattaAndRaceIdentifier, Pair<Boolean, Duration>> preResult = new HashMap<>();
for (final Entry<RegattaAndRaceIdentifier, Duration> e : delayToLive.entrySet()) {
preResult.put(e.getKey(), new Pair<>(maneuverChanged.contains(e.getKey()), e.getValue()));
}
for (final RegattaAndRaceIdentifier maneuverChanges : maneuverChanged) {
if (!preResult.containsKey(maneuverChanges)) {
preResult.put(maneuverChanges, new Pair<>(true, null));
}
}
return Util.map(preResult.entrySet(), e->new Triple<>(e.getKey(), e.getValue().getA(), e.getValue().getB()));
}
};
/**
*
* @param comp
* The resolved competitor for wich a gpsfix was just recorded.
* @return Will return null or an RegattaAndRaceIdentifier, if the last maneuver for the given competitor changed
@@ -13,7 +13,7 @@ public interface RaceStateChangedListener {
* TODO: We need to recheck the AbortFinder to enable these interface methods
* void onAborted(RaceState2 state);
* void onGeneralRecall(RaceState2 state);*/
void onFinishingPositioningsChanged(ReadonlyRaceState state);
void onFinishingPositionsChanged(ReadonlyRaceState state);
void onFinishingPositionsConfirmed(ReadonlyRaceState state);
void onCourseDesignChanged(ReadonlyRaceState state);
void onWindFixChanged(ReadonlyRaceState state);
@@ -44,7 +44,7 @@ public abstract class BaseRaceStateChangedListener implements RaceStateChangedLi
}
@Override
public void onFinishingPositioningsChanged(ReadonlyRaceState state) {
public void onFinishingPositionsChanged(ReadonlyRaceState state) {
}
@@ -85,9 +85,9 @@ public class RaceStateChangedListeners extends HashSet<RaceStateChangedListener>
}
@Override
public void onFinishingPositioningsChanged(ReadonlyRaceState state) {
public void onFinishingPositionsChanged(ReadonlyRaceState state) {
for (RaceStateChangedListener listener : getWorkingCopyOfListeners()) {
listener.onFinishingPositioningsChanged(state);
listener.onFinishingPositionsChanged(state);
}
}
@@ -557,7 +557,7 @@ public class ReadonlyRaceStateImpl implements ReadonlyRaceState, RaceLogChangedL
CompetitorResults positionedCompetitors = finishPositioningListAnalyzer.analyze().getCompetitorResults();
if (!Util.equalsWithNull(cachedPositionedCompetitors, positionedCompetitors)) {
cachedPositionedCompetitors = positionedCompetitors;
changedListeners.onFinishingPositioningsChanged(this);
changedListeners.onFinishingPositionsChanged(this);
}
CompetitorResultsAndTheirCreationTimePoints confirmedPositionedCompetitors = confirmedFinishPositioningListAnalyzer.analyze();
if (!Util.equalsWithNull(cachedConfirmedPositionedCompetitors, confirmedPositionedCompetitors)) {
@@ -6,9 +6,8 @@ import com.sap.sse.common.NamedWithID;
import com.sap.sse.common.Renamable;
import com.sap.sse.security.shared.WithQualifiedObjectIdentifier;
public interface LeaderboardGroupBase extends Renamable, NamedWithID, WithQualifiedObjectIdentifier {
public interface LeaderboardGroupBase extends Renamable, NamedWithID, WithQualifiedObjectIdentifier, WithDescription {
UUID getId();
String getDescription();
void setDescriptiom(String description);
boolean hasOverallLeaderboard();
String getDisplayName();
@@ -8,10 +8,12 @@ import java.util.function.Consumer;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util.Triple;
public enum EmptySensorFixStore implements SensorFixStore {
INSTANCE;
@@ -56,8 +58,8 @@ public enum EmptySensorFixStore implements SensorFixStore {
}
@Override
public <FixT extends Timed> Iterable<RegattaAndRaceIdentifier> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes) {
public <FixT extends Timed> Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes, boolean returnManeuverUpdate, boolean returnLiveDelay) {
return Collections.emptySet();
}
@@ -2,7 +2,9 @@ package com.sap.sailing.domain.racelog.tracking;
import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util.Triple;
/**
* Listener to be informed about new fixes by {@link SensorFixStore}.
@@ -17,10 +19,21 @@ public interface FixReceivedListener<FixT extends Timed> {
* the device that recorded the fix. Cannot be <code>null</code>.
* @param fix
* The fix that was stored. Cannot be <code>null</code>.
* @param returnManeuverUpdate
* if {@code true}, all listeners to which this fix is forwarded shall check whether the fix feeds into a
* competitor's track in the scope of a race where for that competitor the maneuver list has changed
* since the last call of this type; if so, the race identifier will be part of the result, with the
* {@link Boolean} component being {@code true} for that race. Otherwise, the {@link Boolean} component
* is {@code false} or the race is not listed in the result.
* @param returnLiveDelay
* if {@code true} then all listeners to which the fix is forwarded shall check to which races the fix
* maps and report the live delay for all those races as the third component of the resulting
* {@link Triple}s.
* @return An {@link Iterable} with {@link RegattaAndRaceIdentifier}s is returned that will contain races with new
* maneuvers which were not available at the last time the given device stored a fix. The {@link Iterable}
* returned can be empty but is never {@code null}. It can also contain multiple identifiers if the device
* mapping is currently ambiguous.
*/
Iterable<RegattaAndRaceIdentifier> fixReceived(DeviceIdentifier device, FixT fix);
Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> fixReceived(DeviceIdentifier device, FixT fix,
boolean returnManeuverChanges, boolean returnLiveDelay);
}
@@ -8,10 +8,12 @@ import com.sap.sailing.domain.common.DeviceIdentifier;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.racelog.tracking.TransformationException;
import com.sap.sailing.domain.common.tracking.GPSFix;
import com.sap.sse.common.Duration;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util.Triple;
/**
@@ -71,14 +73,27 @@ public interface SensorFixStore {
*
* @param device
* the device to store the fix for. Must not be <code>null</code>.
* @param returnManeuverUpdate
* if {@code true}, all listeners to which this fix is forwarded shall check whether the fix feeds into a
* competitor's track in the scope of a race where for that competitor the maneuver list has changed
* since the last call of this type; if so, the race identifier will be part of the result, with the
* {@link Boolean} component being {@code true} for that race. Otherwise, the {@link Boolean} component
* is {@code false} or the race is not listed in the result.
* @param returnLiveDelay
* if {@code true} then all listeners to which the fix is forwarded shall check to which races the fix
* maps and report the live delay for all those races as the third component of the resulting
* {@link Triple}s.
* @param fix
* The fix to store. Must not be <code>null</code>.
* @return An {@link Iterable} with {@link RegattaAndRaceIdentifier}s is returned that will contain races with new
* maneuvers which were not available at the last time the given device stored a fix. The {@link Iterable}
* returned can be empty but is never {@code null}. It can also contain multiple identifiers if the device
* mapping is currently ambiguous.
* @return An {@link Iterable} with {@link RegattaAndRaceIdentifier}s in their first component is returned that will
* contain races with new maneuvers which were not available at the last time the given device stored a fix
* in case the {@code returnManeuverUpdate} parameter was set to {@code true}, and all races with their live
* delays to which the fix was mapped in case {@code returnLiveDelay} was set to {@code true}. The
* {@link Iterable} returned can be empty but is never {@code null}. It can also contain multiple
* identifiers if the device mapping is currently ambiguous.
*/
<FixT extends Timed> Iterable<RegattaAndRaceIdentifier> storeFixes(DeviceIdentifier device, Iterable<FixT> fixes);
<FixT extends Timed> Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> storeFixes(
DeviceIdentifier device, Iterable<FixT> fixes, boolean returnManeuverUpdate, boolean returnLiveDelay);
/**
* Listeners are notified, whenever a {@link GPSFix} submitted by the {@code device}
@@ -64,11 +64,13 @@ import com.sap.sailing.expeditionconnector.UDPExpeditionReceiver;
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifier;
import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdentifierImpl;
import com.sap.sailing.expeditionconnector.persistence.ExpeditionSensorDeviceIdentifierImpl;
import com.sap.sse.common.Duration;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.TimeRange;
import com.sap.sse.common.Timed;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Triple;
import com.sap.sse.common.impl.MillisecondsTimePoint;
public class UDPExpeditionReceiverTest {
@@ -153,8 +155,8 @@ public class UDPExpeditionReceiverTest {
}
@Override
public <FixT extends Timed> Iterable<RegattaAndRaceIdentifier> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes) {
public <FixT extends Timed> Iterable<Triple<RegattaAndRaceIdentifier, Boolean, Duration>> storeFixes(DeviceIdentifier device,
Iterable<FixT> fixes, boolean returnManeuverUpdate, boolean returnLiveDelay) {
for (final FixT fix : fixes) {
storeFix(device, fix);
}
@@ -8,7 +8,11 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- -->
<!-- Consider inlining CSS to reduce the number of requested files -->
<!-- -->
@@ -9,6 +9,11 @@
<head>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- -->
<!-- Consider inlining CSS to reduce the number of requested files -->
@@ -7,6 +7,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
+7 -4
View File
@@ -3,7 +3,11 @@
<head>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" selenium-id="shortcutIcon"/>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" /> <link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" selenium-id="shortcutIcon"/>
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon' selenium-id="appIcon">
<title>${SAP}Sailing - Homepage</title>
@@ -14,8 +18,7 @@
href="/sailing-fontface-1.0.cache.css">
<script src="js/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" type="text/css" href="js/jquery.slick/slick-1.8.1.css"/>
<script type="text/javascript" src="js/jquery.slick/slick-1.8.1.min.js"></script>
<script type="text/javascript" src="js/jquery.slick/slick-1.8.1.min.js"></script>
<link href="js/video-js/video-js.min.css" rel="stylesheet">
<link href="js/video-js/video-js-sapsailing.css" rel="stylesheet">
<script src="js/video-js/video.min.js"></script>
@@ -24,7 +27,7 @@
<script src="js/Youtube.min.js"></script>
<script src="js/Vimeo.js"></script>
<script>
videojs.options.techOrder = ['vimeo', 'youtube', 'html5'];
videojs.options.techOrder = ['vimeo', 'youtube', 'html5'];
</script>
<script>
document.clientConfigurationContext = {
@@ -2,6 +2,11 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<title>${SAP}Sailing - Homepage</title>
@@ -2,6 +2,11 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<title>${SAP}Sailing - Homepage</title>
@@ -10,6 +10,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
@@ -8,6 +8,11 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
<!-- -->
@@ -10,6 +10,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
@@ -10,6 +10,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
@@ -8,7 +8,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
@@ -7,6 +7,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
@@ -12,6 +12,11 @@
<meta content='width = device-width, initial-scale = 1.0, user-scalable = yes' name='viewport'>
<meta content='yes' name='apple-mobile-web-app-capable'>
<meta content='black' name='apple-mobile-web-app-status-bar-style'>
<meta property="og:type" content="website" />
<meta property="og:title" content="SAP Sailing" />
<meta property="og:description" content="Help sailors analyze performance and optimize strategy &#8226; Bring fans closer to the action
&#8226; Provide the media with information and insights to deliver a greater informed commentary" />
<meta property="og:image" content="http://media.sapsailing.com/2014/505Worlds/Images_Homepage/505Worlds2014_eventteaser.jpg" />
<!-- <link href='iphone-splash-screen.png' rel='apple-touch-startup-image'> -->
<link href='sap-sailing-app-icon${whitelabeled}.png' rel='apple-touch-icon'>
<link rel="shortcut icon" type="image/x-icon" href="images/sap${whitelabeled}.ico" />
+44 -44
View File
@@ -13,9 +13,9 @@
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
<param-name>useFileMappedBuffer</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
<!-- Apache Shiro -->
@@ -60,29 +60,29 @@
<url-pattern>*.html</url-pattern>
</filter-mapping>
<servlet>
<display-name>ClientConfigurationServlet</display-name>
<servlet-name>ClientConfigurationServlet</servlet-name>
<servlet-class>com.sap.sse.debranding.ClientConfigurationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ClientConfigurationServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet>
<display-name>ClientConfigurationServlet</display-name>
<servlet-name>ClientConfigurationServlet</servlet-name>
<servlet-class>com.sap.sse.debranding.ClientConfigurationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ClientConfigurationServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet>
<display-name>Status</display-name>
<servlet-name>Status</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.StatusServlet</servlet-class>
<display-name>Status</display-name>
<servlet-name>Status</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.StatusServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Status</servlet-name>
<url-pattern>/status</url-pattern>
</servlet-mapping>
<servlet>
<display-name>Sailing Service</display-name>
<servlet-name>SailingService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceImpl</servlet-class>
<display-name>Sailing Service</display-name>
<servlet-name>SailingService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SailingService</servlet-name>
@@ -90,21 +90,21 @@
<url-pattern>/service/sailing/*</url-pattern>
</servlet-mapping>
<servlet>
<display-name>Sailing ServiceWrite</display-name>
<servlet-name>SailingServiceWrite</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceWriteImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SailingServiceWrite</servlet-name>
<url-pattern>/service/sailingmaster</url-pattern>
<url-pattern>/service/sailingmaster/*</url-pattern>
</servlet-mapping>
<servlet>
<display-name>Sailing ServiceWrite</display-name>
<servlet-name>SailingServiceWrite</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SailingServiceWriteImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SailingServiceWrite</servlet-name>
<url-pattern>/service/sailingmaster</url-pattern>
<url-pattern>/service/sailingmaster/*</url-pattern>
</servlet-mapping>
<servlet>
<display-name>Server Configuration Service</display-name>
<servlet-name>ServerConfigurationService</servlet-name>
<servlet-class>com.sap.sailing.gwt.server.ServerConfigurationServiceImpl</servlet-class>
<display-name>Server Configuration Service</display-name>
<servlet-name>ServerConfigurationService</servlet-name>
<servlet-class>com.sap.sailing.gwt.server.ServerConfigurationServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServerConfigurationService</servlet-name>
@@ -112,9 +112,9 @@
</servlet-mapping>
<servlet>
<display-name>Sailing Dispatch Service</display-name>
<servlet-name>sailingDispatch</servlet-name>
<servlet-class>com.sap.sailing.gwt.home.server.servlets.SailingDispatchServlet</servlet-class>
<display-name>Sailing Dispatch Service</display-name>
<servlet-name>sailingDispatch</servlet-name>
<servlet-class>com.sap.sailing.gwt.home.server.servlets.SailingDispatchServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sailingDispatch</servlet-name>
@@ -123,9 +123,9 @@
</servlet-mapping>
<servlet>
<display-name>Media Service</display-name>
<servlet-name>MediaService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.MediaServiceImpl</servlet-class>
<display-name>Media Service</display-name>
<servlet-name>MediaService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.MediaServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MediaService</servlet-name>
@@ -143,9 +143,9 @@
</servlet-mapping>
<servlet>
<display-name>Simulator Service</display-name>
<servlet-name>SimulatorService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SimulatorServiceImpl</servlet-class>
<display-name>Simulator Service</display-name>
<servlet-name>SimulatorService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.SimulatorServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimulatorService</servlet-name>
@@ -153,9 +153,9 @@
</servlet-mapping>
<servlet>
<display-name>Data Mining Service</display-name>
<servlet-name>DataMiningService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.DataMiningServiceImpl</servlet-class>
<display-name>Data Mining Service</display-name>
<servlet-name>DataMiningService</servlet-name>
<servlet-class>com.sap.sailing.gwt.ui.server.DataMiningServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DataMiningService</servlet-name>
+2 -1
View File
@@ -55,5 +55,6 @@ bin.includes = META-INF/,\
PairingList.css,\
PairingList.html,\
com.sap.sailing.gwt.ui.PairingList/,\
src/main/resources/com/sap/sailing/gwt/ui/client/images/boatclass/
src/main/resources/com/sap/sailing/gwt/ui/client/images/boatclass/,\
src/main/resources/com/sap/sailing/gwt/home/shared/
output.. = WEB-INF/classes/
@@ -14,7 +14,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.gwt.autoplay.client.app.AutoPlayClientFactory;
import com.sap.sailing.gwt.autoplay.client.app.AutoPlayPresenterConfigured;
import com.sap.sailing.gwt.common.client.DateUtil;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.gwt.client.media.ImageDTO;
@@ -2,7 +2,7 @@
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<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:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:with field="ares"
type="com.sap.sailing.gwt.home.desktop.partials.desktopaccordion.DesktopAccordionResources" />
@@ -16,8 +16,8 @@ import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO;
import com.sap.sailing.gwt.home.communication.event.LabelType;
import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO;
import com.sap.sailing.gwt.home.desktop.utils.LongNamesUtil;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -57,8 +57,7 @@ public class EventTeaser extends Composite {
placeNavigation.goToPlace();
}
}
});;
});
updateUI();
}
@@ -20,10 +20,11 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO;
import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata;
import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingButtons;
import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingMetadataProvider;
import com.sap.sailing.gwt.home.desktop.places.event.EventView;
import com.sap.sailing.gwt.home.desktop.places.event.EventView.PlaceCallback;
import com.sap.sailing.gwt.home.desktop.places.event.EventView.Presenter;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.home.shared.places.event.AbstractEventPlace;
import com.sap.sailing.gwt.home.shared.utils.DropdownHandler;
import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil;
@@ -83,12 +84,10 @@ public class EventHeader extends Composite {
String dateString = EventDatesFormatterUtil.formatDateRangeWithYear(event.getStartDate(), event.getEndDate());
return StringMessages.INSTANCE.eventSharingShortText(event.getDisplayName(), event.getLocationOrVenue(), dateString);
}
@Override
public String getLongText(String url) {
// TODO regatta details?
String dateString = EventDatesFormatterUtil.formatDateRangeWithYear(event.getStartDate(), event.getEndDate());
return StringMessages.INSTANCE.eventSharingLongText(event.getDisplayName(), event.getLocationOrVenue(), dateString, url);
public ShareablePlaceContext getContext() {
return presenter.getCtx();
}
});
}
@@ -163,7 +162,9 @@ public class EventHeader extends Composite {
hide(dropdownTitle);
} else {
dropdownEventName.setInnerText(nameToShow);
LabelTypeUtil.renderLabelType(dropdownEventState, presenter.showRegattaMetadata() ? presenter.getRegattaMetadata().getState().getStateMarker() : event.getState().getStateMarker());
LabelTypeUtil.renderLabelType(dropdownEventState,
presenter.showRegattaMetadata() ? presenter.getRegattaMetadata().getState().getStateMarker()
: event.getState().getStateMarker());
UIObject.ensureDebugId(dropdownEventState, "EventStateLabelDiv");
hide(staticTitle);
initDropdown();
@@ -3,7 +3,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.eventsrecent.EventsOverviewRecentResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:style>
.quickFix {
padding: 0px 10px;
@@ -3,7 +3,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.eventsupcoming.EventsOverviewUpcomingResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel addStyleNames="{local_res.css.eventsoverviewupcoming} {local_res.css.accordion}">
<!-- IFEND upcomingEvents.events.length > 1 ADD CLASS local_res.css.accordion ELSE ADD CLASS local_res.css.accordioncollapsed -->
<g:HTMLPanel ui:field="header" addStyleNames="{local_res.css.eventsoverviewupcoming_header} {local_res.css.accordion_trigger}">
@@ -12,10 +12,10 @@ import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.home.communication.event.EventLinkDTO;
import com.sap.sailing.gwt.home.communication.media.SailingImageDTO;
import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.fullscreen.FullscreenContainer;
import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sse.gwt.client.controls.carousel.ImageCarousel.FullscreenViewer;
/**
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.desktop.partials.multiregattalist;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface MultiRegattaListResources extends SharedHomeResources {
public static final MultiRegattaListResources INSTANCE = GWT.create(MultiRegattaListResources.class);
@@ -7,8 +7,8 @@ import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.partials.fullscreen.FullscreenContainer;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sse.common.Color;
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator;
import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicatorResources;
@@ -12,7 +12,7 @@ import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.sap.sailing.gwt.home.communication.race.RaceMetadataDTO;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.common.Util;
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.desktop.partials.regattacompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface RegattaCompetitionResources extends SharedHomeResources {
public static final RegattaCompetitionResources INSTANCE = GWT.create(RegattaCompetitionResources.class);
@@ -15,12 +15,13 @@ import com.sap.sailing.gwt.home.communication.event.EventAndLeaderboardReference
import com.sap.sailing.gwt.home.communication.event.EventState;
import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO;
import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingButtons;
import com.sap.sailing.gwt.home.desktop.partials.sharing.SharingMetadataProvider;
import com.sap.sailing.gwt.home.desktop.places.event.regatta.overviewtab.RegattaOverviewPlace;
import com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesView;
import com.sap.sailing.gwt.home.desktop.places.fakeseries.SeriesView.Presenter;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
@@ -46,10 +47,8 @@ public class SeriesHeader extends Composite {
public SeriesHeader(SeriesView.Presenter presenter) {
this.series = presenter.getSeriesDTO();
this.presenter = presenter;
SeriesHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
initFields();
initSharing();
}
@@ -60,11 +59,11 @@ public class SeriesHeader extends Composite {
public String getShortText() {
return StringMessages.INSTANCE.seriesSharingShortText(series.getDisplayName());
}
@Override
public String getLongText(String url) {
return StringMessages.INSTANCE.seriesSharingLongText(series.getDisplayName(), url);
public ShareablePlaceContext getContext() {
return presenter.getCtx();
}
});
}
@@ -1,6 +1,8 @@
.eventheader_sharing {
text-align: right;
padding: 1.333333333333333em 0;
padding: 1.333333333333333em 0 !important;
display: inline-block;
float: right;
}
.eventheader_sharing_item {
display: inline-block;
@@ -48,3 +50,29 @@
.eventheader_sharing_itemfacebook:focus {
background-color: #355089;
}
.eventheader_sharing_itemcopytoclipboard {
float: right;
position: relative;
margin-left: 0.5em;
font-size: 1rem;
background-color: #737373 ;
}
.eventheader_sharing_itemcopytoclipboard:after {
content: "";
position: absolute;
width: 55%;
height: 55%;
top: 22.5%;
left: 22.5%;
background-image: resourceUrl("copyIcon");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
border: none;
}
.eventheader_sharing_itemcopytoclipboard:hover,
.eventheader_sharing_itemcopytoclipboard:focus {
background-color: #808080;
}
@@ -4,18 +4,28 @@ import static com.google.gwt.dom.client.Style.Display.NONE;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.shared.ClientConfiguration;
public class SharingButtons extends Composite {
private static SharingButtonsUiBinder uiBinder = GWT.create(SharingButtonsUiBinder.class);
private static String SHARING_URL_PREFIX = "/sailingserver/shared/home";
interface SharingButtonsUiBinder extends UiBinder<Widget, SharingButtons> {
}
@@ -24,6 +34,7 @@ public class SharingButtons extends Composite {
@UiField AnchorElement mail;
@UiField AnchorElement twitter;
@UiField AnchorElement facebook;
@UiField Button copyToClipBoard;
public SharingButtons() {
SharingButtonsResources.INSTANCE.css().ensureInjected();
@@ -37,17 +48,47 @@ public class SharingButtons extends Composite {
if (!ClientConfiguration.getInstance().isBrandingActive()) {
return;
}
String shortText = provider.getShortText();
String longText = provider.getLongText(Window.Location.getHref());
UrlBuilder mailtoLink = new UrlBuilder().setProtocol("mailto").setParameter("subject", shortText).setParameter("body", longText);
final ShareablePlaceContext context = provider.getContext();
final String urlToShare = Window.Location.createUrlBuilder()
.setPath(SHARING_URL_PREFIX + context.getContextAsPathParameters())
.setHash(null)
.buildString();
final String shortText = provider.getShortText();
final UrlBuilder mailtoLink = new UrlBuilder().setProtocol("mailto").setParameter("subject", shortText).setParameter("body", urlToShare);
// URLBuilder encodes spaces in parameters using "+" instead of "%20". This causes problems in Mail programs that do not decode "+" as space.
mail.setHref(mailtoLink.buildString().replace("+", "%20"));
UrlBuilder twitterLink = new UrlBuilder().setProtocol("https").setHost("twitter.com").setPath("intent/tweet").setParameter("text", shortText).setParameter("url", Window.Location.getHref()).setParameter("short_url_length", "8");
final UrlBuilder twitterLink = new UrlBuilder().setProtocol("https").setHost("twitter.com").setPath("intent/tweet").setParameter("text", shortText).setParameter("url", urlToShare).setParameter("short_url_length", "8");
twitter.setHref(twitterLink.buildString());
UrlBuilder facebookLink = new UrlBuilder().setProtocol("https").setHost("www.facebook.com")
.setPath("sharer/sharer.php").setParameter("u", Window.Location.getHref());
final UrlBuilder facebookLink = new UrlBuilder().setProtocol("https").setHost("www.facebook.com")
.setPath("sharer/sharer.php").setParameter("u", urlToShare);
facebook.setHref(facebookLink.buildString());
if (clientHasNavigatorCopyToClipboardSupport()) {
copyToClipBoard.removeStyleDependentName("gwt-button");
copyToClipBoard.removeStyleDependentName("gwt-Button:visited");
copyToClipBoard.removeStyleName("button");
copyToClipBoard.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
copyToClipboard(urlToShare);
Notification.notify(StringMessages.INSTANCE.sharingLinkCopied(), NotificationType.INFO);
}
});
} else {
copyToClipBoard.setVisible(false);
}
}
public static native void copyToClipboard(String text) /*-{
window.focus();
navigator.clipboard.writeText(text);
}-*/;
public static native boolean clientHasNavigatorCopyToClipboardSupport() /*-{
window.focus();
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
return true;
} else {
return false;
}
}-*/;
}
@@ -10,5 +10,7 @@
class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemtwitter}"></a>
<a ui:field="facebook" title="{i18n.sharingFacebookTooltip}" target="_blank"
class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemfacebook}"></a>
<g:Button ui:field="copyToClipBoard" title="{i18n.sharingCopyToClipBoardTooltip}"
addStyleNames="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemcopytoclipboard}"></g:Button>
</g:HTMLPanel>
</ui:UiBinder>
@@ -3,7 +3,7 @@ package com.sap.sailing.gwt.home.desktop.partials.sharing;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface SharingButtonsResources extends SharedHomeResources {
public static final SharingButtonsResources INSTANCE = GWT.create(SharingButtonsResources.class);
@@ -20,6 +20,7 @@ public interface SharingButtonsResources extends SharedHomeResources {
String eventheader_sharing_itememail();
String eventheader_sharing_itemtwitter();
String eventheader_sharing_itemfacebook();
String eventheader_sharing_itemcopytoclipboard();
}
}
@@ -1,9 +0,0 @@
package com.sap.sailing.gwt.home.desktop.partials.sharing;
public interface SharingMetadataProvider {
String getShortText();
String getLongText(String url);
}
@@ -4,7 +4,7 @@
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<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:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.socialfooter.SocialFooterResources" />
<g:HTMLPanel ui:field="htmlPanel">
<!-- The search/social media page footer-->
@@ -13,8 +13,8 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.start.EventStageDTO;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.gwt.client.controls.carousel.LazyLoadable;
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.desktop.partials.standings;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface StandingsResources extends SharedHomeResources {
public static final StandingsResources INSTANCE = GWT.create(StandingsResources.class);
@@ -3,7 +3,7 @@
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.desktop.partials.updates.UpdatesBoxResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<li class="{local_res.css.box_content_item}">
<a ui:field="link" class="{local_res.css.updatesbox_item} {local_res.css.updatesbox_itemlink}">
<div ui:field="icon" class="{local_res.css.updatesbox_item_icon}"></div>
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.desktop.partials.updates;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface UpdatesBoxResources extends SharedHomeResources {
public static final UpdatesBoxResources INSTANCE = GWT.create(UpdatesBoxResources.class);
@@ -57,7 +57,6 @@ public class EventRegattaActivity extends AbstractEventActivity<AbstractEventReg
new Timer(PlayModes.Live, PlayStates.Paused, delayBetweenAutoAdvancesInMilliseconds),
clientFactory.getErrorReporter(), flagImageResolver));
}
initNavigationPath(navigationPathDisplay);
}
@@ -15,7 +15,7 @@ import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.text.shared.SafeHtmlRenderer;
import com.google.gwt.user.cellview.client.Column;
import com.sap.sailing.gwt.home.desktop.places.user.profile.sailorprofiletab.SailorProfileDesktopResources;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
/**
* NavigatorColumn with a navigator arrow. After a click on the column, it will redirect to the associated URL,
@@ -28,7 +28,7 @@ import com.sap.sailing.gwt.home.desktop.places.user.profile.sailorprofiletab.Sai
import com.sap.sailing.gwt.home.desktop.places.user.profile.sailorprofiletab.details.ShowAndEditSailorProfile;
import com.sap.sailing.gwt.home.desktop.places.user.profile.sailorprofiletab.details.events.CompetitorWithoutClubnameItemDescription;
import com.sap.sailing.gwt.home.desktop.places.user.profile.sailorprofiletab.details.events.NavigatorColumn;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.settings.client.EntryPointWithSettingsLinkFactory;
import com.sap.sailing.gwt.settings.client.raceboard.RaceBoardPerspectiveOwnSettings;
import com.sap.sailing.gwt.settings.client.raceboard.RaceboardContextDefinition;
@@ -8,6 +8,7 @@
<ul class="bulletList">
<li>Dependent start times now correctly transmit the race course area ID for display
in the Regatta Overview.</li>
<li>Fixed not running timer below a flag in the navigation drawer.</li>
</ul>
<h5 class="articleSubheadline">August 2020</h5>
<ul class="bulletList">
@@ -3,8 +3,8 @@ package com.sap.sailing.gwt.home.desktop.resources;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.DataResource.MimeType;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.google.gwt.resources.client.ImageResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
public interface SharedDesktopResources extends SharedHomeResources {
@@ -2,7 +2,7 @@
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.accordion.AccordionResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel addStyleNames="{local_res.css.accordion_item} {res.mediaCss.small12} {res.mediaCss.columns}">
<div ui:field="headerUi" class="{local_res.css.accordion_item_header}">
<h2 ui:field="titleUi" class="{local_res.css.accordion_item_header_title}"></h2>
@@ -10,10 +10,15 @@ import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO;
import com.sap.sailing.gwt.home.mobile.partials.sharing.SharingButtons;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.home.shared.places.event.EventContext;
import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.home.shared.utils.LogoUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.databylogo.DataByLogo;
public class EventHeader extends Composite {
@@ -31,12 +36,13 @@ public class EventHeader extends Composite {
@UiField DivElement eventLocationUi;
@UiField DivElement eventHeader;
@UiField DataByLogo dataByLogo;
@UiField SharingButtons sharingButtons;
public EventHeader(EventViewDTO event, String optionalRegattaDisplayName, PlaceNavigation<?> logoNavigation) {
public EventHeader(EventContext eventContext, EventViewDTO event, String optionalRegattaDisplayName, PlaceNavigation<?> logoNavigation) {
EventHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
setUiFieldValues(event, optionalRegattaDisplayName, logoNavigation);
setupSharing(eventContext, event);
}
private void setUiFieldValues(EventViewDTO event, String optionalRegattaDisplayName, PlaceNavigation<?> logoNavigation) {
@@ -58,4 +64,20 @@ public class EventHeader extends Composite {
eventDateUi.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(event.getStartDate(), event.getEndDate()));
eventLocationUi.setInnerText(event.getLocationAndVenueAndCountry());
}
private void setupSharing(EventContext eventContext, EventViewDTO event) {
sharingButtons.setUp(new SharingMetadataProvider() {
@Override
public ShareablePlaceContext getContext() {
return eventContext;
}
@Override
public String getShortText() {
String dateString = EventDatesFormatterUtil.formatDateRangeWithYear(event.getStartDate(), event.getEndDate());
return StringMessages.INSTANCE.eventSharingShortText(event.getDisplayName(), event.getLocationOrVenue(), dateString);
}
});
}
}
@@ -1,6 +1,8 @@
<!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:s="urn:import:com.sap.sailing.gwt.ui.shared">
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:dp="urn:import:com.sap.sailing.gwt.home.mobile.partials"
xmlns:s="urn:import:com.sap.sailing.gwt.ui.shared">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
@@ -42,6 +44,7 @@
</div>
</div>
</div>
<s:databylogo.DataByLogo ui:field="dataByLogo" addStyleNames="{local_res.css.eventheader_info_subtitle_dataBy_logo_container}" />
<s:databylogo.DataByLogo ui:field="dataByLogo" addStyleNames="{local_res.css.eventheader_info_subtitle_dataBy_logo_container}"/>
<dp:sharing.SharingButtons ui:field="sharingButtons"/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -4,7 +4,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.eventsteps.EventStepsResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel addStyleNames="{local_res.css.eventsteps_phases_phase}">
<a class="{local_res.css.eventsteps_phases_phase_link}" ui:field="anchorUi">
<div class="{local_res.css.eventsteps_phases_phase_progress}">
@@ -4,7 +4,7 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.DataResource.MimeType;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface HeaderResources extends SharedHomeResources {
public static final HeaderResources INSTANCE = GWT.create(HeaderResources.class);
@@ -1,7 +1,7 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:style gss="true" type="com.sap.sailing.gwt.home.mobile.partials.imagegallery.MobileFullscreenGallery.Style">
.popup {
position: fixed !important;
@@ -3,7 +3,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.recents.EventsOverviewRecentResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<a class="{local_res.css.eventsoverviewrecent_event} {local_res.css.seriesInfo}">
<div class="{local_res.css.eventteaser_title}">
<div class="{local_res.css.eventteaser_title_name}" ui:field="seriesNameUi"></div>
@@ -3,7 +3,7 @@
xmlns:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<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:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.recents.EventsOverviewRecentResources" />
<g:HTMLPanel addStyleNames="{local_res.css.eventsoverviewrecent_year}">
<g:HTMLPanel ui:field="headerDiv"
@@ -7,7 +7,7 @@
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.home.mobile.partials.recents.EventsOverviewRecentResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<div>
<a ui:field="eventLinkUi">
<div class="{local_res.css.eventsoverviewrecent_event}">
@@ -4,7 +4,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.regattaStatus.RegattaStatusResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel>
<a title="" ui:field="linkUi">
<div class="{local_res.css.regattastatus_content_regatta_race} {res.mediaCss.grid}">
@@ -4,7 +4,7 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.DataResource.MimeType;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface RegattaStatusResources extends SharedHomeResources {
public static final RegattaStatusResources INSTANCE = GWT.create(RegattaStatusResources.class);
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.mobile.partials.regattacompetition;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface RegattaCompetitionResources extends SharedHomeResources {
public static final RegattaCompetitionResources INSTANCE = GWT.create(RegattaCompetitionResources.class);
@@ -4,7 +4,7 @@ import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.DataResource.MimeType;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface SearchResultResources extends SharedHomeResources {
public static final SearchResultResources INSTANCE = GWT.create(SearchResultResources.class);
@@ -11,6 +11,7 @@
.sectionSubHeader {
background: #f2f2f2;
border-top: 1px solid #ccc;
overflow: hidden;
}
.sectionHeaderNoBorder {
border-top: none;
@@ -3,33 +3,33 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.sectionHeader.SectionHeaderResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<g:HTMLPanel>
<a style="display:block;" ui:field="headerMainUi">
<div class="{local_res.css.sectionheader_item}" ui:field="headerLeftUi">
<div class="{local_res.css.sectionheader_item_image}" style="display:none;" ui:field="imageUi">
<div class="{local_res.css.sectionheader_item_image_seperator}"></div>
</div>
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel>
<a style="display:block;" ui:field="headerMainUi">
<div class="{local_res.css.sectionheader_item}" ui:field="headerLeftUi">
<div class="{local_res.css.sectionheader_item_image}" style="display:none;" ui:field="imageUi">
<div class="{local_res.css.sectionheader_item_image_seperator}"></div>
</div>
<div ui:field="titleAndLabelContainerUi" class="{local_res.css.sectionheader_item_title_label}">
<div>
<h2 class="{local_res.css.sectionheader_item_title}" ui:field="titleUi"></h2>
<div class="{local_res.css.sectionheader_item_label} {res.mainCss.label}" style="display:none;"
ui:field="labelUi"></div>
</div>
<h2 class="{local_res.css.sectionheader_item_title}" ui:field="titleUi"></h2>
<div class="{local_res.css.sectionheader_item_label} {res.mainCss.label}" style="display:none;"
ui:field="labelUi"></div>
</div>
<div>
<g:SimplePanel addStyleNames="{local_res.css.sectionheader_itemright_container}"
ui:field="widgetContainerUi" />
</div>
</div>
<div class="{local_res.css.sectionheader_item_subtitle}" style="display:none;" ui:field="subtitleUi"></div>
</div>
<g:HTMLPanel addStyleNames="{local_res.css.sectionheader_item} {local_res.css.sectionheader_itemright}"
ui:field="headerRightUi">
<div class="{local_res.css.sectionheader_item_infotext}" style="display:none;" ui:field="infoTextUi"></div>
<div class="{local_res.css.sectionheader_item_arrow}" style="display:none;" ui:field="actionArrowUi"></div>
</g:HTMLPanel>
</a>
<g:HTMLPanel ui:field="headerContentUi"
addStyleNames="{local_res.css.sectionheader_itemright} {local_res.css.sectionheader_element}" />
</g:HTMLPanel>
<div class="{local_res.css.sectionheader_item_subtitle}" style="display:none;" ui:field="subtitleUi"></div>
</div>
<g:HTMLPanel addStyleNames="{local_res.css.sectionheader_item} {local_res.css.sectionheader_itemright}"
ui:field="headerRightUi">
<div class="{local_res.css.sectionheader_item_infotext}" style="display:none;" ui:field="infoTextUi"></div>
<div class="{local_res.css.sectionheader_item_arrow}" style="display:none;" ui:field="actionArrowUi"></div>
</g:HTMLPanel>
</a>
<g:HTMLPanel ui:field="headerContentUi"
addStyleNames="{local_res.css.sectionheader_itemright} {local_res.css.sectionheader_element}" />
</g:HTMLPanel>
</ui:UiBinder>
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.mobile.partials.sectionHeader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface SectionHeaderResources extends SharedHomeResources {
public static final SectionHeaderResources INSTANCE = GWT.create(SectionHeaderResources.class);
@@ -10,9 +10,14 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.event.EventAndLeaderboardReferenceWithStateDTO;
import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO;
import com.sap.sailing.gwt.home.mobile.partials.sharing.SharingButtons;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesContext;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.home.shared.utils.LogoUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
public class SeriesHeader extends Composite {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@@ -24,28 +29,29 @@ public class SeriesHeader extends Composite {
@UiField DivElement eventStateUi;
@UiField AnchorElement eventLogoUi;
@UiField DivElement locationsUi;
@UiField SharingButtons sharingButtons;
public SeriesHeader(EventSeriesViewDTO event) {
this(event, null);
public SeriesHeader(SeriesContext seriesContext, EventSeriesViewDTO series) {
this(seriesContext, series, null);
}
public SeriesHeader(EventSeriesViewDTO event, PlaceNavigation<?> logoNavigation) {
public SeriesHeader(SeriesContext seriesContext, EventSeriesViewDTO series, PlaceNavigation<?> logoNavigation) {
SeriesHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
setUiFieldValues(event, logoNavigation);
setUiFieldValues(series, logoNavigation);
setupSharing(seriesContext, series);
}
private void setUiFieldValues(EventSeriesViewDTO event, PlaceNavigation<?> logoNavigation) {
LogoUtil.setEventLogo(eventLogoUi, event);
private void setUiFieldValues(EventSeriesViewDTO series, PlaceNavigation<?> logoNavigation) {
LogoUtil.setEventLogo(eventLogoUi, series);
if (logoNavigation != null) {
logoNavigation.configureAnchorElement(eventLogoUi);
}
eventNameUi.setInnerText(event.getDisplayName());
LabelTypeUtil.renderLabelType(eventStateUi, event.getState().getStateMarker());
eventNameUi.setInnerText(series.getDisplayName());
LabelTypeUtil.renderLabelType(eventStateUi, series.getState().getStateMarker());
StringBuilder locationsBuilder = new StringBuilder();
boolean first = true;
for (EventAndLeaderboardReferenceWithStateDTO eventOfSeries : event.getEventsAndRegattasOfSeriesAscending()) {
for (EventAndLeaderboardReferenceWithStateDTO eventOfSeries : series.getEventsAndRegattasOfSeriesAscending()) {
if(!first) {
locationsBuilder.append(", ");
}
@@ -57,4 +63,18 @@ public class SeriesHeader extends Composite {
}
locationsUi.setInnerText(locationsBuilder.toString());
}
private void setupSharing(SeriesContext seriesContext, EventSeriesViewDTO series) {
sharingButtons.setUp(new SharingMetadataProvider() {
@Override
public ShareablePlaceContext getContext() {
return seriesContext;
}
@Override
public String getShortText() {
return StringMessages.INSTANCE.seriesSharingShortText(series.getDisplayName());
}
});
}
}
@@ -1,6 +1,7 @@
<!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:s="urn:import:com.sap.sailing.gwt.home.client.shared">
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared"
xmlns:dp="urn:import:com.sap.sailing.gwt.home.mobile.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
@@ -31,5 +32,6 @@
</div>
</div>
</div>
<dp:sharing.SharingButtons ui:field="sharingButtons"/>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,64 @@
.eventheader_sharing_container {
position: fixed;
z-index: 999;
right: 25px;
bottom: 25px;
}
.eventheader_sharing_faded_in {
visibility:visible;
-webkit-transition: opacity 0.5s ease-in-out;
-moz-transition: opacity 0.5s ease-in-out;
-ms-transition: opacity 0.5s ease-in-out;
-o-transition: opacity 0.5s ease-in-out;
opacity: 1;
}
.eventheader_sharing_faded_out {
visibility: hidden;
-webkit-transition: visibility 0s 2s, opacity 2s;
-moz-transition: visibility 0s 2s, opacity 2s;
-ms-transition: visibility 0s 2s, opacity 2s;
-o-transition: visibility 0s 2s, opacity 2s;
opacity: 0;
}
.eventheader_sharing_item {
display: inline-block;
height: 3.5em;
width: 3.5em;
background-position: center center;
background-repeat: no-repeat;
border-radius: 100%;
border-width: thin;
border-style: solid;
background-size: contain;
background-color: rgb(0, 143, 204) !important;
}
eventheader_sharing_item:hover,
eventheader_sharing_item:focus{
background-color: rgb(0, 143, 204);
}
.eventheader_sharing_itemcopytoclipboard {
}
.eventheader_sharing_itemcopytoclipboard:after {
content: "";
position: absolute;
width: 50%;
height: 50%;
top: 25%;
left: 25%;
background-image: resourceUrl("copyIcon");
background-size: contain;
background-position: center;
background-repeat: no-repeat;
border: none;
}
.eventheader_sharing_itemshare {
background-image: resourceUrl("sharingIcon");
background-size: 50%;
}
@@ -0,0 +1,133 @@
package com.sap.sailing.gwt.home.mobile.partials.sharing;
import static com.google.gwt.dom.client.Style.Display.NONE;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.ScrollEvent;
import com.google.gwt.user.client.Window.ScrollHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.mobile.partials.sharing.SharingButtonsResources.LocalCss;
import com.sap.sailing.gwt.home.shared.partials.shared.SharingMetadataProvider;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.shared.ClientConfiguration;
public class SharingButtons extends Composite {
private static SharingButtonsUiBinder uiBinder = GWT.create(SharingButtonsUiBinder.class);
private static String SHARING_URL_PREFIX = "/sailingserver/shared/home";
interface SharingButtonsUiBinder extends UiBinder<Widget, SharingButtons> {
}
@UiField
HTMLPanel htmlPanel;
@UiField
Button shareButton;
@UiField
Button copyToClipBoard;
public SharingButtons() {
SharingButtonsResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
if (!ClientConfiguration.getInstance().isBrandingActive()) {
htmlPanel.getElement().getStyle().setDisplay(NONE);
}
}
public void setUp(SharingMetadataProvider provider) {
if (!ClientConfiguration.getInstance().isBrandingActive()) {
return;
}
final ShareablePlaceContext context = provider.getContext();
String urlToShare = Window.Location.createUrlBuilder()
.setPath(SHARING_URL_PREFIX + context.getContextAsPathParameters())
.setHash(null)
.buildString();
if (clientHasNavigatorShareSupport()) {
copyToClipBoard.setVisible(false);
shareButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
share(urlToShare, provider.getShortText());
}
});
} else if (clientHasNavigatorCopyToClipboardSupport()) {
shareButton.setVisible(false);
copyToClipBoard.removeStyleDependentName("gwt-button");
copyToClipBoard.removeStyleDependentName("gwt-Button:visited");
copyToClipBoard.removeStyleName("button");
copyToClipBoard.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
copyToClipboard(urlToShare);
Notification.notify(StringMessages.INSTANCE.sharingLinkCopied(), NotificationType.INFO);
}
});
} else {
shareButton.setVisible(false);
copyToClipBoard.setVisible(false);
}
final LocalCss css = SharingButtonsResources.INSTANCE.css();
Timer fadeOutSharingButtonsTimer = new Timer() {
@Override
public void run() {
htmlPanel.removeStyleName(css.eventheader_sharing_faded_in());
htmlPanel.addStyleName(css.eventheader_sharing_faded_out());
}
};
Window.addWindowScrollHandler(new ScrollHandler() {
@Override
public void onWindowScroll(ScrollEvent event) {
htmlPanel.removeStyleName(css.eventheader_sharing_faded_out());
htmlPanel.addStyleName(css.eventheader_sharing_faded_in());
fadeOutSharingButtonsTimer.schedule(1500);
}
});
fadeOutSharingButtonsTimer.schedule(2000);
}
public static native void copyToClipboard(String text) /*-{
window.focus();
navigator.clipboard.writeText(text);
}-*/;
public static native void share(String url, String text) /*-{
window.focus();
navigator.share({
url: url,
text: text
});
}-*/;
public static native boolean clientHasNavigatorShareSupport() /*-{
window.focus();
if (navigator.share) {
return true;
} else {
return false;
}
}-*/;
public static native boolean clientHasNavigatorCopyToClipboardSupport() /*-{
window.focus();
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
return true;
} else {
return false;
}
}-*/;
}
@@ -0,0 +1,12 @@
<!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">
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.sharing.SharingButtonsResources" />
<g:HTMLPanel ui:field="htmlPanel" addStyleNames="{local_res.css.eventheader_sharing_container} {local_res.css.eventheader_sharing_faded_in}">
<g:Button ui:field="shareButton" title="{i18n.sharingCopyToClipBoardTooltip}"
addStyleNames="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemshare}"></g:Button>
<g:Button ui:field="copyToClipBoard" title="{i18n.sharingCopyToClipBoardTooltip}"
addStyleNames="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemcopytoclipboard}"></g:Button>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,22 @@
package com.sap.sailing.gwt.home.mobile.partials.sharing;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface SharingButtonsResources extends SharedHomeResources {
public static final SharingButtonsResources INSTANCE = GWT.create(SharingButtonsResources.class);
@Source("SharingButtons.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String eventheader_sharing_item();
String eventheader_sharing_itemcopytoclipboard();
String eventheader_sharing_itemshare();
String eventheader_sharing_container();
String eventheader_sharing_faded_out();
String eventheader_sharing_faded_in();
}
}
@@ -3,7 +3,7 @@
<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:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.home.mobile.partials.socialfooter.SocialFooterResources" />
<g:HTMLPanel ui:field="htmlPanel">
@@ -13,8 +13,8 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.event.EventLinkAndMetadataDTO;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.gwt.client.controls.carousel.LazyLoadable;
@@ -5,7 +5,7 @@
<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:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.upcoming.EventsOverviewUpcomingResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<g:HTMLPanel addStyleNames="{local_res.css.eventsoverviewupcoming} {local_res.css.accordion}">
@@ -5,7 +5,7 @@
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.home.mobile.partials.upcoming.EventsOverviewUpcomingResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:style>
.holder {
@@ -2,7 +2,7 @@ package com.sap.sailing.gwt.home.mobile.partials.updatesBox;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.CssResource;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
public interface UpdatesBoxResources extends SharedHomeResources {
public static final UpdatesBoxResources INSTANCE = GWT.create(UpdatesBoxResources.class);
@@ -26,6 +26,7 @@ import com.sap.sailing.gwt.home.mobile.partials.simpleinfoblock.SimpleInfoBlock;
import com.sap.sailing.gwt.home.mobile.places.QuickfinderPresenter;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.windfinder.WindfinderControl;
import com.sap.sailing.gwt.home.shared.places.event.EventContext;
import com.sap.sailing.gwt.home.shared.refresh.RefreshManager;
import com.sap.sailing.gwt.home.shared.refresh.RefreshManagerWithErrorAndBusy;
import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -46,8 +47,8 @@ public abstract class AbstractEventView<P extends EventViewBase.Presenter> exten
@UiField(provided = true) WindfinderControl windfinderUi;
@UiField SimplePanel viewContentUi;
private AbstractEventViewLayout(EventViewDTO event, String regattaName, PlaceNavigation<?> logoNavigation) {
this.eventHeaderUi = new EventHeader(event, regattaName, logoNavigation);
private AbstractEventViewLayout(EventContext eventContext, EventViewDTO event, String regattaName, PlaceNavigation<?> logoNavigation) {
this.eventHeaderUi = new EventHeader(eventContext, event, regattaName, logoNavigation);
this.windfinderUi = new WindfinderControl(SpotDTO::getCurrentlyMostAppropriateUrl);
}
}
@@ -62,14 +63,16 @@ public abstract class AbstractEventView<P extends EventViewBase.Presenter> exten
this(presenter, showRegattaName, enableLogoNavigation, true);
}
public AbstractEventView(P presenter, boolean showRegattaName, boolean enableLogoNavigation, boolean supportsRefresh) {
public AbstractEventView(P presenter, boolean showRegattaName, boolean enableLogoNavigation,
boolean supportsRefresh) {
this.currentPresenter = presenter;
String regattaName = showRegattaName ? currentPresenter.getRegatta().getDisplayName() : null;
PlaceNavigation<?> logoNavigation = enableLogoNavigation ? currentPresenter.getEventNavigation() : null;
this.layout = new AbstractEventViewLayout(currentPresenter.getEventDTO(), regattaName, logoNavigation);
this.layout = new AbstractEventViewLayout(currentPresenter.getCtx(), currentPresenter.getEventDTO(), regattaName, logoNavigation);
initWidget(uiBinder.createAndBindUi(this.layout));
if(supportsRefresh) {
this.refreshManager = new RefreshManagerWithErrorAndBusy(contentRoot, layout.viewContentUi, currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory());
if (supportsRefresh) {
this.refreshManager = new RefreshManagerWithErrorAndBusy(contentRoot, layout.viewContentUi,
currentPresenter.getDispatch(), currentPresenter.getErrorAndBusyClientFactory());
} else {
this.refreshManager = null;
layout.viewContentUi.setWidget(contentRoot);
@@ -92,11 +95,13 @@ public abstract class AbstractEventView<P extends EventViewBase.Presenter> exten
return currentPresenter.isMultiRegattaEvent();
}
protected void setQuickFinderValues(Quickfinder quickfinder, Map<String, Set<RegattaMetadataDTO>> regattasByLeaderboardGroupName) {
protected void setQuickFinderValues(Quickfinder quickfinder,
Map<String, Set<RegattaMetadataDTO>> regattasByLeaderboardGroupName) {
QuickfinderPresenter.getForRegattaLeaderboards(quickfinder, currentPresenter, regattasByLeaderboardGroupName);
}
protected void setQuickFinderValues(Quickfinder quickfinder, String seriesName, Collection<EventAndLeaderboardReferenceWithStateDTO> eventsOfSeries) {
protected void setQuickFinderValues(Quickfinder quickfinder, String seriesName,
Collection<EventAndLeaderboardReferenceWithStateDTO> eventsOfSeries) {
QuickfinderPresenter.getForSeriesLeaderboards(quickfinder, seriesName, currentPresenter, eventsOfSeries);
}
@@ -118,7 +123,8 @@ public abstract class AbstractEventView<P extends EventViewBase.Presenter> exten
}
@Override
public final void setQuickFinderValues(String seriesName, Collection<EventAndLeaderboardReferenceWithStateDTO> eventsOfSeries) {
public final void setQuickFinderValues(String seriesName,
Collection<EventAndLeaderboardReferenceWithStateDTO> eventsOfSeries) {
setQuickFinderValues(layout.quickFinderUi, seriesName, eventsOfSeries);
}
@@ -46,7 +46,7 @@ public class SeriesViewImpl extends Composite implements SeriesView {
this.currentPresenter = presenter;
this.refreshManager = new LifecycleRefreshManager(this, currentPresenter.getDispatch());
EventSeriesViewDTO series = currentPresenter.getSeriesDTO();
eventHeaderUi = new SeriesHeader(series);
eventHeaderUi = new SeriesHeader(currentPresenter.getCtx(), series);
this.setupStatisticsBox(series);
leaderboardUi = new MinileaderboardBox(true, flagImageResolver);
initWidget(uiBinder.createAndBindUi(this));
@@ -35,7 +35,7 @@ public class SeriesMiniOverallLeaderboardViewImpl extends Composite implements S
public SeriesMiniOverallLeaderboardViewImpl(Presenter presenter, FlagImageResolver flagImageResolver) {
this.currentPresenter = presenter;
minileaderboardUi = new MinileaderboardBox(true, flagImageResolver);
eventHeaderUi = new SeriesHeader(presenter.getSeriesDTO(), presenter.getSeriesNavigation());
eventHeaderUi = new SeriesHeader(presenter.getCtx(), presenter.getSeriesDTO(), presenter.getSeriesNavigation());
initWidget(uiBinder.createAndBindUi(this));
RefreshManager refreshManager = new LifecycleRefreshManager(this, currentPresenter.getDispatch());
refreshManager.add(minileaderboardUi, new GetMiniOverallLeaderbordAction(presenter.getCtx().getLeaderboardGroupId(),
@@ -12,8 +12,8 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.communication.user.profile.domain.ParticipatedEventDTO;
import com.sap.sailing.gwt.home.communication.user.profile.domain.ParticipatedRegattaDTO;
import com.sap.sailing.gwt.home.mobile.places.user.profile.sailorprofiles.SailorProfileMobileResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.ui.client.FlagImageResolver;
/**
@@ -1,4 +1,4 @@
package com.sap.sailing.gwt.home.shared.resources;
package com.sap.sailing.gwt.home.shared;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.DataResource;
@@ -75,4 +75,12 @@ public interface SharedHomeResources extends CommonIcons {
@Source("raw_gps_fixes.png")
ImageResource gpsFixes();
@Source("../../ui/client/images/share.svg")
@MimeType("image/svg+xml")
DataResource sharingIcon();
@Source("../../ui/client/images/flat_copy.svg")
@MimeType("image/svg+xml")
DataResource copyIcon();
}
@@ -18,10 +18,10 @@ import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewRaceTickerStageDTO;
import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewRegattaTickerStageDTO;
import com.sap.sailing.gwt.home.communication.event.eventoverview.EventOverviewTickerStageDTO;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.countdown.CountdownResources.LocalCss;
import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
@@ -1,7 +1,7 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.resources.SharedHomeResources" />
<ui:with field="shr" type="com.sap.sailing.gwt.home.shared.SharedHomeResources" />
<ui:style gss="true" type="com.sap.sailing.gwt.home.shared.partials.fullscreen.FullscreenContainer.Style">
.popup {
position: fixed !important;
@@ -0,0 +1,10 @@
package com.sap.sailing.gwt.home.shared.partials.shared;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
public interface SharingMetadataProvider {
String getShortText();
ShareablePlaceContext getContext();
}
@@ -0,0 +1,10 @@
package com.sap.sailing.gwt.home.shared.places;
public interface ShareablePlaceContext {
/**
*
* @return Returns the path parameters to reach the Place this context belongs to, conforming to the shared URL
* pattern for Places. Will return @null, if there are no path parameters to be found.
*/
public String getContextAsPathParameters();
}
@@ -1,6 +1,8 @@
package com.sap.sailing.gwt.home.shared.places.event;
import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaAnalyticsDataManager;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
import com.sap.sse.gwt.client.URLEncoder;
/**
* Common context used by the different tabs in the event place.
@@ -8,7 +10,7 @@ import com.sap.sailing.gwt.home.desktop.places.event.regatta.RegattaAnalyticsDat
* @author pgtaboada
*
*/
public class EventContext {
public class EventContext implements ShareablePlaceContext {
private String eventId;
private String regattaId;
private RegattaAnalyticsDataManager regattaAnalyticsManager;
@@ -48,4 +50,17 @@ public class EventContext {
this.regattaAnalyticsManager = regattaAnalyticsManager;
return this;
}
@Override
public String getContextAsPathParameters() {
if(eventId != null) {
String path = "/events/" + eventId;
if(regattaId != null) {
path += "/regattas/" + URLEncoder.encode(regattaId);
}
return path;
}else {
return null;
}
}
}
@@ -4,12 +4,13 @@ import java.util.UUID;
import com.google.gwt.core.client.GWT;
import com.sap.sailing.gwt.home.desktop.places.fakeseries.EventSeriesAnalyticsDataManager;
import com.sap.sailing.gwt.home.shared.places.ShareablePlaceContext;
/**
* Common context used by the different tabs in the series place.
*
*/
public class SeriesContext {
public class SeriesContext implements ShareablePlaceContext{
private final UUID seriesId;
private UUID leaderboardGroupId;
@@ -44,8 +45,8 @@ public class SeriesContext {
public UUID getSeriesId() {
if(leaderboardGroupId != null) {
GWT.log("Access to seriesid! when leaderboardgroupid exist!" + seriesId + " lid " + leaderboardGroupId);
GWT.debugger();
GWT.log("Access to seriesid! Use leaderboardgroupid instead"
+ " seriesId:" + seriesId + "; lid: " + leaderboardGroupId);
}
return seriesId;
}
@@ -62,5 +63,13 @@ public class SeriesContext {
public void updateLeaderboardGroupId(UUID leaderboardGroupUUID) {
this.leaderboardGroupId = leaderboardGroupUUID;
}
@Override
public String getContextAsPathParameters() {
if(leaderboardGroupId != null) {
return "/series/" + leaderboardGroupId;
}else {
return null;
}
}
}
@@ -4,7 +4,7 @@ import com.google.gwt.dom.client.Element;
import com.google.gwt.safehtml.shared.SafeUri;
import com.sap.sailing.gwt.home.communication.event.HasLogo;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.SharedHomeResources;
/**
* Utility class to set logo url on UI elements using a default logo as fallback if no logo is provided.
@@ -1158,10 +1158,9 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String sharingMailTooltip();
String sharingTwitterTooltip();
String sharingFacebookTooltip();
String sharingCopyToClipBoardTooltip();
String eventSharingShortText(String eventName, String venue, String dateString);
String eventSharingLongText(String eventName, String venue, String dateString, String url);
String seriesSharingShortText(String seriesName);
String seriesSharingLongText(String seriesName, String url);
String competitorsAnalytics();
String mediaNoContent();
String media();
@@ -2397,4 +2396,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String unableToLoadCourseAreas(String message);
String insufficientPermissions();
String manageEvents();
String sharingLinkCopied();
}
@@ -1142,12 +1142,9 @@ upcomingEventStartsInDays[none]=today
sharingMailTooltip=Share by mail
sharingTwitterTooltip=Share on Twitter
sharingFacebookTooltip=Share on Facebook
sharingCopyToClipBoardTooltip=Copy link to clipboard
#String eventSharingShortText(String eventName, String venue, String dateString);
eventSharingShortText={0} in {1} on {2}
#String eventSharingLongText(String eventName, String venue, String dateString, String url);
eventSharingLongText=I''d like to share {0} in {1} on {2}. Details on: \n{3}
#String seriesSharingLongText(String seriesName, String url);
seriesSharingLongText=I''d like to share series {0}. Details: {1}
#String seriesSharingShortText(String seriesName);
seriesSharingShortText={0}
competitorsAnalytics=Progression
@@ -2402,4 +2399,5 @@ whitelabelSailing=Sailing
unableToLoadCourseAreas=Unable to load course areas: {0}
serverName=Server Name: {0}
insufficientPermissions=The current user has insufficient permissions for this action. Please log in with an authorized user.
manageEvents=Manage Events
manageEvents=Manage Events
sharingLinkCopied=Copied link to clipboard!
@@ -1124,12 +1124,9 @@ upcomingEventStartsInDays[none]=heute
sharingMailTooltip=Per Mail teilen
sharingTwitterTooltip=Auf Twitter teilen
sharingFacebookTooltip=Auf Facebook teilen
sharingCopyToClipBoardTooltip=Link in Zwischenablage kopieren
#String eventSharingShortText(String eventName, String venue, String dateString);
eventSharingShortText={0} in {1} vom {2}
#String eventSharingLongText(String eventName, String venue, String dateString, String url);
eventSharingLongText=Schau mal auf {0} in {1} vom {2}. Details unter: \n{3}
#String seriesSharingLongText(String seriesName, String url);
seriesSharingLongText=Schau mal auf {0}. Details: {1}
#String seriesSharingShortText(String seriesName);
seriesSharingShortText={0}
competitorsAnalytics=Verlauf
@@ -2410,4 +2407,5 @@ autoRestartTrackingUponCompetitorSetChange=Tracking der Rennen automatisch neu s
unableToLoadCourseAreas=Liste der Regattabahnen kann nicht geladen werden: {0}
serverName=Server Name: {0}
insufficientPermissions=Aktuelle Berechtigungen reichen nicht aus um die gewählte Aktion auszuführen. Bitte melden Sie sich als ein authorisier Benutzer an.
manageEvents=Events Verwalten
manageEvents=Events Verwalten
sharingLinkCopied=Copied link to clipboard!

Some files were not shown because too many files have changed in this diff Show More