From 928ba0ce419bacba113951095278a5138ead34cf Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 10 Apr 2022 16:04:03 +0800 Subject: ... --- BackEnd/Timeline/Models/Http/HttpTimeline.cs | 7 +- BackEnd/Timeline/Models/Http/HttpTimelinePost.cs | 14 +- BackEnd/Timeline/Services/Mapper/TimelineMapper.cs | 3 + FrontEnd/package.json | 8 +- FrontEnd/src/App.tsx | 5 +- FrontEnd/src/http/timeline.ts | 136 ++++++++--- .../src/views/timeline-common/CollapseButton.tsx | 23 -- .../timeline-common/ConnectionStatusBadge.css | 36 --- .../timeline-common/ConnectionStatusBadge.tsx | 41 ---- .../src/views/timeline-common/MarkdownPostEdit.css | 21 -- .../src/views/timeline-common/MarkdownPostEdit.tsx | 203 ---------------- .../timeline-common/PostPropertyChangeDialog.tsx | 37 --- FrontEnd/src/views/timeline-common/Timeline.tsx | 165 ------------- .../views/timeline-common/TimelineDateLabel.tsx | 19 -- .../views/timeline-common/TimelineEmptyItem.tsx | 25 -- .../src/views/timeline-common/TimelineLine.tsx | 51 ---- .../src/views/timeline-common/TimelineLoading.tsx | 16 -- .../src/views/timeline-common/TimelineMember.css | 8 - .../src/views/timeline-common/TimelineMember.tsx | 193 --------------- .../timeline-common/TimelinePageCardTemplate.tsx | 153 ------------ .../views/timeline-common/TimelinePageTemplate.tsx | 90 ------- .../timeline-common/TimelinePagedPostListView.tsx | 34 --- .../timeline-common/TimelinePostContentView.tsx | 197 --------------- .../src/views/timeline-common/TimelinePostEdit.css | 20 -- .../src/views/timeline-common/TimelinePostEdit.tsx | 270 --------------------- .../views/timeline-common/TimelinePostEditCard.tsx | 31 --- .../timeline-common/TimelinePostEditNoLogin.tsx | 18 -- .../views/timeline-common/TimelinePostListView.tsx | 75 ------ .../src/views/timeline-common/TimelinePostView.tsx | 159 ------------ .../TimelinePropertyChangeDialog.tsx | 88 ------- FrontEnd/src/views/timeline-common/index.css | 246 ------------------- FrontEnd/src/views/timeline/CollapseButton.tsx | 23 ++ .../src/views/timeline/ConnectionStatusBadge.css | 36 +++ .../src/views/timeline/ConnectionStatusBadge.tsx | 41 ++++ FrontEnd/src/views/timeline/MarkdownPostEdit.css | 21 ++ FrontEnd/src/views/timeline/MarkdownPostEdit.tsx | 209 ++++++++++++++++ .../views/timeline/PostPropertyChangeDialog.tsx | 42 ++++ FrontEnd/src/views/timeline/Timeline.tsx | 166 +++++++++++++ FrontEnd/src/views/timeline/TimelineCard.tsx | 210 ++++++++++++---- FrontEnd/src/views/timeline/TimelineDateLabel.tsx | 19 ++ FrontEnd/src/views/timeline/TimelineEmptyItem.tsx | 25 ++ FrontEnd/src/views/timeline/TimelineLine.tsx | 51 ++++ FrontEnd/src/views/timeline/TimelineLoading.tsx | 16 ++ FrontEnd/src/views/timeline/TimelineMember.css | 8 + FrontEnd/src/views/timeline/TimelineMember.tsx | 193 +++++++++++++++ .../views/timeline/TimelinePagedPostListView.tsx | 34 +++ .../src/views/timeline/TimelinePostContentView.tsx | 197 +++++++++++++++ FrontEnd/src/views/timeline/TimelinePostEdit.css | 20 ++ FrontEnd/src/views/timeline/TimelinePostEdit.tsx | 270 +++++++++++++++++++++ .../src/views/timeline/TimelinePostEditCard.tsx | 31 +++ .../src/views/timeline/TimelinePostEditNoLogin.tsx | 18 ++ .../src/views/timeline/TimelinePostListView.tsx | 75 ++++++ FrontEnd/src/views/timeline/TimelinePostView.tsx | 159 ++++++++++++ .../timeline/TimelinePropertyChangeDialog.tsx | 88 +++++++ FrontEnd/src/views/timeline/index.css | 246 +++++++++++++++++++ FrontEnd/src/views/timeline/index.tsx | 80 +++++- FrontEnd/src/views/user/UserCard.tsx | 53 ---- FrontEnd/src/views/user/index.css | 0 FrontEnd/src/views/user/index.tsx | 36 --- 59 files changed, 2352 insertions(+), 2407 deletions(-) delete mode 100644 FrontEnd/src/views/timeline-common/CollapseButton.tsx delete mode 100644 FrontEnd/src/views/timeline-common/ConnectionStatusBadge.css delete mode 100644 FrontEnd/src/views/timeline-common/ConnectionStatusBadge.tsx delete mode 100644 FrontEnd/src/views/timeline-common/MarkdownPostEdit.css delete mode 100644 FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx delete mode 100644 FrontEnd/src/views/timeline-common/PostPropertyChangeDialog.tsx delete mode 100644 FrontEnd/src/views/timeline-common/Timeline.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelineDateLabel.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelineEmptyItem.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelineLine.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelineLoading.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelineMember.css delete mode 100644 FrontEnd/src/views/timeline-common/TimelineMember.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePageCardTemplate.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePageTemplate.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePagedPostListView.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostContentView.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostEdit.css delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostEdit.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostEditCard.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostEditNoLogin.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostListView.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePostView.tsx delete mode 100644 FrontEnd/src/views/timeline-common/TimelinePropertyChangeDialog.tsx delete mode 100644 FrontEnd/src/views/timeline-common/index.css create mode 100644 FrontEnd/src/views/timeline/CollapseButton.tsx create mode 100644 FrontEnd/src/views/timeline/ConnectionStatusBadge.css create mode 100644 FrontEnd/src/views/timeline/ConnectionStatusBadge.tsx create mode 100644 FrontEnd/src/views/timeline/MarkdownPostEdit.css create mode 100644 FrontEnd/src/views/timeline/MarkdownPostEdit.tsx create mode 100644 FrontEnd/src/views/timeline/PostPropertyChangeDialog.tsx create mode 100644 FrontEnd/src/views/timeline/Timeline.tsx create mode 100644 FrontEnd/src/views/timeline/TimelineDateLabel.tsx create mode 100644 FrontEnd/src/views/timeline/TimelineEmptyItem.tsx create mode 100644 FrontEnd/src/views/timeline/TimelineLine.tsx create mode 100644 FrontEnd/src/views/timeline/TimelineLoading.tsx create mode 100644 FrontEnd/src/views/timeline/TimelineMember.css create mode 100644 FrontEnd/src/views/timeline/TimelineMember.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePagedPostListView.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostContentView.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostEdit.css create mode 100644 FrontEnd/src/views/timeline/TimelinePostEdit.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostEditCard.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostEditNoLogin.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostListView.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePostView.tsx create mode 100644 FrontEnd/src/views/timeline/TimelinePropertyChangeDialog.tsx create mode 100644 FrontEnd/src/views/timeline/index.css delete mode 100644 FrontEnd/src/views/user/UserCard.tsx delete mode 100644 FrontEnd/src/views/user/index.css delete mode 100644 FrontEnd/src/views/user/index.tsx diff --git a/BackEnd/Timeline/Models/Http/HttpTimeline.cs b/BackEnd/Timeline/Models/Http/HttpTimeline.cs index e3e46bd5..83398baf 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimeline.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimeline.cs @@ -10,11 +10,12 @@ namespace Timeline.Models.Http { public HttpTimeline() { } - public HttpTimeline(string uniqueId, string title, string name, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, bool manageable, bool postable, HttpTimelineLinks links) + public HttpTimeline(string uniqueId, string title, string name, string nameV2, DateTime nameLastModifed, string description, HttpUser owner, TimelineVisibility visibility, List members, string? color, DateTime createTime, DateTime lastModified, bool isHighlight, bool isBookmark, bool manageable, bool postable, HttpTimelineLinks links) { UniqueId = uniqueId; Title = title; Name = name; + NameV2 = nameV2; NameLastModifed = nameLastModifed; Description = description; Owner = owner; @@ -43,6 +44,10 @@ namespace Timeline.Models.Http /// public string Name { get; set; } = default!; /// + /// Name of timeline. + /// + public string NameV2 { get; set; } = default!; + /// /// Last modified time of timeline name. /// public DateTime NameLastModifed { get; set; } = default!; diff --git a/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs b/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs index 5e069821..5c6a7167 100644 --- a/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs +++ b/BackEnd/Timeline/Models/Http/HttpTimelinePost.cs @@ -11,7 +11,7 @@ namespace Timeline.Models.Http { public HttpTimelinePost() { } - public HttpTimelinePost(long id, List dataList, bool deleted, DateTime time, HttpUser? author, string? color, DateTime lastUpdated, string timelineName, bool editable) + public HttpTimelinePost(long id, List dataList, bool deleted, DateTime time, HttpUser? author, string? color, DateTime lastUpdated, string timelineOwnerV2, string timelineNameV2, string timelineName, bool editable) { Id = id; DataList = dataList; @@ -20,6 +20,8 @@ namespace Timeline.Models.Http Author = author; Color = color; LastUpdated = lastUpdated; + TimelineOwnerV2 = timelineOwnerV2; + TimelineNameV2 = timelineNameV2; TimelineName = timelineName; Editable = editable; } @@ -27,7 +29,7 @@ namespace Timeline.Models.Http /// /// Post id. /// - public long Id { get; set; } + public long Id { get; set; } /// /// The data list. /// @@ -54,6 +56,14 @@ namespace Timeline.Models.Http /// Last updated time. /// public DateTime LastUpdated { get; set; } = default!; + /// + /// Timeline owner username. + /// + public string TimelineOwnerV2 { get; set; } = default!; + /// + /// Timeline name. + /// + public string TimelineNameV2 { get; set; } = default!; /// /// Timeline name. /// diff --git a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs index 2a0ba89f..a59b906c 100644 --- a/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs +++ b/BackEnd/Timeline/Services/Mapper/TimelineMapper.cs @@ -77,6 +77,7 @@ namespace Timeline.Services.Mapper uniqueId: entity.UniqueId, title: string.IsNullOrEmpty(entity.Title) ? timelineName : entity.Title, name: timelineName, + nameV2: entity.Name is null ? "self" : entity.Name, nameLastModifed: entity.NameLastModified, description: entity.Description ?? "", owner: await _userMapper.MapAsync(entity.Owner, urlHelper, user), @@ -137,6 +138,8 @@ namespace Timeline.Services.Mapper color: entity.Color, deleted: entity.Deleted, lastUpdated: entity.LastUpdated, + timelineOwnerV2: entity.Timeline.Owner.Username, + timelineNameV2: entity.Timeline.Name is null ? "self" : entity.Timeline.Name, timelineName: CalculateTimelineName(entity.Timeline), editable: editable ); diff --git a/FrontEnd/package.json b/FrontEnd/package.json index b1fc3b2f..ffe9a641 100644 --- a/FrontEnd/package.json +++ b/FrontEnd/package.json @@ -20,9 +20,9 @@ "lodash": "^4.17.21", "moment": "^2.29.2", "pepjs": "^0.5.3", - "react": "^18.0.0", + "react": "^17.0.0", "react-color": "^2.19.3", - "react-dom": "^18.0.0", + "react-dom": "^17.0.0", "react-i18next": "^11.16.2", "react-popper": "^2.2.5", "react-responsive": "^8.2.0", @@ -34,8 +34,8 @@ "workbox-cacheable-response": "^6.5.2", "workbox-expiration": "^6.5.2", "workbox-precaching": "^6.5.2", - "workbox-routing": "^6.5.0", - "workbox-strategies": "^6.5.1", + "workbox-routing": "^6.5.2", + "workbox-strategies": "^6.5.2", "workbox-window": "^6.5.2", "xregexp": "^5.1.0" }, diff --git a/FrontEnd/src/App.tsx b/FrontEnd/src/App.tsx index 69223abb..5e61848a 100644 --- a/FrontEnd/src/App.tsx +++ b/FrontEnd/src/App.tsx @@ -8,7 +8,6 @@ import Home from "./views/home"; import Login from "./views/login"; import Settings from "./views/settings"; import About from "./views/about"; -import User from "./views/user"; import TimelinePage from "./views/timeline"; import Search from "./views/search"; import Admin from "./views/admin"; @@ -35,8 +34,8 @@ function App(): ReactElement | null { } /> } /> } /> - } /> - } /> + } /> + } /> } /> } /> } /> diff --git a/FrontEnd/src/http/timeline.ts b/FrontEnd/src/http/timeline.ts index 9697c1a0..49a7b8f2 100644 --- a/FrontEnd/src/http/timeline.ts +++ b/FrontEnd/src/http/timeline.ts @@ -6,7 +6,7 @@ import { axios, apiBaseUrl, extractResponseData, - convertToIfErrorCodeIs, + convertToIfStatusCodeIs, getHttpToken, } from "./common"; import { HttpUser } from "./user"; @@ -18,7 +18,7 @@ export type TimelineVisibility = typeof kTimelineVisibilities[number]; export interface HttpTimelineInfo { uniqueId: string; title: string; - name: string; + nameV2: string; description: string; owner: HttpUser; visibility: TimelineVisibility; @@ -54,7 +54,8 @@ export interface HttpTimelinePostInfo { dataList: HttpTimelinePostDataDigest[]; color: string; lastUpdated: string; - timelineName: string; + timelineOwnerV2: string; + timelineNameV2: string; editable: boolean; } @@ -90,28 +91,57 @@ export class HttpTimelineNameConflictError extends Error { export interface IHttpTimelineClient { listTimeline(query: HttpTimelineListQuery): Promise; - getTimeline(timelineName: string): Promise; + getTimeline( + ownerUsername: string, + timelineName: string + ): Promise; postTimeline(req: HttpTimelinePostRequest): Promise; patchTimeline( + ownerUsername: string, timelineName: string, req: HttpTimelinePatchRequest ): Promise; - deleteTimeline(timelineName: string): Promise; - memberPut(timelineName: string, username: string): Promise; - memberDelete(timelineName: string, username: string): Promise; - listPost(timelineName: string): Promise; - generatePostDataUrl(timelineName: string, postId: number): string; - getPostDataAsString(timelineName: string, postId: number): Promise; + deleteTimeline(ownerUsername: string, timelineName: string): Promise; + memberPut( + ownerUsername: string, + timelineName: string, + username: string + ): Promise; + memberDelete( + ownerUsername: string, + timelineName: string, + username: string + ): Promise; + listPost( + ownerUsername: string, + timelineName: string + ): Promise; + generatePostDataUrl( + ownerUsername: string, + timelineName: string, + postId: number + ): string; + getPostDataAsString( + ownerUsername: string, + timelineName: string, + postId: number + ): Promise; postPost( + ownerUsername: string, timelineName: string, req: HttpTimelinePostPostRequest ): Promise; patchPost( + ownerUsername: string, timelineName: string, postId: number, req: HttpTimelinePostPatchRequest ): Promise; - deletePost(timelineName: string, postId: number): Promise; + deletePost( + ownerUsername: string, + timelineName: string, + postId: number + ): Promise; } export class HttpTimelineClient implements IHttpTimelineClient { @@ -123,63 +153,97 @@ export class HttpTimelineClient implements IHttpTimelineClient { .then(extractResponseData); } - getTimeline(timelineName: string): Promise { + getTimeline( + ownerUsername: string, + timelineName: string + ): Promise { return axios - .get(`${apiBaseUrl}/timelines/${timelineName}`) + .get( + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}` + ) .then(extractResponseData); } postTimeline(req: HttpTimelinePostRequest): Promise { return axios - .post(`${apiBaseUrl}/timelines`, req) + .post(`${apiBaseUrl}/v2/timelines`, req) .then(extractResponseData) - .catch(convertToIfErrorCodeIs(11040101, HttpTimelineNameConflictError)); + .catch(convertToIfStatusCodeIs(422, HttpTimelineNameConflictError)); } patchTimeline( + ownerUsername: string, timelineName: string, req: HttpTimelinePatchRequest ): Promise { return axios - .patch(`${apiBaseUrl}/timelines/${timelineName}`, req) + .patch( + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}`, + req + ) .then(extractResponseData); } - deleteTimeline(timelineName: string): Promise { - return axios.delete(`${apiBaseUrl}/timelines/${timelineName}`).then(); + deleteTimeline(ownerUsername: string, timelineName: string): Promise { + return axios + .delete(`${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}`) + .then(); } - memberPut(timelineName: string, username: string): Promise { + memberPut( + ownerUsername: string, + timelineName: string, + username: string + ): Promise { return axios - .put(`${apiBaseUrl}/timelines/${timelineName}/members/${username}`) + .put( + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/members/${username}` + ) .then(); } - memberDelete(timelineName: string, username: string): Promise { + memberDelete( + ownerUsername: string, + timelineName: string, + username: string + ): Promise { return axios - .delete(`${apiBaseUrl}/timelines/${timelineName}/members/${username}`) + .delete( + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/members/${username}` + ) .then(); } - listPost(timelineName: string): Promise { + listPost( + ownerUsername: string, + timelineName: string + ): Promise { return axios .get( - `${apiBaseUrl}/timelines/${timelineName}/posts` + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts` ) .then(extractResponseData); } - generatePostDataUrl(timelineName: string, postId: number): string { + generatePostDataUrl( + ownerUsername: string, + timelineName: string, + postId: number + ): string { return applyQueryParameters( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}/data`, + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts/${postId}/data`, { token: getHttpToken() } ); } - getPostDataAsString(timelineName: string, postId: number): Promise { + getPostDataAsString( + ownerUsername: string, + timelineName: string, + postId: number + ): Promise { return axios .get( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}/data`, + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts/${postId}/data`, { responseType: "text", } @@ -188,33 +252,41 @@ export class HttpTimelineClient implements IHttpTimelineClient { } postPost( + ownerUsername: string, timelineName: string, req: HttpTimelinePostPostRequest ): Promise { return axios .post( - `${apiBaseUrl}/timelines/${timelineName}/posts`, + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts`, req ) .then(extractResponseData); } patchPost( + ownerUsername: string, timelineName: string, postId: number, req: HttpTimelinePostPatchRequest ): Promise { return axios .patch( - `${apiBaseUrl}/timelines/${timelineName}/posts/${postId}`, + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts/${postId}`, req ) .then(extractResponseData); } - deletePost(timelineName: string, postId: number): Promise { + deletePost( + ownerUsername: string, + timelineName: string, + postId: number + ): Promise { return axios - .delete(`${apiBaseUrl}/timelines/${timelineName}/posts/${postId}`) + .delete( + `${apiBaseUrl}/v2/timelines/${ownerUsername}/${timelineName}/posts/${postId}` + ) .then(); } } diff --git a/FrontEnd/src/views/timeline-common/CollapseButton.tsx b/FrontEnd/src/views/timeline-common/CollapseButton.tsx deleted file mode 100644 index 31976228..00000000 --- a/FrontEnd/src/views/timeline-common/CollapseButton.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; -import classnames from "classnames"; - -const CollapseButton: React.FC<{ - collapse: boolean; - onClick: () => void; - className?: string; - style?: React.CSSProperties; -}> = ({ collapse, onClick, className, style }) => { - return ( - - ); -}; - -export default CollapseButton; diff --git a/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.css b/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.css deleted file mode 100644 index 7fe83b9b..00000000 --- a/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.css +++ /dev/null @@ -1,36 +0,0 @@ -.connection-status-badge { - font-size: 0.8em; - border-radius: 5px; - padding: 0.1em 1em; - background-color: #eaf2ff; -} -.connection-status-badge::before { - width: 10px; - height: 10px; - border-radius: 50%; - display: inline-block; - content: ""; - margin-right: 0.6em; -} -.connection-status-badge.success { - color: #006100; -} -.connection-status-badge.success::before { - background-color: #006100; -} - -.connection-status-badge.warning { - color: #e4a700; -} - -.connection-status-badge.warning::before { - background-color: #e4a700; -} - -.connection-status-badge.danger { - color: #fd1616; -} - -.connection-status-badge.danger::before { - background-color: #fd1616; -} diff --git a/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.tsx b/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.tsx deleted file mode 100644 index c8478557..00000000 --- a/FrontEnd/src/views/timeline-common/ConnectionStatusBadge.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from "react"; -import classnames from "classnames"; -import { HubConnectionState } from "@microsoft/signalr"; -import { useTranslation } from "react-i18next"; - -import "./ConnectionStatusBadge.css"; - -export interface ConnectionStatusBadgeProps { - status: HubConnectionState; - className?: string; - style?: React.CSSProperties; -} - -const classNameMap: Record = { - Connected: "success", - Connecting: "warning", - Disconnected: "danger", - Disconnecting: "warning", - Reconnecting: "warning", -}; - -const ConnectionStatusBadge: React.FC = (props) => { - const { status, className, style } = props; - - const { t } = useTranslation(); - - return ( -
- {t(`connectionState.${status}`)} -
- ); -}; - -export default ConnectionStatusBadge; diff --git a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.css b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.css deleted file mode 100644 index e36be992..00000000 --- a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.css +++ /dev/null @@ -1,21 +0,0 @@ -.timeline-markdown-post-edit-page { - overflow: auto; - max-height: 300px; -} - -.timeline-markdown-post-edit-image-container { - position: relative; - text-align: center; - margin-bottom: 1em; -} - -.timeline-markdown-post-edit-image { - max-width: 100%; - max-height: 200px; -} - -.timeline-markdown-post-edit-image-delete-button { - position: absolute; - right: 10px; - top: 2px; -} diff --git a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx b/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx deleted file mode 100644 index a3a8f408..00000000 --- a/FrontEnd/src/views/timeline-common/MarkdownPostEdit.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import React from "react"; -import classnames from "classnames"; -import { useTranslation } from "react-i18next"; - -import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; - -import TimelinePostBuilder from "@/services/TimelinePostBuilder"; - -import FlatButton from "../common/button/FlatButton"; -import TabPages from "../common/tab/TabPages"; -import ConfirmDialog from "../common/dailog/ConfirmDialog"; -import Spinner from "../common/Spinner"; - -import "./MarkdownPostEdit.css"; - -export interface MarkdownPostEditProps { - timeline: string; - onPosted: (post: HttpTimelinePostInfo) => void; - onPostError: () => void; - onClose: () => void; - className?: string; - style?: React.CSSProperties; -} - -const MarkdownPostEdit: React.FC = ({ - timeline: timelineName, - onPosted, - onClose, - onPostError, - className, - style, -}) => { - const { t } = useTranslation(); - - const [canLeave, setCanLeave] = React.useState(true); - - const [process, setProcess] = React.useState(false); - - const [showLeaveConfirmDialog, setShowLeaveConfirmDialog] = - React.useState(false); - - const [text, _setText] = React.useState(""); - const [images, _setImages] = React.useState<{ file: File; url: string }[]>( - [] - ); - const [previewHtml, _setPreviewHtml] = React.useState(""); - - const _builder = React.useRef(null); - - const getBuilder = (): TimelinePostBuilder => { - if (_builder.current == null) { - const builder = new TimelinePostBuilder(() => { - setCanLeave(builder.isEmpty); - _setText(builder.text); - _setImages(builder.images); - _setPreviewHtml(builder.renderHtml()); - }); - _builder.current = builder; - } - return _builder.current; - }; - - const canSend = text.length > 0; - - React.useEffect(() => { - return () => { - getBuilder().dispose(); - }; - }, []); - - React.useEffect(() => { - window.onbeforeunload = (): unknown => { - if (!canLeave) { - return t("timeline.confirmLeave"); - } - }; - - return () => { - window.onbeforeunload = null; - }; - }, [canLeave, t]); - - const send = async (): Promise => { - setProcess(true); - try { - const dataList = await getBuilder().build(); - const post = await getHttpTimelineClient().postPost(timelineName, { - dataList, - }); - onPosted(post); - onClose(); - } catch (e) { - setProcess(false); - onPostError(); - } - }; - - return ( - <> - - ) : ( -
- { - if (canLeave) { - onClose(); - } else { - setShowLeaveConfirmDialog(true); - } - }} - /> - {canSend && ( - void send()} /> - )} -
- ) - } - pages={[ - { - name: "text", - text: "edit", - page: ( -