Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/frontend/account/upgrades/upgrades-page.tsx
Views: 687
/*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 { Footer, 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(): JSX.Element {45return (46<div>47<h3>Upgrades are no longer available</h3>48Please visit <A href={join(appBasePath, "store")}>49the new store50</A>, explore <A href={join(appBasePath, "pricing")}>our products</A>, or{" "}51<A href={join(appBasePath, "billing/subscriptions")}>52view your legacy upgrade subscriptions53</A>54.55<Footer />56</div>57);58}5960private render_have_upgrades(): JSX.Element {61return (62<div style={{ margin: "10px 0" }}>63<h3>64Thank you for supporting <SiteName />65</h3>66<div style={{ color: "#666" }}>67<p>68You have some now deprecated "quota upgrades". They are listed69below, along with how you have applied them to projects. You can70adjust your project upgrade contribution from the settings page in71any project.72</p>73<p>74Going forward, we offer many{" "}75<A href={PolicyPricingPageUrl}> pricing and subscription options</A>76, which you can subscribe to in the{" "}77<A href={join(appBasePath, "store")}>Store</A>.78</p>79</div>80<Gap />81</div>82);83}8485private render_upgrade(param, amount, used, darker): JSX.Element {86const info = PROJECT_UPGRADES.params[param];87const n = round1(amount != null ? info.display_factor * amount : 0);88let u = round1(used != null ? info.display_factor * used : 0);89if (u > n) {90u = n;91}92const percent_used = Math.round((u / n) * 100);93return (94<Row key={param} style={darker ? { backgroundColor: "#eee" } : undefined}>95<Col sm={2}>{info.display}</Col>96<Col sm={3}>97<Row>98<Col sm={5}>99{u != null ? (100<span>101{u} {plural(u, info.display_unit)}102</span>103) : undefined}104</Col>105<Col sm={7}>106<Progress percent={percent_used} />107</Col>108</Row>109</Col>110<Col sm={2}>111{n != null ? (112<span>113{n} {plural(n, info.display_unit)}114</span>115) : undefined}116</Col>117<Col sm={5} style={{ color: "#666" }}>118{info.desc}119</Col>120</Row>121);122}123124private render_upgrade_rows(upgrades, used): JSX.Element[] {125let i = 1;126const result: JSX.Element[] = [];127for (let prop of PROJECT_UPGRADES.field_order) {128const amount = upgrades[prop];129i += 1;130result.push(this.render_upgrade(prop, amount, used[prop], i % 2 === 0));131}132return result;133}134135private render_upgrades(): JSX.Element {136const upgrades = redux.getStore("account").get_total_upgrades();137const used = redux138.getStore("projects")139.get_total_upgrades_you_have_applied();140if (upgrades == null || used == null) {141return this.render_no_upgrades();142}143144// Ensure that all projects loaded -- this can change used above, which is fine,145// and would re-render this component. The issue is that it's conceivable you have146// a project nobody has touched for a month, which has upgrades applied to it.147redux.getActions("projects").load_all_projects();148149return (150<Panel151header={152<span>153<Icon name="tachometer-alt" /> Upgrades from your subscriptions and154course packages155</span>156}157>158<Row key="header">159<Col sm={2}>160<strong>Quota</strong>161</Col>162<Col sm={3}>163<strong>Used</strong>164</Col>165<Col sm={2}>166<strong>Purchased</strong>167</Col>168<Col sm={5}>169<strong>Description</strong>170</Col>171</Row>172{this.render_upgrade_rows(upgrades, used)}173</Panel>174);175}176177public render(): JSX.Element {178if (this.props.project_map == null) {179return <Loading theme={"medium"} />;180}181if (!this.props.all_projects_have_been_loaded) {182// See https://github.com/sagemathinc/cocalc/issues/3802183redux.getActions("projects").load_all_projects();184return <Loading theme={"medium"} />;185}186if (187!DEBUG &&188!this.props.stripe_customer?.getIn(["subscriptions", "total_count"])189) {190return this.render_no_upgrades();191} else {192return (193<div>194{this.render_have_upgrades()}195{this.render_upgrades()}196<ProjectUpgradesTable />197</div>198);199}200}201}202203const tmp = rclass(UpgradesPage);204205206