ソースを参照

Added billing page and integrated with ironplans

jnfrati 4 年 前
コミット
0f67464101

+ 66 - 0
dashboard/package-lock.json

@@ -2496,6 +2496,47 @@
       "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
       "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="
     },
+    "@ironplans/api": {
+      "version": "0.1.1-alpha.0",
+      "resolved": "https://registry.npmjs.org/@ironplans/api/-/api-0.1.1-alpha.0.tgz",
+      "integrity": "sha512-sOtVjG/9O67DSKnTBQr+z2JROQoDsM6FrU02jIYF1tet0ZsQlmxHXT7rWQh2bSrK7IIkhp+5wgUsfRHeexCr1g=="
+    },
+    "@ironplans/react": {
+      "version": "0.1.1-alpha.1",
+      "resolved": "https://registry.npmjs.org/@ironplans/react/-/react-0.1.1-alpha.1.tgz",
+      "integrity": "sha512-5uBZb9kgHdnG144znEGQGbpDo4y2Jy4xHZRegerhOhTyuFVaI8Yrm6xKJucFeDkQIQCh1NqeVTy8a+sPwQl2CQ==",
+      "requires": {
+        "@ironplans/sdk": "^0.1.1-alpha.1"
+      }
+    },
+    "@ironplans/sdk": {
+      "version": "0.1.1-alpha.1",
+      "resolved": "https://registry.npmjs.org/@ironplans/sdk/-/sdk-0.1.1-alpha.1.tgz",
+      "integrity": "sha512-8nno59ZRKju3KYNj9KBHL6xpltZPuIvfUBih14H4R1SpLtEprASy5eurK/Cdxgq3s7uwygU1ompyLKGtdB/ORg==",
+      "requires": {
+        "@ironplans/api": "^0.1.1-alpha.0",
+        "@ironplans/types": "^0.0.30-alpha.0",
+        "js-cookie": "^3.0.1",
+        "jwt-decode": "^3.1.2",
+        "micro-typed-events": "^1.0.2",
+        "qs": "^6.10.1"
+      },
+      "dependencies": {
+        "qs": {
+          "version": "6.10.1",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz",
+          "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==",
+          "requires": {
+            "side-channel": "^1.0.4"
+          }
+        }
+      }
+    },
+    "@ironplans/types": {
+      "version": "0.0.30-alpha.0",
+      "resolved": "https://registry.npmjs.org/@ironplans/types/-/types-0.0.30-alpha.0.tgz",
+      "integrity": "sha512-7goQ8VKTO2ra90j29ZFUiR1mz/Jpz/sqF1S7fEjgOjynL4DQc4P5qTb+to8QbZJQAUSha+vNesCsbN59iNTEUw=="
+    },
     "@jest/types": {
       "version": "24.9.0",
       "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz",
@@ -7839,6 +7880,11 @@
       "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.6.0.tgz",
       "integrity": "sha512-wVdUBYQeY2gY73RIlPrysvpYx+2vheGo8Y1SNQv/BzHToWpAZzJU7Z6uheKMAe+GLSBig5/Ps2nxg/8tRB73xg=="
     },
+    "js-cookie": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
+      "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7970,6 +8016,11 @@
         "jss": "10.5.1"
       }
     },
+    "jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "killable": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -8195,6 +8246,11 @@
       "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
       "dev": true
     },
+    "micro-typed-events": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/micro-typed-events/-/micro-typed-events-1.0.2.tgz",
+      "integrity": "sha512-YfSk2bMe6P4l0m/EMKF0wAsXAAtnsu/EHJ0yvTX8TwmKVokJZQYbd8VsJ7Hy+7lSwSt0b6QHD2F0e6VciJ5a8w=="
+    },
     "micromatch": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
@@ -10090,6 +10146,16 @@
       "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
       "dev": true
     },
+    "side-channel": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+      "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+      "requires": {
+        "call-bind": "^1.0.0",
+        "get-intrinsic": "^1.0.2",
+        "object-inspect": "^1.9.0"
+      }
+    },
     "signal-exit": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",

+ 1 - 0
dashboard/package.json

@@ -3,6 +3,7 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "@ironplans/react": "^0.1.1-alpha.1",
     "@material-ui/core": "^4.11.3",
     "@sentry/react": "^6.13.2",
     "@sentry/tracing": "^6.13.2",

+ 45 - 0
dashboard/src/main/home/project-settings/BillingPage.tsx

@@ -0,0 +1,45 @@
+import React, { useContext, useEffect, useState } from "react";
+import { CustomerProvider, PlanSelect } from "@ironplans/react";
+import api from "shared/api";
+import { Context } from "shared/Context";
+
+function BillingPage() {
+  const [customerToken, setCustomerToken] = useState("");
+  const { currentProject, setCurrentError } = useContext(Context);
+
+  useEffect(() => {
+    let isSubscripted = true;
+    api
+      .getCustomerToken("<token>", {}, { project_id: currentProject?.id })
+      .then((res) => {
+        if (isSubscripted) {
+          const token = res?.data?.token;
+          setCustomerToken(token);
+        }
+      })
+      .catch((err) => {
+        setCurrentError(err);
+      });
+    return () => {
+      isSubscripted = false;
+    };
+  }, [currentProject?.id]);
+
+  return (
+    <div style={{ height: "1000px" }}>
+      <CustomerProvider token={customerToken}>
+        <PlanSelect
+          theme={{
+            base: {
+              darkMode: "on",
+              primaryColor: "white",
+              fontFamily: "sans-serif",
+            },
+          }}
+        ></PlanSelect>
+      </CustomerProvider>
+    </div>
+  );
+}
+
+export default BillingPage;

+ 2 - 7
dashboard/src/main/home/project-settings/ProjectSettings.tsx

@@ -11,6 +11,7 @@ import TitleSection from "components/TitleSection";
 import { withAuth, WithAuthProps } from "shared/auth/AuthorizationHoc";
 import { RouteComponentProps, withRouter, WithRouterProps } from "react-router";
 import { getQueryParam } from "shared/routing";
+import BillingPage from "./BillingPage";
 
 type PropsType = RouteComponentProps & WithAuthProps & {};
 
@@ -69,13 +70,7 @@ class ProjectSettings extends Component<PropsType, StateType> {
     }
 
     if (this.state.currentTab === "billing") {
-      return (
-        <div>
-          <a href="https://www.youtube.com/watch?v=ETxmCCsMoD0&ab_channel=AbbaVEVO">
-            Money money money
-          </a>
-        </div>
-      );
+      return <BillingPage />;
     }
 
     if (this.state.currentTab === "manage-access") {

+ 7 - 0
dashboard/src/shared/api.tsx

@@ -1052,6 +1052,12 @@ const getUsage = baseApi<{}, { project_id: number }>(
   ({ project_id }) => `/api/projects/${project_id}/usage`
 );
 
+// Used for billing purposes
+const getCustomerToken = baseApi<{}, { project_id: number }>(
+  "GET",
+  ({ project_id }) => `/api/projects/${project_id}/billing/token`
+);
+
 // Bundle export to allow default api import (api.<method> is more readable)
 export default {
   checkAuth,
@@ -1158,4 +1164,5 @@ export default {
   getPolicyDocument,
   createWebhookToken,
   getUsage,
+  getCustomerToken,
 };