Merge remote-tracking branch 'origin/master' into bug2610_lifecycle

# Conflicts:
#	java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java
This commit is contained in:
fmittag committed 2016-03-08 13:02:51 +01:00
commit 32bf2bcee0
298 files changed
+4630 -2055

No files matched your search

@@ -1,37 +1,63 @@
package com.sap.sailing.domain.common.impl;
import java.net.URLEncoder;
import com.sap.sse.common.Util;
import java.util.HashMap;
import java.util.Map;
/**
* This class is used by our backend, in GWT-client code and by the Android app. Therefore we cannot use classes like
* {@link URLEncoder} to help us with the encoding.
*/
public class DeviceConfigurationQRCodeUtils {
public static final String fragmentKey = "identifier";
public static String composeQRContent(String deviceIdentifier, String apkUrl) {
// poor man's uri fragment encoding: ' ' as '%20'
String encodedIdentifier = deviceIdentifier.replaceAll(" ", "%20");
return apkUrl + "#" + fragmentKey + "=" + encodedIdentifier;
public static final String deviceIdentifierKey = "identifier";
public static final String accessTokenKey = "token";
public static class DeviceConfigurationDetails {
private final String apkUrl;
private final String deviceIdentifier;
private final String accessToken;
public DeviceConfigurationDetails(String apkUrl, String deviceIdentifier, String accessToken) {
super();
this.apkUrl = apkUrl;
this.deviceIdentifier = deviceIdentifier;
this.accessToken = accessToken;
}
public String getApkUrl() {
return apkUrl;
}
public String getDeviceIdentifier() {
return deviceIdentifier;
}
public String getAccessToken() {
return accessToken;
}
}
public static Util.Pair<String, String> splitQRContent(String qrCodeContent) {
public static String composeQRContent(String deviceIdentifier, String apkUrl, String accessToken) {
// poor man's uri fragment encoding: ' ' as '%20'
String encodedIdentifier = deviceIdentifier.replaceAll(" ", "%20");
return apkUrl + "#" + deviceIdentifierKey + "=" + encodedIdentifier+"&"+accessTokenKey + "=" + accessToken;
}
public static DeviceConfigurationDetails splitQRContent(String qrCodeContent) {
int fragmentIndex = qrCodeContent.lastIndexOf('#');
if (fragmentIndex == -1 || fragmentIndex == 0 || qrCodeContent.length() == fragmentIndex + 1) {
throw new IllegalArgumentException("There is no server or identifier.");
}
String deviceIdentifier = qrCodeContent.substring(fragmentIndex + 1, qrCodeContent.length());
if (!deviceIdentifier.startsWith(fragmentKey + "=")) {
throw new IllegalArgumentException("The identifier is malformed");
String fragment = qrCodeContent.substring(fragmentIndex + 1, qrCodeContent.length());
final String[] params = fragment.split("&");
final Map<String, String> paramMap = new HashMap<>();
for (String param : params) {
final String[] keyValue = param.split("=", 2);
if (keyValue.length == 2) {
paramMap.put(keyValue[0], keyValue[1].replaceAll("%20", " "));
}
}
if (!paramMap.containsKey(deviceIdentifierKey)) {
throw new IllegalArgumentException("Device identifier missing from QR code contents");
}
deviceIdentifier = deviceIdentifier.substring((fragmentKey + "=").length());
deviceIdentifier = deviceIdentifier.replaceAll("%20", " ");
String apkUrl = qrCodeContent.substring(0, fragmentIndex);
return new Util.Pair<String, String>(deviceIdentifier, apkUrl);
return new DeviceConfigurationDetails(apkUrl, paramMap.get(deviceIdentifierKey), paramMap.get(accessTokenKey));
}
}
@@ -1,6 +1,10 @@
package com.sap.sailing.domain.common.security;
public enum Permission implements com.sap.sse.security.shared.Permission {
// AdminConsole permissions
MANAGE_EVENTS,
MANAGE_REGATTAS,
MANAGE_TRACKED_RACES,
@@ -11,6 +15,7 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
MANAGE_WIND,
MANAGE_IGTIMI_ACCOUNTS,
MANAGE_LEADERBOARDS,
MANAGE_LEADERBOARD_RESULTS,
MANAGE_LEADERBOARD_GROUPS,
MANAGE_RESULT_IMPORT_URLS,
MANAGE_STRUCTURE_IMPORT_URLS,
@@ -23,10 +28,69 @@ public enum Permission implements com.sap.sse.security.shared.Permission {
MANAGE_USERS,
MANAGE_FILE_STORAGE,
MANAGE_MARK_PASSINGS,
CAN_REPLAY_DURING_LIVE_RACES;
CAN_REPLAY_DURING_LIVE_RACES,
// back-end permissions
EVENT,
REGATTA,
LEADERBOARD,
LEADERBOARD_GROUP,
TRACKED_RACE
;
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
@Override
public String getStringPermission() {
return name()+":";
public String getStringPermission(com.sap.sse.security.shared.Permission.Mode... modes) {
final String result;
if (modes==null || modes.length==0) {
result = name();
} else {
final StringBuilder modesString = new StringBuilder();
boolean first = true;
for (com.sap.sse.security.shared.Permission.Mode mode : modes) {
if (first) {
first = false;
} else {
modesString.append(',');
}
modesString.append(mode.getStringPermission());
}
result = name()+":"+modesString.toString();
}
return result;
}
// TODO once we can use Java8 here, move this up into a "default" method on the Permission interface
@Override
public String getStringPermissionForObjects(com.sap.sse.security.shared.Permission.Mode mode, String... objectIdentifiers) {
final StringBuilder result = new StringBuilder(getStringPermission(mode));
if (objectIdentifiers!=null && objectIdentifiers.length>0) {
result.append(':');
boolean first = true;
for (String objectIdentifier : objectIdentifiers) {
if (first) {
first = false;
} else {
result.append(',');
}
result.append(objectIdentifier);
}
}
return result.toString();
}
/**
* The mode of interaction with a resource; used as the second element of a wildcard permission
*
* @author Axel Uhl (d043530)
*
*/
public static enum Mode implements com.sap.sse.security.shared.Permission.Mode {
CREATE, READ, UPDATE, DELETE;
@Override
public String getStringPermission() {
return name();
}
}
}
@@ -13,13 +13,40 @@ public class SailingPermissionsForRoleProvider implements PermissionsForRoleProv
public Iterable<String> getPermissions(String role) {
final Iterable<String> result;
if (DefaultRoles.ADMIN.getRolename().equals(role)) {
return Collections.<String>singletonList("*");
result = Collections.<String>singletonList("*");
} else if (Roles.eventmanager.getRolename().equals(role)) {
return asList(Permission.MANAGE_MEDIA, Permission.MANAGE_MARK_PASSINGS);
result = asList(
// RaceBoard:
Permission.MANAGE_MEDIA,
Permission.MANAGE_MARK_PASSINGS,
// AdminConsole:
Permission.MANAGE_ALL_COMPETITORS,
Permission.MANAGE_COURSE_LAYOUT,
Permission.MANAGE_DEVICE_CONFIGURATION,
Permission.MANAGE_EVENTS,
Permission.MANAGE_IGTIMI_ACCOUNTS,
Permission.MANAGE_LEADERBOARD_GROUPS,
Permission.MANAGE_LEADERBOARDS,
Permission.MANAGE_LEADERBOARD_RESULTS,
Permission.MANAGE_MEDIA,
Permission.MANAGE_RACELOG_TRACKING,
Permission.MANAGE_REGATTAS,
Permission.MANAGE_RESULT_IMPORT_URLS,
Permission.MANAGE_STRUCTURE_IMPORT_URLS,
Permission.MANAGE_TRACKED_RACES,
Permission.MANAGE_WIND,
// back-end:
Permission.EVENT,
Permission.REGATTA,
Permission.LEADERBOARD,
Permission.LEADERBOARD_GROUP
);
} else if (Roles.mediaeditor.getRolename().equals(role)) {
return asList(Permission.MANAGE_MEDIA);
result = asList(Permission.MANAGE_MEDIA);
} else if (Roles.moderator.getRolename().equals(role)) {
return asList(Permission.CAN_REPLAY_DURING_LIVE_RACES);
result = asList(Permission.CAN_REPLAY_DURING_LIVE_RACES);
} else {
result = Collections.emptyList();
}
@@ -16,7 +16,8 @@ Require-Bundle: org.json.simple;bundle-version="1.1.0",
com.sap.sailing.domain,
com.sap.sailing.declination,
com.sap.sse.common,
com.sap.sse
com.sap.sse,
com.sap.sse.security
Import-Package: javax.ws.rs;version="1.1.1",
javax.ws.rs.core;version="1.1.1",
javax.ws.rs.ext;version="1.1.1",
@@ -6,12 +6,14 @@ import java.util.Set;
import javax.ws.rs.core.Application;
import com.sap.sse.security.jaxrs.ShiroAuthorizationExceptionTo401ResponseMapper;
public class RestApiApplication extends Application {
public RestApiApplication() {
}
@Override
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { AuthorizationCallback.class }));
return new HashSet<Class<?>>(Arrays.asList(new Class<?>[] { AuthorizationCallback.class, ShiroAuthorizationExceptionTo401ResponseMapper.class }));
}
}
@@ -948,7 +948,8 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
try {
for (DBObject object : eventCollection.find()) {
Event event = loadEvent(object);
Boolean requiresStoreAfterMigration = loadLegacyImageAndVideoURLs(event, object);
boolean requiresStoreAfterMigration = loadLegacyImageAndVideoURLs(event, object);
requiresStoreAfterMigration |= loadLegacySailorsInfoWebsiteURL(event, object);
result.add(new Pair<Event, Boolean>(event, requiresStoreAfterMigration));
}
} catch (Exception e) {
@@ -1030,14 +1031,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
logger.severe("Error parsing official website URL "+officialWebSiteURLAsString+" for event "+name+". Ignoring this URL.");
}
}
String sailorsInfoWebSiteURLAsString = (String) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name());
if (sailorsInfoWebSiteURLAsString != null) {
try {
result.setSailorsInfoWebsiteURL(new URL(sailorsInfoWebSiteURLAsString));
} catch (MalformedURLException e) {
logger.severe("Error parsing sailors info website URL "+sailorsInfoWebSiteURLAsString+" for event "+name+". Ignoring this URL.");
}
}
BasicDBList images = (BasicDBList) eventDBObject.get(FieldNames.EVENT_IMAGES.name());
if (images != null) {
for (Object imageObject : images) {
@@ -1056,6 +1049,18 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
}
}
BasicDBList sailorsInfoWebsiteURLs = (BasicDBList) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name());
if (sailorsInfoWebsiteURLs != null) {
for (Object sailorsInfoWebsiteObject : sailorsInfoWebsiteURLs) {
DBObject sailorsInfoWebsiteDBObject = (DBObject) sailorsInfoWebsiteObject;
URL url = loadURL(sailorsInfoWebsiteDBObject, FieldNames.SAILORS_INFO_URL);
String localeRaw = (String) sailorsInfoWebsiteDBObject.get(FieldNames.SAILORS_INFO_LOCALE.name());
if (url != null) {
Locale locale = localeRaw != null ? Locale.forLanguageTag(localeRaw) : null;
result.setSailorsInfoWebsiteURL(locale, url);
}
}
}
return result;
}
@@ -2162,4 +2167,29 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory {
}
return event.setMediaURLs(imageURLs, sponsorImageURLs, videoURLs, logoImageURL, Collections.emptyMap());
}
private boolean loadLegacySailorsInfoWebsiteURL(Event event, DBObject eventDBObject) {
final boolean modified;
final String sailorsInfoWebSiteURLAsString = (String) eventDBObject.get(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name());
if (sailorsInfoWebSiteURLAsString != null) {
try {
// The legacy sailors info URL (only used at Kieler/Travemuender Woche events) used to have 2 localized versions:
// The German version with no suffix (e.g. http://sailorsinfo.travemuender-woche.com)
// The English/international version with "/en" suffix (e.g. http://sailorsinfo.travemuender-woche.com/en)
if (!event.hasSailorsInfoWebsiteURL(null)) {
final String englishURL = sailorsInfoWebSiteURLAsString + (sailorsInfoWebSiteURLAsString.endsWith("/") ? "" : "/") + "en";
event.setSailorsInfoWebsiteURL(null, new URL(englishURL));
}
if (!event.hasSailorsInfoWebsiteURL(Locale.GERMAN)) {
event.setSailorsInfoWebsiteURL(Locale.GERMAN, new URL(sailorsInfoWebSiteURLAsString));
}
} catch (MalformedURLException e) {
logger.severe("Error parsing sailors info website URL "+sailorsInfoWebSiteURLAsString+" for event "+event.getName()+". Ignoring this URL.");
}
modified = true;
} else {
modified = false;
}
return modified;
}
}
@@ -23,6 +23,7 @@ public enum FieldNames {
EVENT_VIDEOS,
EVENT_OFFICIAL_WEBSITE_URL,
EVENT_SAILORS_INFO_WEBSITE_URL,
EVENT_SAILORS_INFO_WEBSITES,
EVENT_LOGO_IMAGE_URL,
REGATTA_NAME,
@@ -148,5 +149,8 @@ public enum FieldNames {
// video fields
VIDEO_URL, VIDEO_LOCALE, VIDEO_TITLE, VIDEO_SUBTITLE, VIDEO_MIMETYPE, VIDEO_COPYRIGHT, VIDEO_CREATEDATDATE,
VIDEO_TAGS, VIDEO_THUMBNAIL_URL, VIDEO_LENGTH_IN_SECONDS;
VIDEO_TAGS, VIDEO_THUMBNAIL_URL, VIDEO_LENGTH_IN_SECONDS,
// sailors info fileds
SAILORS_INFO_URL, SAILORS_INFO_LOCALE;
}
@@ -3,6 +3,8 @@ package com.sap.sailing.domain.persistence.impl;
import java.io.Serializable;
import java.net.URL;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -535,7 +537,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
/**
* StoreEvent() uses some deprecated methods of event to keep backward compatibility.
*/
@SuppressWarnings("deprecation")
@Override
public void storeEvent(Event event) {
DBCollection eventCollection = database.getCollection(CollectionNames.EVENTS.name());
@@ -546,29 +547,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
eventDBObject.put(FieldNames.EVENT_NAME.name(), event.getName());
eventDBObject.put(FieldNames.EVENT_DESCRIPTION.name(), event.getDescription());
eventDBObject.put(FieldNames.EVENT_ID.name(), event.getId());
eventDBObject.put(FieldNames.EVENT_LOGO_IMAGE_URL.name(), event.getLogoImageURL() != null ? event.getLogoImageURL().toString() : null);
eventDBObject.put(FieldNames.EVENT_OFFICIAL_WEBSITE_URL.name(), event.getOfficialWebsiteURL() != null ? event.getOfficialWebsiteURL().toString() : null);
eventDBObject.put(FieldNames.EVENT_SAILORS_INFO_WEBSITE_URL.name(), event.getSailorsInfoWebsiteURL() != null ? event.getSailorsInfoWebsiteURL().toString() : null);
storeTimePoint(event.getStartDate(), eventDBObject, FieldNames.EVENT_START_DATE);
storeTimePoint(event.getEndDate(), eventDBObject, FieldNames.EVENT_END_DATE);
eventDBObject.put(FieldNames.EVENT_IS_PUBLIC.name(), event.isPublic());
DBObject venueDBObject = getVenueAsDBObject(event.getVenue());
eventDBObject.put(FieldNames.VENUE.name(), venueDBObject);
BasicDBList imageURLs = new BasicDBList();
for (URL imageURL : event.getImageURLs()) {
imageURLs.add(imageURL.toString());
}
eventDBObject.put(FieldNames.EVENT_IMAGE_URLS.name(), imageURLs);
BasicDBList videoURLs = new BasicDBList();
for (URL videoURL : event.getVideoURLs()) {
videoURLs.add(videoURL.toString());
}
eventDBObject.put(FieldNames.EVENT_VIDEO_URLS.name(), videoURLs);
BasicDBList sponsorImageURLs = new BasicDBList();
for (URL sponsorImageURL : event.getSponsorImageURLs()) {
sponsorImageURLs.add(sponsorImageURL.toString());
}
eventDBObject.put(FieldNames.EVENT_SPONSOR_IMAGE_URLS.name(), sponsorImageURLs);
BasicDBList images = new BasicDBList();
for (ImageDescriptor image : event.getImages()) {
DBObject imageObject = createImageObject(image);
@@ -581,6 +565,12 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
videos.add(videoObject);
}
eventDBObject.put(FieldNames.EVENT_VIDEOS.name(), videos);
BasicDBList sailorsInfoWebsiteURLs = new BasicDBList();
for(Map.Entry<Locale, URL> sailorsInfoWebsite : event.getSailorsInfoWebsiteURLs().entrySet()) {
DBObject sailorsInfoWebsiteObject = createSailorsInfoWebsiteObject(sailorsInfoWebsite.getKey(), sailorsInfoWebsite.getValue());
sailorsInfoWebsiteURLs.add(sailorsInfoWebsiteObject);
}
eventDBObject.put(FieldNames.EVENT_SAILORS_INFO_WEBSITES.name(), sailorsInfoWebsiteURLs);
eventCollection.update(query, eventDBObject, /* upsrt */ true, /* multi */ false, WriteConcern.SAFE);
// now store the links to the leaderboard groups
DBCollection linksCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUP_LINKS_FOR_EVENTS.name());
@@ -1477,4 +1467,11 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory {
result.put(FieldNames.VIDEO_TAGS.name(), tags);
return result;
}
private DBObject createSailorsInfoWebsiteObject(Locale locale, URL url) {
DBObject result = new BasicDBObject();
result.put(FieldNames.SAILORS_INFO_URL.name(), url.toString());
result.put(FieldNames.SAILORS_INFO_LOCALE.name(), locale != null ? locale.toLanguageTag() : null);
return result;
}
}
@@ -1,6 +1,7 @@
package com.sap.sailing.domain.base;
import java.net.URL;
import java.util.Locale;
import java.util.Map;
import com.sap.sailing.domain.common.Renamable;
@@ -41,38 +42,6 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
void setPublic(boolean isPublic);
/**
* @deprecated
* Returns a non-<code>null</code> live but unmodifiable collection of URLs pointing to image resources that can be
* used to represent the event, e.g., on a web page.
*
* @return a non-<code>null</code> value which may be empty
*/
Iterable<URL> getImageURLs();
/**
* @deprecated
* An event may have zero or more sponsors, each of which usually want to see their logo on the web page.
*
* @return the sponsors' logos; always non-<code>null</code> but possibly empty
*/
Iterable<URL> getSponsorImageURLs();
/**
* @deprecated
* An optional logo image; may return <code>null</code>.
*/
URL getLogoImageURL();
/**
* @deprecated
* Returns a non-<code>null</code> live but unmodifiable collection of URLs pointing to video resources that can be
* used to represent the event, e.g., on a web page.
*
* @return a non-<code>null</code> value which may be empty
*/
Iterable<URL> getVideoURLs();
/**
* @return the URL of the event's official web site, or <code>null</code> if such a site does not exist or its URL
* is not known
@@ -82,12 +51,43 @@ public interface EventBase extends Named, WithDescription, Renamable, WithID, Wi
void setOfficialWebsiteURL(URL officialWebsiteURL);
/**
* @return the URL of an external web site containing sailor related information like protests, official results, etc.
* or <code>null</code> if such a site does not exist or its URL is not known.
* Returns a mapping of Locales to URLs where the URLs are meant as an external web site containing sailor related
* information like protests, official results, etc.
* The default, language independent URL has {@code null} as key.
*
* @return the URLs of an external web site containing sailor related information like protests, official results,
* etc.
*/
URL getSailorsInfoWebsiteURL();
Map<Locale, URL> getSailorsInfoWebsiteURLs();
void setSailorsInfoWebsiteURL(URL sailorsInfoWebsiteURL);
void setSailorsInfoWebsiteURLs(Map<Locale, URL> sailorsInfoWebsiteURLs);
/**
* Sets a sailorsInfoWebsiteURL for the given locale
*/
void setSailorsInfoWebsiteURL(Locale locale, URL sailorsInfoWebsiteURL);
/**
* Checks if there is a sailorsInfoWebsiteURL available for the given locale.
*
* @param locale a locale or null
* @return true if there is a sailorsInfoWebsiteURL available for the given locale
*/
boolean hasSailorsInfoWebsiteURL(Locale locale);
/**
* @param locale a locale to get the associated sailors info website URL for
* @return the URL of an external web site containing sailor related information like protests, official results, etc.
* or <code>null</code> if such a site does not exist for the given locale or its URL is not known.
*/
URL getSailorsInfoWebsiteURL(Locale locale);
/**
* Gets the sailorsInfoWebsiteURL for the given locale. If there is no sailorsInfoWebsiteURL for the specific locale
* but there is a default sailorsInfoWebsiteURL available, this one is returned.
* So this method returns the best available sailorsInfoWebsiteURL for a user who uses the given locale.
*/
URL getSailorsInfoWebsiteURLOrFallback(Locale locale);
Iterable<? extends LeaderboardGroupBase> getLeaderboardGroups();
@@ -6,6 +6,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -18,6 +19,7 @@ import com.sap.sse.common.Util.Pair;
import com.sap.sse.common.media.ImageSize;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.concurrent.CopyOnWriteHashMap;
import com.sap.sse.shared.media.ImageDescriptor;
import com.sap.sse.shared.media.MediaDescriptor;
import com.sap.sse.shared.media.MediaUtils;
@@ -26,7 +28,7 @@ import com.sap.sse.shared.media.impl.ImageDescriptorImpl;
import com.sap.sse.shared.media.impl.VideoDescriptorImpl;
public abstract class EventBaseImpl implements EventBase {
private static final long serialVersionUID = -5749964088848611074L;
private static final long serialVersionUID = -4055554853909324357L;
private String name;
private String description;
@@ -36,7 +38,7 @@ public abstract class EventBaseImpl implements EventBase {
private TimePoint startDate;
private TimePoint endDate;
private URL officialWebsiteURL;
private URL sailorsInfoWebsiteURL;
private CopyOnWriteHashMap<Locale, URL> sailorsInfoWebsiteURLs;
private ConcurrentLinkedQueue<ImageDescriptor> images;
private ConcurrentLinkedQueue<VideoDescriptor> videos;
@@ -57,6 +59,7 @@ public abstract class EventBaseImpl implements EventBase {
this.isPublic = isPublic;
this.images = new ConcurrentLinkedQueue<ImageDescriptor>();
this.videos = new ConcurrentLinkedQueue<VideoDescriptor>();
this.sailorsInfoWebsiteURLs = new CopyOnWriteHashMap<>("lock for sailorsInfoWebsiteURLs of event " + id.toString());
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
@@ -67,6 +70,9 @@ public abstract class EventBaseImpl implements EventBase {
if (videos == null) {
videos = new ConcurrentLinkedQueue<VideoDescriptor>();
}
if (sailorsInfoWebsiteURLs == null) {
this.sailorsInfoWebsiteURLs = new CopyOnWriteHashMap<>("lock for sailorsInfoWebsiteURLs of event " + id.toString());
}
}
@Override
@@ -134,45 +140,6 @@ public abstract class EventBaseImpl implements EventBase {
this.endDate = endDate;
}
@Override
public Iterable<URL> getImageURLs() {
List<URL> result = new ArrayList<URL>();
for (ImageDescriptor image : images) {
if (!image.hasTag(MediaTagConstants.SPONSOR) && !image.hasTag(MediaTagConstants.LOGO)) {
result.add(image.getURL());
}
}
return result;
}
@Override
public Iterable<URL> getVideoURLs() {
List<URL> result = new ArrayList<URL>();
for(VideoDescriptor video: videos) {
result.add(video.getURL());
}
return result;
}
@Override
public Iterable<URL> getSponsorImageURLs() {
List<URL> result = new ArrayList<URL>();
for(MediaDescriptor media : findMediaWithTag(images, MediaTagConstants.SPONSOR)) {
result.add(media.getURL());
}
return result;
}
@Override
public URL getLogoImageURL() {
URL result = null;
ImageDescriptor media = findImageWithTag(MediaTagConstants.LOGO);
if(media != null) {
result = media.getURL();
}
return result;
}
@Override
public URL getOfficialWebsiteURL() {
return officialWebsiteURL;
@@ -182,15 +149,45 @@ public abstract class EventBaseImpl implements EventBase {
public void setOfficialWebsiteURL(URL officialWebsiteURL) {
this.officialWebsiteURL = officialWebsiteURL;
}
@Override
public URL getSailorsInfoWebsiteURL() {
return sailorsInfoWebsiteURL;
public Map<Locale, URL> getSailorsInfoWebsiteURLs() {
return Collections.unmodifiableMap(sailorsInfoWebsiteURLs);
}
@Override
public void setSailorsInfoWebsiteURLs(Map<Locale, URL> sailorsInfoWebsiteURLs) {
this.sailorsInfoWebsiteURLs.set(sailorsInfoWebsiteURLs);
}
@Override
public void setSailorsInfoWebsiteURL(URL sailorsInfoWebsiteURL) {
this.sailorsInfoWebsiteURL = sailorsInfoWebsiteURL;
public void setSailorsInfoWebsiteURL(Locale locale, URL sailorsInfoWebsiteURL) {
if (sailorsInfoWebsiteURL == null) {
this.sailorsInfoWebsiteURLs.remove(locale);
} else {
this.sailorsInfoWebsiteURLs.put(locale, sailorsInfoWebsiteURL);
}
}
@Override
public boolean hasSailorsInfoWebsiteURL(Locale locale) {
return this.sailorsInfoWebsiteURLs.containsKey(locale);
}
@Override
public URL getSailorsInfoWebsiteURL(Locale locale) {
return this.sailorsInfoWebsiteURLs.get(locale);
}
@Override
public URL getSailorsInfoWebsiteURLOrFallback(Locale locale) {
final URL result;
if (hasSailorsInfoWebsiteURL(locale)) {
result = this.sailorsInfoWebsiteURLs.get(locale);
} else {
result = this.sailorsInfoWebsiteURLs.get(null);
}
return result;
}
@Override
@@ -0,0 +1,44 @@
package com.sap.sailing.domain.test;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.junit.Before;
import org.junit.Test;
import com.sap.sse.concurrent.CopyOnWriteHashMap;
public class CopyOnWriteHashMapSerializationTest {
private CopyOnWriteHashMap<String, String> expected;
@Before
public void setUp() {
expected = new CopyOnWriteHashMap<>();
expected.put("a", "1");
expected.put("b", "2");
}
@Test
public void testSerializationOfCopyOnWriteHashMap() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream ous = new ObjectOutputStream(baos);
ous.writeObject(expected);
ous.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
@SuppressWarnings("unchecked")
CopyOnWriteHashMap<String, String> deserializedInstance = (CopyOnWriteHashMap<String, String>) ois.readObject();
assertEquals(expected, deserializedInstance);
assertEquals(-1, ois.read(new byte[1]));
ois.close();
}
}
@@ -27,6 +27,8 @@ import com.sap.sailing.domain.tracking.TrackedRegattaRegistry;
*/
public interface Series extends SeriesBase {
static public final String DEFAULT_NAME = "Default";
/**
* A series consists of one or more "race columns." Some people would just say "race," but we use the term "race" for
* something that has a single start time and start line; so if each fleet in a series gets their own start for
@@ -647,6 +647,9 @@ public class CandidateFinderImpl implements CandidateFinder {
}
pos.add(po);
}
if (pos.size() != 2){
return true;
}
Bearing diff1 = pos.get(0).getBearingGreatCircle(p)
.getDifferenceTo(pos.get(0).getBearingGreatCircle(pos.get(1)));
Bearing diff2 = pos.get(1).getBearingGreatCircle(p)
@@ -757,9 +760,7 @@ public class CandidateFinderImpl implements CandidateFinder {
Position portLinePosition = race.getOrCreateTrack(posLine.getA()).getEstimatedPosition(t, false);
Position starboardLinePosition = race.getOrCreateTrack(posLine.getB()).getEstimatedPosition(t, false);
distances.add((portLinePosition != null && starboardLinePosition != null) ? p.getDistanceToLine(
portLinePosition, starboardLinePosition) : portLinePosition != null ? p
.getDistance(portLinePosition) : starboardLinePosition != null ? p
.getDistance(portLinePosition) : null);
portLinePosition, starboardLinePosition) : null);
}
break;
case Offset:
@@ -863,6 +864,9 @@ public class CandidateFinderImpl implements CandidateFinder {
}
markPositions.add(estimatedMarkPosition);
}
if (markPositions.size() != 2){
return new Util.Pair<Mark, Mark>(null, null);
}
final List<Leg> legs = race.getRace().getCourse().getLegs();
final int indexOfWaypoint = race.getRace().getCourse().getIndexOfWaypoint(w);
if (indexOfWaypoint < 0) {
+10 -1
View File
@@ -1,10 +1,19 @@
/** Add css rules here for your application. */
* {
.adminConsolePanel, .adminConsolePanel * {
font-family: Arial;
font-size: 12px;
}
body, html {
font-size: 15px;
font-family: 'Open Sans',sans-serif;
margin: 0;
}
body {
font-size: 14px;
}
/** Example rules used by the template application (remove for your app) */
h1 {
font-size: 2em;
@@ -22,6 +22,10 @@
position: absolute;
top: -1000px; }
html {
font-size: 15px;
}
body {
background: #fff;
font-family: 'Open Sans', Arial, Verdana, sans-serif;
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="DE_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
<g>
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
<g>
<g>
<path fill="#FFFFFF" d="M30.129,19.783c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.225c1.625-0.066,2.232-1.035,4.193-1.035
c1.943,0,2.513,1.035,4.207,0.996c1.744-0.027,2.842-1.559,3.89-3.127c1.255-1.779,1.759-3.533,1.779-3.623
C33.508,24.923,30.162,23.647,30.129,19.783z"/>
<path fill="#FFFFFF" d="M26.929,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
c-0.806,0.942-1.526,2.486-1.34,3.938C24.558,12.204,26.017,11.382,26.929,10.306z"/>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M53.681,31.502h-2.271l-1.244-3.908h-4.324l-1.185,3.908h-2.211l4.284-13.307h2.646L53.681,31.502z
M49.792,25.954l-1.125-3.475c-0.119-0.355-0.342-1.191-0.671-2.508h-0.04c-0.131,0.566-0.342,1.401-0.632,2.508l-1.105,3.475
H49.792z"/>
<path fill="#FFFFFF" d="M64.698,26.586c0,1.633-0.441,2.922-1.323,3.869c-0.79,0.844-1.771,1.264-2.942,1.264
c-1.264,0-2.172-0.453-2.725-1.361h-0.04v5.055h-2.132V25.066c0-1.027-0.027-2.08-0.079-3.16h1.875l0.119,1.521h0.04
c0.711-1.146,1.79-1.719,3.238-1.719c1.132,0,2.077,0.447,2.833,1.343S64.698,25.125,64.698,26.586z M62.526,26.665
c0-0.935-0.21-1.704-0.632-2.31c-0.461-0.633-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.175-1.431,0.523
c-0.428,0.349-0.708,0.806-0.839,1.372c-0.066,0.264-0.099,0.48-0.099,0.651v1.6c0,0.698,0.214,1.286,0.642,1.767
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.309,1.875-0.928S62.526,27.679,62.526,26.665z"/>
<path fill="#FFFFFF" d="M75.736,26.586c0,1.633-0.441,2.922-1.324,3.869c-0.789,0.844-1.77,1.264-2.941,1.264
c-1.264,0-2.172-0.453-2.725-1.361h-0.039v5.055h-2.132V25.066c0-1.027-0.027-2.08-0.079-3.16h1.875l0.119,1.521h0.04
c0.711-1.146,1.79-1.719,3.239-1.719c1.131,0,2.076,0.447,2.834,1.343C75.357,23.947,75.736,25.125,75.736,26.586z M73.564,26.665
c0-0.935-0.211-1.704-0.633-2.31c-0.461-0.633-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.175-1.432,0.523
s-0.708,0.806-0.839,1.372c-0.065,0.264-0.099,0.48-0.099,0.651v1.6c0,0.698,0.214,1.286,0.641,1.767
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.309,1.875-0.928S73.564,27.679,73.564,26.665z"/>
<path fill="#FFFFFF" d="M88.076,27.771c0,1.131-0.395,2.053-1.182,2.764c-0.867,0.777-2.076,1.164-3.625,1.164
c-1.432,0-2.582-0.275-3.449-0.828l0.494-1.777c0.934,0.566,1.961,0.85,3.08,0.85c0.805,0,1.43-0.182,1.877-0.545
c0.447-0.361,0.672-0.848,0.672-1.453c0-0.541-0.186-0.996-0.553-1.365c-0.369-0.369-0.98-0.711-1.836-1.028
c-2.33-0.87-3.496-2.142-3.496-3.816c0-1.094,0.408-1.991,1.225-2.69s1.902-1.048,3.258-1.048c1.211,0,2.219,0.211,3.021,0.632
l-0.533,1.738c-0.75-0.408-1.6-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.758,0.553c-0.355,0.329-0.533,0.73-0.533,1.204
c0,0.527,0.205,0.961,0.613,1.303c0.355,0.316,1,0.658,1.934,1.027c1.146,0.461,1.988,1,2.527,1.619
C87.807,26.08,88.076,26.85,88.076,27.771z"/>
<path fill="#FFFFFF" d="M95.123,23.506h-2.35v4.66c0,1.184,0.416,1.777,1.244,1.777c0.383,0,0.697-0.033,0.949-0.1l0.059,1.619
c-0.422,0.158-0.975,0.236-1.658,0.236c-0.844,0-1.502-0.256-1.975-0.77c-0.475-0.514-0.711-1.375-0.711-2.586v-4.838h-1.402v-1.6
h1.402v-1.757l2.092-0.632v2.389h2.35V23.506z"/>
<path fill="#FFFFFF" d="M105.727,26.625c0,1.475-0.422,2.686-1.264,3.633c-0.881,0.975-2.053,1.461-3.514,1.461
c-1.41,0-2.531-0.467-3.367-1.4c-0.836-0.936-1.254-2.113-1.254-3.535c0-1.486,0.432-2.705,1.293-3.652
c0.863-0.947,2.025-1.422,3.486-1.422c1.408,0,2.539,0.468,3.395,1.402C105.318,24.02,105.727,25.191,105.727,26.625z
M103.516,26.695c0-0.885-0.191-1.645-0.572-2.277c-0.447-0.766-1.086-1.148-1.916-1.148c-0.855,0-1.508,0.383-1.955,1.148
c-0.381,0.633-0.572,1.405-0.572,2.316c0,0.885,0.191,1.645,0.572,2.277c0.461,0.766,1.105,1.148,1.936,1.148
c0.816,0,1.455-0.391,1.916-1.168C103.318,28.346,103.516,27.579,103.516,26.695z"/>
<path fill="#FFFFFF" d="M112.656,23.782c-0.211-0.04-0.434-0.06-0.67-0.06c-0.752,0-1.33,0.283-1.738,0.85
c-0.355,0.5-0.533,1.133-0.533,1.896v5.034h-2.133l0.02-6.574c0-1.105-0.025-2.113-0.078-3.021h1.855l0.08,1.836h0.059
c0.223-0.631,0.578-1.138,1.066-1.52c0.473-0.342,0.986-0.514,1.539-0.514c0.197,0,0.375,0.014,0.533,0.039V23.782z"/>
<path fill="#FFFFFF" d="M122.193,26.25c0,0.383-0.027,0.705-0.08,0.968h-6.396c0.025,0.948,0.336,1.673,0.928,2.173
c0.539,0.447,1.238,0.67,2.094,0.67c0.947,0,1.809-0.15,2.586-0.453l0.336,1.48c-0.908,0.395-1.982,0.592-3.219,0.592
c-1.488,0-2.656-0.438-3.504-1.312c-0.85-0.875-1.273-2.051-1.273-3.524c0-1.448,0.395-2.652,1.184-3.613
c0.83-1.026,1.949-1.54,3.357-1.54c1.381,0,2.428,0.514,3.139,1.54C121.91,24.046,122.193,25.053,122.193,26.25z M120.16,25.697
c0.012-0.631-0.127-1.178-0.416-1.639c-0.367-0.592-0.934-0.889-1.697-0.889c-0.697,0-1.264,0.29-1.697,0.869
c-0.355,0.461-0.566,1.014-0.633,1.658H120.16z"/>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M47.427,13.432h-3.715V6.894h1.048v5.655h2.667V13.432z"/>
<path fill="#FFFFFF" d="M52.365,13.432h-0.941l-0.077-0.543h-0.029c-0.323,0.433-0.782,0.65-1.377,0.65
c-0.446,0-0.806-0.143-1.077-0.427c-0.246-0.258-0.368-0.579-0.368-0.96c0-0.576,0.24-1.015,0.723-1.319
c0.481-0.304,1.159-0.453,2.032-0.446v-0.087c0-0.621-0.326-0.931-0.978-0.931c-0.465,0-0.875,0.117-1.229,0.349L48.83,9.028
c0.438-0.271,0.979-0.407,1.617-0.407c1.233,0,1.85,0.65,1.85,1.95v1.736C52.296,12.778,52.32,13.154,52.365,13.432z
M51.278,11.812v-0.727c-1.157-0.02-1.735,0.297-1.735,0.95c0,0.246,0.067,0.43,0.202,0.553c0.135,0.123,0.306,0.184,0.511,0.184
c0.231,0,0.445-0.073,0.642-0.218s0.317-0.331,0.362-0.558C51.272,11.944,51.278,11.883,51.278,11.812z"/>
<path fill="#FFFFFF" d="M58.32,13.432h-0.931l-0.049-0.757h-0.029c-0.297,0.576-0.802,0.864-1.513,0.864
c-0.569,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.61-1.853c0.395-0.44,0.88-0.66,1.455-0.66
c0.634,0,1.077,0.213,1.329,0.64h0.02V6.554h1.048v5.607C58.282,12.62,58.294,13.043,58.32,13.432z M57.234,11.443v-0.786
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.38-0.635c-0.195-0.171-0.429-0.257-0.701-0.257
c-0.39,0-0.696,0.155-0.921,0.466c-0.224,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
c0.227,0.31,0.532,0.465,0.915,0.465c0.344,0,0.62-0.129,0.828-0.388C57.133,12.067,57.234,11.779,57.234,11.443z"/>
<path fill="#FFFFFF" d="M64.025,10.852c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.013,0.466,0.164,0.821,0.455,1.067
c0.266,0.22,0.608,0.33,1.028,0.33c0.466,0,0.89-0.074,1.271-0.223l0.164,0.728c-0.446,0.194-0.973,0.291-1.581,0.291
c-0.73,0-1.305-0.215-1.722-0.645s-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
c0.407-0.504,0.956-0.756,1.648-0.756c0.679,0,1.193,0.252,1.542,0.756C63.885,9.769,64.025,10.263,64.025,10.852z M63.025,10.58
c0.007-0.311-0.062-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.343,0-0.621,0.142-0.835,0.427
c-0.174,0.227-0.277,0.498-0.31,0.815H63.025z"/>
<path fill="#FFFFFF" d="M69.641,13.432h-1.048v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
c0.361,0.349,0.543,0.87,0.543,1.562V13.432z"/>
<path fill="#FFFFFF" d="M75.479,7.311c0,0.188-0.061,0.339-0.184,0.456c-0.123,0.117-0.281,0.175-0.475,0.175
c-0.176,0-0.322-0.06-0.441-0.179c-0.121-0.12-0.18-0.27-0.18-0.451s0.061-0.33,0.184-0.446S74.658,6.69,74.84,6.69
c0.18,0,0.332,0.059,0.455,0.175S75.479,7.13,75.479,7.311z M75.363,13.432h-1.049V8.717h1.049V13.432z"/>
<path fill="#FFFFFF" d="M83.977,13.432h-1.027V10.79c0-0.871-0.299-1.306-0.893-1.306c-0.285,0-0.514,0.108-0.684,0.324
c-0.172,0.216-0.258,0.469-0.258,0.759v2.864h-1.027v-2.777c0-0.355-0.074-0.639-0.219-0.852
c-0.146-0.213-0.361-0.319-0.645-0.319c-0.285,0-0.518,0.116-0.699,0.348c-0.182,0.232-0.271,0.497-0.271,0.793v2.806h-1.029
v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.9l0.049,0.717h0.029c0.324-0.542,0.803-0.814,1.436-0.814
c0.641,0,1.074,0.294,1.301,0.882h0.02c0.148-0.246,0.332-0.443,0.553-0.591c0.277-0.194,0.598-0.291,0.959-0.291
c0.422,0,0.768,0.142,1.039,0.427c0.336,0.355,0.504,0.886,0.504,1.591V13.432z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
<g>
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
<g>
<g>
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
H49.755z"/>
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
S47.945,10.892,47.945,10.038z"/>
<path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
C53.725,11.882,53.822,11.506,53.822,11.071z"/>
<path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
<path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
<path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
<path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
C76.074,11.882,76.17,11.506,76.17,11.071z"/>
<path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
<path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
<path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
C96.064,11.882,96.162,11.506,96.162,11.071z"/>
<path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
<path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
<path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
<path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="RU_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
<g>
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
<g>
<g>
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
H49.755z"/>
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M43.424,7.273c0.227-0.136,0.483-0.25,0.771-0.344c0.287-0.094,0.625-0.141,1.014-0.141
c0.627,0,1.121,0.149,1.483,0.446s0.543,0.698,0.543,1.203c0,0.401-0.121,0.737-0.363,1.009s-0.552,0.453-0.927,0.543v0.029
c0.207,0.033,0.403,0.089,0.587,0.17c0.185,0.081,0.347,0.189,0.485,0.325c0.139,0.136,0.249,0.294,0.33,0.476
c0.08,0.181,0.121,0.381,0.121,0.602c0,0.362-0.073,0.666-0.219,0.912s-0.336,0.446-0.572,0.602
c-0.235,0.155-0.499,0.267-0.79,0.334s-0.582,0.102-0.873,0.102c-0.311,0-0.618-0.033-0.922-0.097s-0.585-0.171-0.844-0.32
l0.262-0.805c0.168,0.084,0.385,0.165,0.65,0.243c0.265,0.078,0.533,0.116,0.805,0.116c0.446,0,0.791-0.1,1.033-0.3
c0.242-0.201,0.364-0.469,0.364-0.805c0-0.227-0.049-0.412-0.146-0.558c-0.098-0.146-0.224-0.26-0.379-0.345
c-0.155-0.084-0.328-0.142-0.519-0.174c-0.191-0.032-0.38-0.049-0.567-0.049h-0.437V9.65h0.437c0.2,0,0.386-0.025,0.558-0.078
c0.171-0.051,0.32-0.124,0.446-0.218s0.225-0.206,0.296-0.335c0.07-0.129,0.106-0.275,0.106-0.437
c0-0.291-0.104-0.519-0.311-0.684c-0.207-0.165-0.485-0.248-0.834-0.248c-0.239,0-0.479,0.039-0.718,0.116
c-0.239,0.078-0.453,0.162-0.641,0.252L43.424,7.273z"/>
<path fill="#FFFFFF" d="M51.755,13.433l-0.077-0.543h-0.029c-0.316,0.433-0.775,0.65-1.377,0.65
c-0.214,0-0.407-0.036-0.582-0.107s-0.327-0.168-0.456-0.291c-0.13-0.123-0.229-0.268-0.301-0.437
c-0.071-0.168-0.106-0.353-0.106-0.553c0-0.588,0.239-1.03,0.718-1.324c0.479-0.294,1.157-0.441,2.037-0.441V10.3
c0-0.621-0.326-0.931-0.978-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688c0.433-0.271,0.972-0.407,1.617-0.407
c1.233,0,1.85,0.65,1.85,1.95v1.736c0,0.485,0.023,0.86,0.068,1.125H51.755z M51.61,11.086c-0.585,0-1.021,0.074-1.307,0.223
c-0.286,0.149-0.429,0.392-0.429,0.728c0,0.246,0.067,0.43,0.202,0.553c0.135,0.123,0.306,0.184,0.512,0.184
c0.135,0,0.263-0.024,0.386-0.073c0.122-0.048,0.229-0.115,0.322-0.199c0.094-0.084,0.169-0.186,0.228-0.306
c0.058-0.12,0.086-0.247,0.086-0.383V11.086z"/>
<path fill="#FFFFFF" d="M57.683,8.719v0.863h-1.96v3.851h-1.047V8.719H57.683z"/>
<path fill="#FFFFFF" d="M63.677,11.018c0,0.375-0.052,0.718-0.155,1.028c-0.104,0.311-0.247,0.576-0.432,0.795
c-0.184,0.22-0.404,0.392-0.659,0.514c-0.256,0.123-0.538,0.185-0.849,0.185c-0.621,0-1.067-0.223-1.339-0.669h-0.02v2.483
h-1.048v-5.083c0-0.252-0.003-0.506-0.01-0.762c-0.006-0.255-0.016-0.519-0.028-0.791h0.921l0.059,0.747h0.02
c0.349-0.562,0.879-0.844,1.591-0.844c0.277,0,0.535,0.058,0.771,0.174c0.236,0.117,0.441,0.28,0.616,0.49
c0.175,0.21,0.312,0.462,0.412,0.757C63.627,10.337,63.677,10.662,63.677,11.018z M62.611,11.057
c0-0.233-0.028-0.448-0.083-0.645s-0.136-0.365-0.242-0.504s-0.236-0.249-0.388-0.33c-0.152-0.081-0.322-0.121-0.51-0.121
c-0.148,0-0.294,0.033-0.437,0.097s-0.267,0.152-0.373,0.262c-0.107,0.11-0.192,0.243-0.257,0.398
c-0.065,0.155-0.098,0.32-0.098,0.495v0.786c0,0.174,0.027,0.336,0.083,0.485c0.055,0.149,0.132,0.278,0.232,0.388
s0.22,0.196,0.359,0.257c0.139,0.062,0.292,0.092,0.46,0.092c0.395,0,0.702-0.15,0.922-0.451S62.611,11.561,62.611,11.057z"/>
<path fill="#FFFFFF" d="M69.305,8.719l-1.194,3.269c-0.284,0.776-0.561,1.411-0.829,1.906c-0.269,0.495-0.525,0.855-0.771,1.082
c-0.362,0.323-0.747,0.521-1.155,0.591l-0.252-0.882c0.271-0.071,0.53-0.21,0.776-0.417c0.245-0.207,0.442-0.465,0.592-0.776
c0.052-0.103,0.077-0.174,0.077-0.213c0-0.039-0.02-0.113-0.058-0.223l-1.708-4.336h1.154l0.893,2.629
c0.046,0.123,0.091,0.262,0.136,0.417c0.046,0.155,0.094,0.327,0.146,0.514h0.02c0.032-0.104,0.068-0.234,0.106-0.393
c0.039-0.158,0.091-0.341,0.155-0.548l0.796-2.619H69.305z"/>
<path fill="#FFFFFF" d="M71.119,10.678h0.484c0.355,0,0.631-0.064,0.824-0.194s0.291-0.288,0.291-0.476
c0-0.194-0.082-0.349-0.248-0.465c-0.164-0.116-0.393-0.175-0.684-0.175c-0.188,0-0.377,0.031-0.566,0.092
c-0.191,0.062-0.367,0.138-0.529,0.228L70.42,9.01c0.271-0.148,0.541-0.25,0.811-0.305c0.268-0.055,0.537-0.083,0.809-0.083
c0.215,0,0.43,0.021,0.646,0.063c0.215,0.042,0.408,0.113,0.576,0.213s0.307,0.231,0.412,0.393
c0.107,0.162,0.16,0.362,0.16,0.602c0,0.149-0.029,0.28-0.088,0.393c-0.057,0.113-0.135,0.213-0.232,0.3
c-0.096,0.087-0.205,0.159-0.324,0.213c-0.119,0.055-0.242,0.096-0.363,0.122v0.029c0.154,0.02,0.305,0.059,0.451,0.117
c0.145,0.058,0.275,0.134,0.393,0.228c0.115,0.094,0.209,0.207,0.281,0.339c0.07,0.133,0.105,0.283,0.105,0.451
c0,0.278-0.066,0.511-0.203,0.698c-0.135,0.188-0.309,0.336-0.52,0.446c-0.209,0.11-0.441,0.189-0.693,0.238
c-0.252,0.048-0.498,0.073-0.736,0.073c-0.291,0-0.58-0.031-0.863-0.092c-0.285-0.062-0.541-0.157-0.768-0.286l0.273-0.689
c0.168,0.091,0.359,0.167,0.576,0.228s0.438,0.092,0.664,0.092c0.355,0,0.629-0.069,0.82-0.208
c0.189-0.139,0.285-0.312,0.285-0.519c0-0.136-0.031-0.25-0.096-0.344s-0.156-0.17-0.271-0.228
c-0.117-0.058-0.252-0.099-0.408-0.121c-0.154-0.023-0.324-0.034-0.504-0.034h-0.494V10.678z"/>
<path fill="#FFFFFF" d="M76.715,8.719v1.668c0,0.382-0.006,0.725-0.02,1.028c-0.014,0.304-0.029,0.624-0.049,0.96l0.02,0.019
c0.123-0.246,0.244-0.486,0.363-0.723c0.121-0.236,0.242-0.477,0.365-0.723l1.164-2.231h1.357v4.714h-0.99v-1.668
c0-0.349,0.01-0.698,0.025-1.047c0.016-0.35,0.033-0.702,0.053-1.058h-0.049c-0.109,0.291-0.219,0.543-0.33,0.757
c-0.109,0.213-0.219,0.433-0.328,0.66c-0.201,0.388-0.4,0.776-0.598,1.164c-0.197,0.388-0.406,0.786-0.625,1.193h-1.357V8.719
H76.715z"/>
<path fill="#FFFFFF" d="M85.445,8.719v0.863H84.01v3.851H82.98V9.582h-1.426V8.719H85.445z"/>
<path fill="#FFFFFF" d="M90.789,10.853c0,0.09-0.004,0.176-0.01,0.257c-0.006,0.081-0.016,0.154-0.029,0.218h-3.143
c0.014,0.446,0.154,0.791,0.422,1.033c0.268,0.242,0.623,0.364,1.062,0.364c0.459,0,0.883-0.074,1.271-0.223l0.164,0.728
c-0.447,0.194-0.973,0.291-1.582,0.291c-0.367,0-0.697-0.057-0.988-0.17c-0.291-0.113-0.537-0.273-0.738-0.48
c-0.199-0.207-0.354-0.456-0.461-0.747c-0.105-0.291-0.158-0.617-0.158-0.979s0.053-0.697,0.158-1.004
c0.107-0.307,0.258-0.574,0.451-0.8c0.195-0.227,0.43-0.404,0.703-0.534c0.275-0.129,0.582-0.194,0.918-0.194
c0.297,0,0.566,0.053,0.811,0.16c0.242,0.106,0.449,0.258,0.619,0.456c0.172,0.197,0.303,0.434,0.393,0.708
C90.744,10.211,90.789,10.517,90.789,10.853z M89.789,10.582c0-0.369-0.088-0.668-0.266-0.897S89.088,9.34,88.752,9.34
c-0.305,0-0.562,0.116-0.775,0.349s-0.336,0.53-0.369,0.893H89.789z"/>
<path fill="#FFFFFF" d="M95.01,8.758c0.188-0.032,0.426-0.058,0.717-0.078s0.588-0.029,0.893-0.029
c0.193,0,0.412,0.012,0.654,0.034s0.475,0.074,0.693,0.155c0.221,0.081,0.404,0.202,0.553,0.364s0.225,0.381,0.225,0.659
c0,0.143-0.027,0.271-0.078,0.383c-0.053,0.113-0.121,0.212-0.209,0.296s-0.188,0.154-0.301,0.208
c-0.113,0.055-0.23,0.096-0.354,0.121l0.01,0.029c0.342,0.058,0.621,0.181,0.834,0.369s0.32,0.446,0.32,0.776
c0,0.33-0.092,0.592-0.271,0.786c-0.182,0.194-0.404,0.34-0.67,0.437c-0.266,0.097-0.545,0.159-0.84,0.185
c-0.293,0.025-0.557,0.039-0.789,0.039c-0.26,0-0.514-0.006-0.762-0.02c-0.25-0.013-0.457-0.026-0.625-0.039V8.758z
M96.018,10.64h0.533c0.162,0,0.316-0.011,0.461-0.034c0.146-0.022,0.273-0.058,0.383-0.106c0.111-0.049,0.195-0.113,0.258-0.194
c0.061-0.081,0.092-0.179,0.092-0.296c0-0.213-0.088-0.37-0.268-0.47c-0.178-0.1-0.457-0.15-0.838-0.15
c-0.109,0-0.205,0.003-0.287,0.01c-0.08,0.006-0.191,0.016-0.334,0.029V10.64z M96.018,12.725
c0.129,0.013,0.238,0.022,0.324,0.029c0.088,0.007,0.189,0.01,0.307,0.01c0.143,0,0.287-0.009,0.436-0.029
c0.148-0.019,0.285-0.056,0.408-0.111c0.123-0.054,0.221-0.128,0.295-0.222c0.074-0.093,0.113-0.217,0.113-0.371
c0-0.27-0.121-0.456-0.359-0.559c-0.24-0.103-0.562-0.154-0.971-0.154h-0.553V12.725z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="SC_Download_on_the_App_Store"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="135px" height="40px"
viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
<g>
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
<g>
<g>
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
</g>
</g>
<g>
<path fill="#FFFFFF" d="M54.006,17.03H52l-1.1-3.455h-3.821l-1.047,3.455h-1.955l3.787-11.761h2.338L54.006,17.03z M50.568,12.127
l-0.995-3.071c-0.104-0.314-0.302-1.053-0.593-2.216h-0.035c-0.117,0.5-0.303,1.239-0.559,2.216l-0.977,3.071H50.568z"/>
<path fill="#FFFFFF" d="M63.742,12.685c0,1.443-0.389,2.583-1.168,3.42c-0.699,0.745-1.564,1.117-2.602,1.117
c-1.115,0-1.918-0.401-2.406-1.204h-0.035v4.467h-1.885v-9.144c0-0.908-0.023-1.838-0.07-2.792h1.658l0.105,1.344h0.034
c0.629-1.012,1.582-1.519,2.861-1.519c1.002,0,1.836,0.396,2.506,1.187C63.408,10.353,63.742,11.394,63.742,12.685z
M61.824,12.755c0-0.826-0.188-1.506-0.559-2.042c-0.408-0.558-0.955-0.837-1.641-0.837c-0.465,0-0.887,0.154-1.266,0.462
s-0.625,0.712-0.742,1.213c-0.059,0.232-0.086,0.425-0.086,0.576v1.414c0,0.617,0.188,1.137,0.566,1.562
c0.379,0.425,0.869,0.637,1.475,0.637c0.709,0,1.262-0.273,1.658-0.82C61.625,14.372,61.824,13.651,61.824,12.755z"/>
<path fill="#FFFFFF" d="M73.497,12.685c0,1.443-0.39,2.583-1.169,3.42c-0.698,0.745-1.564,1.117-2.601,1.117
c-1.116,0-1.919-0.401-2.407-1.204h-0.035v4.467H65.4v-9.144c0-0.908-0.023-1.838-0.069-2.792h1.657l0.104,1.344h0.035
c0.628-1.012,1.582-1.519,2.861-1.519c1.001,0,1.835,0.396,2.505,1.187C73.162,10.353,73.497,11.394,73.497,12.685z
M71.578,12.755c0-0.826-0.187-1.506-0.559-2.042c-0.407-0.558-0.954-0.837-1.641-0.837c-0.465,0-0.887,0.154-1.265,0.462
c-0.379,0.308-0.626,0.712-0.742,1.213c-0.059,0.232-0.087,0.425-0.087,0.576v1.414c0,0.617,0.188,1.137,0.567,1.562
c0.378,0.425,0.869,0.637,1.474,0.637c0.71,0,1.263-0.273,1.658-0.82S71.578,13.651,71.578,12.755z"/>
<path fill="#FFFFFF" d="M86.759,13.732c0,1-0.349,1.814-1.045,2.443c-0.766,0.687-1.834,1.029-3.203,1.029
c-1.266,0-2.281-0.244-3.048-0.733l0.436-1.57c0.826,0.5,1.734,0.75,2.724,0.75c0.71,0,1.263-0.16,1.658-0.481
c0.396-0.32,0.594-0.749,0.594-1.285c0-0.478-0.163-0.879-0.488-1.206c-0.326-0.326-0.867-0.629-1.623-0.909
c-2.06-0.769-3.089-1.894-3.089-3.374c0-0.967,0.36-1.759,1.082-2.377c0.721-0.618,1.681-0.926,2.879-0.926
c1.07,0,1.96,0.186,2.67,0.558l-0.471,1.536c-0.663-0.36-1.414-0.541-2.251-0.541c-0.663,0-1.181,0.163-1.554,0.489
c-0.313,0.291-0.471,0.646-0.471,1.064c0,0.465,0.181,0.849,0.541,1.152c0.314,0.279,0.884,0.582,1.71,0.907
c1.012,0.407,1.757,0.884,2.233,1.431C86.52,12.238,86.759,12.918,86.759,13.732z"/>
<path fill="#FFFFFF" d="M92.988,9.963h-2.077v4.118c0,1.047,0.367,1.571,1.1,1.571c0.338,0,0.616-0.029,0.838-0.087l0.053,1.431
c-0.373,0.139-0.861,0.209-1.466,0.209c-0.745,0-1.326-0.227-1.745-0.68c-0.419-0.454-0.629-1.216-0.629-2.286V9.963h-1.238V8.55
h1.238V6.997l1.85-0.558V8.55h2.077V9.963z"/>
<path fill="#FFFFFF" d="M102.358,12.72c0,1.303-0.373,2.373-1.117,3.211c-0.779,0.861-1.814,1.291-3.105,1.291
c-1.245,0-2.237-0.413-2.976-1.239c-0.739-0.826-1.108-1.867-1.108-3.124c0-1.314,0.381-2.391,1.144-3.229
c0.762-0.837,1.788-1.256,3.079-1.256c1.245,0,2.245,0.413,3.002,1.239C101.997,10.417,102.358,11.452,102.358,12.72z
M100.403,12.781c0-0.782-0.168-1.453-0.506-2.012c-0.396-0.677-0.96-1.015-1.692-1.015c-0.757,0-1.332,0.338-1.728,1.015
c-0.338,0.56-0.506,1.242-0.506,2.047c0,0.782,0.168,1.453,0.506,2.013c0.407,0.677,0.978,1.015,1.71,1.015
c0.722,0,1.285-0.344,1.692-1.033C100.229,14.24,100.403,13.563,100.403,12.781z"/>
<path fill="#FFFFFF" d="M108.482,10.208c-0.186-0.035-0.384-0.052-0.593-0.052c-0.663,0-1.176,0.25-1.536,0.75
c-0.313,0.442-0.471,1.001-0.471,1.675v4.45h-1.885l0.018-5.811c0-0.978-0.023-1.867-0.07-2.67h1.641l0.07,1.623h0.052
c0.198-0.558,0.512-1.006,0.942-1.343c0.419-0.303,0.873-0.454,1.361-0.454c0.175,0,0.331,0.012,0.471,0.035V10.208z"/>
<path fill="#FFFFFF" d="M116.91,12.389c0,0.337-0.023,0.623-0.069,0.855h-5.653c0.022,0.837,0.296,1.478,0.819,1.919
c0.478,0.396,1.094,0.593,1.85,0.593c0.838,0,1.6-0.133,2.286-0.401l0.297,1.309c-0.803,0.349-1.751,0.523-2.845,0.523
c-1.314,0-2.347-0.387-3.097-1.161c-0.751-0.773-1.126-1.812-1.126-3.115c0-1.279,0.35-2.344,1.047-3.193
c0.733-0.907,1.722-1.361,2.967-1.361c1.222,0,2.146,0.454,2.774,1.361C116.66,10.44,116.91,11.33,116.91,12.389z M115.113,11.9
c0.012-0.558-0.11-1.041-0.366-1.448c-0.326-0.523-0.826-0.785-1.501-0.785c-0.616,0-1.117,0.256-1.501,0.768
c-0.313,0.408-0.5,0.896-0.558,1.466H115.113z"/>
</g>
<g>
<g>
<path fill="#FFFFFF" d="M56.827,23.984h-6.221v10.89h-1.451v-10.89h-5.132v-1.354h12.804V23.984z M56.547,29.974l-1.056,1.056
c-1.508-1.43-3.063-2.788-4.67-4.075l1.007-0.957C53.456,27.273,55.029,28.599,56.547,29.974z"/>
<path fill="#FFFFFF" d="M65.919,28.488h-4.207c-0.286,0.506-0.522,0.908-0.71,1.205h1.205v-0.875h1.304v0.875h2.095v1.154h-2.095
v0.941l2.244-0.198l-0.231,1.155l-2.013,0.182v1.881h-1.304v-1.783l-3.498,0.363l-0.148-1.287
c1.342-0.065,2.558-0.137,3.646-0.214v-1.04h-0.99c-0.803,0-1.43,0.072-1.881,0.215l-0.363-1.205
c0.363-0.043,0.616-0.172,0.759-0.387c0.144-0.215,0.341-0.542,0.595-0.982h-1.535v-1.154h2.129
c0.132-0.275,0.247-0.562,0.347-0.858l1.237,0.362l-0.231,0.496h3.646V28.488z M71.777,31.904
c-0.177,1.298-0.363,2.105-0.562,2.426c-0.198,0.318-0.498,0.479-0.899,0.479s-0.83-0.204-1.287-0.611
c-0.456-0.406-0.85-0.869-1.18-1.386c-0.671,0.671-1.534,1.37-2.59,2.096l-1.007-0.99c1.199-0.737,2.188-1.528,2.97-2.376
c-0.274-0.814-0.473-1.817-0.594-3.012c-0.121-1.193-0.182-1.905-0.182-2.137h-7.771v-1.171h3.333v-0.94h-2.524v-1.172h2.524
v-1.336h1.32v1.336h2.376v1.172h-2.376v0.94h3.068l-0.065-3.465h1.304c0,1.397,0.021,2.552,0.065,3.465h3.845v1.171h-3.795v0.166
c0,0.22,0.038,0.762,0.115,1.625s0.182,1.576,0.313,2.137c0.562-0.836,1.028-1.837,1.402-3.004l1.205,0.463
c-0.583,1.66-1.26,2.992-2.029,3.992c0.176,0.342,0.426,0.68,0.75,1.016s0.536,0.503,0.636,0.503c0.099,0,0.184-0.157,0.256-0.47
c0.071-0.314,0.123-0.729,0.156-1.246L71.777,31.904z M71.249,24.148l-1.04,0.826c-0.594-0.727-1.227-1.408-1.897-2.047
l0.974-0.809C70.066,22.879,70.721,23.555,71.249,24.148z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Could not determine the version of your GWT SDK; using the module DTD
from GWT 1.6.4. You may want to change this. -->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN" "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module>
<inherits name="com.sap.sailing.gwt.common.SourceCommon" />
<inherits name="com.sap.sse.security.ui.Authentication" />
<source path='authentication' />
</module>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.7.0//EN" "http://gwtproject.org/doctype/2.7.0/gwt-module.dtd">
<module>
<extend-property name="locale" values="en,de,zh,ru" />
<set-property name="locale" value="en,de,zh,ru" />
<set-property-fallback name="locale" value="en" />
</module>
@@ -0,0 +1,18 @@
package com.sap.sailing.gwt.common.authentication;
import com.sap.sse.gwt.common.CommonSharedResources;
import com.sap.sse.security.ui.authentication.generic.GenericAuthentication;
import com.sap.sse.security.ui.authentication.generic.sapheader.FixedFlyoutAuthenticationView;
import com.sap.sse.security.ui.authentication.view.AuthenticationMenuView;
import com.sap.sse.security.ui.client.UserService;
public class FixedSailingAuthentication extends GenericAuthentication {
private static final CommonSharedResources res = CommonSharedResources.INSTANCE;
public FixedSailingAuthentication(UserService userService, AuthenticationMenuView userManagementMenuView) {
super(userService, userManagementMenuView, new FixedFlyoutAuthenticationView(res),
SailingAuthenticationEntryPointLinkFactory.INSTANCE, res);
res.mainCss().ensureInjected();
}
}
@@ -0,0 +1,18 @@
package com.sap.sailing.gwt.common.authentication;
import com.sap.sse.gwt.common.CommonSharedResources;
import com.sap.sse.security.ui.authentication.generic.GenericAuthentication;
import com.sap.sse.security.ui.authentication.generic.sapheader.GenericFlyoutAuthenticationView;
import com.sap.sse.security.ui.authentication.view.AuthenticationMenuView;
import com.sap.sse.security.ui.client.UserService;
public class GenericSailingAuthentication extends GenericAuthentication {
private static final CommonSharedResources res = CommonSharedResources.INSTANCE;
public GenericSailingAuthentication(UserService userService, AuthenticationMenuView userManagementMenuView) {
super(userService, userManagementMenuView, new GenericFlyoutAuthenticationView(res),
SailingAuthenticationEntryPointLinkFactory.INSTANCE, res);
res.mainCss().ensureInjected();
}
}
@@ -0,0 +1,42 @@
package com.sap.sailing.gwt.common.authentication;
import java.util.HashMap;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.user.client.Window;
import com.sap.sse.gwt.client.AbstractEntryPointLinkFactory;
import com.sap.sse.security.ui.authentication.generic.GenericAuthenticationLinkFactory;
public final class SailingAuthenticationEntryPointLinkFactory extends AbstractEntryPointLinkFactory implements
GenericAuthenticationLinkFactory {
public static final GenericAuthenticationLinkFactory INSTANCE = new SailingAuthenticationEntryPointLinkFactory();
private SailingAuthenticationEntryPointLinkFactory() {
}
@Override
public final String createUserProfileLink() {
return createEntryPointLink("/gwt/Home.html#/user/profile/:", new HashMap<String, String>());
}
@Override
public final String createEmailValidationLink() {
return createFullQualifiedLink("/gwt/Home.html", "/user/confirmation/:MAIL_VERIFIED");
}
@Override
public final String createPasswordResetLink() {
return createFullQualifiedLink("/gwt/Home.html", "/user/passwordreset/:");
}
private String createFullQualifiedLink(String baseUrl, String hash) {
String path = createEntryPointLink(baseUrl, new HashMap<String, String>());
UrlBuilder urlBuilder = Window.Location.createUrlBuilder();
for (String parameter : Window.Location.getParameterMap().keySet()) {
urlBuilder.removeParameter(parameter);
}
return urlBuilder.setPath(path).setHash(hash).buildString();
}
}
@@ -0,0 +1,40 @@
package com.sap.sailing.gwt.common.client;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.google.gwt.i18n.client.LocaleInfo;
import com.sap.sse.common.Util;
public final class GWTLocaleUtil {
private static final String NO_LOCALE_TEXT = "---";
private GWTLocaleUtil() {
}
public static Iterable<String> getAvailableLocales() {
List<String> result = new ArrayList<>();
result.addAll(Arrays.asList(LocaleInfo.getAvailableLocaleNames()));
result.remove("default");
return result;
}
public static Iterable<String> getAvailableLocalesAndDefault() {
List<String> result = new ArrayList<>();
result.add(null);
Util.addAll(getAvailableLocales(), result);
return result;
}
public static int getLanguageCountWithDefault() {
return Util.size(getAvailableLocalesAndDefault());
}
public static String getDecoratedLanguageDisplayNameWithDefaultLocaleSupport(String localeNameOrNull) {
if (localeNameOrNull == null || localeNameOrNull.isEmpty()) {
return NO_LOCALE_TEXT;
}
return LocaleInfo.getLocaleNativeDisplayName(localeNameOrNull) + " ["+localeNameOrNull+"]";
}
}
@@ -11,17 +11,13 @@ public interface SharedResources extends ClientBundle, CommonSharedResources {
@Source("main.gss")
MainCss mainCss();
@Source("media.gss")
@Source(CommonSharedResources.MEDIA)
MediaCss mediaCss();
public interface MainCss extends CssResource, CommonMainCss {
String mobile();
String desktop();
String wrapper();
String navbar();
String navbar_button();
String navbar_buttonhidden();
String navbar_buttonactive();
String button();
String buttontextonly();
String buttonsmall();
@@ -1,84 +0,0 @@
package com.sap.sailing.gwt.common.client.controls.tabbar;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
/**
* @author zhorvath
*
*/
public class BreadcrumbPane extends Widget {
interface Resources extends ClientBundle {
@Source("Breadcrumb.css")
Style style();
}
interface Style extends CssResource {
String event_header__breadcrumb();
String event_header__breadcrumb__item();
}
private static Resources resources;
private static Resources getResources() {
if (resources == null) {
resources = GWT.create(Resources.class);
resources.style().ensureInjected();
}
return resources;
}
private final Style style = getResources().style();
private final DivElement breadcrumDiv;
public BreadcrumbPane() {
breadcrumDiv = Document.get().createDivElement();
breadcrumDiv.addClassName(style.event_header__breadcrumb());
setElement(breadcrumDiv);
}
public void addBreadcrumbItem(String title, String link, final Runnable runnable) {
addBreadcrumbItem(title, UriUtils.fromString(link), runnable);
}
public void addBreadcrumbItem(String title, SafeUri link, final Runnable runnable) {
AnchorElement breadcrumItem = Document.get().createAnchorElement();
breadcrumItem.setHref(link);
breadcrumItem.setInnerText(title);
breadcrumItem.addClassName(style.event_header__breadcrumb__item());
breadcrumDiv.appendChild(breadcrumItem);
Event.sinkEvents(breadcrumItem, Event.ONCLICK);
Event.setEventListener(breadcrumItem, new EventListener() {
@Override
public void onBrowserEvent(Event event) {
if (LinkUtil.handleLinkClick(event)) {
event.stopPropagation();
event.preventDefault();
runnable.run();
}
}
});
}
public void clear() {
breadcrumDiv.removeAllChildren();
}
}
@@ -0,0 +1,36 @@
.navbar {
font-size: 1rem;
}
.navbar_button {
font-size: 1.2em;
display: inline-block;
font-weight: 600;
color: #666;
border: 1px solid #dedede;
padding: 0.833333333333333em 0.944444444444444em;
background-color: #ebebeb;
-webkit-transition: background-color 0.2s, border-color 0.2s;
-moz-transition: background-color 0.2s, border-color 0.2s;
transition: background-color 0.2s, border-color 0.2s;
text-decoration: none;
margin-right: 0.555555555555556em;
border-top-left-radius: 0.277777777777778em;
border-top-right-radius: 0.277777777777778em;
}
.navbar_buttonhidden {
display: block;
}
.navbar_button:hover {
background-color: #dedede;
outline: none;
text-decoration: none;
}
.navbar_buttonactive {
color: #333;
background-color: #fff;
border-bottom: 1px solid #fff;
}
.navbar_buttonactive:hover {
background-color: #dedede;
border-bottom: 1px solid #dedede;
}
@@ -13,12 +13,9 @@ import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sse.gwt.client.LinkUtil;
/**
* Capsulates functionality for a tab bar.
@@ -26,14 +23,15 @@ import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
* @author zhorvath
*
*/
public class TabBar extends Widget implements HasSelectionHandlers<Class<Place>> {
public class TabBar<T> extends Widget implements HasSelectionHandlers<T> {
private final MainCss style = SharedResources.INSTANCE.mainCss();
private final TabBarResources.LocalCss style = TabBarResources.INSTANCE.css();
private final List<Class<Place>> knownPlaceClasses = new ArrayList<>();
private final List<T> tabObjects = new ArrayList<>();
private final DivElement tabBarDiv;
public TabBar() {
style.ensureInjected();
tabBarDiv = Document.get().createDivElement();
tabBarDiv.addClassName(style.navbar());
@@ -57,8 +55,8 @@ public class TabBar extends Widget implements HasSelectionHandlers<Class<Place>>
event.stopPropagation();
event.preventDefault();
// the specific tab was clicked -> fire SelectionEvent with the associated place
GWT.log("Found " + knownPlaceClasses.get(i));
SelectionEvent.fire(this, knownPlaceClasses.get(i));
GWT.log("Found " + tabObjects.get(i));
SelectionEvent.fire(this, tabObjects.get(i));
break;
}
}
@@ -74,16 +72,16 @@ public class TabBar extends Widget implements HasSelectionHandlers<Class<Place>>
* @param place
* the place that should get selected.
*/
public void select(Place place) {
GWT.log("Should activate: " + place.getClass().getName());
public void select(T tabObject) {
GWT.log("Should activate: " + tabObject);
// remove all previous selections
for (int i = 0; i < tabBarDiv.getChildCount(); i++) {
Element.as(tabBarDiv.getChild(i)).removeClassName(style.navbar_buttonactive());
}
// find the tab that has to be selected for the given place
for (int i = 0; i < knownPlaceClasses.size(); i++) {
if (place.getClass().equals(knownPlaceClasses.get(i))) {
GWT.log("Activate: " + place.getClass().getName());
for (int i = 0; i < tabObjects.size(); i++) {
if (tabObject.equals(tabObjects.get(i))) {
GWT.log("Activate: " + tabObject);
// found the associated tab -> set the selected style.
Element.as(tabBarDiv.getChild(i)).addClassName(style.navbar_buttonactive());
}
@@ -100,19 +98,19 @@ public class TabBar extends Widget implements HasSelectionHandlers<Class<Place>>
* @param place
* the place that should be associated with the tab.
*/
public void addTab(String title, Class<Place> place, String link) {
public void addTab(String title, T place, String link) {
AnchorElement tabElement = Document.get().createAnchorElement();
tabElement.setHref(link);
tabElement.setInnerText(title);
tabElement.addClassName(style.navbar_button());
tabBarDiv.appendChild(tabElement);
knownPlaceClasses.add(place);
tabObjects.add(place);
}
/** {@inheritDoc} */
@Override
public HandlerRegistration addSelectionHandler(SelectionHandler<Class<Place>> handler) {
public HandlerRegistration addSelectionHandler(SelectionHandler<T> handler) {
return addHandler(handler, SelectionEvent.getType());
}
}
@@ -0,0 +1,20 @@
package com.sap.sailing.gwt.common.client.controls.tabbar;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
public interface TabBarResources extends ClientBundle {
public static final TabBarResources INSTANCE = GWT.create(TabBarResources.class);
@Source("TabBar.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String navbar();
String navbar_button();
String navbar_buttonhidden();
String navbar_buttonactive();
}
}
@@ -7,13 +7,10 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiField;
@@ -26,7 +23,7 @@ import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView.State;
/**
* Defines whole layout for site, including the header with the breadcrumbs and tab bar, and the content.
* Defines the basic Layout of tabbed pages with tabs, an optional header and a content area.
* <p/>
* Created by pgtaboada on 25.11.14.
*/
@@ -41,10 +38,10 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
SimplePanel additionalHeader;
@UiField
SimplePanel tabContentPanelUi;
// Should be TabBar<Class<PLACE>> but UiBinder causes weired generics errors related to the @UiHandler that would have a nested generic too.
@UiField
TabBar tabBar;
@UiField BreadcrumbPane breadcrumbs;
@UiField DivElement breadcrumbsContainer;
TabBar<Class<?>> tabBar;
@UiField FlowPanel tabExtension;
private TABVIEW currentTab;
@@ -56,15 +53,13 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
this.presenter = presenter;
this.historyMapper = historyMapper;
initWidget(ourUiBinder.createAndBindUi(this));
breadcrumbsContainer.getStyle().setDisplay(Display.NONE);
}
public TABVIEW getCurrentTab() {
return currentTab;
}
@UiChild
@UiChild(limit = 1)
public void addHeader(Widget widget) {
additionalHeader.setWidget(widget);
}
@@ -77,7 +72,6 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
* @param title
* The label for the tab.
*/
@SuppressWarnings("unchecked")
@UiChild
public void addTabContent(final TABVIEW tab, String title) {
GWT.log("Adding TAB: " + title);
@@ -90,7 +84,7 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
if(tab.getState() == State.VISIBLE) {
String link = "#" + historyMapper.getToken(tab.placeToFire());
tabBar.addTab(title, (Class<Place>) classForActivation, link);
tabBar.addTab(title, classForActivation, link);
}
}
@@ -101,7 +95,7 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
* @param event
*/
@UiHandler("tabBar")
void onTabSelection(SelectionEvent<Class<Place>> event) {
void onTabSelection(SelectionEvent<Class<?>> event) {
TabView<?, PRESENTER> selectedTabActivity = knownTabs.get(event.getSelectedItem());
if (selectedTabActivity != null) {
@@ -149,7 +143,9 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
// TODO better error handling
logger.log(Level.SEVERE, "Error while initializing Tab for place " + placeToGo.getClass().getName(), e);
}
tabBar.select(placeToGo);
@SuppressWarnings("unchecked")
final Class<PLACE> placeClass = (Class<PLACE>) placeToGo.getClass();
tabBar.select(placeClass);
currentTab = newTab;
@@ -166,14 +162,6 @@ public class TabPanel<PLACE extends Place, PRESENTER, TABVIEW extends TabView<PL
tabContentPanelUi.setWidget(widget);
}
public void addBreadcrumbItem(String title, String link, final Runnable runnable) {
breadcrumbs.addBreadcrumbItem(title, link, runnable);
}
public void addBreadcrumbItem(String title, SafeUri link, final Runnable runnable) {
breadcrumbs.addBreadcrumbItem(title, link, runnable);
}
public HandlerRegistration addTabPanelPlaceSelectionEventHandler(TabPanelPlaceSelectionEvent.Handler handler) {
return addHandler(handler, TabPanelPlaceSelectionEvent.TYPE);
}
@@ -1,5 +1,7 @@
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar" xmlns:b="urn:import:com.sap.sse.gwt.client.controls.busyindicator">
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar"
xmlns:b="urn:import:com.sap.sse.gwt.client.controls.busyindicator">
<ui:with field="res"
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
@@ -11,17 +13,6 @@
border-bottom: 1px solid #dedede;
}
.breadcrumb {
font-size: 1rem;
/* @alternate */ font-size: 0.866666666666667em;
font-weight: 600;
padding: 0.666666666666667em 0;
}
.back:hover {
background-color: #cfcfcf;
}
.content {
width: 100%;
height: 100%;
@@ -38,12 +29,6 @@
</ui:style>
<g:FlowPanel>
<g:HTMLPanel addStyleNames="{style.header}">
<div ui:field="breadcrumbsContainer" class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<c:BreadcrumbPane ui:field="breadcrumbs"
addStyleNames="{style.breadcrumb}" />
</div>
</div>
<g:SimplePanel ui:field="additionalHeader" />
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
@@ -232,4 +232,13 @@ public interface TextMessages extends Messages {
String impressum();
String playstoreCampaign();
String playstoreRacecommitteeApp();
String playstoreRacecommitteeBadge();
String appstoreStgTrainingstagebuch();
String appstoreBadgeSuffix();
}
@@ -223,3 +223,11 @@ contentStrategySimulator=Choosing the right strategy can provide great competiti
strategySimulatorReadMore=Learn More
impressum=Imprint
playstoreCampaign=utm_source=sapsailing&utm_medium=solutions&utm_content=2016.02&utm_campaign=solutions&pcampaignid=2016.sapsailing.solutions
playstoreRacecommitteeApp=https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app
playstoreRacecommitteeBadge=https://play.google.com/intl/en/badges/images/generic/en-play-badge.png
appstoreStgTrainingstagebuch=https://itunes.apple.com/de/app/stg-trainingstagebuch/id779563635?l=en&amp;mt=8
appstoreBadgeSuffix=_en
@@ -223,3 +223,9 @@ contentStrategySimulator=Während eines Rennens hängt viel von der Wahl der ric
strategySimulatorReadMore=Mehr erfahren
impressum=Impressum
playstoreApp=https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app&hl=de
playstoreBadge=https://play.google.com/intl/de-de/badges/images/generic/de-play-badge.png
appstoreStgTrainingstagebuch=https://itunes.apple.com/de/app/stg-trainingstagebuch/id779563635?l=de&amp;mt=8
appstoreBadgeSuffix=_de
@@ -221,3 +221,8 @@ strategySimulator=Тренажер стратегий
contentStrategySimulator=Выбор правильной стратегии может дать большое конкурентное преимущество во время гонки. Тренажер стратегий SAP упрощает определение лучшей стратегии хождения под парусом для различных ветровых режимов и водных течений. Поскольку ветер и течение в тренажере можно быстро изменять, надежность стратегии можно легко оценить даже в условиях изменчивой погоды.
strategySimulatorReadMore=Читать далее
playstoreApp=https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app&hl=ru
playstoreBadge=https://play.google.com/intl/ru/badges/images/generic/ru-play-badge.png
appstoreBadgeSuffix=_ru
@@ -220,3 +220,8 @@ strategySimulator=Strategy Simulator
contentStrategySimulator=在帆船比赛中,选择正确的策略可以提供巨大的竞争优势。Strategy Simulator 简化了多种风力情况和水流下最佳航行策略的制定过程。由于风和水流在模拟中会随时改变,甚至可以针对不确定的天气条件来轻松评估策略的稳固性。
strategySimulatorReadMore=了解更多
playstoreApp=https://play.google.com/store/apps/details?id=com.sap.sailing.racecommittee.app&hl=zh
playstoreBadge=https://play.google.com/intl/zh-cn/badges/images/generic/zh-cn-play-badge.png
appstoreBadgeSuffix=_zh
@@ -77,44 +77,6 @@ figcaption {
.mobile .wrapper {
padding-bottom: 11.333333333333334em;
}
.navbar {
font-size: 1rem;
}
.navbar_button {
font-size: 1.2em;
display: inline-block;
font-weight: 600;
color: #666;
border: 1px solid #dedede;
padding: 0.833333333333333em 0.944444444444444em;
background-color: #ebebeb;
-webkit-transition: background-color 0.2s, border-color 0.2s;
-moz-transition: background-color 0.2s, border-color 0.2s;
transition: background-color 0.2s, border-color 0.2s;
text-decoration: none;
margin-right: 0.555555555555556em;
}
.desktop .navbar_button {
border-top-left-radius: 0.277777777777778em;
border-top-right-radius: 0.277777777777778em;
}
.navbar_buttonhidden {
display: block;
}
.navbar_button:hover {
background-color: #dedede;
outline: none;
text-decoration: none;
}
.navbar_buttonactive {
color: #333;
background-color: #fff;
border-bottom: 1px solid #fff;
}
.navbar_buttonactive:hover {
background-color: #dedede;
border-bottom: 1px solid #dedede;
}
.button {
font-size: 1rem;
display: inline-block;
@@ -1,43 +0,0 @@
.siteheader {
font-size: 1rem;
background: #333;
border-bottom: 5px solid #f0ab00;
height: 70px;
line-height: 4em;
width: 100%;
overflow: hidden;
text-align:center;
}
.siteheaderLeft {
float:left;
width: 25%;
text-align: left;
}
.siteheaderCentered {
width: 50%;
display: inline-block;
margin:0 auto;
}
.siteheaderRight {
float:right;
width: 25%;
text-align: right;
}
.logo {
margin: 0.8em 10px;
float: left;
}
.logotitle {
display: inline;
color: #f6f9fc;
font-weight: bold;
}
.pagetitle {
color: #ffffff;
font-size: 1.5rem;
font-weight: bold;
}
@@ -1,51 +0,0 @@
package com.sap.sailing.gwt.common.theme.component.sapheader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.ParagraphElement;
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.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.theme.util.FullscreenUtil;
public class SAPHeader extends Composite {
private static SAPHeaderUiBinder uiBinder = GWT.create(SAPHeaderUiBinder.class);
interface SAPHeaderUiBinder extends UiBinder<Widget, SAPHeader> {
}
@UiField ParagraphElement applicationNameUi;
@UiField DivElement pageTitleUi;
@UiField Button startFullScreenButton;
public SAPHeader(String applicationName, String pageTitle, boolean startInAutoScreenMode) {
SAPHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
applicationNameUi.setInnerText(applicationName != null ? applicationName : "&nbsp;");
pageTitleUi.setInnerText(pageTitle);
startFullScreenButton.setVisible(startInAutoScreenMode);
// the 'fullscreen' button should disappear after some seconds (10)
if(startInAutoScreenMode) {
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
public boolean execute () {
startFullScreenButton.setVisible(false);
return false;
}
}, 10000);
}
}
@UiHandler("startFullScreenButton")
void startFullScreenClicked(ClickEvent e) {
FullscreenUtil.requestFullscreen();
}
}
@@ -1,25 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n"
type="com.sap.sailing.gwt.common.client.i18n.TextMessages" />
<ui:with field="res"
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.common.theme.component.sapheader.SAPHeaderResources" />
<g:HTMLPanel>
<header class="{local_res.css.siteheader}">
<div class="{local_res.css.siteheaderLeft}">
<g:Image resource="{local_res.logo}" pixelSize="80, 40" altText="SAP Sailing Analytics" styleName="{local_res.css.logo}"/>
<p ui:field="applicationNameUi" class="{local_res.css.logotitle}"></p>
</div>
<div class="{local_res.css.siteheaderCentered}">
<div ui:field="pageTitleUi" class="{local_res.css.pagetitle}"></div>
</div>
<div class="{local_res.css.siteheaderRight}">
<g:Button ui:field="startFullScreenButton" styleName="{res.mainCss.button}" text="Fullscreen" />
<span>&nbsp;</span>
</div>
</header>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,39 +0,0 @@
package com.sap.sailing.gwt.common.theme.component.sapheader2;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
public class SAPHeader2 extends Composite {
private static SAPHeaderUiBinder uiBinder = GWT.create(SAPHeaderUiBinder.class);
interface SAPHeaderUiBinder extends UiBinder<Widget, SAPHeader2> {
}
@UiField
DivElement applicationNameUi;
@UiField
SimplePanel pageTitleUi;
@UiField
SimplePanel rightSideUi;
public SAPHeader2(String applicationName, Widget pageTitle, boolean startInAutoScreenMode) {
SAPHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
applicationNameUi.setInnerText(applicationName != null ? applicationName : "&nbsp;");
pageTitleUi.setWidget(pageTitle);
}
public void addWidgetToRightSide(Widget widget) {
rightSideUi.add(widget);
}
}
@@ -1,22 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:with field="i18n"
type="com.sap.sailing.gwt.common.client.i18n.TextMessages" />
<ui:with field="res"
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.common.theme.component.sapheader2.SAPHeaderResources" />
<g:HTMLPanel>
<header class="{local_res.css.siteheader}">
<div class="{local_res.css.siteheaderLeft}">
<g:Image resource="{local_res.logo}" pixelSize="80, 40" altText="SAP Sailing Analytics" styleName="{local_res.css.logo}"/>
<div ui:field="applicationNameUi" class="{local_res.css.logotitle}"></div>
</div>
<g:SimplePanel ui:field="pageTitleUi" styleName="{local_res.css.siteheaderCentered}">
</g:SimplePanel>
<g:SimplePanel ui:field="rightSideUi" styleName="{local_res.css.siteheaderRight}">
</g:SimplePanel>
</header>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,26 +0,0 @@
package com.sap.sailing.gwt.common.theme.component.sapheader2;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
public interface SAPHeaderResources extends ClientBundle {
public static final SAPHeaderResources INSTANCE = GWT.create(SAPHeaderResources.class);
@Source("SAPHeader2.gss")
LocalCss css();
public interface LocalCss extends CssResource {
String siteheader();
String siteheaderLeft();
String siteheaderCentered();
String siteheaderRight();
String logo();
String logotitle();
String pagetitle();
}
@Source("logo-small@2x.png")
ImageResource logo();
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -13,6 +13,7 @@
<inherits name="com.sap.sse.gwt.AdminConsole" />
<inherits name="com.sap.sse.security.ui.LoginPanel" />
<inherits name="com.sap.sse.security.ui.Authentication" />
<inherits name="com.sap.sse.security.ui.UserProfile" />
<!-- Highcharts API -->
<inherits name='com.sap.sse.gwt.Highcharts' />
@@ -25,9 +26,7 @@
<inherits name="com.github.gwtbootstrap.BootstrapNoResources" />
<inherits name='com.github.gwtbootstrap.datetimepicker.DatetimepickerNoResources' />
<extend-property name="locale" values="en,de,zh,ru" />
<set-property name="locale" value="en,de,zh,ru" />
<set-property-fallback name="locale" value="en"/>
<inherits name='com.sap.sailing.gwt.common.SailingLocales' />
<source path='client' />
<source path='shared' />
@@ -1,10 +1,10 @@
package com.sap.sailing.gwt.home.communication.event;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -15,11 +15,11 @@ import com.sap.sailing.domain.leaderboard.LeaderboardGroup;
import com.sap.sailing.gwt.home.communication.SailingAction;
import com.sap.sailing.gwt.home.communication.SailingDispatchContext;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO;
import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO.EventType;
import com.sap.sailing.gwt.home.communication.eventview.RegattaMetadataDTO;
import com.sap.sailing.gwt.home.server.EventActionUtil;
import com.sap.sailing.gwt.home.server.LeaderboardContext;
import com.sap.sailing.gwt.home.server.EventActionUtil.LeaderboardCallback;
import com.sap.sailing.gwt.home.server.LeaderboardContext;
import com.sap.sailing.gwt.server.HomeServiceUtil;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.gwt.dispatch.shared.caching.IsClientCacheable;
@@ -51,7 +51,8 @@ public class GetEventViewAction implements SailingAction<EventViewDTO>, IsClient
ImageDescriptor logoImage = event.findImageWithTag(MediaTagConstants.LOGO);
dto.setLogoImage(logoImage != null ? HomeServiceUtil.convertToImageDTO(logoImage) : null);
dto.setOfficialWebsiteURL(event.getOfficialWebsiteURL() == null ? null : event.getOfficialWebsiteURL().toString());
dto.setSailorsInfoWebsiteURL(event.getSailorsInfoWebsiteURL() == null ? null : event.getSailorsInfoWebsiteURL().toString());
URL sailorsInfoWebsiteURL = event.getSailorsInfoWebsiteURLOrFallback(context.getClientLocale());
dto.setSailorsInfoWebsiteURL(sailorsInfoWebsiteURL == null ? null : sailorsInfoWebsiteURL.toString());
dto.setHasMedia(HomeServiceUtil.hasMedia(event));
dto.setState(HomeServiceUtil.calculateEventState(event));
@@ -104,16 +105,6 @@ public class GetEventViewAction implements SailingAction<EventViewDTO>, IsClient
} else {
dto.setType(dto.getRegattas().size() == 1 ? EventType.SINGLE_REGATTA: EventType.MULTI_REGATTA);
}
// Special solution for localization of SailorsInfo URL
if(dto.getSailorsInfoWebsiteURL() != null && !Locale.GERMAN.equals(context.getClientLocale())) {
String localizedURL = dto.getSailorsInfoWebsiteURL();
if(!localizedURL.endsWith("/")) {
localizedURL += "/";
}
localizedURL += "en";
dto.setSailorsInfoWebsiteURL(localizedURL);
}
return dto;
}
@@ -10,12 +10,12 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.gwt.common.client.controls.tabbar.BreadcrumbPane;
import com.sap.sailing.gwt.home.desktop.partials.footer.Footer;
import com.sap.sailing.gwt.home.desktop.partials.header.Header;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.DefaultErrorReporter;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.breadcrumb.BreadcrumbPane;
import com.sap.sse.security.ui.authentication.view.AuthenticationMenuView;
/**
@@ -2,7 +2,7 @@
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials"
xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar">
xmlns:sse="urn:import:com.sap.sse.gwt.client">
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
.mainContent {
@@ -22,7 +22,7 @@
<div ui:field="breadcrumbWrapperUi" style="display: none;">
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<c:BreadcrumbPane ui:field="breadcrumbsUi"
<sse:breadcrumb.BreadcrumbPane ui:field="breadcrumbsUi"
addStyleNames="{style.breadcrumb}" />
</div>
</div>
@@ -12,7 +12,6 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO;
import com.sap.sailing.gwt.home.communication.event.LabelType;
import com.sap.sailing.gwt.home.communication.eventlist.EventListEventSeriesDTO;
@@ -21,6 +20,7 @@ import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sse.gwt.client.LinkUtil;
public class EventTeaser extends Composite {
@@ -16,7 +16,6 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.communication.eventview.EventViewDTO;
import com.sap.sailing.gwt.home.communication.eventview.HasRegattaMetadata;
@@ -31,6 +30,7 @@ import com.sap.sailing.gwt.home.shared.utils.EventDatesFormatterUtil;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.home.shared.utils.LogoUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
public class EventHeader extends Composite {
private static EventHeaderUiBinder uiBinder = GWT.create(EventHeaderUiBinder.class);
@@ -1,9 +1,8 @@
package com.sap.sailing.gwt.home.desktop.partials.footer;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.ArrayList;
import java.util.Collection;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
@@ -26,11 +25,13 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.ValueListBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.gwt.common.client.GWTLocaleUtil;
import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator;
import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace;
import com.sap.sailing.gwt.home.desktop.places.whatsnew.WhatsNewPlace.WhatsNewNavigationTabs;
import com.sap.sailing.gwt.home.shared.SwitchingEntryPoint;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
public class Footer extends Composite {
@@ -107,21 +108,21 @@ public class Footer extends Composite {
}
private void updateUI() {
Set<String> availableLocales = new HashSet<String>(Arrays.asList(LocaleInfo.getAvailableLocaleNames()));
availableLocales.remove("default");
final Iterable<String> availableLocales = GWTLocaleUtil.getAvailableLocales();
final int localeCount = Util.size(availableLocales);
if(availableLocales.size() <= 1) {
if (localeCount <= 1) {
// only current language (or removed default) available
changeLanguageLink.removeFromParent();
changeLanguageList.removeFromParent();
languageSelectionDiv.removeFromParent();
return;
}
if(availableLocales.size() == 2) {
if (Util.size(availableLocales) == 2) {
changeLanguageList.removeFromParent();
// current language + one we can switch to
for(String localeName : availableLocales) {
if(!currentLocale.getLocaleName().equals(localeName)) {
for (String localeName : availableLocales) {
if (!currentLocale.getLocaleName().equals(localeName)) {
otherLanguage = localeName;
changeLanguageLink.setText(LocaleInfo.getLocaleNativeDisplayName(otherLanguage));
return;
@@ -130,12 +131,12 @@ public class Footer extends Composite {
return;
}
changeLanguageLink.removeFromParent();
Set<Pair<String, String>> values = new HashSet<>();
Collection<Pair<String, String>> values = new ArrayList<>();
Pair<String, String> selectedValue = null;
for(String localeName : availableLocales) {
for (String localeName : availableLocales) {
Pair<String, String> value = new Pair<String, String>(localeName, LocaleInfo.getLocaleNativeDisplayName(localeName));
values.add(value);
if(currentLocale.getLocaleName().equals(localeName)) {
if (currentLocale.getLocaleName().equals(localeName)) {
selectedValue = value;
}
}
@@ -13,9 +13,9 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.desktop.partials.regattanavigation.RegattaNavigationResources.LocalCss;
import com.sap.sailing.gwt.home.shared.utils.DropdownHandler;
import com.sap.sse.gwt.client.LinkUtil;
public class DropdownFilter<T> extends Composite {
@@ -13,7 +13,6 @@ import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.communication.event.EventMetadataDTO;
import com.sap.sailing.gwt.home.communication.event.EventState;
import com.sap.sailing.gwt.home.communication.fakeseries.EventSeriesViewDTO;
@@ -26,6 +25,7 @@ import com.sap.sailing.gwt.home.shared.places.event.EventDefaultPlace;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
public class SeriesHeader extends Composite {
private static SeriesHeaderUiBinder uiBinder = GWT.create(SeriesHeaderUiBinder.class);
@@ -7,6 +7,16 @@
type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res"
type="com.sap.sailing.gwt.home.desktop.partials.solutions.SolutionsResources" />
<ui:style>
.storeBadgesContainer>a>img {
height: 60px;
width: auto;
margin-right: 10px;
}
.storeBadgesContainer {
margin: 20px 0px;
}
</ui:style>
<g:HTMLPanel>
<!-- Page displays all solutions -->
<div class="{local_res.css.solutions}">
@@ -122,6 +132,18 @@
<p>
<ui:text from='{i18n.contentSapSailingRaceManager}' />
</p>
<div
class="{style.storeBadgesContainer}"
>
<a ui:field="raceManagerPlayStoreLinkUi"
href="{i18n.playstoreRacecommitteeApp}&amp;{i18n.playstoreCampaign}"
target="_blank"
><img
ui:field="raceManagerPlayStoreImgUi"
alt="Get it on Google Play"
src="{i18n.playstoreRacecommitteeBadge}"
/></a>
</div>
<g:Anchor ui:field="raceCommitteeAppDetailsAnchor"
styleName="{res.mainCss.button}">
<ui:text from='{i18n.sapSailingRaceManagerReadMore}' />
@@ -158,11 +180,16 @@
<p>
<ui:text from='{i18n.i18nDeSolutionsTrainingText}' />
</p>
<a
href="https://itunes.apple.com/de/app/stg-trainingstagebuch/id779563635?l=en&amp;mt=8"
target="_blank" class="{local_res.css.solutions_content_linkappstore}">
<img src="images/home/appstore.png"></img>
</a>
<div
class="{style.storeBadgesContainer}"
>
<a
alt="Get it on Appstore"
href="{i18n.appstoreStgTrainingstagebuch}"
target="_blank" class="{local_res.css.solutions_content_linkappstore}">
<img src="images/home/appstore{i18n.appstoreBadgeSuffix}.svg"></img>
</a>
</div>
</div>
</div>
</div>
@@ -14,7 +14,6 @@ import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.BoatClassImageResolver;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.communication.event.news.AbstractRaceNewsEntryDTO;
import com.sap.sailing.gwt.home.communication.event.news.LeaderboardNewsEntryDTO;
import com.sap.sailing.gwt.home.communication.event.news.NewsEntryDTO;
@@ -22,6 +21,7 @@ import com.sap.sailing.gwt.home.desktop.places.event.EventView;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.shared.util.ConditionalDateTimeFormatter;
import com.sap.sse.gwt.client.LinkUtil;
public class UpdatesBoxItem extends Widget {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@@ -1,32 +0,0 @@
package com.sap.sailing.gwt.home.desktop.partials.userHeader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
public class UserHeader extends Composite {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
interface MyUiBinder extends UiBinder<Widget, UserHeader> {
}
@UiField DivElement imageUi;
@UiField DivElement nameUi;
@UiField DivElement usernameUi;
public UserHeader() {
initWidget(uiBinder.createAndBindUi(this));
}
public void setUserManagementContext(AuthenticationContext userManagementContext) {
UserHeaderResources.INSTANCE.css().ensureInjected();
imageUi.getStyle().setBackgroundImage("url(images/home/userdefault.svg)");
nameUi.setInnerText(userManagementContext.getUserTitle());
usernameUi.setInnerText(userManagementContext.getUserSubtitle());
}
}
@@ -1,86 +0,0 @@
package com.sap.sailing.gwt.home.desktop.partials.useraccountDetails;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.InputElement;
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.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.client.i18n.StringMessages;
import com.sap.sse.security.ui.shared.UserDTO;
public class UserAccountDetails extends Composite {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
interface MyUiBinder extends UiBinder<Widget, UserAccountDetails> {
}
public interface Presenter {
void handleSaveChangesRequest(String fullName, String company);
void handleEmailChangeRequest(String email);
void handlePasswordChangeRequest(String oldPassword, String newPassword, String newPasswordConfirmation);
}
@UiField DivElement editImageLinkUi;
@UiField InputElement usernameUi;
@UiField TextBox nameUi;
@UiField TextBox companyUi;
@UiField TextBox emailUi;
@UiField PasswordTextBox oldPasswordUi;
@UiField PasswordTextBox newPasswordUi;
@UiField PasswordTextBox newPasswordConfirmationUi;
private final Presenter presenter;
public UserAccountDetails(Presenter presenter) {
this.presenter = presenter;
UseraccountDetailsResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
StringMessages i18n = StringMessages.INSTANCE;
setPlaceholder(oldPasswordUi, i18n.oldPasswordPlaceholder());
setPlaceholder(newPasswordUi, i18n.newPasswordPlaceholder());
setPlaceholder(newPasswordConfirmationUi, i18n.passwordRepeatPlaceholder());
}
public void setUserManagementContext(AuthenticationContext userManagementContext) {
UserDTO currentUser = userManagementContext.getCurrentUser();
// TODO correct message
editImageLinkUi.setTitle("TODO picture of: " + currentUser.getName());
// TODO use image from user when field is available
editImageLinkUi.getStyle().setBackgroundImage("url(images/home/userdefault.svg)");
nameUi.setValue(currentUser.getFullName());
companyUi.setValue(currentUser.getCompany());
usernameUi.setValue(currentUser.getName());
emailUi.setValue(currentUser.getEmail());
oldPasswordUi.setValue("");
newPasswordUi.setValue("");
newPasswordConfirmationUi.setValue("");
}
private void setPlaceholder(Widget widget, String placeholderText) {
widget.getElement().setAttribute("placeholder", placeholderText);
}
@UiHandler("saveChangesUi")
void onSaveChangesClicked(ClickEvent event) {
presenter.handleSaveChangesRequest(nameUi.getValue(), companyUi.getValue());
}
@UiHandler("changeEmailUi")
void onChangeEmailClicked(ClickEvent event) {
presenter.handleEmailChangeRequest(emailUi.getValue());
}
@UiHandler("changePasswordUi")
void onChangePasswordClicked(ClickEvent event) {
presenter.handlePasswordChangeRequest(oldPasswordUi.getValue(), newPasswordUi.getValue(),
newPasswordConfirmationUi.getValue());
}
}
@@ -15,7 +15,6 @@ import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.desktop.partials.eventheader.EventHeader;
import com.sap.sailing.gwt.home.desktop.partials.sailorinfo.SailorInfo;
import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.client.StringMessages;
public class TabletAndDesktopMultiRegattaEventView extends Composite implements EventMultiregattaView {
@@ -43,7 +42,6 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements
tabPanelUi = new TabPanel<>(currentPresenter, historyMapper);
eventHeader = new EventHeader(currentPresenter);
initWidget(uiBinder.createAndBindUi(this));
initBreadCrumbs();
String sailorsInfoURL = currentPresenter.getEventDTO().getSailorsInfoWebsiteURL();
if(sailorsInfoURL != null && ! sailorsInfoURL.isEmpty()) {
@@ -70,21 +68,6 @@ public class TabletAndDesktopMultiRegattaEventView extends Composite implements
public void onTabSelection(TabPanelPlaceSelectionEvent e) {
currentPresenter.handleTabPlaceSelection((TabView<?, EventMultiregattaView.Presenter>) e.getSelectedActivity());
}
private void initBreadCrumbs() {
addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation());
addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation());
addBreadCrumbItem(currentPresenter.getEventDTO().getDisplayName(), currentPresenter.getCurrentEventNavigation());
}
private void addBreadCrumbItem(String label, final PlaceNavigation<?> placeNavigation) {
tabPanelUi.addBreadcrumbItem(label, placeNavigation.getTargetUrl(), new Runnable() {
@Override
public void run() {
placeNavigation.goToPlace();
}
});
}
@Override
public void showErrorInCurrentTab(IsWidget errorView) {
@@ -14,7 +14,6 @@ import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanel;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanelPlaceSelectionEvent;
@@ -27,6 +26,7 @@ import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.places.fakeseries.SeriesDefaultPlace;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
public class TabletAndDesktopRegattaEventView extends Composite implements EventRegattaView {
@@ -53,7 +53,6 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event
tabPanelUi = new TabPanel<>(currentPresenter, historyMapper);
eventHeader = new EventHeader(currentPresenter);
initWidget(uiBinder.createAndBindUi(this));
initBreadCrumbs();
if(currentPresenter.getEventDTO().getType() == EventType.SERIES_EVENT) {
final PlaceNavigation<SeriesDefaultPlace> currentEventSeriesNavigation = currentPresenter.getCurrentEventSeriesNavigation();
@@ -102,28 +101,6 @@ public class TabletAndDesktopRegattaEventView extends Composite implements Event
currentPresenter.handleTabPlaceSelection((TabView<?, EventRegattaView.Presenter>) e.getSelectedActivity());
}
private void initBreadCrumbs() {
addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation());
addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation());
if(currentPresenter.getEventDTO().getType() == EventType.SERIES_EVENT) {
addBreadCrumbItem(currentPresenter.getEventDTO().getSeriesName(), currentPresenter.getCurrentEventSeriesNavigation());
}
addBreadCrumbItem(currentPresenter.getEventDTO().getLocationOrDisplayName(), currentPresenter.getCurrentEventNavigation());
if(currentPresenter.showRegattaMetadata()) {
addBreadCrumbItem(currentPresenter.getRegattaMetadata().getDisplayName(), currentPresenter.getCurrentRegattaOverviewNavigation());
}
}
private void addBreadCrumbItem(String label, final PlaceNavigation<?> placeNavigation) {
tabPanelUi.addBreadcrumbItem(label, placeNavigation.getTargetUrl(), new Runnable() {
@Override
public void run() {
placeNavigation.goToPlace();
}
});
}
@Override
public void showErrorInCurrentTab(IsWidget errorView) {
tabPanelUi.overrideCurrentContentInTab(errorView);
@@ -5,7 +5,6 @@ import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.controls.tabbar.BreadcrumbPane;
import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator;
import com.sap.sailing.gwt.home.desktop.partials.eventsrecent.EventsOverviewRecent;
import com.sap.sailing.gwt.home.desktop.partials.eventsupcoming.EventsOverviewUpcoming;
@@ -13,6 +12,7 @@ import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.places.events.EventsPlace;
import com.sap.sailing.gwt.home.shared.places.start.StartPlace;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.breadcrumb.BreadcrumbPane;
public class TabletAndDesktopEventsView extends AbstractEventsView {
private static EventsPageViewUiBinder uiBinder = GWT.create(EventsPageViewUiBinder.class);
@@ -1,6 +1,6 @@
<!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:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar"
xmlns:sse="urn:import:com.sap.sse.gwt.client"
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
@@ -17,7 +17,7 @@
</ui:style>
<g:HTMLPanel addStyleNames="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<c:BreadcrumbPane ui:field="breadcrumbs" addStyleNames="{style.breadcrumb}" />
<sse:breadcrumb.BreadcrumbPane ui:field="breadcrumbs" addStyleNames="{style.breadcrumb}" />
<dp:eventsupcoming.EventsOverviewUpcoming ui:field='upcomingEventsWidget'/>
<dp:eventsrecent.EventsOverviewRecent ui:field='recentEventsWidget'/>
</div>
@@ -14,7 +14,6 @@ import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.desktop.partials.seriesheader.SeriesHeader;
import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.ui.client.StringMessages;
public class TabletAndDesktopSeriesView extends Composite implements SeriesView<AbstractSeriesTabPlace, SeriesView.Presenter> {
@@ -46,8 +45,6 @@ public class TabletAndDesktopSeriesView extends Composite implements SeriesView<
seriesHeader = new SeriesHeader(currentPresenter);
initWidget(uiBinder.createAndBindUi(this));
initBreadCrumbs();
}
@Override
@@ -70,21 +67,6 @@ public class TabletAndDesktopSeriesView extends Composite implements SeriesView<
currentPresenter.handleTabPlaceSelection((TabView<?, SeriesView.Presenter>) e.getSelectedActivity());
}
private void initBreadCrumbs() {
addBreadCrumbItem(i18n.home(), currentPresenter.getHomeNavigation());
addBreadCrumbItem(i18n.events(), currentPresenter.getEventsNavigation());
addBreadCrumbItem(currentPresenter.getSeriesDTO().getDisplayName(), currentPresenter.getCurrentEventSeriesNavigation());
}
private void addBreadCrumbItem(String label, final PlaceNavigation<?> placeNavigation) {
tabPanelUi.addBreadcrumbItem(label, placeNavigation.getTargetUrl(), new Runnable() {
@Override
public void run() {
placeNavigation.goToPlace();
}
});
}
@Override
public void showErrorInCurrentTab(IsWidget errorView) {
tabPanelUi.overrideCurrentContentInTab(errorView);
@@ -8,15 +8,16 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanel;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabPanelPlaceSelectionEvent;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.desktop.partials.userHeader.UserHeader;
import com.sap.sailing.gwt.home.shared.app.ApplicationHistoryMapper;
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.userprofile.desktop.userheader.UserHeader;
public class TabletAndDesktopUserProfileView extends Composite implements UserProfileView<AbstractUserProfilePlace, UserProfileView.Presenter> {
private static final ApplicationHistoryMapper historyMapper = GWT.<ApplicationHistoryMapper> create(ApplicationHistoryMapper.class);
@@ -44,7 +45,7 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
this.currentPresenter = currentPresenter;
tabPanelUi = new TabPanel<>(currentPresenter, historyMapper);
headerUi = new UserHeader();
headerUi = new UserHeader(SharedResources.INSTANCE);
initWidget(uiBinder.createAndBindUi(this));
}
@@ -64,9 +65,9 @@ public class TabletAndDesktopUserProfileView extends Composite implements UserPr
}
@Override
public void setUserManagementContext(AuthenticationContext userManagementContext) {
headerUi.setUserManagementContext(userManagementContext);
tabPanelUi.getCurrentTab().setUserManagementContext(userManagementContext);
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
headerUi.setAuthenticationContext(authenticationContext);
tabPanelUi.getCurrentTab().setAuthenticationContext(authenticationContext);
}
@SuppressWarnings("unchecked")
@@ -1,7 +1,7 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.sap.sailing.gwt.common.client.controls.tabbar"
xmlns:dp="urn:import:com.sap.sailing.gwt.home.desktop.partials"
xmlns:uh="urn:import:com.sap.sse.security.ui.userprofile.desktop.userheader"
xmlns:s="urn:import:com.sap.sailing.gwt.home.desktop.places.user.profile">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="tm" type="com.sap.sailing.gwt.common.client.i18n.TextMessages" />
@@ -40,10 +40,10 @@
<g:HTMLPanel>
<c:TabPanel ui:field="tabPanelUi">
<c:header>
<dp:userHeader.UserHeader ui:field="headerUi" />
<uh:UserHeader ui:field="headerUi" />
</c:header>
<c:tabcontent title="{i18n.details}">
<s:detailstab.UserProfileDetailsTabView />
<s:detailstab.UserProfileDetailsTabView ui:field="detailsTabUi" />
</c:tabcontent>
</c:TabPanel>
</g:HTMLPanel>
@@ -6,8 +6,6 @@ import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.UriUtils;
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.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.desktop.app.DesktopPlacesNavigator;
@@ -18,10 +16,10 @@ import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace;
import com.sap.sailing.gwt.home.shared.places.start.StartPlace;
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.ui.authentication.AuthenticationContextEvent;
import com.sap.sse.security.ui.authentication.AuthenticationManager;
import com.sap.sse.security.ui.authentication.AuthenticationRequestEvent;
import com.sap.sse.security.ui.client.component.NewAccountValidator;
import com.sap.sse.security.ui.client.UserManagementServiceAsync;
import com.sap.sse.security.ui.client.i18n.StringMessages;
public class UserProfileActivity extends AbstractActivity implements UserProfileView.Presenter {
@@ -33,16 +31,15 @@ public class UserProfileActivity extends AbstractActivity implements UserProfile
protected final DesktopPlacesNavigator homePlacesNavigator;
private final StringMessages i18n_sec = StringMessages.INSTANCE;
private final NewAccountValidator validator = new NewAccountValidator(i18n_sec);
private UserProfileView<AbstractUserProfilePlace, UserProfileView.Presenter> currentView = new TabletAndDesktopUserProfileView();
public UserProfileActivity(AbstractUserProfilePlace place, UserProfileClientFactory clientFactory,
DesktopPlacesNavigator homePlacesNavigator, NavigationPathDisplay navigationPathDisplay) {
this.currentPlace = place;
this.clientFactory = clientFactory;
this.homePlacesNavigator = homePlacesNavigator;
initNavigationPath(navigationPathDisplay);
}
@@ -57,86 +54,16 @@ public class UserProfileActivity extends AbstractActivity implements UserProfile
currentView.registerPresenter(this);
panel.setWidget(currentView);
currentView.navigateTabsTo(currentPlace);
currentView.setUserManagementContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
currentView.setAuthenticationContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
eventBus.addHandler(AuthenticationContextEvent.TYPE, new AuthenticationContextEvent.Handler() {
@Override
public void onUserChangeEvent(AuthenticationContextEvent event) {
currentView.setUserManagementContext(event.getCtx());
currentView.setAuthenticationContext(event.getCtx());
}
});
}
@Override
public void handleSaveChangesRequest(String fullName, String company) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
clientFactory.getUserManagementService().updateUserProperties(username, fullName, company,
new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
clientFactory.getAuthenticationManager().refreshUserInfo();
Window.alert(i18n_sec.successfullyUpdatedUserProperties(username));
}
@Override
public void onFailure(Throwable caught) {
Window.alert(i18n_sec.errorUpdatingUserProperties(caught.getMessage()));
}
});
}
@Override
public void handleEmailChangeRequest(final String email) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
final String url = Window.Location.createUrlBuilder()
.setHash(homePlacesNavigator.getMailVerifiedConfirmationNavigation().getTargetUrl()).buildString();
clientFactory.getUserManagementService().updateSimpleUserEmail(username, email, url,
new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
Window.alert(i18n_sec.successfullyUpdatedEmail(username, email));
}
@Override
public void onFailure(Throwable caught) {
Window.alert(i18n_sec.errorUpdatingEmail(caught.getMessage()));
}
});
}
@Override
public void handlePasswordChangeRequest(String oldPassword, String newPassword, String newPasswordConfirmation) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
String errorMessage = validator.validateUsernameAndPassword(username, newPassword, newPasswordConfirmation);
if (errorMessage != null && !errorMessage.isEmpty()) {
Window.alert(errorMessage);
return;
}
clientFactory.getUserManagementService().updateSimpleUserPassword(username, oldPassword, null, newPassword,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
if (caught instanceof UserManagementException) {
String message = ((UserManagementException) caught).getMessage();
if (UserManagementException.PASSWORD_DOES_NOT_MEET_REQUIREMENTS.equals(message)) {
Window.alert(i18n_sec.passwordDoesNotMeetRequirements());
} else if (UserManagementException.INVALID_CREDENTIALS.equals(message)) {
Window.alert(i18n_sec.invalidCredentials());
} else {
Window.alert(i18n_sec.errorChangingPassword(caught.getMessage()));
}
} else {
Window.alert(i18n_sec.errorChangingPassword(caught.getMessage()));
}
}
@Override
public void onSuccess(Void result) {
Window.alert(i18n_sec.passwordSuccessfullyChanged());
currentView.setUserManagementContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
}
});
}
@Override
public void handleTabPlaceSelection(TabView<?, ? extends UserProfileView.Presenter> selectedActivity) {
Place tabPlaceToGo = selectedActivity.placeToFire();
@@ -168,4 +95,20 @@ public class UserProfileActivity extends AbstractActivity implements UserProfile
public void doTriggerLoginForm() {
clientFactory.getEventBus().fireEvent(new AuthenticationRequestEvent());
}
@Override
public AuthenticationManager getAuthenticationManager() {
return clientFactory.getAuthenticationManager();
}
@Override
public String getMailVerifiedUrl() {
return homePlacesNavigator
.getMailVerifiedConfirmationNavigation().getTargetUrl();
}
@Override
public UserManagementServiceAsync getUserManagementService() {
return clientFactory.getUserManagementService();
}
}
@@ -2,10 +2,8 @@ package com.sap.sailing.gwt.home.desktop.places.user.profile;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
public interface UserProfileTabView<PLACE extends AbstractUserProfilePlace> extends TabView<PLACE, UserProfileView.Presenter> {
void setUserManagementContext(AuthenticationContext userManagementContext);
public interface UserProfileTabView<PLACE extends AbstractUserProfilePlace> extends
TabView<PLACE, UserProfileView.Presenter>, NeedsAuthenticationContext {
}
@@ -4,17 +4,18 @@ import com.google.gwt.place.shared.Place;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.user.client.ui.IsWidget;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.desktop.partials.useraccountDetails.UserAccountDetails;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.places.fakeseries.AbstractSeriesPlace;
import com.sap.sailing.gwt.home.shared.places.start.StartPlace;
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.authentication.AuthenticationManager;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.client.UserManagementServiceAsync;
public interface UserProfileView<PLACE extends AbstractUserProfilePlace, PRES extends UserProfileView.Presenter> extends IsWidget {
public interface UserProfileView<PLACE extends AbstractUserProfilePlace, PRES extends UserProfileView.Presenter> extends IsWidget, NeedsAuthenticationContext {
public interface Presenter extends UserAccountDetails.Presenter, NotLoggedInPresenter {
public interface Presenter extends NotLoggedInPresenter {
void handleTabPlaceSelection(TabView<?, ? extends Presenter> selectedActivity);
SafeUri getUrl(AbstractSeriesPlace place);
@@ -22,6 +23,12 @@ public interface UserProfileView<PLACE extends AbstractUserProfilePlace, PRES ex
PlaceNavigation<StartPlace> getHomeNavigation();
PlaceNavigation<? extends AbstractUserProfilePlace> getUserProfileNavigation();
AuthenticationManager getAuthenticationManager();
UserManagementServiceAsync getUserManagementService();
String getMailVerifiedUrl();
}
/**
@@ -39,7 +46,4 @@ public interface UserProfileView<PLACE extends AbstractUserProfilePlace, PRES ex
void navigateTabsTo(PLACE place);
void showErrorInCurrentTab(IsWidget errorView);
void setUserManagementContext(AuthenticationContext userManagementContext);
}
@@ -0,0 +1,27 @@
package com.sap.sailing.gwt.home.desktop.places.user.profile.detailstab;
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileView;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsPresenter;
public class UserProfileDetailsPresenter implements UserProfileDetailsView.Presenter {
private final UserProfileDetailsView view;
private final UserDetailsPresenter userDetailsPresenter;
public UserProfileDetailsPresenter(UserProfileDetailsView view, UserProfileView.Presenter userProfilePresenter) {
this.view = view;
view.setPresenter(this);
userDetailsPresenter = new UserDetailsPresenter(view.getUserDetailsView(),
userProfilePresenter.getAuthenticationManager(), userProfilePresenter.getUserManagementService(),
userProfilePresenter.getMailVerifiedUrl());
}
@Override
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
view.getDecorator().setAuthenticationContext(authenticationContext);
userDetailsPresenter.setAuthenticationContext(authenticationContext);
}
}
@@ -1,17 +1,11 @@
package com.sap.sailing.gwt.home.desktop.places.user.profile.detailstab;
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.AcceptsOneWidget;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.controls.tabbar.TabView;
import com.sap.sailing.gwt.home.desktop.partials.useraccountDetails.UserAccountDetails;
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileTabView;
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileView;
import com.sap.sailing.gwt.home.shared.places.user.profile.UserProfileDetailsPlace;
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.AuthorizedContentDecoratorDesktop;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
/**
@@ -19,18 +13,9 @@ import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
*/
public class UserProfileDetailsTabView extends Composite implements UserProfileTabView<UserProfileDetailsPlace> {
interface MyBinder extends UiBinder<Widget, UserProfileDetailsTabView> {
}
private UserProfileDetailsView.Presenter currentPresenter;
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField(provided = true)
AuthorizedContentDecoratorDesktop decoratorUi;
@UiField(provided = true)
UserAccountDetails accountDetailsUi;
private UserProfileView.Presenter currentPresenter;
private UserProfileDetailsView view;
public UserProfileDetailsTabView() {
}
@@ -47,16 +32,12 @@ public class UserProfileDetailsTabView extends Composite implements UserProfileT
@Override
public void start(UserProfileDetailsPlace myPlace, AcceptsOneWidget contentArea) {
decoratorUi = new AuthorizedContentDecoratorDesktop(currentPresenter);
accountDetailsUi = new UserAccountDetails(currentPresenter);
initWidget(ourUiBinder.createAndBindUi(this));
contentArea.setWidget(this);
contentArea.setWidget(view);
}
@Override
public void setUserManagementContext(AuthenticationContext userManagementContext) {
decoratorUi.setUserManagementContext(userManagementContext);
accountDetailsUi.setUserManagementContext(userManagementContext);
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
currentPresenter.setAuthenticationContext(authenticationContext);
}
@Override
@@ -71,6 +52,7 @@ public class UserProfileDetailsTabView extends Composite implements UserProfileT
@Override
public void setPresenter(UserProfileView.Presenter currentPresenter) {
this.currentPresenter = currentPresenter;
view = new UserProfileDetailsViewImpl();
this.currentPresenter = new UserProfileDetailsPresenter(view, currentPresenter);
}
}
@@ -0,0 +1,19 @@
package com.sap.sailing.gwt.home.desktop.places.user.profile.detailstab;
import com.google.gwt.user.client.ui.IsWidget;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsView;
public interface UserProfileDetailsView extends IsWidget {
void setPresenter(Presenter presenter);
UserDetailsView getUserDetailsView();
NeedsAuthenticationContext getDecorator();
public interface Presenter {
void setAuthenticationContext(AuthenticationContext userManagementContext);
}
}
@@ -0,0 +1,52 @@
package com.sap.sailing.gwt.home.desktop.places.user.profile.detailstab;
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.Widget;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.home.desktop.places.user.profile.UserProfileView;
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.AuthorizedContentDecoratorDesktop;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
import com.sap.sse.security.ui.userprofile.desktop.userdetails.UserAccountDetails;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsView;
/**
* Created by pgtaboada on 25.11.14.
*/
public class UserProfileDetailsViewImpl extends Composite implements UserProfileDetailsView {
interface MyBinder extends UiBinder<Widget, UserProfileDetailsViewImpl> {
}
private static MyBinder ourUiBinder = GWT.create(MyBinder.class);
@UiField(provided = true)
AuthorizedContentDecoratorDesktop decoratorUi;
@UiField(provided = true)
UserAccountDetails accountDetailsUi;
private UserProfileView.Presenter currentPresenter;
public UserProfileDetailsViewImpl() {
}
public UserDetailsView getUserDetailsView() {
return accountDetailsUi;
}
@Override
public void setPresenter(Presenter presenter) {
decoratorUi = new AuthorizedContentDecoratorDesktop(currentPresenter);
accountDetailsUi = new UserAccountDetails(SharedResources.INSTANCE);
initWidget(ourUiBinder.createAndBindUi(this));
}
@Override
public NeedsAuthenticationContext getDecorator() {
return decoratorUi;
}
}
@@ -1,12 +1,13 @@
<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.desktop.partials" xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator">
xmlns:ud="urn:import:com.sap.sse.security.ui.userprofile.desktop.userdetails"
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:style>
</ui:style>
<um:AuthorizedContentDecoratorDesktop ui:field="decoratorUi">
<um:content>
<s:useraccountDetails.UserAccountDetails ui:field="accountDetailsUi"
<ud:UserAccountDetails ui:field="accountDetailsUi"
addStyleNames="{res.mainCss.spacermargintopmediumbig} {res.mainCss.spacermarginbottommediumbig}" />
</um:content>
</um:AuthorizedContentDecoratorDesktop>
@@ -15,7 +15,6 @@ import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.EventBus;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
import com.sap.sailing.gwt.home.mobile.app.MobilePlacesNavigator;
import com.sap.sailing.gwt.home.shared.ExperimentalFeatures;
@@ -23,8 +22,9 @@ import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.app.ResettableNavigationPathDisplay;
import com.sap.sailing.gwt.home.shared.utils.DropdownHandler;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
import com.sap.sse.security.ui.authentication.AuthenticationContextEvent;
import com.sap.sse.security.ui.authentication.AuthenticationRequestEvent;
import com.sap.sse.security.ui.authentication.AuthenticationSignOutRequestEvent;
public class Header extends Composite {
@@ -73,7 +73,7 @@ public class Header extends Composite {
signOutNavigationItem = addNavigation(com.sap.sse.security.ui.client.i18n.StringMessages.INSTANCE.signOut(), new Runnable() {
@Override
public void run() {
eventBus.fireEvent(new AuthenticationRequestEvent(false));
eventBus.fireEvent(new AuthenticationSignOutRequestEvent());
}
});
@@ -16,12 +16,12 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.home.communication.event.LabelType;
import com.sap.sailing.gwt.home.shared.app.PlaceNavigation;
import com.sap.sailing.gwt.home.shared.partials.filter.AbstractSelectionFilter;
import com.sap.sailing.gwt.home.shared.utils.CollapseAnimation;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sse.gwt.client.LinkUtil;
public class SectionHeaderContent extends Composite {
@@ -4,6 +4,16 @@
<ui:with field="i18n" type="com.sap.sailing.gwt.common.client.i18n.TextMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.solutions.SolutionsResources" />
<ui:style>
.storeBadgesContainer>a>img {
height: 60px;
width: auto;
margin-right: 10px;
}
.storeBadgesContainer {
margin: 20px 0px;
}
</ui:style>
<g:HTMLPanel>
<div class="{res.mediaCss.grid}">
<div class="{local_res.css.solutions} {local_res.css.accordion}">
@@ -93,6 +103,18 @@
<p>
<ui:text from='{i18n.contentSapSailingRaceManager}' />
</p>
<div
class="{style.storeBadgesContainer}"
>
<a ui:field="raceManagerPlayStoreLinkUi"
href="{i18n.playstoreRacecommitteeApp}&amp;{i18n.playstoreCampaign}"
target="_blank"
><img
ui:field="raceManagerPlayStoreImgUi"
alt="Get it on Google Play"
src="{i18n.playstoreRacecommitteeBadge}"
/></a>
</div>
</div>
</div>
<div ui:field="postRaceAnalyticsUi"
@@ -128,6 +150,16 @@
<p>
<ui:text from='{i18n.i18nDeSolutionsTrainingText}' />
</p>
<div
class="{style.storeBadgesContainer}"
>
<a
alt="Get it on Appstore"
href="{i18n.appstoreStgTrainingstagebuch}"
target="_blank" >
<img src="images/home/appstore{i18n.appstoreBadgeSuffix}.svg"></img>
</a>
</div>
</div>
</div>
<div ui:field="strategySimulatorUi"
@@ -1,69 +0,0 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:s="urn:import:com.sap.sailing.gwt.home.client.shared">
<ui:with field="i18n" type="com.sap.sailing.gwt.ui.client.StringMessages" />
<ui:with field="i18n_sec" type="com.sap.sse.security.ui.client.i18n.StringMessages" />
<ui:with field="res" type="com.sap.sailing.gwt.common.client.SharedResources" />
<ui:with field="local_res" type="com.sap.sailing.gwt.home.mobile.partials.userdetails.UserDetailsResources" />
<g:HTMLPanel>
<div class="{local_res.css.userdetails}">
<div class="{res.mediaCss.grid}">
<div class="{res.mediaCss.small12} {res.mediaCss.columns}">
<form action="" method="">
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.username}' />
</div>
<input ui:field="usernameUi" type="text" disabled="disabled" class="{res.mainCss.input_input}" />
</div>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.name}' />
</div>
<input ui:field="nameUi" type="text" class="{res.mainCss.input_input}" />
</div>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.company}' />
</div>
<input ui:field="companyUi" type="text" class="{res.mainCss.input_input}" />
</div>
<g:Button ui:field="saveChangesUi" addStyleNames="{local_res.css.userdetails_save} {res.mainCss.button} {res.mainCss.buttonprimary}">
<ui:text from='{i18n_sec.save}' />
</g:Button>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.email}' />
</div>
<g:TextBox ui:field="emailUi" addStyleNames="{res.mainCss.input_input}" />
</div>
<g:Button ui:field="changeEmailUi" addStyleNames="{local_res.css.userdetails_save} {res.mainCss.button} {res.mainCss.buttonprimary}">
<ui:text from='{i18n_sec.save}' />
</g:Button>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.oldPassword}' />
</div>
<g:PasswordTextBox ui:field="oldPasswordUi" addStyleNames="{res.mainCss.input_input}" />
</div>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.password}' />
</div>
<g:PasswordTextBox ui:field="newPasswordUi" addStyleNames="{res.mainCss.input_input}" />
</div>
<div class="{res.mainCss.input}">
<div class="{res.mainCss.input_label}">
<ui:text from='{i18n_sec.passwordRepeat}' />
</div>
<g:PasswordTextBox ui:field="newPasswordConfirmationUi" addStyleNames="{res.mainCss.input_input}" />
</div>
<g:Button ui:field="changePasswordUi" addStyleNames="{local_res.css.userdetails_save} {res.mainCss.button} {res.mainCss.buttonprimary}">
<ui:text from='{i18n_sec.changePassword}' />
</g:Button>
</form>
</div>
</div>
</div>
</g:HTMLPanel>
</ui:UiBinder>
@@ -1,43 +0,0 @@
package com.sap.sailing.gwt.home.mobile.partials.userheader;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.HeadingElement;
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.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.shared.UserDTO;
public class UserHeader extends Composite {
interface MyUiBinder extends UiBinder<Widget, UserHeader> {
}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@UiField HeadingElement titleUi;
@UiField DivElement imageUi;
@UiField DivElement subtitleUi;
public UserHeader() {
UserHeaderResources.INSTANCE.css().ensureInjected();
initWidget(uiBinder.createAndBindUi(this));
imageUi.getStyle().setBackgroundImage("url(images/home/userdefault.svg)");
titleUi.setInnerText("testuser");
subtitleUi.setInnerText("jennifer@auchnichtwennduderletztemenschauferdenwaerts.looser");
}
public void setUserManagementContext(AuthenticationContext userManagementContext) {
UserDTO currentUser = userManagementContext.getCurrentUser();
// TODO correct message
imageUi.setTitle("TODO picture of: " + currentUser.getName());
// TODO use image from user when field is available
imageUi.getStyle().setBackgroundImage("url(images/home/userdefault.svg)");
titleUi.setInnerText(userManagementContext.getUserTitle());
subtitleUi.setInnerText(userManagementContext.getUserSubtitle());
}
}
@@ -2,24 +2,19 @@ package com.sap.sailing.gwt.home.mobile.places.user.profile;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.sap.sailing.gwt.home.mobile.app.MobileApplicationClientFactory;
import com.sap.sailing.gwt.home.shared.places.user.profile.AbstractUserProfilePlace;
import com.sap.sse.security.shared.UserManagementException;
import com.sap.sse.security.ui.authentication.AuthenticationContextEvent;
import com.sap.sse.security.ui.client.component.NewAccountValidator;
import com.sap.sse.security.ui.client.i18n.StringMessages;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsPresenter;
public class UserProfileDetailsActivity extends AbstractActivity implements UserProfileDetailsView.Presenter {
private final MobileApplicationClientFactory clientFactory;
private final StringMessages i18n_sec = StringMessages.INSTANCE;
private final NewAccountValidator validator = new NewAccountValidator(i18n_sec);
private final UserProfileDetailsView currentView = new UserProfileDetailsViewImpl(this);
private UserDetailsPresenter userDetailsPresenter;
public UserProfileDetailsActivity(AbstractUserProfilePlace place, MobileApplicationClientFactory clientFactory) {
this.clientFactory = clientFactory;
@@ -28,11 +23,17 @@ public class UserProfileDetailsActivity extends AbstractActivity implements User
@Override
public void start(final AcceptsOneWidget panel, final EventBus eventBus) {
panel.setWidget(currentView);
currentView.setUserManagementContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
currentView.setAuthenticationContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
userDetailsPresenter = new UserDetailsPresenter(currentView.getUserDetailsView(),
clientFactory.getAuthenticationManager(), clientFactory.getUserManagementService(), clientFactory
.getNavigator().getMailVerifiedConfirmationNavigation().getTargetUrl());
eventBus.addHandler(AuthenticationContextEvent.TYPE, new AuthenticationContextEvent.Handler() {
@Override
public void onUserChangeEvent(AuthenticationContextEvent event) {
currentView.setUserManagementContext(event.getCtx());
currentView.setAuthenticationContext(event.getCtx());
userDetailsPresenter.setAuthenticationContext(event.getCtx());
}
});
}
@@ -41,76 +42,4 @@ public class UserProfileDetailsActivity extends AbstractActivity implements User
public void doTriggerLoginForm() {
clientFactory.getNavigator().getSignInNavigation().goToPlace();
}
@Override
public void handleSaveChangesRequest(String fullName, String company) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
clientFactory.getUserManagementService().updateUserProperties(username, fullName, company,
new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
clientFactory.getAuthenticationManager().refreshUserInfo();
Window.alert(i18n_sec.successfullyUpdatedUserProperties(username));
}
@Override
public void onFailure(Throwable caught) {
Window.alert(i18n_sec.errorUpdatingUserProperties(caught.getMessage()));
}
});
}
@Override
public void handleEmailChangeRequest(final String email) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
final String url = Window.Location.createUrlBuilder()
.setHash(clientFactory.getNavigator().getMailVerifiedConfirmationNavigation().getTargetUrl())
.buildString();
clientFactory.getUserManagementService().updateSimpleUserEmail(username, email, url,
new AsyncCallback<Void>() {
@Override
public void onSuccess(Void result) {
Window.alert(i18n_sec.successfullyUpdatedEmail(username, email));
}
@Override
public void onFailure(Throwable caught) {
Window.alert(i18n_sec.errorUpdatingEmail(caught.getMessage()));
}
});
}
@Override
public void handlePasswordChangeRequest(String oldPassword, String newPassword, String newPasswordConfirmation) {
final String username = clientFactory.getAuthenticationManager().getAuthenticationContext().getCurrentUser().getName();
String errorMessage = validator.validateUsernameAndPassword(username, newPassword, newPasswordConfirmation);
if (errorMessage != null && !errorMessage.isEmpty()) {
Window.alert(errorMessage);
return;
}
clientFactory.getUserManagementService().updateSimpleUserPassword(username, oldPassword, null, newPassword,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
if (caught instanceof UserManagementException) {
String message = ((UserManagementException) caught).getMessage();
if (UserManagementException.PASSWORD_DOES_NOT_MEET_REQUIREMENTS.equals(message)) {
Window.alert(i18n_sec.passwordDoesNotMeetRequirements());
} else if (UserManagementException.INVALID_CREDENTIALS.equals(message)) {
Window.alert(i18n_sec.invalidCredentials());
} else {
Window.alert(i18n_sec.errorChangingPassword(caught.getMessage()));
}
} else {
Window.alert(i18n_sec.errorChangingPassword(caught.getMessage()));
}
}
@Override
public void onSuccess(Void result) {
Window.alert(i18n_sec.passwordSuccessfullyChanged());
currentView.setUserManagementContext(clientFactory.getAuthenticationManager().getAuthenticationContext());
}
});
}
}
@@ -1,15 +1,15 @@
package com.sap.sailing.gwt.home.mobile.places.user.profile;
import com.google.gwt.user.client.ui.IsWidget;
import com.sap.sailing.gwt.home.mobile.partials.userdetails.UserDetails;
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.authentication.app.NeedsAuthenticationContext;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsView;
public interface UserProfileDetailsView extends IsWidget {
public interface UserProfileDetailsView extends IsWidget, NeedsAuthenticationContext {
void setUserManagementContext(AuthenticationContext userManagementContext);
UserDetailsView getUserDetailsView();
public interface Presenter extends UserDetails.Presenter, NotLoggedInPresenter {
public interface Presenter extends NotLoggedInPresenter {
}
}
@@ -5,10 +5,12 @@ 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.home.mobile.partials.userdetails.UserDetails;
import com.sap.sailing.gwt.home.mobile.partials.userheader.UserHeader;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.home.shared.usermanagement.decorator.AuthorizedContentDecoratorMobile;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.userprofile.mobile.userdetails.UserDetails;
import com.sap.sse.security.ui.userprofile.mobile.userheader.UserHeader;
import com.sap.sse.security.ui.userprofile.shared.userdetails.UserDetailsView;
public class UserProfileDetailsViewImpl extends Composite implements UserProfileDetailsView {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@@ -16,20 +18,25 @@ public class UserProfileDetailsViewImpl extends Composite implements UserProfile
interface MyUiBinder extends UiBinder<Widget, UserProfileDetailsViewImpl> {
}
@UiField UserHeader userHeaderUi;
@UiField(provided = true) AuthorizedContentDecoratorMobile decoratorUi;
@UiField(provided = true) UserDetails userDetailsUi;
@UiField(provided = true) final UserHeader userHeaderUi;
@UiField(provided = true) final AuthorizedContentDecoratorMobile decoratorUi;
@UiField(provided = true) final UserDetails userDetailsUi;
public UserProfileDetailsViewImpl(Presenter presenter) {
userHeaderUi = new UserHeader(SharedResources.INSTANCE);
decoratorUi = new AuthorizedContentDecoratorMobile(presenter);
userDetailsUi = new UserDetails(presenter);
userDetailsUi = new UserDetails(SharedResources.INSTANCE);
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void setUserManagementContext(AuthenticationContext userManagementContext) {
userHeaderUi.setUserManagementContext(userManagementContext);
decoratorUi.setUserManagementContext(userManagementContext);
userDetailsUi.setUserManagementContext(userManagementContext);
public UserDetailsView getUserDetailsView() {
return userDetailsUi;
}
@Override
public void setAuthenticationContext(AuthenticationContext authenticationContext) {
userHeaderUi.setAuthenticationContext(authenticationContext);
decoratorUi.setAuthenticationContext(authenticationContext);
}
}
@@ -1,12 +1,13 @@
<!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:mp="urn:import:com.sap.sailing.gwt.home.mobile.partials"
xmlns:ud="urn:import:com.sap.sse.security.ui.userprofile.mobile.userdetails"
xmlns:uh="urn:import:com.sap.sse.security.ui.userprofile.mobile.userheader"
xmlns:um="urn:import:com.sap.sailing.gwt.home.shared.usermanagement.decorator">
<g:FlowPanel>
<mp:userheader.UserHeader ui:field="userHeaderUi" />
<uh:UserHeader ui:field="userHeaderUi" />
<um:AuthorizedContentDecoratorMobile ui:field="decoratorUi">
<um:content>
<mp:userdetails.UserDetails ui:field="userDetailsUi" />
<ud:UserDetails ui:field="userDetailsUi" />
</um:content>
</um:AuthorizedContentDecoratorMobile>
</g:FlowPanel>
@@ -8,7 +8,7 @@ import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Window;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sse.gwt.client.LinkUtil;
public class PlaceNavigation<T extends Place> {
private final PlaceNavigator placeNavigator;
@@ -13,7 +13,6 @@ import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.client.SharedResources.MainCss;
import com.sap.sailing.gwt.common.client.i18n.TextMessages;
@@ -25,6 +24,7 @@ import com.sap.sailing.gwt.home.shared.partials.countdown.CountdownResources.Loc
import com.sap.sailing.gwt.home.shared.partials.countdowntimer.CountdownTimer;
import com.sap.sailing.gwt.home.shared.resources.SharedHomeResources;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.LinkUtil;
public class Countdown extends Composite {
@@ -12,12 +12,12 @@ import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.gwt.common.client.LinkUtil;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.home.communication.event.LabelType;
import com.sap.sailing.gwt.home.shared.utils.ButtonUtil;
import com.sap.sailing.gwt.home.shared.utils.LabelTypeUtil;
import com.sap.sailing.gwt.home.shared.utils.ButtonUtil.ButtonType;
import com.sap.sse.gwt.client.LinkUtil;
public class LowerThird extends Widget {
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
@@ -1,34 +0,0 @@
package com.sap.sailing.gwt.home.shared.usermanagement.decorator;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.ui.authentication.app.AuthenticationContext;
import com.sap.sse.security.ui.client.i18n.StringMessages;
public class AuthorizedContentDecorator extends Composite {
private final SimplePanel contentHolder = new SimplePanel();
private Widget content;
private final NotLoggedInView notLoggedInView;
public AuthorizedContentDecorator(NotLoggedInPresenter presenter, NotLoggedInView notLoggedInView) {
this.notLoggedInView = notLoggedInView;
notLoggedInView.setPresenter(presenter);
notLoggedInView.setMessage(StringMessages.INSTANCE.youAreNotSignedIn());
notLoggedInView.setSignInText(StringMessages.INSTANCE.signIn());
initWidget(contentHolder);
}
@UiChild(limit = 1)
public void addContent(Widget content) {
this.content = content;
}
public void setUserManagementContext(AuthenticationContext userManagementContext) {
contentHolder.setWidget(userManagementContext.isLoggedIn() ? content : notLoggedInView);
}
}
@@ -1,5 +1,8 @@
package com.sap.sailing.gwt.home.shared.usermanagement.decorator;
import com.sap.sse.security.ui.authentication.decorator.AuthorizedContentDecorator;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
public class AuthorizedContentDecoratorDesktop extends AuthorizedContentDecorator {
@@ -1,5 +1,8 @@
package com.sap.sailing.gwt.home.shared.usermanagement.decorator;
import com.sap.sse.security.ui.authentication.decorator.AuthorizedContentDecorator;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
public class AuthorizedContentDecoratorMobile extends AuthorizedContentDecorator {
@@ -1,5 +0,0 @@
package com.sap.sailing.gwt.home.shared.usermanagement.decorator;
public interface NotLoggedInPresenter {
void doTriggerLoginForm();
}
@@ -1,12 +0,0 @@
package com.sap.sailing.gwt.home.shared.usermanagement.decorator;
import com.google.gwt.user.client.ui.IsWidget;
public interface NotLoggedInView extends IsWidget {
void setPresenter(NotLoggedInPresenter presenter);
void setMessage(String message);
void setSignInText(String signInText);
}
@@ -9,6 +9,8 @@ import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInView;
public class NotLoggedInViewDesktopImpl extends Composite implements NotLoggedInView {
@@ -9,6 +9,8 @@ import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInPresenter;
import com.sap.sse.security.ui.authentication.decorator.NotLoggedInView;
public class NotLoggedInViewMobileImpl extends Composite implements NotLoggedInView {
@@ -19,7 +19,7 @@ public class AuthenticationViewDesktop extends AbstractFlyoutAuthenticationView
Element anchor = Document.get().getElementById("usrMngmtFlyover");
if (anchor != null) {
int left = anchor.getAbsoluteLeft() + anchor.getOffsetWidth() - offsetWidth + 15;
popupPanel.setPopupPosition(left, anchor.getAbsoluteTop() + 20);
popupPanel.setPopupPosition(left, anchor.getAbsoluteTop() + 10);
}
getPresenter().onVisibilityChanged(true);
}
@@ -41,6 +41,7 @@
<inherits name='com.sap.sailing.gwt.ui.SourceCommon'/>
<inherits name='com.sap.sailing.gwt.ui.SourceSimulator'/>
<inherits name='com.sap.sailing.gwt.common.SourceCommon'/>
<inherits name='com.sap.sailing.gwt.common.AuthenticationCommon'/>
<inherits name='com.sap.sse.gwt.CommonControlCSS_Autoinject'/>
</module>
@@ -13,30 +13,12 @@ body {
font-weight: 500;
}
.eventDescription {
vertical-align: top;
height: 40px;
}
.repeatedInfoLabel {
margin: 10px;
font-size: 20px;
font-weight: 700;
}
.eventLabel {
color: #fff;
vertical-align: top;
font-size: 20px;
font-weight: 700;
}
.venueLabel {
color: #fff;
font-size: 18px;
vertical-align: top;
}
.clockLabel {
margin-left:30px;
@@ -14,12 +14,13 @@ import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication;
import com.sap.sailing.gwt.common.client.SharedResources;
import com.sap.sailing.gwt.common.theme.component.sapheader2.SAPHeader2;
import com.sap.sailing.gwt.regattaoverview.client.RegattaRaceStatesComponent.EntryHandler;
import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint;
import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO;
import com.sap.sse.gwt.client.URLEncoder;
import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication;
public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
@@ -33,11 +34,10 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
private DockLayoutPanel containerPanel;
private RaceDetailPanel detailPanel;
private RegattaOverviewPanel regattaPanel;
private final Label eventNameLabel = new Label();
private final Label venueNameLabel = new Label();
private final Label clockLabel = new Label();
private final RegattaOverviewResources.LocalCss style = RegattaOverviewResources.INSTANCE.css();
private SAPHeaderWithAuthentication siteHeader;
@Override
public void doOnModuleLoad() {
@@ -52,18 +52,14 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
rootPanel.add(containerPanel);
containerPanel.addStyleName(RegattaOverviewResources.INSTANCE.css().container());
FlowPanel descriptionUi = new FlowPanel();
descriptionUi.setStyleName(style.eventDescription());
eventNameLabel.addStyleName(style.eventLabel());
venueNameLabel.addStyleName(style.venueLabel());
clockLabel.addStyleName(style.clockLabel());
descriptionUi.add(eventNameLabel);
descriptionUi.add(venueNameLabel);
SAPHeader2 logoAndTitlePanel = new SAPHeader2(getStringMessages().sapSailingAnalytics(), descriptionUi, false);
siteHeader = new SAPHeaderWithAuthentication(getStringMessages()
.sapSailingAnalytics());
new FixedSailingAuthentication(getUserService(), siteHeader.getAuthenticationMenuView());
logoAndTitlePanel.addWidgetToRightSide(clockLabel);
containerPanel.addNorth(logoAndTitlePanel, 75);
siteHeader.addWidgetToRightSide(clockLabel);
containerPanel.addNorth(siteHeader, 75);
String eventIdAsString = Window.Location.getParameter(PARAM_EVENT);
if (eventIdAsString == null) {
@@ -103,9 +99,8 @@ public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint {
regattaPanel.addHandler(new EventDTOLoadedEvent.Handler() {
@Override
public void onEventDTOLoaded(EventDTOLoadedEvent e) {
eventNameLabel.setText(e.getCurrentEvent().getName());
venueNameLabel.setText(e.getCurrentEvent().venue.getName());
siteHeader.setHeaderTitle(e.getCurrentEvent().getName());
siteHeader.setHeaderSubTitle(e.getCurrentEvent().venue.getName());
}
}, EventDTOLoadedEvent.TYPE);
@@ -13,8 +13,6 @@ public interface RegattaOverviewResources extends ClientBundle {
public interface LocalCss extends CssResource {
String container();
String titleLabel();
String eventLabel();
String venueLabel();
String clockLabel();
String refreshStopTime();
String functionBar();
@@ -29,22 +27,13 @@ public interface RegattaOverviewResources extends ClientBundle {
String raceDetailPanel_content();
String leaderboards();
String viewerToolbar_innerElement();
String settingsButton();
String refreshButton();
String refreshButton_live();
String refreshButton_playing();
String eventDescription();
String button();
String buttonLeaderboard();
String functionBarLeft();
String repeatedInfoLabel();
}
}
@@ -44,9 +44,11 @@
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="ENABLED" />
<extend-property name="locale" values="en,de" />
<inherits name='com.sap.sailing.gwt.common.SailingLocales' />
<!-- AdminConsole inherits the default sailing locale configuration but only activates de and en permutations.
With this, all default sailing locales are included in GWT'2 LocaleInfo.
So we can populate UI elements in the AdminConsole with all locales without the need to really support all those locales for users of the AdminConsole. -->
<set-property name="locale" value="en,de"/>
<set-property-fallback name="locale" value="en"/>
<!-- Turning CSS obfuscation off -->
<!-- <set-configuration-property name="CssResource.style" value="pretty"/> -->
@@ -64,6 +66,11 @@
<inherits name='com.sap.sailing.gwt.ui.SourceLeaderboard'/>
<inherits name='com.sap.sailing.gwt.ui.SourceRaceboard'/>
<inherits name='com.sap.sailing.gwt.common.AuthenticationCommon'/>
<set-configuration-property name="CssResource.enableGss" value="true" />
<set-configuration-property name="CssResource.legacy" value="true" />
<source path='masterdataimport'/>
<source path='test'/>
<source path='actions'/>
@@ -3,7 +3,7 @@
<module>
<inherits name='com.google.gwt.user.User'/>
<inherits name="com.sap.sse.security.ui.Authentication" />
<inherits name='com.sap.sailing.gwt.common.SourceCommon'/>
<inherits name='com.sap.sailing.gwt.common.AuthenticationCommon'/>
<source path="raceboard"/>
@@ -1,5 +1,6 @@
package com.sap.sailing.gwt.ui.adminconsole;
import com.google.gwt.user.client.ui.FocusWidget;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.sap.sailing.domain.common.ScoringSchemeType;
@@ -32,9 +33,8 @@ public abstract class AbstractLeaderboardDialog extends DataEntryDialog<Leaderbo
}
@Override
public void show() {
super.show();
nameTextBox.setFocus(true);
protected FocusWidget getInitialFocusWidget() {
return nameTextBox;
}
protected static ListBox createScoringSchemeListBox(DataEntryDialog<?> dialog, StringMessages stringMessages) {
Loaded 100 of 298 files, more files were not shown because too many files have changed in this diff. Show more