diff --git a/src/renderer/components/layout/sidebar-cluster.module.css b/src/renderer/components/layout/sidebar-cluster.module.css new file mode 100644 index 0000000000..1bb61d27f9 --- /dev/null +++ b/src/renderer/components/layout/sidebar-cluster.module.css @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +.SidebarCluster { + display: flex; + align-items: center; + padding: 1.25rem; + cursor: pointer; + + &:focus-visible { + background: var(--blue); + color: white; + } + + &:hover { + background: var(--sidebarLogoBackground); + } +} + +.clusterName { + font-weight: bold; + overflow: hidden; + word-break: break-word; + color: var(--textColorAccent); + display: -webkit-box; + /* Simulate text-overflow:ellipsis styles but for multiple text lines */ + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; +} + +.menu { + width: 184px; + margin-top: -10px; +} \ No newline at end of file diff --git a/src/renderer/components/layout/sidebar-cluster.tsx b/src/renderer/components/layout/sidebar-cluster.tsx new file mode 100644 index 0000000000..9cf6367c25 --- /dev/null +++ b/src/renderer/components/layout/sidebar-cluster.tsx @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import styles from "./sidebar-cluster.module.css"; +import { observable } from "mobx"; +import React, { useState } from "react"; +import { HotbarStore } from "../../../common/hotbar-store"; +import { broadcastMessage } from "../../../common/ipc"; +import type { CatalogEntity, CatalogEntityContextMenu, CatalogEntityContextMenuContext } from "../../api/catalog-entity"; +import { IpcRendererNavigationEvents } from "../../navigation/events"; +import { Avatar } from "../avatar/avatar"; +import { Icon } from "../icon"; +import { navigate } from "../../navigation"; +import { Menu, MenuItem } from "../menu"; +import { ConfirmDialog } from "../confirm-dialog"; + +const contextMenu: CatalogEntityContextMenuContext = observable({ + menuItems: [], + navigate: (url: string, forceMainFrame = true) => { + if (forceMainFrame) { + broadcastMessage(IpcRendererNavigationEvents.NAVIGATE_IN_APP, url); + } else { + navigate(url); + } + }, +}); + +function onMenuItemClick(menuItem: CatalogEntityContextMenu) { + if (menuItem.confirm) { + ConfirmDialog.open({ + okButtonProps: { + primary: false, + accent: true, + }, + ok: () => { + menuItem.onClick(); + }, + message: menuItem.confirm.message, + }); + } else { + menuItem.onClick(); + } +} + +export function SidebarCluster({ clusterEntity }: { clusterEntity: CatalogEntity }) { + const [opened, setOpened] = useState(false); + + if (!clusterEntity) { + return null; + } + + const onMenuOpen = () => { + const hotbarStore = HotbarStore.getInstance(); + const isAddedToActive = HotbarStore.getInstance().isAddedToActive(clusterEntity); + const title = isAddedToActive + ? "Remove from Hotbar" + : "Add to Hotbar"; + const onClick = isAddedToActive + ? () => hotbarStore.removeFromHotbar(metadata.uid) + : () => hotbarStore.addToHotbar(clusterEntity); + + contextMenu.menuItems = [{ title, onClick }]; + clusterEntity.onContextMenuOpen(contextMenu); + + setOpened(true); + }; + + const toggle = () => { + setOpened(!opened); + }; + + const { metadata, spec } = clusterEntity; + const id = `cluster-${metadata.uid}`; + + return ( +
+ +
+ {metadata.name} +
+ + + { + contextMenu.menuItems.map((menuItem) => ( + onMenuItemClick(menuItem)}> + {menuItem.title} + + )) + } + +
+ ); +} diff --git a/src/renderer/components/layout/sidebar.module.css b/src/renderer/components/layout/sidebar.module.css index 2dbdf3d759..13f10c76a9 100644 --- a/src/renderer/components/layout/sidebar.module.css +++ b/src/renderer/components/layout/sidebar.module.css @@ -40,29 +40,3 @@ padding: 3px; border-radius: 50%; } - -.cluster { - display: flex; - align-items: center; - padding: 1.25rem; - cursor: pointer; - - &:focus-visible { - background: var(--blue); - color: white; - } - - &:hover { - background: var(--sidebarLogoBackground); - } -} - -.clusterName { - @apply font-bold overflow-hidden; - word-break: break-word; - color: var(--textColorAccent); - display: -webkit-box; - /* Simulate text-overflow:ellipsis styles but for multiple text lines */ - -webkit-line-clamp: 3; - -webkit-box-orient: vertical; -} diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx index 6b661c955f..a9a79c1d1b 100644 --- a/src/renderer/components/layout/sidebar.tsx +++ b/src/renderer/components/layout/sidebar.tsx @@ -47,6 +47,7 @@ import type { CatalogEntityContextMenuContext } from "../../../common/catalog"; import { HotbarStore } from "../../../common/hotbar-store"; import { broadcastMessage } from "../../../common/ipc"; import { IpcRendererNavigationEvents } from "../../navigation/events"; +import { SidebarCluster } from "./sidebar-cluster"; interface Props { className?: string; @@ -246,7 +247,8 @@ export class Sidebar extends React.Component { return (
- {this.renderCluster()} + {/* {this.renderCluster()} */} +