From 645a88e7e35d15cec6106709c42b071bec045e0d Mon Sep 17 00:00:00 2001 From: crupest Date: Wed, 2 Aug 2023 02:52:07 +0800 Subject: ... --- FrontEnd/src/views/admin/Admin.tsx | 27 -- FrontEnd/src/views/admin/AdminNav.tsx | 29 -- FrontEnd/src/views/admin/MoreAdmin.tsx | 7 - FrontEnd/src/views/admin/UserAdmin.tsx | 304 ---------------- FrontEnd/src/views/admin/index.css | 33 -- FrontEnd/src/views/admin/index.tsx | 7 - FrontEnd/src/views/center/CenterBoards.tsx | 131 ------- FrontEnd/src/views/center/TimelineBoard.tsx | 390 --------------------- FrontEnd/src/views/center/TimelineCreateDialog.tsx | 57 --- FrontEnd/src/views/center/index.css | 43 --- FrontEnd/src/views/center/index.tsx | 60 ---- FrontEnd/src/views/common/button/LoadingButton.css | 2 +- FrontEnd/src/views/search/index.css | 15 - FrontEnd/src/views/search/index.tsx | 131 ------- 14 files changed, 1 insertion(+), 1235 deletions(-) delete mode 100644 FrontEnd/src/views/admin/Admin.tsx delete mode 100644 FrontEnd/src/views/admin/AdminNav.tsx delete mode 100644 FrontEnd/src/views/admin/MoreAdmin.tsx delete mode 100644 FrontEnd/src/views/admin/UserAdmin.tsx delete mode 100644 FrontEnd/src/views/admin/index.css delete mode 100644 FrontEnd/src/views/admin/index.tsx delete mode 100644 FrontEnd/src/views/center/CenterBoards.tsx delete mode 100644 FrontEnd/src/views/center/TimelineBoard.tsx delete mode 100644 FrontEnd/src/views/center/TimelineCreateDialog.tsx delete mode 100644 FrontEnd/src/views/center/index.css delete mode 100644 FrontEnd/src/views/center/index.tsx delete mode 100644 FrontEnd/src/views/search/index.css delete mode 100644 FrontEnd/src/views/search/index.tsx (limited to 'FrontEnd/src/views') diff --git a/FrontEnd/src/views/admin/Admin.tsx b/FrontEnd/src/views/admin/Admin.tsx deleted file mode 100644 index 986c36b4..00000000 --- a/FrontEnd/src/views/admin/Admin.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Route, Routes } from "react-router-dom"; -import { useTranslation } from "react-i18next"; - -import AdminNav from "./AdminNav"; -import UserAdmin from "./UserAdmin"; -import MoreAdmin from "./MoreAdmin"; - -import "./index.css"; - -const Admin: React.FC = () => { - useTranslation("admin"); - - return ( - <> -
- - - } /> - } /> - } /> - -
- - ); -}; - -export default Admin; diff --git a/FrontEnd/src/views/admin/AdminNav.tsx b/FrontEnd/src/views/admin/AdminNav.tsx deleted file mode 100644 index b7385e5c..00000000 --- a/FrontEnd/src/views/admin/AdminNav.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useLocation } from "react-router-dom"; - -import Tabs from "../common/tab/Tabs"; - -export function AdminNav({ className }: { className?: string }) { - const location = useLocation(); - const name = location.pathname.split("/")[2] ?? "user"; - - return ( - - ); -} - -export default AdminNav; diff --git a/FrontEnd/src/views/admin/MoreAdmin.tsx b/FrontEnd/src/views/admin/MoreAdmin.tsx deleted file mode 100644 index d49d211f..00000000 --- a/FrontEnd/src/views/admin/MoreAdmin.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import * as React from "react"; - -const MoreAdmin: React.FC = () => { - return <>More...; -}; - -export default MoreAdmin; diff --git a/FrontEnd/src/views/admin/UserAdmin.tsx b/FrontEnd/src/views/admin/UserAdmin.tsx deleted file mode 100644 index d5179bf5..00000000 --- a/FrontEnd/src/views/admin/UserAdmin.tsx +++ /dev/null @@ -1,304 +0,0 @@ -import { useState, useEffect } from "react"; -import * as React from "react"; -import { Trans, useTranslation } from "react-i18next"; -import classnames from "classnames"; - -import { getHttpUserClient, HttpUser, kUserPermissionList } from "@/http/user"; - -import OperationDialog, { - OperationDialogBoolInput, -} from "../common/dialog/OperationDialog"; -import Button from "../common/button/Button"; -import Spinner from "../common/Spinner"; -import FlatButton from "../common/button/FlatButton"; -import IconButton from "../common/button/IconButton"; - -const CreateUserDialog: React.FC<{ - open: boolean; - close: () => void; - onSuccess: (user: HttpUser) => void; -}> = ({ open, close, onSuccess }) => { - return ( - - getHttpUserClient().post({ - username, - password, - }) - } - onClose={close} - open={open} - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UsernameLabel: React.FC<{ children: React.ReactNode }> = (props) => { - return {props.children}; -}; - -const UserDeleteDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - return ( - ( - - 0{user.username}2 - - )} - onProcess={() => getHttpUserClient().delete(user.username)} - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UserModifyDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - return ( - ( - - 0{user.username}2 - - )} - inputScheme={ - [ - { - type: "text", - label: "admin:user.username", - initValue: user.username, - }, - { type: "text", label: "admin:user.password" }, - { - type: "text", - label: "admin:user.nickname", - initValue: user.nickname, - }, - ] as const - } - onProcess={([username, password, nickname]) => - getHttpUserClient().patch(user.username, { - username: username !== user.username ? username : undefined, - password: password !== "" ? password : undefined, - nickname: nickname !== user.nickname ? nickname : undefined, - }) - } - onSuccessAndClose={onSuccess} - /> - ); -}; - -const UserPermissionModifyDialog: React.FC<{ - open: boolean; - close: () => void; - user: HttpUser; - onSuccess: () => void; -}> = ({ open, close, user, onSuccess }) => { - const oldPermissionBoolList: boolean[] = kUserPermissionList.map( - (permission) => user.permissions.includes(permission) - ); - - return ( - ( - - 0{user.username}2 - - )} - inputScheme={kUserPermissionList.map( - (permission, index) => ({ - type: "bool", - label: { type: "custom", value: permission }, - initValue: oldPermissionBoolList[index], - }) - )} - onProcess={async (newPermissionBoolList): Promise => { - for (let index = 0; index < kUserPermissionList.length; index++) { - const oldValue = oldPermissionBoolList[index]; - const newValue = newPermissionBoolList[index]; - const permission = kUserPermissionList[index]; - if (oldValue === newValue) continue; - if (newValue) { - await getHttpUserClient().putUserPermission( - user.username, - permission - ); - } else { - await getHttpUserClient().deleteUserPermission( - user.username, - permission - ); - } - } - return newPermissionBoolList; - }} - onSuccessAndClose={onSuccess} - /> - ); -}; - -interface UserItemProps { - user: HttpUser; - onChange: () => void; -} - -const UserItem: React.FC = ({ user, onChange }) => { - const { t } = useTranslation(); - - const [dialog, setDialog] = useState< - "delete" | "modify" | "permission" | null - >(null); - - const [editMaskVisible, setEditMaskVisible] = React.useState(false); - - return ( - <> -
- setEditMaskVisible(true)} - /> -
{user.username}
- - {t("admin:user.nickname")} - {user.nickname} - - - {t("admin:user.uniqueId")} - {user.uniqueId} - - - {t("admin:user.permissions")} - {user.permissions.map((permission) => { - return ( - - {permission} - - ); - })} - -
setEditMaskVisible(false)} - > - setDialog("modify")} - /> - setDialog("permission")} - /> - setDialog("delete")} - /> -
-
- setDialog(null)} - user={user} - onSuccess={onChange} - /> - setDialog(null)} - user={user} - onSuccess={onChange} - /> - setDialog(null)} - user={user} - onSuccess={onChange} - /> - - ); -}; - -const UserAdmin: React.FC = () => { - const [users, setUsers] = useState(null); - const [dialog, setDialog] = useState<"create" | null>(null); - const [usersVersion, setUsersVersion] = useState(0); - const updateUsers = (): void => { - setUsersVersion(usersVersion + 1); - }; - - useEffect(() => { - let subscribe = true; - void getHttpUserClient() - .list() - .then((us) => { - if (subscribe) { - setUsers(us.items); - } - }); - return () => { - subscribe = false; - }; - }, [usersVersion]); - - if (users) { - const userComponents = users.map((user) => { - return ( - - ); - }); - - return ( - <> -
-
-
-
- {userComponents} - setDialog(null)} - onSuccess={updateUsers} - /> - - ); - } else { - return ; - } -}; - -export default UserAdmin; diff --git a/FrontEnd/src/views/admin/index.css b/FrontEnd/src/views/admin/index.css deleted file mode 100644 index 17e24586..00000000 --- a/FrontEnd/src/views/admin/index.css +++ /dev/null @@ -1,33 +0,0 @@ -.admin-user-item { - position: relative; - border: var(--cru-primary-color) solid; - border-width: 1px 1px 0; - padding: 1em; -} - -.admin-user-item:last-of-type { - border-bottom-width: 1px; -} - -.admin-user-item .edit-mask { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: rgba(255, 255, 255, 0.9); - position: absolute; - display: flex; - justify-content: space-around; - align-items: center; -} - -@media (max-width: 576px) { - .admin-user-item .edit-mask { - flex-direction: column; - } -} - -.admin-user-item .edit-mask button { - margin: 0.5em 2em; -} diff --git a/FrontEnd/src/views/admin/index.tsx b/FrontEnd/src/views/admin/index.tsx deleted file mode 100644 index 0467711d..00000000 --- a/FrontEnd/src/views/admin/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { lazy } from "react"; - -const Admin = lazy( - () => import(/* webpackChunkName: "admin" */ "./Admin") -); - -export default Admin; diff --git a/FrontEnd/src/views/center/CenterBoards.tsx b/FrontEnd/src/views/center/CenterBoards.tsx deleted file mode 100644 index a8be2c29..00000000 --- a/FrontEnd/src/views/center/CenterBoards.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import * as React from "react"; -import { useTranslation } from "react-i18next"; - -import { highlightTimelineUsername } from "@/common"; - -import { pushAlert } from "@/services/alert"; -import { useUserLoggedIn } from "@/services/user"; - -import { getHttpTimelineClient } from "@/http/timeline"; -import { getHttpBookmarkClient } from "@/http/bookmark"; - -import TimelineBoard from "./TimelineBoard"; - -const CenterBoards: React.FC = () => { - const { t } = useTranslation(); - - const user = useUserLoggedIn(); - - return ( - <> -
-
-
-
- - getHttpBookmarkClient() - .list(user.username) - .then((p) => p.items) - } - editHandler={{ - onDelete: (owner, timeline) => { - return getHttpBookmarkClient() - .delete(user.username, owner, timeline) - .catch((e) => { - pushAlert({ - message: "home.message.deleteBookmarkFail", - type: "danger", - }); - throw e; - }); - }, - onMove: (owner, timeline, index, offset) => { - return getHttpBookmarkClient() - .move( - user.username, - owner, - timeline, - index + offset + 1 // +1 because backend contract: index starts at 1 - ) - .catch((e) => { - pushAlert({ - message: "home.message.moveBookmarkFail", - type: "danger", - }); - throw e; - }) - .then(); - }, - }} - /> -
-
- - getHttpBookmarkClient() - .list(highlightTimelineUsername) - .then((p) => p.items) - } - editHandler={ - user.username === highlightTimelineUsername - ? { - onDelete: (owner, timeline) => { - return getHttpBookmarkClient() - .delete(highlightTimelineUsername, owner, timeline) - .catch((e) => { - pushAlert({ - message: "home.message.deleteHighlightFail", - type: "danger", - }); - throw e; - }); - }, - onMove: (owner, timeline, index, offset) => { - return getHttpBookmarkClient() - .move( - highlightTimelineUsername, - owner, - timeline, - index + offset + 1 // +1 because backend contract: index starts at 1 - ) - .catch((e) => { - pushAlert({ - message: "home.message.moveBookmarkFail", - type: "danger", - }); - throw e; - }) - .then(); - }, - } - : undefined - } - /> -
-
-
-
- - getHttpTimelineClient() - .listTimeline({ relate: user.username }) - .then((l) => - l.map((t, index) => ({ - timelineOwner: t.owner.username, - timelineName: t.nameV2, - position: index + 1, - })) - ) - } - /> -
-
- - ); -}; - -export default CenterBoards; diff --git a/FrontEnd/src/views/center/TimelineBoard.tsx b/FrontEnd/src/views/center/TimelineBoard.tsx deleted file mode 100644 index b3ccdf8c..00000000 --- a/FrontEnd/src/views/center/TimelineBoard.tsx +++ /dev/null @@ -1,390 +0,0 @@ -import * as React from "react"; -import classnames from "classnames"; -import { Link } from "react-router-dom"; - -import { TimelineBookmark } from "@/http/bookmark"; - -import TimelineLogo from "../common/TimelineLogo"; -import LoadFailReload from "../common/LoadFailReload"; -import FlatButton from "../common/button/FlatButton"; -import Card from "../common/Card"; -import Spinner from "../common/Spinner"; -import IconButton from "../common/button/IconButton"; - -interface TimelineBoardItemProps { - timeline: TimelineBookmark; - // In height. - offset?: number; - // In px. - arbitraryOffset?: number; - // If not null, will disable navigation on click. - actions?: { - onDelete: () => void; - onMove: { - start: (e: React.PointerEvent) => void; - moving: (e: React.PointerEvent) => void; - end: (e: React.PointerEvent) => void; - }; - }; -} - -const TimelineBoardItem: React.FC = ({ - timeline, - arbitraryOffset, - offset, - actions, -}) => { - const content = ( - <> - - - {timeline.timelineOwner}/{timeline.timelineName} - - - {actions != null ? ( -
- - { - e.currentTarget.setPointerCapture(e.pointerId); - actions.onMove.start(e); - }} - onPointerUp={(e) => { - actions.onMove.end(e); - try { - e.currentTarget.releasePointerCapture(e.pointerId); - } catch (_) { - void null; - } - }} - onPointerMove={actions.onMove.moving} - /> -
- ) : null} - - ); - - const offsetStyle: React.CSSProperties = { - transform: - arbitraryOffset != null - ? `translate(0,${arbitraryOffset}px)` - : offset != null - ? `translate(0,${offset * 100}%)` - : undefined, - transition: offset != null ? "transform 0.5s" : undefined, - zIndex: arbitraryOffset != null ? 1 : undefined, - }; - - return actions == null ? ( - - {content} - - ) : ( -
- {content} -
- ); -}; - -interface TimelineBoardItemContainerProps { - timelines: TimelineBookmark[]; - editHandler?: { - // offset may exceed index range plusing index. - onMove: ( - owner: string, - timeline: string, - index: number, - offset: number - ) => void; - onDelete: (owner: string, timeline: string) => void; - }; -} - -const TimelineBoardItemContainer: React.FC = ({ - timelines, - editHandler, -}) => { - const [moveState, setMoveState] = React.useState(null); - - return ( - <> - {timelines.map((timeline, index) => { - const height = 48; - - let offset: number | undefined = undefined; - let arbitraryOffset: number | undefined = undefined; - if (moveState != null) { - if (index === moveState.index) { - arbitraryOffset = moveState.offset; - } else { - if (moveState.offset >= 0) { - const offsetCount = Math.round(moveState.offset / height); - if ( - index > moveState.index && - index <= moveState.index + offsetCount - ) { - offset = -1; - } else { - offset = 0; - } - } else { - const offsetCount = Math.round(-moveState.offset / height); - if ( - index < moveState.index && - index >= moveState.index - offsetCount - ) { - offset = 1; - } else { - offset = 0; - } - } - } - } - - return ( - { - editHandler.onDelete( - timeline.timelineOwner, - timeline.timelineName - ); - }, - onMove: { - start: (e) => { - if (moveState != null) return; - setMoveState({ - index, - offset: 0, - startPointY: e.clientY, - }); - }, - moving: (e) => { - if (moveState == null) return; - setMoveState({ - index, - offset: e.clientY - moveState.startPointY, - startPointY: moveState.startPointY, - }); - }, - end: () => { - if (moveState != null) { - const offsetCount = Math.round( - moveState.offset / height - ); - editHandler.onMove( - timeline.timelineOwner, - timeline.timelineName, - moveState.index, - offsetCount - ); - } - setMoveState(null); - }, - }, - } - : undefined - } - /> - ); - })} - - ); -}; - -interface TimelineBoardUIProps { - title?: string | null; - state: "offline" | "loading" | "loaded"; - timelines: TimelineBookmark[]; - onReload: () => void; - className?: string; - editHandler?: { - onMove: ( - owner: string, - timeline: string, - index: number, - offset: number - ) => void; - onDelete: (owner: string, timeline: string) => void; - }; -} - -const TimelineBoardUI: React.FC = (props) => { - const { title, state, timelines, className, editHandler } = props; - - const editable = editHandler != null; - - const [editing, setEditing] = React.useState(false); - - return ( - -
- {title != null &&

{title}

} - {editable && - (editing ? ( - { - setEditing(false); - }} - /> - ) : ( - { - setEditing(true); - }} - /> - ))} -
- {(() => { - if (state === "loading") { - return ( -
- -
- ); - } else if (state === "offline") { - return ( -
- -
- ); - } else { - return ( - { - if (index + offset >= timelines.length) { - offset = timelines.length - index - 1; - } else if (index + offset < 0) { - offset = -index; - } - editHandler.onMove(owner, timeline, index, offset); - }, - } - : undefined - } - /> - ); - } - })()} -
- ); -}; - -export interface TimelineBoardProps { - title?: string | null; - className?: string; - load: () => Promise; - editHandler?: { - onMove: ( - owner: string, - timeline: string, - index: number, - offset: number - ) => Promise; - onDelete: (owner: string, timeline: string) => Promise; - }; -} - -const TimelineBoard: React.FC = ({ - className, - title, - load, - editHandler, -}) => { - const [state, setState] = React.useState<"offline" | "loading" | "loaded">( - "loading" - ); - const [timelines, setTimelines] = React.useState([]); - - React.useEffect(() => { - let subscribe = true; - if (state === "loading") { - void load().then( - (timelines) => { - if (subscribe) { - setState("loaded"); - setTimelines(timelines); - } - }, - () => { - setState("offline"); - } - ); - } - return () => { - subscribe = false; - }; - }, [load, state]); - - return ( - { - setState("loaded"); - }} - editHandler={ - typeof timelines === "object" && editHandler != null - ? { - onMove: (owner, timeline, index, offset) => { - const newTimelines = timelines.slice(); - const [t] = newTimelines.splice(index, 1); - newTimelines.splice(index + offset, 0, t); - setTimelines(newTimelines); - editHandler - .onMove(owner, timeline, index, offset) - .then(null, () => { - setTimelines(timelines); - }); - }, - onDelete: (owner, timeline) => { - const newTimelines = timelines.slice(); - newTimelines.splice( - timelines.findIndex( - (t) => - t.timelineOwner === owner && t.timelineName === timeline - ), - 1 - ); - setTimelines(newTimelines); - editHandler.onDelete(owner, timeline).then(null, () => { - setTimelines(timelines); - }); - }, - } - : undefined - } - /> - ); -}; - -export default TimelineBoard; diff --git a/FrontEnd/src/views/center/TimelineCreateDialog.tsx b/FrontEnd/src/views/center/TimelineCreateDialog.tsx deleted file mode 100644 index 63742936..00000000 --- a/FrontEnd/src/views/center/TimelineCreateDialog.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import * as React from "react"; -import { useNavigate } from "react-router-dom"; - -import { validateTimelineName } from "@/services/timeline"; -import { getHttpTimelineClient, HttpTimelineInfo } from "@/http/timeline"; - -import OperationDialog from "../common/dialog/OperationDialog"; -import { useUserLoggedIn } from "@/services/user"; - -interface TimelineCreateDialogProps { - open: boolean; - close: () => void; -} - -const TimelineCreateDialog: React.FC = (props) => { - const navigate = useNavigate(); - - const user = useUserLoggedIn(); - - return ( - { - if (name.length === 0) { - return { 0: "home.createDialog.noEmpty" }; - } else if (name.length > 26) { - return { 0: "home.createDialog.tooLong" }; - } else if (!validateTimelineName(name)) { - return { 0: "home.createDialog.badFormat" }; - } else { - return null; - } - }} - onProcess={([name]): Promise => - getHttpTimelineClient().postTimeline({ name }) - } - onSuccessAndClose={(timeline: HttpTimelineInfo) => { - navigate(`${user.username}/${timeline.nameV2}`); - }} - failurePrompt={(e) => `${e as string}`} - /> - ); -}; - -export default TimelineCreateDialog; diff --git a/FrontEnd/src/views/center/index.css b/FrontEnd/src/views/center/index.css deleted file mode 100644 index a779ff90..00000000 --- a/FrontEnd/src/views/center/index.css +++ /dev/null @@ -1,43 +0,0 @@ -.timeline-board { - min-height: 200px; - height: 100%; - position: relative; - padding: 1em 0; - display: flex; - flex-direction: column; -} - -.timeline-board-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 1em; -} - -.timeline-board-item { - font-size: 1.1em; - height: 48px; - transition: background 0.3s; - display: flex; - align-items: center; - padding: 0 1em; -} - -.timeline-board-item .icon { - height: 1.3em; - color: black; -} - -.timeline-board-item:hover { - background: #dee2e6; -} -.timeline-board-item .right { - display: flex; - align-items: center; - flex-shrink: 0; -} -.timeline-board-item .title { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} diff --git a/FrontEnd/src/views/center/index.tsx b/FrontEnd/src/views/center/index.tsx deleted file mode 100644 index 77af2c20..00000000 --- a/FrontEnd/src/views/center/index.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import * as React from "react"; -import { useNavigate } from "react-router-dom"; - -import { useUserLoggedIn } from "@/services/user"; - -import SearchInput from "../common/SearchInput"; -import Button from "../common/button/Button"; -import CenterBoards from "./CenterBoards"; -import TimelineCreateDialog from "./TimelineCreateDialog"; - -import "./index.css"; - -const HomePage: React.FC = () => { - const navigate = useNavigate(); - - const user = useUserLoggedIn(); - - const [navText, setNavText] = React.useState(""); - - const [dialog, setDialog] = React.useState<"create" | null>(null); - - return ( - <> -
-
-
- { - navigate(`search?q=${navText}`); - }} - additionalButton={ - user != null && ( -
-
- -
- { - setDialog(null); - }} - /> - - ); -}; - -export default HomePage; diff --git a/FrontEnd/src/views/common/button/LoadingButton.css b/FrontEnd/src/views/common/button/LoadingButton.css index 2f73116a..0a7e4a3a 100644 --- a/FrontEnd/src/views/common/button/LoadingButton.css +++ b/FrontEnd/src/views/common/button/LoadingButton.css @@ -11,4 +11,4 @@ .cru-loading-button-spinner { margin-left: 0.5em; -} +} \ No newline at end of file diff --git a/FrontEnd/src/views/search/index.css b/FrontEnd/src/views/search/index.css deleted file mode 100644 index 6ff4d9fa..00000000 --- a/FrontEnd/src/views/search/index.css +++ /dev/null @@ -1,15 +0,0 @@ -.timeline-search-result-item { - border: 1px solid; - border-color: #e9ecef; - background: #f8f9fa; - transition: all 0.3s; -} -.timeline-search-result-item:hover { - border-color: #0d6efd; -} - -.timeline-search-result-item-avatar { - width: 2em; - height: 2em; - border-radius: 50%; -} diff --git a/FrontEnd/src/views/search/index.tsx b/FrontEnd/src/views/search/index.tsx deleted file mode 100644 index 58257465..00000000 --- a/FrontEnd/src/views/search/index.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import * as React from "react"; -import { useTranslation } from "react-i18next"; -import { useNavigate, useLocation } from "react-router-dom"; -import { Link } from "react-router-dom"; - -import { HttpNetworkError } from "@/http/common"; -import { getHttpSearchClient } from "@/http/search"; -import { HttpTimelineInfo } from "@/http/timeline"; - -import SearchInput from "../common/SearchInput"; -import UserAvatar from "../common/user/UserAvatar"; - -import "./index.css"; - -const TimelineSearchResultItemView: React.FC<{ - timeline: HttpTimelineInfo; -}> = ({ timeline }) => { - return ( -
-

- - {timeline.title} - {timeline.nameV2} - -

-
- - {timeline.owner.nickname} - - @{timeline.owner.username} - -
-
- ); -}; - -const SearchPage: React.FC = () => { - const { t } = useTranslation(); - - const navigate = useNavigate(); - const location = useLocation(); - const searchParams = new URLSearchParams(location.search); - const queryParam = searchParams.get("q"); - - const [searchText, setSearchText] = React.useState(""); - const [state, setState] = React.useState< - HttpTimelineInfo[] | "init" | "loading" | "network-error" | "error" - >("init"); - - const [forceResearchKey, setForceResearchKey] = React.useState(0); - - React.useEffect(() => { - setState("init"); - if (queryParam != null && queryParam.length > 0) { - setSearchText(queryParam); - setState("loading"); - void getHttpSearchClient() - .searchTimelines(queryParam) - .then( - (ts) => { - setState(ts); - }, - (e) => { - if (e instanceof HttpNetworkError) { - setState("network-error"); - } else { - setState("error"); - } - } - ); - } - }, [queryParam, forceResearchKey]); - - return ( -
-
- { - if (queryParam === searchText) { - setForceResearchKey((old) => old + 1); - } else { - navigate(`/search?q=${searchText}`); - } - }} - /> -
- {(() => { - switch (state) { - case "init": { - if (queryParam == null || queryParam.length === 0) { - return
{t("searchPage.input")}
; - } - break; - } - case "loading": { - return
{t("searchPage.loading")}
; - } - case "network-error": { - return
{t("error.network")}
; - } - case "error": { - return
{t("error.unknown")}
; - } - default: { - if (state.length === 0) { - return
{t("searchPage.noResult")}
; - } - return state.map((t) => ( - - )); - } - } - })()} -
- ); -}; - -export default SearchPage; -- cgit v1.2.3