diff --git a/api/user.go b/api/user.go index bd82426..a4970dc 100644 --- a/api/user.go +++ b/api/user.go @@ -54,8 +54,8 @@ type UserPatch struct { Email *string `json:"email"` Name *string `json:"name"` Password *string `json:"password"` + ResetOpenID *bool `json:"resetOpenId"` PasswordHash *string - ResetOpenID *bool `json:"resetOpenId"` OpenID *string } diff --git a/web/src/App.tsx b/web/src/App.tsx index 99884a8..b451353 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -6,6 +6,7 @@ import Only from "./components/common/OnlyWhen"; import Auth from "./pages/Auth"; import Home from "./pages/Home"; import WorkspaceDetail from "./pages/WorkspaceDetail"; +import UserDetail from "./pages/UserDetail"; function App() { const navigate = useNavigate(); @@ -30,6 +31,7 @@ function App() { } /> } /> + } /> } /> diff --git a/web/src/components/Header.tsx b/web/src/components/Header.tsx index 47ab250..51d77ed 100644 --- a/web/src/components/Header.tsx +++ b/web/src/components/Header.tsx @@ -16,7 +16,9 @@ const Header: React.FC = () => { return (
- Corgi + navigate("/")}> + Corgi +
{ } actions={ <> - handleSignOutButtonClick()}> + navigate(`/user/${user?.id}`)} + > + My information + + handleSignOutButtonClick()} + > Sign out } + actionsClassName="!w-36" >
diff --git a/web/src/components/ShortcutListView.tsx b/web/src/components/ShortcutListView.tsx index d2aa6ba..f620b94 100644 --- a/web/src/components/ShortcutListView.tsx +++ b/web/src/components/ShortcutListView.tsx @@ -45,6 +45,7 @@ const ShortcutListView: React.FC = (props: Props) => { } + actionsClassName="!w-24" >
); diff --git a/web/src/components/WorkspaceListView.tsx b/web/src/components/WorkspaceListView.tsx index a03700e..79269ea 100644 --- a/web/src/components/WorkspaceListView.tsx +++ b/web/src/components/WorkspaceListView.tsx @@ -49,6 +49,7 @@ const WorkspaceListView: React.FC = (props: Props) => { } + actionsClassName="!w-24" > ); diff --git a/web/src/components/common/Dropdown.tsx b/web/src/components/common/Dropdown.tsx index 272a23c..598ea21 100644 --- a/web/src/components/common/Dropdown.tsx +++ b/web/src/components/common/Dropdown.tsx @@ -1,16 +1,16 @@ import { ReactNode, useEffect, useRef } from "react"; import useToggle from "../../hooks/useToggle"; import Icon from "../Icon"; -import "../../less/common/dropdown.less"; interface Props { trigger?: ReactNode; actions?: ReactNode; className?: string; + actionsClassName?: string; } const Dropdown: React.FC = (props: Props) => { - const { trigger, actions, className } = props; + const { trigger, actions, className, actionsClassName } = props; const [dropdownStatus, toggleDropdownStatus] = useToggle(false); const dropdownWrapperRef = useRef(null); @@ -29,15 +29,25 @@ const Dropdown: React.FC = (props: Props) => { }, [dropdownStatus]); return ( -
toggleDropdownStatus()}> +
toggleDropdownStatus()} + > {trigger ? ( trigger ) : ( - - + + )} -
{actions}
+
+ {actions} +
); }; diff --git a/web/src/components/common/Selector.tsx b/web/src/components/common/Selector.tsx deleted file mode 100644 index ee7f939..0000000 --- a/web/src/components/common/Selector.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { memo, useEffect, useRef } from "react"; -import useToggle from "../../hooks/useToggle"; -import Icon from "../Icon"; -import "../../less/common/selector.less"; - -interface SelectorItem { - text: string; - value: string; -} - -interface Props { - className?: string; - value: string; - dataSource: SelectorItem[]; - handleValueChanged?: (value: string) => void; -} - -const nullItem = { - text: "Select", - value: "", -}; - -const Selector: React.FC = (props: Props) => { - const { className, dataSource, handleValueChanged, value } = props; - const [showSelector, toggleSelectorStatus] = useToggle(false); - - const seletorElRef = useRef(null); - - let currentItem = nullItem; - for (const d of dataSource) { - if (d.value === value) { - currentItem = d; - break; - } - } - - useEffect(() => { - if (showSelector) { - const handleClickOutside = (event: MouseEvent) => { - if (!seletorElRef.current?.contains(event.target as Node)) { - toggleSelectorStatus(false); - } - }; - window.addEventListener("click", handleClickOutside, { - capture: true, - once: true, - }); - } - }, [showSelector]); - - const handleItemClick = (item: SelectorItem) => { - if (handleValueChanged) { - handleValueChanged(item.value); - } - toggleSelectorStatus(false); - }; - - const handleCurrentValueClick = (event: React.MouseEvent) => { - event.stopPropagation(); - toggleSelectorStatus(); - }; - - return ( -
-
- {currentItem.text} - - - -
- -
- {dataSource.length > 0 ? ( - dataSource.map((d) => { - return ( -
{ - handleItemClick(d); - }} - > - {d.text} -
- ); - }) - ) : ( -

Null

- )} -
-
- ); -}; - -export default memo(Selector); diff --git a/web/src/hooks/useRefresh.ts b/web/src/hooks/useRefresh.ts deleted file mode 100644 index e892d9b..0000000 --- a/web/src/hooks/useRefresh.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { useCallback, useState } from "react"; - -const useRefresh = () => { - const [, setBoolean] = useState(false); - - const refresh = useCallback(() => { - setBoolean((ps) => { - return !ps; - }); - }, []); - - return refresh; -}; - -export default useRefresh; diff --git a/web/src/less/common/dropdown.less b/web/src/less/common/dropdown.less deleted file mode 100644 index a37d801..0000000 --- a/web/src/less/common/dropdown.less +++ /dev/null @@ -1,19 +0,0 @@ -.dropdown-wrapper { - @apply relative flex flex-col justify-start items-start select-none; - - > .trigger-button { - @apply flex flex-row justify-center items-center border p-1 rounded shadow text-gray-600 cursor-pointer hover:opacity-80; - - > .icon-img { - @apply w-4 h-auto; - } - } - - > .action-buttons-container { - @apply w-28 mt-1 absolute top-full right-0 flex flex-col justify-start items-start bg-white z-1 border p-1 rounded shadow; - - > button { - @apply w-full text-left px-2 text-sm leading-7 rounded hover:bg-gray-100; - } - } -} diff --git a/web/src/less/common/selector.less b/web/src/less/common/selector.less deleted file mode 100644 index 95d2144..0000000 --- a/web/src/less/common/selector.less +++ /dev/null @@ -1,44 +0,0 @@ -.selector-wrapper { - @apply flex flex-col justify-start items-start relative h-8; - - > .current-value-container { - @apply flex flex-row justify-between items-center w-full h-full rounded px-2 pr-1 bg-white border cursor-pointer select-none; - - &:hover, - &.active { - @apply bg-gray-100; - } - - > .value-text { - @apply text-sm mr-0 truncate; - width: calc(100% - 20px); - } - - > .arrow-text { - @apply flex flex-row justify-center items-center w-4 shrink-0; - - > .icon-img { - @apply w-4 h-auto opacity-40; - } - } - } - - > .items-wrapper { - @apply flex flex-col justify-start items-start absolute top-full left-0 w-auto p-1 mt-1 -ml-2 bg-white rounded-md overflow-y-auto z-1; - min-width: calc(100% + 16px); - max-height: 256px; - box-shadow: 0 0 8px 0 rgb(0 0 0 / 20%); - - > .item-container { - @apply flex flex-col justify-start items-start w-full px-3 text-sm select-none leading-8 cursor-pointer rounded whitespace-nowrap hover:bg-gray-100; - - &.selected { - color: @text-green; - } - } - - > .tip-text { - @apply px-3 py-1 text-sm text-gray-600; - } - } -} diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index a812d43..1168123 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -22,14 +22,16 @@ const Home: React.FC = () => {
{loadingState.isLoading ? null : (
-

Workspace List

- -
showCreateWorkspaceDialog()} - > - Create Workspace +
+ Workspace List +
showCreateWorkspaceDialog()} + > + Create Workspace +
+
)}
diff --git a/web/src/pages/UserDetail.tsx b/web/src/pages/UserDetail.tsx new file mode 100644 index 0000000..a404701 --- /dev/null +++ b/web/src/pages/UserDetail.tsx @@ -0,0 +1,19 @@ +import { useAppSelector } from "../store"; +import Header from "../components/Header"; + +const UserDetail: React.FC = () => { + const { user } = useAppSelector((state) => state.user); + + return ( +
+
+
+

{user?.name}

+

Email: {user?.email}

+

OpenID: {user?.openId}

+
+
+ ); +}; + +export default UserDetail; diff --git a/web/src/pages/WorkspaceDetail.tsx b/web/src/pages/WorkspaceDetail.tsx index a0be532..9c3b949 100644 --- a/web/src/pages/WorkspaceDetail.tsx +++ b/web/src/pages/WorkspaceDetail.tsx @@ -49,22 +49,22 @@ const WorkspaceDetail: React.FC = () => { {loadingState.isLoading ? null : (
+ handleBackToHome()}> + Home + + / + Workspace: {state?.workspace.name} +
+
+ Shortcut List
handleBackToHome()} + className="text-sm flex flex-row justify-start items-center border px-3 py-2 rounded-lg cursor-pointer hover:shadow" + onClick={() => showCreateShortcutDialog(state.workspace.id)} > - Back to Home + Create Shortcut
- Workspace: {state?.workspace.name}
-

Shortcut List

-
showCreateShortcutDialog(state.workspace.id)} - > - Create Shortcut -
)}
diff --git a/web/src/types/modules/user.d.ts b/web/src/types/modules/user.d.ts index d9f6be3..c2c9b16 100644 --- a/web/src/types/modules/user.d.ts +++ b/web/src/types/modules/user.d.ts @@ -9,6 +9,7 @@ interface User { email: string; name: string; + openId: string; } interface UserCreate { @@ -24,6 +25,7 @@ interface UserPatch { name?: string; password?: string; + resetOpenID?: boolean; } interface UserDelete {