mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-23 22:19:13 +00:00
Merge branch 'master' into ubilabs--tracking_app--develop
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.1.0-alpha5'
|
||||
classpath 'com.android.tools.build:gradle:2.1.0-beta1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ SAP is at the center of today’s technology revolution, developing innovations
|
||||
* [[Amazon EC2|wiki/amazon-ec2]]
|
||||
* [[SSL / HTTPS Support|wiki/ssl-support]]
|
||||
* [[EC2 Backup Strategy|wiki/amazon-ec2-backup-strategy]]
|
||||
* [[EC2 mail relaying|wiki/mail-relaying]]
|
||||
* [[TracTrac|wiki/tractrac-lifecycle]]
|
||||
* [[Analytics on a stick|wiki/analytics-on-a-stick]]
|
||||
* [[Operating Igtimi WindBots/windbot-operations]]
|
||||
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
trackingInvitationFor=Einladung zum Tracken für
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Installiere die SAP Sailing Boat Tracker App. Dann scanne den QRCode oder klicke den Link mit deinem Smartphone an, um dich zu registrieren als
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Installiere die {0} App. Dann scanne den QRCode oder klicke den Link mit deinem Smartphone an, um dich zu registrieren als
|
||||
welcomeTo=Willkommen zu
|
||||
iOSUsers=iOS App starten
|
||||
androidUsers=Android App starten
|
||||
@@ -7,4 +7,6 @@ alternativelyVisitThisLink=Wenn die App bereits installiert ist, und du diese Ma
|
||||
buoyTender=Bojenleger
|
||||
appStoreInstallText=Falls die App noch nicht installiert ist, kannst du sie hier finden:Ÿ
|
||||
appIos=iOS App installieren
|
||||
appAndroid=Android App installieren
|
||||
appAndroid=Android App installieren
|
||||
buoyPingerAppName=SAP Sailing Buoy Pinger
|
||||
sailInSightAppName=SAP Sail InSight
|
||||
+4
-2
@@ -1,5 +1,5 @@
|
||||
trackingInvitationFor=Tracking Invitation for
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Make sure you have the SAP Sailing Boat Tracker App installed. Then scan the following QRCode or click the link using your smartphone to register as
|
||||
scanQRCodeOrVisitUrlToRegisterAs=Make sure you have the {0} App installed. Then scan the following QRCode or click the link using your smartphone to register as
|
||||
welcomeTo=Welcome to
|
||||
iOSUsers=Start iOS App
|
||||
androidUsers=Start Android App
|
||||
@@ -7,4 +7,6 @@ alternativelyVisitThisLink=If you are reading this mail on the device with the A
|
||||
buoyTender=buoy tender
|
||||
appStoreInstallText=If don't have the App yet, please install:
|
||||
appIos=Install iOS App
|
||||
appAndroid=Install Android App
|
||||
appAndroid=Install Android App
|
||||
buoyPingerAppName=SAP Sailing Buoy Pinger
|
||||
sailInSightAppName=SAP Sail InSight
|
||||
+8
-6
@@ -298,8 +298,9 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
logoUrl = imagesWithTag.get(0).getURL().toString();
|
||||
}
|
||||
try {
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, competitorName, url, iOSAppUrl,
|
||||
androidAppUrl, logoUrl);
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName, competitorName, url, B.get(locale, "sailInSightAppName"),
|
||||
iOSAppUrl, androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
@@ -311,7 +312,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
}
|
||||
|
||||
private void sendInvitationEmail(Locale locale, final String toAddress, String leaderboardName, String invitee,
|
||||
String url, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
String url, String appName, String iOSAppUrl, String androidAppUrl, String logoUrl) throws MailException {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
String subject = String.format("%s %s", B.get(locale, "trackingInvitationFor"), invitee);
|
||||
|
||||
@@ -338,7 +339,7 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
htmlText.append("<p><img src=\"").append(logoUrl).append("\" /></p> ");
|
||||
}
|
||||
htmlText.append("<h1>").append(B.get(locale, "welcomeTo")).append(" ").append(leaderboardName).append("</h1> ");
|
||||
htmlText.append("<p>").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs")).append(" <b>").append(invitee)
|
||||
htmlText.append("<p>").append(B.get(locale, "scanQRCodeOrVisitUrlToRegisterAs", appName)).append(" <b>").append(invitee)
|
||||
.append("</b></p> ");
|
||||
htmlText.append("<p class=\"qr\"><img src=\"cid:image\" title=\"").append(url).append("\" /></p> ");
|
||||
htmlText.append("<p class=\"spacer\">").append(B.get(locale, "alternativelyVisitThisLink")).append("</p> ");
|
||||
@@ -407,9 +408,10 @@ public class RaceLogTrackingAdapterImpl implements RaceLogTrackingAdapter {
|
||||
eventId, NonGwtUrlHelper.INSTANCE);
|
||||
for (String toAddress : emailArray) {
|
||||
try {
|
||||
final ResourceBundleStringMessages B = RaceLogTrackingI18n.STRING_MESSAGES;
|
||||
sendInvitationEmail(locale, toAddress, leaderboardName,
|
||||
RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, iOSAppUrl, androidAppUrl,
|
||||
logoUrl);
|
||||
RaceLogTrackingI18n.STRING_MESSAGES.get(locale, "buoyTender"), url, B.get(locale, "buoyPingerAppName"), iOSAppUrl,
|
||||
androidAppUrl, logoUrl);
|
||||
} catch (MailException e) {
|
||||
occuredExceptions.append(e.getMessage() + "\r\n");
|
||||
}
|
||||
|
||||
+2
-2
@@ -54,10 +54,10 @@ public class WindStatusHtmlServlet extends WindStatusServlet implements IgtimiWi
|
||||
TimePoint latestTimePoint = copyOfLastIgtimiMessages.peek().getWind().getTimePoint();
|
||||
long lastFixDiffInMs = System.currentTimeMillis() - latestTimePoint.asMillis();
|
||||
out.println(" Last fix:");
|
||||
if(lastFixDiffInMs / 1000 < 60) {
|
||||
if (lastFixDiffInMs / 1000 < 60) {
|
||||
out.println(lastFixDiffInMs / 1000 +"s ago");
|
||||
} else {
|
||||
out.println("<span style=\"color:red;\">" + lastFixDiffInMs / 1000 +"min ago</span>");
|
||||
out.println("<span style=\"color:red;\">" + lastFixDiffInMs / 1000 / 60 +"min ago</span>");
|
||||
}
|
||||
}
|
||||
out.println("<br/>");
|
||||
|
||||
+5
-2
@@ -3,18 +3,20 @@ package com.sap.sse.security.replication.test;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import com.sap.sse.common.mail.MailException;
|
||||
import com.sap.sse.mongodb.MongoDBService;
|
||||
import com.sap.sse.replication.testsupport.AbstractServerReplicationTestSetUp;
|
||||
import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.impl.SecurityServiceImpl;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
|
||||
|
||||
public abstract class AbstractSecurityReplicationTest extends AbstractServerWithSingleServiceReplicationTest<SecurityService, SecurityServiceImpl> {
|
||||
public AbstractSecurityReplicationTest() {
|
||||
super(new SecurityServerReplicationTestSetUp());
|
||||
}
|
||||
|
||||
|
||||
public static class SecurityServerReplicationTestSetUp extends AbstractServerReplicationTestSetUp<SecurityService, SecurityServiceImpl> {
|
||||
private MongoDBService mongoDBService;
|
||||
|
||||
@@ -27,7 +29,8 @@ public abstract class AbstractSecurityReplicationTest extends AbstractServerWith
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException {
|
||||
protected SecurityServiceImpl createNewMaster() throws MalformedURLException, IOException, InterruptedException,
|
||||
UserManagementException, MailException {
|
||||
SecurityServiceImpl result = new SecurityServiceImpl(new UserStoreImpl());
|
||||
result.clearReplicaState();
|
||||
return result;
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.sap.sse.security.replication.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sse.common.mail.MailException;
|
||||
import com.sap.sse.replication.testsupport.AbstractServerWithSingleServiceReplicationTest;
|
||||
import com.sap.sse.security.SecurityService;
|
||||
import com.sap.sse.security.impl.SecurityServiceImpl;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
|
||||
|
||||
public class SecurityServiceInitialLoadTest extends AbstractServerWithSingleServiceReplicationTest<SecurityService, SecurityServiceImpl> {
|
||||
private final static String username = "abc";
|
||||
private final static String email = "e@mail.com";
|
||||
private final static String password = "password";
|
||||
private final static String fullName = "Full Name";
|
||||
private final static String company = "Company";
|
||||
private static String accessToken = "Company";
|
||||
|
||||
public SecurityServiceInitialLoadTest() {
|
||||
super(new AbstractSecurityReplicationTest.SecurityServerReplicationTestSetUp() {
|
||||
@Override
|
||||
protected SecurityServiceImpl createNewMaster()
|
||||
throws MalformedURLException, IOException, InterruptedException, UserManagementException, MailException {
|
||||
final SecurityServiceImpl newMaster = new SecurityServiceImpl(new UserStoreImpl(null, null)); // no persistence
|
||||
newMaster.clearReplicaState();
|
||||
newMaster.createSimpleUser(username, email, password, fullName, company, /* validationBaseURL */ null);
|
||||
accessToken = newMaster.createAccessToken(username);
|
||||
return newMaster;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleMasterTest() {
|
||||
assertEquals(username, master.getUserByName(username).getName());
|
||||
assertEquals(username, master.getUserByAccessToken(accessToken).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleReplicaTest() {
|
||||
assertEquals(username, replica.getUserByName(username).getName());
|
||||
assertEquals(username, replica.getUserByAccessToken(accessToken).getName());
|
||||
}
|
||||
}
|
||||
+6
@@ -40,6 +40,12 @@ public class SimpleSecurityReplicationTest extends AbstractSecurityReplicationTe
|
||||
assertEquals(emailValidationSecret, replicatedErnie.getValidationSecret());
|
||||
assertEquals(fullName, replicatedErnie.getFullName());
|
||||
assertEquals(company, replicatedErnie.getCompany());
|
||||
|
||||
// check that incremental replication of access token handling works
|
||||
final String accessToken = master.createAccessToken(username);
|
||||
replicaReplicator.waitUntilQueueIsEmpty();
|
||||
Thread.sleep(3000);
|
||||
assertEquals(username, replica.getUserByAccessToken(accessToken).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.sap.sse.security.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sse.security.UserStore;
|
||||
import com.sap.sse.security.shared.UserManagementException;
|
||||
import com.sap.sse.security.userstore.mongodb.UserStoreImpl;
|
||||
|
||||
public class UserStoreTest {
|
||||
private final UserStore userStore = new UserStoreImpl(null, null);
|
||||
private final String username = "abc";
|
||||
private final String email = "e@mail.com";
|
||||
private final String accessToken = "ak";
|
||||
private final String prefKey = "pk";
|
||||
private final String prefValue = "pv";
|
||||
|
||||
@Before
|
||||
public void setUp() throws UserManagementException {
|
||||
userStore.createUser(username, email);
|
||||
userStore.setAccessToken(username, accessToken);
|
||||
userStore.setPreference(username, prefKey, prefValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClear() throws UserManagementException {
|
||||
assertEquals(prefValue, userStore.getPreference(username, prefKey));
|
||||
assertEquals(username, userStore.getUserByAccessToken(accessToken).getName());
|
||||
userStore.clear();
|
||||
assertNull(userStore.getPreference(username, prefKey));
|
||||
assertNull(userStore.getUserByAccessToken(accessToken));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws UserManagementException {
|
||||
UserStore newUserStore = new UserStoreImpl(null, null);
|
||||
newUserStore.replaceContentsFrom(userStore);
|
||||
assertEquals(prefValue, newUserStore.getPreference(username, prefKey));
|
||||
assertEquals(username, newUserStore.getUserByAccessToken(accessToken).getName());
|
||||
}
|
||||
}
|
||||
+39
-30
@@ -54,6 +54,10 @@ public class UserStoreImpl implements UserStore {
|
||||
private final transient MongoObjectFactory mongoObjectFactory;
|
||||
|
||||
public UserStoreImpl() {
|
||||
this(PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory(), PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory());
|
||||
}
|
||||
|
||||
public UserStoreImpl(final DomainObjectFactory domainObjectFactory, final MongoObjectFactory mongoObjectFactory) {
|
||||
users = new ConcurrentHashMap<>();
|
||||
usersByEmail = new ConcurrentHashMap<>();
|
||||
emailForUsername = new ConcurrentHashMap<>();
|
||||
@@ -61,36 +65,37 @@ public class UserStoreImpl implements UserStore {
|
||||
settingTypes = new ConcurrentHashMap<>();
|
||||
usersByAccessToken = new ConcurrentHashMap<>();
|
||||
preferences = new ConcurrentHashMap<>();
|
||||
final DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDefaultDomainObjectFactory();
|
||||
mongoObjectFactory = PersistenceFactory.INSTANCE.getDefaultMongoObjectFactory();
|
||||
for (Entry<String, Class<?>> e : domainObjectFactory.loadSettingTypes().entrySet()) {
|
||||
settingTypes.put(e.getKey(), e.getValue());
|
||||
}
|
||||
for (Entry<String, Object> e : domainObjectFactory.loadSettings().entrySet()) {
|
||||
settings.put(e.getKey(), e.getValue());
|
||||
}
|
||||
for (Entry<String, Map<String, String>> e : domainObjectFactory.loadPreferences().entrySet()) {
|
||||
preferences.put(e.getKey(), e.getValue());
|
||||
}
|
||||
boolean changed = false;
|
||||
changed = changed || initSocialSettingsIfEmpty();
|
||||
if (changed) {
|
||||
mongoObjectFactory.storeSettingTypes(settingTypes);
|
||||
mongoObjectFactory.storeSettings(settings);
|
||||
}
|
||||
for (User u : domainObjectFactory.loadAllUsers()) {
|
||||
users.put(u.getName(), u);
|
||||
addToUsersByEmail(u);
|
||||
}
|
||||
for (Entry<String, Map<String, String>> e : preferences.entrySet()) {
|
||||
if (e.getValue() != null) {
|
||||
final String accessToken = e.getValue().get(ACCESS_TOKEN_KEY);
|
||||
if (accessToken != null) {
|
||||
final User user = users.get(e.getKey());
|
||||
if (user != null) {
|
||||
usersByAccessToken.put(accessToken, user);
|
||||
} else {
|
||||
logger.warning("Couldn't find user \""+e.getKey()+"\" for which an access token was found in the preferences");
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
if (domainObjectFactory != null) {
|
||||
for (Entry<String, Class<?>> e : domainObjectFactory.loadSettingTypes().entrySet()) {
|
||||
settingTypes.put(e.getKey(), e.getValue());
|
||||
}
|
||||
for (Entry<String, Object> e : domainObjectFactory.loadSettings().entrySet()) {
|
||||
settings.put(e.getKey(), e.getValue());
|
||||
}
|
||||
for (Entry<String, Map<String, String>> e : domainObjectFactory.loadPreferences().entrySet()) {
|
||||
preferences.put(e.getKey(), e.getValue());
|
||||
}
|
||||
boolean changed = false;
|
||||
changed = changed || initSocialSettingsIfEmpty();
|
||||
if (changed) {
|
||||
mongoObjectFactory.storeSettingTypes(settingTypes);
|
||||
mongoObjectFactory.storeSettings(settings);
|
||||
}
|
||||
for (User u : domainObjectFactory.loadAllUsers()) {
|
||||
users.put(u.getName(), u);
|
||||
addToUsersByEmail(u);
|
||||
}
|
||||
for (Entry<String, Map<String, String>> e : preferences.entrySet()) {
|
||||
if (e.getValue() != null) {
|
||||
final String accessToken = e.getValue().get(ACCESS_TOKEN_KEY);
|
||||
if (accessToken != null) {
|
||||
final User user = users.get(e.getKey());
|
||||
if (user != null) {
|
||||
usersByAccessToken.put(accessToken, user);
|
||||
} else {
|
||||
logger.warning("Couldn't find user \""+e.getKey()+"\" for which an access token was found in the preferences");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,6 +110,7 @@ public class UserStoreImpl implements UserStore {
|
||||
settingTypes.clear();
|
||||
users.clear();
|
||||
usersByEmail.clear();
|
||||
usersByAccessToken.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,6 +121,9 @@ public class UserStoreImpl implements UserStore {
|
||||
addToUsersByEmail(user);
|
||||
for (Entry<String, String> userPref : newUserStore.getAllPreferences(user.getName()).entrySet()) {
|
||||
setPreference(user.getName(), userPref.getKey(), userPref.getValue());
|
||||
if (userPref.getKey().equals(ACCESS_TOKEN_KEY)) {
|
||||
usersByAccessToken.put(userPref.getValue(), user);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Entry<String, Object> setting : newUserStore.getAllSettings().entrySet()) {
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
com.sap.sailing.android.tracking.app.test-test/bin/
|
||||
/target
|
||||
**/build.info
|
||||
build.info
|
||||
@@ -49,4 +49,8 @@
|
||||
<string name="warning">Warnung</string>
|
||||
<string name="enable_gps">GPS ist nicht aktiviert. Diese App erfordert GPS Positionen. Möchten Sie GPS in den Einstellungen aktivieren?</string>
|
||||
|
||||
<!-- Message Sending -->
|
||||
<string name="sending_waiting">%1$d Events konnten noch nicht gesendet werden.\nLetzter erfolgreicher Versand fand statt %2$s</string>
|
||||
<string name="sending_no_waiting">Derzeit keine unversendeten Events.</string>
|
||||
|
||||
</resources>
|
||||
@@ -72,7 +72,7 @@
|
||||
<string name="enable_gps">GPS is turned off. This app requires GPS positions. Do you want to turn on GPS in the location settings?</string>
|
||||
|
||||
<!-- Message Sending -->
|
||||
<string name="sending_waiting" translatable="false">Currently %1$d events waiting to be sent.\nLast successful sent was at %2$s</string>
|
||||
<string name="sending_no_waiting" translatable="false">Currently no event waiting to be sent.</string>
|
||||
<string name="sending_waiting">Currently %1$d events waiting to be sent.\nLast successful sent was at %2$s</string>
|
||||
<string name="sending_no_waiting">Currently no event waiting to be sent.</string>
|
||||
|
||||
</resources>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="about_partnership_text" translatable="false">The SAP Sail InSight app supports live tracking of race boats by leveraging mobile phone technology, allowing the ability for friends and fans to follow racing whether onsite or online through live leaderboards and 2D visualization. Following racing sailors can replay their races allowing the opportunity to review performance and optimize strategies all available at: sapsailing.com\n\nSAP supports US Sailing through the implementation of a range of innovative technology solutions, delivering analytics to help teams and sailors improve performance whilst also providing applications to help sailing operations run more efficiently.\n\nAs the national governing body for sailing, US Sailing provides leadership, integrity and growth for the sport including training and education programs for instructors and race officials alongside administration and oversight of competitive sailing across the country.</string>
|
||||
<string name="about_partnership_clickable" translatable="false">sapsailing.com</string>
|
||||
<string name="about_partnership_text" translatable="false">The SAP Sail InSight app supports live tracking of race boats by leveraging mobile phone technology, allowing the ability for friends and fans to follow racing whether onsite or online through live leaderboards and 2D visualization. Following racing sailors can replay their races allowing the opportunity to review performance and optimize strategies all available at: https://www.sapsailing.com\n\nSAP supports US Sailing through the implementation of a range of innovative technology solutions, delivering analytics to help teams and sailors improve performance whilst also providing applications to help sailing operations run more efficiently.\n\nAs the national governing body for sailing, US Sailing provides leadership, integrity and growth for the sport including training and education programs for instructors and race officials alongside administration and oversight of competitive sailing across the country.</string>
|
||||
<string name="about_partnership_clickable" translatable="false">https://www.sapsailing.com</string>
|
||||
|
||||
</resources>
|
||||
+1
-1
@@ -74,7 +74,7 @@ public class AboutFragment extends com.sap.sailing.android.ui.fragments.BaseFrag
|
||||
ClickableSpan clickableSpan = new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + url));
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
startActivity(browserIntent);
|
||||
}
|
||||
};
|
||||
|
||||
+7
-3
@@ -72,6 +72,8 @@ public class LoginActivity extends BaseActivity
|
||||
private final static String CourseAreaListFragmentTag = "CourseAreaListFragmentTag";
|
||||
private final static String AreaPositionListFragmentTag = "AreaPositionListFragmentTag";
|
||||
|
||||
private boolean wakeUp;
|
||||
|
||||
private final static String TAG = LoginActivity.class.getName();
|
||||
|
||||
private final PositionListFragment positionFragment;
|
||||
@@ -385,6 +387,7 @@ public class LoginActivity extends BaseActivity
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
wakeUp = true;
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@@ -537,11 +540,12 @@ public class LoginActivity extends BaseActivity
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (AppConstants.INTENT_ACTION_RESET.equals(action)) {
|
||||
if (AppConstants.INTENT_ACTION_RESET.equals(action) && !wakeUp) {
|
||||
resetData();
|
||||
} else if (AppConstants.INTENT_ACTION_VALID_DATA.equals(action)) {
|
||||
} else if (AppConstants.INTENT_ACTION_VALID_DATA.equals(action) && !wakeUp) {
|
||||
resetData();
|
||||
}
|
||||
wakeUp = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,7 +571,7 @@ public class LoginActivity extends BaseActivity
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
|
||||
// no op
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+102
-90
@@ -6,7 +6,38 @@ import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.internal.widget.TintImageView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.sap.sailing.android.shared.logging.ExLog;
|
||||
import com.sap.sailing.android.shared.util.AppUtils;
|
||||
import com.sap.sailing.android.shared.util.BitmapHelper;
|
||||
@@ -47,36 +78,6 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.internal.widget.TintImageView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class RacingActivity extends SessionActivity implements RaceListCallbacks {
|
||||
private static final String TAG = RacingActivity.class.getName();
|
||||
private static final String WIND = "wind";
|
||||
@@ -517,8 +518,8 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
|
||||
overflow.setMinimumWidth(getResources().getDimensionPixelSize(R.dimen.bigger_over_flow_width));
|
||||
overflow.setMinimumHeight(getResources().getDimensionPixelSize(R.dimen.bigger_over_flow_height));
|
||||
Bitmap bitmap = BitmapHelper
|
||||
.decodeSampledBitmapFromResource(getResources(), R.drawable.ic_more_vert_white_48dp, overflow.getMinimumWidth(), overflow
|
||||
.getMinimumHeight());
|
||||
.decodeSampledBitmapFromResource(getResources(), R.drawable.ic_more_vert_white_48dp,
|
||||
ViewCompat.getMinimumWidth(overflow), ViewCompat.getMinimumHeight(overflow));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
overflow.setScaleType(ImageView.ScaleType.FIT_END);
|
||||
}
|
||||
@@ -540,71 +541,82 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
|
||||
}
|
||||
}
|
||||
|
||||
public void processIntent(Intent intent) {
|
||||
Fragment content;
|
||||
Fragment extra = null;
|
||||
Bundle args = new Bundle();
|
||||
View view;
|
||||
|
||||
String action = intent.getAction();
|
||||
public void processIntent(final Intent intent) {
|
||||
final Bundle args = new Bundle();
|
||||
if (mSelectedRace != null) {
|
||||
args.putSerializable(AppConstants.RACE_ID_KEY, mSelectedRace.getId());
|
||||
}
|
||||
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
// artificial delay (to prevent "java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState")
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Fragment content;
|
||||
Fragment extra = null;
|
||||
View view;
|
||||
String action = intent.getAction();
|
||||
|
||||
if (AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT.equals(action)) {
|
||||
view = findViewById(R.id.race_edit);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.race_edit);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
if (findViewById(R.id.race_content) != null) {
|
||||
if (mSelectedRace.getStatus() != RaceLogRaceStatus.FINISHING) {
|
||||
content = RaceFlagViewerFragment.newInstance();
|
||||
} else {
|
||||
if (preferences.getRacingProcedureIsResultEntryEnabled(mSelectedRace.getState().
|
||||
getRacingProcedure().getType())) {
|
||||
content = TrackingListFragment.newInstance(args, 1);
|
||||
} else {
|
||||
content = RaceFinishingFragment.newInstance();
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
|
||||
if (AppConstants.INTENT_ACTION_SHOW_MAIN_CONTENT.equals(action)) {
|
||||
view = findViewById(R.id.race_edit);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.race_edit);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
if (findViewById(R.id.race_content) != null) {
|
||||
if (mSelectedRace.getStatus() != RaceLogRaceStatus.FINISHING) {
|
||||
content = RaceFlagViewerFragment.newInstance();
|
||||
} else {
|
||||
if (preferences.getRacingProcedureIsResultEntryEnabled(mSelectedRace.getState().
|
||||
getRacingProcedure().getType())) {
|
||||
content = TrackingListFragment.newInstance(args, 1);
|
||||
} else {
|
||||
content = RaceFinishingFragment.newInstance();
|
||||
}
|
||||
}
|
||||
content.setArguments(args);
|
||||
transaction.replace(R.id.race_content, content);
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.INTENT_ACTION_SHOW_SUMMARY_CONTENT.equals(action)) {
|
||||
view = findViewById(R.id.finished_edit);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.finished_edit);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
if (extra == null && findViewById(R.id.finished_content) != null) {
|
||||
content = RaceSummaryFragment.newInstance(args);
|
||||
transaction.replace(R.id.finished_content, content);
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.INTENT_ACTION_REMOVE_PROTEST.equals(action)) {
|
||||
view = findViewById(R.id.protest_time_fragment);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.protest_time_fragment);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
}
|
||||
content.setArguments(args);
|
||||
transaction.replace(R.id.race_content, content);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.INTENT_ACTION_SHOW_SUMMARY_CONTENT.equals(action)) {
|
||||
view = findViewById(R.id.finished_edit);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.finished_edit);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
if (extra == null && findViewById(R.id.finished_content) != null) {
|
||||
content = RaceSummaryFragment.newInstance(args);
|
||||
transaction.replace(R.id.finished_content, content);
|
||||
}
|
||||
}
|
||||
|
||||
if (AppConstants.INTENT_ACTION_REMOVE_PROTEST.equals(action)) {
|
||||
view = findViewById(R.id.protest_time_fragment);
|
||||
if (view != null) {
|
||||
ViewHelper.setSiblingsVisibility(view, View.VISIBLE);
|
||||
extra = getFragmentManager().findFragmentById(R.id.protest_time_fragment);
|
||||
if (extra != null) {
|
||||
transaction.remove(extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transaction.commit();
|
||||
}).start();
|
||||
}
|
||||
|
||||
private class RaceLoadClient implements LoadClient<Collection<ManagedRace>> {
|
||||
|
||||
+5
@@ -102,6 +102,7 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(AppConstants.INTENT_ACTION_TOGGLE);
|
||||
filter.addAction(AppConstants.INTENT_ACTION_RESET);
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mListener, filter);
|
||||
}
|
||||
|
||||
@@ -252,6 +253,10 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli
|
||||
}
|
||||
break;
|
||||
|
||||
case AppConstants.INTENT_ACTION_RESET:
|
||||
mSignUp.setEnabled(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ public abstract class BaseRaceInfoRaceFragment<ProcedureType extends RacingProce
|
||||
args.putAll(fragment.getArguments());
|
||||
}
|
||||
fragment.setArguments(args);
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
FragmentTransaction transaction = getActivity().getFragmentManager().beginTransaction();
|
||||
transaction.replace(id, fragment);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ I then did a `yum update` and added the following packages:
|
||||
- tigervnc-server
|
||||
- WindowMaker
|
||||
- xterm
|
||||
- sendmail-cf
|
||||
|
||||
Then I created a mount point /home/sailing and copied the following lines from the /etc/fstab file from an existing SL instance:
|
||||
|
||||
@@ -121,4 +122,7 @@ Adjust the /etc/sysconfig/vncservers settings to something like:
|
||||
```
|
||||
VNCSERVERS="2:sailing"
|
||||
VNCSERVERARGS[2]="-geometry 1600x900"
|
||||
```
|
||||
```
|
||||
|
||||
## Mail Relaying
|
||||
For setting up mail relaying towards central postfix server, have a look [here](https://wiki.sapsailing.com/wiki/mail-relaying)
|
||||
@@ -0,0 +1,19 @@
|
||||
# Setup central mail server (instance "Webserver")
|
||||
- you need to add the local subnet (which the instance which should relay) is in
|
||||
- edit `/etc/postfix/main.cf` and edit `mynetworks = x.y.z.w/v` to match the subnet. Currently all subnets from VPC Ireland and US East are in here, this means adding an instance to existing subnets / zones will not require a change here
|
||||
- restart postfix with `service postfix restart`
|
||||
- check the log if everything is working with `tailf /var/log/maillog`
|
||||
# Setup standalone instance for relaying
|
||||
- on each Sailing App instance a local sendmail client will be running, which is in default using its own binaries to send out mails directly
|
||||
- the problem here is, that external mail servers will check actually the domain "sapsailing.com" and its MX and A-Record. IF this does not match (it does not, because A/MX goes to central webserver) most correctly mailservers will deferr or even reject the incoming mail as it looks like hard spam
|
||||
- to prevent this you need to relay mails send from any instance to the central postfix (with the correct A and MX records), so that other mail servers dont reject mails
|
||||
- install package `sendmail-cf` via `yum install`
|
||||
- edit the config `/etc/mail/sendmail.mc` and insert the line
|
||||
```
|
||||
define(`SMART_HOST', `ip-172-31-18-15.eu-west-1.compute.internal')dnl
|
||||
``` and save
|
||||
- regenerate the sendmail config with `. /etc/mail/make`
|
||||
- restart sendmail with `service sendmail restart`
|
||||
- test the setup by tailing both `/var/log/maillog`'s and send a mail from the relayed instance via `echo "test" | sendmail yourmail@domain.tld`
|
||||
|
||||
=> all this shall be included to a next HVM version
|
||||
Reference in New Issue
Block a user