mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-09-21 05:05:31 +00:00
bug5510: Implemented price selection on cards.
Added FREE subscription to cards (TODO: action needs to be implemented) - some styling improvements - added missing .project files of new xmlreport projects to git
This commit is contained in:
+43
-41
@@ -1,41 +1,43 @@
|
||||
/target
|
||||
www-test
|
||||
war
|
||||
build.log
|
||||
reporting.log
|
||||
.metadata
|
||||
*.class
|
||||
*.swp
|
||||
*~
|
||||
manifest.txt
|
||||
java/com.sap.sailing.gwt.ui/gwt-unitCache/*
|
||||
java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/*
|
||||
java/com.sap.sse.security.ui/WEB-INF/deploy/*
|
||||
sailing_debug0*
|
||||
dist
|
||||
build
|
||||
.DS_Store
|
||||
java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml
|
||||
/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT.launch
|
||||
|
||||
## Android Studio and Intellij and Android in general
|
||||
gen/
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
out/
|
||||
.gradle
|
||||
local.properties
|
||||
git.xml
|
||||
mobile/github-advrecyclerview_lib/bin
|
||||
captures
|
||||
/.recommenders/
|
||||
/java/.recommenders/
|
||||
java/com.sap.sailing.selenium.test/com.sap.sailing.selenium.test (No Proxy) individual.launch
|
||||
|
||||
## Kubernetes
|
||||
kubernetes/aws-alb-ingress-controller.yaml
|
||||
java/com.sap.sailing.gwt.ui/360_VR_Wimbachklamm.mp4
|
||||
/target
|
||||
www-test
|
||||
war
|
||||
build.log
|
||||
reporting.log
|
||||
.metadata
|
||||
*.class
|
||||
*.swp
|
||||
*~
|
||||
manifest.txt
|
||||
java/com.sap.sailing.gwt.ui/gwt-unitCache/*
|
||||
java/com.sap.sailing.gwt.ui/war/WEB-INF/deploy/*
|
||||
java/com.sap.sse.security.ui/WEB-INF/deploy/*
|
||||
sailing_debug0*
|
||||
dist
|
||||
build
|
||||
.DS_Store
|
||||
java/com.sap.sailing.simulator/bin/com/sap/sailing/simulator/Simulator.gwt.xml
|
||||
/mobile/com.sap.sailing.racecommittee.app/res/values/keys.xml
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling (Run-Mode only).launch
|
||||
java/com.sap.sailing.gwt.ui/SailingGWT.launch
|
||||
|
||||
## Android Studio and Intellij and Android in general
|
||||
gen/
|
||||
.idea/
|
||||
*.ipr
|
||||
*.iws
|
||||
*.iml
|
||||
out/
|
||||
.gradle
|
||||
local.properties
|
||||
git.xml
|
||||
mobile/github-advrecyclerview_lib/bin
|
||||
captures
|
||||
/.recommenders/
|
||||
/java/.recommenders/
|
||||
java/com.sap.sailing.selenium.test/com.sap.sailing.selenium.test (No Proxy) individual.launch
|
||||
|
||||
## Kubernetes
|
||||
kubernetes/aws-alb-ingress-controller.yaml
|
||||
java/com.sap.sailing.gwt.ui/360_VR_Wimbachklamm.mp4
|
||||
SailingServer (No Proxy, Axel) Chargebee.launch
|
||||
SailingServer (No Proxy) Chargebee.launch
|
||||
|
||||
+20
-1
@@ -11,6 +11,7 @@
|
||||
}
|
||||
.feature {
|
||||
padding-left: 25px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.features {
|
||||
margin: 30px;
|
||||
@@ -20,6 +21,8 @@
|
||||
}
|
||||
.owned {
|
||||
}
|
||||
.free {
|
||||
}
|
||||
.subscription {
|
||||
order: 20;
|
||||
text-align: center;
|
||||
@@ -95,7 +98,23 @@
|
||||
margin: 20px;
|
||||
}
|
||||
.price {
|
||||
margin: 20px;
|
||||
width: 100%;
|
||||
border: solid;
|
||||
border-width: 1px;
|
||||
border-radius: .333333333333333em;
|
||||
border-color: #ddd;
|
||||
padding: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.price.selected {
|
||||
border-color: #8ab54e;
|
||||
border-width: 2px;
|
||||
}
|
||||
.prices {
|
||||
padding: 1em;
|
||||
width: 100%;
|
||||
}
|
||||
.subscribe {
|
||||
margin-left: auto;
|
||||
|
||||
+68
-13
@@ -1,16 +1,22 @@
|
||||
package com.sap.sailing.gwt.home.desktop.partials.subscription;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.dom.client.HeadingElement;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.i18n.client.NumberFormat;
|
||||
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.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.FocusPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.sap.sailing.gwt.common.client.SharedResources;
|
||||
@@ -18,12 +24,13 @@ import com.sap.sailing.gwt.home.shared.places.subscription.SailingSubscriptionSt
|
||||
import com.sap.sailing.gwt.ui.client.StringMessages;
|
||||
import com.sap.sse.security.shared.StringMessagesKey;
|
||||
import com.sap.sse.security.shared.subscription.SubscriptionPrice;
|
||||
import com.sap.sse.security.ui.client.i18n.subscription.SubscriptionStringConstants;
|
||||
import com.sap.sse.security.ui.shared.subscription.SubscriptionPlanDTO;
|
||||
|
||||
public class SubscriptionCard extends Composite {
|
||||
|
||||
public static enum Type {
|
||||
OWNER, HIGHLIGHT, INDIVIDUAL, DEFAULT
|
||||
FREE, OWNER, HIGHLIGHT, INDIVIDUAL, DEFAULT
|
||||
}
|
||||
|
||||
private static SubscriptionUiBinder uiBinder = GWT.create(SubscriptionUiBinder.class);
|
||||
@@ -32,6 +39,9 @@ public class SubscriptionCard extends Composite {
|
||||
private static final String INDIVIDUAL_STYLE = SubscriptionCardResources.INSTANCE.css().individual();
|
||||
private static final String OWNED_STYLE = SubscriptionCardResources.INSTANCE.css().owned();
|
||||
private static final String SUBSCRIPTION_STYLE = SubscriptionCardResources.INSTANCE.css().subscription();
|
||||
private static final String FREE_STYLE = SubscriptionCardResources.INSTANCE.css().free();
|
||||
private static final String PRICE_STYLE = SubscriptionCardResources.INSTANCE.css().price();
|
||||
private static final String SELECTED_STYLE = SubscriptionCardResources.INSTANCE.css().selected();
|
||||
|
||||
interface SubscriptionUiBinder extends UiBinder<Widget, SubscriptionCard> {
|
||||
}
|
||||
@@ -43,7 +53,7 @@ public class SubscriptionCard extends Composite {
|
||||
@UiField
|
||||
HeadingElement description;
|
||||
@UiField
|
||||
HeadingElement price;
|
||||
FlowPanel prices;
|
||||
@UiField
|
||||
FlowPanel features;
|
||||
@UiField
|
||||
@@ -52,21 +62,64 @@ public class SubscriptionCard extends Composite {
|
||||
@UiField
|
||||
StringMessages i18n;
|
||||
|
||||
private final Runnable subscriptionCallback;
|
||||
private final Consumer<SubscriptionPrice> subscriptionCallback;
|
||||
private SubscriptionPrice currentPrice;
|
||||
|
||||
public SubscriptionCard(SubscriptionPlanDTO subscriptionPlanDTO, Type type, Runnable subscriptionCallback) {
|
||||
public <T> SubscriptionCard(SubscriptionPlanDTO subscriptionPlanDTO, Type type, Consumer<SubscriptionPrice> subscriptionCallback) {
|
||||
this.subscriptionCallback = subscriptionCallback;
|
||||
SubscriptionCardResources.INSTANCE.css().ensureInjected();
|
||||
SharedResources.INSTANCE.mediaCss().ensureInjected();
|
||||
initWidget(uiBinder.createAndBindUi(this));
|
||||
addStyleName(SUBSCRIPTION_STYLE);
|
||||
final String priceText;
|
||||
final HashSet<SubscriptionPrice> prices = subscriptionPlanDTO.getPrices();
|
||||
if (prices != null && !prices.isEmpty()) {
|
||||
priceText = subscriptionPlanDTO.getPrices().toString();
|
||||
//TODO: Implement new Price handling
|
||||
final List<SubscriptionPrice> priceList = new ArrayList<SubscriptionPrice>(subscriptionPlanDTO.getPrices());
|
||||
priceList.sort(new Comparator<SubscriptionPrice>() {
|
||||
@Override
|
||||
public int compare(SubscriptionPrice o1, SubscriptionPrice o2) {
|
||||
return o1.getPaymentInterval().compareTo(o2.getPaymentInterval());
|
||||
}
|
||||
});
|
||||
if (priceList.size() > 0) {
|
||||
currentPrice = priceList.get(0);
|
||||
} else {
|
||||
priceText = i18n.price() + ": " + i18n.individual();
|
||||
currentPrice = null;
|
||||
}
|
||||
if (priceList != null && !priceList.isEmpty()) {
|
||||
for (SubscriptionPrice subscriptionPrice: priceList) {
|
||||
FocusPanel price = new FocusPanel();
|
||||
price.addStyleName(PRICE_STYLE);
|
||||
String intervalTranslated = SubscriptionStringConstants.INSTANCE.getString("payment_interval_" + subscriptionPrice.getPaymentInterval().name());
|
||||
String priceText = NumberFormat.getCurrencyFormat("USD").format(subscriptionPrice.getPrice())
|
||||
+ " /" + intervalTranslated;
|
||||
price.add(new Label(priceText));
|
||||
if (subscriptionPrice.equals(currentPrice)) {
|
||||
price.addStyleName(SELECTED_STYLE);
|
||||
}
|
||||
price.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
for (int i=0; i<prices.getWidgetCount(); i++) {
|
||||
prices.getWidget(i).removeStyleName(SELECTED_STYLE);
|
||||
}
|
||||
currentPrice = subscriptionPrice;
|
||||
price.addStyleName(SELECTED_STYLE);
|
||||
}
|
||||
});
|
||||
prices.add(price);
|
||||
}
|
||||
// TODO: Implement new Price handling
|
||||
} else {
|
||||
final String priceText;
|
||||
if (type == Type.FREE) {
|
||||
priceText = i18n.free();
|
||||
} else if (type == Type.INDIVIDUAL) {
|
||||
priceText = i18n.individual();
|
||||
} else {
|
||||
priceText = i18n.price() + ": - ";
|
||||
}
|
||||
FlowPanel price = new FlowPanel();
|
||||
price.addStyleName(PRICE_STYLE);
|
||||
price.add(new Label(priceText));
|
||||
prices.add(price);
|
||||
}
|
||||
switch (type) {
|
||||
case HIGHLIGHT:
|
||||
@@ -86,13 +139,15 @@ public class SubscriptionCard extends Composite {
|
||||
addStyleName(INDIVIDUAL_STYLE);
|
||||
button.setText(i18n.send());
|
||||
break;
|
||||
case FREE:
|
||||
addStyleName(FREE_STYLE);
|
||||
button.setText(i18n.signUp());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
final SailingSubscriptionStringConstants subscriptionStringConstants = SailingSubscriptionStringConstants.INSTANCE;
|
||||
title.setInnerText(subscriptionStringConstants.getString(subscriptionPlanDTO.getNameMessageKey()));
|
||||
description.setInnerText(subscriptionStringConstants.getString(subscriptionPlanDTO.getDescMessageKey()));
|
||||
price.setInnerText(priceText);
|
||||
for (StringMessagesKey featureKey : subscriptionPlanDTO.getFeatures()) {
|
||||
FlowPanel feature = new FlowPanel();
|
||||
feature.addStyleName(FEATURE_STYLE);
|
||||
@@ -103,7 +158,7 @@ public class SubscriptionCard extends Composite {
|
||||
|
||||
@UiHandler("button")
|
||||
void onClick(ClickEvent e) {
|
||||
subscriptionCallback.run();
|
||||
subscriptionCallback.accept(currentPrice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,8 +11,8 @@
|
||||
</g:FlowPanel>
|
||||
<div class="{local.css.subscriptionBody}">
|
||||
<h1 ui:field="title" class="{local.css.title}"></h1>
|
||||
<g:FlowPanel ui:field="prices" styleName="{local.css.prices}"></g:FlowPanel>
|
||||
<h4 ui:field="description" class="{local.css.description}"></h4>
|
||||
<h3 ui:field="price" class="{local.css.price}"></h3>
|
||||
<g:FlowPanel ui:field="features" styleName="{local.css.features}"></g:FlowPanel>
|
||||
<g:Button styleName="{main.mainCss.button} {main.mainCss.buttonstrong} {main.mainCss.buttonprimary} {main.mainCss.buttonarrowrightwhite} {local.css.subscribe}" ui:field="button" text=""/>
|
||||
</div>
|
||||
|
||||
+3
@@ -12,6 +12,7 @@ public interface SubscriptionCardResources extends SharedHomeResources {
|
||||
LocalCss css();
|
||||
|
||||
public interface LocalCss extends CssResource {
|
||||
String free();
|
||||
String feature();
|
||||
String highlight();
|
||||
String owned();
|
||||
@@ -20,6 +21,8 @@ public interface SubscriptionCardResources extends SharedHomeResources {
|
||||
String title();
|
||||
String description();
|
||||
String price();
|
||||
String selected();
|
||||
String prices();
|
||||
String features();
|
||||
String subscribe();
|
||||
String container();
|
||||
|
||||
+19
@@ -1,9 +1,13 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.subscription;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gwt.activity.shared.AbstractActivity;
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.shared.EventBus;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
@@ -34,6 +38,21 @@ public class SubscriptionActivity extends AbstractActivity {
|
||||
.getAllSubscriptionPlans(new AsyncCallback<ArrayList<SubscriptionPlanDTO>>() {
|
||||
@Override
|
||||
public void onSuccess(final ArrayList<SubscriptionPlanDTO> result) {
|
||||
GWT.log("onSuccess");
|
||||
Set<StringMessagesKey> freeFeatures = new LinkedHashSet<StringMessagesKey>(
|
||||
Arrays.asList(new StringMessagesKey("free_feature_1"),
|
||||
new StringMessagesKey("free_feature_2"),
|
||||
new StringMessagesKey("free_feature_3"),
|
||||
new StringMessagesKey("free_feature_4"))
|
||||
);
|
||||
|
||||
final SubscriptionPlanDTO freePlan = new SubscriptionPlanDTO(null /* id */,
|
||||
new StringMessagesKey("free_subscription_plan_name"),
|
||||
new StringMessagesKey("free_subscription_plan_description"),
|
||||
freeFeatures,
|
||||
Collections.emptySet() /* prices */,
|
||||
null /* error */);
|
||||
view.addSubscriptionPlan(freePlan, Type.FREE);
|
||||
result.forEach(plan -> {
|
||||
if (checkIfUserIsOwnerOfThePlan(plan)) {
|
||||
view.addSubscriptionPlan(plan, Type.OWNER);
|
||||
|
||||
+16
-6
@@ -1,5 +1,6 @@
|
||||
package com.sap.sailing.gwt.home.shared.places.subscription;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.user.client.Window;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.sap.sailing.gwt.home.desktop.partials.subscription.SubscriptionCard;
|
||||
@@ -20,25 +21,34 @@ public class SubscriptionViewImpl extends Composite implements SubscriptionView
|
||||
public void addSubscriptionPlan(final SubscriptionPlanDTO plan, final SubscriptionCard.Type type) {
|
||||
switch (type) {
|
||||
case HIGHLIGHT:
|
||||
container.addSubscription(new SubscriptionCard(plan, type, () -> {
|
||||
presenter.startSubscription(plan.getId());
|
||||
container.addSubscription(new SubscriptionCard(plan, type, (price) -> {
|
||||
if (price != null) {
|
||||
presenter.startSubscription(price.getPriceId());
|
||||
}
|
||||
}));
|
||||
break;
|
||||
case DEFAULT:
|
||||
container.addSubscription(new SubscriptionCard(plan, type, () -> {
|
||||
presenter.startSubscription(plan.getId());
|
||||
container.addSubscription(new SubscriptionCard(plan, type, (price) -> {
|
||||
if (price != null) {
|
||||
presenter.startSubscription(price.getPriceId());
|
||||
}
|
||||
}));
|
||||
break;
|
||||
case OWNER:
|
||||
container.addSubscription(new SubscriptionCard(plan, type, () -> {
|
||||
container.addSubscription(new SubscriptionCard(plan, type, (price) -> {
|
||||
presenter.manageSubscriptions();
|
||||
}));
|
||||
break;
|
||||
case INDIVIDUAL:
|
||||
container.addSubscription(new SubscriptionCard(plan, type, () -> {
|
||||
container.addSubscription(new SubscriptionCard(plan, type, (price) -> {
|
||||
Window.Location.assign("mailto:info@sapsailing.com");
|
||||
}));
|
||||
break;
|
||||
case FREE:
|
||||
container.addSubscription(new SubscriptionCard(plan, type, (price) -> {
|
||||
GWT.log("TODO: sign up dialog");
|
||||
}));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+1
@@ -2331,6 +2331,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
|
||||
String subscriptionOwnerHeaderText();
|
||||
String subscriptionHighlightText();
|
||||
String individual();
|
||||
String free();
|
||||
String openPortal();
|
||||
String plans();
|
||||
String freePlan();
|
||||
|
||||
+1
@@ -2370,6 +2370,7 @@ cancelSubscription=Cancel Subscription
|
||||
subscriptionOwnerHeaderText=You are already the owner!
|
||||
subscriptionHighlightText=Recommended for you!
|
||||
individual=individual
|
||||
free=free
|
||||
openPortal=Open Portal
|
||||
plans=Plans
|
||||
freePlan=Free
|
||||
|
||||
+4
@@ -2377,6 +2377,10 @@ subscriptions=Abonnements
|
||||
noSubscriptions=Keine Abonnements
|
||||
subscribe=Abonnieren
|
||||
cancelSubscription=Abonnement beenden
|
||||
subscriptionOwnerHeaderText=Sie sind bereits Eigentümer!
|
||||
subscriptionHighlightText=Für Sie empfohlen!
|
||||
individual=Individuell
|
||||
free=Kostenlos
|
||||
openPortal=Portal öffnen
|
||||
plans=Abonnement-Pläne
|
||||
freePlan=Kostenlos
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.xmlexport.test</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>com.sap.sailing.xmlexport</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
+10
@@ -20,6 +20,16 @@ public interface SubscriptionStringConstants extends ConstantsWithLookup {
|
||||
}
|
||||
}
|
||||
|
||||
String free_subscription_plan_name();
|
||||
String free_subscription_plan_description();
|
||||
String free_feature_1();
|
||||
String free_feature_2();
|
||||
String free_feature_3();
|
||||
String free_feature_4();
|
||||
String payment_interval_YEAR();
|
||||
String payment_interval_MONTH();
|
||||
String payment_interval_WEEK();
|
||||
String payment_interval_DAY();
|
||||
String individual_subscription_plan_name();
|
||||
String individual_subscription_plan_description();
|
||||
String basic_plan_name();
|
||||
|
||||
+10
@@ -1,3 +1,13 @@
|
||||
free_subscription_plan_name=Free
|
||||
free_subscription_plan_description=Try it out
|
||||
free_feature_1=Start your first steps in SAP sailing
|
||||
free_feature_2=Use basic features of SAP Sailing Analytics
|
||||
free_feature_3=Have a look on SAP Sailing Race Manager
|
||||
free_feature_4=Try more features and functions that will improve your life in sailing
|
||||
payment_interval_YEAR=year
|
||||
payment_interval_MONTH=month
|
||||
payment_interval_WEEK=week
|
||||
payment_interval_DAY=day
|
||||
individual_subscription_plan_name=Enterprise
|
||||
individual_subscription_plan_description=For individual offer contact us!
|
||||
basic_plan_name=Basic
|
||||
|
||||
Reference in New Issue
Block a user