diff --git a/src/packages/frontend/project/settings/compute-image-selector.tsx b/src/packages/frontend/project/settings/compute-image-selector.tsx index 462ff62c51..a74f6c665b 100644 --- a/src/packages/frontend/project/settings/compute-image-selector.tsx +++ b/src/packages/frontend/project/settings/compute-image-selector.tsx @@ -20,6 +20,7 @@ import { Row, Space, Spin, + Switch, } from "antd"; import { SizeType } from "antd/es/config-provider/SizeContext"; import { fromJS } from "immutable"; @@ -45,6 +46,7 @@ import { CancelText } from "@cocalc/frontend/i18n/components"; import { capitalize, unreachable } from "@cocalc/util/misc"; import { COLORS } from "@cocalc/util/theme"; import { SOFTWARE_ENVIRONMENT_ICON } from "./software-consts"; +import { ComputeImages } from "../../custom-software/init"; type MenuItem = Required["items"][number]; @@ -68,7 +70,7 @@ const img_sorter = (a, b): number => { interface ComputeImageSelectorProps { current_image: string; - layout: "horizontal" | "compact" | "dialog"; + layout: "horizontal" | "compact" | "dialog" | "dropdown"; onSelect: (img: string) => void; disabled?: boolean; size?: SizeType; @@ -91,6 +93,7 @@ export function ComputeImageSelector({ const disabled = propsDisabled ?? false; const size = propsSize ?? "small"; const label = propsLabel ?? capitalize(intl.formatMessage(labels.select)); + const [dropdownCustom, setDropdownCustom] = useState(false); // initialize with the given default const [nextImg, setNextImg] = useState(current_image); @@ -107,6 +110,11 @@ export function ComputeImageSelector({ "software", ); + const images: ComputeImages | undefined = useTypedRedux( + "compute_images", + "images", + ); + if (software_envs === undefined) { return ; } @@ -160,9 +168,11 @@ export function ComputeImageSelector({ } function render_menu_group(group: string): MenuItem { + const children = render_menu_children(group); + if (children.length === 0) return null; return { key: group, - children: render_menu_children(group), + children, label: group, type: "group", }; @@ -174,7 +184,12 @@ export function ComputeImageSelector({ function getMenu() { return { - onClick: (e) => (layout === "dialog" ? setNextImg : onSelect)(e.key), + onClick: (e) => { + setNextImg(e.key); + if (layout !== "dialog") { + onSelect(e.key); + } + }, style: { maxHeight: "50vh", overflow: "auto" }, items: menu_items(), }; @@ -190,6 +205,22 @@ export function ComputeImageSelector({ ); } + function render_dropdown_custom() { + if (!isCoCalcCom) return null; + return ( + + + help + + ); + } + function render_doubt() { return ( @@ -364,7 +395,6 @@ export function ComputeImageSelector({ case "compact": return render_selector(); case "horizontal": - // used in projects → create new project return ( @@ -378,6 +408,23 @@ export function ComputeImageSelector({ ); + // used in projects → create new project + case "dropdown": + return ( + + + + + {render_selector()} + + {render_dropdown_custom()} + + + {render_info(nextImg)} +
{JSON.stringify(images?.toJS(), null, 2)}
+ +
+ ); // successor of "vertical", where there is a dialog with a clear indication to click a button case "dialog": return ( diff --git a/src/packages/frontend/projects/create-project.tsx b/src/packages/frontend/projects/create-project.tsx index e12a15cc26..7e2d44c343 100644 --- a/src/packages/frontend/projects/create-project.tsx +++ b/src/packages/frontend/projects/create-project.tsx @@ -10,6 +10,7 @@ Create a new project import { Button, Card, Col, Form, Input, Row, Space } from "antd"; import { delay } from "awaiting"; import { useIntl } from "react-intl"; + import { Alert, Well } from "@cocalc/frontend/antd-bootstrap"; import { CSS, @@ -29,9 +30,11 @@ import { SoftwareEnvironmentState, } from "@cocalc/frontend/custom-software/selector"; import { labels } from "@cocalc/frontend/i18n"; +import { ComputeImageSelector } from "@cocalc/frontend/project/settings/compute-image-selector"; import { SiteLicenseInput } from "@cocalc/frontend/site-licenses/input"; import { BuyLicenseForProject } from "@cocalc/frontend/site-licenses/purchase/buy-license-for-project"; import track from "@cocalc/frontend/user-tracking"; +import { DEFAULT_COMPUTE_IMAGE } from "@cocalc/util/db-schema"; import { KUCALC_COCALC_COM, KUCALC_ON_PREMISES, @@ -61,7 +64,6 @@ export const NewProjectCreator: React.FC = ({ ); const [title_text, set_title_text] = useState(default_value ?? ""); const [error, set_error] = useState(""); - const [show_advanced, set_show_advanced] = useState(false); const [title_prefill, set_title_prefill] = useState(false); const [license_id, set_license_id] = useState(""); const [custom_software, set_custom_software] = @@ -82,6 +84,15 @@ export const NewProjectCreator: React.FC = ({ [customize_kucalc], ); + const customize_software = useTypedRedux("customize", "software"); + const [default_software_img, software_images] = useMemo( + () => [ + customize_software.get("default"), + customize_software.get("environments"), + ], + [customize_software], + ); + const [form] = Form.useForm(); useEffect(() => { @@ -112,7 +123,6 @@ export const NewProjectCreator: React.FC = ({ set_title_text(default_value ?? ""); set_error(""); set_custom_software({}); - set_show_advanced(false); set_show_add_license(requireLicense); set_title_prefill(true); set_license_id(""); @@ -267,15 +277,33 @@ export const NewProjectCreator: React.FC = ({ set_custom_software(obj); } - function render_advanced() { - if (!show_advanced) return; + function render_customize_software_env() { return ( - - - + <> + + { + const display = software_images.get(img)?.get("title"); + custom_software_on_change({ + image_selected: img, + title_text: display, + image_type: "standard", + }); + }} + changing={false} + label={"set"} + /> + + + + + + ); } @@ -284,63 +312,44 @@ export const NewProjectCreator: React.FC = ({ } function render_add_license() { - if (!show_add_license) return; - return ( - -
- -
- Select License - - } - style={CARD_STYLE} - > - -
- ); - } - - function render_advanced_toggle(): JSX.Element | undefined { - // we only support custom images on cocalc.com and onprem if (!show) return; - if (show_advanced) return; - return ( -
- -
- ); - } - - function render_add_license_toggle(): JSX.Element | undefined { - if (!show) return; - if (show_add_license) return; - return ( -
- +
+ ); + } else { + return ( + +
+ +
+ Select License + + } + style={CARD_STYLE} > - Add a license key... - - - ); + +
+ ); + } } function render_license() { @@ -381,6 +390,7 @@ export const NewProjectCreator: React.FC = ({ message: helpTxt, }, ]} + help={"You can change the title at any time."} > = ({ /> -
- You can change the title at any time. -
@@ -412,18 +419,13 @@ export const NewProjectCreator: React.FC = ({
- {render_add_license_toggle()} + {render_customize_software_env()} {render_add_license()} {render_license()} - {render_advanced_toggle()} - {render_advanced()} -