import "./hotbar-icon.scss"; import React, { DOMAttributes } from "react"; import { observer } from "mobx-react"; import { cssNames, IClassName, iter } from "../../utils"; import { Tooltip } from "../tooltip"; import { Avatar } from "@material-ui/core"; import { CatalogEntity, CatalogEntityContextMenu, CatalogEntityContextMenuContext } from "../../../common/catalog"; import { Menu, MenuItem } from "../menu"; import { Icon } from "../icon"; import { computed, observable } from "mobx"; import { navigate } from "../../navigation"; import { HotbarStore } from "../../../common/hotbar-store"; import { ConfirmDialog } from "../confirm-dialog"; import randomColor from "randomcolor"; import { catalogCategoryRegistry } from "../../api/catalog-category-registry"; import GraphemeSplitter from "grapheme-splitter"; interface Props extends DOMAttributes { entity: CatalogEntity; index: number; className?: IClassName; errorClass?: IClassName; isActive?: boolean; } function getNameParts(name: string): string[] { const byWhitespace = name.split(/\s+/); if (byWhitespace.length > 1) { return byWhitespace; } const byDashes = name.split(/[-_]+/); if (byDashes.length > 1) { return byDashes; } return name.split(/@+/); } @observer export class HotbarIcon extends React.Component { @observable.deep private contextMenu: CatalogEntityContextMenuContext; @observable menuOpen = false; componentDidMount() { this.contextMenu = { menuItems: [], navigate: (url: string) => navigate(url) }; } @computed get iconString() { const [rawFirst, rawSecond, rawThird] = getNameParts(this.props.entity.metadata.name); const splitter = new GraphemeSplitter(); const first = splitter.iterateGraphemes(rawFirst); const second = rawSecond ? splitter.iterateGraphemes(rawSecond): first; const third = rawThird ? splitter.iterateGraphemes(rawThird) : iter.newEmpty(); return [ ...iter.take(first, 1), ...iter.take(second, 1), ...iter.take(third, 1), ].filter(Boolean).join(""); } get kindIcon() { const className = "badge"; const category = catalogCategoryRegistry.getCategoryForEntity(this.props.entity); if (!category) { return ; } if (category.metadata.icon.includes("; } else { return ; } } get ledIcon() { const className = cssNames("led", { online: this.props.entity.status.phase == "connected"}); // TODO: make it more generic return
; } toggleMenu() { this.menuOpen = !this.menuOpen; } remove(item: CatalogEntity) { const hotbar = HotbarStore.getInstance(); hotbar.removeFromHotbar(item); } onMenuItemClick(menuItem: CatalogEntityContextMenu) { if (menuItem.confirm) { ConfirmDialog.open({ okButtonProps: { primary: false, accent: true, }, ok: () => { menuItem.onClick(); }, message: menuItem.confirm.message }); } else { menuItem.onClick(); } } generateAvatarStyle(entity: CatalogEntity): React.CSSProperties { return { "backgroundColor": randomColor({ seed: entity.metadata.name, luminosity: "dark" }) }; } render() { const { entity, errorClass, isActive, children, ...elemProps } = this.props; const entityIconId = `hotbar-icon-${this.props.index}`; const className = cssNames("HotbarIcon flex inline", this.props.className, { interactive: true, active: isActive, }); const onOpen = async () => { await entity.onContextMenuOpen(this.contextMenu); this.toggleMenu(); }; const menuItems = this.contextMenu?.menuItems.filter((menuItem) => !menuItem.onlyVisibleForSource || menuItem.onlyVisibleForSource === entity.metadata.source); return (
{entity.metadata.name} {this.iconString} { this.ledIcon } { this.kindIcon } onOpen()} close={() => this.toggleMenu()}> this.remove(entity) }> Remove from Hotbar { this.contextMenu && menuItems.map((menuItem) => { return ( this.onMenuItemClick(menuItem) }> {menuItem.title} ); })} {children}
); } }