Skip to content

Commit 6b8123e

Browse files
committed
Remove team name field and add automatic subdomain generation from email
1 parent 4e44f7b commit 6b8123e

File tree

4 files changed

+89
-31
lines changed

4 files changed

+89
-31
lines changed

assets/js/hubmanaged.js

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,21 @@ class HubManaged {
2727
data: {
2828
email: this._submitData.email
2929
}
30-
}).done(_ => {
30+
}).done(response => {
31+
// Auto-populate subdomain only if it's a company email
32+
if (response.isCompanyEmail) {
33+
this._submitData.subdomain = emailToSubdomain(this._submitData.email);
34+
} else {
35+
// Clear subdomain for non-company emails (freemail, etc.)
36+
this._submitData.subdomain = '';
37+
}
3138
this.onValidationSucceeded();
3239
}).fail(xhr => {
3340
this.onValidationFailed(xhr.responseJSON?.message || 'Validating email failed.');
3441
});
3542
}
3643

37-
validateTeamAndSubdomain() {
44+
validateSubdomain() {
3845
if (!$(this._form)[0].checkValidity()) {
3946
$(this._form).find(':input').addClass('show-invalid');
4047
this._feedbackData.errorMessage = 'Please fill in all required fields.';
@@ -47,13 +54,12 @@ class HubManaged {
4754
url: VALIDATE_HUB_MANAGED_REQUEST_URL,
4855
type: 'GET',
4956
data: {
50-
team: this._submitData.team,
5157
subdomain: this._submitData.subdomain
5258
}
5359
}).done(_ => {
5460
this.onValidationSucceeded();
5561
}).fail(xhr => {
56-
this.onValidationFailed(xhr.responseJSON?.message || 'Validating team and subdomain failed.');
62+
this.onValidationFailed(xhr.responseJSON?.message || 'Validating subdomain failed.');
5763
});
5864
}
5965

@@ -153,6 +159,73 @@ function teamToSubdomain(team) {
153159
return subdomain;
154160
}
155161

162+
function emailToSubdomain(email) {
163+
if (!email || !email.includes('@')) {
164+
return '';
165+
}
166+
167+
// Extract domain from email
168+
const domain = email.split('@')[1].toLowerCase();
169+
170+
// Extract subdomain from email domain
171+
const domainParts = domain.split('.');
172+
173+
// For domains with multiple levels, try to find the most meaningful part
174+
let subdomain = '';
175+
176+
if (domainParts.length >= 2) {
177+
// Common TLDs and country codes to ignore
178+
const tlds = ['com', 'org', 'net', 'edu', 'gov', 'mil', 'co', 'io', 'me', 'info', 'biz'];
179+
const countryCodes = ['de', 'uk', 'fr', 'es', 'it', 'nl', 'at', 'ch', 'us', 'ca', 'au', 'jp', 'cn', 'in', 'br'];
180+
181+
// For academic domains (containing .edu, .ac, .edu.*, .ac.*)
182+
if (domain.includes('.edu') || domain.includes('.ac.')) {
183+
// Try to find the institution name (usually right before .edu/.ac)
184+
for (let i = domainParts.length - 3; i >= 0; i--) {
185+
if (!tlds.includes(domainParts[i]) && !countryCodes.includes(domainParts[i])) {
186+
subdomain = domainParts[i];
187+
break;
188+
}
189+
}
190+
}
191+
192+
// If no academic pattern or no match found, use heuristics
193+
if (!subdomain) {
194+
// Skip the last part (TLD) and country code if present
195+
let skipParts = 1;
196+
if (domainParts.length > 2 && countryCodes.includes(domainParts[domainParts.length - 1])) {
197+
skipParts = 2;
198+
}
199+
200+
// Look for the most meaningful part (skip common subdomains)
201+
const commonSubdomains = ['www', 'mail', 'email', 'smtp', 'pop', 'imap', 'webmail', 'smail'];
202+
for (let i = domainParts.length - skipParts - 1; i >= 0; i--) {
203+
if (!commonSubdomains.includes(domainParts[i])) {
204+
subdomain = domainParts[i];
205+
break;
206+
}
207+
}
208+
209+
// If all parts are common subdomains, just use the first part
210+
if (!subdomain && domainParts.length > skipParts) {
211+
subdomain = domainParts[0];
212+
}
213+
}
214+
215+
// Clean up the subdomain to match the allowed pattern
216+
subdomain = subdomain.replace(/[^a-z0-9-]/g, '-');
217+
subdomain = subdomain.replace(/-+/g, '-');
218+
subdomain = subdomain.replace(/^-+|-+$/g, '');
219+
220+
// Ensure it's not empty and within length limits
221+
if (subdomain && subdomain.length <= 63) {
222+
return subdomain;
223+
}
224+
}
225+
226+
return '';
227+
}
228+
156229
function subdomainToURL(subdomain) {
157230
return `https://${subdomain}.cryptomator.cloud`;
158231
}

i18n/de.yaml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -662,15 +662,13 @@
662662
translation: "E-Mail-Adresse"
663663

664664
- id: hub_managed_step_2_nav_title
665-
translation: "Team-Name"
665+
translation: "Subdomain"
666666
- id: hub_managed_step_2_title
667-
translation: "Wie heißt dein Team?"
668-
- id: hub_managed_step_2_team_placeholder
669-
translation: "Name deines Teams, Unternehmens oder deiner Organisation"
667+
translation: "Welche Subdomain möchtest du?"
670668
- id: hub_managed_step_2_subdomain_description
671-
translation: "Dies ist die URL deiner Hub-Instanz."
669+
translation: "Dies wird die URL deiner Hub-Instanz sein."
672670
- id: hub_managed_step_2_subdomain_placeholder
673-
translation: "Subdomain deiner Hub-Instanz"
671+
translation: "deine-subdomain"
674672

675673
- id: hub_managed_step_3_nav_title
676674
translation: "Erwartete Nutzer"
@@ -687,8 +685,6 @@
687685
translation: "Zusammenfassung"
688686
- id: hub_managed_step_4_email
689687
translation: "E-Mail"
690-
- id: hub_managed_step_4_team
691-
translation: "Team-Name"
692688
- id: hub_managed_step_4_url
693689
translation: "URL"
694690
- id: hub_managed_step_4_quantity

i18n/en.yaml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -662,15 +662,13 @@
662662
translation: "Email address"
663663

664664
- id: hub_managed_step_2_nav_title
665-
translation: "Team Name"
665+
translation: "Subdomain"
666666
- id: hub_managed_step_2_title
667-
translation: "What's your team's name?"
668-
- id: hub_managed_step_2_team_placeholder
669-
translation: "Name of your team, company, or organization"
667+
translation: "What subdomain would you like?"
670668
- id: hub_managed_step_2_subdomain_description
671-
translation: "This is the URL of your Hub instance."
669+
translation: "This will be the URL of your Hub instance."
672670
- id: hub_managed_step_2_subdomain_placeholder
673-
translation: "Subdomain of your Hub instance"
671+
translation: "your-subdomain"
674672

675673
- id: hub_managed_step_3_nav_title
676674
translation: "Expected Users"
@@ -687,8 +685,6 @@
687685
translation: "Summary"
688686
- id: hub_managed_step_4_email
689687
translation: "Email"
690-
- id: hub_managed_step_4_team
691-
translation: "Team Name"
692688
- id: hub_managed_step_4_url
693689
translation: "URL"
694690
- id: hub_managed_step_4_quantity

layouts/hub-managed/single.html

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{ define "main" }}
2-
<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: '', team: '', subdomain: '', quantity: null, message: null, acceptNewsletter: false}, acceptTerms: false, lowQuantityModalIsOpen: false, hubManaged: null, captchaState: null}" x-init="hubManaged = new HubManaged($refs.form, feedbackData, submitData); $watch('submitData.team', team => submitData.subdomain = teamToSubdomain(team))" class="container py-12">
2+
<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">
33
<header class="mb-6">
44
<h1 class="font-h1 mb-8">{{ .Title }}</h1>
55
<p class="lead">{{ i18n "hub_managed_description" }}</p>
@@ -78,7 +78,7 @@ <h2 class="font-h2 mb-6">
7878
</div>
7979
</template>
8080

81-
<!-- Step 2: Team Name -->
81+
<!-- Step 2: Subdomain -->
8282
<template x-if="feedbackData.currentStep == 1">
8383
<div class="md:col-span-2 grid grid-cols-6 gap-6">
8484
<div class="flex flex-col col-span-6 lg:col-span-4">
@@ -88,20 +88,19 @@ <h2 class="font-h2 mb-6">
8888
<h2 class="font-h2 mb-6">
8989
{{ i18n "hub_managed_step_2_title" }}
9090
</h2>
91-
<input type="text" id="team" class="block input-box w-full mb-6" placeholder="{{ i18n "hub_managed_step_2_team_placeholder" }}" x-init="$el.focus()" x-model="submitData.team" @blur="$el.classList.add('show-invalid')" required>
9291
<p class="font-p text-sm mb-2">
9392
{{ i18n "hub_managed_step_2_subdomain_description" }}
9493
</p>
9594
<div class="col-span-6 mb-8 lg:col-span-4">
9695
<div class="flex items-center rounded-sm bg-gray-300">
9796
<div class="text-sm text-gray-700 px-3">https://</div>
98-
<input type="text" id="subdomain" pattern="[a-z\d\-](?:[a-z\d\-]{0,61}[a-z\d])?" class="block input-box rounded-none text-sm w-full" placeholder="{{ i18n "hub_managed_step_2_subdomain_placeholder" }}" maxlength="63" x-model="submitData.subdomain" @blur="$el.classList.add('show-invalid')" required>
97+
<input type="text" id="subdomain" pattern="[a-z\d\-](?:[a-z\d\-]{0,61}[a-z\d])?" class="block input-box rounded-none text-sm w-full" placeholder="{{ i18n "hub_managed_step_2_subdomain_placeholder" }}" maxlength="63" x-init="$el.focus()" x-model="submitData.subdomain" @blur="$el.classList.add('show-invalid')" required>
9998
<div class="text-sm text-gray-700 px-3">.cryptomator.cloud</div>
10099
</div>
101100
</div>
102101
<div class="mt-auto">
103102
<p :class="{'hidden': !feedbackData.errorMessage}" class="text-sm text-red-600 mb-2" x-text="feedbackData.errorMessage"></p>
104-
<button :disabled="feedbackData.inProgress" @click.prevent="hubManaged.validateTeamAndSubdomain()" class="btn btn-primary w-full md:w-64" data-umami-event="hub-managed-step-2">
103+
<button :disabled="feedbackData.inProgress" @click.prevent="hubManaged.validateSubdomain()" class="btn btn-primary w-full md:w-64" data-umami-event="hub-managed-step-2">
105104
<i :class="{'fa-chevron-right': !feedbackData.inProgress, 'fa-spinner fa-spin': feedbackData.inProgress}" class="fas fa-fw" aria-hidden="true"></i>
106105
{{ i18n "hub_managed_steps_next" }}
107106
</button>
@@ -152,12 +151,6 @@ <h2 class="font-h2 mb-6">
152151
</span>
153152
<span class="font-p text-sm" x-text="submitData.email"></span>
154153
</li>
155-
<li class="flex justify-between gap-2">
156-
<span class="font-p text-sm text-gray-500">
157-
{{ i18n "hub_managed_step_4_team" }}
158-
</span>
159-
<span class="font-p text-sm" x-text="submitData.team"></span>
160-
</li>
161154
<li class="flex justify-between gap-2">
162155
<span class="font-p text-sm text-gray-500">
163156
{{ i18n "hub_managed_step_4_url" }}

0 commit comments

Comments
 (0)