@ant-design/icons#LogoutOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#LogoutOutlined. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Header.tsx    From wildduck-ui with MIT License 6 votes vote down vote up
Header = () => {
	const { setAccessToken } = useActions(appLogic);
	const logout = () => {
		sessionStorage.removeItem(accessTokenString);
		sessionStorage.removeItem(apiString);
		setAccessToken('');
	};

	/** Header Renderer */
	return (
		<Layout.Header className='header'>
			<WildDuckIcon />
			<Tooltip title='Logout'>
				<Button shape='circle' onClick={logout} icon={<LogoutOutlined />}></Button>
			</Tooltip>
		</Layout.Header>
	);
}
Example #2
Source File: Logout.tsx    From mayoor with MIT License 6 votes vote down vote up
Logout: React.FC = () => {
	const dispatch = useAppDispatch();
	const { t } = useTranslation();

	const onLogoutClick = () => {
		localStorage.removeItem('auth-token');
		dispatch({ type: 'SET_CURRENT_USER', user: null });
	};
	return (
		<Tooltip placement="bottomRight" title={t('Log Out')}>
			<Button onClick={onLogoutClick} icon={<LogoutOutlined />} type="link" shape="circle" />
		</Tooltip>
	);
}
Example #3
Source File: Header.tsx    From nodestatus with MIT License 6 votes vote down vote up
Header: FC<Props> = props => {
  const navigate = useNavigate();
  const { isCollapsed, toggleCollapsed } = props.collapsed;

  const menu = (
    <Menu
      items={[
        {
          key: 'logout',
          label: 'Logout',
          icon: <LogoutOutlined className="mr-2 align-middle" />,
          className: 'align-middle'
        }
      ]}
      onClick={({ key }) => {
        if (key === 'logout') {
          localStorage.removeItem('token');
          navigate('/login');
        }
      }}
    />
  );

  return (
    <div className="h-full flex items-center justify-between">
      {React.createElement(isCollapsed ? MenuUnfoldOutlined : MenuFoldOutlined, {
        className: 'text-2xl',
        onClick: toggleCollapsed
      })}
      <Dropdown overlay={menu} placement="bottom">
        <Avatar size={40} icon={<UserOutlined />} />
      </Dropdown>
    </div>
  );
}
Example #4
Source File: AppHeader.tsx    From jmix-frontend with Apache License 2.0 5 votes vote down vote up
AppHeader = observer(({ children }: { children?: React.ReactNode }) => {
  const intl = useIntl();
  const mainStore = useMainStore();

  const [settingsEnabled, setSettingsEnabled] = useState(false);

  const [visibleHotkeyInfo, setVisibleHotkeyInfo] = useState(false);

  const toggleHotkeyInfo = useCallback<KeyHandler>(
    () => setVisibleHotkeyInfo(!visibleHotkeyInfo),
    [visibleHotkeyInfo]
  );
  useHotkey(toggleHotkeyInfoHotkeyConfig, toggleHotkeyInfo);

  const toggleSettings = useCallback(() => {
    setSettingsEnabled(isEnabled => {
      return !isEnabled;
    });
  }, []);

  const showLogoutConfirm = useCallback(() => {
    modals.open({
      content: intl.formatMessage({ id: "header.logout.areYouSure" }),
      okText: intl.formatMessage({ id: "header.logout.ok" }),
      cancelText: intl.formatMessage({ id: "header.logout.cancel" }),
      onOk: () => mainStore.logout()
    });
  }, [mainStore, intl]);

  return (
    <div className={styles.header}>
      <JmixLightIcon className={styles.icon} />

      <div className={styles.content}>{children}</div>
      <>
        {settingsEnabled && (
          <>
            <ThemeSwitcher className={styles.themeSwitcher} />
            <LanguageSwitcher className={styles.languageSwitcher} />
          </>
        )}
      </>
      <Space className={styles.userPanel}>
        <span>{mainStore.userName}</span>
        <Button
          className={classNames(
            settingsEnabled ? styles.settingsBtnActive : styles.settingsBtn,
            appStyles.focusOuterHighlight
          )}
          type={"text"}
          icon={<SettingOutlined role={""} />}
          onClick={toggleSettings}
          role={"switch"}
          aria-checked={settingsEnabled}
        />
        <HotkeyInfoModalButton
          visible={visibleHotkeyInfo}
          setVisible={setVisibleHotkeyInfo}
          className={classNames(styles.infoBtn, appStyles.focusOuterHighlight)}
        />
        <Button
          id="button_logout"
          className={classNames(
            styles.logoutBtn,
            appStyles.focusOuterHighlight
          )}
          type="text"
          icon={<LogoutOutlined role={""} />}
          onClick={showLogoutConfirm}
        />
      </Space>
    </div>
  );
})
Example #5
Source File: AvatarDropdown.tsx    From anew-server with MIT License 5 votes vote down vote up
AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
  const { initialState, setInitialState } = useModel('@@initialState');

  const onMenuClick = useCallback(
    (event: MenuInfo) => {
      const { key } = event;
      if (key === 'logout' && initialState) {
        setInitialState({ ...initialState, currentUser: undefined });
        loginOut();
        return;
      }
      history.push('/account/settings');
    },
    [initialState, setInitialState],
  );

  const loading = (
    <span className={`${styles.action} ${styles.account}`}>
      <Spin
        size="small"
        style={{
          marginLeft: 8,
          marginRight: 8,
        }}
      />
    </span>
  );

  if (!initialState) {
    return loading;
  }

  const { currentUser } = initialState;

  if (!currentUser || !currentUser.name) {
    return loading;
  }

  const menuHeaderDropdown = (
    <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
      {menu && (
        <Menu.Item key="settings">
          <SettingOutlined />
          个人设置
        </Menu.Item>
      )}
      {menu && <Menu.Divider />}

      <Menu.Item key="logout">
        <LogoutOutlined />
        退出登录
      </Menu.Item>
    </Menu>
  );
  return (
    <HeaderDropdown overlay={menuHeaderDropdown}>
      <span className={`${styles.action} ${styles.account}`}>
        <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
        <span className={`${styles.name} anticon`}>{currentUser.name}</span>
      </span>
    </HeaderDropdown>
  );
}
Example #6
Source File: AvatarDropdown.tsx    From ant-design-pro-V5-multitab with MIT License 5 votes vote down vote up
AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
  const { initialState, setInitialState } = useModel('@@initialState');

  const onMenuClick = useCallback(
    (event: {
      key: React.Key;
      keyPath: React.Key[];
      item: React.ReactInstance;
      domEvent: React.MouseEvent<HTMLElement>;
    }) => {
      const { key } = event;
      if (key === 'logout' && initialState) {
        setInitialState({ ...initialState, currentUser: undefined });
        loginOut();
        return;
      }
      history.push(`/account/${key}`);
    },
    [initialState, setInitialState],
  );

  const loading = (
    <span className={`${styles.action} ${styles.account}`}>
      <Spin
        size="small"
        style={{
          marginLeft: 8,
          marginRight: 8,
        }}
      />
    </span>
  );

  if (!initialState) {
    return loading;
  }

  const { currentUser } = initialState;

  if (!currentUser || !currentUser.name) {
    return loading;
  }

  const menuHeaderDropdown = (
    <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
      {menu && (
        <Menu.Item key="center">
          <UserOutlined />
          个人中心
        </Menu.Item>
      )}
      {menu && (
        <Menu.Item key="settings">
          <SettingOutlined />
          个人设置
        </Menu.Item>
      )}
      {menu && <Menu.Divider />}

      <Menu.Item key="logout">
        <LogoutOutlined />
        退出登录
      </Menu.Item>
    </Menu>
  );
  return (
    <HeaderDropdown overlay={menuHeaderDropdown}>
      <span className={`${styles.action} ${styles.account}`}>
        <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
        <span className={`${styles.name} anticon`}>{currentUser.name}</span>
      </span>
    </HeaderDropdown>
  );
}
Example #7
Source File: ManageActions.tsx    From wildduck-ui with MIT License 5 votes vote down vote up
ManageActions: React.SFC<ManageActionsProps> = (props: ManageActionsProps) => {
	const { setShowResetPasswordModal, setPassword } = useActions(usersLogic);

	const { mutate: recalculateQuota } = useRecalculateQuota();
	const { mutate: logoutUser } = useLogoutUser();
	const { mutate } = useUpdateUserDetails();
	const { mutate: resetPassword, data } = useResetPassword();

	const { user } = props;

	React.useEffect(() => {
		if (!_.isEmpty(data)) {
			setPassword(_.get(data, 'data.password'));
			mutate({
				userId: user.id,
				userDetails: { password: _.get(data, 'data.password'), disabledScopes: [] },
			});
			setShowResetPasswordModal(true);
		}
	}, [data]);

	const Actions = () => {
		return (
			<Space size={'middle'}>
				<Tooltip title={'Logout User'}>
					<Button className='ant-btn-icon' shape='circle' onClick={() => logoutUser(user.id)}>
						<LogoutOutlined />
					</Button>
				</Tooltip>
				<Tooltip title={'Recalculate Quota'}>
					<Button className='ant-btn-icon' shape='circle' onClick={() => recalculateQuota(user.id)}>
						<RecalculateQuotaIcon />
					</Button>
				</Tooltip>
				<Tooltip title={'Reset Password'}>
					<Button
						className='ant-btn-icon'
						shape='circle'
						onClick={() =>
							showConfirm(() => {
								resetPassword(user.id);
							})
						}
					>
						<ResetPasswordIcon />
					</Button>
				</Tooltip>
			</Space>
		);
	};

	return (
		<Popover content={<Actions />} trigger='hover'>
			<Button type='link'>Manage</Button>
		</Popover>
	);
}
Example #8
Source File: ProfileDrawer.tsx    From office-hours with GNU General Public License v3.0 5 votes vote down vote up
export default function ProfileDrawer({
  courseId,
}: ProfileDrawerProps): ReactElement {
  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
  const role = useRoleInCourse(courseId);

  return (
    <>
      <NoPaddingPopover
        content={
          isPopoverOpen && (
            <Menu mode="inline">
              <Menu.Item icon={<SettingOutlined />}>
                <Link
                  href={{ pathname: "/settings", query: { cid: courseId } }}
                >
                  <a>Settings</a>
                </Link>
              </Menu.Item>
              <Menu.Item
                icon={<MacCommandOutlined />}
                onClick={() => {
                  Modal.info({
                    title: "Queue Page Keyboard Shortcuts",
                    content: shortcutInfoContent(role),
                  });
                  setIsPopoverOpen(false);
                }}
              >
                Keyboard Shortcuts
              </Menu.Item>
              <Menu.Item
                key="1"
                icon={<QuestionCircleOutlined />}
                onClick={() => {
                  window.open("https://info.khouryofficehours.com/help");
                  setIsPopoverOpen(false);
                }}
              >
                Help Guide
              </Menu.Item>
              <Menu.Item
                key="2"
                icon={<FileTextOutlined />}
                onClick={() => {
                  window.open(
                    "https://info.khouryofficehours.com/release-notes-archive"
                  );
                  setIsPopoverOpen(false);
                }}
              >
                Release Notes
              </Menu.Item>
              <Menu.Item key="3" icon={<ReadOutlined />}>
                <Link href={"/about"}>
                  <a>About Us</a>
                </Link>
              </Menu.Item>
              <Menu.Item key="4" icon={<LogoutOutlined />}>
                <Link href={"/api/v1/logout"}>
                  <a data-cy="logout-button">Logout</a>
                </Link>
              </Menu.Item>
            </Menu>
          )
        }
        placement="bottomRight"
        trigger="click"
        visible={isPopoverOpen}
        onVisibleChange={setIsPopoverOpen}
      >
        <AvatarButton>
          <SelfAvatar size={40} />
        </AvatarButton>
      </NoPaddingPopover>
    </>
  );
}
Example #9
Source File: StaffAdminAvatarDropdown.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
render(): React.ReactNode {
    const { menu, currentStaffAdmin } = this.props;

    const currentUser = {
      ...currentStaffAdmin,
    };

    const menuHeaderDropdown = (
      <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
        {menu && CanSee([BizRole_Full, BizRole_Read]) && (
          <Menu.Item
            key="settings"
          >
            <SettingOutlined />
            权限设置
          </Menu.Item>
        )}
        {menu && <Menu.Divider />}
        <Menu.Item key="logout">
          <LogoutOutlined />
          退出登录
        </Menu.Item>
      </Menu>
    );
    return currentUser && currentUser.name ? (
      <HeaderDropdown overlay={menuHeaderDropdown}>
        <span className={`${styles.action} ${styles.account}`}>
          <Avatar
            size="small"
            className={styles.avatar}
            src={currentUser.avatar_url}
            alt="avatar"
          />
          <span className={`${styles.name} anticon`}>{currentUser.name}</span>
        </span>
      </HeaderDropdown>
    ) : (
      <span className={`${styles.action} ${styles.account}`}>
        <Spin
          size="small"
          style={{
            marginLeft: 8,
            marginRight: 8,
          }}
        />
      </span>
    );
  }
Example #10
Source File: index.tsx    From tinyhouse with MIT License 5 votes vote down vote up
export function MenuItems({ viewer, setViewer }: MenuItemsProps) {
    const [logOut] = useMutation<LogOutData>(LOG_OUT, {
        onCompleted: (data) => {
            if (data && data.logOut) {
                setViewer(data.logOut);
                sessionStorage.removeItem("token");
                displaySuccessNotification("You've successfully logged out!");
            }
        },
        onError: (error) => {
            displayErrorMessage(
                "Sorry, we weren't able to to log you out. Please try again later!"
            );
        },
    });

    const handleLogout = async () => {
        await logOut();
    };

    const subMenuLogin =
        viewer.id && viewer.avatar ? (
            <SubMenu key={viewer.id} title={<Avatar src={viewer.avatar} />}>
                <Item key="/user">
                    <NavLink to={`/user/${viewer.id}`}>
                        <UserOutlined></UserOutlined>
                        Profile
                    </NavLink>
                </Item>
                <Item key="/logout" onClick={handleLogout}>
                    <LogoutOutlined></LogoutOutlined>
                    Log out
                </Item>
            </SubMenu>
        ) : (
            <Item>
                <NavLink to="/login">
                    <Button type="primary">Sign In</Button>
                </NavLink>
            </Item>
        );

    return (
        <Menu mode="horizontal" selectable={false} className="menu">
            <Item key="/host">
                <NavLink to="/host">
                    <HomeOutlined />
                    Host
                </NavLink>
            </Item>
            {subMenuLogin}
        </Menu>
    );
}
Example #11
Source File: Layout.tsx    From jitsu with MIT License 5 votes vote down vote up
DropdownMenu: React.FC<{ user: User; plan: CurrentSubscription; hideMenu: () => void }> = ({
  plan,
  user,
  hideMenu,
}) => {
  const services = useServices()
  const history = useHistory()

  const showSettings = React.useCallback<() => void>(() => history.push("/user/settings"), [history])

  const becomeUser = async () => {
    let email = prompt("Please enter e-mail of the user", "")
    if (!email) {
      return
    }
    try {
      AnalyticsBlock.blockAll()
      await services.userService.becomeUser(email)
    } catch (e) {
      handleError(e, "Can't login as other user")
      AnalyticsBlock.unblockAll()
    }
  }

  return (
    <div>
      <div className="py-5 border-b px-5 flex flex-col items-center">
        <div className="text-center text-text text-lg">{user.name}</div>
        <div className="text-secondaryText text-xs underline">{user.email}</div>
      </div>
      <div className="py-2 border-b border-main px-5 flex flex-col items-start">
        <div>
          {services.activeProject?.name && (
            <>
              Project: <b>{services.activeProject.name}</b>
            </>
          )}
          <div className="text-xs">
            <a
              onClick={() => {
                hideMenu()
                showProjectSwitchModal()
              }}
            >
              Switch project
            </a>
          </div>
        </div>
      </div>
      {services.features.billingEnabled && services.applicationConfiguration.billingUrl && (
        <div className="py-5 border-b border-main px-5 flex flex-col items-start">
          <BillingCurrentPlan planStatus={plan} onPlanChangeModalOpen={hideMenu} />
        </div>
      )}
      <div className="p-2 flex flex-col items-stretch">
        <Button type="text" className="text-left" key="settings" icon={<SettingOutlined />} onClick={showSettings}>
          Settings
        </Button>
        {(services.userService.getUser().email === "[email protected]" ||
          services.userService.getUser().email.endsWith("@jitsu.com")) && (
          <Button className="text-left" type="text" key="become" icon={<UserSwitchOutlined />} onClick={becomeUser}>
            Become User
          </Button>
        )}
        <Button
          className="text-left"
          type="text"
          key="logout"
          icon={<LogoutOutlined />}
          onClick={() => services.userService.removeAuth(reloadPage)}
        >
          Logout
        </Button>
      </div>
    </div>
  )
}
Example #12
Source File: AvatarDropdown.tsx    From ui-visualization with MIT License 5 votes vote down vote up
render(): React.ReactNode {
    const {
      currentUser = {
        avatar: '',
        name: '',
      },
      menu,
    } = this.props;
    const menuHeaderDropdown = (
      <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
        {menu && (
          <Menu.Item key="center">
            <UserOutlined />
            个人中心
          </Menu.Item>
        )}
        {menu && (
          <Menu.Item key="settings">
            <SettingOutlined />
            个人设置
          </Menu.Item>
        )}
        {menu && <Menu.Divider />}

        <Menu.Item key="logout">
          <LogoutOutlined />
          退出登录
        </Menu.Item>
      </Menu>
    );
    return currentUser && currentUser.name ? (
      <HeaderDropdown overlay={menuHeaderDropdown}>
        <span className={`${styles.action} ${styles.account}`}>
          <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
          <span className={styles.name}>{currentUser.name}</span>
        </span>
      </HeaderDropdown>
    ) : (
      <span className={`${styles.action} ${styles.account}`}>
        <Spin
          size="small"
          style={{
            marginLeft: 8,
            marginRight: 8,
          }}
        />
      </span>
    );
  }
Example #13
Source File: AvatarDropdown.tsx    From ant-design-pro-V4 with MIT License 5 votes vote down vote up
render(): React.ReactNode {
    const { todoList } = this.props?.todo
    // const todoNum = todoList.filter((item: any) => item.status === 0).length
    const todoNum = todoList?.filter((item: any) => {
      if (item != null) {
        return item.status === 0
      }
    }).length
    const {
      currentUser = {
        avatar: '',
        name: '',
      },
      menu,
    } = this.props;
    const menuHeaderDropdown = (
      <Menu className={styles.menu} selectedKeys={[]} onClick={this.onMenuClick}>
        {menu && (
          <Menu.Item key="center">
            <UserOutlined />
            个人中心
          </Menu.Item>
        )}
        {menu && (
          <Menu.Item key="settings">
            <SettingOutlined />
            个人设置
          </Menu.Item>
        )}
        {menu && <Menu.Divider />}
        <Menu.Item key="todo">
          <UnorderedListOutlined />
          待办事项
          <Badge count={todoNum} offset={[10, -5]} />
        </Menu.Item>
        {menu && <Menu.Divider />}
        <Menu.Item key="logout">
          <LogoutOutlined />
          退出登录
        </Menu.Item>
      </Menu>
    );
    return currentUser && currentUser.name ? (
      <HeaderDropdown overlay={menuHeaderDropdown}>
        <span className={`${styles.action} ${styles.account}`}>
          <Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
          <span className={`${styles.name} anticon`}>{currentUser.name}
            <Badge count={todoNum} dot={true} /></span>
        </span>
      </HeaderDropdown>
    ) : (
      <span className={`${styles.action} ${styles.account}`}>
        <Spin
          size="small"
          style={{
            marginLeft: 8,
            marginRight: 8,
          }}
        />
      </span>
    );
  }
Example #14
Source File: TeamMembers.tsx    From posthog-foss with MIT License 5 votes vote down vote up
function ActionsComponent(member: FusedTeamMemberType): JSX.Element | null {
    const { user } = useValues(userLogic)
    const { currentTeam } = useValues(teamLogic)
    const { removeMember } = useActions(teamMembersLogic)

    if (!user) {
        return null
    }

    function handleClick(): void {
        Modal.confirm({
            title: `${
                member.user.uuid == user?.uuid
                    ? 'Leave'
                    : `Remove ${member.user.first_name} (${member.user.email}) from`
            } project ${currentTeam?.name}?`,
            icon: <ExclamationCircleOutlined />,
            okText: member.user.uuid == user?.uuid ? 'Leave' : 'Remove',
            okType: 'danger',
            onOk() {
                removeMember({ member })
            },
        })
    }

    const allowDeletion =
        // You can leave, but only project admins can remove others
        ((currentTeam?.effective_membership_level &&
            currentTeam.effective_membership_level >= OrganizationMembershipLevel.Admin) ||
            member.user.uuid === user.uuid) &&
        // Only members without implicit access can leave or be removed
        member.organization_level < MINIMUM_IMPLICIT_ACCESS_LEVEL

    return allowDeletion ? (
        <a className="text-danger" onClick={handleClick} data-attr="delete-team-membership">
            {member.user.uuid !== user.uuid ? (
                <CloseCircleOutlined title="Remove from project" />
            ) : (
                <LogoutOutlined title="Leave project" />
            )}
        </a>
    ) : null
}
Example #15
Source File: Members.tsx    From posthog-foss with MIT License 5 votes vote down vote up
function ActionsComponent(member: OrganizationMemberType): JSX.Element | null {
    const { user } = useValues(userLogic)
    const { currentOrganization } = useValues(organizationLogic)
    const { removeMember } = useActions(membersLogic)

    if (!user) {
        return null
    }

    const currentMembershipLevel = currentOrganization?.membership_level ?? -1

    function handleClick(): void {
        if (!user) {
            throw Error
        }
        Modal.confirm({
            title: `${member.user.uuid == user.uuid ? 'Leave' : `Remove ${member.user.first_name} from`} organization ${
                user.organization?.name
            }?`,
            icon: <ExclamationCircleOutlined />,
            okText: member.user.uuid == user.uuid ? 'Leave' : 'Remove',
            okType: 'danger',
            cancelText: 'Cancel',
            onOk() {
                removeMember(member)
            },
        })
    }

    const allowDeletion =
        // higher-ranked users cannot be removed, at the same time the currently logged-in user can leave any time
        ((currentMembershipLevel >= OrganizationMembershipLevel.Admin && member.level <= currentMembershipLevel) ||
            member.user.uuid === user.uuid) &&
        // unless that user is the organization's owner, in which case they can't leave
        member.level !== OrganizationMembershipLevel.Owner

    return (
        <div>
            {allowDeletion && (
                <a className="text-danger" onClick={handleClick} data-attr="delete-org-membership">
                    {member.user.uuid !== user.uuid ? (
                        <DeleteOutlined title="Remove from organization" />
                    ) : (
                        <LogoutOutlined title="Leave organization" />
                    )}
                </a>
            )}
        </div>
    )
}
Example #16
Source File: AppHeader.tsx    From jmix-frontend with Apache License 2.0 5 votes vote down vote up
AppHeader = observer(({children}: {children?: React.ReactNode}) => {
  const intl = useIntl();
  const mainStore = useMainStore();

  const [settingsEnabled, setSettingsEnabled] = useState(false);

  const [visibleHotkeyInfo, setVisibleHotkeyInfo] = useState(false);

  const toggleHotkeyInfo = useCallback<KeyHandler>(() => setVisibleHotkeyInfo(!visibleHotkeyInfo), [visibleHotkeyInfo]);
  useHotkey(toggleHotkeyInfoHotkeyConfig, toggleHotkeyInfo);

  const toggleSettings = useCallback(() => {
    setSettingsEnabled((isEnabled) => {
      return !isEnabled;
    })
  }, [])

  const showLogoutConfirm = useCallback(() => {
    modals.open({
      content: intl.formatMessage({id: 'header.logout.areYouSure'}),
      okText: intl.formatMessage({id: 'header.logout.ok'}),
      cancelText: intl.formatMessage({id: 'header.logout.cancel'}),
      onOk: () => mainStore.logout()
    });
  }, [mainStore, intl]);

  return (
    <div className={styles.header}>
      <JmixLightIcon className={styles.icon} />

      <div className={styles.content}>{children}</div>
      <>
      {settingsEnabled && (
          <>
            <ThemeSwitcher className={styles.themeSwitcher} />
            <LanguageSwitcher className={styles.languageSwitcher} />
          </>
        )}
      </>
      <Space className={styles.userPanel}>
        <span>{mainStore.userName}</span>
        <Button
          className={classNames(settingsEnabled ? styles.settingsBtnActive : styles.settingsBtn, appStyles.focusOuterHighlight)}
          type={"text"}
          icon={<SettingOutlined role={""}/>}
          onClick={toggleSettings}
          role={"switch"}
          aria-checked={settingsEnabled}
        />
        <HotkeyInfoModalButton
          visible={visibleHotkeyInfo}
          setVisible={setVisibleHotkeyInfo}
          className={classNames(styles.infoBtn, appStyles.focusOuterHighlight)}
        />
        <Button
          id="button_logout"
          className={classNames(styles.logoutBtn, appStyles.focusOuterHighlight)}
          type="text"
          icon={<LogoutOutlined role={""}/>}
          onClick={showLogoutConfirm}
        />
      </Space>
    </div>
  );
})
Example #17
Source File: NavBarMobile.tsx    From foodie with MIT License 4 votes vote down vote up
NavBarMobile: React.FC<IProps> = ({ theme, isAuth, auth, openModal }) => {
    const [isOpenSearch, setOpenSearch] = useState(false);
    const [isOpenMenu, setOpenMenu] = useState(false);
    const { pathname } = useLocation();
    const history = useHistory();

    const onClickMenuItem = () => {
        setOpenMenu(false);
    }

    const clickSearchItemCallback = (user: IUser) => {
        setOpenSearch(false);
        history.push(`/user/${user.username}`);
    }

    return isOpenSearch ? (
        <div className="fixed top-0 left-0 flex w-full items-center bg-indigo-700 z-9999 py-2 pr-2 shadow-xl">
            <div
                className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-indigo-500"
                onClick={() => setOpenSearch(false)}
            >
                <ArrowLeftOutlined className="text-white" style={{ fontSize: '18px' }} />
            </div>
            <SearchInput
                clickItemCallback={clickSearchItemCallback}
                inputClassName="w-full"
            />
        </div>
    ) : (
        <nav className="contain flex justify-between z-9999 align-center w-100 border-b border-transparent bg-white dark:bg-indigo-1000 text-gray-700 h-60px py-2 fixed top-0 left-0 w-full shadow-md laptop:shadow-sm dark:border-gray-800">
            <div className="flex items-center space-x-8">
                {/* ---- LOGO -------- */}
                <Link
                    to={{
                        pathname: '/',
                        state: { from: pathname }
                    }}
                >
                    <img
                        src={logo}
                        alt=""
                        className="w-24"
                        style={{ filter: `brightness(${theme === 'dark' ? 3.5 : 1})` }}
                    />
                </Link>
            </div>
            {/* ---- NAVICONS FOR MOBILE ---- */}
            <div className="flex items-center space-x-4 laptop:hidden">
                {isAuth && (
                    <>
                        <div
                            className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:hover:bg-indigo-1100"
                        >
                            <Messages isAuth={isAuth} />
                        </div>
                        <div
                            className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:hover:bg-indigo-1100"
                        >
                            <Notification isAuth={isAuth} />
                        </div>
                    </>
                )}
                <div
                    className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200 dark:text-white dark:hover:bg-indigo-1100"
                    onClick={() => setOpenSearch(true)}
                >
                    <SearchOutlined style={{ fontSize: '20px' }} />
                </div>
                <div
                    className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:text-white dark:hover:bg-indigo-1100"
                    onClick={() => setOpenMenu(true)}
                >
                    <MenuOutlined style={{ fontSize: '20px' }} />
                </div>
            </div>
            {/* ---- NAV DRAWER FOR MOBILE --- */}
            <div className={`flex  flex-col w-full h-screen fixed top-0 right-0 transition-transform  transform ${isOpenMenu ? 'translate-x-0' : 'translate-x-full'} bg-white dark:bg-indigo-1000 laptop:hidden`}>
                <div className="flex items-center justify-between px-4">
                    <div className="flex items-center space-x-4">
                        <h1 className="dark:text-white">Menu</h1>
                        <ThemeToggler />
                    </div>
                    <div
                        className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200 dark:text-white dark:hover:bg-indigo-1100"
                        onClick={() => setOpenMenu(false)}
                    >
                        <CloseOutlined style={{ fontSize: '20px' }} />
                    </div>
                </div>
                {isAuth ? (
                    <ul className="divide-y divide-gray-100 dark:divide-gray-800">
                        <li className="px-4 py-3 pb-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex font-medium dark:text-indigo-400"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}`}
                            >
                                <Avatar url={auth.profilePicture?.url} size="lg" className="mr-2" />
                                <div className="flex flex-col">
                                    <span>{auth.username}</span>
                                    <span className="text-gray-400 text-xs">View Profile</span>
                                </div>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/following`}
                            >
                                <TeamOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Following</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/followers`}
                            >
                                <TeamOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Followers</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/bookmarks`}
                            >
                                <StarOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Bookmarks</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={SUGGESTED_PEOPLE}
                            >
                                <UsergroupAddOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Suggested People</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <div
                                className="flex items-center text-black dark:text-white"
                                onClick={() => {
                                    openModal();
                                    setOpenMenu(false);
                                }}
                            >
                                <LogoutOutlined className="text-red-500" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm text-red-500">Logout</h6>
                            </div>
                        </li>
                    </ul>
                ) : (
                    <ul className="divide-y divide-gray-100 dark:divide-gray-800">
                        <li className="px-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100 flex items-center justify-start">
                            <ArrowRightOutlined className="dark:text-white" />
                            <Link
                                className="p-4 font-medium dark:text-indigo-400 flex-grow"
                                to={LOGIN}
                            >
                                Login
                                    </Link>
                        </li>
                        <li className="px-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100 flex items-center justify-start">
                            <ArrowRightOutlined className="dark:text-white" />
                            <Link
                                className="p-4 font-medium dark:text-indigo-400 flex-grow"
                                to={REGISTER}
                            >
                                Register
                                    </Link>
                        </li>
                    </ul>
                )}
                {/* --- COPYRIGHT -- */}
                <span className="text-gray-400 text-xs absolute bottom-8 left-0 right-0 mx-auto text-center">
                    &copy;Copyright {new Date().getFullYear()} Foodie
                    </span>
            </div>
        </nav>
    )
}
Example #18
Source File: Header.tsx    From leek with Apache License 2.0 4 votes vote down vote up
Header = () => {
  const { logout } = useAuth();
  const {
    applications,
    selectApplication,
    selectEnv,
    currentApp,
    currentEnv,
    seenEnvs,
  } = useApplication();

  const { switcher, currentTheme, themes } = useThemeSwitcher();

  function handleAppSelect(e) {
    selectApplication(e.key);
  }

  function handleEnvSelect(e) {
    selectEnv(e.key);
  }

  const apps = (
    <Menu
      onClick={handleAppSelect}
      selectedKeys={currentApp ? [currentApp] : []}
      selectable
    >
      {applications.map((app, index) => (
        <Menu.Item key={app["app_name"]}>{app["app_name"]}</Menu.Item>
      ))}
    </Menu>
  );

  function getMenuItems(location) {
    return tabs.map((tab) => {
      return (
        <Menu.Item key={`/${tab.key}/`}>
          <Link to={`/${tab.key}/${location.search}`}>
            <Space size={4}>
              {tab.icon} <span>{tab.name}</span>
            </Space>
          </Link>
        </Menu.Item>
      );
    });
  }

  const envs = (
    <Menu
      onClick={handleEnvSelect}
      selectedKeys={currentEnv ? [currentEnv] : []}
      selectable
    >
      {seenEnvs.map((env, index) => (
        <Menu.Item key={env["key"]}>{env["key"]}</Menu.Item>
      ))}
    </Menu>
  );

  const toggleTheme = (isChecked) => {
    if (isChecked) localStorage.setItem("theme", "dark");
    else localStorage.setItem("theme", "light");
    switcher({ theme: isChecked ? themes.dark : themes.light });
  };

  return (
    <Location>
      {({ location }) => {
        return (
          <Layout.Header
            style={{
              position: "fixed",
              zIndex: 1,
              width: "100%",
              // borderBottom: "1px solid #f0f0f0"
            }}
          >
            <div
              style={{
                width: "40px",
                height: "40px",
                margin: "5px 20px 5px 0",
                float: "left",
              }}
            >
              <Link to={`/${location.search}`}>
                <Image
                  alt="Logo"
                  width={40}
                  height={40}
                  style={{ margin: 0 }}
                  src="/leek.png"
                  preview={false}
                />
              </Link>
            </div>
            <Row justify="space-between">
              <Col xxl={18} xl={18} lg={14} md={0} sm={0} xs={0}>
                <Menu
                  mode="horizontal"
                  selectedKeys={[location.pathname]}
                  style={{ lineHeight: "48px", borderBottom: "0" }}
                >
                  {getMenuItems(location)}
                </Menu>
              </Col>
              <Col xxl={0} xl={0} lg={0} md={6} sm={6} xs={6}>
                <Menu
                  mode="horizontal"
                  selectedKeys={[location.pathname]}
                  style={{ lineHeight: "48px", borderBottom: "0" }}
                >
                  <SubMenu key="sub2" icon={<MenuOutlined />}>
                    {getMenuItems(location)}
                  </SubMenu>
                </Menu>
              </Col>
              <Col>
                <Row style={{ float: "right" }} gutter={10}>
                  {seenEnvs.length > 0 && (
                    <Col>
                      <Dropdown.Button
                        size="small"
                        icon={<DownOutlined />}
                        overlay={envs}
                        placement="bottomLeft"
                      >
                        <span style={{ color: "#00BFA6" }}>env:&nbsp;</span>
                        {currentEnv ? currentEnv : "-"}
                      </Dropdown.Button>
                    </Col>
                  )}

                  <Col>
                    <Dropdown.Button
                      size="small"
                      icon={<DownOutlined />}
                      overlay={apps}
                      placement="bottomLeft"
                    >
                      <span style={{ color: "#00BFA6" }}>app:&nbsp;</span>
                      {currentApp ? currentApp : "-"}
                    </Dropdown.Button>
                  </Col>

                  <Col>
                    <Switch
                      checked={currentTheme === themes.dark}
                      onChange={toggleTheme}
                      checkedChildren={<span>?</span>}
                      unCheckedChildren={<span>☀</span>}
                      style={{ background: "#555" }}
                    />
                  </Col>

                  {env.LEEK_API_ENABLE_AUTH !== "false" && (
                    <Col key="/logout" style={{ float: "right" }}>
                      <Button
                        size="small"
                        danger
                        onClick={logout}
                        style={{ textAlign: "center" }}
                      >
                        <LogoutOutlined />
                      </Button>
                    </Col>
                  )}
                </Row>
              </Col>
            </Row>
          </Layout.Header>
        );
      }}
    </Location>
  );
}
Example #19
Source File: index.tsx    From ql with MIT License 4 votes vote down vote up
export default function (props: any) {
  const logout = () => {
    request.post(`${config.apiPrefix}logout`).then(() => {
      localStorage.removeItem(config.authKey);
      history.push('/login');
    });
  };

  useEffect(() => {
    const isAuth = localStorage.getItem(config.authKey);
    if (!isAuth) {
      history.push('/login');
    }
    vhCheck();
  }, []);

  useEffect(() => {
    if (props.location.pathname === '/') {
      history.push('/crontab');
    }
  }, [props.location.pathname]);

  useEffect(() => {
    const theme = localStorage.getItem('qinglong_dark_theme') || 'auto';
    setFetchMethod(window.fetch);
    if (theme === 'dark') {
      enableDarkMode({
        brightness: 100,
        contrast: 90,
        sepia: 10,
      });
    } else if (theme === 'light') {
      disableDarkMode();
    } else {
      followSystemColorScheme({
        brightness: 100,
        contrast: 90,
        sepia: 10,
      });
    }
  }, []);

  if (props.location.pathname === '/login') {
    return props.children;
  }

  const isFirefox = navigator.userAgent.includes('Firefox');
  const isSafari =
    navigator.userAgent.includes('Safari') &&
    !navigator.userAgent.includes('Chrome');
  return (
    <ProLayout
      selectedKeys={[props.location.pathname]}
      title={
        <>
          控制面板
          <a href={changeLog} target="_blank" rel="noopener noreferrer">
            <span
              style={{
                fontSize: isFirefox ? 9 : 12,
                color: '#666',
                marginLeft: 5,
                zoom: isSafari ? 0.66 : 0.8,
              }}
            >
              {version}
            </span>
          </a>
        </>
      }
      menuItemRender={(menuItemProps: any, defaultDom: any) => {
        if (
          menuItemProps.isUrl ||
          !menuItemProps.path ||
          location.pathname === menuItemProps.path
        ) {
          return defaultDom;
        }
        return <Link to={menuItemProps.path}>{defaultDom}</Link>;
      }}
      postMenuData={(menuData) => {
        return [
          ...(menuData || []),
          {
            icon: <LogoutOutlined />,
            name: '退出登录',
            path: 'logout',
            onTitleClick: () => logout(),
          },
        ];
      }}
      pageTitleRender={() => '控制面板'}
      {...defaultProps}
    >
      {props.children}
    </ProLayout>
  );
}
Example #20
Source File: Icon.tsx    From html2sketch with MIT License 4 votes vote down vote up
IconSymbol: FC = () => {
  return (
    <Row>
      {/*<CaretUpOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
      {/*/>*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
      {/*/>*/}
      {/*<StepBackwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      {/*<StepForwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      <StepForwardOutlined />
      <ShrinkOutlined />
      <ArrowsAltOutlined />
      <DownOutlined />
      <UpOutlined />
      <LeftOutlined />
      <RightOutlined />
      <CaretUpOutlined />
      <CaretDownOutlined />
      <CaretLeftOutlined />
      <CaretRightOutlined />
      <VerticalAlignTopOutlined />
      <RollbackOutlined />
      <FastBackwardOutlined />
      <FastForwardOutlined />
      <DoubleRightOutlined />
      <DoubleLeftOutlined />
      <VerticalLeftOutlined />
      <VerticalRightOutlined />
      <VerticalAlignMiddleOutlined />
      <VerticalAlignBottomOutlined />
      <ForwardOutlined />
      <BackwardOutlined />
      <EnterOutlined />
      <RetweetOutlined />
      <SwapOutlined />
      <SwapLeftOutlined />
      <SwapRightOutlined />
      <ArrowUpOutlined />
      <ArrowDownOutlined />
      <ArrowLeftOutlined />
      <ArrowRightOutlined />
      <LoginOutlined />
      <LogoutOutlined />
      <MenuFoldOutlined />
      <MenuUnfoldOutlined />
      <BorderBottomOutlined />
      <BorderHorizontalOutlined />
      <BorderInnerOutlined />
      <BorderOuterOutlined />
      <BorderLeftOutlined />
      <BorderRightOutlined />
      <BorderTopOutlined />
      <BorderVerticleOutlined />
      <PicCenterOutlined />
      <PicLeftOutlined />
      <PicRightOutlined />
      <RadiusBottomleftOutlined />
      <RadiusBottomrightOutlined />
      <RadiusUpleftOutlined />
      <RadiusUprightOutlined />
      <FullscreenOutlined />
      <FullscreenExitOutlined />
      <QuestionOutlined />
      <PauseOutlined />
      <MinusOutlined />
      <PauseCircleOutlined />
      <InfoOutlined />
      <CloseOutlined />
      <ExclamationOutlined />
      <CheckOutlined />
      <WarningOutlined />
      <IssuesCloseOutlined />
      <StopOutlined />
      <EditOutlined />
      <CopyOutlined />
      <ScissorOutlined />
      <DeleteOutlined />
      <SnippetsOutlined />
      <DiffOutlined />
      <HighlightOutlined />
      <AlignCenterOutlined />
      <AlignLeftOutlined />
      <AlignRightOutlined />
      <BgColorsOutlined />
      <BoldOutlined />
      <ItalicOutlined />
      <UnderlineOutlined />
      <StrikethroughOutlined />
      <RedoOutlined />
      <UndoOutlined />
      <ZoomInOutlined />
      <ZoomOutOutlined />
      <FontColorsOutlined />
      <FontSizeOutlined />
      <LineHeightOutlined />
      <SortAscendingOutlined />
      <SortDescendingOutlined />
      <DragOutlined />
      <OrderedListOutlined />
      <UnorderedListOutlined />
      <RadiusSettingOutlined />
      <ColumnWidthOutlined />
      <ColumnHeightOutlined />
      <AreaChartOutlined />
      <PieChartOutlined />
      <BarChartOutlined />
      <DotChartOutlined />
      <LineChartOutlined />
      <RadarChartOutlined />
      <HeatMapOutlined />
      <FallOutlined />
      <RiseOutlined />
      <StockOutlined />
      <BoxPlotOutlined />
      <FundOutlined />
      <SlidersOutlined />
      <AndroidOutlined />
      <AppleOutlined />
      <WindowsOutlined />
      <IeOutlined />
      <ChromeOutlined />
      <GithubOutlined />
      <AliwangwangOutlined />
      <DingdingOutlined />
      <WeiboSquareOutlined />
      <WeiboCircleOutlined />
      <TaobaoCircleOutlined />
      <Html5Outlined />
      <WeiboOutlined />
      <TwitterOutlined />
      <WechatOutlined />
      <AlipayCircleOutlined />
      <TaobaoOutlined />
      <SkypeOutlined />
      <FacebookOutlined />
      <CodepenOutlined />
      <CodeSandboxOutlined />
      <AmazonOutlined />
      <GoogleOutlined />
      <AlipayOutlined />
      <AntDesignOutlined />
      <AntCloudOutlined />
      <ZhihuOutlined />
      <SlackOutlined />
      <SlackSquareOutlined />
      <BehanceSquareOutlined />
      <DribbbleOutlined />
      <DribbbleSquareOutlined />
      <InstagramOutlined />
      <YuqueOutlined />
      <AlibabaOutlined />
      <YahooOutlined />
      <RedditOutlined />
      <SketchOutlined />
      <AccountBookOutlined />
      <AlertOutlined />
      <ApartmentOutlined />
      <ApiOutlined />
      <QqOutlined />
      <MediumWorkmarkOutlined />
      <GitlabOutlined />
      <MediumOutlined />
      <GooglePlusOutlined />
      <AppstoreAddOutlined />
      <AppstoreOutlined />
      <AudioOutlined />
      <AudioMutedOutlined />
      <AuditOutlined />
      <BankOutlined />
      <BarcodeOutlined />
      <BarsOutlined />
      <BellOutlined />
      <BlockOutlined />
      <BookOutlined />
      <BorderOutlined />
      <BranchesOutlined />
      <BuildOutlined />
      <BulbOutlined />
      <CalculatorOutlined />
      <CalendarOutlined />
      <CameraOutlined />
      <CarOutlined />
      <CarryOutOutlined />
      <CiCircleOutlined />
      <CiOutlined />
      <CloudOutlined />
      <ClearOutlined />
      <ClusterOutlined />
      <CodeOutlined />
      <CoffeeOutlined />
      <CompassOutlined />
      <CompressOutlined />
      <ContactsOutlined />
      <ContainerOutlined />
      <ControlOutlined />
      <CopyrightCircleOutlined />
      <CopyrightOutlined />
      <CreditCardOutlined />
      <CrownOutlined />
      <CustomerServiceOutlined />
      <DashboardOutlined />
      <DatabaseOutlined />
      <DeleteColumnOutlined />
      <DeleteRowOutlined />
      <DisconnectOutlined />
      <DislikeOutlined />
      <DollarCircleOutlined />
      <DollarOutlined />
      <DownloadOutlined />
      <EllipsisOutlined />
      <EnvironmentOutlined />
      <EuroCircleOutlined />
      <EuroOutlined />
      <ExceptionOutlined />
      <ExpandAltOutlined />
      <ExpandOutlined />
      <ExperimentOutlined />
      <ExportOutlined />
      <EyeOutlined />
      <FieldBinaryOutlined />
      <FieldNumberOutlined />
      <FieldStringOutlined />
      <DesktopOutlined />
      <DingtalkOutlined />
      <FileAddOutlined />
      <FileDoneOutlined />
      <FileExcelOutlined />
      <FileExclamationOutlined />
      <FileOutlined />
      <FileImageOutlined />
      <FileJpgOutlined />
      <FileMarkdownOutlined />
      <FilePdfOutlined />
      <FilePptOutlined />
      <FileProtectOutlined />
      <FileSearchOutlined />
      <FileSyncOutlined />
      <FileTextOutlined />
      <FileUnknownOutlined />
      <FileWordOutlined />
      <FilterOutlined />
      <FireOutlined />
      <FlagOutlined />
      <FolderAddOutlined />
      <FolderOutlined />
      <FolderOpenOutlined />
      <ForkOutlined />
      <FormatPainterOutlined />
      <FrownOutlined />
      <FunctionOutlined />
      <FunnelPlotOutlined />
      <GatewayOutlined />
      <GifOutlined />
      <GiftOutlined />
      <GlobalOutlined />
      <GoldOutlined />
      <GroupOutlined />
      <HddOutlined />
      <HeartOutlined />
      <HistoryOutlined />
      <HomeOutlined />
      <HourglassOutlined />
      <IdcardOutlined />
      <ImportOutlined />
      <InboxOutlined />
      <InsertRowAboveOutlined />
      <InsertRowBelowOutlined />
      <InsertRowLeftOutlined />
      <InsertRowRightOutlined />
      <InsuranceOutlined />
      <InteractionOutlined />
      <KeyOutlined />
      <LaptopOutlined />
      <LayoutOutlined />
      <LikeOutlined />
      <LineOutlined />
      <LinkOutlined />
      <Loading3QuartersOutlined />
      <LoadingOutlined />
      <LockOutlined />
      <MailOutlined />
      <ManOutlined />
      <MedicineBoxOutlined />
      <MehOutlined />
      <MenuOutlined />
      <MergeCellsOutlined />
      <MessageOutlined />
      <MobileOutlined />
      <MoneyCollectOutlined />
      <MonitorOutlined />
      <MoreOutlined />
      <NodeCollapseOutlined />
      <NodeExpandOutlined />
      <NodeIndexOutlined />
      <NotificationOutlined />
      <NumberOutlined />
      <PaperClipOutlined />
      <PartitionOutlined />
      <PayCircleOutlined />
      <PercentageOutlined />
      <PhoneOutlined />
      <PictureOutlined />
      <PoundCircleOutlined />
      <PoundOutlined />
      <PoweroffOutlined />
      <PrinterOutlined />
      <ProfileOutlined />
      <ProjectOutlined />
      <PropertySafetyOutlined />
      <PullRequestOutlined />
      <PushpinOutlined />
      <QrcodeOutlined />
      <ReadOutlined />
      <ReconciliationOutlined />
      <RedEnvelopeOutlined />
      <ReloadOutlined />
      <RestOutlined />
      <RobotOutlined />
      <RocketOutlined />
      <SafetyCertificateOutlined />
      <SafetyOutlined />
      <ScanOutlined />
      <ScheduleOutlined />
      <SearchOutlined />
      <SecurityScanOutlined />
      <SelectOutlined />
      <SendOutlined />
      <SettingOutlined />
      <ShakeOutlined />
      <ShareAltOutlined />
      <ShopOutlined />
      <ShoppingCartOutlined />
      <ShoppingOutlined />
      <SisternodeOutlined />
      <SkinOutlined />
      <SmileOutlined />
      <SolutionOutlined />
      <SoundOutlined />
      <SplitCellsOutlined />
      <StarOutlined />
      <SubnodeOutlined />
      <SyncOutlined />
      <TableOutlined />
      <TabletOutlined />
      <TagOutlined />
      <TagsOutlined />
      <TeamOutlined />
      <ThunderboltOutlined />
      <ToTopOutlined />
      <ToolOutlined />
      <TrademarkCircleOutlined />
      <TrademarkOutlined />
      <TransactionOutlined />
      <TrophyOutlined />
      <UngroupOutlined />
      <UnlockOutlined />
      <UploadOutlined />
      <UsbOutlined />
      <UserAddOutlined />
      <UserDeleteOutlined />
      <UserOutlined />
      <UserSwitchOutlined />
      <UsergroupAddOutlined />
      <UsergroupDeleteOutlined />
      <VideoCameraOutlined />
      <WalletOutlined />
      <WifiOutlined />
      <BorderlessTableOutlined />
      <WomanOutlined />
      <BehanceOutlined />
      <DropboxOutlined />
      <DeploymentUnitOutlined />
      <UpCircleOutlined />
      <DownCircleOutlined />
      <LeftCircleOutlined />
      <RightCircleOutlined />
      <UpSquareOutlined />
      <DownSquareOutlined />
      <LeftSquareOutlined />
      <RightSquareOutlined />
      <PlayCircleOutlined />
      <QuestionCircleOutlined />
      <PlusCircleOutlined />
      <PlusSquareOutlined />
      <MinusSquareOutlined />
      <MinusCircleOutlined />
      <InfoCircleOutlined />
      <ExclamationCircleOutlined />
      <CloseCircleOutlined />
      <CloseSquareOutlined />
      <CheckCircleOutlined />
      <CheckSquareOutlined />
      <ClockCircleOutlined />
      <FormOutlined />
      <DashOutlined />
      <SmallDashOutlined />
      <YoutubeOutlined />
      <CodepenCircleOutlined />
      <AliyunOutlined />
      <PlusOutlined />
      <LinkedinOutlined />
      <AimOutlined />
      <BugOutlined />
      <CloudDownloadOutlined />
      <CloudServerOutlined />
      <CloudSyncOutlined />
      <CloudUploadOutlined />
      <CommentOutlined />
      <ConsoleSqlOutlined />
      <EyeInvisibleOutlined />
      <FileGifOutlined />
      <DeliveredProcedureOutlined />
      <FieldTimeOutlined />
      <FileZipOutlined />
      <FolderViewOutlined />
      <FundProjectionScreenOutlined />
      <FundViewOutlined />
      <MacCommandOutlined />
      <PlaySquareOutlined />
      <OneToOneOutlined />
      <RotateLeftOutlined />
      <RotateRightOutlined />
      <SaveOutlined />
      <SwitcherOutlined />
      <TranslationOutlined />
      <VerifiedOutlined />
      <VideoCameraAddOutlined />
      <WhatsAppOutlined />

      {/*</Col>*/}
    </Row>
  );
}
Example #21
Source File: commandPaletteLogic.ts    From posthog-foss with MIT License 4 votes vote down vote up
commandPaletteLogic = kea<
    commandPaletteLogicType<
        Command,
        CommandFlow,
        CommandRegistrations,
        CommandResult,
        CommandResultDisplayable,
        RegExpCommandPairs
    >
>({
    path: ['lib', 'components', 'CommandPalette', 'commandPaletteLogic'],
    connect: {
        actions: [personalAPIKeysLogic, ['createKey']],
        values: [teamLogic, ['currentTeam'], userLogic, ['user']],
        logic: [preflightLogic], // used in afterMount, which does not auto-connect
    },
    actions: {
        hidePalette: true,
        showPalette: true,
        togglePalette: true,
        setInput: (input: string) => ({ input }),
        onArrowUp: true,
        onArrowDown: (maxIndex: number) => ({ maxIndex }),
        onMouseEnterResult: (index: number) => ({ index }),
        onMouseLeaveResult: true,
        executeResult: (result: CommandResult) => ({ result }),
        activateFlow: (flow: CommandFlow | null) => ({ flow }),
        backFlow: true,
        registerCommand: (command: Command) => ({ command }),
        deregisterCommand: (commandKey: string) => ({ commandKey }),
        setCustomCommand: (commandKey: string) => ({ commandKey }),
        deregisterScope: (scope: string) => ({ scope }),
    },
    reducers: {
        isPaletteShown: [
            false,
            {
                hidePalette: () => false,
                showPalette: () => true,
                togglePalette: (previousState) => !previousState,
            },
        ],
        keyboardResultIndex: [
            0,
            {
                setInput: () => 0,
                executeResult: () => 0,
                activateFlow: () => 0,
                backFlow: () => 0,
                onArrowUp: (previousIndex) => (previousIndex > 0 ? previousIndex - 1 : 0),
                onArrowDown: (previousIndex, { maxIndex }) => (previousIndex < maxIndex ? previousIndex + 1 : maxIndex),
            },
        ],
        hoverResultIndex: [
            null as number | null,
            {
                activateFlow: () => null,
                backFlow: () => null,
                onMouseEnterResult: (_, { index }) => index,
                onMouseLeaveResult: () => null,
                onArrowUp: () => null,
                onArrowDown: () => null,
            },
        ],
        input: [
            '',
            {
                setInput: (_, { input }) => input,
                activateFlow: () => '',
                backFlow: () => '',
                executeResult: () => '',
            },
        ],
        activeFlow: [
            null as CommandFlow | null,
            {
                activateFlow: (currentFlow, { flow }) =>
                    flow ? { ...flow, scope: flow.scope ?? currentFlow?.scope, previousFlow: currentFlow } : null,
                backFlow: (currentFlow) => currentFlow?.previousFlow ?? null,
            },
        ],
        rawCommandRegistrations: [
            {} as CommandRegistrations,
            {
                registerCommand: (commands, { command }) => {
                    return { ...commands, [command.key]: command }
                },
                deregisterCommand: (commands, { commandKey }) => {
                    const { [commandKey]: _, ...cleanedCommands } = commands // eslint-disable-line
                    return cleanedCommands
                },
            },
        ],
    },

    listeners: ({ actions, values }) => ({
        showPalette: () => {
            posthog.capture('palette shown', { isMobile: isMobile() })
        },
        togglePalette: () => {
            if (values.isPaletteShown) {
                posthog.capture('palette shown', { isMobile: isMobile() })
            }
        },
        executeResult: ({ result }: { result: CommandResult }) => {
            if (result.executor === true) {
                actions.activateFlow(null)
                actions.hidePalette()
            } else {
                const possibleFlow = result.executor?.() || null
                actions.activateFlow(possibleFlow)
                if (!possibleFlow) {
                    actions.hidePalette()
                }
            }
            // Capture command execution, without useless data
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            const { icon, index, ...cleanedResult }: Record<string, any> = result
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            const { resolver, ...cleanedCommand } = cleanedResult.source
            cleanedResult.source = cleanedCommand
            cleanedResult.isMobile = isMobile()
            posthog.capture('palette command executed', cleanedResult)
        },
        deregisterScope: ({ scope }) => {
            for (const command of Object.values(values.commandRegistrations)) {
                if (command.scope === scope) {
                    actions.deregisterCommand(command.key)
                }
            }
        },
        setInput: async ({ input }, breakpoint) => {
            await breakpoint(300)
            if (input.length > 8) {
                const response = await api.get('api/person/?key_identifier=' + encodeURIComponent(input))
                const person = response.results[0]
                if (person) {
                    actions.registerCommand({
                        key: `person-${person.distinct_ids[0]}`,
                        resolver: [
                            {
                                icon: UserOutlined,
                                display: `View person ${input}`,
                                executor: () => {
                                    const { push } = router.actions
                                    push(urls.person(person.distinct_ids[0]))
                                },
                            },
                        ],
                        scope: GLOBAL_COMMAND_SCOPE,
                    })
                }
            }
        },
    }),
    selectors: {
        isSqueak: [
            (selectors) => [selectors.input],
            (input: string) => {
                return input.trim().toLowerCase() === 'squeak'
            },
        ],
        activeResultIndex: [
            (selectors) => [selectors.keyboardResultIndex, selectors.hoverResultIndex],
            (keyboardResultIndex: number, hoverResultIndex: number | null) => {
                return hoverResultIndex ?? keyboardResultIndex
            },
        ],
        commandRegistrations: [
            (selectors) => [
                selectors.rawCommandRegistrations,
                dashboardsModel.selectors.nameSortedDashboards,
                teamLogic.selectors.currentTeam,
            ],
            (rawCommandRegistrations: CommandRegistrations, dashboards: DashboardType[]): CommandRegistrations => ({
                ...rawCommandRegistrations,
                custom_dashboards: {
                    key: 'custom_dashboards',
                    resolver: dashboards.map((dashboard: DashboardType) => ({
                        key: `dashboard_${dashboard.id}`,
                        icon: LineChartOutlined,
                        display: `Go to Dashboard: ${dashboard.name}`,
                        executor: () => {
                            const { push } = router.actions
                            push(urls.dashboard(dashboard.id))
                        },
                    })),
                    scope: GLOBAL_COMMAND_SCOPE,
                },
            }),
        ],
        regexpCommandPairs: [
            (selectors) => [selectors.commandRegistrations],
            (commandRegistrations: CommandRegistrations) => {
                const array: RegExpCommandPairs = []
                for (const command of Object.values(commandRegistrations)) {
                    if (command.prefixes) {
                        array.push([new RegExp(`^\\s*(${command.prefixes.join('|')})(?:\\s+(.*)|$)`, 'i'), command])
                    } else {
                        array.push([null, command])
                    }
                }
                return array
            },
        ],
        commandSearchResults: [
            (selectors) => [
                selectors.isPaletteShown,
                selectors.regexpCommandPairs,
                selectors.input,
                selectors.activeFlow,
                selectors.isSqueak,
            ],
            (
                isPaletteShown: boolean,
                regexpCommandPairs: RegExpCommandPairs,
                argument: string,
                activeFlow: CommandFlow | null,
                isSqueak: boolean
            ) => {
                if (!isPaletteShown || isSqueak) {
                    return []
                }
                if (activeFlow) {
                    return resolveCommand(activeFlow, argument)
                }
                let directResults: CommandResult[] = []
                let prefixedResults: CommandResult[] = []
                for (const [regexp, command] of regexpCommandPairs) {
                    if (regexp) {
                        const match = argument.match(regexp)
                        if (match && match[1]) {
                            prefixedResults = [...prefixedResults, ...resolveCommand(command, match[2], match[1])]
                        }
                    }
                    directResults = [...directResults, ...resolveCommand(command, argument)]
                }
                const allResults = directResults.concat(prefixedResults)
                let fusableResults: CommandResult[] = []
                let guaranteedResults: CommandResult[] = []
                for (const result of allResults) {
                    if (result.guarantee) {
                        guaranteedResults.push(result)
                    } else {
                        fusableResults.push(result)
                    }
                }
                fusableResults = uniqueBy(fusableResults, (result) => result.display)
                guaranteedResults = uniqueBy(guaranteedResults, (result) => result.display)
                const fusedResults = argument
                    ? new Fuse(fusableResults, {
                          keys: ['display', 'synonyms'],
                      })
                          .search(argument)
                          .slice(0, RESULTS_MAX)
                          .map((result) => result.item)
                    : sample(fusableResults, RESULTS_MAX - guaranteedResults.length)
                return guaranteedResults.concat(fusedResults)
            },
        ],
        commandSearchResultsGrouped: [
            (selectors) => [selectors.commandSearchResults, selectors.activeFlow],
            (commandSearchResults: CommandResult[], activeFlow: CommandFlow | null) => {
                const resultsGrouped: {
                    [scope: string]: CommandResult[]
                } = {}
                if (activeFlow) {
                    resultsGrouped[activeFlow.scope ?? '?'] = []
                }
                for (const result of commandSearchResults) {
                    const scope: string = result.source.scope ?? '?'
                    if (!(scope in resultsGrouped)) {
                        resultsGrouped[scope] = []
                    } // Ensure there's an array to push to
                    resultsGrouped[scope].push({ ...result })
                }
                let rollingGroupIndex = 0
                let rollingResultIndex = 0
                const resultsGroupedInOrder: [string, CommandResultDisplayable[]][] = []
                for (const [group, results] of Object.entries(resultsGrouped)) {
                    resultsGroupedInOrder.push([group, []])
                    for (const result of results) {
                        resultsGroupedInOrder[rollingGroupIndex][1].push({ ...result, index: rollingResultIndex++ })
                    }
                    rollingGroupIndex++
                }
                return resultsGroupedInOrder
            },
        ],
    },

    events: ({ actions }) => ({
        afterMount: () => {
            const { push } = router.actions

            const goTo: Command = {
                key: 'go-to',
                scope: GLOBAL_COMMAND_SCOPE,
                prefixes: ['open', 'visit'],
                resolver: [
                    {
                        icon: FundOutlined,
                        display: 'Go to Dashboards',
                        executor: () => {
                            push(urls.dashboards())
                        },
                    },
                    {
                        icon: RiseOutlined,
                        display: 'Go to Insights',
                        executor: () => {
                            push(urls.savedInsights())
                        },
                    },
                    {
                        icon: RiseOutlined,
                        display: 'Go to Trends',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.TRENDS }))
                        },
                    },
                    {
                        icon: FunnelPlotOutlined,
                        display: 'Go to Funnels',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.FUNNELS }))
                        },
                    },
                    {
                        icon: GatewayOutlined,
                        display: 'Go to Retention',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.RETENTION }))
                        },
                    },
                    {
                        icon: InteractionOutlined,
                        display: 'Go to Paths',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.PATHS }))
                        },
                    },
                    {
                        icon: ContainerOutlined,
                        display: 'Go to Events',
                        executor: () => {
                            push(urls.events())
                        },
                    },
                    {
                        icon: AimOutlined,
                        display: 'Go to Actions',
                        executor: () => {
                            push(urls.actions())
                        },
                    },
                    {
                        icon: UserOutlined,
                        display: 'Go to Persons',
                        synonyms: ['people'],
                        executor: () => {
                            push(urls.persons())
                        },
                    },
                    {
                        icon: UsergroupAddOutlined,
                        display: 'Go to Cohorts',
                        executor: () => {
                            push(urls.cohorts())
                        },
                    },
                    {
                        icon: FlagOutlined,
                        display: 'Go to Feature Flags',
                        synonyms: ['feature flags', 'a/b tests'],
                        executor: () => {
                            push(urls.featureFlags())
                        },
                    },
                    {
                        icon: MessageOutlined,
                        display: 'Go to Annotations',
                        executor: () => {
                            push(urls.annotations())
                        },
                    },
                    {
                        icon: TeamOutlined,
                        display: 'Go to Team members',
                        synonyms: ['organization', 'members', 'invites', 'teammates'],
                        executor: () => {
                            push(urls.organizationSettings())
                        },
                    },
                    {
                        icon: ProjectOutlined,
                        display: 'Go to Project settings',
                        executor: () => {
                            push(urls.projectSettings())
                        },
                    },
                    {
                        icon: SmileOutlined,
                        display: 'Go to My settings',
                        synonyms: ['account'],
                        executor: () => {
                            push(urls.mySettings())
                        },
                    },
                    {
                        icon: ApiOutlined,
                        display: 'Go to Plugins',
                        synonyms: ['integrations'],
                        executor: () => {
                            push(urls.plugins())
                        },
                    },
                    {
                        icon: DatabaseOutlined,
                        display: 'Go to System status page',
                        synonyms: ['redis', 'celery', 'django', 'postgres', 'backend', 'service', 'online'],
                        executor: () => {
                            push(urls.systemStatus())
                        },
                    },
                    {
                        icon: PlusOutlined,
                        display: 'Create action',
                        executor: () => {
                            push(urls.createAction())
                        },
                    },
                    {
                        icon: LogoutOutlined,
                        display: 'Log out',
                        executor: () => {
                            userLogic.actions.logout()
                        },
                    },
                ],
            }

            const debugClickhouseQueries: Command = {
                key: 'debug-clickhouse-queries',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver:
                    userLogic.values.user?.is_staff ||
                    userLogic.values.user?.is_impersonated ||
                    preflightLogic.values.preflight?.is_debug ||
                    preflightLogic.values.preflight?.instance_preferences?.debug_queries
                        ? {
                              icon: PlusOutlined,
                              display: 'Debug queries (ClickHouse)',
                              executor: () => {
                                  debugCHQueries()
                              },
                          }
                        : [],
            }

            const calculator: Command = {
                key: 'calculator',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: (argument) => {
                    // don't try evaluating if there's no argument or if it's a plain number already
                    if (!argument || !isNaN(+argument)) {
                        return null
                    }
                    try {
                        const result = +Parser.evaluate(argument)
                        return isNaN(result)
                            ? null
                            : {
                                  icon: CalculatorOutlined,
                                  display: `= ${result}`,
                                  guarantee: true,
                                  executor: () => {
                                      copyToClipboard(result.toString(), 'calculation result')
                                  },
                              }
                    } catch {
                        return null
                    }
                },
            }

            const openUrls: Command = {
                key: 'open-urls',
                scope: GLOBAL_COMMAND_SCOPE,
                prefixes: ['open', 'visit'],
                resolver: (argument) => {
                    const results: CommandResultTemplate[] = (teamLogic.values.currentTeam?.app_urls ?? []).map(
                        (url: string) => ({
                            icon: LinkOutlined,
                            display: `Open ${url}`,
                            synonyms: [`Visit ${url}`],
                            executor: () => {
                                open(url)
                            },
                        })
                    )
                    if (argument && isURL(argument)) {
                        results.push({
                            icon: LinkOutlined,
                            display: `Open ${argument}`,
                            synonyms: [`Visit ${argument}`],
                            executor: () => {
                                open(argument)
                            },
                        })
                    }
                    results.push({
                        icon: LinkOutlined,
                        display: 'Open PostHog Docs',
                        synonyms: ['technical documentation'],
                        executor: () => {
                            open('https://posthog.com/docs')
                        },
                    })
                    return results
                },
            }

            const createPersonalApiKey: Command = {
                key: 'create-personal-api-key',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: KeyOutlined,
                    display: 'Create Personal API Key',
                    executor: () => ({
                        instruction: 'Give your key a label',
                        icon: TagOutlined,
                        scope: 'Creating Personal API Key',
                        resolver: (argument) => {
                            if (argument?.length) {
                                return {
                                    icon: KeyOutlined,
                                    display: `Create Key "${argument}"`,
                                    executor: () => {
                                        personalAPIKeysLogic.actions.createKey(argument)
                                        push(urls.mySettings(), {}, 'personal-api-keys')
                                    },
                                }
                            }
                            return null
                        },
                    }),
                },
            }

            const createDashboard: Command = {
                key: 'create-dashboard',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: FundOutlined,
                    display: 'Create Dashboard',
                    executor: () => ({
                        instruction: 'Name your new dashboard',
                        icon: TagOutlined,
                        scope: 'Creating Dashboard',
                        resolver: (argument) => {
                            if (argument?.length) {
                                return {
                                    icon: FundOutlined,
                                    display: `Create Dashboard "${argument}"`,
                                    executor: () => {
                                        dashboardsModel.actions.addDashboard({ name: argument, show: true })
                                    },
                                }
                            }
                            return null
                        },
                    }),
                },
            }

            const shareFeedback: Command = {
                key: 'share-feedback',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: CommentOutlined,
                    display: 'Share Feedback',
                    synonyms: ['send opinion', 'ask question', 'message posthog', 'github issue'],
                    executor: () => ({
                        scope: 'Sharing Feedback',
                        resolver: [
                            {
                                display: 'Send Message Directly to PostHog',
                                icon: CommentOutlined,
                                executor: () => ({
                                    instruction: "What's on your mind?",
                                    icon: CommentOutlined,
                                    resolver: (argument) => ({
                                        icon: SendOutlined,
                                        display: 'Send',
                                        executor: !argument?.length
                                            ? undefined
                                            : () => {
                                                  posthog.capture('palette feedback', { message: argument })
                                                  return {
                                                      resolver: {
                                                          icon: CheckOutlined,
                                                          display: 'Message Sent!',
                                                          executor: true,
                                                      },
                                                  }
                                              },
                                    }),
                                }),
                            },
                            {
                                icon: VideoCameraOutlined,
                                display: 'Schedule Quick Call',
                                executor: () => {
                                    open('https://calendly.com/posthog-feedback')
                                },
                            },
                            {
                                icon: ExclamationCircleOutlined,
                                display: 'Create GitHub Issue',
                                executor: () => {
                                    open('https://github.com/PostHog/posthog/issues/new/choose')
                                },
                            },
                        ],
                    }),
                },
            }

            actions.registerCommand(goTo)
            actions.registerCommand(openUrls)
            actions.registerCommand(debugClickhouseQueries)
            actions.registerCommand(calculator)
            actions.registerCommand(createPersonalApiKey)
            actions.registerCommand(createDashboard)
            actions.registerCommand(shareFeedback)
        },
        beforeUnmount: () => {
            actions.deregisterCommand('go-to')
            actions.deregisterCommand('open-urls')
            actions.deregisterCommand('debug-clickhouse-queries')
            actions.deregisterCommand('calculator')
            actions.deregisterCommand('create-personal-api-key')
            actions.deregisterCommand('create-dashboard')
            actions.deregisterCommand('share-feedback')
        },
    }),
})
Example #22
Source File: Header.tsx    From react_admin with MIT License 4 votes vote down vote up
Headers: React.FC<Iprops> = (props) => {
  const { collapsed } = props;
  const [fullScreen, setFullScreen] = useState(false); // 当前是否是全屏状态
  // 进入全屏
  const requestFullScreen = useCallback(() => {
    const element: HTMLElement & Element = document.documentElement;
    // 判断各种浏览器,找到正确的方法
    const requestMethod =
      element.requestFullscreen || // W3C
      element.webkitRequestFullscreen || // Chrome等
      element.mozRequestFullScreen || // FireFox
      element.msRequestFullscreen; // IE11
    if (requestMethod) {
      requestMethod.call(element);
    }
    setFullScreen(true);
  }, []);

  // 退出登录
  const onMenuClick = useCallback(
    (e) => {
      // 退出按钮被点击
      if (e.key === "logout") {
        props.onLogout();
      }
    },
    [props]
  );

  // 退出全屏
  const exitFullScreen = useCallback(() => {
    // 判断各种浏览器,找到正确的方法
    const element: Document & Element = document;
    const exitMethod =
      element.exitFullscreen || // W3C
      element.mozCancelFullScreen || // firefox
      element.webkitExitFullscreen || // Chrome等
      element.msExitFullscreen; // IE11

    if (exitMethod) {
      exitMethod.call(document);
    }
    setFullScreen(false);
  }, []);
  const toggle = () => {
    props.setColl(!collapsed);
  };
  return (
    <Header className="site-layout-background header" style={{ padding: 0 }}>
      <Tooltip title={props.collapsed ? "展开菜单" : "收起菜单"}>
        {React.createElement(
          collapsed ? MenuUnfoldOutlined : MenuFoldOutlined,
          {
            className: "trigger",
            onClick: toggle,
          }
        )}
      </Tooltip>
      <div className="rightBox">
        <Tooltip placement="bottom" title={fullScreen ? "退出全屏" : "全屏"}>
          <div className="full all_center">
            {fullScreen ? (
              <FullscreenExitOutlined
                className="icon"
                onClick={exitFullScreen}
              />
            ) : (
              <FullscreenOutlined
                className="icon"
                onClick={requestFullScreen}
              />
            )}
          </div>
        </Tooltip>
        <Dropdown
          overlay={
            <Menu className="menu" selectedKeys={[]} onClick={onMenuClick}>
              <Menu.Item key="user">
                <Link to="/home/user/admin">
                  <UserOutlined />
                  个人中心
                </Link>
              </Menu.Item>
              <Menu.Item key="message">
                <Link to="/home/user/level">
                  <MessageOutlined />
                  个人设置
                </Link>
              </Menu.Item>
              <Menu.Divider />
              <Menu.Item key="logout">
                <LogoutOutlined />
                退出登录
              </Menu.Item>
            </Menu>
          }
          placement="bottomRight"
        >
          <div className="userhead all_center">
            <SmileOutlined />
            <span className="username">admin</span>
          </div>
        </Dropdown>
      </div>
    </Header>
  );
}