(core) New URL that opens Create site popup.

Summary: Adding new url parameter for team site creation

Test Plan: Updated tests.

Reviewers: georgegevoian

Reviewed By: georgegevoian

Differential Revision: https://phab.getgrist.com/D3554
This commit is contained in:
Jarosław Sadziński 2022-08-03 12:48:01 +02:00
parent c359547f6b
commit 40c9b8b7e8
5 changed files with 35 additions and 8 deletions

View File

@ -226,6 +226,13 @@ export class AppModelImpl extends Disposable implements AppModel {
) {
super();
this._recordSignUpIfIsNewUser();
const state = urlState().state.get();
if (state.createTeam) {
// Remove params from the URL.
urlState().pushUrl({createTeam: false, params: {}}, {avoidReload: true, replace: true}).catch(() => {});
this.showNewSiteModal(state.params?.planType);
}
}
public get planName() {
@ -244,10 +251,11 @@ export class AppModelImpl extends Disposable implements AppModel {
}
}
public showNewSiteModal() {
public showNewSiteModal(selectedPlan?: string) {
if (this.planName) {
buildNewSiteModal(this, {
planName: this.planName,
selectedPlan,
onCreate: () => this.topAppModel.fetchUsersAndOrgs().catch(reportError)
});
}

View File

@ -10,7 +10,7 @@ import {BillingPlanManagers} from 'app/client/ui/BillingPlanManagers';
import {createForbiddenPage} from 'app/client/ui/errorPages';
import {leftPanelBasic} from 'app/client/ui/LeftPanelCommon';
import {pagePanels} from 'app/client/ui/PagePanels';
import {showTeamUpgradeConfirmation} from 'app/client/ui/ProductUpgrades';
import {NEW_DEAL, showTeamUpgradeConfirmation} from 'app/client/ui/ProductUpgrades';
import {createTopBarHome} from 'app/client/ui/TopBar';
import {cssBreadcrumbs, cssBreadcrumbsLink, separator} from 'app/client/ui2018/breadcrumbs';
import {bigBasicButton, bigBasicButtonLink, bigPrimaryButton} from 'app/client/ui2018/buttons';
@ -273,8 +273,8 @@ export class BillingPage extends Disposable {
!canManage ? null :
makeActionLink('Manage billing', 'Settings', this._model.getCustomerPortalUrl(), testId('portal-link')),
!wasTeam ? null :
makeActionButton('Downgrade plan', 'Settings',
() => this._confirmDowngradeToTeamFree(), testId('downgrade-free-link')),
dom.maybe(NEW_DEAL(), () => makeActionButton('Downgrade plan', 'Settings',
() => this._confirmDowngradeToTeamFree(), testId('downgrade-free-link'))),
!canRenew ? null :
makeActionLink('Renew subscription', 'Settings', this._model.renewPlan(), testId('renew-link')),
!canUpgrade ? null :

View File

@ -4,6 +4,7 @@ import {Disposable, DomContents, IDisposableOwner, Observable, observable} from
export function buildNewSiteModal(context: Disposable, options: {
planName: string,
selectedPlan?: string,
onCreate?: () => void
}) {
window.location.href = commonUrls.plans;

View File

@ -87,8 +87,10 @@ export interface IGristUrlState {
welcomeTour?: boolean;
docTour?: boolean;
manageUsers?: boolean;
createTeam?: boolean;
params?: {
billingPlan?: string;
planType?: string;
billingTask?: BillingTask;
embed?: boolean;
state?: string;
@ -258,6 +260,8 @@ export function encodeUrl(gristConfig: Partial<GristLoadConfig>,
url.hash = 'repeat-doc-tour';
} else if (state.manageUsers) {
url.hash = 'manage-users';
} else if (state.createTeam) {
url.hash = 'create-team';
} else {
url.hash = '';
}
@ -313,6 +317,7 @@ export function decodeUrl(gristConfig: Partial<GristLoadConfig>, location: Locat
if (map.has('account')) { state.account = AccountPage.parse(map.get('account')) || 'account'; }
if (map.has('billing')) { state.billing = BillingSubPage.parse(map.get('billing')) || 'billing'; }
if (map.has('welcome')) { state.welcome = WelcomePage.parse(map.get('welcome')); }
if (sp.has('planType')) { state.params!.planType = sp.get('planType')!; }
if (sp.has('billingPlan')) { state.params!.billingPlan = sp.get('billingPlan')!; }
if (sp.has('billingTask')) {
state.params!.billingTask = BillingTask.parse(sp.get('billingTask'));
@ -374,6 +379,7 @@ export function decodeUrl(gristConfig: Partial<GristLoadConfig>, location: Locat
state.welcomeTour = hashMap.get('#') === 'repeat-welcome-tour';
state.docTour = hashMap.get('#') === 'repeat-doc-tour';
state.manageUsers = hashMap.get('#') === 'manage-users';
state.createTeam = hashMap.get('#') === 'create-team';
}
return state;
}

View File

@ -4,6 +4,8 @@ import {encodeUrl, getSlugIfNeeded, GristLoadConfig, IGristUrlState, isOrgInPath
parseSubdomain, sanitizePathTail} from 'app/common/gristUrls';
import {getOrgUrlInfo} from 'app/common/gristUrls';
import {UserProfile} from 'app/common/LoginSessionAPI';
import {BillingTask} from 'app/common/BillingAPI';
import {TEAM_FREE_PLAN, TEAM_PLAN} from 'app/common/Features';
import {tbind} from 'app/common/tbind';
import * as version from 'app/common/version';
import {ApiServer, getOrgFromRequest} from 'app/gen-server/ApiServer';
@ -70,7 +72,6 @@ import {AddressInfo} from 'net';
import fetch from 'node-fetch';
import * as path from 'path';
import * as serveStatic from "serve-static";
import {BillingTask} from 'app/common/BillingAPI';
// Health checks are a little noisy in the logs, so we don't show them all.
// We show the first N health checks:
@ -1200,6 +1201,19 @@ export class FlexServer implements GristServer {
const url = `${getPrefix(req)}/api/billing/signup?planType=${planType}&billingPlan=${billingPlan}`;
return resp.redirect(url);
}));
// New landing page for the new NEW_DEAL.
this.app.get('/billing/create-team', ...middleware, expressWrap(async (req, resp, next) => {
const planType = optStringParam(req.query.planType) || '';
// Currently we have hardcoded support only for those two plans.
const supportedPlans = [TEAM_PLAN, TEAM_FREE_PLAN];
if (!supportedPlans.includes(planType)) {
return this._sendAppPage(req, resp, {path: 'error.html', status: 404, config: {errPage: 'not-found'}});
}
// Redirect to home page with url params
const url = `${getPrefix(req)}?planType=${planType}#create-team`;
return resp.redirect(url);
}));
}
/**
@ -1238,9 +1252,7 @@ export class FlexServer implements GristServer {
});
resp.status(200).send();
}),
// Add a final error handler that reports errors as JSON.
jsonErrorHandler);
}), jsonErrorHandler); // Add a final error handler that reports errors as JSON.
}
public finalize() {