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/next/components/account/navtab.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/* The "Account" navigation tab in the bar at the top. */67import type { MenuProps } from "antd";8import { Dropdown } from "antd";9import { join } from "path";10import { CSSProperties } from "react";1112import { Icon } from "@cocalc/frontend/components/icon";13import Avatar from "components/account/avatar";14import {15menuGroup,16menuItem,17MenuItem,18MenuItems,19} from "components/antd-menu-items";20import A from "components/misc/A";21import apiPost from "lib/api/post";22import basePath from "lib/base-path";23import { useCustomize } from "lib/customize";24import useProfile from "lib/hooks/profile";25import { useRouter } from "next/router";2627const DIVIDER = {28type: "divider",29} as const;3031interface Props {32style: CSSProperties;33}3435// We make this menu fixed width in all cases, since otherwise the entire top navbar36// would flicker when profile isn't initially defined. See37// https://github.com/sagemathinc/cocalc/issues/65043839const WIDTH = "125px";4041export default function AccountNavTab({ style }: Props) {42const router = useRouter();43const { isCommercial, shareServer, siteName, sshGateway } = useCustomize();44const profile = useProfile();45if (!profile) {46return (47<div48style={{49cursor: "pointer",50...style,51width: WIDTH,52}}53>54Account55</div>56);57}5859const { first_name, last_name, name, account_id, is_admin, is_anonymous } =60profile;6162const profile_url = name ? `/${name}` : `/share/accounts/${account_id}`;6364const signedIn = menuItem(65"signed-in",66<A href={is_anonymous ? "/config/search/input" : profile_url}>67Signed into {siteName} as68<br />69<b>70{first_name} {last_name}71{name ? ` (@${name})` : ""}72</b>73</A>74);7576const docs = menuItem(77"docs",78<A href="https://doc.cocalc.com" external>79Documentation80</A>,81"book"82);8384const configuration = menuGroup(85"configuration",86<A href="/config/search/input">87<span style={{ color: "#a4acb3" }}>88<Icon name="wrench" /> Configuration89</span>90</A>,91[92menuItem("account", <A href="/config/account/name">Account</A>, "user"),93menuItem(94"editor",95<A href="/config/editor/appearance">Editor</A>,96"edit"97),98menuItem(99"system",100<A href="/config/system/appearance">System</A>,101"gear"102),103]104);105106function profileItems() {107if (!profile) return [];108const ret: MenuItems = [];109ret.push(signedIn);110if (is_anonymous) {111ret.push(112menuItem(113"sign-up",114<A href="/config/search/input">115<b>Sign Up (save your work)!</b>116</A>,117"user"118)119);120}121ret.push(docs);122if (isCommercial) {123ret.push(menuItem("store", <A href="/store">Store</A>, "shopping-cart"));124}125ret.push(DIVIDER);126ret.push(configuration);127ret.push(DIVIDER);128return ret;129}130131function yourPages(): MenuItem[] {132const yours: MenuItem[] = [];133yours.push(134menuItem(135"projects",136<a href={join(basePath, "projects")}>137{is_anonymous ? "Project" : "Projects"}138</a>,139"edit"140)141);142143if (!is_anonymous) {144yours.push(menuItem("licenses", <A href="/licenses">Licenses</A>, "key"));145146if (isCommercial) {147yours.push(148menuItem(149"billing",150<A href="/billing">Billing Management</A>,151"credit-card"152)153);154}155if (sshGateway) {156yours.push(157menuItem(158"ssh",159<A href={join(basePath, "settings", "ssh-keys")} external>160SSH Keys161</A>,162"key"163)164);165}166167if (shareServer) {168yours.push(169menuItem(170"shared",171<A172href={173profile?.name ? `/${name}` : `/share/accounts/${account_id}`174}175external176>177Shared Files178</A>,179"bullhorn"180)181);182183yours.push(184menuItem("stars", <A href="/stars">Stars</A>, "star-filled")185);186}187}188189return [190menuGroup(191"your",192<span style={{ color: "#a4acb3" }}>193<Icon name="user" /> Your...194</span>,195yours196),197];198}199200function admin(): MenuItem[] {201if (!is_admin) return [];202return [203DIVIDER,204menuItem(205"admin",206<a href={join(basePath, "admin")}>Site Administration</a>,207"settings"208),209];210}211212const signout: MenuItem[] = [213DIVIDER,214menuItem(215"sign-out",216<A217onClick={async () => {218await apiPost("/accounts/sign-out", { all: false });219router.push("/");220}}221>222Sign Out223</A>224),225];226227const items: MenuProps["items"] = [228...profileItems(),229...yourPages(),230...admin(),231...signout,232];233234// NOTE: we had a dark theme before for the menu, but that's deprecated from antd235// https://github.com/ant-design/ant-design/issues/4903236return (237<div238style={{239display: "inline-block",240cursor: "pointer",241width: WIDTH,242}}243>244{/* The negative margin fixes some weird behavior that stretches header. */}245{account_id && (246<>247<Avatar account_id={account_id} style={{ margin: "-10px 0" }} />248 249</>250)}251<Dropdown menu={{ items }} trigger={["click"]}>252<span style={style}>Account ▼</span>253</Dropdown>254</div>255);256}257258259