aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/app/views
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/app/views')
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx281
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx26
2 files changed, 142 insertions, 165 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
index f66d14e0..b4058fbe 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
@@ -1,25 +1,20 @@
import React from "react";
import { useTranslation } from "react-i18next";
-import { of } from "rxjs";
-import { catchError } from "rxjs/operators";
import { UiLogicError } from "@/common";
import { pushAlert } from "@/services/alert";
-import { useUser, userInfoService, UserNotExistError } from "@/services/user";
-import {
- timelineService,
- usePostList,
- useTimelineInfo,
-} from "@/services/timeline";
+import { useUser } from "@/services/user";
+import { timelineService, usePosts, useTimeline } from "@/services/timeline";
import { getHttpBookmarkClient } from "@/http/bookmark";
import { getHttpHighlightClient } from "@/http/highlight";
+import { getHttpUserClient, HttpUserNotExistError } from "@/http/user";
import { TimelineMemberDialog } from "./TimelineMember";
import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog";
import { TimelinePageTemplateUIProps } from "./TimelinePageTemplateUI";
import { TimelinePostSendCallback } from "./TimelinePostEdit";
-import { TimelineSyncStatus } from "./SyncStatusBadge";
import { TimelinePostInfoEx } from "./Timeline";
+import { mergeDataStatus } from "@/services/DataHub2";
export interface TimelinePageTemplateProps<TManageItem> {
name: string;
@@ -45,8 +40,8 @@ export default function TimelinePageTemplate<TManageItem>(
null
);
- const [timelineState, setTimelineState] = useTimelineInfo(name);
- const postListState = usePostList(name);
+ const [timelineAndStatus, setTimelineAndStatus] = useTimeline(name);
+ const postsAndState = usePosts(name);
const onPost: TimelinePostSendCallback = React.useCallback(
(req) => {
@@ -68,147 +63,122 @@ export default function TimelinePageTemplate<TManageItem>(
[onManageProp]
);
- const childProps = ((): [
- data: TimelinePageTemplateUIProps<TManageItem>["data"],
- syncStatus: TimelineSyncStatus
- ] => {
- if (timelineState == null) {
- return [undefined, "syncing"];
+ const data = ((): TimelinePageTemplateUIProps<TManageItem>["data"] => {
+ const { status, data: timeline } = timelineAndStatus;
+ if (timeline == null) {
+ if (status === "offline") {
+ return { type: "custom", value: "Network Error" };
+ } else {
+ return undefined;
+ }
+ } else if (timeline === "notexist") {
+ return props.notFoundI18nKey;
} else {
- const { type, timeline } = timelineState;
- if (timeline == null) {
- if (type === "offline") {
- return [{ type: "custom", value: "Network Error" }, "offline"];
- } else if (type === "synced") {
- return [props.notFoundI18nKey, "synced"];
+ const posts = ((): TimelinePostInfoEx[] | "forbid" | undefined => {
+ const { data: postsInfo } = postsAndState;
+ if (postsInfo === "forbid") {
+ return "forbid";
+ } else if (postsInfo === "notexist") {
+ return undefined;
+ } else if (postsInfo == null) {
+ return undefined;
} else {
- return [undefined, "syncing"];
- }
- } else {
- if (postListState != null && postListState.type === "notexist") {
- return [props.notFoundI18nKey, "synced"];
- }
- if (postListState != null && postListState.type === "forbid") {
- return ["timeline.messageCantSee", "synced"];
+ return postsInfo.posts.map((post) => ({
+ ...post,
+ onDelete: service.hasModifyPostPermission(user, timeline, post)
+ ? () => {
+ service.deletePost(name, post.id).subscribe({
+ error: () => {
+ pushAlert({
+ type: "danger",
+ message: t("timeline.deletePostFailed"),
+ });
+ },
+ });
+ }
+ : undefined,
+ }));
}
+ })();
- const posts:
- | TimelinePostInfoEx[]
- | undefined = postListState?.posts?.map((post) => ({
- ...post,
- onDelete: service.hasModifyPostPermission(user, timeline, post)
+ const operations = {
+ onPost: service.hasPostPermission(user, timeline) ? onPost : undefined,
+ onManage: service.hasManagePermission(user, timeline)
+ ? onManage
+ : undefined,
+ onMember: () => setDialog("member"),
+ onBookmark:
+ user != null
? () => {
- service.deletePost(name, post.id).subscribe({
- error: () => {
+ const { isBookmark } = timeline;
+ setTimelineAndStatus({
+ ...timelineAndStatus,
+ data: {
+ ...timeline,
+ isBookmark: !isBookmark,
+ },
+ });
+ const client = getHttpBookmarkClient();
+ const promise = isBookmark
+ ? client.delete(name)
+ : client.put(name);
+ promise.then(
+ () => {
+ void timelineService.syncTimeline(name);
+ },
+ () => {
pushAlert({
+ message: {
+ type: "i18n",
+ key: isBookmark
+ ? "timeline.removeBookmarkFail"
+ : "timeline.addBookmarkFail",
+ },
type: "danger",
- message: t("timeline.deletePostFailed"),
});
+ setTimelineAndStatus(timelineAndStatus);
+ }
+ );
+ }
+ : undefined,
+ onHighlight:
+ user != null && user.hasHighlightTimelineAdministrationPermission
+ ? () => {
+ const { isHighlight } = timeline;
+ setTimelineAndStatus({
+ ...timelineAndStatus,
+ data: {
+ ...timeline,
+ isHighlight: !isHighlight,
},
});
+ const client = getHttpHighlightClient();
+ const promise = isHighlight
+ ? client.delete(name)
+ : client.put(name);
+ promise.then(
+ () => {
+ void timelineService.syncTimeline(name);
+ },
+ () => {
+ pushAlert({
+ message: {
+ type: "i18n",
+ key: isHighlight
+ ? "timeline.removeHighlightFail"
+ : "timeline.addHighlightFail",
+ },
+ type: "danger",
+ });
+ setTimelineAndStatus(timelineAndStatus);
+ }
+ );
}
: undefined,
- }));
-
- const operations = {
- onPost: service.hasPostPermission(user, timeline)
- ? onPost
- : undefined,
- onManage: service.hasManagePermission(user, timeline)
- ? onManage
- : undefined,
- onMember: () => setDialog("member"),
- onBookmark:
- user != null
- ? () => {
- const { isBookmark } = timeline;
- setTimelineState({
- ...timelineState,
- timeline: {
- ...timeline,
- isBookmark: !isBookmark,
- },
- });
- const client = getHttpBookmarkClient();
- const promise = isBookmark
- ? client.delete(name)
- : client.put(name);
- promise.then(
- () => {
- void timelineService.syncTimeline(name);
- },
- () => {
- pushAlert({
- message: {
- type: "i18n",
- key: isBookmark
- ? "timeline.removeBookmarkFail"
- : "timeline.addBookmarkFail",
- },
- type: "danger",
- });
- setTimelineState(timelineState);
- }
- );
- }
- : undefined,
- onHighlight:
- user != null && user.hasHighlightTimelineAdministrationPermission
- ? () => {
- const { isHighlight } = timeline;
- setTimelineState({
- ...timelineState,
- timeline: {
- ...timeline,
- isHighlight: !isHighlight,
- },
- });
- const client = getHttpHighlightClient();
- const promise = isHighlight
- ? client.delete(name)
- : client.put(name);
- promise.then(
- () => {
- void timelineService.syncTimeline(name);
- },
- () => {
- pushAlert({
- message: {
- type: "i18n",
- key: isHighlight
- ? "timeline.removeHighlightFail"
- : "timeline.addHighlightFail",
- },
- type: "danger",
- });
- setTimelineState(timelineState);
- }
- );
- }
- : undefined,
- };
+ };
- if (type === "cache") {
- return [{ timeline, posts, operations }, "syncing"];
- } else if (type === "offline") {
- return [{ timeline, posts, operations }, "offline"];
- } else {
- if (postListState == null) {
- return [{ timeline, posts, operations }, "syncing"];
- } else {
- const { type: postListType } = postListState;
- if (postListType === "synced") {
- return [{ timeline, posts, operations }, "synced"];
- } else if (postListType === "cache") {
- return [{ timeline, posts, operations }, "syncing"];
- } else if (postListType === "offline") {
- return [{ timeline, posts, operations }, "offline"];
- }
- }
- }
- }
+ return { timeline, posts, operations };
}
- throw new UiLogicError("Failed to calculate TimelinePageUITemplate props.");
})();
const closeDialog = React.useCallback((): void => {
@@ -217,10 +187,10 @@ export default function TimelinePageTemplate<TManageItem>(
let dialogElement: React.ReactElement | undefined;
- const timeline = timelineState?.timeline;
+ const timeline = timelineAndStatus?.data;
if (dialog === "property") {
- if (timeline == null) {
+ if (timeline == null || timeline === "notexist") {
throw new UiLogicError(
"Timeline is null but attempt to open change property dialog."
);
@@ -241,7 +211,7 @@ export default function TimelinePageTemplate<TManageItem>(
/>
);
} else if (dialog === "member") {
- if (timeline == null) {
+ if (timeline == null || timeline === "notexist") {
throw new UiLogicError(
"Timeline is null but attempt to open change property dialog."
);
@@ -256,18 +226,15 @@ export default function TimelinePageTemplate<TManageItem>(
service.hasManagePermission(user, timeline)
? {
onCheckUser: (u) => {
- return userInfoService
- .getUserInfo(u)
- .pipe(
- catchError((e) => {
- if (e instanceof UserNotExistError) {
- return of(null);
- } else {
- throw e;
- }
- })
- )
- .toPromise();
+ return getHttpUserClient()
+ .get(u)
+ .catch((e) => {
+ if (e instanceof HttpUserNotExistError) {
+ return null;
+ } else {
+ throw e;
+ }
+ });
},
onAddUser: (u) => {
return service.addMember(name, u.username).toPromise().then();
@@ -286,7 +253,13 @@ export default function TimelinePageTemplate<TManageItem>(
return (
<>
- <UiComponent data={childProps[0]} syncStatus={childProps[1]} />
+ <UiComponent
+ data={data}
+ syncStatus={mergeDataStatus([
+ timelineAndStatus.status,
+ postsAndState.status,
+ ])}
+ />
{dialogElement}
</>
);
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
index b2824c84..41246175 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
@@ -29,7 +29,7 @@ export interface TimelinePageTemplateUIProps<TManageItems> {
data?:
| {
timeline: TimelineInfo;
- posts?: TimelinePostInfoEx[];
+ posts?: TimelinePostInfoEx[] | "forbid";
operations: {
onManage?: (item: TManageItems | "property") => void;
onMember: () => void;
@@ -166,16 +166,20 @@ export default function TimelinePageTemplateUI<TManageItems>(
/>
) : null}
{posts != null ? (
- <div
- className="timeline-container"
- style={{ minHeight: `calc(100vh - ${56 + bottomSpaceHeight}px)` }}
- >
- <Timeline
- containerRef={timelineRef}
- posts={posts}
- onResize={triggerResizeEvent}
- />
- </div>
+ posts === "forbid" ? (
+ <div>{t("timeline.messageCantSee")}</div>
+ ) : (
+ <div
+ className="timeline-container"
+ style={{ minHeight: `calc(100vh - ${56 + bottomSpaceHeight}px)` }}
+ >
+ <Timeline
+ containerRef={timelineRef}
+ posts={posts}
+ onResize={triggerResizeEvent}
+ />
+ </div>
+ )
) : (
<div className="full-viewport-center-child">
<Spinner variant="primary" animation="grow" />