Path: blob/master/src/packages/frontend/account/upgrades/upgrades-page.tsx
1503 views
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Col, Panel, Row } from "@cocalc/frontend/antd-bootstrap";6import {7Component,8rclass,9redux,10rtypes,11} from "@cocalc/frontend/app-framework";12import { A, Icon, Loading, Gap } from "@cocalc/frontend/components";13import { appBasePath } from "@cocalc/frontend/customize/app-base-path";14import { plural, round1 } from "@cocalc/util/misc";15import { PROJECT_UPGRADES } from "@cocalc/util/schema";16import { Progress } from "antd";17import { Map } from "immutable";18import { join } from "path";19import { PolicyPricingPageUrl, SiteName } from "../../customize";20import "./project-upgrades-table";21import { ProjectUpgradesTable } from "./project-upgrades-table";22export { tmp as UpgradesPage };23declare var DEBUG: boolean;2425interface reduxProps {26stripe_customer?: Map<string, any>;27project_map?: Map<string, any>;28all_projects_have_been_loaded?: boolean;29}3031class UpgradesPage extends Component<reduxProps> {32static reduxProps() {33return {34projects: {35project_map: rtypes.immutable.Map,36all_projects_have_been_loaded: rtypes.bool,37},38account: {39stripe_customer: rtypes.immutable.Map,40},41};42}4344private render_no_upgrades(): React.JSX.Element {45return (46<div>47<h3>Upgrades are no longer available</h3>48Please visit <A href={join(appBasePath, "store")}>the new store</A>,49explore <A href={join(appBasePath, "pricing")}>our products</A>, or{" "}50<A href={join(appBasePath, "billing/subscriptions")}>51view your legacy upgrade subscriptions52</A>53.54</div>55);56}5758private render_have_upgrades(): React.JSX.Element {59return (60<div style={{ margin: "10px 0" }}>61<h3>62Thank you for supporting <SiteName />63</h3>64<div style={{ color: "#666" }}>65<p>66You have some now deprecated "quota upgrades". They are listed67below, along with how you have applied them to projects. You can68adjust your project upgrade contribution from the settings page in69any project.70</p>71<p>72Going forward, we offer many{" "}73<A href={PolicyPricingPageUrl}> pricing and subscription options</A>74, which you can subscribe to in the{" "}75<A href={join(appBasePath, "store")}>Store</A>.76</p>77</div>78<Gap />79</div>80);81}8283private render_upgrade(param, amount, used, darker): React.JSX.Element {84const info = PROJECT_UPGRADES.params[param];85const n = round1(amount != null ? info.display_factor * amount : 0);86let u = round1(used != null ? info.display_factor * used : 0);87if (u > n) {88u = n;89}90const percent_used = Math.round((u / n) * 100);91return (92<Row key={param} style={darker ? { backgroundColor: "#eee" } : undefined}>93<Col sm={2}>{info.display}</Col>94<Col sm={3}>95<Row>96<Col sm={5}>97{u != null ? (98<span>99{u} {plural(u, info.display_unit)}100</span>101) : undefined}102</Col>103<Col sm={7}>104<Progress percent={percent_used} />105</Col>106</Row>107</Col>108<Col sm={2}>109{n != null ? (110<span>111{n} {plural(n, info.display_unit)}112</span>113) : undefined}114</Col>115<Col sm={5} style={{ color: "#666" }}>116{info.desc}117</Col>118</Row>119);120}121122private render_upgrade_rows(upgrades, used): React.JSX.Element[] {123let i = 1;124const result: React.JSX.Element[] = [];125for (let prop of PROJECT_UPGRADES.field_order) {126const amount = upgrades[prop];127i += 1;128result.push(this.render_upgrade(prop, amount, used[prop], i % 2 === 0));129}130return result;131}132133private render_upgrades(): React.JSX.Element {134const upgrades = redux.getStore("account").get_total_upgrades();135const used = redux136.getStore("projects")137.get_total_upgrades_you_have_applied();138if (upgrades == null || used == null) {139return this.render_no_upgrades();140}141142// Ensure that all projects loaded -- this can change used above, which is fine,143// and would re-render this component. The issue is that it's conceivable you have144// a project nobody has touched for a month, which has upgrades applied to it.145redux.getActions("projects").load_all_projects();146147return (148<Panel149header={150<span>151<Icon name="tachometer-alt" /> Upgrades from your subscriptions and152course packages153</span>154}155>156<Row key="header">157<Col sm={2}>158<strong>Quota</strong>159</Col>160<Col sm={3}>161<strong>Used</strong>162</Col>163<Col sm={2}>164<strong>Purchased</strong>165</Col>166<Col sm={5}>167<strong>Description</strong>168</Col>169</Row>170{this.render_upgrade_rows(upgrades, used)}171</Panel>172);173}174175public render(): React.JSX.Element {176if (this.props.project_map == null) {177return <Loading theme={"medium"} />;178}179if (!this.props.all_projects_have_been_loaded) {180// See https://github.com/sagemathinc/cocalc/issues/3802181redux.getActions("projects").load_all_projects();182return <Loading theme={"medium"} />;183}184if (185!DEBUG &&186!this.props.stripe_customer?.getIn(["subscriptions", "total_count"])187) {188return this.render_no_upgrades();189} else {190return (191<div>192{this.render_have_upgrades()}193{this.render_upgrades()}194<ProjectUpgradesTable />195</div>196);197}198}199}200201const tmp = rclass(UpgradesPage);202203204