diff --git a/apps/36-blocks-widget/src/app/otp/widget/widget.component.ts b/apps/36-blocks-widget/src/app/otp/widget/widget.component.ts index 0e9135c5..baed0651 100644 --- a/apps/36-blocks-widget/src/app/otp/widget/widget.component.ts +++ b/apps/36-blocks-widget/src/app/otp/widget/widget.component.ts @@ -206,6 +206,12 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O private hcaptchaLoading: boolean = false; private hcaptchaRenderQueue: Array<() => void> = []; public isUserProxyContainer: boolean = true; + /** Host page URL where this widget script is embedded. */ + public hostPageUrl: string = ''; + /** Origin of the host page (protocol + host). */ + public hostPageOrigin: string = ''; + /** Absolute URL of the proxy-auth.js script tag, if found. */ + public widgetScriptUrl: string = ''; constructor() { super(); @@ -235,6 +241,7 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O } ngOnInit() { + this.captureHostPageUrl(); this.store.dispatch(resetAll()); this._authToken$.set(this.authToken); this._type$.set(this.type); @@ -359,6 +366,41 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O }); } + /** + * Reads the page URL where the widget is loaded, plus the script src if available. + * Uses standard browser APIs — works for both CDN embeds and local serve. + */ + private captureHostPageUrl(): void { + this.hostPageUrl = window.location?.href ?? ''; + this.hostPageOrigin = window.location?.origin ?? ''; + this.widgetScriptUrl = + (document.currentScript as HTMLScriptElement | null)?.src || + (document.querySelector('script[src*="proxy-auth"]') as HTMLScriptElement | null)?.src || + ''; + console.log('[36Blocks] Host page URL:', this.hostPageUrl); + } + + /** True when the host page URL looks like a register / sign-up route. */ + private isSignupRoute(): boolean { + const path = `${window.location?.pathname ?? ''} ${window.location?.href ?? ''}`.toLowerCase(); + return /sign[-_]?up|register|registration|signup/.test(path); + } + + /** + * On register/sign-up routes, rewrite login-oriented auth button labels to "Sign up". + * e.g. "Continue with Google" → "Sign up with Google" + * "Login with OTP" → "Sign up with OTP" + */ + private getAuthButtonText(text: string): string { + if (!text || !this.isSignupRoute()) { + return text; + } + return text + .replace(/\bcontinue\b/gi, 'Sign up') + .replace(/\blog[\s-]?in\b/gi, 'Sign up') + .replace(/\bsign[\s-]?in\b/gi, 'Sign up'); + } + private loadExternalFonts() { const node = document.querySelector('proxy-auth')?.shadowRoot; const styleElement = document.createElement('link'); @@ -667,11 +709,20 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O } }); } else { - if ( - buttonsData?.service_id !== FeatureServiceIds.PasswordAuthentication || - (buttonsData?.service_id === FeatureServiceIds.PasswordAuthentication && - this.version === 'v1') - ) { + const isPasswordAuth = buttonsData?.service_id === FeatureServiceIds.PasswordAuthentication; + + // On signup/register routes, skip password login entirely. + if (isPasswordAuth && this.isSignupRoute()) { + buttonsProcessed++; + this.checkAndAppendCreateAccountText( + element, + buttonsProcessed, + totalButtons, + fallbackTimeout, + immediateFallback, + otpTimeout + ); + } else if (!isPasswordAuth || this.version === 'v1') { this.appendButton(element, buttonsData); buttonsProcessed++; this.checkAndAppendCreateAccountText( @@ -740,6 +791,10 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O } public appendPasswordAuthenticationButtonV2(element: HTMLElement, buttonsData: any, totalButtons: number): void { + // Password login form is not shown on signup/register routes. + if (this.isSignupRoute()) { + return; + } if (this.showSkeleton) { this.showSkeleton = false; this.domBuilder.removeSkeletonLoader(this.renderer, element); @@ -1261,6 +1316,10 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O } private appendButton(element, buttonsData): void { + // Password login button is not shown on signup/register routes. + if (buttonsData?.service_id === FeatureServiceIds.PasswordAuthentication && this.isSignupRoute()) { + return; + } if (this.showSkeleton) { this.showSkeleton = false; this.domBuilder.removeSkeletonLoader(this.renderer, element); @@ -1331,8 +1390,9 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O width: 24px; ${invertIcon ? 'filter: invert(1);' : ''} `; + const authButtonText = this.getAuthButtonText(buttonsData.text); image.src = buttonsData.icon; - image.alt = buttonsData.text; + image.alt = authButtonText; image.loading = 'lazy'; if (buttonsData?.service_id) { @@ -1352,6 +1412,7 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O this.renderer.appendChild(iconsContainer, button); } else { const span: HTMLSpanElement = this.renderer.createElement('span'); + const authButtonText = this.getAuthButtonText(buttonsData.text); button.setAttribute('data-paw-button', 'true'); button.style.cssText = ` @@ -1386,9 +1447,9 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O min-width: 170px `; image.src = buttonsData.icon; - image.alt = buttonsData.text; + image.alt = authButtonText; image.loading = 'lazy'; - span.innerText = buttonsData.text; + span.innerText = authButtonText; if (buttonsData?.service_id) { button.setAttribute('data-service-id', buttonsData.service_id); @@ -1454,50 +1515,53 @@ export class ProxyAuthWidgetComponent extends BaseComponent implements OnInit, O const selectWidgetTheme = this.widgetTheme() as any; const primaryColor = this.getPrimaryColorForCurrentTheme(selectWidgetTheme?.ui_preferences); - const paragraph: HTMLParagraphElement = this.renderer.createElement('p'); - const span: HTMLSpanElement = this.renderer.createElement('span'); - const link: HTMLAnchorElement = this.renderer.createElement('a'); - - paragraph.setAttribute('data-create-account', 'true'); - - paragraph.style.cssText = ` - margin: 20px 8px 8px 8px !important; - font-size: 14px !important; - outline: none !important; - display: flex !important; - align-items: center !important; - justify-content: center !important; - flex-wrap: wrap; - gap: 8px !important; - color: ${primaryColor} !important; - cursor: pointer !important; - width: 316px !important; - max-width:100%; - `; + // Hide "Are you a new user? Create an account" on signup/register routes. + if (!this.isSignupRoute()) { + const paragraph: HTMLParagraphElement = this.renderer.createElement('p'); + const span: HTMLSpanElement = this.renderer.createElement('span'); + const link: HTMLAnchorElement = this.renderer.createElement('a'); + + paragraph.setAttribute('data-create-account', 'true'); + + paragraph.style.cssText = ` + margin: 20px 8px 8px 8px !important; + font-size: 14px !important; + outline: none !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + flex-wrap: wrap; + gap: 8px !important; + color: ${primaryColor} !important; + cursor: pointer !important; + width: 316px !important; + max-width:100%; + `; - // Style the link - link.style.cssText = ` - color: #007bff !important; - text-decoration: none; - cursor: pointer; - font-weight: 500 !important; - `; + // Style the link + link.style.cssText = ` + color: #007bff !important; + text-decoration: none; + cursor: pointer; + font-weight: 500 !important; + `; - // Set the text content - span.textContent = 'Are you a new user? '; - link.textContent = selectWidgetTheme?.ui_preferences?.sign_up_button_text || 'Create an account'; + // Set the text content + span.textContent = 'Are you a new user? '; + link.textContent = selectWidgetTheme?.ui_preferences?.sign_up_button_text || 'Create an account'; - // Add click event to the link - link.addEventListener('click', (event) => { - event.preventDefault(); - this.cameFromLogin = false; // Set flag to indicate user came from dynamically appended buttons - this.setShowRegistration(true); - }); + // Add click event to the link + link.addEventListener('click', (event) => { + event.preventDefault(); + this.cameFromLogin = false; // Set flag to indicate user came from dynamically appended buttons + this.setShowRegistration(true); + }); - // Append elements - this.renderer.appendChild(paragraph, span); - this.renderer.appendChild(paragraph, link); - this.renderer.appendChild(element, paragraph); + // Append elements + this.renderer.appendChild(paragraph, span); + this.renderer.appendChild(paragraph, link); + this.renderer.appendChild(element, paragraph); + } // Powered by footer — hidden when branding is removed (ui_preferences.remove_branding) if (selectWidgetTheme?.ui_preferences?.remove_branding) { diff --git a/apps/36-blocks/src/app/panel/users/management/management.component.html b/apps/36-blocks/src/app/panel/users/management/management.component.html index da569ef7..3f3ccc38 100644 --- a/apps/36-blocks/src/app/panel/users/management/management.component.html +++ b/apps/36-blocks/src/app/panel/users/management/management.component.html @@ -88,7 +88,22 @@ -
+
+ @if (element.feature_configuration_id) { + + + + }