diff options
author | crupest <crupest@outlook.com> | 2023-09-14 23:47:16 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2023-09-14 23:47:16 +0800 |
commit | 40b4871c3f7bfe04f332ae7fb687fd7d9ae34734 (patch) | |
tree | cba45fa30627a704c2fb5132eff3f936ba1dd54e | |
parent | c1f79460d57a4daba75bdc34b7b7a3ea2d7254b3 (diff) | |
download | timeline-40b4871c3f7bfe04f332ae7fb687fd7d9ae34734.tar.gz timeline-40b4871c3f7bfe04f332ae7fb687fd7d9ae34734.tar.bz2 timeline-40b4871c3f7bfe04f332ae7fb687fd7d9ae34734.zip |
...
13 files changed, 140 insertions, 158 deletions
diff --git a/FrontEnd/src/pages/timeline/ConnectionStatusBadge.css b/FrontEnd/src/pages/timeline/ConnectionStatusBadge.css index fc01484e..f2f8df66 100644 --- a/FrontEnd/src/pages/timeline/ConnectionStatusBadge.css +++ b/FrontEnd/src/pages/timeline/ConnectionStatusBadge.css @@ -22,7 +22,7 @@ }
.connection-status-badge.warning {
- color: #e4a700;
+ color: #e4a700; /* TODO: Warning color */
}
.connection-status-badge.warning::before {
diff --git a/FrontEnd/src/pages/timeline/ConnectionStatusBadge.tsx b/FrontEnd/src/pages/timeline/ConnectionStatusBadge.tsx index 2b820454..63990878 100644 --- a/FrontEnd/src/pages/timeline/ConnectionStatusBadge.tsx +++ b/FrontEnd/src/pages/timeline/ConnectionStatusBadge.tsx @@ -1,14 +1,13 @@ -import * as React from "react"; -import classnames from "classnames"; +import classNames from "classnames"; import { HubConnectionState } from "@microsoft/signalr"; -import { useTranslation } from "react-i18next"; + +import { useC }from '~/src/components/common'; import "./ConnectionStatusBadge.css"; -export interface ConnectionStatusBadgeProps { +interface ConnectionStatusBadgeProps { status: HubConnectionState; className?: string; - style?: React.CSSProperties; } const classNameMap: Record<HubConnectionState, string> = { @@ -19,23 +18,19 @@ const classNameMap: Record<HubConnectionState, string> = { Reconnecting: "warning", }; -const ConnectionStatusBadge: React.FC<ConnectionStatusBadgeProps> = (props) => { - const { status, className, style } = props; - - const { t } = useTranslation(); +export default function ConnectionStatusBadge({status, className}: ConnectionStatusBadgeProps) { + const c = useC(); return ( <div - className={classnames( + className={classNames( "connection-status-badge", classNameMap[status], className )} - style={style} > - {t(`connectionState.${status}`)} + {c(`connectionState.${status}`)} </div> ); }; -export default ConnectionStatusBadge; diff --git a/FrontEnd/src/pages/timeline/Timeline.tsx b/FrontEnd/src/pages/timeline/Timeline.tsx index 1d8e28d5..32cbf8c8 100644 --- a/FrontEnd/src/pages/timeline/Timeline.tsx +++ b/FrontEnd/src/pages/timeline/Timeline.tsx @@ -18,8 +18,8 @@ import { getTimelinePostUpdate$ } from "~src/services/timeline"; import { useScrollToBottom } from "~src/components/hooks"; import TimelinePostList from "./TimelinePostList"; -import TimelinePostEdit from "./TimelinePostCreateView"; import TimelineInfoCard from "./TimelineInfoCard"; +import TimelinePostEdit from "./edit/TimelinePostCreateView"; import "./Timeline.css"; diff --git a/FrontEnd/src/pages/timeline/TimelinePostCreateView.css b/FrontEnd/src/pages/timeline/TimelinePostCreateView.css deleted file mode 100644 index e483ca17..00000000 --- a/FrontEnd/src/pages/timeline/TimelinePostCreateView.css +++ /dev/null @@ -1,54 +0,0 @@ -.timeline-post-create-card {
- position: sticky !important;
- top: 106px;
- z-index: 100;
- margin-right: 200px;
-}
-
-@media (max-width: 576px) {
- .timeline-post-create-container {
- padding-top: 60px;
- }
-
- .timeline-post-create-card{
- margin-right: 0;
- }
-}
-
-.timeline-post-create {
- display: flex;
-}
-
-.timeline-post-create-edit-area {
- flex-grow: 1;
-}
-
-.timeline-post-create-edit-text {
- width: 100%;
- height: 100%;
- background-color: var(--cru-background-color);
- color: var(--cru-text-major-color);
- border: 1px solid var(--cru-text-major-color);
- padding: 0.5em;
- border-radius: 5px;
-}
-
-.timeline-post-create-edit-text:hover {
- border-color: var(--cru-clickable-secondary-normal-color)
-}
-
-.timeline-post-create-edit-text:focus {
- border-color: var(--cru-clickable-secondary-normal-color)
-}
-
-.timeline-post-create-image {
- max-width: 100px;
- max-height: 100px;
-}
-
-.timeline-post-create-right-area {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-left: 1em;
-}
diff --git a/FrontEnd/src/pages/timeline/TimelinePropertyChangeDialog.tsx b/FrontEnd/src/pages/timeline/TimelinePropertyChangeDialog.tsx index ee5388cb..79838d58 100644 --- a/FrontEnd/src/pages/timeline/TimelinePropertyChangeDialog.tsx +++ b/FrontEnd/src/pages/timeline/TimelinePropertyChangeDialog.tsx @@ -1,5 +1,3 @@ -import * as React from "react"; - import { getHttpTimelineClient, HttpTimelineInfo, @@ -10,7 +8,7 @@ import { import OperationDialog from "~src/components/dialog/OperationDialog"; -export interface TimelinePropertyChangeDialogProps { +interface TimelinePropertyChangeDialogProps { timeline: HttpTimelineInfo; onChange: () => void; } @@ -21,11 +19,10 @@ const labelMap: { [key in TimelineVisibility]: string } = { Register: "timeline.visibility.register", }; -const TimelinePropertyChangeDialog: React.FC< - TimelinePropertyChangeDialogProps -> = (props) => { - const { timeline, onChange } = props; - +export default function TimelinePropertyChangeDialog({ + timeline, + onChange, +}: TimelinePropertyChangeDialogProps) { return ( <OperationDialog title={"timeline.dialogChangeProperty.title"} @@ -78,6 +75,5 @@ const TimelinePropertyChangeDialog: React.FC< }} /> ); -}; +} -export default TimelinePropertyChangeDialog; diff --git a/FrontEnd/src/pages/timeline/edit/ImagePostEdit.css b/FrontEnd/src/pages/timeline/edit/ImagePostEdit.css new file mode 100644 index 00000000..3d5e895c --- /dev/null +++ b/FrontEnd/src/pages/timeline/edit/ImagePostEdit.css @@ -0,0 +1,4 @@ +.timeline-post-create-image { + max-width: 100px; + max-height: 100px; +} diff --git a/FrontEnd/src/pages/timeline/edit/ImagePostEdit.tsx b/FrontEnd/src/pages/timeline/edit/ImagePostEdit.tsx new file mode 100644 index 00000000..d25d04b4 --- /dev/null +++ b/FrontEnd/src/pages/timeline/edit/ImagePostEdit.tsx @@ -0,0 +1,36 @@ +import classNames from "classnames"; + +import BlobImage from "~/src/components/BlobImage"; + +interface TimelinePostEditImageProps { + file: File; + onChange: (file: File | null) => void; + disabled: boolean; + className?: string; +} + +export default function ImagePostEdit(props: TimelinePostEditImageProps) { + const { file, onChange, disabled, className } = props; + + return ( + <div + className={classNames("timeline-post-create-edit-container", className)} + > + <input + type="file" + accept="image/*" + disabled={disabled} + onChange={(e) => { + const files = e.target.files; + if (files == null || files.length === 0) { + onChange(null); + } else { + onChange(files[0]); + } + }} + className="mx-3 my-1" + /> + {file && <BlobImage src={file} className="timeline-post-create-image" />} + </div> + ); +} diff --git a/FrontEnd/src/pages/timeline/MarkdownPostEdit.css b/FrontEnd/src/pages/timeline/edit/MarkdownPostEdit.css index 33a77943..33a77943 100644 --- a/FrontEnd/src/pages/timeline/MarkdownPostEdit.css +++ b/FrontEnd/src/pages/timeline/edit/MarkdownPostEdit.css diff --git a/FrontEnd/src/pages/timeline/MarkdownPostEdit.tsx b/FrontEnd/src/pages/timeline/edit/MarkdownPostEdit.tsx index d10d3f2d..d10d3f2d 100644 --- a/FrontEnd/src/pages/timeline/MarkdownPostEdit.tsx +++ b/FrontEnd/src/pages/timeline/edit/MarkdownPostEdit.tsx diff --git a/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.css b/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.css new file mode 100644 index 00000000..0f2b9dbd --- /dev/null +++ b/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.css @@ -0,0 +1,18 @@ +.timeline-post-create-edit-text { + width: 100%; + height: 100%; + background-color: var(--cru-background-color); + color: var(--cru-text-major-color); + border: 1px solid var(--cru-text-major-color); + padding: 0.5em; + border-radius: 5px; +} + +.timeline-post-create-edit-text:hover { + border-color: var(--cru-clickable-secondary-normal-color); +} + +.timeline-post-create-edit-text:focus { + border-color: var(--cru-clickable-secondary-normal-color); +} + diff --git a/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.tsx b/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.tsx new file mode 100644 index 00000000..1bea3daf --- /dev/null +++ b/FrontEnd/src/pages/timeline/edit/PlainTextPostEdit.tsx @@ -0,0 +1,26 @@ +import classNames from 'classnames' + +interface TimelinePostEditTextProps { + text: string; + disabled: boolean; + onChange: (text: string) => void; + className?: string; +} + +export default function TimelinePostEditText(props: TimelinePostEditTextProps) { + const { text, disabled, onChange, className } = props; + + return ( + <div className={classNames("timeline-post-create-edit-container", className)}> + <textarea + value={text} + disabled={disabled} + onChange={(event) => { + onChange(event.target.value); + }} + className={classNames("timeline-post-create-edit-text")} + /> + </div> + ); +} + diff --git a/FrontEnd/src/pages/timeline/edit/TimelinePostCreateView.css b/FrontEnd/src/pages/timeline/edit/TimelinePostCreateView.css new file mode 100644 index 00000000..5e93d9f2 --- /dev/null +++ b/FrontEnd/src/pages/timeline/edit/TimelinePostCreateView.css @@ -0,0 +1,33 @@ +.timeline-post-create-card {
+ position: sticky !important;
+ top: 106px;
+ z-index: 100;
+ margin-right: 200px;
+}
+
+@media (max-width: 576px) {
+ .timeline-post-create-container {
+ padding-top: 60px;
+ }
+
+ .timeline-post-create-card{
+ margin-right: 0;
+ }
+}
+
+.timeline-post-create {
+ display: flex;
+}
+
+.timeline-post-create-edit-area {
+ flex-grow: 1;
+}
+
+
+
+.timeline-post-create-right-area {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-left: 1em;
+}
diff --git a/FrontEnd/src/pages/timeline/TimelinePostCreateView.tsx b/FrontEnd/src/pages/timeline/edit/TimelinePostCreateView.tsx index 70925cd9..45d742f7 100644 --- a/FrontEnd/src/pages/timeline/TimelinePostCreateView.tsx +++ b/FrontEnd/src/pages/timeline/edit/TimelinePostCreateView.tsx @@ -1,5 +1,6 @@ import { useState, useEffect, ChangeEventHandler } from "react"; import { useTranslation } from "react-i18next"; +import classNames from "classnames"; import { UiLogicError } from "~src/common"; @@ -13,93 +14,20 @@ import { import base64 from "~src/utilities/base64"; import { pushAlert } from "~src/components/alert"; -import BlobImage from "~src/components/BlobImage"; import LoadingButton from "~src/components/button/LoadingButton"; import PopupMenu from "~src/components/menu/PopupMenu"; -import MarkdownPostEdit from "./MarkdownPostEdit"; -import TimelinePostCard from "./TimelinePostCard"; -import TimelinePostContainer from "./TimelinePostContainer"; +import TimelinePostCard from "../TimelinePostCard"; +import TimelinePostContainer from "../TimelinePostContainer"; import IconButton from "~src/components/button/IconButton"; -import "./TimelinePostCreateView.css"; -import classNames from "classnames"; - -interface TimelinePostEditTextProps { - text: string; - disabled: boolean; - onChange: (text: string) => void; - className?: string; -} - -function TimelinePostEditText(props: TimelinePostEditTextProps) { - const { text, disabled, onChange, className } = props; - - return ( - <textarea - value={text} - disabled={disabled} - onChange={(event) => { - onChange(event.target.value); - }} - className={classNames("timeline-post-create-edit-text", className)} - /> - ); -} - -interface TimelinePostEditImageProps { - onSelect: (file: File | null) => void; - disabled: boolean; -} - -function TimelinePostEditImage(props: TimelinePostEditImageProps) { - const { onSelect, disabled } = props; +import PlainTextPostEdit from './PlainTextPostEdit' +import MarkdownPostEdit from "./MarkdownPostEdit"; - const { t } = useTranslation(); +import "./TimelinePostCreateView.css"; - const [file, setFile] = useState<File | null>(null); - const [error, setError] = useState<boolean>(false); - const onInputChange: ChangeEventHandler<HTMLInputElement> = (e) => { - setError(false); - const files = e.target.files; - if (files == null || files.length === 0) { - setFile(null); - onSelect(null); - } else { - setFile(files[0]); - } - }; - useEffect(() => { - return () => { - onSelect(null); - }; - }, [onSelect]); - return ( - <> - <input - type="file" - onChange={onInputChange} - accept="image/*" - disabled={disabled} - className="mx-3 my-1" - /> - {file != null && !error && ( - <BlobImage - src={file} - className="timeline-post-create-image" - onLoad={() => onSelect(file)} - onError={() => { - onSelect(null); - setError(true); - }} - /> - )} - {error ? <div className="text-danger">{t("loadImageError")}</div> : null} - </> - ); -} type PostKind = "text" | "markdown" | "image"; @@ -212,7 +140,7 @@ function TimelinePostEdit(props: TimelinePostEditProps) { {(() => { if (kind === "text") { return ( - <TimelinePostEditText + <PlainTextPostEdit className="timeline-post-create-edit-text" text={text} disabled={process} |