mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: clean dropdown
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { Button, Dropdown, Input, Menu, MenuButton, Radio, RadioGroup } from "@mui/joy";
|
import { Button, Dropdown, Input, Menu, MenuButton, MenuItem, Radio, RadioGroup } from "@mui/joy";
|
||||||
import { sortBy } from "lodash-es";
|
import { sortBy } from "lodash-es";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
@ -217,34 +217,16 @@ const MemberSection = () => {
|
|||||||
<MenuButton size="sm">
|
<MenuButton size="sm">
|
||||||
<Icon.MoreVertical className="w-4 h-auto" />
|
<Icon.MoreVertical className="w-4 h-auto" />
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
<Menu>
|
<Menu placement="bottom-end" size="sm">
|
||||||
<button
|
<MenuItem onClick={() => handleChangePasswordClick(user)}>
|
||||||
className="w-full text-left text-sm whitespace-nowrap leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
|
||||||
onClick={() => handleChangePasswordClick(user)}
|
|
||||||
>
|
|
||||||
{t("setting.account-section.change-password")}
|
{t("setting.account-section.change-password")}
|
||||||
</button>
|
</MenuItem>
|
||||||
{user.rowStatus === RowStatus.ACTIVE ? (
|
{user.rowStatus === RowStatus.ACTIVE ? (
|
||||||
<button
|
<MenuItem onClick={() => handleArchiveUserClick(user)}>{t("setting.member-section.archive-member")}</MenuItem>
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
|
||||||
onClick={() => handleArchiveUserClick(user)}
|
|
||||||
>
|
|
||||||
{t("setting.member-section.archive-member")}
|
|
||||||
</button>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<button
|
<MenuItem onClick={() => handleRestoreUserClick(user)}>{t("common.restore")}</MenuItem>
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
<MenuItem onClick={() => handleDeleteUserClick(user)}>{t("setting.member-section.delete-member")}</MenuItem>
|
||||||
onClick={() => handleRestoreUserClick(user)}
|
|
||||||
>
|
|
||||||
{t("common.restore")}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded text-red-600 hover:bg-gray-100 dark:hover:bg-zinc-600"
|
|
||||||
onClick={() => handleDeleteUserClick(user)}
|
|
||||||
>
|
|
||||||
{t("setting.member-section.delete-member")}
|
|
||||||
</button>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Button, Divider, List, ListItem } from "@mui/joy";
|
import { Button, Divider, Dropdown, List, ListItem, Menu, MenuButton, MenuItem } from "@mui/joy";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@ -7,8 +7,8 @@ import { useGlobalStore } from "@/store/module";
|
|||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
import showCreateIdentityProviderDialog from "../CreateIdentityProviderDialog";
|
import showCreateIdentityProviderDialog from "../CreateIdentityProviderDialog";
|
||||||
import { showCommonDialog } from "../Dialog/CommonDialog";
|
import { showCommonDialog } from "../Dialog/CommonDialog";
|
||||||
|
import Icon from "../Icon";
|
||||||
import LearnMore from "../LearnMore";
|
import LearnMore from "../LearnMore";
|
||||||
import Dropdown from "../kit/Dropdown";
|
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
disablePasswordLogin: boolean;
|
disablePasswordLogin: boolean;
|
||||||
@ -78,25 +78,17 @@ const SSOSection = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<Dropdown
|
<Dropdown>
|
||||||
actionsClassName="!w-28"
|
<MenuButton size="sm">
|
||||||
actions={
|
<Icon.MoreVertical className="w-4 h-auto" />
|
||||||
<>
|
</MenuButton>
|
||||||
<button
|
<Menu placement="bottom-end" size="sm">
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
<MenuItem onClick={() => showCreateIdentityProviderDialog(identityProvider, fetchIdentityProviderList)}>
|
||||||
onClick={() => showCreateIdentityProviderDialog(identityProvider, fetchIdentityProviderList)}
|
|
||||||
>
|
|
||||||
{t("common.edit")}
|
{t("common.edit")}
|
||||||
</button>
|
</MenuItem>
|
||||||
<button
|
<MenuItem onClick={() => handleDeleteIdentityProvider(identityProvider)}>{t("common.delete")}</MenuItem>
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded text-red-600 hover:bg-gray-100 dark:hover:bg-zinc-600"
|
</Menu>
|
||||||
onClick={() => handleDeleteIdentityProvider(identityProvider)}
|
</Dropdown>
|
||||||
>
|
|
||||||
{t("common.delete")}
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Button, Divider, IconButton, List, ListItem, Radio, RadioGroup } from "@mui/joy";
|
import { Button, Divider, Dropdown, IconButton, List, ListItem, Menu, MenuButton, MenuItem, Radio, RadioGroup } from "@mui/joy";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@ -10,7 +10,6 @@ import { showCommonDialog } from "../Dialog/CommonDialog";
|
|||||||
import Icon from "../Icon";
|
import Icon from "../Icon";
|
||||||
import LearnMore from "../LearnMore";
|
import LearnMore from "../LearnMore";
|
||||||
import showUpdateLocalStorageDialog from "../UpdateLocalStorageDialog";
|
import showUpdateLocalStorageDialog from "../UpdateLocalStorageDialog";
|
||||||
import Dropdown from "../kit/Dropdown";
|
|
||||||
|
|
||||||
const StorageSection = () => {
|
const StorageSection = () => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
@ -100,25 +99,15 @@ const StorageSection = () => {
|
|||||||
<p className="ml-2">{storage.name}</p>
|
<p className="ml-2">{storage.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
<Dropdown
|
<Dropdown>
|
||||||
actionsClassName="!w-28"
|
<MenuButton size="sm">
|
||||||
actions={
|
<Icon.MoreVertical className="w-4 h-auto" />
|
||||||
<>
|
</MenuButton>
|
||||||
<button
|
<Menu placement="bottom-end" size="sm">
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded hover:bg-gray-100 dark:hover:bg-zinc-600"
|
<MenuItem onClick={() => showCreateStorageServiceDialog(storage, fetchStorageList)}>{t("common.edit")}</MenuItem>
|
||||||
onClick={() => showCreateStorageServiceDialog(storage, fetchStorageList)}
|
<MenuItem onClick={() => handleDeleteStorage(storage)}>{t("common.delete")}</MenuItem>
|
||||||
>
|
</Menu>
|
||||||
{t("common.edit")}
|
</Dropdown>
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="w-full text-left text-sm leading-6 py-1 px-3 cursor-pointer rounded text-red-600 hover:bg-gray-100 dark:hover:bg-zinc-600"
|
|
||||||
onClick={() => handleDeleteStorage(storage)}
|
|
||||||
>
|
|
||||||
{t("common.delete")}
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
import { ReactNode, useEffect, useRef } from "react";
|
|
||||||
import useToggle from "react-use/lib/useToggle";
|
|
||||||
import Icon from "../Icon";
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
trigger?: ReactNode;
|
|
||||||
actions?: ReactNode;
|
|
||||||
disabled?: boolean;
|
|
||||||
className?: string;
|
|
||||||
actionsClassName?: string;
|
|
||||||
positionClassName?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Dropdown: React.FC<Props> = (props: Props) => {
|
|
||||||
const { trigger, actions, disabled, className, actionsClassName, positionClassName } = props;
|
|
||||||
const [dropdownStatus, toggleDropdownStatus] = useToggle(false);
|
|
||||||
const dropdownWrapperRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (dropdownStatus) {
|
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
|
||||||
if (!dropdownWrapperRef.current?.contains(event.target as Node)) {
|
|
||||||
toggleDropdownStatus(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
window.addEventListener("click", handleClickOutside, {
|
|
||||||
capture: true,
|
|
||||||
once: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [dropdownStatus]);
|
|
||||||
|
|
||||||
const handleDropdownClick = () => {
|
|
||||||
if (disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
toggleDropdownStatus();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={dropdownWrapperRef}
|
|
||||||
className={`relative flex flex-col justify-start items-start select-none ${className ?? ""}`}
|
|
||||||
onClick={handleDropdownClick}
|
|
||||||
>
|
|
||||||
{trigger ? (
|
|
||||||
trigger
|
|
||||||
) : (
|
|
||||||
<button className="flex flex-row justify-center items-center border dark:border-zinc-700 p-1 rounded shadow text-gray-600 dark:text-gray-200 cursor-pointer hover:opacity-80">
|
|
||||||
<Icon.MoreHorizontal className="w-4 h-auto" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className={`w-auto absolute flex flex-col justify-start items-start bg-white dark:bg-zinc-700 z-10 p-1 rounded-md shadow ${
|
|
||||||
dropdownStatus ? "" : "!hidden"
|
|
||||||
} ${actionsClassName ?? ""} ${positionClassName ?? "top-full right-0 mt-1"}`}
|
|
||||||
>
|
|
||||||
{actions}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Dropdown;
|
|
@ -1,50 +0,0 @@
|
|||||||
.date-picker-wrapper {
|
|
||||||
@apply flex flex-col justify-start items-start p-4;
|
|
||||||
|
|
||||||
> .date-picker-header {
|
|
||||||
@apply flex flex-row justify-center items-center w-full mb-2;
|
|
||||||
|
|
||||||
> .btn-text {
|
|
||||||
@apply w-6 h-6 rounded cursor-pointer select-none flex flex-col justify-center items-center opacity-40 hover:bg-gray-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .normal-text {
|
|
||||||
@apply mx-1 leading-6 font-mono;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .date-picker-day-container {
|
|
||||||
@apply flex flex-row justify-start items-start;
|
|
||||||
width: 280px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
> .date-picker-day-header {
|
|
||||||
@apply flex flex-row justify-around items-center w-full;
|
|
||||||
|
|
||||||
> .day-item {
|
|
||||||
@apply w-9 h-9 select-none flex flex-col justify-center items-center;
|
|
||||||
color: gray;
|
|
||||||
font-size: 13px;
|
|
||||||
margin: 2px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .day-item {
|
|
||||||
@apply w-9 h-9 rounded-full text-sm select-none cursor-pointer flex flex-col justify-center items-center hover:bg-gray-200 dark:hover:bg-zinc-600;
|
|
||||||
margin: 2px;
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
@apply text-blue-600 !bg-blue-100 text-base font-medium;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
@apply cursor-not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.null {
|
|
||||||
background-color: unset;
|
|
||||||
cursor: unset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user