aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx')
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx170
1 files changed, 59 insertions, 111 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
index f27171f5..01561704 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplateUI.tsx
@@ -4,18 +4,10 @@ import { fromEvent } from "rxjs";
import { Spinner } from "react-bootstrap";
import { getAlertHost } from "@/services/alert";
-import { useEventEmiiter, UiLogicError } from "@/common";
-import {
- TimelineInfo,
- TimelinePostsWithSyncState,
- timelineService,
-} from "@/services/timeline";
-import { userService } from "@/services/user";
-
-import Timeline, {
- TimelinePostInfoEx,
- TimelineDeleteCallback,
-} from "./Timeline";
+import { useEventEmiiter, I18nText, convertI18nText } from "@/common";
+import { TimelineInfo } from "@/services/timeline";
+
+import Timeline, { TimelinePostInfoEx } from "./Timeline";
import TimelinePostEdit, { TimelinePostSendCallback } from "./TimelinePostEdit";
import { TimelineSyncStatus } from "./SyncStatusBadge";
@@ -30,20 +22,23 @@ export interface TimelineCardComponentProps<TManageItems> {
}
export interface TimelinePageTemplateUIProps<TManageItems> {
- timeline?: TimelineInfo;
- postListState?: TimelinePostsWithSyncState;
+ data?:
+ | {
+ timeline: TimelineInfo;
+ posts?: TimelinePostInfoEx[];
+ onManage?: (item: TManageItems | "property") => void;
+ onMember: () => void;
+ onPost?: TimelinePostSendCallback;
+ }
+ | I18nText;
+ syncStatus: TimelineSyncStatus;
CardComponent: React.ComponentType<TimelineCardComponentProps<TManageItems>>;
- onMember: () => void;
- onManage?: (item: TManageItems | "property") => void;
- onPost?: TimelinePostSendCallback;
- onDelete: TimelineDeleteCallback;
- error?: string;
}
export default function TimelinePageTemplateUI<TManageItems>(
props: TimelinePageTemplateUIProps<TManageItems>
): React.ReactElement | null {
- const { timeline, postListState } = props;
+ const { data, syncStatus, CardComponent } = props;
const { t } = useTranslation();
@@ -68,6 +63,9 @@ export default function TimelinePageTemplateUI<TManageItems>(
const [getResizeEvent, triggerResizeEvent] = useEventEmiiter();
+ const timelineName: string | null =
+ typeof data === "object" && "timeline" in data ? data.timeline.name : null;
+
React.useEffect(() => {
const { current: timelineElement } = timelineRef;
if (timelineElement != null) {
@@ -115,13 +113,10 @@ export default function TimelinePageTemplateUI<TManageItems>(
subscriptions.forEach((s) => s.unsubscribe());
};
}
- }, [getResizeEvent, triggerResizeEvent, timeline, postListState]);
-
- const genCardCollapseLocalStorageKey = (uniqueId: string): string =>
- `timeline.${uniqueId}.cardCollapse`;
+ }, [getResizeEvent, triggerResizeEvent, timelineName]);
const cardCollapseLocalStorageKey =
- timeline != null ? genCardCollapseLocalStorageKey(timeline.uniqueId) : null;
+ timelineName != null ? `timeline.${timelineName}.cardCollapse` : null;
const [cardCollapse, setCardCollapse] = React.useState<boolean>(true);
React.useEffect(() => {
@@ -135,9 +130,9 @@ export default function TimelinePageTemplateUI<TManageItems>(
const toggleCardCollapse = (): void => {
const newState = !cardCollapse;
setCardCollapse(newState);
- if (timeline != null) {
+ if (cardCollapseLocalStorageKey != null) {
window.localStorage.setItem(
- genCardCollapseLocalStorageKey(timeline.uniqueId),
+ cardCollapseLocalStorageKey,
newState.toString()
);
}
@@ -145,98 +140,51 @@ export default function TimelinePageTemplateUI<TManageItems>(
let body: React.ReactElement;
- if (props.error != null) {
- body = <p className="text-danger">{t(props.error)}</p>;
+ if (data != null && (typeof data === "string" || "type" in data)) {
+ body = <p className="text-danger">{convertI18nText(data, t)}</p>;
} else {
- if (timeline != null) {
- let timelineBody: React.ReactElement;
- if (postListState != null) {
- if (postListState.type === "notexist") {
- throw new UiLogicError(
- "Timeline is not null but post list state is notexist."
- );
- }
- if (postListState.type === "forbid") {
- timelineBody = (
- <p className="text-danger">{t("timeline.messageCantSee")}</p>
- );
- } else {
- const posts: TimelinePostInfoEx[] = postListState.posts.map(
- (post) => ({
- ...post,
- deletable: timelineService.hasModifyPostPermission(
- userService.currentUser,
- timeline,
- post
- ),
- })
- );
-
- timelineBody = (
- <Timeline
- containerRef={timelineRef}
- posts={posts}
- onDelete={props.onDelete}
- onResize={triggerResizeEvent}
- />
- );
- if (props.onPost != null) {
- timelineBody = (
- <>
- {timelineBody}
- <div
- style={{ height: bottomSpaceHeight }}
- className="flex-fix-length"
- />
- <TimelinePostEdit
- className="fixed-bottom"
- onPost={props.onPost}
- onHeightChange={onPostEditHeightChange}
- timelineUniqueId={timeline.uniqueId}
- />
- </>
- );
- }
- }
- } else {
- timelineBody = (
- <div className="full-viewport-center-child">
- <Spinner variant="primary" animation="grow" />
- </div>
- );
- }
+ const posts = data?.posts;
- const { CardComponent } = props;
- const syncStatus: TimelineSyncStatus =
- postListState == null || postListState.syncing
- ? "syncing"
- : postListState.type === "synced"
- ? "synced"
- : "offline";
-
- body = (
- <>
- <div className="timeline-background" />
+ body = (
+ <div className="timeline-background">
+ {data != null ? (
<CardComponent
className="timeline-template-card"
- timeline={timeline}
- onManage={props.onManage}
- onMember={props.onMember}
+ timeline={data.timeline}
+ onManage={data.onManage}
+ onMember={data.onMember}
syncStatus={syncStatus}
collapse={cardCollapse}
toggleCollapse={toggleCardCollapse}
/>
- {timelineBody}
- </>
- );
- } else {
- body = (
- <div className="full-viewport-center-child">
- <Spinner variant="primary" animation="grow" />
- </div>
- );
- }
+ ) : null}
+ {posts != null ? (
+ <Timeline
+ containerRef={timelineRef}
+ posts={posts}
+ onResize={triggerResizeEvent}
+ />
+ ) : (
+ <div className="full-viewport-center-child">
+ <Spinner variant="primary" animation="grow" />
+ </div>
+ )}
+ {data != null && data.onPost != null ? (
+ <>
+ <div
+ style={{ height: bottomSpaceHeight }}
+ className="flex-fix-length"
+ />
+ <TimelinePostEdit
+ className="fixed-bottom"
+ onPost={data.onPost}
+ onHeightChange={onPostEditHeightChange}
+ timelineUniqueId={data.timeline.uniqueId}
+ />
+ </>
+ ) : null}
+ </div>
+ );
}
-
return body;
}