diff --git a/components/dashboard/package.json b/components/dashboard/package.json index a7b306441b3a3d..87788a7848399f 100644 --- a/components/dashboard/package.json +++ b/components/dashboard/package.json @@ -5,6 +5,7 @@ "private": true, "dependencies": { "@gitpod/gitpod-protocol": "0.1.5", + "countries-list": "^2.6.1", "moment": "^2.29.1", "react": "^17.0.1", "react-dom": "^17.0.1", diff --git a/components/dashboard/src/Login.tsx b/components/dashboard/src/Login.tsx index 4c251bb54798dc..f3cd1747ac6ef8 100644 --- a/components/dashboard/src/Login.tsx +++ b/components/dashboard/src/Login.tsx @@ -4,12 +4,13 @@ * See License-AGPL.txt in the project root for license information. */ -import { gitpod, gitpodIcon } from './images'; import { AuthProviderInfo } from "@gitpod/gitpod-protocol"; import { useContext, useEffect, useState } from "react"; import { UserContext } from "./user-context"; import { getGitpodService, gitpodHostUrl, reconnectGitpodService } from "./service/service"; import { iconForAuthProvider, simplifyProviderName } from "./provider-utils"; +import gitpod from './images/gitpod.svg'; +import gitpodIcon from './icons/gitpod.svg'; import automate from "./images/welcome/automate.svg"; import code from "./images/welcome/code.svg"; import collaborate from "./images/welcome/collaborate.svg"; diff --git a/components/dashboard/src/chargebee/chargebee-client.ts b/components/dashboard/src/chargebee/chargebee-client.ts new file mode 100644 index 00000000000000..0efdce333dbc81 --- /dev/null +++ b/components/dashboard/src/chargebee/chargebee-client.ts @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2021 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +import * as chargebee from 'chargebee'; + +import { Without } from '@gitpod/gitpod-protocol/lib/util/without'; +import { GitpodServer } from '@gitpod/gitpod-protocol'; +import { getGitpodService } from '../service/service'; + +class ChargebeeClientProvider { + protected static client: chargebee.Client; + + static async get() { + if (!this.client) { + await new Promise((resolve) => { + var scriptTag = document.createElement('script'); + scriptTag.src = "https://js.chargebee.com/v2/chargebee.js"; + scriptTag.async = true; + scriptTag.addEventListener("load", () => { + resolve(); + }); + document.head.appendChild(scriptTag); + }) + const site = await getGitpodService().server.getChargebeeSiteId(); + this.client = (((window as any).Chargebee) as chargebee.Client).init({ + site + }); + } + return this.client; + } +} + +export interface OpenPortalParams { + loaded?: () => void; + close?: () => void; + visit?: (sectionName: string) => void; +} + +// https://www.chargebee.com/checkout-portal-docs/api.html +export class ChargebeeClient { + constructor(protected readonly client: chargebee.Client) {} + + static async getOrCreate(): Promise { + const create = async () => { + const chargebeeClient = await ChargebeeClientProvider.get(); + const client = new ChargebeeClient(chargebeeClient); + client.createPortalSession(); + return client; + }; + + const w = window as any; + const _gp = w._gp || (w._gp = {}); + const chargebeeClient = _gp.chargebeeClient || (_gp.chargebeeClient = await create()); + return chargebeeClient; + } + + checkout(hostedPage: (paymentServer: GitpodServer) => Promise<{}>, params: Without = { success: noOp }) { + const paymentServer = getGitpodService().server; + this.client.openCheckout({ + ...params, + async hostedPage(): Promise { + return hostedPage(paymentServer); + } + }); + } + + checkoutExisting(hostedPage: (paymentServer: GitpodServer) => Promise<{}>, params: Without = { success: noOp }) { + const paymentServer = getGitpodService().server; + this.client.openCheckout({ + ...params, + async hostedPage(): Promise { + return hostedPage(paymentServer); + } + }); + } + + createPortalSession() { + const paymentServer = getGitpodService().server; + this.client.setPortalSession(async () => { + return paymentServer.createPortalSession(); + }); + } + + openPortal(params: OpenPortalParams = {}) { + this.client.createChargebeePortal().open(params); + } +} +const noOp = () => { /* tslint:disable:no-empty */ }; \ No newline at end of file diff --git a/components/dashboard/src/chargebee/chargebee.d.ts b/components/dashboard/src/chargebee/chargebee.d.ts new file mode 100644 index 00000000000000..bf1710b264a0dd --- /dev/null +++ b/components/dashboard/src/chargebee/chargebee.d.ts @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2021 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License-AGPL.txt in the project root for license information. + */ + +declare module 'chargebee' { + + export interface Client { + init(options: object): Client; + openCheckout(callbacks: CheckoutCallbacks); + setPortalSession(callback: () => Promise); + createChargebeePortal(): Portal; + } + + export interface CheckoutCallbacks { + hostedPage(): Promise; + success(hostedPageId: string); + loaded?: () => void; + error?: (error: any) => void; + step?: (step: string) => void; + close?: () => void; + } + + export interface OpenCheckoutParams { + +} + + export interface Portal { + open(callbacks: object); + } +} \ No newline at end of file diff --git a/components/dashboard/src/components/Menu.tsx b/components/dashboard/src/components/Menu.tsx index a079c0303a32f3..3816f9804e59cc 100644 --- a/components/dashboard/src/components/Menu.tsx +++ b/components/dashboard/src/components/Menu.tsx @@ -7,10 +7,10 @@ import { User } from "@gitpod/gitpod-protocol"; import { useContext } from "react"; import { Link } from "react-router-dom"; +import gitpodIcon from '../icons/gitpod.svg'; import { gitpodHostUrl } from "../service/service"; import { UserContext } from "../user-context"; import ContextMenu from "./ContextMenu"; -import * as images from '../images'; import { useLocation } from "react-router"; interface Entry { title: string, link: string, alternatives?: string[] @@ -44,7 +44,7 @@ function Menu(props: { left: Entry[], right: Entry[] }) {
- +