diff options
author | crupest <crupest@outlook.com> | 2021-02-13 16:35:39 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-02-13 16:35:39 +0800 |
commit | aeed3cb80d8c0a62d0ccc565733c4a213759c5bd (patch) | |
tree | fd00577d63c396bcbbd72a31d2f2aeda2fff6218 | |
parent | 8211994b7175f2ad04663abc0c2605eb96143841 (diff) | |
download | timeline-aeed3cb80d8c0a62d0ccc565733c4a213759c5bd.tar.gz timeline-aeed3cb80d8c0a62d0ccc565733c4a213759c5bd.tar.bz2 timeline-aeed3cb80d8c0a62d0ccc565733c4a213759c5bd.zip |
...
9 files changed, 52 insertions, 42 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/TimelineMember.tsx b/FrontEnd/src/app/views/timeline-common/TimelineMember.tsx index dd8c7389..51512f15 100644 --- a/FrontEnd/src/app/views/timeline-common/TimelineMember.tsx +++ b/FrontEnd/src/app/views/timeline-common/TimelineMember.tsx @@ -46,9 +46,10 @@ const TimelineMemberItem: React.FC<{ ); }; -const TimelineMemberUserSearch: React.FC<{ timeline: HttpTimelineInfo }> = ({ - timeline, -}) => { +const TimelineMemberUserSearch: React.FC<{ + timeline: HttpTimelineInfo; + onChange: () => void; +}> = ({ timeline, onChange }) => { const { t } = useTranslation(); const [userSearchText, setUserSearchText] = useState<string>(""); @@ -120,6 +121,7 @@ const TimelineMemberUserSearch: React.FC<{ timeline: HttpTimelineInfo }> = ({ .then(() => { setUserSearchText(""); setUserSearchState({ type: "init" }); + onChange(); }); }} /> @@ -139,14 +141,13 @@ const TimelineMemberUserSearch: React.FC<{ timeline: HttpTimelineInfo }> = ({ ); }; -// TODO: Trigger resync. - export interface TimelineMemberProps { timeline: HttpTimelineInfo; + onChange: () => void; } const TimelineMember: React.FC<TimelineMemberProps> = (props) => { - const { timeline } = props; + const { timeline, onChange } = props; const members = [timeline.owner, ...timeline.members]; return ( @@ -159,10 +160,9 @@ const TimelineMember: React.FC<TimelineMemberProps> = (props) => { onAction={ timeline.manageable && index !== 0 ? () => { - void getHttpTimelineClient().memberDelete( - timeline.name, - member.username - ); + void getHttpTimelineClient() + .memberDelete(timeline.name, member.username) + .then(onChange); } : undefined } @@ -170,7 +170,7 @@ const TimelineMember: React.FC<TimelineMemberProps> = (props) => { ))} </ListGroup> {timeline.manageable ? ( - <TimelineMemberUserSearch timeline={timeline} /> + <TimelineMemberUserSearch timeline={timeline} onChange={onChange} /> ) : null} </Container> ); diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx index caab1768..6a8dd63c 100644 --- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx +++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx @@ -16,12 +16,14 @@ export interface TimelinePageTemplateProps<TManageItem> { Omit<TimelinePageTemplateUIProps<TManageItem>, "CardComponent"> >; notFoundI18nKey: string; + reloadKey: number; + onReload: () => void; } export default function TimelinePageTemplate<TManageItem>( props: TimelinePageTemplateProps<TManageItem> ): React.ReactElement | null { - const { name } = props; + const { name, reloadKey, onReload } = props; const [dialog, setDialog] = React.useState<null | "property" | "member">( null @@ -68,7 +70,7 @@ export default function TimelinePageTemplate<TManageItem>( return () => { subscribe = false; }; - }, [name]); + }, [name, reloadKey]); let dialogElement: React.ReactElement | undefined; const closeDialog = (): void => setDialog(null); @@ -85,6 +87,7 @@ export default function TimelinePageTemplate<TManageItem>( open close={closeDialog} timeline={timeline} + onChange={onReload} /> ); } else if (dialog === "member") { @@ -95,7 +98,12 @@ export default function TimelinePageTemplate<TManageItem>( } dialogElement = ( - <TimelineMemberDialog open onClose={closeDialog} timeline={timeline} /> + <TimelineMemberDialog + open + onClose={closeDialog} + timeline={timeline} + onChange={onReload} + /> ); } diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx index 48263486..56be8cfe 100644 --- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx +++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx @@ -134,7 +134,6 @@ export default function TimelinePageTemplateUI<TManageItems>( className="fixed-bottom" timeline={timeline} onHeightChange={onPostEditHeightChange} - timelineUniqueId={timeline.uniqueId} /> </> ) : null} diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePropertyChangeDialog.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePropertyChangeDialog.tsx index b99ec267..a5628a9a 100644 --- a/FrontEnd/src/app/views/timeline-common/TimelinePropertyChangeDialog.tsx +++ b/FrontEnd/src/app/views/timeline-common/TimelinePropertyChangeDialog.tsx @@ -10,12 +10,11 @@ import { import OperationDialog from "../common/OperationDialog"; -// TODO: Trigger resync. - export interface TimelinePropertyChangeDialogProps { open: boolean; close: () => void; timeline: HttpTimelineInfo; + onChange: () => void; } const labelMap: { [key in TimelineVisibility]: string } = { @@ -27,7 +26,7 @@ const labelMap: { [key in TimelineVisibility]: string } = { const TimelinePropertyChangeDialog: React.FC<TimelinePropertyChangeDialogProps> = ( props ) => { - const { timeline } = props; + const { timeline, onChange } = props; return ( <OperationDialog @@ -66,7 +65,9 @@ const TimelinePropertyChangeDialog: React.FC<TimelinePropertyChangeDialogProps> if (newDescription !== timeline.description) { req.description = newDescription; } - return getHttpTimelineClient().patchTimeline(timeline.name, req); + return getHttpTimelineClient() + .patchTimeline(timeline.name, req) + .then(onChange); }} /> ); diff --git a/FrontEnd/src/app/views/timeline/TimelineDeleteDialog.tsx b/FrontEnd/src/app/views/timeline/TimelineDeleteDialog.tsx index 0d3199d6..f472c16a 100644 --- a/FrontEnd/src/app/views/timeline/TimelineDeleteDialog.tsx +++ b/FrontEnd/src/app/views/timeline/TimelineDeleteDialog.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useHistory } from "react-router"; import { Trans } from "react-i18next"; -import { timelineService } from "@/services/timeline"; +import { getHttpTimelineClient } from "@/http/timeline"; import OperationDialog from "../common/OperationDialog"; @@ -43,7 +43,7 @@ const TimelineDeleteDialog: React.FC<TimelineDeleteDialog> = (props) => { } }} onProcess={() => { - return timelineService.deleteTimeline(name).toPromise(); + return getHttpTimelineClient().deleteTimeline(name); }} onSuccessAndClose={() => { history.replace("/"); diff --git a/FrontEnd/src/app/views/timeline/TimelineInfoCard.tsx b/FrontEnd/src/app/views/timeline/TimelineInfoCard.tsx index 920f504d..63da6f3c 100644 --- a/FrontEnd/src/app/views/timeline/TimelineInfoCard.tsx +++ b/FrontEnd/src/app/views/timeline/TimelineInfoCard.tsx @@ -1,12 +1,10 @@ import React from "react"; -import { useAvatar } from "@/services/user"; - -import BlobImage from "../common/BlobImage"; import TimelineCardTemplate, { TimelineCardTemplateProps, } from "../timeline-common/TimelineCardTemplate"; import { TimelineCardComponentProps } from "../timeline-common/TimelinePageTemplateUI"; +import UserAvatar from "../common/user/UserAvatar"; export type OrdinaryTimelineManageItem = "delete"; @@ -16,8 +14,6 @@ const TimelineInfoCard: React.FC<TimelineInfoCardProps> = (props) => { const { timeline, operations } = props; const { onManage, onMember } = operations; - const avatar = useAvatar(timeline?.owner?.username); - return ( <TimelineCardTemplate infoArea={ @@ -27,8 +23,8 @@ const TimelineInfoCard: React.FC<TimelineInfoCardProps> = (props) => { <small className="ml-3 text-secondary">{timeline.name}</small> </h3> <div className="align-middle"> - <BlobImage - blob={avatar} + <UserAvatar + username={timeline.owner.username} className="avatar small rounded-circle mr-3" /> {timeline.owner.nickname} diff --git a/FrontEnd/src/app/views/timeline/index.tsx b/FrontEnd/src/app/views/timeline/index.tsx index 225a1a59..8048dd12 100644 --- a/FrontEnd/src/app/views/timeline/index.tsx +++ b/FrontEnd/src/app/views/timeline/index.tsx @@ -7,12 +7,13 @@ import TimelinePageUI from "./TimelinePageUI"; import { OrdinaryTimelineManageItem } from "./TimelineInfoCard"; import TimelineDeleteDialog from "./TimelineDeleteDialog"; -const TimelinePage: React.FC = (_) => { +const TimelinePage: React.FC = () => { const { name } = useParams<{ name: string }>(); const [dialog, setDialog] = React.useState<OrdinaryTimelineManageItem | null>( null ); + const [reloadKey, setReloadKey] = React.useState<number>(0); let dialogElement: React.ReactElement | undefined; if (dialog === "delete") { @@ -28,6 +29,8 @@ const TimelinePage: React.FC = (_) => { UiComponent={TimelinePageUI} onManage={(item) => setDialog(item)} notFoundI18nKey="timeline.timelineNotExist" + reloadKey={reloadKey} + onReload={() => setReloadKey(reloadKey + 1)} /> {dialogElement} </> diff --git a/FrontEnd/src/app/views/user/UserInfoCard.tsx b/FrontEnd/src/app/views/user/UserInfoCard.tsx index 01d2c096..24b7b979 100644 --- a/FrontEnd/src/app/views/user/UserInfoCard.tsx +++ b/FrontEnd/src/app/views/user/UserInfoCard.tsx @@ -1,12 +1,10 @@ import React from "react"; -import { useAvatar } from "@/services/user"; - -import BlobImage from "../common/BlobImage"; import TimelineCardTemplate, { TimelineCardTemplateProps, } from "../timeline-common/TimelineCardTemplate"; import { TimelineCardComponentProps } from "../timeline-common/TimelinePageTemplateUI"; +import UserAvatar from "../common/user/UserAvatar"; export type PersonalTimelineManageItem = "avatar" | "nickname"; @@ -16,8 +14,6 @@ const UserInfoCard: React.FC<UserInfoCardProps> = (props) => { const { timeline, operations } = props; const { onManage, onMember } = operations; - const avatar = useAvatar(timeline?.owner?.username); - return ( <TimelineCardTemplate infoArea={ @@ -27,8 +23,8 @@ const UserInfoCard: React.FC<UserInfoCardProps> = (props) => { <small className="ml-3 text-secondary">{timeline.name}</small> </h3> <div className="align-middle"> - <BlobImage - blob={avatar} + <UserAvatar + username={timeline.owner.username} className="avatar small rounded-circle mr-3" /> {timeline.owner.nickname} diff --git a/FrontEnd/src/app/views/user/index.tsx b/FrontEnd/src/app/views/user/index.tsx index bb986178..9b5acbba 100644 --- a/FrontEnd/src/app/views/user/index.tsx +++ b/FrontEnd/src/app/views/user/index.tsx @@ -1,10 +1,9 @@ import React, { useState } from "react"; import { useParams } from "react-router"; -import { userInfoService } from "@/services/user"; +import { getHttpUserClient } from "@/http/user"; import TimelinePageTemplate from "../timeline-common/TimelinePageTemplate"; - import UserPageUI from "./UserPageUI"; import { PersonalTimelineManageItem } from "./UserInfoCard"; import ChangeNicknameDialog from "./ChangeNicknameDialog"; @@ -15,6 +14,8 @@ const UserPage: React.FC = (_) => { const [dialog, setDialog] = useState<null | PersonalTimelineManageItem>(null); + const [reloadKey, setReloadKey] = React.useState<number>(0); + let dialogElement: React.ReactElement | undefined; const closeDialog = (): void => setDialog(null); @@ -24,9 +25,10 @@ const UserPage: React.FC = (_) => { <ChangeNicknameDialog open close={closeDialog} - onProcess={(newNickname) => - userInfoService.setNickname(username, newNickname) - } + onProcess={async (newNickname) => { + await getHttpUserClient().patch(username, { nickname: newNickname }); + setReloadKey(reloadKey + 1); + }} /> ); } else if (dialog === "avatar") { @@ -34,7 +36,10 @@ const UserPage: React.FC = (_) => { <ChangeAvatarDialog open close={closeDialog} - process={(file) => userInfoService.setAvatar(username, file)} + process={async (file) => { + await getHttpUserClient().putAvatar(username, file); + setReloadKey(reloadKey + 1); + }} /> ); } @@ -46,6 +51,8 @@ const UserPage: React.FC = (_) => { UiComponent={UserPageUI} onManage={(item) => setDialog(item)} notFoundI18nKey="timeline.userNotExist" + reloadKey={reloadKey} + onReload={() => setReloadKey(reloadKey + 1)} /> {dialogElement} </> |