aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd')
-rw-r--r--FrontEnd/package.json1
-rw-r--r--FrontEnd/src/common.ts2
-rw-r--r--FrontEnd/src/http/bookmark.ts95
-rw-r--r--FrontEnd/src/http/common.ts8
-rw-r--r--FrontEnd/src/http/highlight.ts49
-rw-r--r--FrontEnd/src/http/timeline.ts7
-rw-r--r--FrontEnd/src/views/center/CenterBoards.tsx61
-rw-r--r--FrontEnd/src/views/center/TimelineBoard.tsx55
-rw-r--r--FrontEnd/src/views/home/TimelineListView.tsx24
-rw-r--r--FrontEnd/src/views/home/index.tsx14
-rw-r--r--FrontEnd/src/views/timeline/Timeline.tsx2
-rw-r--r--FrontEnd/src/views/timeline/TimelineCard.tsx29
12 files changed, 191 insertions, 156 deletions
diff --git a/FrontEnd/package.json b/FrontEnd/package.json
index b7db3306..358eadc1 100644
--- a/FrontEnd/package.json
+++ b/FrontEnd/package.json
@@ -43,6 +43,7 @@
"start": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
+ "typecheck": "tsc",
"lint": "eslint src/ --ext .js --ext .jsx --ext .ts --ext .tsx",
"lint:fix": "eslint src/ --ext .js --ext .jsx --ext .ts --ext .tsx --fix"
},
diff --git a/FrontEnd/src/common.ts b/FrontEnd/src/common.ts
index 91d58562..b819d209 100644
--- a/FrontEnd/src/common.ts
+++ b/FrontEnd/src/common.ts
@@ -29,3 +29,5 @@ export function convertI18nText(
return text.value;
}
}
+
+export const highlightTimelineUsername = "crupest";
diff --git a/FrontEnd/src/http/bookmark.ts b/FrontEnd/src/http/bookmark.ts
index 3e5be229..382543ff 100644
--- a/FrontEnd/src/http/bookmark.ts
+++ b/FrontEnd/src/http/bookmark.ts
@@ -1,36 +1,93 @@
-import { axios, apiBaseUrl, extractResponseData } from "./common";
+import { applyQueryParameters } from "@/utilities/url";
+import { axios, apiBaseUrl, extractResponseData, Page } from "./common";
-import { HttpTimelineInfo } from "./timeline";
-
-export interface HttpHighlightMoveRequest {
- timeline: string;
- newPosition: number;
+export interface TimelineBookmark {
+ timelineOwner: string;
+ timelineName: string;
+ position: number;
}
export interface IHttpBookmarkClient {
- list(): Promise<HttpTimelineInfo[]>;
- put(timeline: string): Promise<void>;
- delete(timeline: string): Promise<void>;
- move(req: HttpHighlightMoveRequest): Promise<void>;
+ list(
+ username: string,
+ page?: number,
+ pageSize?: number
+ ): Promise<Page<TimelineBookmark>>;
+ post(
+ username: string,
+ timelineOwner: string,
+ timelineName: string
+ ): Promise<TimelineBookmark>;
+ delete(
+ username: string,
+ timelineOwner: string,
+ timelineName: string
+ ): Promise<void>;
+ move(
+ username: string,
+ timelineOwner: string,
+ timelineName: string,
+ position: number
+ ): Promise<TimelineBookmark>;
}
export class HttpHighlightClient implements IHttpBookmarkClient {
- list(): Promise<HttpTimelineInfo[]> {
+ list(
+ username: string,
+ page?: number,
+ pageSize?: number
+ ): Promise<Page<TimelineBookmark>> {
+ const url = applyQueryParameters(
+ `${apiBaseUrl}/v2/users/${username}/bookmarks`,
+ { page, pageSize }
+ );
+
+ return axios.get<Page<TimelineBookmark>>(url).then(extractResponseData);
+ }
+
+ post(
+ username: string,
+ timelineOwner: string,
+ timelineName: string
+ ): Promise<TimelineBookmark> {
+ const url = `${apiBaseUrl}/v2/users/${username}/bookmarks`;
+
return axios
- .get<HttpTimelineInfo[]>(`${apiBaseUrl}/bookmarks`)
+ .post<TimelineBookmark>(url, {
+ timelineOwner,
+ timelineName,
+ })
.then(extractResponseData);
}
- put(timeline: string): Promise<void> {
- return axios.put(`${apiBaseUrl}/bookmarks/${timeline}`).then();
- }
+ delete(
+ username: string,
+ timelineOwner: string,
+ timelineName: string
+ ): Promise<void> {
+ const url = `${apiBaseUrl}/v2/users/${username}/bookmarks/delete`;
- delete(timeline: string): Promise<void> {
- return axios.delete(`${apiBaseUrl}/bookmarks/${timeline}`).then();
+ return axios.post(url, {
+ timelineOwner,
+ timelineName,
+ });
}
- move(req: HttpHighlightMoveRequest): Promise<void> {
- return axios.post(`${apiBaseUrl}/bookmarkop/move`, req).then();
+ move(
+ username: string,
+ timelineOwner: string,
+ timelineName: string,
+ position: number
+ ): Promise<TimelineBookmark> {
+ const url = `${apiBaseUrl}/v2/users/${username}/bookmarks/move`;
+
+ return axios
+ .post<TimelineBookmark>(url, {
+ timelineOwner,
+ timelineName,
+ position,
+ })
+ .then(extractResponseData);
}
}
diff --git a/FrontEnd/src/http/common.ts b/FrontEnd/src/http/common.ts
index e1672985..0a27b908 100644
--- a/FrontEnd/src/http/common.ts
+++ b/FrontEnd/src/http/common.ts
@@ -212,3 +212,11 @@ export function convertToBlobWithEtag(res: AxiosResponse<Blob>): BlobWithEtag {
export function extractEtag(res: AxiosResponse): string {
return (res.headers as Record<"etag", string>)["etag"];
}
+
+export interface Page<T> {
+ pageNumber: number;
+ pageSize: number;
+ totalPageCount: number;
+ totalCount: number;
+ items: T[];
+}
diff --git a/FrontEnd/src/http/highlight.ts b/FrontEnd/src/http/highlight.ts
deleted file mode 100644
index fddf0729..00000000
--- a/FrontEnd/src/http/highlight.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { axios, apiBaseUrl, extractResponseData } from "./common";
-
-import { HttpTimelineInfo } from "./timeline";
-
-export interface HttpHighlightMoveRequest {
- timeline: string;
- newPosition: number;
-}
-
-export interface IHttpHighlightClient {
- list(): Promise<HttpTimelineInfo[]>;
- put(timeline: string): Promise<void>;
- delete(timeline: string): Promise<void>;
- move(req: HttpHighlightMoveRequest): Promise<void>;
-}
-
-export class HttpHighlightClient implements IHttpHighlightClient {
- list(): Promise<HttpTimelineInfo[]> {
- return axios
- .get<HttpTimelineInfo[]>(`${apiBaseUrl}/highlights`)
- .then(extractResponseData);
- }
-
- put(timeline: string): Promise<void> {
- return axios.put(`${apiBaseUrl}/highlights/${timeline}`).then();
- }
-
- delete(timeline: string): Promise<void> {
- return axios.delete(`${apiBaseUrl}/highlights/${timeline}`).then();
- }
-
- move(req: HttpHighlightMoveRequest): Promise<void> {
- return axios.post(`${apiBaseUrl}/highlightop/move`, req).then();
- }
-}
-
-let client: IHttpHighlightClient = new HttpHighlightClient();
-
-export function getHttpHighlightClient(): IHttpHighlightClient {
- return client;
-}
-
-export function setHttpHighlightClient(
- newClient: IHttpHighlightClient
-): IHttpHighlightClient {
- const old = client;
- client = newClient;
- return old;
-}
diff --git a/FrontEnd/src/http/timeline.ts b/FrontEnd/src/http/timeline.ts
index 49a7b8f2..65717a83 100644
--- a/FrontEnd/src/http/timeline.ts
+++ b/FrontEnd/src/http/timeline.ts
@@ -8,6 +8,7 @@ import {
extractResponseData,
convertToIfStatusCodeIs,
getHttpToken,
+ Page,
} from "./common";
import { HttpUser } from "./user";
@@ -115,7 +116,7 @@ export interface IHttpTimelineClient {
listPost(
ownerUsername: string,
timelineName: string
- ): Promise<HttpTimelinePostInfo[]>;
+ ): Promise<Page<HttpTimelinePostInfo>>;
generatePostDataUrl(
ownerUsername: string,
timelineName: string,
@@ -217,9 +218,9 @@ export class HttpTimelineClient implements IHttpTimelineClient {
listPost(
ownerUsername: string,
timelineName: string
- ): Promise<HttpTimelinePostInfo[]> {
+ ): Promise<Page<HttpTimelinePostInfo>> {
return axios
- .get<HttpTimelinePostInfo[]>(
+ .get<Page<HttpTimelinePostInfo>>(
`${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts`
)
.then(extractResponseData);
diff --git a/FrontEnd/src/views/center/CenterBoards.tsx b/FrontEnd/src/views/center/CenterBoards.tsx
index 392c2d08..e95f4cb8 100644
--- a/FrontEnd/src/views/center/CenterBoards.tsx
+++ b/FrontEnd/src/views/center/CenterBoards.tsx
@@ -1,12 +1,13 @@
import 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 { getHttpHighlightClient } from "@/http/highlight";
import TimelineBoard from "./TimelineBoard";
@@ -23,11 +24,15 @@ const CenterBoards: React.FC = () => {
<div className="col col-12 my-2">
<TimelineBoard
title={t("home.bookmarkTimeline")}
- load={() => getHttpBookmarkClient().list()}
+ load={() =>
+ getHttpBookmarkClient()
+ .list(user.username)
+ .then((p) => p.items)
+ }
editHandler={{
- onDelete: (timeline) => {
+ onDelete: (owner, timeline) => {
return getHttpBookmarkClient()
- .delete(timeline)
+ .delete(user.username, owner, timeline)
.catch((e) => {
pushAlert({
message: "home.message.deleteBookmarkFail",
@@ -36,10 +41,13 @@ const CenterBoards: React.FC = () => {
throw e;
});
},
- onMove: (timeline, index, offset) => {
+ onMove: (owner, timeline, index, offset) => {
return getHttpBookmarkClient()
.move(
- { timeline, newPosition: index + offset + 1 } // +1 because backend contract: index starts at 1
+ user.username,
+ owner,
+ timeline,
+ index + offset + 1 // +1 because backend contract: index starts at 1
)
.catch((e) => {
pushAlert({
@@ -47,7 +55,8 @@ const CenterBoards: React.FC = () => {
type: "danger",
});
throw e;
- });
+ })
+ .then();
},
}}
/>
@@ -55,13 +64,17 @@ const CenterBoards: React.FC = () => {
<div className="col col-12 my-2">
<TimelineBoard
title={t("home.highlightTimeline")}
- load={() => getHttpHighlightClient().list()}
+ load={() =>
+ getHttpBookmarkClient()
+ .list(highlightTimelineUsername)
+ .then((p) => p.items)
+ }
editHandler={
- user.hasHighlightTimelineAdministrationPermission
+ user.username === highlightTimelineUsername
? {
- onDelete: (timeline) => {
- return getHttpHighlightClient()
- .delete(timeline)
+ onDelete: (owner, timeline) => {
+ return getHttpBookmarkClient()
+ .delete(highlightTimelineUsername, owner, timeline)
.catch((e) => {
pushAlert({
message: "home.message.deleteHighlightFail",
@@ -70,18 +83,22 @@ const CenterBoards: React.FC = () => {
throw e;
});
},
- onMove: (timeline, index, offset) => {
- return getHttpHighlightClient()
+ onMove: (owner, timeline, index, offset) => {
+ return getHttpBookmarkClient()
.move(
- { timeline, newPosition: index + offset + 1 } // +1 because backend contract: index starts at 1
+ highlightTimelineUsername,
+ owner,
+ timeline,
+ index + offset + 1 // +1 because backend contract: index starts at 1
)
.catch((e) => {
pushAlert({
- message: "home.message.moveHighlightFail",
+ message: "home.message.moveBookmarkFail",
type: "danger",
});
throw e;
- });
+ })
+ .then();
},
}
: undefined
@@ -94,7 +111,15 @@ const CenterBoards: React.FC = () => {
<TimelineBoard
title={t("home.relatedTimeline")}
load={() =>
- getHttpTimelineClient().listTimeline({ relate: user.username })
+ getHttpTimelineClient()
+ .listTimeline({ relate: user.username })
+ .then((l) =>
+ l.map((t, index) => ({
+ timelineOwner: t.owner.username,
+ timelineName: t.nameV2,
+ position: index + 1,
+ }))
+ )
}
/>
</div>
diff --git a/FrontEnd/src/views/center/TimelineBoard.tsx b/FrontEnd/src/views/center/TimelineBoard.tsx
index f8dc4bfd..45b4a8a5 100644
--- a/FrontEnd/src/views/center/TimelineBoard.tsx
+++ b/FrontEnd/src/views/center/TimelineBoard.tsx
@@ -2,7 +2,7 @@ import React from "react";
import classnames from "classnames";
import { Link } from "react-router-dom";
-import { HttpTimelineInfo } from "@/http/timeline";
+import { TimelineBookmark } from "@/http/bookmark";
import TimelineLogo from "../common/TimelineLogo";
import LoadFailReload from "../common/LoadFailReload";
@@ -11,7 +11,7 @@ import Card from "../common/Card";
import Spinner from "../common/Spinner";
interface TimelineBoardItemProps {
- timeline: HttpTimelineInfo;
+ timeline: TimelineBookmark;
// In height.
offset?: number;
// In px.
@@ -33,15 +33,12 @@ const TimelineBoardItem: React.FC<TimelineBoardItemProps> = ({
offset,
actions,
}) => {
- const { title } = timeline;
-
const content = (
<>
<TimelineLogo className="icon" />
- <span className="title">{title}</span>
- <small className="ms-2 cru-color-secondary">
- {timeline.owner.username}/{timeline.nameV2}
- </small>
+ <span className="title">
+ {timeline.timelineOwner}/{timeline.timelineName}
+ </span>
<span className="flex-grow-1"></span>
{actions != null ? (
<div className="right">
@@ -83,7 +80,7 @@ const TimelineBoardItem: React.FC<TimelineBoardItemProps> = ({
return actions == null ? (
<Link
- to={`${timeline.owner.username}/${timeline.nameV2}`}
+ to={`${timeline.timelineOwner}/${timeline.timelineName}`}
className="timeline-board-item"
>
{content}
@@ -96,7 +93,7 @@ const TimelineBoardItem: React.FC<TimelineBoardItemProps> = ({
};
interface TimelineBoardItemContainerProps {
- timelines: HttpTimelineInfo[];
+ timelines: TimelineBookmark[];
editHandler?: {
// offset may exceed index range plusing index.
onMove: (
@@ -156,7 +153,7 @@ const TimelineBoardItemContainer: React.FC<TimelineBoardItemContainerProps> = ({
return (
<TimelineBoardItem
- key={`${timeline.owner.username}/${timeline.nameV2}`}
+ key={timeline.timelineOwner + "/" + timeline.timelineName}
timeline={timeline}
offset={offset}
arbitraryOffset={arbitraryOffset}
@@ -165,8 +162,8 @@ const TimelineBoardItemContainer: React.FC<TimelineBoardItemContainerProps> = ({
? {
onDelete: () => {
editHandler.onDelete(
- timeline.owner.username,
- timeline.nameV2
+ timeline.timelineOwner,
+ timeline.timelineName
);
},
onMove: {
@@ -192,8 +189,8 @@ const TimelineBoardItemContainer: React.FC<TimelineBoardItemContainerProps> = ({
moveState.offset / height
);
editHandler.onMove(
- timeline.owner.username,
- timeline.nameV2,
+ timeline.timelineOwner,
+ timeline.timelineName,
moveState.index,
offsetCount
);
@@ -214,7 +211,7 @@ const TimelineBoardItemContainer: React.FC<TimelineBoardItemContainerProps> = ({
interface TimelineBoardUIProps {
title?: string;
state: "offline" | "loading" | "loaded";
- timelines: HttpTimelineInfo[];
+ timelines: TimelineBookmark[];
onReload: () => void;
className?: string;
editHandler?: {
@@ -299,10 +296,15 @@ const TimelineBoardUI: React.FC<TimelineBoardUIProps> = (props) => {
export interface TimelineBoardProps {
title?: string;
className?: string;
- load: () => Promise<HttpTimelineInfo[]>;
+ load: () => Promise<TimelineBookmark[]>;
editHandler?: {
- onMove: (timeline: string, index: number, offset: number) => Promise<void>;
- onDelete: (timeline: string) => Promise<void>;
+ onMove: (
+ owner: string,
+ timeline: string,
+ index: number,
+ offset: number
+ ) => Promise<void>;
+ onDelete: (owner: string, timeline: string) => Promise<void>;
};
}
@@ -315,7 +317,7 @@ const TimelineBoard: React.FC<TimelineBoardProps> = ({
const [state, setState] = React.useState<"offline" | "loading" | "loaded">(
"loading"
);
- const [timelines, setTimelines] = React.useState<HttpTimelineInfo[]>([]);
+ const [timelines, setTimelines] = React.useState<TimelineBookmark[]>([]);
React.useEffect(() => {
let subscribe = true;
@@ -354,20 +356,23 @@ const TimelineBoard: React.FC<TimelineBoardProps> = ({
const [t] = newTimelines.splice(index, 1);
newTimelines.splice(index + offset, 0, t);
setTimelines(newTimelines);
- editHandler.onMove(timeline, index, offset).then(null, () => {
- setTimelines(timelines);
- });
+ editHandler
+ .onMove(owner, timeline, index, offset)
+ .then(null, () => {
+ setTimelines(timelines);
+ });
},
onDelete: (owner, timeline) => {
const newTimelines = timelines.slice();
newTimelines.splice(
timelines.findIndex(
- (t) => t.owner.username === owner && t.nameV2 === timeline
+ (t) =>
+ t.timelineOwner === owner && t.timelineName === timeline
),
1
);
setTimelines(newTimelines);
- editHandler.onDelete(timeline).then(null, () => {
+ editHandler.onDelete(owner, timeline).then(null, () => {
setTimelines(timelines);
});
},
diff --git a/FrontEnd/src/views/home/TimelineListView.tsx b/FrontEnd/src/views/home/TimelineListView.tsx
index 2f283e1c..b26f1f70 100644
--- a/FrontEnd/src/views/home/TimelineListView.tsx
+++ b/FrontEnd/src/views/home/TimelineListView.tsx
@@ -1,13 +1,13 @@
import React from "react";
+import { useTranslation } from "react-i18next";
+import { Link } from "react-router-dom";
import { convertI18nText, I18nText } from "@/common";
-import { HttpTimelineInfo } from "@/http/timeline";
-import { useTranslation } from "react-i18next";
-import { Link } from "react-router-dom";
+import { TimelineBookmark } from "@/http/bookmark";
interface TimelineListItemProps {
- timeline: HttpTimelineInfo;
+ timeline: TimelineBookmark;
}
const TimelineListItem: React.FC<TimelineListItemProps> = ({ timeline }) => {
@@ -21,12 +21,9 @@ const TimelineListItem: React.FC<TimelineListItemProps> = ({ timeline }) => {
/>
</svg>
<div>
- <div>{timeline.title}</div>
- <div>
- <small className="text-secondary">{timeline.description}</small>
- </div>
+ {timeline.timelineOwner}/{timeline.timelineName}
</div>
- <Link to={`${timeline.owner.username}/${timeline.nameV2}`}>
+ <Link to={`${timeline.timelineOwner}/${timeline.timelineName}`}>
<i className="icon-button bi-arrow-right ms-3" />
</Link>
</div>
@@ -60,7 +57,7 @@ const TimelineListArrow: React.FC = () => {
interface TimelineListViewProps {
headerText?: I18nText;
- timelines?: HttpTimelineInfo[];
+ timelines?: TimelineBookmark[];
}
const TimelineListView: React.FC<TimelineListViewProps> = ({
@@ -83,7 +80,12 @@ const TimelineListView: React.FC<TimelineListViewProps> = ({
<h3>{convertI18nText(headerText, t)}</h3>
</div>
{timelines != null
- ? timelines.map((t) => <TimelineListItem key={t.nameV2} timeline={t} />)
+ ? timelines.map((t) => (
+ <TimelineListItem
+ key={`${t.timelineOwner}/${t.timelineName}`}
+ timeline={t}
+ />
+ ))
: null}
<TimelineListArrow />
</div>
diff --git a/FrontEnd/src/views/home/index.tsx b/FrontEnd/src/views/home/index.tsx
index 9533ea5a..d734b2b7 100644
--- a/FrontEnd/src/views/home/index.tsx
+++ b/FrontEnd/src/views/home/index.tsx
@@ -1,8 +1,10 @@
import React from "react";
import { useNavigate } from "react-router-dom";
-import { HttpTimelineInfo } from "@/http/timeline";
-import { getHttpHighlightClient } from "@/http/highlight";
+import { highlightTimelineUsername } from "@/common";
+
+import { Page } from "@/http/common";
+import { getHttpBookmarkClient, TimelineBookmark } from "@/http/bookmark";
import SearchInput from "../common/SearchInput";
import TimelineListView from "./TimelineListView";
@@ -25,14 +27,14 @@ const HomeV2: React.FC = () => {
"loading" | "done" | "error"
>("loading");
const [highlightTimelines, setHighlightTimelines] = React.useState<
- HttpTimelineInfo[] | undefined
+ Page<TimelineBookmark> | undefined
>();
React.useEffect(() => {
if (highlightTimelineState === "loading") {
let subscribe = true;
- void getHttpHighlightClient()
- .list()
+ void getHttpBookmarkClient()
+ .list(highlightTimelineUsername)
.then(
(data) => {
if (subscribe) {
@@ -67,7 +69,7 @@ const HomeV2: React.FC = () => {
<WebsiteIntroduction className="m-2" />
<TimelineListView
headerText={highlightTimelineMessageMap[highlightTimelineState]}
- timelines={highlightTimelines}
+ timelines={highlightTimelines?.items}
/>
</>
);
diff --git a/FrontEnd/src/views/timeline/Timeline.tsx b/FrontEnd/src/views/timeline/Timeline.tsx
index e8ed9fe5..a2047651 100644
--- a/FrontEnd/src/views/timeline/Timeline.tsx
+++ b/FrontEnd/src/views/timeline/Timeline.tsx
@@ -89,7 +89,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
([t, p]) => {
if (subscribe) {
setTimeline(t);
- setPosts(p);
+ setPosts(p.items);
setState("loaded");
onTimelineLoaded.current?.(t);
}
diff --git a/FrontEnd/src/views/timeline/TimelineCard.tsx b/FrontEnd/src/views/timeline/TimelineCard.tsx
index dcf5e870..872ad6d3 100644
--- a/FrontEnd/src/views/timeline/TimelineCard.tsx
+++ b/FrontEnd/src/views/timeline/TimelineCard.tsx
@@ -8,7 +8,6 @@ import { timelineVisibilityTooltipTranslationMap } from "@/services/timeline";
import { useUser } from "@/services/user";
import { pushAlert } from "@/services/alert";
import { HttpTimelineInfo } from "@/http/timeline";
-import { getHttpHighlightClient } from "@/http/highlight";
import { getHttpBookmarkClient } from "@/http/bookmark";
import UserAvatar from "../common/user/UserAvatar";
@@ -71,28 +70,6 @@ const TimelineCard: React.FC<TimelinePageCardProps> = (props) => {
{t(timelineVisibilityTooltipTranslationMap[timeline.visibility])}
</small>
<div className="mt-2 cru-text-end">
- <i
- className={classnames(
- timeline.isHighlight ? "bi-star-fill" : "bi-star",
- "icon-button cru-color-primary me-3"
- )}
- onClick={
- user?.hasHighlightTimelineAdministrationPermission
- ? () => {
- getHttpHighlightClient()
- [timeline.isHighlight ? "delete" : "put"](timeline.nameV2)
- .then(onReload, () => {
- pushAlert({
- message: timeline.isHighlight
- ? "timeline.removeHighlightFail"
- : "timeline.addHighlightFail",
- type: "danger",
- });
- });
- }
- : undefined
- }
- />
{user != null ? (
<i
className={classnames(
@@ -101,7 +78,11 @@ const TimelineCard: React.FC<TimelinePageCardProps> = (props) => {
)}
onClick={() => {
getHttpBookmarkClient()
- [timeline.isBookmark ? "delete" : "put"](timeline.nameV2)
+ [timeline.isBookmark ? "delete" : "post"](
+ user.username,
+ timeline.owner.username,
+ timeline.nameV2
+ )
.then(onReload, () => {
pushAlert({
message: timeline.isBookmark