Skip to content

Commit

Permalink
make applying a license to a project slightly more discoverable
Browse files Browse the repository at this point in the history
  • Loading branch information
williamstein committed Oct 19, 2024
1 parent dfef472 commit b124b36
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 64 deletions.
19 changes: 8 additions & 11 deletions src/packages/frontend/account/licenses/licenses-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* License: MS-RSL – see LICENSE.md for details
*/

import { React } from "@cocalc/frontend/app-framework";
import { Footer } from "@cocalc/frontend/customize";
import { BuyLicenseForProject } from "@cocalc/frontend/site-licenses/purchase/buy-license-for-project";
import { DOC_LICENSE_URL } from "../../billing/data";
Expand All @@ -12,20 +11,23 @@ import { ProjectsWithLicenses } from "./projects-with-licenses";
import Next from "@cocalc/frontend/components/next";
import { A } from "@cocalc/frontend/components/A";

export const LicensesPage: React.FC = () => {
export function LicensesPage() {
return (
<div>
<div style={{ maxWidth: "1000px", margin: "auto" }}>
<div style={{ fontSize: "12pt" }}>
<h3>About</h3>
<A href={DOC_LICENSE_URL}>Licenses</A> allow you to automatically
upgrade projects whenever they start up, so that they have more memory,
better hosting, run faster, etc.
run faster, etc.
</div>
<br />
<div>
<BuyLicenseForProject />
<BuyLicenseForProject noVoucher />
</div>
<ManagedLicenses />
<ProjectsWithLicenses />
<div>
{/* kind of outdated */}
<h3>Links</h3>
<ul style={{ fontSize: "12pt" }}>
<li>
Expand All @@ -45,12 +47,7 @@ export const LicensesPage: React.FC = () => {
</li>
</ul>
</div>
<br />
<ManagedLicenses />
<br />
<ProjectsWithLicenses />
<br />
<Footer />
</div>
);
};
}
5 changes: 3 additions & 2 deletions src/packages/frontend/account/licenses/managed-licenses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const ManagedLicenses: React.FC = () => {
return (
<>
<Title level={3}>
Licenses that you manage {render_count()}
Licenses You Manage {render_count()}
<div style={{ float: "right" }}>{render_show_all()}</div>
{loading && <Spin />}
</Title>
Expand Down Expand Up @@ -148,7 +148,8 @@ function CancelSubscriptionBanner() {
visit the Subscription tab above
</a>
. To edit a license <i>that you purchased</i> expand the license
below, then click on the "Edit License..." button.
below, then click on the "Edit License..." button. To apply a license
to a project, select the project under Projects below.
</>
}
/>
Expand Down
61 changes: 35 additions & 26 deletions src/packages/frontend/account/licenses/projects-with-licenses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,27 @@
* License: MS-RSL – see LICENSE.md for details
*/

import { Row, Col } from "antd";
import {
React,
useMemo,
useTypedRedux,
useEffect,
redux,
} from "../../app-framework";
import { Alert, Row, Col } from "antd";
import { useEffect, useMemo, useState } from "react";
import { useTypedRedux, redux } from "../../app-framework";
import { Loading, TimeAgo } from "../../components";
import { projects_with_licenses } from "./util";
import { plural, trunc_middle } from "@cocalc/util/misc";
import { LICENSES_STYLE } from "./managed-licenses";
import { Virtuoso } from "react-virtuoso";
import { SelectProject } from "@cocalc/frontend/projects/select-project";
import { SiteLicense } from "@cocalc/frontend/project/settings/site-license";

function open_project(project_id: string): void {
redux.getActions("projects").open_project({ project_id });
redux.getProjectActions(project_id).set_active_tab("settings");
}

export const ProjectsWithLicenses: React.FC = () => {
export function ProjectsWithLicenses({}) {
const [project_id, setProjectId] = useState<string | undefined>(undefined);
const project_map = useTypedRedux("projects", "project_map");
const all_projects_have_been_loaded = useTypedRedux(
"projects",
"all_projects_have_been_loaded"
"all_projects_have_been_loaded",
);
const projects = useMemo(
() => projects_with_licenses(project_map),
[project_map]
[project_map],
);

useEffect(() => {
Expand All @@ -47,7 +40,7 @@ export const ProjectsWithLicenses: React.FC = () => {
key={projects[index]?.project_id}
style={{ borderBottom: "1px solid lightgrey", cursor: "pointer" }}
onClick={() => {
open_project(project_id);
setProjectId(project_id);
}}
>
<Col span={12} style={{ paddingLeft: "15px" }}>
Expand All @@ -74,7 +67,7 @@ export const ProjectsWithLicenses: React.FC = () => {
}
return (
<div
style={{ ...LICENSES_STYLE, height: "50vh" }}
style={{ ...LICENSES_STYLE, height: "175px", marginTop: "5px" }}
className={"smc-vfill"}
>
<Virtuoso
Expand All @@ -86,16 +79,32 @@ export const ProjectsWithLicenses: React.FC = () => {
);
}

function render_count() {
if (projects == null || projects.length == 0) return;
return <>({projects.length})</>;
}

return (
<div>
{" "}
<h3>Projects with licenses {render_count()}</h3>
<h3>Projects</h3>
<Alert
style={{ marginBottom: "15px" }}
banner
type="info"
message={
<>
Select a project below to add or remove a license from that project,
or to buy a license for that project.
</>
}
/>
<SelectProject value={project_id} onChange={setProjectId} />
{project_id && project_map && (
<SiteLicense
project_id={project_id}
site_license={project_map.getIn([project_id, "site_license"]) as any}
/>
)}
<div style={{ marginTop: "10px" }}>
The following {projects.length} {plural(projects.length, "project")}{" "}
have a license:
</div>
{render_projects_with_license()}
</div>
);
};
}
17 changes: 13 additions & 4 deletions src/packages/frontend/project/settings/site-license.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
} from "@cocalc/util/upgrades/quota";
import { isBoostLicense } from "@cocalc/util/upgrades/utils";
import { SiteLicense as SiteLicenseT } from "./types";
import { ProjectTitle } from "@cocalc/frontend/projects/project-title";

interface Props {
project_id: string;
Expand Down Expand Up @@ -60,8 +61,11 @@ export async function applyLicense(opts: ALOpts): Promise<void> {
}
}

export const SiteLicense: React.FC<Props> = (props: Props) => {
const { project_id, site_license, mode = "project" } = props;
export function SiteLicense({
project_id,
site_license,
mode = "project",
}: Props) {
const isFlyout = mode === "flyout";

const intl = useIntl();
Expand Down Expand Up @@ -191,7 +195,12 @@ export const SiteLicense: React.FC<Props> = (props: Props) => {
<Icon name="key" /> {intl.formatMessage(labels.licenses)}
{isFlyout ? (
<span style={{ float: "right" }}>{render_extra()}</span>
) : undefined}
) : (
<>
{" "}
- <ProjectTitle project_id={project_id} />
</>
)}
</Title>
);
}
Expand Down Expand Up @@ -267,4 +276,4 @@ export const SiteLicense: React.FC<Props> = (props: Props) => {
</Card>
);
}
};
}
7 changes: 5 additions & 2 deletions src/packages/frontend/project/settings/upgrade-usage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,11 @@ export const UpgradeUsage: React.FC<Props> = React.memo(
}

function render_site_license(): Rendered {
// site licenses are also used in on-prem setups to tweak project quotas
if (!in_kucalc) return;
if (!in_kucalc) {
// site licenses are also used in on-prem setups to tweak project quotas, but
// nowhere else (currently).
return;
}
return (
<SiteLicense
project_id={project_id}
Expand Down
20 changes: 7 additions & 13 deletions src/packages/frontend/projects/select-project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,7 @@
// Component for selecting a project.

import { Checkbox, Select } from "antd";
import {
CSS,
redux,
React,
useMemo,
useState,
useTypedRedux,
} from "../app-framework";
import { CSS, redux, useMemo, useState, useTypedRedux } from "../app-framework";
import { webapp_client } from "../webapp-client";
import { Loading } from "../components";

Expand All @@ -28,18 +21,18 @@ interface Props {
style?: CSS;
}

export const SelectProject: React.FC<Props> = ({
export function SelectProject({
exclude,
at_top,
onChange,
value,
defaultValue,
style,
}) => {
}: Props) {
const project_map = useTypedRedux("projects", "project_map");
const all_projects_have_been_loaded = useTypedRedux(
"projects",
"all_projects_have_been_loaded"
"all_projects_have_been_loaded",
);

// include deleted projects in the selector
Expand Down Expand Up @@ -106,7 +99,7 @@ export const SelectProject: React.FC<Props> = ({
}
}
return data.concat(others);
}, [project_map, exclude, at_top, include_deleted, include_hidden]);
}, [project_map, exclude, at_top, include_deleted, include_hidden, value]);

if (data == null) {
return <Loading />;
Expand All @@ -116,6 +109,7 @@ export const SelectProject: React.FC<Props> = ({
<div style={style}>
<div style={{ display: "flex", flexDirection: "row" }}>
<Select
allowClear
style={{ marginRight: "15px", flex: 1 }}
showSearch={true}
placeholder={"Select a project..."}
Expand Down Expand Up @@ -164,4 +158,4 @@ export const SelectProject: React.FC<Props> = ({
</div>
</div>
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import { Button, Space } from "antd";
import { join } from "path";

import { CSS, useTypedRedux } from "@cocalc/frontend/app-framework";
import { A, Icon } from "@cocalc/frontend/components";
import { appBasePath } from "@cocalc/frontend/customize/app-base-path";
Expand All @@ -20,17 +19,19 @@ interface Props {
style?: CSS;
size?: "small" | "middle" | "large";
wrap?: boolean;
noVoucher?: boolean;
}

export const BuyLicenseForProject: React.FC<Props> = ({
export function BuyLicenseForProject({
project_id,
buyText = "Buy a license",
voucherText = "Redeem a voucher",
asLink = false,
style,
size = "large",
wrap = false,
}: Props) => {
noVoucher,
}: Props) {
const commercial = useTypedRedux("customize", "commercial");

function url(path): string {
Expand Down Expand Up @@ -102,8 +103,8 @@ export const BuyLicenseForProject: React.FC<Props> = ({
return (
<Space wrap={wrap}>
{renderBuyButton()}
{renderVoucherButton()}
{!noVoucher && renderVoucherButton()}
</Space>
);
}
};
}
2 changes: 1 addition & 1 deletion src/packages/frontend/site-licenses/purchase/purchase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ export const PurchaseOneLicense: React.FC<Props> = React.memo(({ onClose }) => {
/>
You should see it listed under{" "}
<A href={join(appBasePath, "/licenses/managed")}>
Licenses that you manage
Licenses You Manage
</A>
.
</div>
Expand Down

0 comments on commit b124b36

Please sign in to comment.