Merge branch 'master' into improved-replication

This commit is contained in:
Axel Uhl committed 2014-07-15 15:58:04 +02:00
commit af0d3f0a18
95 files changed
+5477 -925

No files matched your search

@@ -7,6 +7,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -498,6 +500,15 @@ public class IgtimiConnectionFactoryImpl implements IgtimiConnectionFactory {
URI uri = new URI((String) serverUrl);
result.add(uri);
}
// sort those to the front that don't do port 443 nor wss://
Collections.sort(result, new Comparator<URI>() {
@Override
public int compare(URI o1, URI o2) {
int o1Score = (o1.toString().contains("443") ? 1 : 0) + (o1.toString().contains("wss") ? 1 : 0);
int o2Score = (o2.toString().contains("443") ? 1 : 0) + (o2.toString().contains("wss") ? 1 : 0);
return o1Score - o2Score;
}
});
return result;
}
@@ -11,6 +11,23 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.sap.sse.common.Named;
/**
* To be used in conjunction with {@link LockUtil}. Provides additional naming
* for locks which is helpful in the tracing that {@link LockUtil} provides.
* Use as in
* <pre>
* NamedReentrantReadWriteLock lock = ...;
* LockUtil.lockForRead(lock);
* try {
* // do something while holding the lock
* } finally {
* LockUtil.unlockAfterRead(lock);
* }
* </pre>
*
* @author Axel Uhl (d043530)
*
*/
public class NamedReentrantReadWriteLock extends ReentrantReadWriteLock implements Named {
private static final long serialVersionUID = 2906084982209339774L;
private final String name;
+1
View File
@@ -26,6 +26,7 @@
<!-- be added before this line. -->
<!-- -->
<script type="text/javascript" src="com.sap.sailing.gwt.Home/com.sap.sailing.gwt.Home.nocache.js"></script>
<script type="text/javascript" src="js/newhome/idangerous.swiper.js"></script>
</head>
<!-- -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

File diff suppressed because it is too large. Load diff
@@ -0,0 +1,92 @@
package com.sap.sailing.gwt.home.client;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.google.gwt.place.shared.Place;
/**
* An abstract Place which is able to manage and parse place parameters.
* @author Frank
*
*/
public abstract class AbstractBasePlace extends Place {
private static final Logger logger = Logger.getLogger(AbstractBasePlace.class.getName());
private static final String VALIDATE_TOKENS_MESSAGE_PREFIX = "Missing token(s): ";
private String placeParametersAsToken;
private Map<String, String> params = new HashMap<String, String>();
public AbstractBasePlace(String... paramKeysAndValues) {
if (paramKeysAndValues.length % 2 == 0) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < paramKeysAndValues.length; i++) {
String paramName = paramKeysAndValues[i++];
String paramValue = paramKeysAndValues[i];
// for now we don't add 'null' parameters
if(paramValue != null) {
params.put(paramName, paramValue);
if(stringBuilder.length() > 0) {
stringBuilder.append("&");
}
stringBuilder.append(paramName + "=" + paramValue);
}
}
placeParametersAsToken = stringBuilder.toString();
} else {
logger.warning("Invalid number of arguments received! Must be key,value,key,value ... ignoring arguments");
}
}
public AbstractBasePlace(String url) {
if (url != null && !url.isEmpty()) {
this.placeParametersAsToken = url;
List<String> list = Arrays.asList(url.split("&"));
if (list == null || list.size() < 1) {
logger.warning("Token empty, no-op");
return;
}
for (String listItem : list) {
List<String> nvPair = Arrays.asList(listItem.split("="));
if (nvPair == null || nvPair.size() != 2) {
logger.warning("Invalid parameters");
continue;
}
params.put(nvPair.get(0), nvPair.get(1));
}
}
}
protected void validate(String... paramNames) {
StringBuffer message = new StringBuffer(VALIDATE_TOKENS_MESSAGE_PREFIX);
for (String name : paramNames) {
if (!params.containsKey(name))
message.append(name + " ");
}
if (!message.toString().equals(VALIDATE_TOKENS_MESSAGE_PREFIX)) {
logger.warning(message.toString());
}
}
public String getParametersAsToken() {
return placeParametersAsToken;
}
public String getParameter(String name) {
return params.get(name);
}
public boolean hasParameter(String name) {
return params.containsKey(name);
}
}
@@ -42,6 +42,18 @@ public interface HomeResources extends ClientBundle {
String mainsection_header();
String mainsection_header_title();
String mainsection_navigation();
String lightbox();
String lightbox_overlay();
String lightbox_overlayhidden();
String lightbox_content();
String lightbox_contenthidden();
String lightbox_content_enlargedimage();
String lightbox_content_enlargedimage_caption();
String lightbox_content_enlargedimage_close();
String lightbox_data();
String lightbox_photo();
String lightbox_item();
}
@Shared
@@ -2,7 +2,8 @@ package com.sap.sailing.gwt.home.client.app;
public interface PlaceNavigator {
void goToHome();
void goToEvent(String eventUuidAsString);
void goToEvent(String eventUuidAsString, String baseUrl);
void goToRegattaOfEvent(String eventUuidAsString, String regattaIdAsNameString, String baseUrl);
void goToSearchResult(String searchQuery);
void goToEvents();
void goToAboutUs();
@@ -1,6 +1,9 @@
package com.sap.sailing.gwt.home.client.app;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceTokenizer;
import com.google.gwt.user.client.Window;
import com.sap.sailing.gwt.home.client.place.aboutus.AboutUsPlace;
import com.sap.sailing.gwt.home.client.place.contact.ContactPlace;
import com.sap.sailing.gwt.home.client.place.event.EventPlace;
@@ -12,6 +15,7 @@ import com.sap.sailing.gwt.home.client.place.start.StartPlace;
public class PlaceNavigatorImpl implements PlaceNavigator {
private final PlaceController placeController;
private final static String SAPSAILING_DOMAIN = "www.sapsailing.com";
protected PlaceNavigatorImpl(PlaceController placeController) {
super();
@@ -20,42 +24,79 @@ public class PlaceNavigatorImpl implements PlaceNavigator {
@Override
public void goToHome() {
placeController.goTo(new StartPlace());
gotoPlace(new StartPlace(), new StartPlace.Tokenizer());
}
@Override
public void goToEvent(String eventUuidAsString) {
placeController.goTo(new EventPlace(eventUuidAsString));
public void goToEvent(String eventUuidAsString, String baseUrl) {
EventPlace eventPlace = new EventPlace(eventUuidAsString);
if(isLocationOnLocalhost() || baseUrl.contains(SAPSAILING_DOMAIN)) {
placeController.goTo(eventPlace);
} else {
String remoteEventUrl = buildRemotePlaceUrl(baseUrl, eventPlace, new EventPlace.Tokenizer());
Window.Location.replace(remoteEventUrl);
}
}
@Override
public void goToRegattaOfEvent(String eventUuidAsString, String leaderboardIdAsNameString, String baseUrl) {
EventPlace eventPlace = new EventPlace(eventUuidAsString, leaderboardIdAsNameString);
if(isLocationOnLocalhost() || baseUrl.contains(SAPSAILING_DOMAIN)) {
placeController.goTo(eventPlace);
} else {
String remoteEventUrl = buildRemotePlaceUrl(baseUrl, eventPlace, new EventPlace.Tokenizer());
Window.Location.replace(remoteEventUrl);
}
}
@Override
public void goToSearchResult(String searchQuery) {
placeController.goTo(new SearchResultPlace(searchQuery));
gotoPlace(new SearchResultPlace(searchQuery), new SearchResultPlace.Tokenizer());
}
@Override
public void goToEvents() {
placeController.goTo(new EventsPlace());
gotoPlace(new EventsPlace(), new EventsPlace.Tokenizer());
}
@Override
public void goToAboutUs() {
placeController.goTo(new AboutUsPlace());
gotoPlace(new AboutUsPlace(), new AboutUsPlace.Tokenizer());
}
@Override
public void goToContact() {
placeController.goTo(new ContactPlace());
gotoPlace(new ContactPlace(), new ContactPlace.Tokenizer());
}
@Override
public void goToSolutions() {
placeController.goTo(new SolutionsPlace());
gotoPlace(new SolutionsPlace(), new SolutionsPlace.Tokenizer());
}
@Override
public void goToSponsoring() {
placeController.goTo(new SponsoringPlace());
gotoPlace(new SponsoringPlace(), new SponsoringPlace.Tokenizer());
}
private <T extends Place> void gotoPlace(T destinationPlace, PlaceTokenizer<T> tokenizer) {
if(isLocationOnLocalhost() || isLocationOnSapSailingCom()) {
placeController.goTo(destinationPlace);
} else {
String homeUrl = buildRemotePlaceUrl("http://" + SAPSAILING_DOMAIN, destinationPlace, tokenizer);
Window.Location.replace(homeUrl);
}
}
private <T extends Place> String buildRemotePlaceUrl(String baseUrl, T destinationPlace, PlaceTokenizer<T> tokenizer) {
return baseUrl + "/gwt/Home.html#" + destinationPlace.getClass().getSimpleName() + ":" + tokenizer.getToken(destinationPlace);
}
private boolean isLocationOnSapSailingCom() {
return Window.Location.getHostName().contains(SAPSAILING_DOMAIN);
}
private boolean isLocationOnLocalhost() {
return Window.Location.getHostName().contains("localhost") || Window.Location.getHostName().contains("127.0.0.1");
}
}
@@ -1,19 +1,28 @@
package com.sap.sailing.gwt.home.client.app;
import java.util.List;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.gwt.home.client.place.event.EventView;
import com.sap.sailing.gwt.home.client.place.event.TabletAndDesktopEventView;
import com.sap.sailing.gwt.home.client.place.events.EventsActivity;
import com.sap.sailing.gwt.home.client.place.events.EventsView;
import com.sap.sailing.gwt.home.client.place.events.TabletAndDesktopEventsView;
import com.sap.sailing.gwt.home.client.place.searchresult.SearchResultView;
import com.sap.sailing.gwt.home.client.place.searchresult.TabletAndDesktopSearchResultView;
import com.sap.sailing.gwt.home.client.place.solutions.SolutionsActivity;
import com.sap.sailing.gwt.home.client.place.solutions.SolutionsView;
import com.sap.sailing.gwt.home.client.place.solutions.TabletAndDesktopSolutionsView;
import com.sap.sailing.gwt.home.client.place.sponsoring.SponsoringActivity;
import com.sap.sailing.gwt.home.client.place.sponsoring.SponsoringView;
import com.sap.sailing.gwt.home.client.place.start.SmartphoneStartView;
import com.sap.sailing.gwt.home.client.place.sponsoring.TabletAndDesktopSponsoringView;
import com.sap.sailing.gwt.home.client.place.start.StartView;
import com.sap.sailing.gwt.home.client.place.start.TabletAndDesktopStartView;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sse.gwt.client.player.Timer;
public class SmartphoneApplicationClientFactory extends AbstractApplicationClientFactory implements ApplicationClientFactory {
@@ -30,32 +39,33 @@ public class SmartphoneApplicationClientFactory extends AbstractApplicationClien
}
@Override
public EventView createEventView(EventDTO event) {
return null;
public EventView createEventView(EventDTO event, List<RaceGroupDTO> raceGroups, String leaderboardName, Timer timerForClientServerOffset) {
return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset);
}
@Override
public EventsView createEventsView(EventsActivity activity) {
return null;
return new TabletAndDesktopEventsView(getPlaceNavigator());
}
@Override
public StartView createStartView() {
return new SmartphoneStartView(getPlaceNavigator());
return new TabletAndDesktopStartView(getPlaceNavigator());
// return new SmartphoneStartView(getPlaceNavigator());
}
@Override
public SponsoringView createSponsoringView(SponsoringActivity activity) {
return null;
return new TabletAndDesktopSponsoringView();
}
@Override
public SolutionsView createSolutionsView(SolutionsActivity activity) {
return null;
return new TabletAndDesktopSolutionsView();
}
@Override
public SearchResultView createSearchResultView() {
return null;
return new TabletAndDesktopSearchResultView(getPlaceNavigator(), getEventBus());
}
}
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.home.client.app;
import java.util.List;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.web.bindery.event.shared.EventBus;
@@ -19,6 +21,8 @@ import com.sap.sailing.gwt.home.client.place.sponsoring.TabletAndDesktopSponsori
import com.sap.sailing.gwt.home.client.place.start.StartView;
import com.sap.sailing.gwt.home.client.place.start.TabletAndDesktopStartView;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sse.gwt.client.player.Timer;
public class TabletAndDesktopApplicationClientFactory extends AbstractApplicationClientFactory implements ApplicationClientFactory {
@@ -35,8 +39,8 @@ public class TabletAndDesktopApplicationClientFactory extends AbstractApplicatio
}
@Override
public EventView createEventView(EventDTO event) {
return new TabletAndDesktopEventView(event);
public EventView createEventView(EventDTO event, List<RaceGroupDTO> raceGroups, String leaderboardName, Timer timerForClientServerOffset) {
return new TabletAndDesktopEventView(getSailingService(), event, raceGroups, leaderboardName, timerForClientServerOffset);
}
@Override
@@ -20,6 +20,8 @@ public interface TextMessages extends Messages {
String countdownMinutes();
String countdownSeconds();
String live();
String finished();
String watchNow();
String lastUpdate();
String leaderBoard();
String boxNewsUpdateMoreLink();
@@ -39,9 +41,19 @@ public interface TextMessages extends Messages {
String eventHeaderOverview();
String eventHeaderRaces();
String eventHeaderRegattas();
String eventHeaderSchedule();
String seriesHeaderOverview();
String seriesHeaderUpcoming();
String seriesHeaderRecent();
String seriesHeaderLeaderboard();
String seriesOverviewHeaderRecent();
String seriesOverviewReadMore();
String eventsOverviewRecentEvents();
String eventsOverviewRecentCountries();
String eventsOverviewRecentSailors();
String eventsOverviewRecentTrackedRaces();
String eventResultsHeadline();
String eventResultsBoatClassesDropDown();
String eventOverviewMoreEvents();
String eventOverviewRecentEvents();
String eventOverviewUpcomingDate();
String eventOverviewUpcomingEvent();
@@ -51,7 +63,8 @@ public interface TextMessages extends Messages {
String eventOverviewUpcomingTeaser();
String eventQuickfinderTitle();
String eventRegattaHeaderLeaderboard();
String eventRegattaHeaderRaceSchedule();
String eventRegattaHeaderRaceRaces();
String eventRegattaListAllBoatClasses();
String eventRegattaLeaderboardCompetitor();
String eventRegattaLeaderboardExtendLeaderboard();
String eventRegattaLeaderboardFinishedMessage();
@@ -59,11 +72,22 @@ public interface TextMessages extends Messages {
String eventRegattaLeaderboardName();
String eventRegattaLeaderboardRegattaRank();
String eventRegattaLeaderboardTotalPoints();
String eventRegattaRaceWatch();
String eventRegattaRaceAnalyse();
String eventRegattaRaceNotTracked();
String eventRegattaRaceFinished();
String eventRegattaRaceStarted();
String eventRegattaRaceScheduled();
String eventRegattaRacesLegendGps();
String eventRegattaRacesLegendWind();
String eventRegattaRacesLegendVideo();
String eventRegattaRacesLegendAudio();
String eventSponsorsTitle();
String footerCopyright();
String footerLanguage();
String footerLegal();
String footerPrivacy();
String footerFeedback();
String headerEvents();
String headerHome();
String headerLogo();
@@ -80,7 +104,6 @@ public interface TextMessages extends Messages {
String leaderboardQuickAccessLabel();
String mainEventShowAll();
String mainEventTitle();
String mainMediaShowMore();
String mainMediaSubtitle();
String mainMediaTitle();
String mainMediaVideosSubtitle();
@@ -88,12 +111,16 @@ public interface TextMessages extends Messages {
String mainSponsorsReadMore();
String mediaTeaserPhotosTitle();
String mediaTeaserVideosTitle();
String regattaIntroContentCompetitors();
String regattaIntroContentCourse();
String regattaIntroContentRaces();
String regattaIntroContentScoring();
String regattaIntroContentMethod();
String regattaIntroContentWindAvg();
String regattaCompetitors();
String regattaRaces();
String regattaTracked();
String regattaRegattaStarts();
String regattaPts();
String regattaCourse();
String regattaArea();
String regattaFinishedAt();
String regattaScheduledAt();
String regattaStartedAt();
String regattasResultsTitle();
String searchResultHeaderButton();
String searchResultHeaderLabel();
@@ -105,20 +132,26 @@ public interface TextMessages extends Messages {
String searchResultSortNewest();
String searchResultSortOldest();
String searchResultSortRelevance();
String searchResultCount();
String sharingEmail();
String sharingFacebook();
String sharingTwitter();
String socialFooterShare();
String socialFooterTitle();
String solutionsSAPNav();
String solutionsSAPHeadline();
String solutionsSAPText1();
String solutionsSAPText2();
String solutionsRaceNav();
String solutionsRaceHeadline();
String solutionsRaceText();
String solutionsPostNav();
String solutionsPostHeadline();
String solutionsPostText();
String solutionsTrainingNav();
String solutionsTrainingHeadline();
String solutionsTrainingText();
String solutionsSimulatorNav();
String solutionsSimulatorHeadline();
String solutionsSimulatorText();
}
@@ -15,6 +15,8 @@ countdownHours=Hours
countdownMinutes=Mins
countdownSeconds=Secs
live=Live
finished=Finished
watchNow=Watch now
lastUpdate=Last Update
leaderBoard=LeaderBoard
boxNewsUpdateMoreLink=Report news
@@ -32,11 +34,21 @@ boxWeatherUnit=KTS
defaultTitle=SAP Sailing Analytics
eventHeaderMedia=Media
eventHeaderOverview=Overview
eventHeaderRaces=Races
eventHeaderRaces=Schedule
eventHeaderRegattas=Regattas
eventHeaderSchedule=Schedule
seriesHeaderOverview=About the Series
seriesHeaderUpcoming=Upcoming Events
seriesHeaderRecent=Recent Events
seriesHeaderLeaderboard=Leaderboard
seriesOverviewHeaderRecent=Latest Series Events
seriesOverviewReadMore=More
eventsOverviewRecentEvents=Events
eventsOverviewRecentCountries=Countries
eventsOverviewRecentSailors=Sailors
eventsOverviewRecentTrackedRaces=Tracked Races
eventResultsHeadline=Winners and Results
eventResultsBoatClassesDropDown=All Boat Classes
eventOverviewMoreEvents=More Events
eventOverviewRecentEvents=Recent Events
eventOverviewUpcomingDate=Date
eventOverviewUpcomingEvent=Event
@@ -46,7 +58,8 @@ eventOverviewUpcomingSeries=Series
eventOverviewUpcomingTeaser=More Events To Be Announced Soon!
eventQuickfinderTitle=Event Quick-Finder
eventRegattaHeaderLeaderboard=Leaderboard
eventRegattaHeaderRaceSchedule=Race Schedule
eventRegattaHeaderRaceRaces=Races
eventRegattaListAllBoatClasses=All boat classes
eventRegattaLeaderboardCompetitor=Competitor
eventRegattaLeaderboardExtendLeaderboard=Extend Leaderboard
eventRegattaLeaderboardFinishedMessage=No more races
@@ -54,16 +67,27 @@ eventRegattaLeaderboardLastScoreUpdate=Last Score Update
eventRegattaLeaderboardName=Name
eventRegattaLeaderboardRegattaRank=Regatta Rank
eventRegattaLeaderboardTotalPoints=Total Points
eventRegattaRaceWatch=Watch live
eventRegattaRaceAnalyse=Analyze Race
eventRegattaRaceNotTracked=Not Tracked
eventRegattaRaceFinished=Finished at:
eventRegattaRaceStarted=Started at:
eventRegattaRaceScheduled=Scheduled for:
eventRegattaRacesLegendGps=Tracking
eventRegattaRacesLegendWind=Wind Data
eventRegattaRacesLegendVideo=Video Stream
eventRegattaRacesLegendAudio=Audio Stream
eventSponsorsTitle=Event Sponsorships
footerCopyright=\u00A9 2014 SAP Sailing Analytics
footerCopyright=© 2014 SAP Sailing Analytics
footerLanguage=SAP Sailing offered in
footerLegal=Legal Disclosure
footerPrivacy=Privacy
footerFeedback=Feedback
headerEvents=Events
headerHome=Home
headerLogo=SAP Sailing Analytics
headerSearch=Search
headerSearchPlaceholder=Search SAPSailing.com
headerSearchPlaceholder=Search
headerSolutions=Solutions
headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
@@ -75,7 +99,6 @@ latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
mainEventShowAll=Show All Events
mainEventTitle=Latest Events from the Sailing World
mainMediaShowMore=Show More
mainMediaSubtitle=Get lost in the latest and most beautiful impressions from your favorite sailing event.
mainMediaTitle=Sailing loves Photography
mainMediaVideosSubtitle=Immerse yourself in the world of sailing and check out our latest events for more videos.
@@ -83,12 +106,16 @@ mainMediaVideosTitle=Recent Video Entries
mainSponsorsReadMore=Read More
mediaTeaserPhotosTitle=Photos
mediaTeaserVideosTitle=Videos
regattaIntroContentCompetitors=Competitors
regattaIntroContentCourse=Course
regattaIntroContentRaces=Planned Races
regattaIntroContentScoring=Scoring
regattaIntroContentMethod=Method
regattaIntroContentWindAvg=Wind Average
regattaCompetitors=Competitors
regattaRaces=Races
regattaTracked=Tracked
regattaRegattaStarts=Regatta will start
regattaPts=Pts.
regattaCourse=Course
regattaArea=Area
regattaFinishedAt=Finished at
regattaScheduledAt=Scheduled at
regattaStartedAt=Started at
regattasResultsTitle=Winner and Results
searchResultHeaderButton=Search
searchResultHeaderLabel=Your Search
@@ -100,19 +127,25 @@ searchResultSortLabel=Sort by
searchResultSortNewest=Neueste
searchResultSortOldest=Älteste
searchResultSortRelevance=Relevance
searchResultCount=About 2,450 reslts where found for 'Schnitzel'
sharingEmail=Send an email
sharingFacebook=Share on Facebook
sharingTwitter=Tweet about it
socialFooterShare=Share this on
socialFooterTitle=Recommend SAP Sailing Analytics
solutionsSAPNav=SAP Sailing Analytics
solutionsSAPHeadline=SAP Sailing Analytics
solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.
solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.
solutionsRaceNav=Race Committee App
solutionsRaceHeadline=Race Committee App
solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.
solutionsPostNav=Post-Race Analytics
solutionsPostHeadline=Post-Race Analytics
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better. SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.<br> SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsTrainingNav=Training Diary
solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary
solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.
solutionsSimulatorNav=Strategy Simulator
solutionsSimulatorHeadline=Strategy Simulator
solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
@@ -15,6 +15,8 @@ countdownHours=Hours
countdownMinutes=Mins
countdownSeconds=Secs
live=Live
finished=Finished
watchNow=Watch now
lastUpdate=Last Update
leaderBoard=LeaderBoard
boxNewsUpdateMoreLink=Report news
@@ -32,11 +34,21 @@ boxWeatherUnit=KTS
defaultTitle=SAP Sailing Analytics
eventHeaderMedia=Media
eventHeaderOverview=Overview
eventHeaderRaces=Races
eventHeaderRaces=Schedule
eventHeaderRegattas=Regattas
eventHeaderSchedule=Schedule
seriesHeaderOverview=About the Series
seriesHeaderUpcoming=Upcoming Events
seriesHeaderRecent=Recent Events
seriesHeaderLeaderboard=Leaderboard
seriesOverviewHeaderRecent=Latest Series Events
seriesOverviewReadMore=More
eventsOverviewRecentEvents=Events
eventsOverviewRecentCountries=Countries
eventsOverviewRecentSailors=Sailors
eventsOverviewRecentTrackedRaces=Tracked Races
eventResultsHeadline=Winners and Results
eventResultsBoatClassesDropDown=All Boat Classes
eventOverviewMoreEvents=More Events
eventOverviewRecentEvents=Recent Events
eventOverviewUpcomingDate=Date
eventOverviewUpcomingEvent=Event
@@ -46,7 +58,8 @@ eventOverviewUpcomingSeries=Series
eventOverviewUpcomingTeaser=More Events To Be Announced Soon!
eventQuickfinderTitle=Event Quick-Finder
eventRegattaHeaderLeaderboard=Leaderboard
eventRegattaHeaderRaceSchedule=Race Schedule
eventRegattaHeaderRaceRaces=Races
eventRegattaListAllBoatClasses=All boat classes
eventRegattaLeaderboardCompetitor=Competitor
eventRegattaLeaderboardExtendLeaderboard=Extend Leaderboard
eventRegattaLeaderboardFinishedMessage=No more races
@@ -54,16 +67,27 @@ eventRegattaLeaderboardLastScoreUpdate=Last Score Update
eventRegattaLeaderboardName=Name
eventRegattaLeaderboardRegattaRank=Regatta Rank
eventRegattaLeaderboardTotalPoints=Total Points
eventRegattaRaceWatch=Watch live
eventRegattaRaceAnalyse=Analyze Race
eventRegattaRaceNotTracked=Not Tracked
eventRegattaRaceFinished=Finished at:
eventRegattaRaceStarted=Started at:
eventRegattaRaceScheduled=Scheduled for:
eventRegattaRacesLegendGps=Tracking
eventRegattaRacesLegendWind=Wind Data
eventRegattaRacesLegendVideo=Video Stream
eventRegattaRacesLegendAudio=Audio Stream
eventSponsorsTitle=Event Sponsorships
footerCopyright=\u00A9 2014 SAP Sailing Analytics
footerCopyright=© 2014 SAP Sailing Analytics
footerLanguage=SAP Sailing offered in
footerLegal=Legal Disclosure
footerPrivacy=Privacy
footerFeedback=Feedback
headerEvents=Events
headerHome=Home
headerLogo=SAP Sailing Analytics
headerSearch=Search
headerSearchPlaceholder=Search SAPSailing.com
headerSearchPlaceholder=Search
headerSolutions=Solutions
headerSponsoring=Sponsoring
latestRaceResultsHeadline=Latest Official Race Results
@@ -75,7 +99,6 @@ latestRaceResultsRefresh=refresh
leaderboardQuickAccessLabel=Leaderboard Quick Access
mainEventShowAll=Show All Events
mainEventTitle=Latest Events from the Sailing World
mainMediaShowMore=Show More
mainMediaSubtitle=Get lost in the latest and most beautiful impressions from your favorite sailing event.
mainMediaTitle=Sailing loves Photography
mainMediaVideosSubtitle=Immerse yourself in the world of sailing and check out our latest events for more videos.
@@ -83,12 +106,16 @@ mainMediaVideosTitle=Recent Video Entries
mainSponsorsReadMore=Read More
mediaTeaserPhotosTitle=Photos
mediaTeaserVideosTitle=Videos
regattaIntroContentCompetitors=Competitors
regattaIntroContentCourse=Course
regattaIntroContentRaces=Planned Races
regattaIntroContentScoring=Scoring
regattaIntroContentMethod=Method
regattaIntroContentWindAvg=Wind Average
regattaCompetitors=Competitors
regattaRaces=Races
regattaTracked=Tracked
regattaRegattaStarts=Regatta will start
regattaPts=Pts.
regattaCourse=Course
regattaArea=Area
regattaFinishedAt=Finished at
regattaScheduledAt=Scheduled at
regattaStartedAt=Started at
regattasResultsTitle=Winner and Results
searchResultHeaderButton=Search
searchResultHeaderLabel=Your Search
@@ -100,19 +127,25 @@ searchResultSortLabel=Sort by
searchResultSortNewest=Neueste
searchResultSortOldest=Älteste
searchResultSortRelevance=Relevance
searchResultCount=About 2,450 reslts where found for 'Schnitzel'
sharingEmail=Send an email
sharingFacebook=Share on Facebook
sharingTwitter=Tweet about it
socialFooterShare=Share this on
socialFooterTitle=Recommend SAP Sailing Analytics
solutionsSAPNav=SAP Sailing Analytics
solutionsSAPHeadline=SAP Sailing Analytics
solutionsSAPText1=By delivering real time analytics around race rankings, speeds, maneuvers, bearings etc., SAP is helping to simplify and demystify the complex sport of sailing.
solutionsSAPText2=SAP Sailing Analytics provide insights and transparency to the world of sailing by utilizing Cloud and In-Memory Technology, processing GPS and wind measurement data in real time and visualizing contents in various frontends accessible from anywhere.
solutionsRaceNav=Race Committee App
solutionsRaceHeadline=Race Committee App
solutionsRaceText=The SAP Race Committee App delivers greater efficiency and control to race organizers by automating and simplifying their manual tasks and communication during running sailing regattas. The Race Committee App helps simplify the operation of running and managing race events to help race committees operate smarter.
solutionsPostNav=Post-Race Analytics
solutionsPostHeadline=Post-Race Analytics
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better. SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsPostText=Access to data collected at sailing events gives sailors the opportunity to assess and analyse their performances to help develop strategies and sail better.<br> SAP Business Analytics solutions provide sailors, coaches, fans and media with tools to browse and analyse historical data across many regattas and races. SAP HANA allows them to learn about performance patterns, tendencies and sailor profiles in a simple, fast and efficient way in order to optimize their own performance and develop successful strategies for future regattas.
solutionsTrainingNav=Training Diary
solutionsTrainingHeadline=SAP Sail Better \u2013 STG Training Diary
solutionsTrainingText=The STG Training Diary supports the daily documentation and analysis of an athlete\u2019s physical condition and training efforts in the areas of water training, physical training, boat work, mental, theory as well as other activities like education or travel.
solutionsSimulatorNav=Strategy Simulator
solutionsSimulatorHeadline=Strategy Simulator
solutionsSimulatorText=Choosing the right strategy can provide great competitive advantage during a race. The Strategy Simulator simplifies determining the best sailing strategy for various wind conditions and water currents. Since wind and current can be changed in the simulation right away, the robustness of a strategy can be easily evaluated even for uncertain weather conditions.
@@ -1,5 +1,6 @@
package com.sap.sailing.gwt.home.client.place.event;
import java.util.List;
import java.util.UUID;
import com.google.gwt.activity.shared.AbstractActivity;
@@ -8,31 +9,59 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
public class EventActivity extends AbstractActivity {
private final EventClientFactory clientFactory;
private final EventPlace eventPlace;
private final Timer timerForClientServerOffset;
public EventActivity(EventPlace place, EventClientFactory clientFactory) {
this.clientFactory = clientFactory;
this.eventPlace = place;
timerForClientServerOffset = new Timer(PlayModes.Replay);
}
@Override
public void start(final AcceptsOneWidget panel, final EventBus eventBus) {
final long clientTimeWhenRequestWasSent = System.currentTimeMillis();
clientFactory.getSailingService().getEventById(UUID.fromString(eventPlace.getEventUuidAsString()), new AsyncCallback<EventDTO>() {
@Override
public void onSuccess(EventDTO event) {
final EventView view = clientFactory.createEventView(event);
panel.setWidget(view.asWidget());
public void onSuccess(final EventDTO event) {
clientFactory.getSailingService().getRegattaStructureForEvent(event.id, new AsyncCallback<List<RaceGroupDTO>>() {
@Override
public void onSuccess(List<RaceGroupDTO> raceGroups) {
for(LeaderboardGroupDTO leaderboardGroupDTO: event.getLeaderboardGroups()) {
final long clientTimeWhenResponseWasReceived = System.currentTimeMillis();
if (leaderboardGroupDTO.getAverageDelayToLiveInMillis() != null) {
timerForClientServerOffset.setLivePlayDelayInMillis(leaderboardGroupDTO.getAverageDelayToLiveInMillis());
}
timerForClientServerOffset.adjustClientServerOffset(clientTimeWhenRequestWasSent, leaderboardGroupDTO.getCurrentServerTime(), clientTimeWhenResponseWasReceived);
}
final EventView view = clientFactory.createEventView(event, raceGroups, eventPlace.getLeaderboardIdAsNameString(), timerForClientServerOffset);
panel.setWidget(view.asWidget());
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Shit happens");
}
});
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Shit happens");
}
});
});
}
}
@@ -1,8 +1,12 @@
package com.sap.sailing.gwt.home.client.place.event;
import java.util.List;
import com.sap.sailing.gwt.ui.client.SailingClientFactory;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sse.gwt.client.player.Timer;
public interface EventClientFactory extends SailingClientFactory {
EventView createEventView(EventDTO event);
EventView createEventView(EventDTO event, List<RaceGroupDTO> raceGroups, String leaderboardName, Timer timerForClientServerOffset);
}
@@ -1,5 +1,7 @@
package com.sap.sailing.gwt.home.client.place.event;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
public interface EventPageNavigator {
@@ -7,5 +9,7 @@ public interface EventPageNavigator {
void goToRegattas();
void goToSchedule();
void goToMedia();
void goToRegattaRaces(StrippedLeaderboardDTO leaderboard);
void goToRegattaRaces(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard);
void openRaceViewer(StrippedLeaderboardDTO leaderboard, RaceDTO race);
void openLeaderboardViewer(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard);
}
@@ -1,29 +1,39 @@
package com.sap.sailing.gwt.home.client.place.event;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceTokenizer;
import com.sap.sailing.gwt.home.client.AbstractBasePlace;
public class EventPlace extends Place {
public class EventPlace extends AbstractBasePlace {
private final String eventUuidAsString;
private final String leaderboardIdAsNameString;
public EventPlace(String eventUuidAsString) {
super();
this(eventUuidAsString, null);
}
public EventPlace(String eventUuidAsString, String leaderboardIdAsNameString) {
super("eventId", eventUuidAsString, "leaderboardName", leaderboardIdAsNameString);
this.eventUuidAsString = eventUuidAsString;
this.leaderboardIdAsNameString = leaderboardIdAsNameString;
}
public String getEventUuidAsString() {
return eventUuidAsString;
}
public String getLeaderboardIdAsNameString() {
return leaderboardIdAsNameString;
}
public static class Tokenizer implements PlaceTokenizer<EventPlace> {
@Override
public String getToken(EventPlace place) {
return place.getEventUuidAsString();
return place.getParametersAsToken();
}
@Override
public EventPlace getPlace(String eventUuidAsString) {
return new EventPlace(eventUuidAsString);
public EventPlace getPlace(String url) {
return new EventPlace(url);
}
}
}
@@ -1,13 +1,19 @@
package com.sap.sailing.gwt.home.client.place.event;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.gwt.core.client.GWT;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.RegattaAndRaceIdentifier;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.gwt.home.client.place.event.header.EventHeader;
import com.sap.sailing.gwt.home.client.place.event.media.EventMedia;
import com.sap.sailing.gwt.home.client.place.event.overview.EventOverview;
@@ -15,8 +21,15 @@ import com.sap.sailing.gwt.home.client.place.event.regattalist.EventRegattaList;
import com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaSchedule;
import com.sap.sailing.gwt.home.client.place.event.schedule.EventSchedule;
import com.sap.sailing.gwt.home.client.shared.eventsponsors.EventSponsors;
import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.raceboard.RaceBoardViewConfiguration;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RaceGroupDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class TabletAndDesktopEventView extends Composite implements EventView, EventPageNavigator {
private static EventViewUiBinder uiBinder = GWT.create(EventViewUiBinder.class);
@@ -35,10 +48,14 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E
private final List<Widget> pageElements;
public TabletAndDesktopEventView(EventDTO event) {
private final SailingServiceAsync sailingService;
public TabletAndDesktopEventView(SailingServiceAsync sailingService, EventDTO event, List<RaceGroupDTO> raceGroups, String leaderboardName,
Timer timerForClientServerOffset) {
this.sailingService = sailingService;
eventHeader = new EventHeader(event, this);
eventRegattaList = new EventRegattaList(event, this);
eventRegattaSchedule = new EventRegattaSchedule(event, this);
eventRegattaSchedule = new EventRegattaSchedule(event, timerForClientServerOffset, this);
eventOverview = new EventOverview(event);
eventSchedule = new EventSchedule(event);
eventMedia = new EventMedia(event);
@@ -46,36 +63,156 @@ public class TabletAndDesktopEventView extends Composite implements EventView, E
initWidget(uiBinder.createAndBindUi(this));
pageElements = Arrays.asList(new Widget[] { eventOverview, eventRegattaList, eventRegattaSchedule, eventMedia, eventSchedule });
setVisibleEventElement(eventOverview);
eventSponsors.setEventSponsors(event);
int leaderboardsCount = 0;
int leaderboardsGroupCount = event.getLeaderboardGroups().size();
for(LeaderboardGroupDTO leaderboardGroup: event.getLeaderboardGroups()) {
leaderboardsCount += leaderboardGroup.getLeaderboards().size();
}
if(leaderboardsGroupCount == 0 || leaderboardsCount == 0) {
Window.alert("There is no data available for this event.");
} else {
LeaderboardGroupDTO selectedLeaderboardGroup = null;
StrippedLeaderboardDTO selectedLeaderboard = null;
// find the preselected leaderboard (if one exist)
if (leaderboardName != null) {
for (LeaderboardGroupDTO leaderboardGroup : event.getLeaderboardGroups()) {
for (StrippedLeaderboardDTO leaderboard : leaderboardGroup.getLeaderboards()) {
if (leaderboard.name.equals(leaderboardName)) {
selectedLeaderboardGroup = leaderboardGroup;
selectedLeaderboard = leaderboard;
break;
}
}
}
}
// in case we only have one regatta/leaderboard we go directly to the 'races' page
if(selectedLeaderboard == null && leaderboardsCount == 1) {
for (LeaderboardGroupDTO leaderboardGroup : event.getLeaderboardGroups()) {
if(leaderboardGroup.getLeaderboards().size() > 0) {
selectedLeaderboard = leaderboardGroup.getLeaderboards().get(0);
selectedLeaderboardGroup = leaderboardGroup;
}
}
}
if(selectedLeaderboard != null && selectedLeaderboardGroup != null) {
goToRegattaRaces(selectedLeaderboardGroup, selectedLeaderboard);
} else {
goToRegattas();
}
if(event.getSponsorImageURLs() != null && event.getSponsorImageURLs().size() > 0) {
eventSponsors.setVisible(false);
eventSponsors.setEventSponsors(event.getSponsorImageURLs());
} else {
eventSponsors.setVisible(false);
eventSponsors.setEventSponsors(null);
}
}
}
@Override
public void goToOverview() {
setVisibleEventElement(eventOverview);
eventHeader.setDataNavigationType("normal");
}
@Override
public void goToRegattas() {
setVisibleEventElement(eventRegattaList);
eventHeader.setDataNavigationType("normal");
}
@Override
public void goToRegattaRaces(StrippedLeaderboardDTO leaderboard) {
setVisibleEventElement(eventRegattaSchedule);
public void goToRegattaRaces(final LeaderboardGroupDTO leaderboardGroup, final StrippedLeaderboardDTO leaderboard) {
switch (leaderboard.type) {
case RegattaLeaderboard:
sailingService.getRegattaByName(leaderboard.regattaName, new AsyncCallback<RegattaDTO>() {
@Override
public void onSuccess(RegattaDTO regatta) {
eventRegattaSchedule.setRacesFromRegatta(regatta, leaderboardGroup, leaderboard);
eventHeader.setDataNavigationType("compact");
setVisibleEventElement(eventRegattaSchedule);
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Shit happens");
}
});
break;
case FlexibleLeaderboard:
eventRegattaSchedule.setRacesFromFlexibleLeaderboard(leaderboardGroup, leaderboard);
eventHeader.setDataNavigationType("compact");
setVisibleEventElement(eventRegattaSchedule);
break;
case FlexibleMetaLeaderboard:
eventHeader.setDataNavigationType("compact");
setVisibleEventElement(eventRegattaSchedule);
break;
case RegattaMetaLeaderboard:
eventHeader.setDataNavigationType("compact");
setVisibleEventElement(eventRegattaSchedule);
break;
}
}
@Override
public void goToSchedule() {
setVisibleEventElement(eventSchedule);
eventHeader.setDataNavigationType("normal");
}
@Override
public void goToMedia() {
setVisibleEventElement(eventMedia);
eventHeader.setDataNavigationType("normal");
}
@Override
public void openRaceViewer(StrippedLeaderboardDTO leaderboard, RaceDTO race) {
RegattaAndRaceIdentifier raceIdentifier = race.getRaceIdentifier();
String link = EntryPointLinkFactory.createRaceBoardLink(createRaceBoardLinkParameters(leaderboard.name, raceIdentifier));
Window.open(link, "_blank", "");
}
@Override
public void openLeaderboardViewer(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard) {
String link = EntryPointLinkFactory.createLeaderboardLink(createLeaderboardLinkParameters(leaderboardGroup, leaderboard));
Window.open(link, "_blank", "");
}
private Map<String, String> createRaceBoardLinkParameters(String leaderboardName, RegattaAndRaceIdentifier raceIdentifier) {
Map<String, String> linkParams = new HashMap<String, String>();
linkParams.put("leaderboardName", leaderboardName);
linkParams.put("raceName", raceIdentifier.getRaceName());
linkParams.put(RaceBoardViewConfiguration.PARAM_CAN_REPLAY_DURING_LIVE_RACES, "true");
linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_MAPCONTROLS, "true");
linkParams.put(RaceBoardViewConfiguration.PARAM_VIEW_SHOW_NAVIGATION_PANEL, "true");
linkParams.put("regattaName", raceIdentifier.getRegattaName());
return linkParams;
}
private Map<String, String> createLeaderboardLinkParameters(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard) {
Map<String, String> linkParams = new HashMap<String, String>();
linkParams.put("name", leaderboard.name);
linkParams.put("showRaceDetails", "true");
linkParams.put("embedded", "true");
if (leaderboard.displayName != null) {
linkParams.put("displayName", leaderboard.displayName);
}
if(leaderboardGroup != null) {
linkParams.put("leaderboardGroupName", leaderboardGroup.getName());
}
return linkParams;
}
private void setVisibleEventElement(Widget visibleWidget) {
for (Widget element : pageElements) {
element.setVisible(element == visibleWidget);
@@ -1,6 +1,73 @@
/**
* The header of the pages to an event
*/
.dropdown {
font-size: 16px;
font-size: 1rem;
width: 18.75em;
max-width: 100%;
display: inline-block;
text-align: left;
}
.dropdown_head {
cursor: pointer;
display: block;
}
.dropdown_head_title {
cursor: pointer;
background: #f8f8f8;
color: #666;
height: 2.5625em;
line-height: 2.5em;
padding-left: 0.9375em;
font-weight: 700;
}
.dropdown_head_titlebutton {
float: right;
}
.dropdown_content {
position: absolute;
z-index: 1;
background: #f6f9fc;
display: none;
width: 18.75em;
height: auto;
max-height: 21.875em;
overflow: auto;
-webkit-box-shadow: 0 0.0625em 0.25em #ccc;
box-shadow: 0 0.0625em 0.25em #ccc;
border-bottom: solid 1px #ccc;
}
.dropdown_content_link {
display: block;
cursor: pointer;
padding: 1.25em 0.9375em;
border-bottom: 1px solid #ddd;
}
.dropdown_content_link:hover,
.dropdown_content_link:focus {
background: #f8f8f8;
text-decoration: none;
}
.dropdown_content_link:hover .dropdown_content_link_title,
.dropdown_content_link:focus .dropdown_content_link_title {
text-decoration: underline;
}
.dropdown_content_link_title {
color: #008fcc;
display: block;
font-weight: 700;
font-size: 1.125em;
}
.dropdown_content_link_subtitle {
color: #666;
font-size: 1em;
}
.leaderboardquickaccess {
font-size: 16px;
font-size: 1rem;
text-align: right;
}
.eventheaderwrapper {
font-size: 16px;
font-size: 1rem;
@@ -23,7 +90,7 @@
font-size: 16px;
font-size: 1rem;
background: #f2f2f2;
padding: 1.875em;
padding: 1.875em 0;
}
.eventheader_intro {
padding-left: 9.6875em;
@@ -56,7 +123,8 @@
.eventheader_intro_details_item {
display: inline-block;
border-right: 1px solid #ddd;
padding: 0.25em 0.625em;
padding: 0.25em 0.625em 0.25em 0;
margin-right: 0.625em;
}
.eventheader_intro_details_itemlink {
color: inherit;
@@ -64,9 +132,14 @@
.eventheader_intro_details_item:first-child {
padding-left: 0;
}
.eventheader_intro_details_item:nth-child\(2\) {
border: none;
}
.eventheader_intro_details_item:last-child {
border-right: none;
padding-right: 0;
display: block;
padding: 0;
border: none;
margin: 0;
}
.eventheader_sharing {
text-align: right;
@@ -134,7 +207,7 @@
}
.eventnavigationcompactfloating {
position: fixed;
top: -10em;
top: -5em;
left: 0;
right: 0;
z-index: 5;
@@ -1,8 +1,5 @@
package com.sap.sailing.gwt.home.client.place.event.header;
import java.util.Arrays;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.ImageElement;
@@ -11,7 +8,6 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
@@ -27,24 +23,25 @@ public class EventHeader extends Composite {
private final EventDTO event;
@UiField Anchor overviewLink;
@UiField Anchor regattasLink;
@UiField Anchor scheduleLink;
@UiField Anchor mediaLink;
@UiField Anchor overviewLink2;
@UiField Anchor regattasLink2;
@UiField Anchor scheduleLink2;
@UiField Anchor mediaLink2;
@UiField Anchor overviewLink3;
@UiField Anchor regattasLink3;
@UiField Anchor scheduleLink3;
@UiField Anchor mediaLink3;
// @UiField Anchor overviewLink;
@UiField Anchor regattasLink;
// @UiField Anchor scheduleLink;
// @UiField Anchor mediaLink;
//
// @UiField Anchor overviewLink2;
@UiField Anchor regattasLink2;
// @UiField Anchor scheduleLink2;
// @UiField Anchor mediaLink2;
//
// @UiField Anchor overviewLink3;
// @UiField Anchor regattasLink3;
// @UiField Anchor scheduleLink3;
// @UiField Anchor mediaLink3;
@UiField DivElement eventHeaderWrapperDiv;
@UiField SpanElement eventName;
@UiField SpanElement eventName2;
@UiField SpanElement eventName3;
// @UiField SpanElement eventName3;
@UiField SpanElement eventDate;
@UiField SpanElement eventDescription;
@UiField SpanElement venueName;
@@ -52,18 +49,13 @@ public class EventHeader extends Composite {
@UiField ImageElement eventLogo;
@UiField ImageElement eventLogo2;
@UiField ImageElement eventLogo3;
@UiField DivElement eventHeaderDiv;
@UiField DivElement eventNavigationNormalDiv;
@UiField DivElement eventNavigationCompactDiv;
@UiField DivElement eventNavigationFloatingDiv;
// @UiField ImageElement eventLogo3;
private final String defaultLogoUrl = "http://static.sapsailing.com/newhome/default_event_logo.png";
private final List<Anchor> links1;
private final List<Anchor> links2;
private final List<Anchor> links3;
// private final List<Anchor> links1;
// private final List<Anchor> links2;
// private final List<Anchor> links3;
private final EventPageNavigator pageNavigator;
@@ -74,20 +66,25 @@ public class EventHeader extends Composite {
EventHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
links1 = Arrays.asList(new Anchor[] { overviewLink, regattasLink, scheduleLink, mediaLink });
links2 = Arrays.asList(new Anchor[] { overviewLink2, regattasLink2, scheduleLink2, mediaLink2 });
links3 = Arrays.asList(new Anchor[] { overviewLink3, regattasLink3, scheduleLink3, mediaLink3 });
setActiveLink(links1, overviewLink);
setActiveLink(links2, overviewLink2);
setActiveLink(links3, overviewLink3);
// links1 = Arrays.asList(new Anchor[] { overviewLink, regattasLink, scheduleLink, mediaLink });
// links2 = Arrays.asList(new Anchor[] { overviewLink2, regattasLink2, scheduleLink2, mediaLink2 });
// links3 = Arrays.asList(new Anchor[] { overviewLink3, regattasLink3, scheduleLink3, mediaLink3 });
// setActiveLink(links1, overviewLink);
// setActiveLink(links2, overviewLink2);
// setActiveLink(links3, overviewLink3);
setDataNavigationType("normal");
updateUI();
}
public void setDataNavigationType(String dataNavigationType) {
eventHeaderWrapperDiv.setAttribute("data-navigationtype", dataNavigationType);
}
private void updateUI() {
eventName.setInnerHTML(event.getName());
eventName2.setInnerHTML(event.getName()+"2");
eventName3.setInnerHTML(event.getName()+"3");
eventName2.setInnerHTML(event.getName());
// eventName3.setInnerHTML(event.getName());
venueName.setInnerHTML(event.venue.getName());
eventDate.setInnerHTML(EventDatesFormatterUtil.formatDateRangeWithYear(event.startDate, event.endDate));
@@ -101,30 +98,30 @@ public class EventHeader extends Composite {
String logoUrl = event.getLogoImageURL() != null ? event.getLogoImageURL() : defaultLogoUrl;
eventLogo.setSrc(logoUrl);
eventLogo2.setSrc(logoUrl);
eventLogo3.setSrc(logoUrl);
// eventLogo3.setSrc(logoUrl);
}
@UiHandler("overviewLink")
void overviewClicked(ClickEvent event) {
showOverview();
}
// @UiHandler("overviewLink")
// void overviewClicked(ClickEvent event) {
// showOverview();
// }
//
// @UiHandler("overviewLink2")
// void overview2Clicked(ClickEvent event) {
// showOverview();
// }
//
// @UiHandler("overviewLink3")
// void overview3Clicked(ClickEvent event) {
// showOverview();
// }
@UiHandler("overviewLink2")
void overview2Clicked(ClickEvent event) {
showOverview();
}
@UiHandler("overviewLink3")
void overview3Clicked(ClickEvent event) {
showOverview();
}
private void showOverview() {
pageNavigator.goToOverview();
setActiveLink(links1, overviewLink);
setActiveLink(links2, overviewLink2);
setActiveLink(links3, overviewLink3);
}
// private void showOverview() {
// pageNavigator.goToOverview();
// setActiveLink(links1, overviewLink);
// setActiveLink(links2, overviewLink2);
// setActiveLink(links3, overviewLink3);
// }
@UiHandler("regattasLink")
void regattasClicked(ClickEvent event) {
@@ -136,61 +133,61 @@ public class EventHeader extends Composite {
showRegattas();
}
@UiHandler("regattasLink3")
void regattas3Clicked(ClickEvent event) {
showRegattas();
}
// @UiHandler("regattasLink3")
// void regattas3Clicked(ClickEvent event) {
// showRegattas();
// }
//
private void showRegattas() {
pageNavigator.goToRegattas();
setActiveLink(links1, regattasLink);
setActiveLink(links2, regattasLink2);
setActiveLink(links3, regattasLink3);
// setActiveLink(links1, regattasLink);
// setActiveLink(links2, regattasLink2);
// setActiveLink(links3, regattasLink3);
}
@UiHandler("scheduleLink")
void scheduleClicked(ClickEvent event) {
showSchedule();
}
@UiHandler("scheduleLink2")
void schedule2Clicked(ClickEvent event) {
showSchedule();
}
@UiHandler("scheduleLink3")
void schedule3Clicked(ClickEvent event) {
showSchedule();
}
private void showSchedule() {
pageNavigator.goToSchedule();
setActiveLink(links1, scheduleLink);
setActiveLink(links2, scheduleLink2);
setActiveLink(links3, scheduleLink3);
}
@UiHandler("mediaLink")
void mediaClicked(ClickEvent event) {
showMedia();
}
@UiHandler("mediaLink2")
void media2Clicked(ClickEvent event) {
showMedia();
}
@UiHandler("mediaLink3")
void media3Clicked(ClickEvent event) {
showMedia();
}
private void showMedia() {
pageNavigator.goToMedia();
setActiveLink(links1, mediaLink);
setActiveLink(links2, mediaLink2);
setActiveLink(links3, mediaLink3);
}
// @UiHandler("scheduleLink")
// void scheduleClicked(ClickEvent event) {
// showSchedule();
// }
//
// @UiHandler("scheduleLink2")
// void schedule2Clicked(ClickEvent event) {
// showSchedule();
// }
//
// @UiHandler("scheduleLink3")
// void schedule3Clicked(ClickEvent event) {
// showSchedule();
// }
//
// private void showSchedule() {
// pageNavigator.goToSchedule();
// setActiveLink(links1, scheduleLink);
// setActiveLink(links2, scheduleLink2);
// setActiveLink(links3, scheduleLink3);
// }
//
// @UiHandler("mediaLink")
// void mediaClicked(ClickEvent event) {
// showMedia();
// }
//
// @UiHandler("mediaLink2")
// void media2Clicked(ClickEvent event) {
// showMedia();
// }
//
// @UiHandler("mediaLink3")
// void media3Clicked(ClickEvent event) {
// showMedia();
// }
//
// private void showMedia() {
// pageNavigator.goToMedia();
// setActiveLink(links1, mediaLink);
// setActiveLink(links2, mediaLink2);
// setActiveLink(links3, mediaLink3);
// }
@Override
protected void onLoad() {
@@ -200,29 +197,29 @@ public class EventHeader extends Composite {
}
private void initNormalNavigation() {
Window.addWindowScrollHandler(new Window.ScrollHandler() {
public void onWindowScroll(Window.ScrollEvent event) {
int scrollY = Math.max(0, Window.getScrollTop());
int navNormalOffset = eventNavigationNormalDiv.getOffsetTop();
if (scrollY > navNormalOffset) {
eventNavigationFloatingDiv.addClassName(EventHeaderResources.INSTANCE.css().eventnavigationfixed());
} else {
eventNavigationFloatingDiv.removeClassName(EventHeaderResources.INSTANCE.css()
.eventnavigationfixed());
}
}
});
// Window.addWindowScrollHandler(new Window.ScrollHandler() {
// public void onWindowScroll(Window.ScrollEvent event) {
// int scrollY = Math.max(0, Window.getScrollTop());
// int navNormalOffset = eventNavigationNormalDiv.getOffsetTop();
//
// if (scrollY > navNormalOffset) {
// eventNavigationFloatingDiv.addClassName(EventHeaderResources.INSTANCE.css().eventnavigationfixed());
// } else {
// eventNavigationFloatingDiv.removeClassName(EventHeaderResources.INSTANCE.css()
// .eventnavigationfixed());
// }
// }
// });
}
private void setActiveLink(List<Anchor> linksToSet, Anchor link) {
final String activeStyle = EventHeaderResources.INSTANCE.css().eventnavigation_linkactive();
for (Anchor l : linksToSet) {
if (l == link) {
l.addStyleName(activeStyle);
} else {
l.removeStyleName(activeStyle);
}
}
}
// private void setActiveLink(List<Anchor> linksToSet, Anchor link) {
// final String activeStyle = EventHeaderResources.INSTANCE.css().eventnavigation_linkactive();
// for (Anchor l : linksToSet) {
// if (l == link) {
// l.addStyleName(activeStyle);
// } else {
// l.removeStyleName(activeStyle);
// }
// }
// }
}
@@ -7,14 +7,14 @@
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.header.EventHeaderResources" />
<g:HTMLPanel>
<!-- The header of an event including the event navigation-->
<div data-navigationtype="normal" class="{local_res.css.eventheaderwrapper}">
<div ui:field='eventHeaderDiv' class="{local_res.css.eventheader}">
<!-- The header of an event including the event navigation-->
<div ui:field="eventHeaderWrapperDiv" data-navigationtype="normal" class="{local_res.css.eventheaderwrapper}">
<div class="{local_res.css.eventheader}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small8} {res.mediaCss.columns}">
<div class="{res.mediaCss.small9} {res.mediaCss.large8} {res.mediaCss.columns}">
<div class="{local_res.css.eventheader_intro}"><img ui:field='eventLogo' alt="" height="140" width="140" class="{local_res.css.eventheader_intro_logo}"></img>
<h3 class="{local_res.css.eventheader_intro_name}"><span ui:field='eventName' /></h3>
<div data-labeltype="live" class="{res.mainCss.label}">Live</div>
<div data-labeltype="live" class="{res.mainCss.label}"><ui:text from='{i18n.live}'/></div>
<div class="{local_res.css.eventheader_intro_details}">
<div class="{local_res.css.eventheader_intro_details_item}"><span ui:field='eventDate'/></div>
<div class="{local_res.css.eventheader_intro_details_item}"><img src="images/location-icon.png" class="{local_res.css.locationicon}"></img><span ui:field='venueName' />
@@ -23,74 +23,29 @@
<div class="{local_res.css.eventheader_intro"><span ui:field='eventDescription'/></div>
</div>
</div>
<div class="{res.mediaCss.small4} {res.mediaCss.columns}">
<div class="{local_res.css.eventheader_sharing}">
<a href="mailto:hello@example.de" title="Send an email" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itememail}"></a>
<a href="https://twitter.com/event" title="Tweet about it" target="_blank" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemtwitter}"></a>
<a href="https://facebook.com/event" title="Share on facebook" target="_blank" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemfacebook}"></a>
</div>
<div class="{res.mediaCss.small3} {res.mediaCss.large4} {res.mediaCss.columns}">
<div class="{local_res.css.eventheader_sharing}"><a href="mailto:hello@example.de" title="{i18n.sharingEmail}" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itememail}"></a><a href="https://twitter.com/event" title="{i18n.sharingTwitter}" target="_blank" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemtwitter}"></a><a href="https://facebook.com/event" title="{i18n.sharingFacebook}" target="_blank" class="{local_res.css.eventheader_sharing_item} {local_res.css.eventheader_sharing_itemfacebook}"></a></div>
</div>
</div>
</div>
<div ui:field="eventNavigationNormalDiv" class="{local_res.css.eventnavigation} {local_res.css.eventnavigationnormal}">
<div class="{local_res.css.eventnavigation} {local_res.css.eventnavigationcompact}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<g:Anchor ui:field="overviewLink" text="Overview" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="regattasLink" text="Regattas" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="scheduleLink" text="Schedule" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="mediaLink" text="Media" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<!--
<a href="series-overview.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Overview</a>
<a href="series-races.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Races</a>
<a href="series-media.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Media</a>
-->
<div class="{res.mediaCss.columns}">
<g:Anchor ui:field="regattasLink">
<img ui:field='eventLogo2' alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img>
</g:Anchor>
<g:Anchor ui:field="regattasLink2" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}"><span ui:field='eventName2' /></g:Anchor>
</div>
</div>
</div>
<div ui:field="eventNavigationCompactDiv" class="{local_res.css.eventnavigation} {local_res.css.eventnavigationcompact}">
<!--
<div class="{local_res.css.eventnavigation} {local_res.css.eventnavigationcompactfloating}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<a href="event-overview.html">
<img ui:field='eventLogo2' alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img>
</a>
<g:Anchor ui:field="overviewLink2" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}"><span ui:field='eventName2' /></g:Anchor>
<g:Anchor ui:field="regattasLink2" text="Regattas" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="scheduleLink2" text="Schedule" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="mediaLink2" text="Media" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<!--
<a href="series-overview.html">
<img src="images/{event.logo}" alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img>
</a>
<a href="series-overview.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">{event.name}</a>
<a href="series-races.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Races</a>
<a href="series-media.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Media</a>
-->
</div>
</div>
</div>
<div ui:field="eventNavigationFloatingDiv" class="{local_res.css.eventnavigation} {local_res.css.eventnavigationcompactfloating}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<!-- event -->
<a href="event-overview.html">
<img ui:field='eventLogo3' alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img>
</a>
<g:Anchor ui:field="overviewLink3" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}"><span ui:field='eventName3' /></g:Anchor>
<g:Anchor ui:field="regattasLink3" text="Regattas" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="scheduleLink3" text="Schedule" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<g:Anchor ui:field="mediaLink3" text="Media" styleName="{res.mainCss.button} {local_res.css.eventnavigation_link}" />
<!-- series -->
<!--
<a href="series-overview.html">
<img src="images/eventlogo.jpg" alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img>
</a>
<a href="series-overview.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">{event.name}</a>
<a href="series-races.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Races</a>
<a href="series-media.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">Media</a>
-->
</div>
<div class="{res.mediaCss.columns}">{#if navigation.isEvent}<a href="event-overview.html"><img src="images/{event.logo}" alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img></a><a href="event-overview.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">{event.name}</a>{/if navigation.isEvent}{#if navigation.isSeries}<a href="series-overview.html"><img src="images/{event.logo}" alt="" height="41" width="41" class="{local_res.css.eventnavigationcompact_logo}"></img></a><a href="series-overview.html" class="{res.mainCss.button} {local_res.css.eventnavigation_link}">{event.name}</a>
</div></s>
</div>
</div>
-->
</div>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
@@ -11,6 +11,15 @@ public interface EventHeaderResources extends ClientBundle {
LocalCss css();
public interface LocalCss extends CssResource {
String dropdown();
String dropdown_head();
String dropdown_head_title();
String dropdown_head_titlebutton();
String dropdown_content();
String dropdown_content_link();
String dropdown_content_link_title();
String dropdown_content_link_subtitle();
String leaderboardquickaccess();
String eventheaderwrapper();
String eventheader();
String eventnavigationnormal();
@@ -74,97 +74,6 @@
.columns .latestraceresults_detail_wrapperimage {
max-width: none;
}
.lightbox {
font-size: 16px;
font-size: 1rem;
}
.lightbox_overlay {
font-size: 16px;
font-size: 1rem;
background: #000;
opacity: 0.7;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: literal("alpha(opacity=70)");
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 2000;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
}
.lightbox_overlayhidden {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.lightbox_content {
position: fixed;
width: 100%;
height: 100%;
opacity: 1;
-ms-filter: none;
filter: none;
top: 0;
left: 0;
z-index: 2001;
background-repeat: no-repeat;
background-position: center center;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
}
.lightbox_contenthidden {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.lightbox_content_enlargedimage {
-webkit-transition: margin 0.7s linear;
-moz-transition: margin 0.7s linear;
-o-transition: margin 0.7s linear;
-ms-transition: margin 0.7s linear;
transition: margin 0.7s linear;
display: inline-block;
position: absolute;
left: 50%;
top: 50%;
}
.lightbox_content_enlargedimage_caption {
text-align: center;
color: #f6f9fc;
font-weight: 700;
}
.lightbox_content_enlargedimage_close {
display: inline-block;
background-image: url("../images/x_lightbox.png");
background-repeat: no-repeat;
background-position: center center;
width: 1.25em;
height: 0;
overflow: hidden;
padding-top: 1.25em;
position: absolute;
top: 1.25em;
right: 1.25em;
cursor: pointer;
z-index: 2003;
}
.lightbox_content .media_slideshow_controls {
z-index: 2002;
}
.lightbox_data {
display: none;
}
.lightbox_photo {
cursor: pointer;
}
.mediateaser {
font-size: 16px;
font-size: 1rem;
@@ -29,17 +29,6 @@ public interface EventOverviewResources extends ClientBundle {
String latestraceresults_detail_datetime();
String columns();
String latestraceresults_detail_wrapperimage();
String lightbox();
String lightbox_overlay();
String lightbox_overlayhidden();
String lightbox_content();
String lightbox_contenthidden();
String lightbox_content_enlargedimage();
String lightbox_content_enlargedimage_caption();
String lightbox_content_enlargedimage_close();
String media_slideshow_controls();
String lightbox_data();
String lightbox_photo();
String mediateaser();
String mediateaser_title();
String mediateaser_title_link();
@@ -52,15 +52,12 @@
.regattalink:hover .regatta_intro_image {
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: alpha(opacity=90);
filter: literal("alpha(opacity=90)");
}
.regattalink:hover .regatta_intro_header_name {
text-decoration: underline;
}
.regattalink:nth-child(even) {
.regattalink:nth-child\(even\) {
background-color: #f8f8f8;
}
.regattalink:nth-child(even):hover {
.regattalink:nth-child\(even\):hover {
background-color: #f3f3f3;
}
.regatta_intro {
@@ -81,8 +78,9 @@
}
.regatta_intro_header {
margin-bottom: 0.625em;
padding-top: 0.3125em;
padding-bottom: 0.625em;
border-bottom: 1px solid #f2f2f2;
border-bottom: 1px solid #d9d9d9;
position: relative;
}
.regatta_intro_header_logo {
@@ -90,11 +88,12 @@
}
.regatta_intro_header_name {
display: inline-block;
font-size: 1.125em;
font-size: 1.25em;
margin: 0;
margin-left: 0.25em;
padding-left: 0.5em;
border-left: 1px solid #f2f2f2;
margin-right: 0.25em;
}
.regatta_intro_header_name:hover {
text-decoration: underline;
}
.regatta_intro_header_labels {
display: inline-block;
@@ -106,11 +105,12 @@
vertical-align: baseline;
}
.regatta_intro_races {
min-height: 3.75em;
position: relative;
min-height: 1.875em;
margin-bottom: 0.625em;
padding-bottom: 0.625em;
padding-left: 0.3125em;
border-bottom: 1px solid #f2f2f2;
border-bottom: 1px solid #d9d9d9;
}
.regatta_intro_races_race {
display: inline-block;
@@ -127,11 +127,24 @@
.regatta_intro_races_race[data-finished='data-finished'] {
background-color: #f0ab00;
}
.regatta_intro_meta {
position: relative;
font-weight: 600;
}
.regatta_intro_meta_scoring {
color: #008fcc;
display: inline-block;
}
.regatta_intro_meta_leaderboardlink {
position: absolute;
top: 0;
right: 0;
text-transform: uppercase;
line-height: 2.8125em;
}
.regatta_intro_details {
font-size: 0.875em;
font-weight: 600;
color: #666;
text-transform: uppercase;
}
.regatta_intro_details_item {
display: inline-block;
@@ -143,10 +156,6 @@
.regatta_intro_details_item_sub {
display: inline;
}
.regatta_intro_details_item_sub:after {
content: ' | ';
display: inline;
}
.regatta_intro_details_item_sub:last-child:after {
content: '';
}
@@ -1,10 +1,21 @@
package com.sap.sailing.gwt.home.client.place.event.regattaheader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class EventRegattaHeader extends Composite {
private static EventRegattaHeaderUiBinder uiBinder = GWT.create(EventRegattaHeaderUiBinder.class);
@@ -14,12 +25,49 @@ public class EventRegattaHeader extends Composite {
@SuppressWarnings("unused")
private final EventDTO event;
public EventRegattaHeader(EventDTO event) {
private final Timer timerForClientServerOffset;
private final EventPageNavigator pageNavigator;
private StrippedLeaderboardDTO leaderboard;
@UiField SpanElement regattaName;
@UiField SpanElement leaderboardGroupName;
@UiField SpanElement regattaPhase;
@UiField SpanElement competitorsCount;
@UiField DivElement isLiveDiv;
@UiField Anchor leaderboardLink;
public EventRegattaHeader(EventDTO event, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
this.event = event;
this.timerForClientServerOffset = timerForClientServerOffset;
this.pageNavigator = pageNavigator;
EventRegattaHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
public void setData(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard) {
this.leaderboard = leaderboard;
boolean hasLiveRace = leaderboard.hasLiveRace(timerForClientServerOffset.getLiveTimePointInMillis());
isLiveDiv.setAttribute("data-labeltype", hasLiveRace ? "live" : "");
regattaName.setInnerText(leaderboard.displayName != null ? leaderboard.displayName : leaderboard.name);
leaderboardGroupName.setInnerText(leaderboardGroup.getName());
if(leaderboard.rows != null) {
competitorsCount.setInnerText(String.valueOf(leaderboard.rows.size()));
} else {
competitorsCount.getStyle().setVisibility(Visibility.HIDDEN);
}
regattaPhase.setInnerText(calculateCurrentRegattaPhase(leaderboard));
}
private String calculateCurrentRegattaPhase(StrippedLeaderboardDTO leaderboard) {
return "";
}
@UiHandler("leaderboardLink")
public void goToLeaderboard(ClickEvent e) {
pageNavigator.openLeaderboardViewer(null, leaderboard);
}
}
@@ -8,43 +8,47 @@
<g:HTMLPanel>
<!-- The regatta header contains basic regatta information and the regatta navigation-->
<!-- A view, introducing a regatta-->
<!--
<div class="{local_res.css.eventregattaheader}">
<div class="{local_res.css.regatta}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<div class="{local_res.css.regatta_intro}"><img src="images/{regatta.image}" alt="{regatta.name}" height="140" width="140" class="{local_res.css.regatta_intro_image}"></img>
<div class="{local_res.css.regatta_intro_header}"><img src="images/{regatta.logo}" alt="" class="{local_res.css.regatta_intro_header_logo}"></img>
<h3 class="{local_res.css.regatta_intro_header_name}">{regatta.name}</h3>
<div class="{local_res.css.regatta_intro_header_labels}">{#if regatta.isLive}
<div data-labeltype="live" class="{res.mainCss.label}"><ui:text from='{i18n.live}'/></div>{/if regatta.isLive}{#if regatta.series}
<div data-labeltype="{regatta.series.id}" class="{res.mainCss.label}">{regatta.series.name}</div>{/if regatta.series}
<div class="{local_res.css.regatta_intro}"><img src="images/home/regatta-boatclass_sample.png" alt="" height="140" width="140" class="{local_res.css.regatta_intro_image}"></img>
<div class="{local_res.css.regatta_intro_header}">
<g:Anchor ui:field="regattaRacesLink">
<h3 class="{local_res.css.regatta_intro_header_name}"><span ui:field="regattaName" /></h3>
<div ui:field="isLiveDiv" data-labeltype="" class="{res.mainCss.label}"><ui:text from='{i18n.live}'/></div>
</g:Anchor>
<div class="{local_res.css.regatta_intro_header_labels}">
<div data-labeltype="ess" class="{res.mainCss.label}"><span ui:field="leaderboardGroupName" /></div>
</div>
</div>
<div class="{local_res.css.regatta_intro_meta}">Phase
<div class="{local_res.css.regatta_intro_meta_scoring}"><span ui:field="regattaPhase" />
</div>
<div class="{local_res.css.regatta_intro_meta_leaderboardlink}">
<g:Anchor ui:field="leaderboardLink">Leaderboard</g:Anchor>
</div>
</div>
<div class="{local_res.css.regatta_intro_races}">
<div data-finished="{race.finished}" class="{local_res.css.regatta_intro_races_race}"></div>
<div data-finished="race.finished" class="{local_res.css.regatta_intro_races_race}"></div>
</div>
<div class="{local_res.css.regatta_intro_details}">
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><span class="{local_res.css.regatta_intro_details_item_value}">{regatta.racesCount}</span>&nbsp;<ui:text from='{i18n.regattaIntroContentRaces}'/></div>
<div class="{local_res.css.regatta_intro_details_item_sub}"><span class="{local_res.css.regatta_intro_details_item_value}">{regatta.competitorsCount}</span>&nbsp;<ui:text from='{i18n.regattaIntroContentCompetitors}'/></div>
<div class="{local_res.css.regatta_intro_details_item_sub}">&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="competitorsCount" /></span></div>
</div>
<div class="{local_res.css.regatta_intro_details_item} {local_res.css.regatta_intro_details_itemhideoncompact}">
<div class="{local_res.css.regatta_intro_details_item_sub}">{feature}
</div>
</div>
<div class="{local_res.css.regatta_intro_details_item} {local_res.css.regatta_intro_details_itemhideoncompact}"><ui:text from='{i18n.regattaIntroContentCourse}'/>:&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}">{regatta.course}</span></div>
<div class="{local_res.css.regatta_intro_details_item}"><ui:text from='{i18n.lastUpdate}'/>:&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}">{regatta.lastUpdate}</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
<div class="{local_res.css.regattanavigation}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}"><a href="event-regatta-schedule.html" class="{local_res.css.regattanavigation_link}"><ui:text from='{i18n.eventRegattaHeaderRaceSchedule}'/></a><a href="event-regatta-leaderboard.html" class="{local_res.css.regattanavigation_link}"><ui:text from='{i18n.eventRegattaHeaderLeaderboard}'/></a></div>
<div class="{res.mediaCss.small12} {res.mediaCss.columns}"><a href="event-regatta-schedule.html" class="{local_res.css.regattanavigation_link}"><ui:text from='{i18n.eventRegattaHeaderRaceSchedule}'/></a>
</div>
</div>
</div>
-->
@@ -20,14 +20,17 @@ public interface EventRegattaHeaderResources extends ClientBundle {
String regatta_intro_details_itemhideoncompact();
String regattalink();
String regatta_intro_image();
String regatta_intro_header_name();
String regatta_intro();
String regatta_intro_header();
String regatta_intro_header_logo();
String regatta_intro_header_name();
String regatta_intro_header_labels();
String label();
String regatta_intro_races();
String regatta_intro_races_race();
String regatta_intro_meta();
String regatta_intro_meta_scoring();
String regatta_intro_meta_leaderboardlink();
String regatta_intro_details();
String regatta_intro_details_item();
String regatta_intro_details_item_sub();
@@ -7,8 +7,7 @@
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattalist.EventRegattaListResources" />
<g:HTMLPanel>
<div class="{local_res.css.eventregattalist}">
<g:HTMLPanel ui:field="regattaListItemPanel">
</g:HTMLPanel>
<g:HTMLPanel ui:field="regattaListItemPanel" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -3,6 +3,7 @@ package com.sap.sailing.gwt.home.client.place.event.regattalist;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
@@ -23,22 +24,16 @@ public class EventRegattaListItem extends Composite {
@UiField SpanElement regattaName;
@UiField SpanElement leaderboardGroupName;
@UiField SpanElement competitorsCount;
@UiField SpanElement boatDesign;
@UiField SpanElement scoringSystem;
@UiField SpanElement averageWind;
@UiField SpanElement plannedRacesCount;
@UiField SpanElement regattaSeriesName;
@UiField SpanElement regattaPhase;
@UiField DivElement isLiveElement;
@UiField Anchor regattaRacesLink;
@SuppressWarnings("unused")
private RegattaDTO regatta;
private final LeaderboardGroupDTO leaderboardGroup;
private final StrippedLeaderboardDTO leaderboard;
private final LeaderboardGroupDTO leaderboardGroup;
private final EventPageNavigator pageNavigator;
public EventRegattaListItem(EventPageNavigator pageNavigator, LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO leaderboard) {
@@ -49,23 +44,24 @@ public class EventRegattaListItem extends Composite {
EventRegattaListResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
updateUI();
regattaName.setInnerText(leaderboard.displayName != null ? leaderboard.displayName : leaderboard.name);
leaderboardGroupName.setInnerText(leaderboardGroup.getName());
if(leaderboard.rows != null) {
competitorsCount.setInnerText(String.valueOf(leaderboard.rows.size()));
} else {
competitorsCount.getStyle().setVisibility(Visibility.HIDDEN);
}
}
@UiHandler("regattaRacesLink")
public void goToRegattaRaces(ClickEvent e) {
pageNavigator.goToRegattaRaces(leaderboard);
pageNavigator.goToRegattaRaces(leaderboardGroup, leaderboard);
}
@UiHandler("leaderboardLink")
public void goToLeaderboard(ClickEvent e) {
pageNavigator.openLeaderboardViewer(leaderboardGroup, leaderboard);
}
private void updateUI() {
regattaName.setInnerText(leaderboard.displayName != null ? leaderboard.displayName : leaderboard.name);
leaderboardGroupName.setInnerText(leaderboardGroup.getName());
competitorsCount.setInnerText("XYZ");
boatDesign.setInnerText("XYZ");
scoringSystem.setInnerText("XYZ");
averageWind.setInnerText("XYZ");
plannedRacesCount.setInnerText("XYZ");
regattaSeriesName.setInnerText("ABC");
}
}
@@ -20,28 +20,18 @@
</div>
</div>
<div class="{local_res.css.regatta_intro_meta}">Phase
<div class="{local_res.css.regatta_intro_meta_scoring}"><span ui:field="regattaSeriesName" />
<div class="{local_res.css.regatta_intro_meta_scoring}"><span ui:field="regattaPhase" />
</div>
<div class="{local_res.css.regatta_intro_meta_leaderboardlink}">
<g:Anchor ui:field="leaderboardLink">Leaderboard</g:Anchor>
</div>
<div class="{local_res.css.regatta_intro_meta_leaderboardlink}"><a href="">Leaderboard</a></div>
</div>
<div class="{local_res.css.regatta_intro_races}">
<div data-finished="race.finished" class="{local_res.css.regatta_intro_races_race}"></div>
</div>
<div class="{local_res.css.regatta_intro_details}">
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><ui:text from='{i18n.regattaIntroContentCompetitors}'/>&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="competitorsCount" /></span></div>
</div>
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><ui:text from='{i18n.regattaIntroContentMethod}'/>&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="boatDesign" /></span></div>
</div>
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><ui:text from='{i18n.regattaIntroContentScoring}'/>&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="scoringSystem" /></span></div>
</div>
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><ui:text from='{i18n.regattaIntroContentWindAvg}'/>&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="averageWind" /></span></div>
</div>
<div class="{local_res.css.regatta_intro_details_item}">
<div class="{local_res.css.regatta_intro_details_item_sub}"><ui:text from='{i18n.regattaIntroContentRaces}'/>&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="plannedRacesCount" /></span></div>
<div class="{local_res.css.regatta_intro_details_item_sub}">&nbsp;<span class="{local_res.css.regatta_intro_details_item_value}"><span ui:field="competitorsCount" /></span></div>
</div>
</div>
</div>
@@ -2,10 +2,18 @@ package com.sap.sailing.gwt.home.client.place.event.regattaschedule;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator;
import com.sap.sailing.gwt.home.client.place.event.regattaheader.EventRegattaHeader;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.RegattaDTO;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class EventRegattaSchedule extends Composite {
private static EventRegattaScheduleUiBinder uiBinder = GWT.create(EventRegattaScheduleUiBinder.class);
@@ -13,14 +21,40 @@ public class EventRegattaSchedule extends Composite {
interface EventRegattaScheduleUiBinder extends UiBinder<Widget, EventRegattaSchedule> {
}
@UiField(provided=true) EventRegattaHeader regattaHeader;
@UiField HTMLPanel seriesListPanel;
@SuppressWarnings("unused")
private final EventDTO event;
public EventRegattaSchedule(EventDTO event, EventPageNavigator pageNavigator) {
private final Timer timerForClientServerOffset;
private final EventPageNavigator pageNavigator;
public EventRegattaSchedule(EventDTO event, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
this.event = event;
this.timerForClientServerOffset = timerForClientServerOffset;
this.pageNavigator = pageNavigator;
regattaHeader = new EventRegattaHeader(event, timerForClientServerOffset, pageNavigator);
EventRegattaScheduleResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
public void setRacesFromRegatta(RegattaDTO regatta, LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO regattaLeaderboard) {
regattaHeader.setData(leaderboardGroup, regattaLeaderboard);
for(SeriesDTO series: regatta.series) {
EventRegattaScheduleSeries eventRegattaScheduleSeries = new EventRegattaScheduleSeries(regattaLeaderboard, series, timerForClientServerOffset, pageNavigator);
seriesListPanel.add(eventRegattaScheduleSeries);
}
}
public void setRacesFromFlexibleLeaderboard(LeaderboardGroupDTO leaderboardGroup, StrippedLeaderboardDTO flexibleLeaderboard) {
regattaHeader.setData(leaderboardGroup, flexibleLeaderboard);
EventRegattaScheduleFleet eventRegattaScheduleFleet = new EventRegattaScheduleFleet(flexibleLeaderboard, timerForClientServerOffset, pageNavigator);
seriesListPanel.add(eventRegattaScheduleFleet);
}
}
@@ -1,30 +1,19 @@
<!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:s="urn:import:com.sap.sailing.gwt.home.client.place.event">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaScheduleResources" />
<g:HTMLPanel>
<!-- The schedule of races for a day-->
<h3>Races of regatta xyz</h3>
<!--
<s:regattaheader.EventRegattaHeader ui:field="regattaHeader" />
<div class="{local_res.css.eventregattaschedule}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">{#each series in regatta.series}
<div class="{local_res.css.eventregattaschedule_series}">
<h3 class="{local_res.css.eventregattaschedule_series_name}">{series.name}</h3><span class="{local_res.css.eventregattaschedule_series_date}">{series.date}</span>{#each fleet in series.trackedRaces.fleets}
<div class="{local_res.css.eventregattaschedule_series_fleet}">{#if series.trackedRaces.fleets.length &gt; 1}
<div data-racescount="{fleet.races.length}" style="background-color:rgb({fleet.color.r},{fleet.color.g},{fleet.color.b})" class="{local_res.css.eventregattaschedule_series_fleet_name}">{fleet.name}
</div>{/if series.trackedRaces.fleets.length &gt; 1}{#each race in fleet.races}{#if race.isTracked}<a href="{race.link}" data-live="{race.isLive}" data-upcoming="{race.isUpcoming}" class="{local_res.css.eventregattaschedule_series_fleet_race} {local_res.css.eventregattaschedule_series_fleet_racetracked}">
<div class="{local_res.css.eventregattaschedule_series_fleet_race_name}">{race.name}</div>
<div class="{local_res.css.eventregattaschedule_series_fleet_race_details}">{race.details}</div></a>{/if race.isTracked}{/each fleet.races}
</div>{/each series.trackedRaces.fleets}
</div>{/each regatta.series}
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<g:HTMLPanel ui:field="seriesListPanel" />
</div>
</div>
</div>
-->
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,85 @@
package com.sap.sailing.gwt.home.client.place.event.regattaschedule;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.LeaderboardNameConstants;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class EventRegattaScheduleFleet extends Composite {
private static EventRegattaScheduleSeriesUiBinder uiBinder = GWT.create(EventRegattaScheduleSeriesUiBinder.class);
interface EventRegattaScheduleSeriesUiBinder extends UiBinder<Widget, EventRegattaScheduleFleet> {
}
private final FleetDTO fleet;
@UiField DivElement fleetDiv;
@UiField SpanElement fleetName;
@UiField HTMLPanel racesListPanel;
public EventRegattaScheduleFleet(StrippedLeaderboardDTO leaderboard, SeriesDTO series, FleetDTO fleet,
Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
this.fleet = fleet;
EventRegattaScheduleResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
// if(!fleet.getName().equals(LeaderboardNameConstants.DEFAULT_FLEET_NAME)) {
// fleetName.setInnerText(fleet.getName());
// fleetDiv.getStyle().setBackgroundColor(fleet.getColor().getAsHtml());
// }
List<RaceColumnDTO> racesOfFleet = getRacesOfFleet(leaderboard, series, fleet);
for(RaceColumnDTO raceColumn: racesOfFleet) {
EventRegattaScheduleRace eventRegattaScheduleRace = new EventRegattaScheduleRace(leaderboard, fleet, raceColumn, timerForClientServerOffset, pageNavigator);
racesListPanel.add(eventRegattaScheduleRace);
}
}
public EventRegattaScheduleFleet(StrippedLeaderboardDTO leaderboard, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
this.fleet = new FleetDTO(LeaderboardNameConstants.DEFAULT_FLEET_NAME, 0, null);
EventRegattaScheduleResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
fleetName.setInnerText("Races");
// fleetDiv.getStyle().setBackgroundColor(fleet.getColor().getAsHtml());
List<RaceColumnDTO> racesOfFleet = leaderboard.getRaceList();
for(RaceColumnDTO raceColumn: racesOfFleet) {
EventRegattaScheduleRace eventRegattaScheduleRace = new EventRegattaScheduleRace(leaderboard, fleet, raceColumn, timerForClientServerOffset, pageNavigator);
racesListPanel.add(eventRegattaScheduleRace);
}
}
private List<RaceColumnDTO> getRacesOfFleet(StrippedLeaderboardDTO leaderboard, SeriesDTO series, FleetDTO fleet) {
List<RaceColumnDTO> racesColumnsOfFleet = new ArrayList<RaceColumnDTO>();
int raceColumnCounter = 1;
for (RaceColumnDTO raceColumn : series.getRaceColumns()) {
boolean skipCarryForwardColumn = series.isFirstColumnIsNonDiscardableCarryForward();
for (FleetDTO fleetOfRaceColumn : series.getFleets()) {
if (fleet.equals(fleetOfRaceColumn) && !(skipCarryForwardColumn == true && raceColumnCounter == 1)) {
// We have to get the race column from the leaderboard, because the race column of the series
// have no tracked race and would be displayed as inactive race.
racesColumnsOfFleet.add(leaderboard.getRaceColumnByName(raceColumn.getName()));
}
}
raceColumnCounter++;
}
return racesColumnsOfFleet;
}
}
@@ -0,0 +1,14 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaScheduleResources" />
<g:HTMLPanel>
<div class="{local_res.css.eventregattaschedule_series_fleet}">
<div ui:field="fleetDiv" class="{local_res.css.eventregattaschedule_series_fleet_name}"><span ui:field="fleetName" /></div>
<g:HTMLPanel ui:field="racesListPanel" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,79 @@
package com.sap.sailing.gwt.home.client.place.event.regattaschedule;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.i18n.shared.DateTimeFormat;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.domain.common.dto.RaceColumnDTO;
import com.sap.sailing.domain.common.dto.RaceDTO;
import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator;
import com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaScheduleResources.LocalCss;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class EventRegattaScheduleRace extends Composite {
private static EventRegattaScheduleSeriesUiBinder uiBinder = GWT.create(EventRegattaScheduleSeriesUiBinder.class);
interface EventRegattaScheduleSeriesUiBinder extends UiBinder<Widget, EventRegattaScheduleRace> {
}
private final FleetDTO fleet;
private final RaceColumnDTO raceColumn;
private final StrippedLeaderboardDTO leaderboard;
@UiField Anchor raceBox;
@UiField SpanElement raceName;
@UiField SpanElement raceDetails;
private final DateTimeFormat raceTimeFormat = DateTimeFormat.getFormat("EEE, h:mm a");
private final EventPageNavigator pageNavigator;
public EventRegattaScheduleRace(StrippedLeaderboardDTO leaderboard, FleetDTO fleet, RaceColumnDTO raceColumn, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
this.leaderboard = leaderboard;
this.fleet = fleet;
this.raceColumn = raceColumn;
this.pageNavigator = pageNavigator;
LocalCss css = EventRegattaScheduleResources.INSTANCE.css();
css.ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
raceName.setInnerText(raceColumn.getName());
RaceDTO race = raceColumn.getRace(fleet);
if(race != null) {
boolean live = raceColumn.isLive(fleet, timerForClientServerOffset.getLiveTimePointInMillis());
// tracked race
raceBox.getElement().addClassName(css.eventregattaschedule_series_fleet_racetracked());
if(race.trackedRace != null) {
if(race.trackedRace.startOfTracking != null) {
raceDetails.setInnerText(raceTimeFormat.format(race.trackedRace.startOfTracking));
} else {
raceDetails.setInnerText("tracked");
}
if(live) {
raceBox.getElement().setAttribute("data-live", "data-live");
}
}
} else {
raceBox.getElement().addClassName(css.eventregattaschedule_series_fleet_raceuntracked());
raceDetails.setInnerText("untracked");
}
}
@UiHandler("raceBox")
public void goToRaceboard(ClickEvent e) {
RaceDTO race = raceColumn.getRace(fleet);
if(race != null && race.trackedRace != null) {
pageNavigator.openRaceViewer(leaderboard, race);
}
}
}
@@ -0,0 +1,14 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaScheduleResources" />
<g:HTMLPanel>
<g:Anchor ui:field="raceBox" styleName="{local_res.css.eventregattaschedule_series_fleet_race}">
<div class="{local_res.css.eventregattaschedule_series_fleet_race_name}"><span ui:field="raceName" /></div>
<div class="{local_res.css.eventregattaschedule_series_fleet_race_details}"><span ui:field="raceDetails" /></div>
</g:Anchor>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,39 @@
package com.sap.sailing.gwt.home.client.place.event.regattaschedule;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.dto.FleetDTO;
import com.sap.sailing.gwt.home.client.place.event.EventPageNavigator;
import com.sap.sailing.gwt.ui.shared.SeriesDTO;
import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO;
import com.sap.sse.gwt.client.player.Timer;
public class EventRegattaScheduleSeries extends Composite {
private static EventRegattaScheduleSeriesUiBinder uiBinder = GWT.create(EventRegattaScheduleSeriesUiBinder.class);
interface EventRegattaScheduleSeriesUiBinder extends UiBinder<Widget, EventRegattaScheduleSeries> {
}
@UiField SpanElement seriesName;
@UiField SpanElement seriesDate;
@UiField HTMLPanel fleetsListPanel;
public EventRegattaScheduleSeries(StrippedLeaderboardDTO leaderboard, SeriesDTO series, Timer timerForClientServerOffset, EventPageNavigator pageNavigator) {
EventRegattaScheduleResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
seriesName.setInnerText(series.getName());
seriesDate.setInnerText("Some series data");
for(FleetDTO fleet: series.getFleets()) {
EventRegattaScheduleFleet eventRegattaScheduleFleet = new EventRegattaScheduleFleet(leaderboard, series, fleet, timerForClientServerOffset, pageNavigator);
fleetsListPanel.add(eventRegattaScheduleFleet);
}
}
}
@@ -0,0 +1,15 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.event.regattaschedule.EventRegattaScheduleResources" />
<g:HTMLPanel>
<div class="{local_res.css.eventregattaschedule_series}">
<h3 class="{local_res.css.eventregattaschedule_series_name}"><span ui:field="seriesName" /></h3>
<span class="{local_res.css.eventregattaschedule_series_date}"><span ui:field="seriesDate" /></span>
<g:HTMLPanel ui:field="fleetsListPanel" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,116 @@
.eventteasercontainer {
font-size: 15px;
font-size: 1rem;
text-align: center;
width: 100%;
}
.eventteaser {
font-size: 15px;
font-size: 1rem;
display: inline-block;
margin-bottom: 3em;
text-align: left;
max-width: 100%;
}
.eventteaser:hover {
text-decoration: none;
}
.eventteaser:hover .eventteaser_name {
text-decoration: underline;
}
.eventteaser:hover .eventteaser_image {
opacity: 0.9;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)";
filter: literal("alpha(opacity=90)");
}
.eventteaser_image {
position: relative;
display: inline-block;
max-width: 100%;
}
.eventteaser_series {
position: absolute;
bottom: 0;
right: 0;
}
.eventteaser_name {
font-size: 1.466666666666667em;
font-weight: bold;
color: #008fcc;
margin-top: 0.333333333333333em;
}
.eventteaser_location {
color: #222;
}
.eventsoverviewnavigation {
font-size: 15px;
font-size: 1rem;
}
.eventsoverviewnavigation .gridalternator {
overflow: visible;
}
.eventsoverviewrecent {
font-size: 15px;
font-size: 1rem;
padding-top: 2em;
}
.eventsoverviewrecent_year {
border-bottom: 1px solid #ccc;
transiton: opacity 0.1s;
}
.eventsoverviewrecent_year:nth-child\(even\) {
background: #f8f8f8;
}
.eventsoverviewrecent_year:nth-child\(even\) .eventsoverviewrecent_year_header:hover,
.eventsoverviewrecent_year:nth-child\(even\) .eventsoverviewrecent_year_header:focus {
background-color: #f3f3f3;
}
.eventsoverviewrecent_yearcollapsed .eventsoverviewrecent_year_header_info_arrow_image {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-o-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
.eventsoverviewrecent_year_header {
padding: 0.666666666666667em;
cursor: pointer;
}
.eventsoverviewrecent_year_header:hover,
.eventsoverviewrecent_year_header:focus {
background-color: #fcfcfc;
}
.eventsoverviewrecent_year_header:hover .eventsoverviewrecent_year_header_title,
.eventsoverviewrecent_year_header:focus .eventsoverviewrecent_year_header_title {
text-decoration: underline;
}
.eventsoverviewrecent_year_header_title {
margin-bottom: 0;
}
.eventsoverviewrecent_year_header_info {
float: right;
}
.eventsoverviewrecent_year_header_info_arrow {
padding: 0.466666666666667em 1.133333333333333em;
}
.eventsoverviewrecent_year_header_info_arrow_image {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
transiton: transform 0.4s;
}
.eventsoverviewrecent_year_header_info_item {
border-right: 1px solid #ccc;
padding: 0.466666666666667em 1.133333333333333em;
}
.eventsoverviewrecent_year_header_info_item_value {
font-weight: 700;
color: #008fcc;
margin-right: 0.533333333333333em;
}
.eventsoverviewrecent_year_content {
margin-top: 0.666666666666667em;
padding-bottom: 1.333333333333333em;
}
@@ -13,7 +13,6 @@ import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.DateUtil;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.shared.recentevent.RecentEvents;
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
public class EventsOverviewRecent extends Composite {
@@ -25,13 +24,13 @@ public class EventsOverviewRecent extends Composite {
private final PlaceNavigator navigator;
@UiField HTMLPanel htmlPanel;
@UiField HTMLPanel recentEventsPerYearPanel;
private final Map<Integer, RecentEvents> recentEventsComposites;
private final Map<Integer, EventsOverviewRecentYear> recentEventsComposites;
public EventsOverviewRecent(PlaceNavigator navigator) {
this.navigator = navigator;
recentEventsComposites = new HashMap<Integer, RecentEvents>();
recentEventsComposites = new HashMap<Integer, EventsOverviewRecentYear>();
EventsOverviewRecentResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
@@ -39,26 +38,33 @@ public class EventsOverviewRecent extends Composite {
public void updateEvents(Map<Integer, List<EventBaseDTO>> recentEventsOrderedByYear) {
// remove old widgets
htmlPanel.clear();
recentEventsPerYearPanel.clear();
recentEventsComposites.clear();
// recent events of this year
Date now = new Date();
int currentYear = DateUtil.getYear(now);
boolean oneYearIsExpanded = false;
if(recentEventsOrderedByYear.get(currentYear) != null) {
RecentEvents recentEvents = new RecentEvents(navigator);
recentEvents.setEvents(recentEventsOrderedByYear.get(currentYear), null);
htmlPanel.add(recentEvents);
recentEventsComposites.put(currentYear, recentEvents);
EventsOverviewRecentYear recentEventsOfOneYear = new EventsOverviewRecentYear(currentYear, recentEventsOrderedByYear.get(currentYear), navigator);
recentEventsPerYearPanel.add(recentEventsOfOneYear);
recentEventsComposites.put(currentYear, recentEventsOfOneYear);
recentEventsOfOneYear.showContent();
oneYearIsExpanded = true;
}
currentYear--;
while (currentYear > 2010) {
if(recentEventsOrderedByYear.get(currentYear) != null) {
RecentEvents recentEvents = new RecentEvents(navigator);
recentEvents.setEvents(recentEventsOrderedByYear.get(currentYear), String.valueOf(currentYear));
htmlPanel.add(recentEvents);
recentEventsComposites.put(currentYear, recentEvents);
EventsOverviewRecentYear recentEventsOfOneYear = new EventsOverviewRecentYear(currentYear, recentEventsOrderedByYear.get(currentYear), navigator);
recentEventsPerYearPanel.add(recentEventsOfOneYear);
recentEventsComposites.put(currentYear, recentEventsOfOneYear);
if(oneYearIsExpanded == true) {
recentEventsOfOneYear.hideContent();
} else {
recentEventsOfOneYear.showContent();
oneYearIsExpanded = true;
}
}
currentYear--;
}
@@ -5,7 +5,10 @@
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.events.recent.EventsOverviewRecentResources" />
<g:HTMLPanel ui:field="htmlPanel">
<!-- The whole content will be created dynamically -->
<g:HTMLPanel>
<!-- The events main content-->
<div class="{local_res.css.eventsoverviewrecent}">
<g:HTMLPanel ui:field="recentEventsPerYearPanel" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -11,5 +11,24 @@ public interface EventsOverviewRecentResources extends ClientBundle {
LocalCss css();
public interface LocalCss extends CssResource {
String eventteasercontainer();
String eventteaser();
String eventteaser_name();
String eventteaser_image();
String eventteaser_series();
String eventteaser_location();
String eventsoverviewnavigation();
String gridalternator();
String eventsoverviewrecent();
String eventsoverviewrecent_year();
String eventsoverviewrecent_year_header();
String eventsoverviewrecent_yearcollapsed();
String eventsoverviewrecent_year_header_info_arrow_image();
String eventsoverviewrecent_year_header_title();
String eventsoverviewrecent_year_header_info();
String eventsoverviewrecent_year_header_info_arrow();
String eventsoverviewrecent_year_header_info_item();
String eventsoverviewrecent_year_header_info_item_value();
String eventsoverviewrecent_year_content();
}
}
@@ -0,0 +1,84 @@
package com.sap.sailing.gwt.home.client.place.events.recent;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
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.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.shared.recentevent.RecentEvent;
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
public class EventsOverviewRecentYear extends Composite {
interface EventsOverviewUiBinder extends UiBinder<Widget, EventsOverviewRecentYear> {
}
private static EventsOverviewUiBinder uiBinder = GWT.create(EventsOverviewUiBinder.class);
@UiField SpanElement year;
@UiField SpanElement eventsCount;
@UiField SpanElement countriesCount;
@UiField SpanElement sailorsCount;
@UiField SpanElement trackedRacesCount;
@UiField HTMLPanel recentEventsTeaserPanel;
@UiField HTMLPanel contentDiv;
@UiField HTMLPanel headerDiv;
private boolean isContentVisible;
public EventsOverviewRecentYear(Integer year, List<EventBaseDTO> events, PlaceNavigator navigator) {
EventsOverviewRecentResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
this.year.setInnerText(String.valueOf(year));
this.eventsCount.setInnerText(String.valueOf(events.size()));
this.countriesCount.setInnerText("tbd.");
this.sailorsCount.setInnerText("tbd.");
this.trackedRacesCount.setInnerText("tbd.");
for(EventBaseDTO eventDTO: events) {
RecentEvent recentEvent = new RecentEvent(navigator);
recentEvent.setEvent(eventDTO);
recentEventsTeaserPanel.add(recentEvent);
}
isContentVisible = true;
headerDiv.addDomHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
onHeaderCicked();
}
}, ClickEvent.getType());
}
private void onHeaderCicked() {
isContentVisible = !isContentVisible;
updateContentVisibility();
}
public void hideContent() {
isContentVisible = false;
updateContentVisibility();
}
public void showContent() {
isContentVisible = true;
updateContentVisibility();
}
private void updateContentVisibility() {
contentDiv.setVisible(isContentVisible);
if(isContentVisible) {
headerDiv.getElement().removeClassName(EventsOverviewRecentResources.INSTANCE.css().eventsoverviewrecent_yearcollapsed());
} else {
headerDiv.getElement().addClassName(EventsOverviewRecentResources.INSTANCE.css().eventsoverviewrecent_yearcollapsed());
}
}
}
@@ -0,0 +1,57 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.place.events.recent.EventsOverviewRecentResources" />
<g:HTMLPanel>
<!--
THIS DOES NOT WORK UH
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.medium3} {res.mediaCss.columns}">
Hallo Links
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium9} {res.mediaCss.columns}">
Hallo REchts
</div>
</div>
-->
<div class="{local_res.css.eventsoverviewrecent_year}">
<g:HTMLPanel ui:field="headerDiv" styleName="{local_res.css.eventsoverviewrecent_year_header}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small3} {res.mediaCss.columns}">
<h3 class="{local_res.css.eventsoverviewrecent_year_header_title}"><span ui:field="year" /></h3>
</div>
<div class="{res.mediaCss.small9} {res.mediaCss.columns}">
<table class="{local_res.css.eventsoverviewrecent_year_header_info}">
<tr>
<td>
<div class="{local_res.css.eventsoverviewrecent_year_header_info_item}"><span class="{local_res.css.eventsoverviewrecent_year_header_info_item_value}"><span ui:field="eventsCount" /></span><ui:text from='{i18n.eventsOverviewRecentEvents}'/></div>
</td>
<td>
<div class="{local_res.css.eventsoverviewrecent_year_header_info_item}"><span class="{local_res.css.eventsoverviewrecent_year_header_info_item_value}"><span ui:field="countriesCount" /></span><ui:text from='{i18n.eventsOverviewRecentCountries}'/></div>
</td>
<td>
<div class="{local_res.css.eventsoverviewrecent_year_header_info_item}"><span class="{local_res.css.eventsoverviewrecent_year_header_info_item_value}"><span ui:field="sailorsCount" /></span><ui:text from='{i18n.eventsOverviewRecentSailors}'/></div>
</td>
<td>
<div class="{local_res.css.eventsoverviewrecent_year_header_info_item}"><span class="{local_res.css.eventsoverviewrecent_year_header_info_item_value}"><span ui:field="trackedRacesCount" /></span><ui:text from='{i18n.eventsOverviewRecentTrackedRaces}'/></div>
</td>
<td>
<div class="{local_res.css.eventsoverviewrecent_year_header_info_arrow}"><img src="images/home/arrow-down-yellow.png" class="{local_res.css.eventsoverviewrecent_year_header_info_arrow_image}"></img></div>
</td>
</tr>
</table>
</div>
</div>
</g:HTMLPanel>
<g:HTMLPanel ui:field="contentDiv" styleName="{local_res.css.eventsoverviewrecent_year_content}">
<div class="{res.mainCss.grid}">
<g:HTMLPanel ui:field="recentEventsTeaserPanel" />
</div>
</g:HTMLPanel>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -13,7 +13,9 @@ import com.sap.sailing.gwt.home.client.shared.mainmedia.MainMedia;
import com.sap.sailing.gwt.home.client.shared.mainsponsors.MainSponsors;
import com.sap.sailing.gwt.home.client.shared.socialfooter.SocialFooter;
import com.sap.sailing.gwt.home.client.shared.stage.Stage;
import com.sap.sailing.gwt.home.client.shared.stage.StageEventType;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Util.Pair;
public class SmartphoneStartView extends Composite implements StartView {
private static StartPageMobileViewUiBinder uiBinder = GWT.create(StartPageMobileViewUiBinder.class);
@@ -21,13 +23,14 @@ public class SmartphoneStartView extends Composite implements StartView {
interface StartPageMobileViewUiBinder extends UiBinder<Widget, SmartphoneStartView> {
}
@UiField Stage stage;
@UiField(provided=true) Stage stage;
@UiField(provided=true) MainSponsors mainSponsors;
@UiField(provided=true) MainEvents mainEvents;
@UiField(provided=true) MainMedia mainMedia;
@UiField SocialFooter socialFooter;
public SmartphoneStartView(PlaceNavigator navigator) {
stage = new Stage(navigator);
mainSponsors = new MainSponsors(navigator);
mainEvents = new MainEvents(navigator);
mainMedia = new MainMedia(navigator);
@@ -35,8 +38,8 @@ public class SmartphoneStartView extends Composite implements StartView {
}
@Override
public void setFeaturedEvent(EventDTO featuredEvent) {
stage.setFeaturedEvent(featuredEvent);
public void setFeaturedEvents(List<Pair<StageEventType, EventDTO>> featuredEvents) {
stage.setFeaturedEvents(featuredEvents);
}
@Override
@@ -8,7 +8,9 @@ import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.sap.sailing.gwt.home.client.shared.stage.StageEventType;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Util.Pair;
public class StartActivity extends AbstractActivity {
private final StartClientFactory clientFactory;
@@ -36,22 +38,49 @@ public class StartActivity extends AbstractActivity {
@SuppressWarnings("deprecation")
protected void fillStartPageEvents(StartView view, List<EventDTO> events) {
EventDTO featuredEvent = null;
List<EventDTO> recentEvents = new ArrayList<EventDTO>();
List<Pair<StageEventType, EventDTO>> featuredEvents = new ArrayList<Pair<StageEventType, EventDTO>>();
List<EventDTO> recentEventsOfSameYear = new ArrayList<EventDTO>();
List<EventDTO> upcomingSoonEvents = new ArrayList<EventDTO>();
List<EventDTO> popularEvents = new ArrayList<EventDTO>();
Date now = new Date();
int currentYear = now.getYear();
final int MAX_STAGE_EVENTS = 2;
final long TWO_WEEK_IN_MS = 1000 * 60 * 60 * 24 * 7;
for(EventDTO event: events) {
// ignore events with no start and end date
if(event.startDate != null && event.endDate != null) {
if(featuredEvent == null && event.startDate.after(now)) {
featuredEvent = event;
view.setFeaturedEvent(event);
}
if(event.endDate.before(now) && event.endDate.getYear() == currentYear) {
recentEvents.add(event);
if (now.after(event.startDate) && now.before(event.endDate)) {
featuredEvents.add(new Pair<StageEventType, EventDTO>(StageEventType.RUNNING, event));
} else if (event.startDate.after(now) && event.startDate.getTime() - now.getTime() < TWO_WEEK_IN_MS) {
upcomingSoonEvents.add(event);
} else if (event.endDate.before(now) && event.endDate.getYear() == currentYear) {
recentEventsOfSameYear.add(event);
}
}
}
view.setRecentEvents(recentEvents);
if(featuredEvents.size() < MAX_STAGE_EVENTS) {
fillingUpEventsList(MAX_STAGE_EVENTS, featuredEvents, StageEventType.UPCOMING_SOON, upcomingSoonEvents);
}
if(featuredEvents.size() < MAX_STAGE_EVENTS) {
fillingUpEventsList(MAX_STAGE_EVENTS, featuredEvents, StageEventType.POPULAR, popularEvents);
}
// fallback for the case we did not find any events
if(featuredEvents.size() < MAX_STAGE_EVENTS) {
fillingUpEventsList(MAX_STAGE_EVENTS, featuredEvents, StageEventType.POPULAR, recentEventsOfSameYear);
}
view.setFeaturedEvents(featuredEvents);
view.setRecentEvents(recentEventsOfSameYear);
}
private void fillingUpEventsList(int maxAmountOfElements, List<Pair<StageEventType, EventDTO>> resultList, StageEventType type, List<EventDTO> listToTakeElementsFrom) {
int maxElementsToFill = maxAmountOfElements - resultList.size();
int elementsToTransfer = listToTakeElementsFrom.size() > maxElementsToFill ? maxElementsToFill : listToTakeElementsFrom.size();
for(int i = 0; i < elementsToTransfer; i++) {
resultList.add(new Pair<StageEventType, EventDTO>(type, listToTakeElementsFrom.get(i)));
}
}
}
@@ -3,12 +3,14 @@ package com.sap.sailing.gwt.home.client.place.start;
import java.util.List;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.shared.stage.StageEventType;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Util.Pair;
public interface StartView {
Widget asWidget();
void setFeaturedEvent(EventDTO featuredEvent);
void setFeaturedEvents(List<Pair<StageEventType, EventDTO>> featuredEvents);
void setRecentEvents(List<EventDTO> recentEvents);
}
@@ -10,10 +10,11 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.shared.mainevents.MainEvents;
import com.sap.sailing.gwt.home.client.shared.mainmedia.MainMedia;
import com.sap.sailing.gwt.home.client.shared.mainsponsors.MainSponsors;
import com.sap.sailing.gwt.home.client.shared.socialfooter.SocialFooter;
import com.sap.sailing.gwt.home.client.shared.stage.Stage;
import com.sap.sailing.gwt.home.client.shared.stage.StageEventType;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Util.Pair;
public class TabletAndDesktopStartView extends Composite implements StartView {
private static StartPageViewUiBinder uiBinder = GWT.create(StartPageViewUiBinder.class);
@@ -21,14 +22,15 @@ public class TabletAndDesktopStartView extends Composite implements StartView {
interface StartPageViewUiBinder extends UiBinder<Widget, TabletAndDesktopStartView> {
}
@UiField Stage stage;
@UiField(provided=true) MainSponsors mainSponsors;
@UiField(provided=true) Stage stage;
// @UiField(provided=true) MainSponsors mainSponsors;
@UiField(provided=true) MainEvents mainEvents;
@UiField(provided=true) MainMedia mainMedia;
@UiField SocialFooter socialFooter;
public TabletAndDesktopStartView(PlaceNavigator navigator) {
mainSponsors = new MainSponsors(navigator);
stage = new Stage(navigator);
// mainSponsors = new MainSponsors(navigator);
mainEvents = new MainEvents(navigator);
mainMedia = new MainMedia(navigator);
@@ -36,8 +38,8 @@ public class TabletAndDesktopStartView extends Composite implements StartView {
}
@Override
public void setFeaturedEvent(EventDTO featuredEvent) {
stage.setFeaturedEvent(featuredEvent);
public void setFeaturedEvents(List<Pair<StageEventType, EventDTO>> featuredEvents) {
stage.setFeaturedEvents(featuredEvents);
}
@Override
@@ -6,7 +6,7 @@
<g:HTMLPanel>
<s:stage.Stage ui:field='stage'/>
<s:mainsponsors.MainSponsors ui:field='mainSponsors'/>
<!-- <s:mainsponsors.MainSponsors ui:field='mainSponsors'/> -->
<s:mainevents.MainEvents ui:field='mainEvents'/>
<s:mainmedia.MainMedia ui:field='mainMedia'/>
<s:socialfooter.SocialFooter ui:field='socialFooter'/>
@@ -19,9 +19,9 @@ public class EventDatesFormatterUtil {
public static String formatDateRangeWithYear(Date from, Date to) {
String result = "";
if(from.getMonth() == to.getMonth()) {
result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to) + " " + yearFormat.format(from);
result = monthFormat.format(from) + " " + dayFormat.format(from) + " - " + dayFormat.format(to) + ", " + yearFormat.format(from);
} else {
result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to) + " " + yearFormat.format(from);
result = dayAndMonthFormat.format(from) + " - " + dayAndMonthFormat.format(to) + ", " + yearFormat.format(from);
}
return result;
@@ -9,7 +9,6 @@ import com.google.gwt.uibinder.client.UiField;
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.ui.shared.EventBaseDTO;
public class EventSponsors extends Composite {
private static EventSponsorsPanelUiBinder uiBinder = GWT.create(EventSponsorsPanelUiBinder.class);
@@ -28,15 +27,17 @@ public class EventSponsors extends Composite {
eventSponsorComposites = new ArrayList<EventSponsor>();
}
public void setEventSponsors(EventBaseDTO event) {
public void setEventSponsors(List<String> sponsorImageUrls) {
sponsorsPlaceholder.clear();
eventSponsorComposites.clear();
for (String sponsorImageUrl : event.getSponsorImageURLs()) {
EventSponsor eventSponor = new EventSponsor(null /* name */, sponsorImageUrl, null /* link */);
if(sponsorImageUrls != null) {
for (String sponsorImageUrl : sponsorImageUrls) {
EventSponsor eventSponor = new EventSponsor(null /* name */, sponsorImageUrl, null /* link */);
eventSponsorComposites.add(eventSponor);
sponsorsPlaceholder.add(eventSponor);
eventSponsorComposites.add(eventSponor);
sponsorsPlaceholder.add(eventSponor);
}
}
}
}
@@ -1,12 +1,18 @@
package com.sap.sailing.gwt.home.client.shared.footer;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
@@ -15,24 +21,47 @@ public class Footer extends Composite {
private static FooterPanelUiBinder uiBinder = GWT.create(FooterPanelUiBinder.class);
@UiField Anchor changeLanguageLink;
@UiField SpanElement currentLanguage;
private LocaleInfo currentLocale;
private final Map<String, String> localeAndLanguages;
/** set-configuration-property name='locale.searchorder' value='queryparam,cookie,useragent' /> */
interface FooterPanelUiBinder extends UiBinder<Widget, Footer> {
}
public Footer() {
localeAndLanguages = new HashMap<String, String>();
localeAndLanguages.put("default", "English");
localeAndLanguages.put("de", "Deutsch");
FooterResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
currentLocale = LocaleInfo.getCurrentLocale();
currentLanguage.setInnerHTML(currentLocale.getLocaleName());
updateUI();
}
@UiHandler("changeLanguageLink")
public void changeLanguage(ClickEvent e) {
String selectedLanguage = changeLanguageLink.getText();
String selectedLocale = null;
for (Entry<String, String> entry: localeAndLanguages.entrySet()) {
if (entry.getValue().equals(selectedLanguage)) {
selectedLocale = entry.getKey();
}
}
if(selectedLocale != null) {
UrlBuilder builder = Location.createUrlBuilder().setParameter("locale", selectedLocale);
Window.Location.replace(builder.buildString());
}
}
private void updateUI() {
LocaleInfo currentLocale = LocaleInfo.getCurrentLocale();
HashMap<String, String> languagesToSelectFrom = new HashMap<String, String>(localeAndLanguages);
languagesToSelectFrom.remove(currentLocale.getLocaleName());
if(languagesToSelectFrom.size() == 1) {
changeLanguageLink.setText(languagesToSelectFrom.values().iterator().next());
}
}
}
@@ -20,7 +20,7 @@
</a></div>
</div>
<div class="{res.mediaCss.small4} {res.mediaCss.columns} {local_res.css.sitefooter_language}">
<ui:text from='{i18n.footerLanguage}'/>:<g:Anchor ui:field="changeLanguageLink" styleName="{local_res.css.sitefooter_language_link}"><span ui:field="currentLanguage" /></g:Anchor></div>
<ui:text from='{i18n.footerLanguage}'/>:<g:Anchor ui:field="changeLanguageLink" styleName="{local_res.css.sitefooter_language_link}" /></div>
</div>
</footer>
</g:HTMLPanel>
@@ -23,13 +23,12 @@ public class Header extends Composite {
@UiField Anchor startPageLink;
@UiField Anchor eventsPageLink;
@UiField Anchor solutionsPageLink;
@UiField Anchor sponsoringPageLink;
// @UiField Anchor sponsoringPageLink;
@UiField TextBox searchText;
@UiField Button searchButton;
private final List<Anchor> links;
private final List<Anchor> links;
private final PlaceNavigator navigator;
interface HeaderUiBinder extends UiBinder<Widget, Header> {
@@ -41,7 +40,7 @@ public class Header extends Composite {
this.navigator = navigator;
HeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
links = Arrays.asList(new Anchor[] { startPageLink, eventsPageLink, solutionsPageLink, sponsoringPageLink });
links = Arrays.asList(new Anchor[] { startPageLink, eventsPageLink, solutionsPageLink });
searchText.getElement().setAttribute("placeholder", "Search SAPSailing.com");
searchText.addKeyPressHandler(new KeyPressHandler() {
@@ -70,10 +69,10 @@ public class Header extends Composite {
navigator.goToSolutions();
}
@UiHandler("sponsoringPageLink")
public void goToSponsoring(ClickEvent e) {
navigator.goToSponsoring();
}
// @UiHandler("sponsoringPageLink")
// public void goToSponsoring(ClickEvent e) {
// navigator.goToSponsoring();
// }
@UiHandler("searchButton")
void searchButtonClick(ClickEvent event) {
@@ -19,9 +19,10 @@
styleName="{local_res.css.sitenavigation_link}" text="{i18n.events}" href="javascript:;"/>
<g:Anchor ui:field="solutionsPageLink"
styleName="{local_res.css.sitenavigation_link}" text="{i18n.solutions}" href="javascript:;"/>
<!--
<g:Anchor ui:field="sponsoringPageLink"
styleName="{local_res.css.sitenavigation_link}" text="{i18n.sponsoring}" href="javascript:;">
</g:Anchor>
styleName="{local_res.css.sitenavigation_link}" text="{i18n.sponsoring}" href="javascript:;" />
-->
<div class="{local_res.css.search}">
<g:Button ui:field="searchButton" text="Search" styleName="{res.mainCss.button} {res.mainCss.buttonsearch} {local_res.css.search_button}" />
<g:TextBox ui:field="searchText" styleName="{local_res.css.search_textfield}" />
@@ -1,92 +1,115 @@
/**
* Websites main media element
*/
.media {
background: #f8f8f8;
font-size: 16px;
font-size: 1rem;
font-size: 15px;
font-size: 1rem;
}
.media_photo {
width: 100%;
height: 100%;
.media_swipecontainer {
position: relative;
width: 830px;
height: 550px;
margin: 0 auto;
overflow: hidden;
}
.media_slideshow {
position: relative;
height: 550px;
width: 830px;
margin: 0 auto;
.media_swipewrapper {
}
.media_swiperslide {
display: inline-block;
background: no-repeat center center;
-webkit-background-size: contain;
-moz-background-size: contain;
-o-background-size: contain;
background-size: contain;
}
.media_slideshow_controls {
position: absolute;
background-position: 0 0;
background-repeat: no-repeat;
cursor: pointer;
position: absolute;
background-position: 0 0;
background-repeat: no-repeat;
cursor: pointer;
z-index: 10;
}
.media_slideshow_controlsnext,
.media_slideshow_controlsnext,.media_slideshow_controlsprev {
top: 50%;
-webkit-transform: translate(0, -50%);
-moz-transform: translate(0, -50%);
-o-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
width: 60px;
height: 60px;
background-image: url("images/home/media-controls__arrows.png");
}
.media_slideshow_controlsprev {
top: 50%;
-webkit-transform: translate(0, -50%);
-moz-transform: translate(0, -50%);
-o-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
width: 60px;
height: 60px;
background-image: url("images/home/media-controls__arrows.png");
}
.media_slideshow_controlsprev {
left: 0;
background-position: 0 0;
left: 0;
background-position: 0 0;
}
.media_slideshow_controlsprev:hover {
background-position: 0 100%;
background-position: 0 100%;
}
.media_slideshow_controlsnext {
right: 0;
background-position: 100% 0;
right: 0;
background-position: 100% 0;
}
.media_slideshow_controlsnext:hover {
background-position: 100% 100%;
background-position: 100% 100%;
}
.media_slideshow_controlsfullsize {
background-image: url("images/home/media-controls__fullsize.png");
right: 0;
bottom: 0;
width: 40px;
height: 40px;
background-image: url("images/home/media-controls__fullsize.png");
right: 0;
bottom: 0;
width: 40px;
height: 40px;
}
.mediavideos {
background: #333;
color: #fff;
background: #333;
color: #fff;
}
.mediavideos .mainsection_header_title {
color: #fff;
color: #fff;
}
.videopreview {
font-size: 16px;
font-size: 1rem;
margin-bottom: 2.5em;
cursor: pointer;
font-size: 15px;
font-size: 1rem;
margin-bottom: 2.666666666666667em;
cursor: pointer;
}
.videopreview:before {
content: ' ';
position: absolute;
left: 50%;
top: 70px;
-webkit-transform: translate(-50%, 0);
-moz-transform: translate(-50%, 0);
-o-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
width: 69px;
height: 69px;
background: url("images/home/video__preview--play.png");
-webkit-background-size: contain;
-moz-background-size: contain;
background-size: contain;
content: ' ';
position: absolute;
left: 50%;
top: 70px;
-webkit-transform: translate(-50%, 0);
-moz-transform: translate(-50%, 0);
-o-transform: translate(-50%, 0);
-ms-transform: translate(-50%, 0);
transform: translate(-50%, 0);
width: 69px;
height: 69px;
background: url("images/home/video__preview--play.png");
-webkit-background-size: contain;
-moz-background-size: contain;
background-size: contain;
}
.videopreview_title {
font-size: 1.375em;
font-weight: bold;
margin: 0;
font-size: 1.466666666666667em;
font-weight: bold;
margin: 0;
color: #fff;
}
.videopreview time {
display: block;
}
@@ -1,30 +1,34 @@
package com.sap.sailing.gwt.home.client.shared.mainmedia;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.idangerous.Swiper;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class MainMedia extends Composite {
private static final MainMediaResources.LocalCss STYLES = MainMediaResources.INSTANCE.css();
@UiField DivElement photoImage;
@UiField HTMLPanel videosPanel;
@UiField DivElement videoLightBoxData;
@UiField HTMLPanel mediaSlides;
@UiField(provided=true) RecentEventVideo eventVideo1;
@UiField(provided=true) RecentEventVideo eventVideo2;
@UiField(provided=true) RecentEventVideo eventVideo3;
private List<EventDTO> recentEvents;
private final String basePathToImages = "http://static.sapsailing.com/newhome/media/";
private String[] images = { "main-media-photo-1.jpg" };
private Swiper swiper;
interface MainMediaUiBinder extends UiBinder<Widget, MainMedia> {
}
@@ -32,38 +36,61 @@ public class MainMedia extends Composite {
private static MainMediaUiBinder uiBinder = GWT.create(MainMediaUiBinder.class);
public MainMedia(PlaceNavigator navigator) {
eventVideo1 = new RecentEventVideo(navigator);
eventVideo2 = new RecentEventVideo(navigator);
eventVideo3 = new RecentEventVideo(navigator);
MainMediaResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
String imagePath = "url(" + basePathToImages + images[0] + ")";
photoImage.getStyle().setBackgroundImage(imagePath);
recentEvents = new ArrayList<EventDTO>();
}
public void setRecentEvents(List<EventDTO> theRecentEvents) {
recentEvents.clear();
recentEvents.addAll(theRecentEvents);
public void setRecentEvents(List<EventDTO> recentEvents) {
List<String> photoGalleryUrls = new ArrayList<String>();
String lightBoxData = "";
int size = recentEvents.size();
if(size > 0) {
eventVideo1.setEvent(recentEvents.get(0));
} else {
eventVideo1.setVisible(false);
int videoCounter = 0;
for(EventDTO event: recentEvents) {
photoGalleryUrls.addAll(event.getPhotoGalleryImageURLs());
if(event.getVideoURLs().size() > 0 && videoCounter < 3) {
MainMediaVideo video = new MainMediaVideo(event);
lightBoxData += video.getDataForLightBox();
videosPanel.add(video);
videoCounter++;
}
}
if(size > 1) {
eventVideo2.setEvent(recentEvents.get(1));
} else {
eventVideo2.setVisible(false);
videoLightBoxData.setInnerText(lightBoxData);
// shuffle the image url list (Remark: Collections.shuffle() is not implemented in GWT)
int gallerySize = photoGalleryUrls.size();
Random random = new Random(gallerySize);
for(int i = 0; i < gallerySize; i++) {
Collections.swap(photoGalleryUrls, i, random.nextInt(gallerySize));
}
if(size > 2) {
eventVideo3.setEvent(recentEvents.get(2));
} else {
eventVideo3.setVisible(false);
for(String url : photoGalleryUrls) {
SimplePanel imageContainer = new SimplePanel();
imageContainer.addStyleName(STYLES.media_swiperslide());
String image = "url(" + url + ")";
imageContainer.getElement().getStyle().setBackgroundImage(image);
mediaSlides.add(imageContainer);
}
this.swiper = Swiper.createWithDefaultOptions(STYLES.media_swipecontainer(), STYLES.media_swipewrapper(), STYLES.media_swiperslide());
}
@UiHandler("nextPictureLink")
public void nextStageTeaserLinkClicked(ClickEvent e) {
if (this.swiper != null) {
this.swiper.swipeNext();
}
}
@UiHandler("prevPictureLink")
public void prevStageTeaserLinkClicked(ClickEvent e) {
if (this.swiper != null) {
this.swiper.swipePrev();
}
}
}
@@ -1,45 +1,52 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.mainmedia.MainMediaResources" />
<g:HTMLPanel>
<div class="{res.mainCss.mainsection} {local_res.css.media}">
<div class="{res.mainCss.grid}">
<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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.mainmedia.MainMediaResources" />
<g:HTMLPanel>
<!-- Partial for media like image and video -->
<div class="{res.mainCss.mainsection} {local_res.css.media}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<header class="{res.mainCss.mainsection_header}">
<h3 class="{res.mainCss.mainsection_header_title}">Sailing loves Photography</h3>
<p>Get lost in the latest and most beautiful impressions from your favorite sailing event.</p>
</header>
<header class="{res.mainCss.mainsection_header}">
<h3 class="{res.mainCss.mainsection_header_title}">
<ui:text from='{i18n.mainMediaTitle}' />
</h3>
<p>
<ui:text from='{i18n.mainMediaSubtitle}' />
</p>
</header>
</div>
</div>
<div class="{res.mainCss.grid}">
</div>
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<div class="{local_res.css.media_slideshow}">
<div ui:field="photoImage" class="{local_res.css.media_photo}"></div>
<div class="{local_res.css.media_slideshow_controls} {local_res.css.media_slideshow_controlsprev}"></div>
<div class="{local_res.css.media_slideshow_controls} {local_res.css.media_slideshow_controlsnext}"></div>
<div class="{local_res.css.media_slideshow_controls} {local_res.css.media_slideshow_controlsfullsize}"></div>
</div>
<div class="{local_res.css.media_swipecontainer}">
<g:HTMLPanel ui:field="mediaSlides" styleName="{local_res.css.media_swipewrapper}" />
<g:Anchor ui:field="prevPictureLink" styleName="{local_res.css.media_slideshow_controls} {local_res.css.media_slideshow_controlsprev}" />
<g:Anchor ui:field="nextPictureLink" styleName="{local_res.css.media_slideshow_controls} {local_res.css.media_slideshow_controlsnext}" />
</div>
</div>
</div>
</div>
</div>
<div class="{res.mainCss.mainsection} {local_res.css.media} {local_res.css.mediavideos}">
<div class="{res.mainCss.grid}">
<div
class="{res.mainCss.mainsection} {local_res.css.media} {local_res.css.mediavideos}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<header class="{res.mainCss.mainsection_header}">
<h3 class="{res.mainCss.mainsection_header_title}">Recent Video Entries</h3>
<p>Immerse yourself in the world of sailing and check out our latest events for more videos.</p>
</header>
<header class="{res.mainCss.mainsection_header}">
<h3 class="{res.mainCss.mainsection_header_title}">
<ui:text from='{i18n.mainMediaVideosTitle}' />
</h3>
<p>
<ui:text from='{i18n.mainMediaVideosSubtitle}' />
</p>
</header>
</div>
</div>
<div class="{res.mainCss.grid} {res.mainCss.lightbox}">
<div ui:field="videoLightBoxData" class="{res.mainCss.lightbox_data}"></div>
<g:HTMLPanel ui:field="videosPanel" />
</div>
</div>
<div class="{res.mainCss.grid}">
<s:mainmedia.RecentEventVideo ui:field='eventVideo1'/>
<s:mainmedia.RecentEventVideo ui:field='eventVideo2'/>
<s:mainmedia.RecentEventVideo ui:field='eventVideo3'/>
</div>
</div>
</g:HTMLPanel>
</g:HTMLPanel>
</ui:UiBinder>
@@ -12,8 +12,9 @@ public interface MainMediaResources extends ClientBundle {
public interface LocalCss extends CssResource {
String media();
String media_photo();
String media_slideshow();
String media_swipecontainer();
String media_swipewrapper();
String media_swiperslide();
String media_slideshow_controls();
String media_slideshow_controlsnext();
String media_slideshow_controlsprev();
@@ -0,0 +1,66 @@
package com.sap.sailing.gwt.home.client.shared.mainmedia;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class MainMediaVideo extends Composite {
interface MainMediaVideoUiBinder extends UiBinder<Widget, MainMediaVideo> {
}
private static MainMediaVideoUiBinder uiBinder = GWT.create(MainMediaVideoUiBinder.class);
private final static String DEFAULT_VIDEO_THUMB_IMAGE_URL = "http://static.sapsailing.com/ubilabsimages/default/default_video_preview.jpg";
@UiField SpanElement videoTime;
@UiField SpanElement videoTitle;
@UiField ImageElement videoThumbImage;
@UiField Element videoFile;
// Format: {video.thumb},{video.file},{video.title},video;
private String lightBoxData;
public MainMediaVideo(EventDTO event) {
MainMediaResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
String videoThumbImageUrl;
if(event.getPhotoGalleryImageURLs().size() > 0) {
videoThumbImageUrl = event.getPhotoGalleryImageURLs().get(0);
} else {
videoThumbImageUrl = DEFAULT_VIDEO_THUMB_IMAGE_URL;
}
videoThumbImage.setSrc(videoThumbImageUrl);
lightBoxData = videoThumbImageUrl + "," + event.getVideoURLs().get(0) + ";";
videoTime.setInnerHTML("3:40 min");
videoTitle.setInnerHTML(event.getName());
videoFile.setAttribute("data-src", event.getVideoURLs().get(0));
}
public String getDataForLightBox() {
return lightBoxData;
}
// @UiHandler("eventMediaPageLink")
// public void goToEventMediaPage(ClickEvent e) {
// if(event.getBaseURL().contains("localhost") || event.getBaseURL().contains("127.0.0.1")) {
// navigator.goToEvent(event.id.toString());
// } else {
// EventPlace eventPlace = new EventPlace(event.id.toString());
// EventPlace.Tokenizer t = new Tokenizer();
// String remoteEventUrl = event.getBaseURL() + "/gwt/Home.html#" + EventPlace.class.getSimpleName() + ":" + t.getToken(eventPlace);
// Window.Location.replace(remoteEventUrl);
// }
// }
}
@@ -6,14 +6,13 @@
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.mainmedia.MainMediaResources" />
<g:HTMLPanel>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large4} {res.mediaCss.columns}">
<figure class="{local_res.css.videopreview}"><img ui:field="eventVideoPreviewImage" />
<figcaption>
<p class="{local_res.css.videopreview_title}"><span ui:field="eventName" /></p>
<div><span ui:field="eventVideoLength" /></div>
<div><g:Anchor ui:field="eventMediaPageLink" styleName="{res.mainCss.button}" href="javascript:;">Show More</g:Anchor></div>
</figcaption>
</figure>
</div>
<div class="{res.mediaCss.small12} {res.mediaCss.medium6} {res.mediaCss.large4} {res.mediaCss.columns}">
<figure ui:field="videoFile" data-src="" class="{local_res.css.videopreview} {res.mainCss.lightbox_item}"><img ui:field="videoThumbImage" />
<figcaption><div class="{local_res.css.videopreview_title}"><span ui:field="videoTitle" /></div>
<time><span ui:field="videoTime" /></time>
</figcaption>
</figure>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,68 +0,0 @@
package com.sap.sailing.gwt.home.client.shared.mainmedia;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.place.event.EventPlace;
import com.sap.sailing.gwt.home.client.place.event.EventPlace.Tokenizer;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class RecentEventVideo extends Composite {
@UiField SpanElement eventVideoLength;
@UiField SpanElement eventName;
@UiField ImageElement eventVideoPreviewImage;
@UiField Anchor eventMediaPageLink;
private final String defaultVideoImageUrl = "http://static.sapsailing.com/newhome/default_video_preview.jpg";
private EventDTO event;
interface RecentEventVideoUiBinder extends UiBinder<Widget, RecentEventVideo> {
}
private static RecentEventVideoUiBinder uiBinder = GWT.create(RecentEventVideoUiBinder.class);
private final PlaceNavigator navigator;
public RecentEventVideo(PlaceNavigator navigator) {
this.navigator = navigator;
initWidget(uiBinder.createAndBindUi(this));
}
public void setEvent(EventDTO event) {
this.event = event;
updateUI();
}
@UiHandler("eventMediaPageLink")
public void goToEventMediaPage(ClickEvent e) {
if(event.getBaseURL().contains("localhost") || event.getBaseURL().contains("127.0.0.1")) {
navigator.goToEvent(event.id.toString());
} else {
EventPlace eventPlace = new EventPlace(event.id.toString());
EventPlace.Tokenizer t = new Tokenizer();
String remoteEventUrl = event.getBaseURL() + "/gwt/Home.html#" + EventPlace.class.getSimpleName() + ":" + t.getToken(eventPlace);
Window.Location.replace(remoteEventUrl);
}
}
private void updateUI() {
eventName.setInnerText(event.getName());
if(event.getVideoURLs().size() == 0) {
eventVideoPreviewImage.setSrc(defaultVideoImageUrl);
} else {
eventVideoPreviewImage.setSrc(event.getVideoURLs().get(0));
}
}
}
@@ -7,13 +7,10 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.place.event.EventPlace;
import com.sap.sailing.gwt.home.client.place.event.EventPlace.Tokenizer;
import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil;
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
@@ -27,7 +24,7 @@ public class RecentEvent extends Composite {
private EventBaseDTO event;
private final String defaultImageUrl = "http://static.sapsailing.com/newhome/default_event_photo.jpg";
private final String defaultImageUrl = "http://static.sapsailing.com/ubilabsimages/default/default_event_photo.jpg";
interface RecentEventUiBinder extends UiBinder<Widget, RecentEvent> {
}
@@ -50,14 +47,7 @@ public class RecentEvent extends Composite {
@UiHandler("eventOverviewLink")
public void goToEventPlace(ClickEvent e) {
if(event.getBaseURL().contains("localhost") || event.getBaseURL().contains("127.0.0.1")) {
navigator.goToEvent(event.id.toString());
} else {
EventPlace eventPlace = new EventPlace(event.id.toString());
EventPlace.Tokenizer t = new Tokenizer();
String remoteEventUrl = event.getBaseURL() + "/gwt/Home.html#" + EventPlace.class.getSimpleName() + ":" + t.getToken(eventPlace);
Window.Location.replace(remoteEventUrl);
}
navigator.goToEvent(event.id.toString(), event.getBaseURL());
}
private void updateUI() {
@@ -6,13 +6,10 @@ import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.place.event.EventPlace;
import com.sap.sailing.gwt.home.client.place.event.EventPlace.Tokenizer;
import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil;
import com.sap.sailing.gwt.ui.shared.EventBaseDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardSearchResultDTO;
@@ -26,21 +23,28 @@ public class SearchResultItem extends Composite {
@UiField Anchor regattaLink;
@UiField SpanElement resultRegattaDetails;
@UiField SpanElement resultEventDate;
@UiField SpanElement resultEventVenue;
@UiField Anchor eventOverviewLink;
private final PlaceNavigator navigator;
private final PlaceNavigator placeNavigator;
private LeaderboardSearchResultDTO searchResult;
public SearchResultItem(PlaceNavigator navigator, LeaderboardSearchResultDTO searchResult) {
this.navigator = navigator;
this.placeNavigator = navigator;
this.searchResult = searchResult;
SearchResultResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
regattaLink.setText(searchResult.getRegattaName());
resultRegattaDetails.setInnerText("I have no idea yet what to show here...");
String headlineLink = searchResult.getLeaderboardDisplayName();
if(headlineLink == null) {
headlineLink = searchResult.getRegattaName() != null ? searchResult.getRegattaName() : searchResult.getLeaderboardName();
}
regattaLink.setText(headlineLink);
// resultRegattaDetails.setInnerText("I have no idea yet what to show here...");
eventOverviewLink.setText(searchResult.getEvent().getName());
resultEventVenue.setInnerText(searchResult.getEvent().venue.getName());
if(searchResult.getEvent().startDate != null) {
resultEventDate.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(searchResult.getEvent().startDate, searchResult.getEvent().endDate));
} else {
@@ -50,21 +54,13 @@ public class SearchResultItem extends Composite {
@UiHandler("regattaLink")
public void goToRegatta(ClickEvent e) {
Window.alert("Not implemented yet.");
EventBaseDTO event = searchResult.getEvent();
placeNavigator.goToRegattaOfEvent(event.id.toString(), searchResult.getLeaderboardName(), searchResult.getBaseURL());
}
@UiHandler("eventOverviewLink")
public void goToEventPlace(ClickEvent e) {
EventBaseDTO event = searchResult.getEvent();
if(searchResult.getBaseURL().contains("localhost") || searchResult.getBaseURL().contains("127.0.0.1")) {
navigator.goToEvent(event.id.toString());
} else {
EventPlace eventPlace = new EventPlace(event.id.toString());
EventPlace.Tokenizer t = new Tokenizer();
String remoteEventUrl = searchResult.getBaseURL() + "/gwt/Home.html#" + EventPlace.class.getSimpleName() + ":" + t.getToken(eventPlace);
Window.Location.replace(remoteEventUrl);
}
placeNavigator.goToEvent(event.id.toString(), searchResult.getBaseURL());
}
}
@@ -13,6 +13,7 @@
</div>
<div class="{local_res.css.searchresult_content_item_footer}">
<g:Anchor ui:field="eventOverviewLink" styleName="{local_res.css.searchresult_content_item_footer_link}" />
<span class="{local_res.css.searchresult_content_item_footer_separator}">|</span><span ui:field="resultEventVenue" />
<span class="{local_res.css.searchresult_content_item_footer_separator}">|</span><span ui:field="resultEventDate" />
</div>
</div>
@@ -25,7 +25,8 @@
<div class="{res.mediaCss.small5} {res.mediaCss.smalloffset7} {res.mediaCss.columns}">
<h2><ui:text from='{i18n.solutionsSAPHeadline}'/></h2>
<p><ui:text from='{i18n.solutionsSAPText1}'/></p>
<p><ui:text from='{i18n.solutionsSAPText2}'/></p><a href="#" class="{res.mainCss.button}">Read More</a>
<p><ui:text from='{i18n.solutionsSAPText2}'/></p>
<!-- <a href="#" class="{res.mainCss.button}">Read More</a> -->
</div>
</div>
</div>
@@ -36,7 +37,8 @@
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small5} {res.mediaCss.columns}">
<h2><ui:text from='{i18n.solutionsRaceHeadline}'/></h2>
<p><ui:text from='{i18n.solutionsRaceText}'/></p><a href="#" class="{res.mainCss.button}">Start Tour</a>
<p><ui:text from='{i18n.solutionsRaceText}'/></p>
<!-- <a href="#" class="{res.mainCss.button}">Start Tour</a> -->
</div>
</div>
</div>
@@ -66,7 +68,8 @@
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small5} {res.mediaCss.smalloffset7} {res.mediaCss.columns}">
<h2><ui:text from='{i18n.solutionsSimulatorHeadline}'/></h2>
<p><ui:text from='{i18n.solutionsSimulatorText}'/></p><a href="#" class="{res.mainCss.button}">Learn More</a>
<p><ui:text from='{i18n.solutionsSimulatorText}'/></p>
<!-- <a href="#" class="{res.mainCss.button}">Learn More</a> -->
</div>
</div>
</div>
@@ -0,0 +1,25 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Visibility;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class LiveEventStageTeaser extends StageTeaser {
public LiveEventStageTeaser(EventDTO event, PlaceNavigator placeNavigator) {
super(event);
title.setInnerText(event.getName());
subtitle.setInnerText(event.venue.getName());
countDown.getStyle().setDisplay(Display.NONE);
countDown.getStyle().setVisibility(Visibility.HIDDEN);
bandCount.setAttribute("data-bandcount", "2");
stageTeaserBandsPanel.add(new StageTeaserBand(event, placeNavigator));
stageTeaserBandsPanel.add(new StageTeaserBand(event, placeNavigator));
}
}
@@ -0,0 +1,23 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Visibility;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class PopularEventStageTeaser extends StageTeaser {
public PopularEventStageTeaser(EventDTO event, PlaceNavigator placeNavigator) {
super(event);
title.setInnerText(event.getName());
subtitle.setInnerText(event.venue.getName());
countDown.getStyle().setDisplay(Display.NONE);
countDown.getStyle().setVisibility(Visibility.HIDDEN);
bandCount.setAttribute("data-bandcount", "1");
stageTeaserBandsPanel.add(new StageTeaserBand(event, placeNavigator));
}
}
@@ -1,85 +1,261 @@
/**
* Main stage area
*/
.stage {
display: -webkit-box;
display: -moz-box;
display: -webkit-flex;
display: -ms-flexbox;
display: box;
display: flex;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-o-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: start;
-moz-box-pack: start;
-o-box-pack: start;
-ms-flex-pack: start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
font-size: 16px;
.swipercontainer {
margin: 0 auto;
position: relative;
overflow: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
z-index: 1;
}
.swiperwrapper {
position: relative;
width: 100%;
-webkit-transition-property: -webkit-transform, left, top;
-webkit-transition-duration: 0s;
-webkit-transform: translate3d(0px, 0, 0);
-webkit-transition-timing-function: ease;
-moz-transition-property: -moz-transform, left, top;
-moz-transition-duration: 0s;
-moz-transform: translate3d(0px, 0, 0);
-moz-transition-timing-function: ease;
-o-transition-property: -o-transform, left, top;
-o-transition-duration: 0s;
-o-transform: translate3d(0px, 0, 0);
-o-transition-timing-function: ease;
-o-transform: translate(0px, 0px);
-ms-transition-property: -ms-transform, left, top;
-ms-transition-duration: 0s;
-ms-transform: translate3d(0px, 0, 0);
-ms-transition-timing-function: ease;
-webkit-transition-property: -webkit-transform, left, top;
-moz-transition-property: -moz-transform, left, top;
-o-transition-property: -o-transform, left, top;
-ms-transition-property: -ms-transform, left, top;
transition-property: transform, left, top;
-webkit-transition-duration: 0s;
-moz-transition-duration: 0s;
-o-transition-duration: 0s;
-ms-transition-duration: 0s;
transition-duration: 0s;
-webkit-transform: translate3d(0px, 0, 0);
-moz-transform: translate3d(0px, 0, 0);
-o-transform: translate3d(0px, 0, 0);
-ms-transform: translate3d(0px, 0, 0);
transform: translate3d(0px, 0, 0);
-webkit-transition-timing-function: ease;
-moz-transition-timing-function: ease;
-o-transition-timing-function: ease;
-ms-transition-timing-function: ease;
transition-timing-function: ease;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.swiperslide {
font-size: 15px;
font-size: 1rem;
line-height: 1;
background-position: top center;
float: left;
}
.swiperwp8horizontal {
-ms-touch-action: pan-y;
}
.swiperwp8vertical {
-ms-touch-action: pan-x;
}
.countdown {
font-size: 15px;
font-size: 1rem;
}
.countdown_pane {
border: 0.266666666666667em solid #fff;
background: #008fcc;
color: #fff;
text-align: center;
display: inline-block;
margin: 0.333333333333333em;
padding: 0.666666666666667em;
-webkit-border-radius: 0.666666666666667em;
border-radius: 0.666666666666667em;
width: 4.666666666666667em;
height: 4.666666666666667em;
text-shadow: none;
-webkit-box-shadow: 0 0 18px rgba(0,0,0,0.13), 0 2px 6px rgba(0,0,0,0.25);
box-shadow: 0 0 18px rgba(0,0,0,0.13), 0 2px 6px rgba(0,0,0,0.25);
}
.countdown_pane_count {
font-weight: bold;
font-size: 2em;
line-height: 0.866666666666667em;
}
.countdown_pane_unit {
font-size: 1.2em;
}
.stageteaser {
font-size: 15px;
font-size: 1rem;
position: relative;
width: 100%;
}
.stageteaser_background {
height: 38.666666666666664em;
overflow: hidden;
}
.stageteaser_background_image {
display: block;
background-position: center center;
background-repeat: no-repeat;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
height: 36.25em;
position: relative;
height: 100%;
position: absolute;
left: 0;
right: 0;
-webkit-transition: margin 1s ease;
-moz-transition: margin 1s ease;
-o-transition: margin 1s ease;
-ms-transition: margin 1s ease;
transition: margin 1s ease;
}
.stage_header {
padding: 4.875em;
.stageteaser_content {
height: 38.666666666666664em;
margin-top: -38.666666666666664em;
}
.stageteaser_content_header {
position: absolute;
width: 100%;
padding: 5.2em;
line-height: 0.9;
text-shadow: 0 0 18px rgba(0,0,0,0.13), 0 2px 6px rgba(0,0,0,0.25);
text-align: center;
opacity: 1;
-ms-filter: none;
filter: none;
-webkit-transition: opacity 1s ease;
-moz-transition: opacity 1s ease;
-o-transition: opacity 1s ease;
-ms-transition: opacity 1s ease;
transition: opacity 1s ease;
}
.stage_header_subtitle {
font-size: 1.875em;
.stageteaser_content_headerhidden {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: literal("alpha(opacity=0)");
}
.stageteaser_content_header_subtitle {
font-size: 2em;
font-weight: 400;
color: #fff;
margin: 0;
margin: 0 0 0.533333333333333em;
}
.stage_header_title {
font-size: 4.5em;
.stageteaser_content_header_title {
font-size: 4.8em;
font-weight: 700;
color: #fff;
margin: 0;
}
.stage_header_message {
font-size: 1.875em;
font-weight: 600;
color: #fff;
margin: 0;
.stageteaser_content_header_countdown {
font-size: 15px;
font-size: 1rem;
}
.stage_band {
.stageteaser_content_band {
position: absolute;
bottom: 0;
right: 0;
left: 0;
right: 0;
background-color: rgba(51,51,51,0.6);
text-align: center;
padding: 1.5625em;
padding: 1.4em 1.666666666666667em;
}
.stage_band_message {
.stageteaser_content_band_item {
padding: 0 2em;
}
.stageteaser_content_band[data-bandcount="2"] .stageteaser_content_band_item {
width: 50%;
float: left;
}
.stageteaser_content_band[data-bandcount="2"] .stageteaser_content_band_item:first-child {
border-right: solid 1px #82868b;
}
.stageteaser_content_band_text {
display: inline-block;
}
.stageteaser_content_band_text_headline {
color: #f0ab00;
font-size: 1.5em;
font-size: 1.2em;
font-weight: 700;
text-shadow: 0 0 0.625em rgba(51,51,51,0.45);
text-shadow: 0 0 0.666666666666667em rgba(51,51,51,0.45);
text-transform: uppercase;
margin: 0.466666666666667em 0 0.2em;
}
.stage_band_name {
display: inline-block;
.stageteaser_content_band_text_name {
color: #fff;
font-size: 1.5em;
text-shadow: 0 0 0.625em rgba(51,51,51,0.45);
font-size: 1.066666666666667em;
text-shadow: 0 0 0.666666666666667em rgba(51,51,51,0.45);
}
.stage_band_action {
font-size: 1.125em;
padding: 0.875em 1.875em;
margin-left: 1.25em;
text-transform: none;
.stageteaser_content_band_action {
float: right;
font-size: 1.2em;
padding: 0.4em 0.933333333333333em;
margin: 0.7em 0 0.5em;
}
.stageteaser_content_band_item[data-bandcount="1"] {
text-align: center;
padding: 0.7em 0.7em 0.55em;
}
.stageteaser_content_band_item[data-bandcount="1"] .stageteaser_content_band_text {
font-size: 18px;
font-size: 1.2rem;
}
.stageteaser_content_band_item[data-bandcount="1"] .stageteaser_content_band_text_headline {
display: inline-block;
margin: 5px 0 0;
}
.stageteaser_content_band_item[data-bandcount="1"] .stageteaser_content_band_text_headline:after {
content: "–";
margin: 0 0.333333333333333em 0 0.666666666666667em;
}
.stageteaser_content_band_item[data-bandcount="1"] .stageteaser_content_band_text_name {
display: inline-block;
}
.stageteaser_content_band_item[data-bandcount="1"] .stageteaser_content_band_action {
float: none;
margin: 0 0 0 1em;
}
.stage {
font-size: 15px;
font-size: 1rem;
height: 38.666666666666664em;
position: relative;
clear: both;
}
.stage_teasers {
height: 38.666666666666664em;
width: 100%;
}
.stage_controls {
font-size: 15px;
font-size: 1rem;
}
.stage_progress {
height: 0.333333333333333em;
margin-top: -0.333333333333333em;
z-index: 10;
position: relative;
}
.stage_progress_bar {
background-color: #f0ab00;
height: 0.333333333333333em;
width: 0%;
-webkit-transition: width 0.1s linear;
-moz-transition: width 0.1s linear;
-o-transition: width 0.1s linear;
-ms-transition: width 0.1s linear;
transition: width 0.1s linear;
}
@@ -1,45 +1,88 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.idangerous.Swiper;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sse.common.Util.Pair;
public class Stage extends Composite {
@SuppressWarnings("unused")
private EventDTO featuredEvent;
@UiField Label subtitle;
@UiField Label title;
@UiField Label message;
@UiField SpanElement regattaState;
@UiField SpanElement actionMessage;
@SuppressWarnings("unused")
private List<Pair<StageEventType, EventDTO>> featuredEvents;
private List<StageTeaser> stageTeaserComposites;
@UiField HTMLPanel stageElementsPanel;
@UiField Anchor nextStageTeaserLink;
@UiField Anchor prevStageTeaserLink;
private StageTeaser stageTeaser;
private Swiper swiper;
private final PlaceNavigator placeNavigator;
interface StageUiBinder extends UiBinder<Widget, Stage> {
}
private static StageUiBinder uiBinder = GWT.create(StageUiBinder.class);
public Stage() {
public Stage(PlaceNavigator placeNavigator) {
this.placeNavigator = placeNavigator;
StageResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
}
public void setFeaturedEvent(EventDTO featuredEvent) {
this.featuredEvent = featuredEvent;
title.setText(featuredEvent.getName());
subtitle.setText(featuredEvent.venue.getName());
message.setText(EventDatesFormatterUtil.formatDateRangeWithYear(featuredEvent.startDate, featuredEvent.endDate));
actionMessage.setInnerText("[Race 6]");
regattaState.setInnerText("Next Race");
stageTeaserComposites = new ArrayList<StageTeaser>();
}
public void setFeaturedEvents(List<Pair<StageEventType, EventDTO>> featuredEvents) {
this.featuredEvents = featuredEvents;
for(Pair<StageEventType, EventDTO> typeAndEvent: featuredEvents) {
switch (typeAndEvent.getA()) {
case POPULAR:
stageTeaser = new PopularEventStageTeaser(typeAndEvent.getB(), placeNavigator);
break;
case RUNNING:
stageTeaser = new LiveEventStageTeaser(typeAndEvent.getB(), placeNavigator);
break;
case UPCOMING_SOON:
stageTeaser = new UpcomingEventStageTeaser(typeAndEvent.getB(), placeNavigator);
break;
}
stageElementsPanel.add(stageTeaser);
stageTeaserComposites.add(stageTeaser);
}
this.swiper = Swiper.createWithDefaultOptions(StageResources.INSTANCE.css().stage_teasers(),
StageResources.INSTANCE.css().swiperwrapper(),
StageResources.INSTANCE.css().swiperslide());
}
@UiHandler("nextStageTeaserLink")
public void nextStageTeaserLinkClicked(ClickEvent e) {
if (this.swiper != null) {
this.swiper.swipeNext();
}
}
@UiHandler("prevStageTeaserLink")
public void prevStageTeaserLinkClicked(ClickEvent e) {
if (this.swiper != null) {
this.swiper.swipePrev();
}
}
}
@@ -3,27 +3,19 @@
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="media_res" type="com.sap.sailing.gwt.home.client.shared.mainmedia.MainMediaResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.stage.StageResources" />
<g:HTMLPanel>
<!-- The main stage -->
<div style="background-image: url('images/home/banner-background.jpg')" class="{local_res.css.stage}">
<header class="{local_res.css.stage_header}">
<p class="{local_res.css.stage_header_subtitle}"><g:Label ui:field='subtitle' /></p>
<h2 class="{local_res.css.stage_header_title}"><g:Label ui:field='title' /></h2>
<div class="{local_res.css.stage_header_message}"><g:Label ui:field='message' /></div>
</header>
<div class="{local_res.css.stage_band}">
<div class="{res.mainCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<div class="{local_res.css.stage_band_message}"><span ui:field='regattaState' />&nbsp;-
</div>
<div class="{local_res.css.stage_band_name}"><span ui:field='actionMessage' /></div>
<button class="{res.mainCss.button} {local_res.css.stage_band_action}">
<ui:text from='{i18n.fullEventSchedule}'/>
</button>
</div>
</div>
</div>
</div>
<div class="{local_res.css.stage}">
<div class="{local_res.css.stage_teasers} {local_res.css.swipercontainer}">
<g:HTMLPanel ui:field="stageElementsPanel" styleName="{local_res.css.swiperwrapper}" />
</div>
<div class="{local_res.css.stage_progress}">
<div class="{local_res.css.stage_progress_bar}"></div>
</div>
<g:Anchor ui:field="prevStageTeaserLink" styleName="{local_res.css.stage_controls} {media_res.css.media_slideshow_controls} {media_res.css.media_slideshow_controlsprev}"></g:Anchor>
<g:Anchor ui:field="nextStageTeaserLink" styleName="{local_res.css.stage_controls} {media_res.css.media_slideshow_controls} {media_res.css.media_slideshow_controlsnext}"></g:Anchor>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,5 @@
package com.sap.sailing.gwt.home.client.shared.stage;
public enum StageEventType {
RUNNING, UPCOMING_SOON, POPULAR
}
@@ -11,14 +11,34 @@ public interface StageResources extends ClientBundle {
LocalCss css();
public interface LocalCss extends CssResource {
String countdown();
String countdown_pane();
String countdown_pane_count();
String countdown_pane_unit();
String stageteaser();
String stageteaser_background();
String stageteaser_background_image();
String stageteaser_content();
String stageteaser_content_header();
String stageteaser_content_headerhidden();
String stageteaser_content_header_subtitle();
String stageteaser_content_header_title();
String stageteaser_content_header_countdown();
String stageteaser_content_band();
String stageteaser_content_band_item();
String stageteaser_content_band_text();
String stageteaser_content_band_text_headline();
String stageteaser_content_band_text_name();
String stageteaser_content_band_action();
String swipercontainer();
String swiperwrapper();
String swiperslide();
String swiperwp8horizontal();
String swiperwp8vertical();
String stage();
String stage_header();
String stage_header_subtitle();
String stage_header_title();
String stage_header_message();
String stage_band();
String stage_band_message();
String stage_band_name();
String stage_band_action();
String stage_teasers();
String stage_controls();
String stage_progress();
String stage_progress_bar();
}
}
@@ -0,0 +1,37 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public abstract class StageTeaser extends Composite {
@UiField DivElement bandCount;
@UiField SpanElement subtitle;
@UiField SpanElement title;
@UiField DivElement countDown;
@UiField HTMLPanel stageTeaserBandsPanel;
@UiField DivElement teaserImage;
private final static String DEFAULT_STAGE_IMAGE_URL = "http://static.sapsailing.com/ubilabsimages/default/default_stage_event_teaser.jpg";
interface StageTeaserUiBinder extends UiBinder<Widget, StageTeaser> {
}
private static StageTeaserUiBinder uiBinder = GWT.create(StageTeaserUiBinder.class);
public StageTeaser(EventDTO event) {
StageResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
String stageImageUrl = event.getStageImageURL() != null ? event.getStageImageURL() : DEFAULT_STAGE_IMAGE_URL;
String backgroundImage = "url(" + stageImageUrl + ")";
teaserImage.getStyle().setBackgroundImage(backgroundImage);
}
}
@@ -0,0 +1,38 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.stage.StageResources" />
<g:HTMLPanel styleName="{local_res.css.stageteaser} {local_res.css.swiperslide}">
<div class="{local_res.css.stageteaser_background}">
<div ui:field="teaserImage" class="{local_res.css.stageteaser_background_image}" />
</div>
<div class="{local_res.css.stageteaser_content}">
<header class="{local_res.css.stageteaser_content_header}">
<p class="{local_res.css.stageteaser_content_header_subtitle}">
<span ui:field="subtitle" />
</p>
<h2 class="{local_res.css.stageteaser_content_header_title}">
<span ui:field="title" />
</h2>
<div ui:field="countDown" data-starttime="" data-days="" data-hours="" data-minutes="" data-seconds="" class="{local_res.css.stageteaser_content_header_countdown} {local_res.css.countdown}">
<div class="{local_res.css.countdown_pane}">
<div class="{local_res.css.countdown_pane_count}"></div>
<div class="{local_res.css.countdown_pane_unit}"></div>
</div>
<div class="{local_res.css.countdown_pane}">
<div class="{local_res.css.countdown_pane_count}"></div>
<div class="{local_res.css.countdown_pane_unit}"></div>
</div>
</div>
</header>
</div>
<div ui:field="bandCount" data-bandcount="" class="{local_res.css.stageteaser_content_band}">
<div class="{res.mainCss.grid}">
<g:HTMLPanel ui:field="stageTeaserBandsPanel" />
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,47 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.home.client.shared.EventDatesFormatterUtil;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class StageTeaserBand extends Composite {
interface StageTeaserBandUiBinder extends UiBinder<Widget, StageTeaserBand> {
}
private static StageTeaserBandUiBinder uiBinder = GWT.create(StageTeaserBandUiBinder.class);
@UiField SpanElement bandTitle;
@UiField SpanElement bandSubtitle;
@UiField Anchor actionLink;
private final PlaceNavigator placeNavigator;
private final EventDTO event;
public StageTeaserBand(EventDTO event, PlaceNavigator placeNavigator) {
this.event = event;
this.placeNavigator = placeNavigator;
StageResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
bandTitle.setInnerText(event.getName());
bandSubtitle.setInnerText(EventDatesFormatterUtil.formatDateRangeWithYear(event.startDate, event.endDate));
actionLink.setText("Show event");
}
@UiHandler("actionLink")
public void actionLinkClicked(ClickEvent e) {
placeNavigator.goToEvent(event.id.toString(), event.getBaseURL());
}
}
@@ -0,0 +1,19 @@
<!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">
<ui:with field="i18n" type="com.sap.sailing.gwt.home.client.i18n.TextMessages"/>
<ui:with field="res" type="com.sap.sailing.gwt.home.client.HomeResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.client.shared.stage.StageResources" />
<g:HTMLPanel>
<div class="{local_res.css.stageteaser_content_band_item} {res.mediaCss.columns}">
<div class="{local_res.css.stageteaser_content_band_text}">
<div class="{local_res.css.stageteaser_content_band_text_headline}"><span ui:field="bandTitle" /></div>
<div class="{local_res.css.stageteaser_content_band_text_name}"><span ui:field="bandSubtitle" /></div>
</div>
<g:Anchor ui:field="actionLink" styleName="{res.mainCss.button} {local_res.css.stageteaser_content_band_action}" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -0,0 +1,24 @@
package com.sap.sailing.gwt.home.client.shared.stage;
import com.sap.sailing.gwt.home.client.app.PlaceNavigator;
import com.sap.sailing.gwt.ui.shared.EventDTO;
public class UpcomingEventStageTeaser extends StageTeaser {
public UpcomingEventStageTeaser(EventDTO event, PlaceNavigator placeNavigator) {
super(event);
title.setInnerText(event.getName());
subtitle.setInnerText(event.venue.getName());
countDown.setAttribute("data-starttime", event.startDate.toString());
countDown.setAttribute("data-days", "");
countDown.setAttribute("data-hours", "");
countDown.setAttribute("data-minutes", "");
countDown.setAttribute("data-seconds", "");
bandCount.setAttribute("data-bandcount", "1");
stageTeaserBandsPanel.add(new StageTeaserBand(event, placeNavigator));
}
}
@@ -0,0 +1,30 @@
package com.sap.sailing.gwt.idangerous;
import com.google.gwt.core.client.JavaScriptObject;
/**
* Wrapping http://www.idangero.us/sliders/swiper/
*
*/
public final class Swiper extends JavaScriptObject {
protected Swiper() {};
public static native Swiper createWithDefaultOptions(String containerClass, String wrapperClass, String slideClass) /*-{
var options = {
loop: true,
wrapperClass: wrapperClass,
slideClass: slideClass
};
return new $wnd.Swiper('.'+containerClass, options);
}-*/;
public native void swipeNext() /*-{
this.swipeNext();
}-*/;
public native void swipePrev() /*-{
this.swipePrev();
}-*/;
}
@@ -97,6 +97,8 @@ public interface SailingService extends RemoteService {
List<RegattaDTO> getRegattas();
RegattaDTO getRegattaByName(String regattaName);
List<EventDTO> getEvents() throws Exception;
List<EventBaseDTO> getPublicEventsOfAllSailingServers() throws Exception;
@@ -517,5 +519,5 @@ public interface SailingService extends RemoteService {
/**
* @return The RaceDTO of the modified race or <code>null</code>, if the given newStartTimeReceived was null.
*/
RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived);
RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived);
}
@@ -84,6 +84,9 @@ public interface SailingServiceAsync {
void getRegattas(AsyncCallback<List<RegattaDTO>> callback);
void getRegattaByName(String regattaName, AsyncCallback<RegattaDTO> asyncCallback);
/**
* The string returned in the callback's pair is the common event name
* @param listHiddenRaces
@@ -479,7 +482,7 @@ public interface SailingServiceAsync {
void getBuildVersion(AsyncCallback<String> callback);
void stopReplicatingFromMaster(AsyncCallback<Void> asyncCallback);
void getRegattaStructureForEvent(UUID eventId, AsyncCallback<List<RaceGroupDTO>> asyncCallback);
void getRaceStateEntriesForRaceGroup(UUID eventId, List<UUID> visibleCourseAreas,
@@ -47,6 +47,12 @@ import com.sap.sse.gwt.client.player.Timer;
import com.sap.sse.gwt.client.player.Timer.PlayModes;
import com.sap.sse.gwt.client.player.Timer.PlayStates;
/**
* The media selector is used as an {@link AsyncCallback} that receives a collection of {@link MediaTrack}s in case the
* call was successful. This could, e.g., be a call to
* {@link MediaServiceAsync#getMediaTracksForRace(RegattaAndRaceIdentifier, AsyncCallback)}. When the call returns the
* track collection, the UI is updated accordingly.
*/
public class MediaSelector implements PlayStateListener, TimeListener,
AsyncCallback<Collection<MediaTrack>>, MediaSelectionListener, CloseHandler<Window>, ClosingHandler {
@@ -82,7 +88,7 @@ public class MediaSelector implements PlayStateListener, TimeListener,
this.stringMessages = stringMessages;
this.errorReporter = errorReporter;
this.user = user;
this.autoSelectMedia = autoSelectMedia;
this.autoSelectMedia = autoSelectMedia;
Window.addCloseHandler(this);
Window.addWindowClosingHandler(this);
@@ -91,7 +97,6 @@ public class MediaSelector implements PlayStateListener, TimeListener,
manageMediaButton = new Button();
manageMediaButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (mediaSelectionDialog.isShowing()) {
@@ -288,7 +293,7 @@ public class MediaSelector implements PlayStateListener, TimeListener,
toggleMediaButton.setValue(autoSelectMedia);
if (autoSelectMedia) {
playDefault();
playDefault();
}
}
@@ -782,6 +782,9 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
return LatLng.newInstance(lat2 / Math.PI * 180., lon2 / Math.PI * 180.);
}
/**
* Returns a pair whose first component is the leg number (one-based) of the competitor returned as the second component.
*/
private com.sap.sse.common.Util.Pair<Integer, CompetitorDTO> getLeadingVisibleCompetitorInfo(Iterable<CompetitorDTO> competitorsToShow) {
CompetitorDTO leadingCompetitorDTO = null;
int legOfLeaderCompetitor = -1;
@@ -789,7 +792,7 @@ public class RaceMap extends AbsolutePanel implements TimeListener, CompetitorSe
for (QuickRankDTO quickRank : quickRanks) {
if (Util.contains(competitorsToShow, quickRank.competitor)) {
leadingCompetitorDTO = quickRank.competitor;
legOfLeaderCompetitor = quickRank.legNumber;
legOfLeaderCompetitor = quickRank.legNumberOneBased;
return new com.sap.sse.common.Util.Pair<Integer, CompetitorDTO>(legOfLeaderCompetitor, leadingCompetitorDTO);
}
}
@@ -271,9 +271,15 @@ public class RaceBoardPanel extends SimplePanel implements RegattasDisplayer, Ra
return filterSets;
}
/**
* Adds the media selector drop down and fills it with media for the current race.
* NOTE:
* Media selector will NOT listen and react to changes of the start time during a race board session.
* This case and its consequences are considered negligible.
* Consequently, media selector will also NOT react on media added newly during a race board session.
*/
private void addMediaSelectorToNavigationMenu() {
MediaSelector mediaSelector = new MediaSelector(selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, stringMessages, errorReporter, this.user, getConfiguration().isAutoSelectMedia());
// raceTimesInfoProvider.addRaceTimesInfoProviderListener(mediaSelector);
timer.addPlayStateListener(mediaSelector);
timer.addTimeListener(mediaSelector);
mediaService.getMediaTracksForRace(selectedRaceIdentifier, mediaSelector);
@@ -736,7 +736,7 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
@Override
public List<RegattaDTO> getRegattas() throws IllegalArgumentException {
public List<RegattaDTO> getRegattas() {
List<RegattaDTO> result = new ArrayList<RegattaDTO>();
for (Regatta regatta : getService().getAllRegattas()) {
result.add(convertToRegattaDTO(regatta));
@@ -744,6 +744,18 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
return result;
}
@Override
public RegattaDTO getRegattaByName(String regattaName) {
RegattaDTO result = null;
if (regattaName != null && !regattaName.isEmpty()) {
Regatta regatta = getService().getRegatta(new RegattaName(regattaName));
if (regatta != null) {
result = convertToRegattaDTO(regatta);
}
}
return result;
}
private MarkDTO convertToMarkDTO(Mark mark, Position position) {
MarkDTO markDTO;
if(position != null) {
@@ -1865,8 +1877,8 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
for (Competitor competitor : trackedRace.getCompetitorsFromBestToWorst(dateAsTimePoint)) {
TrackedLegOfCompetitor trackedLeg = trackedRace.getTrackedLeg(competitor, dateAsTimePoint);
if (trackedLeg != null) {
int legNumber = race.getCourse().getLegs().indexOf(trackedLeg.getLeg()) + 1;
QuickRankDTO quickRankDTO = new QuickRankDTO(baseDomainFactory.convertToCompetitorDTO(competitor), rank, legNumber);
int legNumberOneBased = race.getCourse().getLegs().indexOf(trackedLeg.getLeg()) + 1;
QuickRankDTO quickRankDTO = new QuickRankDTO(baseDomainFactory.convertToCompetitorDTO(competitor), rank, legNumberOneBased);
result.add(quickRankDTO);
}
rank++;
@@ -35,7 +35,7 @@ public class CompactRaceMapDataDTO implements IsSerializable {
}
this.quickRanks = new ArrayList<CompactQuickRankDTO>(quickRanks.size());
for (QuickRankDTO quickRank : quickRanks) {
this.quickRanks.add(new CompactQuickRankDTO(quickRank.competitor.getIdAsString(), quickRank.rank, quickRank.legNumber));
this.quickRanks.add(new CompactQuickRankDTO(quickRank.competitor.getIdAsString(), quickRank.rank, quickRank.legNumberOneBased));
}
this.courseSidelines = courseSidelines;
this.coursePositions = coursePositions;
@@ -97,6 +97,27 @@ public class EventBaseDTO extends NamedDTO implements IsSerializable {
return imageURLs;
}
public String getStageImageURL() {
String result = null;
for(String imageUrl: imageURLs) {
if(imageUrl.contains("stage") || imageUrl.contains("STAGE")) {
result = imageUrl;
break;
}
}
return result;
}
public List<String> getPhotoGalleryImageURLs() {
List<String> result = new ArrayList<String>();
for(String imageUrl: imageURLs) {
if(!imageUrl.contains("stage") && !imageUrl.contains("STAGE")) {
result.add(imageUrl);
}
}
return result;
}
public List<String> getVideoURLs() {
return videoURLs;
}
@@ -45,7 +45,7 @@ public class EventDTO extends EventBaseDTO {
leaderboardGroups.add(leaderboardGroup);
}
public Iterable<LeaderboardGroupDTO> getLeaderboardGroups() {
public List<LeaderboardGroupDTO> getLeaderboardGroups() {
return leaderboardGroups;
}
@@ -6,13 +6,17 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO;
public class QuickRankDTO implements IsSerializable {
public CompetitorDTO competitor;
public int rank;
public int legNumber;
/**
* The {@link #competitor}'s leg number, starting with 1 for the first leg
*/
public int legNumberOneBased;
public QuickRankDTO() {}
public QuickRankDTO(CompetitorDTO competitorDTO, int rank, int legNumber) {
public QuickRankDTO(CompetitorDTO competitorDTO, int rank, int legNumberOneBased) {
this.competitor = competitorDTO;
this.rank = rank;
this.legNumber = legNumber;
this.legNumberOneBased = legNumberOneBased;
}
}
@@ -74,4 +74,5 @@
<source path='ui/actions' />
<source path='ui/simulator' />
<source path='home' />
<source path='idangerous' />
</module>
@@ -238,3 +238,101 @@ figcaption {
.mainsection_navigation {
text-align: center;
}
.lightbox {
font-size: 16px;
font-size: 1rem;
}
.lightbox_overlay {
font-size: 16px;
font-size: 1rem;
background: #000;
opacity: 0.7;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
filter: literal("alpha(opacity=70)");
width: 100%;
height: 100%;
position: fixed;
left: 0;
top: 0;
z-index: 2000;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
}
.lightbox_overlayhidden {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.lightbox_content {
position: fixed;
width: 100%;
height: 100%;
opacity: 1;
-ms-filter: none;
filter: none;
top: 0;
left: 0;
z-index: 2001;
background-repeat: no-repeat;
background-position: center center;
-webkit-transition: opacity 0.3s ease;
-moz-transition: opacity 0.3s ease;
-o-transition: opacity 0.3s ease;
-ms-transition: opacity 0.3s ease;
transition: opacity 0.3s ease;
}
.lightbox_contenthidden {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.lightbox_content_enlargedimage {
-webkit-transition: margin 0.7s linear;
-moz-transition: margin 0.7s linear;
-o-transition: margin 0.7s linear;
-ms-transition: margin 0.7s linear;
transition: margin 0.7s linear;
display: inline-block;
position: absolute;
left: 50%;
top: 50%;
}
.lightbox_content_enlargedimage_caption {
text-align: center;
color: #f6f9fc;
font-weight: 700;
}
.lightbox_content_enlargedimage_close {
display: inline-block;
background-image: url("images/home/x_lightbox.png");
background-repeat: no-repeat;
background-position: center center;
width: 1.25em;
height: 0;
overflow: hidden;
padding-top: 1.25em;
position: absolute;
top: 1.25em;
right: 1.25em;
cursor: pointer;
z-index: 2003;
}
/**
.lightbox_content .media_slideshow_controls {
z-index: 2002;
}
*/
.lightbox_data {
display: none;
}
.lightbox_photo {
cursor: pointer;
}
.lightbox_item {
}
@@ -15,12 +15,11 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.sap.sailing.domain.common.media.MediaTrack;
import com.sap.sailing.domain.common.media.MediaUtil;
import com.sap.sailing.util.impl.LockUtil;
import com.sap.sailing.util.impl.NamedReentrantReadWriteLock;
class MediaLibrary {
@@ -68,9 +67,7 @@ class MediaLibrary {
*/
private final ConcurrentMap<Interval, Set<MediaTrack>> cacheByInterval = new ConcurrentHashMap<Interval, Set<MediaTrack>>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
private final NamedReentrantReadWriteLock lock = new NamedReentrantReadWriteLock(MediaLibrary.class.getName(), /* fair */ false);
// /**
// * Sort in reverse order of start time! For equal start times compare dbId to distinguish different instances.
@@ -94,7 +91,7 @@ class MediaLibrary {
* performance gain.
*
* Actually, efficient lookup of overlapping intervals is supposed to be performed using an interval tree, e.g.
* http://thekevindolan.com/2010/02/interval-tree/
* http://en.wikipedia.org/wiki/Interval_tree.
*
* However, considering the expected low number of media entries and the expected high rate of cache hits doesn't
* justify providing a dedicated interval tree implementation (given that there's none readily available).
@@ -112,7 +109,7 @@ class MediaLibrary {
if (startTime != null) {
Interval interval = new Interval(startTime, endTime);
readLock.lock();
LockUtil.lockForRead(lock);
try {
Set<MediaTrack> cachedMediaTracks = cacheByInterval.get(interval);
if (cachedMediaTracks == null) {
@@ -134,7 +131,7 @@ class MediaLibrary {
}
} finally {
readLock.unlock();
LockUtil.unlockAfterRead(lock);
}
}
// else
@@ -152,65 +149,65 @@ class MediaLibrary {
}
void addMediaTracks(Collection<MediaTrack> mediaTracks) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
for (MediaTrack mediaTrack : mediaTracks) {
this.mediaTracksByDbId.put(mediaTrack, mediaTrack);
updateCache_Add(mediaTrack);
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void deleteMediaTrack(MediaTrack mediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack deletedMediaTrack = mediaTracksByDbId.remove(mediaTrack);
updateCache_Remove(deletedMediaTrack);
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void titleChanged(MediaTrack changedMediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
if (mediaTrack != null) {
mediaTrack.title = changedMediaTrack.title;
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void urlChanged(MediaTrack changedMediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
if (mediaTrack != null) {
mediaTrack.url = changedMediaTrack.url;
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void mimeTypeChanged(MediaTrack changedMediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
if (mediaTrack != null) {
mediaTrack.mimeType = changedMediaTrack.mimeType;
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void startTimeChanged(MediaTrack changedMediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
if (mediaTrack != null) {
@@ -218,12 +215,12 @@ class MediaLibrary {
updateCache_Change(mediaTrack);
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
void durationChanged(MediaTrack changedMediaTrack) {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
MediaTrack mediaTrack = mediaTracksByDbId.get(changedMediaTrack);
if (mediaTrack != null) {
@@ -231,7 +228,7 @@ class MediaLibrary {
updateCache_Change(mediaTrack);
}
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}
@@ -273,20 +270,20 @@ class MediaLibrary {
* Returns a non-live copy of the media tracks
*/
Collection<MediaTrack> allTracks() {
readLock.lock();
LockUtil.lockForRead(lock);
try {
return new ArrayList<MediaTrack>(mediaTracksByDbId.values());
} finally {
readLock.unlock();
LockUtil.unlockAfterRead(lock);
}
}
void serialize(ObjectOutputStream stream) throws IOException {
readLock.lock();
LockUtil.lockForRead(lock);
try {
stream.writeObject(new ArrayList<MediaTrack>(mediaTracksByDbId.values()));
} finally {
readLock.unlock();
LockUtil.unlockAfterRead(lock);
}
}
@@ -296,12 +293,12 @@ class MediaLibrary {
}
public void clear() {
writeLock.lock();
LockUtil.lockForWrite(lock);
try {
mediaTracksByDbId.clear();
cacheByInterval.clear();
} finally {
writeLock.unlock();
LockUtil.unlockAfterWrite(lock);
}
}