From 47587812b809fee2a95c76266d9d0e42fc4ac1ca Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 15 Jun 2021 14:14:28 +0800 Subject: ... --- FrontEnd/src/app/views/center/CenterBoards.tsx | 107 ------ FrontEnd/src/app/views/center/TimelineBoard.tsx | 370 --------------------- .../src/app/views/center/TimelineCreateDialog.tsx | 53 --- FrontEnd/src/app/views/center/center.sass | 36 -- FrontEnd/src/app/views/center/index.tsx | 64 ---- 5 files changed, 630 deletions(-) delete mode 100644 FrontEnd/src/app/views/center/CenterBoards.tsx delete mode 100644 FrontEnd/src/app/views/center/TimelineBoard.tsx delete mode 100644 FrontEnd/src/app/views/center/TimelineCreateDialog.tsx delete mode 100644 FrontEnd/src/app/views/center/center.sass delete mode 100644 FrontEnd/src/app/views/center/index.tsx (limited to 'FrontEnd/src/app/views/center') diff --git a/FrontEnd/src/app/views/center/CenterBoards.tsx b/FrontEnd/src/app/views/center/CenterBoards.tsx deleted file mode 100644 index f5200415..00000000 --- a/FrontEnd/src/app/views/center/CenterBoards.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import React from "react"; -import { Row, Col } from "react-bootstrap"; -import { useTranslation } from "react-i18next"; - -import { pushAlert } from "@/services/alert"; -import { useUserLoggedIn } from "@/services/user"; - -import { getHttpTimelineClient } from "@/http/timeline"; -import { getHttpBookmarkClient } from "@/http/bookmark"; -import { getHttpHighlightClient } from "@/http/highlight"; - -import TimelineBoard from "./TimelineBoard"; - -const CenterBoards: React.FC = () => { - const { t } = useTranslation(); - - const user = useUserLoggedIn(); - - return ( - <> - - - - - getHttpBookmarkClient().list()} - editHandler={{ - onDelete: (timeline) => { - return getHttpBookmarkClient() - .delete(timeline) - .catch((e) => { - pushAlert({ - message: "home.message.deleteBookmarkFail", - type: "danger", - }); - throw e; - }); - }, - onMove: (timeline, index, offset) => { - return getHttpBookmarkClient() - .move( - { timeline, newPosition: index + offset + 1 } // +1 because backend contract: index starts at 1 - ) - .catch((e) => { - pushAlert({ - message: "home.message.moveBookmarkFail", - type: "danger", - }); - throw e; - }); - }, - }} - /> - - - getHttpHighlightClient().list()} - editHandler={ - user.hasHighlightTimelineAdministrationPermission - ? { - onDelete: (timeline) => { - return getHttpHighlightClient() - .delete(timeline) - .catch((e) => { - pushAlert({ - message: "home.message.deleteHighlightFail", - type: "danger", - }); - throw e; - }); - }, - onMove: (timeline, index, offset) => { - return getHttpHighlightClient() - .move( - { timeline, newPosition: index + offset + 1 } // +1 because backend contract: index starts at 1 - ) - .catch((e) => { - pushAlert({ - message: "home.message.moveHighlightFail", - type: "danger", - }); - throw e; - }); - }, - } - : undefined - } - /> - - - - - - getHttpTimelineClient().listTimeline({ relate: user.username }) - } - /> - - - - ); -}; - -export default CenterBoards; diff --git a/FrontEnd/src/app/views/center/TimelineBoard.tsx b/FrontEnd/src/app/views/center/TimelineBoard.tsx deleted file mode 100644 index 35249f66..00000000 --- a/FrontEnd/src/app/views/center/TimelineBoard.tsx +++ /dev/null @@ -1,370 +0,0 @@ -import React from "react"; -import classnames from "classnames"; -import { Link } from "react-router-dom"; -import { useTranslation } from "react-i18next"; -import { Spinner } from "react-bootstrap"; - -import { HttpTimelineInfo } from "@/http/timeline"; - -import TimelineLogo from "../common/TimelineLogo"; -import UserTimelineLogo from "../common/UserTimelineLogo"; -import LoadFailReload from "../common/LoadFailReload"; - -interface TimelineBoardItemProps { - timeline: HttpTimelineInfo; - // 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 { name, title } = timeline; - const isPersonal = name.startsWith("@"); - const url = isPersonal - ? `/users/${timeline.owner.username}` - : `/timelines/${name}`; - - const content = ( - <> - {isPersonal ? ( - - ) : ( - - )} - {title} - {name} - - {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: HttpTimelineInfo[]; - editHandler?: { - // offset may exceed index range plusing index. - onMove: (timeline: string, index: number, offset: number) => void; - onDelete: (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.name); - }, - 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.name, - moveState.index, - offsetCount - ); - } - setMoveState(null); - }, - }, - } - : undefined - } - /> - ); - })} - - ); -}; - -interface TimelineBoardUIProps { - title?: string; - timelines: HttpTimelineInfo[] | "offline" | "loading"; - onReload: () => void; - className?: string; - editHandler?: { - onMove: (timeline: string, index: number, offset: number) => void; - onDelete: (timeline: string) => void; - }; -} - -const TimelineBoardUI: React.FC = (props) => { - const { title, timelines, className, editHandler } = props; - - const { t } = useTranslation(); - - const editable = editHandler != null; - - const [editing, setEditing] = React.useState(false); - - return ( -
-
- {title != null &&

{title}

} - {editable && - (editing ? ( -
{ - setEditing(false); - }} - > - {t("done")} -
- ) : ( -
{ - setEditing(true); - }} - > - {t("edit")} -
- ))} -
- {(() => { - if (timelines === "loading") { - return ( -
- -
- ); - } else if (timelines === "offline") { - return ( -
- -
- ); - } else { - return ( - { - if (index + offset >= timelines.length) { - offset = timelines.length - index - 1; - } else if (index + offset < 0) { - offset = -index; - } - editHandler.onMove(timeline, index, offset); - }, - } - : undefined - } - /> - ); - } - })()} -
- ); -}; - -export interface TimelineBoardProps { - title?: string; - className?: string; - load: () => Promise; - editHandler?: { - onMove: (timeline: string, index: number, offset: number) => Promise; - onDelete: (timeline: string) => Promise; - }; -} - -const TimelineBoard: React.FC = ({ - className, - title, - load, - editHandler, -}) => { - const [timelines, setTimelines] = React.useState< - HttpTimelineInfo[] | "offline" | "loading" - >("loading"); - - React.useEffect(() => { - let subscribe = true; - if (timelines === "loading") { - void load().then( - (timelines) => { - if (subscribe) { - setTimelines(timelines); - } - }, - () => { - setTimelines("offline"); - } - ); - } - return () => { - subscribe = false; - }; - }, [load, timelines]); - - return ( - { - setTimelines("loading"); - }} - editHandler={ - typeof timelines === "object" && editHandler != null - ? { - onMove: (timeline, index, offset) => { - const newTimelines = timelines.slice(); - const [t] = newTimelines.splice(index, 1); - newTimelines.splice(index + offset, 0, t); - setTimelines(newTimelines); - editHandler.onMove(timeline, index, offset).then(null, () => { - setTimelines(timelines); - }); - }, - onDelete: (timeline) => { - const newTimelines = timelines.slice(); - newTimelines.splice( - timelines.findIndex((t) => t.name === timeline), - 1 - ); - setTimelines(newTimelines); - editHandler.onDelete(timeline).then(null, () => { - setTimelines(timelines); - }); - }, - } - : undefined - } - /> - ); -}; - -export default TimelineBoard; diff --git a/FrontEnd/src/app/views/center/TimelineCreateDialog.tsx b/FrontEnd/src/app/views/center/TimelineCreateDialog.tsx deleted file mode 100644 index b4e25ba1..00000000 --- a/FrontEnd/src/app/views/center/TimelineCreateDialog.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from "react"; -import { useHistory } from "react-router"; - -import { validateTimelineName } from "@/services/timeline"; -import OperationDialog from "../common/OperationDialog"; -import { getHttpTimelineClient, HttpTimelineInfo } from "@/http/timeline"; - -interface TimelineCreateDialogProps { - open: boolean; - close: () => void; -} - -const TimelineCreateDialog: React.FC = (props) => { - const history = useHistory(); - - 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) => { - history.push(`timelines/${timeline.name}`); - }} - failurePrompt={(e) => `${e as string}`} - /> - ); -}; - -export default TimelineCreateDialog; diff --git a/FrontEnd/src/app/views/center/center.sass b/FrontEnd/src/app/views/center/center.sass deleted file mode 100644 index c0dfb9c0..00000000 --- a/FrontEnd/src/app/views/center/center.sass +++ /dev/null @@ -1,36 +0,0 @@ -.timeline-board - @extend .cru-card - @extend .d-flex - @extend .flex-column - @extend .py-3 - min-height: 200px - height: 100% - position: relative - -.timeline-board-header - @extend .px-3 - display: flex - align-items: center - justify-content: space-between - -.timeline-board-item - font-size: 1.1em - @extend .px-3 - height: 48px - transition: background 0.3s - display: flex - align-items: center - .icon - height: 1.3em - color: black - @extend .me-2 - &:hover - background: $gray-300 - .right - display: flex - align-items: center - flex-shrink: 0 - .title - white-space: nowrap - overflow: hidden - text-overflow: ellipsis diff --git a/FrontEnd/src/app/views/center/index.tsx b/FrontEnd/src/app/views/center/index.tsx deleted file mode 100644 index 0a2abb2c..00000000 --- a/FrontEnd/src/app/views/center/index.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from "react"; -import { useHistory } from "react-router"; -import { useTranslation } from "react-i18next"; -import { Row, Container, Button, Col } from "react-bootstrap"; - -import { useUserLoggedIn } from "@/services/user"; - -import SearchInput from "../common/SearchInput"; -import CenterBoards from "./CenterBoards"; -import TimelineCreateDialog from "./TimelineCreateDialog"; - -const HomePage: React.FC = () => { - const history = useHistory(); - - const { t } = useTranslation(); - - const user = useUserLoggedIn(); - - const [navText, setNavText] = React.useState(""); - - const [dialog, setDialog] = React.useState<"create" | null>(null); - - return ( - <> - - - - { - history.push(`search?q=${navText}`); - }} - additionalButton={ - user != null && ( - - ) - } - /> - - - - - {dialog === "create" && ( - { - setDialog(null); - }} - /> - )} - - ); -}; - -export default HomePage; -- cgit v1.2.3