diff --git a/frontend/src/app/components/branding/branding.component.css b/frontend/src/app/components/branding/branding.component.css index ae156a034..61a756909 100644 --- a/frontend/src/app/components/branding/branding.component.css +++ b/frontend/src/app/components/branding/branding.component.css @@ -171,3 +171,45 @@ background-color: var(--color-accentedPalette-700); } } + +.upgrade-required { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 48px 24px; + border: 1px solid var(--color-primaryPalette-100); + height: fit-content; +} + +@media (prefers-color-scheme: dark) { + .upgrade-required { + border-color: var(--color-primaryPalette-700); + } +} + +.upgrade-required__icon { + font-size: 64px; + width: 64px; + height: 64px; + color: rgba(0, 0, 0, 0.38); + margin-bottom: 24px; +} + +@media (prefers-color-scheme: dark) { + .upgrade-required__icon { + color: rgba(255, 255, 255, 0.38); + } +} + +.upgrade-required__description { + color: rgba(0, 0, 0, 0.64); + margin-bottom: 24px; + max-width: 400px; +} + +@media (prefers-color-scheme: dark) { + .upgrade-required__description { + color: rgba(255, 255, 255, 0.7); + } +} diff --git a/frontend/src/app/components/branding/branding.component.html b/frontend/src/app/components/branding/branding.component.html index 4cce16f50..97b4f15de 100644 --- a/frontend/src/app/components/branding/branding.component.html +++ b/frontend/src/app/components/branding/branding.component.html @@ -12,9 +12,9 @@

Branding

-
+ [matTooltip]="currentUser.role !== 'ADMIN' ? 'Contact your Account Owner to set up white label settings.' : 'To white‑label your domain, please upgrade to the Team plan or higher.'">
Branding angularticsAction="Company: custom domain is edited" (change)="posthog.capture('Company: custom domain is edited')" placeholder="e.g. {{companyCustomDomainPlaceholder}}" - [readonly]="currentUser.role === 'DB_ADMIN' || isCustomDomain" + [readonly]="currentUser.role !== 'ADMIN' || isCustomDomain" [(ngModel)]="companyCustomDomainHostname"> To change the domain, visit app.rocketadmin.com/company @@ -48,7 +48,7 @@

Branding

(click)="handleDeleteDomainDialogOpen()"> Delete - @@ -57,7 +57,7 @@

Branding

-
+
diff --git a/frontend/src/app/components/company/company.component.css b/frontend/src/app/components/company/company.component.css index a51f4234f..610ca3fef 100644 --- a/frontend/src/app/components/company/company.component.css +++ b/frontend/src/app/components/company/company.component.css @@ -48,39 +48,6 @@ gap: 4px; } -.company-plan { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 32px; -} - -.company-plan-name { - text-transform: capitalize; -} - -.company-plan__paymnent-buttons { - display: flex; - gap: 12px; - margin-left: auto; -} - -@media (width <= 600px) { - .upgrade-button__caption_desktop { - display: none; - } -} - -.upgrade-button__caption_mobile { - display: none; -} - -@media (width <= 600px) { - .upgrade-button__caption_mobile { - display: initial; - } -} - .tableHeader { display: flex; align-items: center; diff --git a/frontend/src/app/components/company/company.component.html b/frontend/src/app/components/company/company.component.html index 8940685a8..ac9451f36 100644 --- a/frontend/src/app/components/company/company.component.html +++ b/frontend/src/app/components/company/company.component.html @@ -31,37 +31,8 @@

{{submittingChangedName ? 'Saving' : 'Save'}}

- -
-
- Current plan: - {{currentPlan}} -
-
- - Payment settings - Stripe - - - {{ company.portal_link ? 'Change' : 'Upgrade'}} - -
-
-

Members (max 3)

diff --git a/frontend/src/app/components/profile/profile-sidebar/profile-sidebar.component.html b/frontend/src/app/components/profile/profile-sidebar/profile-sidebar.component.html index c117fdf29..2e7a48052 100644 --- a/frontend/src/app/components/profile/profile-sidebar/profile-sidebar.component.html +++ b/frontend/src/app/components/profile/profile-sidebar/profile-sidebar.component.html @@ -41,13 +41,13 @@ payments - Pricing + Subscription Branding ('account'); + activeTab = input<'account' | 'company' | 'subscription' | 'branding' | 'saml' | 'api' | 'secrets' | 'zapier'>('account'); collapsed = signal(false); initialized = signal(false); diff --git a/frontend/src/app/components/secrets/create-secret-dialog/create-secret-dialog.component.css b/frontend/src/app/components/secrets/create-secret-dialog/create-secret-dialog.component.css index 8a7f2ee2f..6052b0629 100644 --- a/frontend/src/app/components/secrets/create-secret-dialog/create-secret-dialog.component.css +++ b/frontend/src/app/components/secrets/create-secret-dialog/create-secret-dialog.component.css @@ -3,6 +3,10 @@ margin-bottom: 16px; } +.full-width:first-child { + margin-top: 12px; +} + .master-encryption-section { margin-top: 8px; padding: 16px; diff --git a/frontend/src/app/components/sso/sso.component.css b/frontend/src/app/components/sso/sso.component.css index 8ef305607..d8c90e1a8 100644 --- a/frontend/src/app/components/sso/sso.component.css +++ b/frontend/src/app/components/sso/sso.component.css @@ -61,3 +61,37 @@ margin-top: 16px; padding-bottom: 32px; } + +.upgrade-required { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 48px 24px; +} + +.upgrade-required__icon { + font-size: 64px; + width: 64px; + height: 64px; + color: rgba(0, 0, 0, 0.38); + margin-bottom: 24px; +} + +@media (prefers-color-scheme: dark) { + .upgrade-required__icon { + color: rgba(255, 255, 255, 0.38); + } +} + +.upgrade-required__description { + color: rgba(0, 0, 0, 0.64); + margin-bottom: 24px; + max-width: 400px; +} + +@media (prefers-color-scheme: dark) { + .upgrade-required__description { + color: rgba(255, 255, 255, 0.7); + } +} diff --git a/frontend/src/app/components/sso/sso.component.html b/frontend/src/app/components/sso/sso.component.html index 44f63c41c..2fc00b01c 100644 --- a/frontend/src/app/components/sso/sso.component.html +++ b/frontend/src/app/components/sso/sso.component.html @@ -6,7 +6,20 @@ -
+ + +

SAML SSO Configuration

Configure SAML Single Sign-On for your organization.

diff --git a/frontend/src/app/components/sso/sso.component.spec.ts b/frontend/src/app/components/sso/sso.component.spec.ts index 3380fbb92..510354fc1 100644 --- a/frontend/src/app/components/sso/sso.component.spec.ts +++ b/frontend/src/app/components/sso/sso.component.spec.ts @@ -16,7 +16,7 @@ describe('SsoComponent', () => { name: 'Test Company', address: {}, portal_link: '', - subscriptionLevel: 'FREE_PLAN', + subscriptionLevel: 'ENTERPRISE_PLAN', connections: [], invitations: [], is_payment_method_added: false, diff --git a/frontend/src/app/components/sso/sso.component.ts b/frontend/src/app/components/sso/sso.component.ts index 8cf2f4925..5f63d544b 100644 --- a/frontend/src/app/components/sso/sso.component.ts +++ b/frontend/src/app/components/sso/sso.component.ts @@ -10,6 +10,7 @@ import { MatTooltipModule } from '@angular/material/tooltip'; import { RouterModule } from '@angular/router'; import { Title } from '@angular/platform-browser'; import { SamlConfig, Company } from 'src/app/models/company'; +import { SubscriptionPlans } from 'src/app/models/user'; import { CompanyService } from 'src/app/services/company.service'; import { AlertComponent } from '../ui-components/alert/alert.component'; import { ProfileSidebarComponent } from '../profile/profile-sidebar/profile-sidebar.component'; @@ -36,6 +37,7 @@ import { PlaceholderSsoComponent } from '../skeletons/placeholder-sso/placeholde }) export class SsoComponent implements OnInit { public company: Company = null; + public hasEnterprisePlan: boolean = false; public samlConfigInitial: SamlConfig = { name: '', @@ -71,9 +73,14 @@ export class SsoComponent implements OnInit { this._company.fetchCompany().subscribe(res => { this.company = res; - this._company.fetchSamlConfiguration(res.id).subscribe((config) => { - if (config.length) this.samlConfig = config[0]; - }); + this.hasEnterprisePlan = res.subscriptionLevel === SubscriptionPlans.enterprise || + res.subscriptionLevel === SubscriptionPlans.enterpriseAnnual; + + if (this.hasEnterprisePlan) { + this._company.fetchSamlConfiguration(res.id).subscribe((config) => { + if (config.length) this.samlConfig = config[0]; + }); + } }); } diff --git a/frontend/src/app/components/upgrade/upgrade.component.css b/frontend/src/app/components/upgrade/upgrade.component.css index 93eb52c4a..56c7feab2 100644 --- a/frontend/src/app/components/upgrade/upgrade.component.css +++ b/frontend/src/app/components/upgrade/upgrade.component.css @@ -28,6 +28,77 @@ width: clamp(300px, 90%, 840px); } +.current-plan-banner { + display: flex; + align-items: center; + justify-content: space-between; + padding: 20px 24px; + background: linear-gradient(135deg, var(--color-primaryPalette-50) 0%, var(--color-primaryPalette-100) 100%); + border-radius: 12px; + margin-bottom: 32px; +} + +@media (prefers-color-scheme: dark) { + .current-plan-banner { + background: linear-gradient(135deg, var(--color-primaryPalette-900) 0%, var(--color-primaryPalette-800) 100%); + } +} + +.current-plan-info { + display: flex; + flex-direction: column; + gap: 4px; +} + +.current-plan-label { + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.5px; + color: rgba(0, 0, 0, 0.64); +} + +@media (prefers-color-scheme: dark) { + .current-plan-label { + color: rgba(255, 255, 255, 0.64); + } +} + +.current-plan-name { + font-size: 24px; + font-weight: 500; + color: var(--color-primaryPalette-700); +} + +@media (prefers-color-scheme: dark) { + .current-plan-label { + color: rgba(255, 255, 255, 0.7); + } + + .current-plan-name { + color: #fff; + } +} + +.payment-settings-button { + display: flex; + align-items: center; + gap: 8px; +} + +.payment-settings-button mat-icon { + font-size: 20px; + width: 20px; + height: 20px; +} + +@media (width <= 600px) { + .current-plan-banner { + flex-direction: column; + align-items: flex-start; + gap: 16px; + } +} + .header { display: grid; grid-template-columns: 0 7fr repeat(3, 6fr); diff --git a/frontend/src/app/components/upgrade/upgrade.component.html b/frontend/src/app/components/upgrade/upgrade.component.html index 6b55fd8ba..cc638d404 100644 --- a/frontend/src/app/components/upgrade/upgrade.component.html +++ b/frontend/src/app/components/upgrade/upgrade.component.html @@ -1,16 +1,30 @@
- +
+
+
+ Current plan + {{ currentPlan.name }} +
+ + credit_card + Payment settings + +
+

- Manage plans + Compare plans

@@ -32,33 +46,35 @@

Current - - + + + - - Upgrade - - - Downgrade - + + Upgrade + + + Downgrade + +

diff --git a/frontend/src/app/components/upgrade/upgrade.component.ts b/frontend/src/app/components/upgrade/upgrade.component.ts index a0185a946..22f7419aa 100644 --- a/frontend/src/app/components/upgrade/upgrade.component.ts +++ b/frontend/src/app/components/upgrade/upgrade.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { AlertComponent } from '../ui-components/alert/alert.component'; import { CommonModule } from '@angular/common'; +import { CompanyMemberRole } from 'src/app/models/company'; import { CompanyService } from 'src/app/services/company.service'; import { MatButtonModule } from '@angular/material/button'; import { MatChipsModule } from '@angular/material/chips'; @@ -11,6 +12,7 @@ import { PaymentService } from 'src/app/services/payment.service'; import { PlanKey } from 'src/app/models/plans'; import { ProfileSidebarComponent } from '../profile/profile-sidebar/profile-sidebar.component'; import { RouterModule } from '@angular/router'; +import { UserService } from 'src/app/services/user.service'; import plans from '../../consts/plans'; @Component({ @@ -30,17 +32,16 @@ import plans from '../../consts/plans'; styleUrls: ['./upgrade.component.css'] }) export class UpgradeComponent implements OnInit { - public testAlert = { - type: 'info' as const, - message: 'This is a demo alert for the upgrade page.' - }; public currentPlan = { key: PlanKey.Free, price: 0, + name: 'Free', }; public hasPaymentMethod = false; + public portalLink: string = null; public companyId: string; public submitting = false; + public isAdmin = false; databases = [ { @@ -177,10 +178,14 @@ export class UpgradeComponent implements OnInit { constructor( private _paymentService: PaymentService, private _company: CompanyService, + private _userService: UserService, ) { } ngOnInit(): void { this.getCompanyPaln(); + this._userService.cast.subscribe((user) => { + this.isAdmin = user.role === CompanyMemberRole.CAO; + }); } getCompanyPaln() { @@ -188,6 +193,7 @@ export class UpgradeComponent implements OnInit { this.currentPlan = this.getPlan(company.subscriptionLevel); this.companyId = company.id; this.hasPaymentMethod = company.is_payment_method_added; + this.portalLink = company.portal_link; }) } @@ -198,10 +204,12 @@ export class UpgradeComponent implements OnInit { } currentPlanKey = currentPlanKey.slice(0, -5).toLowerCase(); + const planData = plans.find(plan => plan.key === currentPlanKey); return { key: currentPlanKey as PlanKey, - price: plans.find(plan => plan.key === currentPlanKey).price, + price: planData?.price || 0, + name: planData?.name || 'Free', }; } diff --git a/frontend/src/environments/environment.dev.ts b/frontend/src/environments/environment.dev.ts index 9490b3494..24d2881ea 100644 --- a/frontend/src/environments/environment.dev.ts +++ b/frontend/src/environments/environment.dev.ts @@ -1,6 +1,6 @@ export const environment = { production: false, - saas: false, + saas: true, apiRoot: 'https://app.rocketadmin.com/api', saasURL: 'https://app.rocketadmin.com', saasHostnames: ['localhost', '127.0.0.1'],