Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions assets/js/hubsubscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,21 @@ class HubSubscription {
constructor(form, subscriptionData, searchParams) {
this._form = form;
this._subscriptionData = subscriptionData;
this._subscriptionData.hubId = searchParams.get('hub_id');
let encodedReturnUrl = searchParams.get('return_url');
if (encodedReturnUrl) {
this._subscriptionData.returnUrl = decodeURIComponent(encodedReturnUrl);
let fragmentParams = new URLSearchParams(location.hash.substring(1));
this._subscriptionData.oldLicense = fragmentParams.get('oldLicense');
if (this._subscriptionData.oldLicense) {
try {
let base64 = this._subscriptionData.oldLicense.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
this._subscriptionData.hubId = JSON.parse(atob(base64)).jti;
} catch (e) {
console.error('Failed to parse hub token:', e);
this._subscriptionData.oldLicense = null;
}
}
this._subscriptionData.hubId = this._subscriptionData.hubId ?? searchParams.get('hub_id');
let returnUrl = fragmentParams.get('returnUrl') ?? searchParams.get('return_url');
if (returnUrl) {
this._subscriptionData.returnUrl = returnUrl;
}
this._subscriptionData.session = searchParams.get('session');
if (this._subscriptionData.hubId && this._subscriptionData.hubId.length > 0 && this._subscriptionData.returnUrl && this._subscriptionData.returnUrl.length > 0) {
Expand Down Expand Up @@ -57,7 +68,7 @@ class HubSubscription {
}

onLoadSubscriptionSucceeded(data) {
this._subscriptionData.verificationToken = data.token;
this._subscriptionData.oldLicense = data.token;
this._subscriptionData.details = data.subscription;
if (data.subscription.quantity) {
this._subscriptionData.quantity = data.subscription.quantity;
Expand Down Expand Up @@ -313,7 +324,7 @@ class HubSubscription {

onPostSucceeded(data) {
this._subscriptionData.state = 'EXISTING_CUSTOMER';
this._subscriptionData.verificationToken = data.token;
this._subscriptionData.oldLicense = data.token;
this._subscriptionData.details = data.subscription;
this._subscriptionData.session = data.session;
var searchParams = new URLSearchParams(window.location.search)
Expand Down Expand Up @@ -480,7 +491,7 @@ class HubSubscription {
}

onPutSucceeded(data, shouldOpenReturnUrl) {
this._subscriptionData.verificationToken = data.token;
this._subscriptionData.oldLicense = data.token;
this._subscriptionData.details = data.subscription;
this._subscriptionData.errorMessage = '';
this._subscriptionData.inProgress = false;
Expand All @@ -505,7 +516,7 @@ class HubSubscription {
url: REFRESH_LICENSE_URL,
type: 'POST',
data: {
token: this._subscriptionData.verificationToken,
token: this._subscriptionData.oldLicense,
captcha: this._subscriptionData.captcha
}
}).done(token => {
Expand Down
15 changes: 15 additions & 0 deletions i18n/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
translation: "Ich bin damit einverstanden, Neuigkeiten von Cryptomator Hub zu erhalten, und akzeptiere die <a class=\"text-link\" href=\"/de/privacy/\">Datenschutzerklärung</a>."
- id: accept_hub_newsletter_optional
translation: "Ich bin damit einverstanden, Neuigkeiten von Cryptomator Hub per E-Mail zu erhalten (optional)."
- id: accept_hub_managed_early_access_optional
translation: "<span class=\"inline-flex px-2 py-0.5 rounded-full text-xs font-medium uppercase bg-primary-l2 text-dark\">BETA</span> <a class=\"text-link\" href=\"https://docs.cryptomator.org/hub/early-access/\" target=\"_blank\">Early Access von Cryptomator Hub 1.5.0</a> mit brandneuen Features und einer verlängerten 100-Tage-Testphase testen (optional)."
- id: accept_privacy
translation: "Ich akzeptiere die <a class=\"text-link\" href=\"/de/privacy/\">Datenschutzerklärung</a>."
- id: accept_privacy_implicitly
Expand Down Expand Up @@ -613,6 +615,19 @@
- id: hub_billing_checkout_standard_submit
translation: "Zur Zahlung"

- id: hub_billing_checkout_community_title
translation: "Community"
- id: hub_billing_checkout_community_statement
translation: "Kostenlos"
- id: hub_billing_checkout_community_description
translation: "bis zu 5 Sitze inklusive"
- id: hub_billing_checkout_community_subtitle
translation: "Kostenlos starten"
- id: hub_billing_checkout_community_cta
translation: "Deine Hub-Instanz unterstützt die Community Edition. Registriere dich für eine kostenlose Lizenz mit bis zu 5 Sitzen."
- id: hub_billing_checkout_community_action
translation: "Kostenlos registrieren"

- id: hub_billing_checkout_enterprise_title
translation: "Enterprise"
- id: hub_billing_checkout_enterprise_statement
Expand Down
15 changes: 15 additions & 0 deletions i18n/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
translation: "I agree to get updates from Cryptomator Hub and accept the <a class=\"text-link\" href=\"/privacy/\" target=\"_blank\">Privacy Policy</a>."
- id: accept_hub_newsletter_optional
translation: "I agree to get updates from Cryptomator Hub via email (optional)."
- id: accept_hub_managed_early_access_optional
translation: "<span class=\"inline-flex px-2 py-0.5 rounded-full text-xs font-medium uppercase bg-primary-l2 text-dark\">BETA</span> Try out <a class=\"text-link\" href=\"https://docs.cryptomator.org/hub/early-access/\" target=\"_blank\">early access of Cryptomator Hub 1.5.0</a> with brand new features and an extended 100-day trial (optional)."
- id: accept_privacy
translation: "I accept the <a class=\"text-link\" href=\"/privacy/\" target=\"_blank\">Privacy Policy</a>."
- id: accept_privacy_implicitly
Expand Down Expand Up @@ -613,6 +615,19 @@
- id: hub_billing_checkout_standard_submit
translation: "Checkout"

- id: hub_billing_checkout_community_title
translation: "Community"
- id: hub_billing_checkout_community_statement
translation: "Free"
- id: hub_billing_checkout_community_description
translation: "up to 5 seats included"
- id: hub_billing_checkout_community_subtitle
translation: "Get Started for Free"
- id: hub_billing_checkout_community_cta
translation: "Your Hub instance supports the Community Edition. Register for a free license with up to 5 seats."
- id: hub_billing_checkout_community_action
translation: "Register for Free"

- id: hub_billing_checkout_enterprise_title
translation: "Enterprise"
- id: hub_billing_checkout_enterprise_statement
Expand Down
43 changes: 39 additions & 4 deletions layouts/hub-billing/single.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{{ end }}
{{ define "main" }}
<div class="container pt-12 pb-24">
<form x-data="{subscriptionData: {state: 'MISSING_PARAMS', captcha: null, hubId: null, returnUrl: null, session: null, customBilling: null, billingInterval: 'yearly', savingsPercent: null, errorMessage: '', inProgress: false, restartModal: {open: false, nextPayment: null}, changeSeatsModal: {open: false, confirmation: false, immediatePayment: null}, token: null, details: null, quantity: 5, email: '', needsTokenRefresh: false, shouldTransferToHub: false}, acceptTerms: false, hubSubscription: null, captchaState: null}" x-init="hubSubscription = new HubSubscription($refs.form, subscriptionData, new URLSearchParams(location.search))" x-ref="form" @submit.prevent="hubSubscription.createSession(); $refs.captcha.reset()">
<form x-data="{subscriptionData: {state: 'MISSING_PARAMS', captcha: null, hubId: null, returnUrl: null, session: null, oldLicense: null, customBilling: null, billingInterval: 'yearly', savingsPercent: null, errorMessage: '', inProgress: false, restartModal: {open: false, nextPayment: null}, changeSeatsModal: {open: false, confirmation: false, immediatePayment: null}, token: null, details: null, quantity: 5, email: '', needsTokenRefresh: false, shouldTransferToHub: false}, acceptTerms: false, hubSubscription: null, captchaState: null}" x-init="hubSubscription = new HubSubscription($refs.form, subscriptionData, new URLSearchParams(location.search))" x-ref="form" @submit.prevent="hubSubscription.createSession(); $refs.captcha.reset()">
<template x-if="subscriptionData.state == 'MISSING_PARAMS'">
<div class="text-center max-w-xl mx-auto">
<h3 class="font-headline text-xl md:text-2xl leading-relaxed mb-4">
Expand Down Expand Up @@ -314,7 +314,8 @@ <h3 class="font-headline text-xl md:text-2xl leading-relaxed mb-4" id="change-se
<h1 class="font-h1 mb-8">{{ .Title }}</h1>
<p class="lead">{{ i18n "hub_billing_checkout_description" . }}</p>
</header>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-12">
<div class="grid grid-cols-1 gap-4 mb-12" :class="subscriptionData.oldLicense && !subscriptionData.customBilling?.managed ? 'md:grid-cols-3' : 'md:grid-cols-2'">
<div x-show="subscriptionData.oldLicense && !subscriptionData.customBilling?.managed" class="hidden md:block"></div>
<div class="flex justify-center">
<button class="w-1/2 py-2 border border-gray-300 rounded-l bg-gray-300 text-gray-700 hover:border-gray-400 hover:bg-gray-400 focus:bg-gray-400 focus:border-secondary" :class="{'border-gray-400 bg-gray-400 text-gray-800 font-medium': audience === 'business'}" @click.prevent="audience = 'business'">
<i class="fa-building" :class="{'fas': audience === 'business', 'far': audience !== 'business'}"></i>
Expand All @@ -326,6 +327,40 @@ <h1 class="font-h1 mb-8">{{ .Title }}</h1>
</button>
</div>
<div class="hidden md:block"></div>
<div x-show="subscriptionData.oldLicense && !subscriptionData.customBilling?.managed" class="flex flex-col white-box">
<div class="p-4 border-b border-primary">
<h2 class="inline-flex px-4 py-1 rounded-full text-sm font-medium tracking-wide uppercase bg-primary-l2 text-dark mb-4">
{{ i18n "hub_billing_checkout_community_title" . }}
</h2>
<div x-show="!subscriptionData.customBilling?.override?.prices" class="lg:h-[22px]"></div>
<p class="text-5xl font-bold">
{{ i18n "hub_billing_checkout_community_statement" . }}
</p>
<p class="text-lg text-gray-500 mb-4">
{{ i18n "hub_billing_checkout_community_description" . }}
</p>
</div>
<div class="grow">
<div class="flex flex-col items-center text-center h-full px-4 py-8">
<h3 class="font-h3 mb-4 md:mb-0">
{{ i18n "hub_billing_checkout_community_subtitle" . }}
</h3>
<div class="mb-4 md:my-auto lg:max-w-sm">
<div class="fa-stack text-5xl text-primary-l2 mb-4">
<i class="fa-solid fa-circle fa-stack-2x"></i>
<i class="fa-solid fa-people-group fa-stack-1x text-primary"></i>
</div>
<p class="font-p">
{{ i18n "hub_billing_checkout_community_cta" . }}
</p>
</div>
<a :href="`{{ "hub/register" | relLangURL }}#oldLicense=${encodeURIComponent(subscriptionData.oldLicense)}&returnUrl=${encodeURIComponent(subscriptionData.returnUrl)}`" role="button" class="btn btn-primary w-full">
<i class="fa-solid fa-user-plus"></i>
{{ i18n "hub_billing_checkout_community_action" . }}
</a>
</div>
</div>
</div>
<div class="white-box">
<div class="p-4 border-b border-primary">
<h2 class="inline-flex px-4 py-1 rounded-full text-sm font-medium tracking-wide uppercase bg-primary-l2 text-dark mb-4">
Expand Down Expand Up @@ -407,7 +442,7 @@ <h2 class="inline-flex px-4 py-1 rounded-full text-sm font-medium tracking-wide
</p>
<p x-show="subscriptionData.customBilling?.managed" class="font-p mb-4">{{ partial "checkbox.html" (dict "context" . "alpineVariable" "acceptTerms" "label" (i18n "accept_hub_managed_terms_and_privacy" | safeHTML)) }}</p>
<p x-show="!subscriptionData.customBilling?.managed" class="font-p mb-4">{{ partial "checkbox.html" (dict "context" . "alpineVariable" "acceptTerms" "label" (i18n "accept_terms_and_privacy" | safeHTML)) }}</p>
<button :disabled="subscriptionData.inProgress || !acceptTerms" @click.prevent="hubSubscription.checkout('{{ .Site.Language.Lang }}')" type="button" class="btn btn-primary w-full lg:w-1/2">
<button :disabled="subscriptionData.inProgress || !acceptTerms" @click.prevent="hubSubscription.checkout('{{ .Site.Language.Lang }}')" type="button" class="btn btn-primary w-full" :class="!(subscriptionData.oldLicense && !subscriptionData.customBilling?.managed) && 'lg:w-1/2'">
<i :class="{'fa-shopping-cart': !subscriptionData.inProgress, 'fa-check': !subscriptionData.inProgress, 'fa-spinner fa-spin': subscriptionData.inProgress}" class="fa-solid" aria-hidden="true"></i>
{{ i18n "hub_billing_checkout_standard_submit" . }}
</button>
Expand Down Expand Up @@ -442,7 +477,7 @@ <h3 class="font-h3 mb-4 md:mb-0">
{{ i18n "hub_billing_checkout_enterprise_cta" . }}
</p>
</div>
<a href="mailto:hub@cryptomator.org" role="button" class="btn btn-primary w-full lg:w-1/2">
<a href="mailto:hub@cryptomator.org" role="button" class="btn btn-primary w-full" :class="!(subscriptionData.oldLicense && !subscriptionData.customBilling?.managed) && 'lg:w-1/2'">
<i class="fa-solid fa-envelope"></i>
{{ i18n "hub_billing_checkout_enterprise_action" . }}
</a>
Expand Down
5 changes: 4 additions & 1 deletion layouts/hub-managed/single.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{{ partial "altcha-css.html" . }}
{{ end }}
{{ define "main" }}
<section x-data="{steps: ['{{ i18n "hub_managed_step_1_nav_title" }}', '{{ i18n "hub_managed_step_2_nav_title" }}', '{{ i18n "hub_managed_step_3_nav_title" }}', '{{ i18n "hub_managed_step_4_nav_title" }}'], feedbackData: {currentStep: 0, success: false, inProgress: false, errorMessage: ''}, submitData: {captcha: null, email: '', subdomain: '', quantity: null, message: null, acceptNewsletter: false}, acceptTerms: false, lowQuantityModalIsOpen: false, hubManaged: null, captchaState: null}" x-init="hubManaged = new HubManaged($refs.form, feedbackData, submitData)" class="container py-12">
<section x-data="{steps: ['{{ i18n "hub_managed_step_1_nav_title" }}', '{{ i18n "hub_managed_step_2_nav_title" }}', '{{ i18n "hub_managed_step_3_nav_title" }}', '{{ i18n "hub_managed_step_4_nav_title" }}'], feedbackData: {currentStep: 0, success: false, inProgress: false, errorMessage: ''}, submitData: {captcha: null, email: '', subdomain: '', quantity: null, message: null, acceptNewsletter: false, earlyaccess: false}, acceptTerms: false, lowQuantityModalIsOpen: false, hubManaged: null, captchaState: null}" x-init="hubManaged = new HubManaged($refs.form, feedbackData, submitData)" class="container py-12">
<header class="mb-6">
<h1 class="font-h1 mb-8">{{ .Title }}</h1>
<p class="lead">{{ i18n "hub_managed_description" }}</p>
Expand Down Expand Up @@ -181,6 +181,9 @@ <h2 class="font-h2 mb-6">
<p class="font-p text-sm mb-2">
{{ partial "checkbox.html" (dict "context" . "alpineVariable" "submitData.acceptNewsletter" "label" (i18n "accept_hub_newsletter_optional")) }}
</p>
<p class="font-p text-sm mb-2">
{{ partial "checkbox.html" (dict "context" . "alpineVariable" "submitData.earlyaccess" "label" (i18n "accept_hub_managed_early_access_optional")) }}
</p>
<div class="mt-auto">
<p :class="{'hidden': !feedbackData.errorMessage}" class="text-sm text-red-600 mb-2" x-text="feedbackData.errorMessage"></p>
<button :disabled="feedbackData.inProgress || !acceptTerms || captchaState == 'verifying'" type="submit" class="btn btn-primary w-full md:w-64" data-umami-event="hub-managed-form" x-cloak>
Expand Down
6 changes: 4 additions & 2 deletions layouts/partials/checkbox.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{{ $unique_id := printf "id-%s" (delimit (shuffle (seq 1 9)) "") }}
<input class="mr-1 rounded-sm text-primary focus:ring-0 focus:ring-offset-0 focus:border-secondary" type="checkbox" id="{{ $unique_id }}" x-model="{{ .alpineVariable }}" />
<label for="{{ $unique_id }}">{{ .label }}</label>
{{/* pl-6 + -indent-6: wrapped lines align with text, not checkbox. [&_*]:indent-0: reset for child elements (e.g. pills). */}}
<label class="inline-block pl-6 -indent-6 [&_*]:indent-0" for="{{ $unique_id }}">
<input class="mr-2 rounded-sm text-primary focus:ring-0 focus:ring-offset-0 focus:border-secondary" type="checkbox" id="{{ $unique_id }}" x-model="{{ .alpineVariable }}" />{{ .label | safeHTML }}
</label>