From 3aa87cc26fd58836b82c067b58a47e08e30a7784 Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 4 Jun 2020 00:18:50 +0800 Subject: refactor(front): Make codes lint-clean! --- .../src/timeline/TimelineDeleteDialog.tsx | 12 +++---- .../ClientApp/src/timeline/TimelineInfoCard.tsx | 17 ++++----- Timeline/ClientApp/src/timeline/TimelineMember.tsx | 24 +++++++------ .../src/timeline/TimelinePageTemplate.tsx | 35 ++++++++++++------ .../src/timeline/TimelinePageTemplateUI.tsx | 4 +-- .../ClientApp/src/timeline/TimelinePostEdit.tsx | 41 +++++++++++++--------- 6 files changed, 77 insertions(+), 56 deletions(-) (limited to 'Timeline/ClientApp/src/timeline') diff --git a/Timeline/ClientApp/src/timeline/TimelineDeleteDialog.tsx b/Timeline/ClientApp/src/timeline/TimelineDeleteDialog.tsx index 2b682a6b..e2d8ad5a 100644 --- a/Timeline/ClientApp/src/timeline/TimelineDeleteDialog.tsx +++ b/Timeline/ClientApp/src/timeline/TimelineDeleteDialog.tsx @@ -4,7 +4,7 @@ import { useHistory } from 'react-router'; import { Trans } from 'react-i18next'; import { apiBaseUrl } from '../config'; -import { useUser } from '../data/user'; +import { useUserLoggedIn } from '../data/user'; import OperationDialog from '../common/OperationDialog'; interface TimelineDeleteDialog { @@ -13,8 +13,8 @@ interface TimelineDeleteDialog { close: () => void; } -const TimelineDeleteDialog: React.FC = props => { - const user = useUser()!; +const TimelineDeleteDialog: React.FC = (props) => { + const user = useUserLoggedIn(); const history = useHistory(); const { name } = props; @@ -35,14 +35,14 @@ const TimelineDeleteDialog: React.FC = props => { inputScheme={[ { type: 'text', - validator: value => { + validator: (value) => { if (value !== name) { return 'timeline.deleteDialog.notMatch'; } else { return null; } - } - } + }, + }, ]} onProcess={() => { return axios.delete( diff --git a/Timeline/ClientApp/src/timeline/TimelineInfoCard.tsx b/Timeline/ClientApp/src/timeline/TimelineInfoCard.tsx index 2ce7c378..b3af4cab 100644 --- a/Timeline/ClientApp/src/timeline/TimelineInfoCard.tsx +++ b/Timeline/ClientApp/src/timeline/TimelineInfoCard.tsx @@ -28,6 +28,7 @@ const TimelineInfoCard: React.FC = (props) => { const { t } = useTranslation(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const containerRef = React.useRef(null!); const notifyHeight = React.useCallback((): void => { @@ -48,13 +49,6 @@ const TimelineInfoCard: React.FC = (props) => { (): void => setManageDropdownOpen((old) => !old), [] ); - const onManageProperty = React.useCallback( - (): void => onManage!('property'), - [onManage] - ); - const onManageDelete = React.useCallback((): void => onManage!('delete'), [ - onManage, - ]); return (
= (props) => { {t(timelineVisibilityTooltipTranslationMap[props.timeline.visibility])}
- {props.onManage != null ? ( + {onManage != null ? ( {t('timeline.manage')} - + onManage('property')}> {t('timeline.manageItem.property')} {t('timeline.manageItem.member')} - + onManage('delete')} + > {t('timeline.manageItem.delete')} diff --git a/Timeline/ClientApp/src/timeline/TimelineMember.tsx b/Timeline/ClientApp/src/timeline/TimelineMember.tsx index eac8d417..b8bb49ee 100644 --- a/Timeline/ClientApp/src/timeline/TimelineMember.tsx +++ b/Timeline/ClientApp/src/timeline/TimelineMember.tsx @@ -11,7 +11,7 @@ import { Modal, Row, Col, - Button + Button, } from 'reactstrap'; export interface TimelineMemberCallbacks { @@ -25,7 +25,7 @@ export interface TimelineMemberProps { edit: TimelineMemberCallbacks | null | undefined; } -const TimelineMember: React.FC = props => { +const TimelineMember: React.FC = (props) => { const { t } = useTranslation(); const [userSearchText, setUserSearchText] = useState(''); @@ -87,7 +87,7 @@ const TimelineMember: React.FC = props => { <> { + onChange={(v) => { setUserSearchText(v); }} loading={userSearchState.type === 'loading'} @@ -95,27 +95,27 @@ const TimelineMember: React.FC = props => { if (userSearchText === '') { setUserSearchState({ type: 'error', - data: 'login.emptyUsername' + data: 'login.emptyUsername', }); return; } setUserSearchState({ type: 'loading' }); edit.onCheckUser(userSearchText).then( - u => { + (u) => { if (u == null) { setUserSearchState({ type: 'error', - data: 'timeline.userNotExist' + data: 'timeline.userNotExist', }); } else { setUserSearchState({ type: 'user', data: u }); } }, - e => { + (e) => { setUserSearchState({ type: 'error', - data: e.toString() + data: `${e as string}`, }); } ); @@ -125,7 +125,7 @@ const TimelineMember: React.FC = props => { if (userSearchState.type === 'user') { const u = userSearchState.data; const addable = - members.findIndex(m => m.username === u.username) === -1; + members.findIndex((m) => m.username === u.username) === -1; return ( <> {!addable ? ( @@ -150,7 +150,7 @@ const TimelineMember: React.FC = props => { className="align-self-center" disabled={!addable} onClick={() => { - edit.onAddUser(u).then(_ => { + void edit.onAddUser(u).then((_) => { setUserSearchText(''); setUserSearchState({ type: 'init' }); }); @@ -185,7 +185,9 @@ export interface TimelineMemberDialogProps extends TimelineMemberProps { onClose: () => void; } -export const TimelineMemberDialog: React.FC = props => { +export const TimelineMemberDialog: React.FC = ( + props +) => { return ( diff --git a/Timeline/ClientApp/src/timeline/TimelinePageTemplate.tsx b/Timeline/ClientApp/src/timeline/TimelinePageTemplate.tsx index 3660ad78..2cfb4341 100644 --- a/Timeline/ClientApp/src/timeline/TimelinePageTemplate.tsx +++ b/Timeline/ClientApp/src/timeline/TimelinePageTemplate.tsx @@ -19,6 +19,7 @@ import { TimelineMemberDialog } from './TimelineMember'; import TimelinePropertyChangeDialog from './TimelinePropertyChangeDialog'; import { TimelinePageTemplateUIProps } from './TimelinePageTemplateUI'; import { TimelinePostSendCallback } from './TimelinePostEdit'; +import { UiLogicError } from '../common'; export interface TimelinePageTemplateProps< TManageItem, @@ -88,7 +89,7 @@ export default function TimelinePageTemplate< }, (error) => { if (subscribe) { - setError(error.toString()); + setError(`${error as string}`); } } ); @@ -129,13 +130,19 @@ export default function TimelinePageTemplate< let dialogElement: React.ReactElement | undefined; if (dialog === 'property') { + if (timeline == null) { + throw new UiLogicError( + 'Timeline is null but attempt to open change property dialog.' + ); + } + dialogElement = ( { return service.changeProperty(name, req).then((newTimeline) => { @@ -145,13 +152,19 @@ export default function TimelinePageTemplate< /> ); } else if (dialog === 'member') { + if (timeline == null) { + throw new UiLogicError( + 'Timeline is null but attempt to open change property dialog.' + ); + } + dialogElement = ( { return fetchUser(u).catch((e) => { @@ -168,18 +181,18 @@ export default function TimelinePageTemplate< onAddUser: (u) => { return service.addMember(name, u.username).then((_) => { setTimeline({ - ...timeline!, - members: concat(timeline!.members, u), + ...timeline, + members: concat(timeline.members, u), }); }); }, onRemoveUser: (u) => { - service.removeMember(name, u).then((_) => { + void service.removeMember(name, u).then((_) => { setTimeline({ - ...timeline!, + ...timeline, members: without( - timeline!.members, - timeline!.members.find((m) => m.username === u) + timeline.members, + timeline.members.find((m) => m.username === u) ), }); }); diff --git a/Timeline/ClientApp/src/timeline/TimelinePageTemplateUI.tsx b/Timeline/ClientApp/src/timeline/TimelinePageTemplateUI.tsx index d96b3260..22fb1987 100644 --- a/Timeline/ClientApp/src/timeline/TimelinePageTemplateUI.tsx +++ b/Timeline/ClientApp/src/timeline/TimelinePageTemplateUI.tsx @@ -44,7 +44,7 @@ export default function TimelinePageTemplateUI( const onPostEditHeightChange = React.useCallback((height: number): void => { const { current: bottomSpaceDiv } = bottomSpaceRef; if (bottomSpaceDiv != null) { - bottomSpaceDiv.style.height = height + 'px'; + bottomSpaceDiv.style.height = `${height}px`; } if (height === 0) { const alertHost = getAlertHost(); @@ -54,7 +54,7 @@ export default function TimelinePageTemplateUI( } else { const alertHost = getAlertHost(); if (alertHost != null) { - alertHost.style.marginBottom = height + 'px'; + alertHost.style.marginBottom = `${height}px`; } } }, []); diff --git a/Timeline/ClientApp/src/timeline/TimelinePostEdit.tsx b/Timeline/ClientApp/src/timeline/TimelinePostEdit.tsx index fe1fda9b..2b76b03b 100644 --- a/Timeline/ClientApp/src/timeline/TimelinePostEdit.tsx +++ b/Timeline/ClientApp/src/timeline/TimelinePostEdit.tsx @@ -1,12 +1,13 @@ import React from 'react'; import clsx from 'clsx'; -import { Container, Button, Spinner, Row, Col } from 'reactstrap'; +import { Button, Spinner, Row, Col } from 'reactstrap'; import { useTranslation } from 'react-i18next'; import { pushAlert } from '../common/alert-service'; import { CreatePostRequest } from '../data/timeline'; import FileInput from '../common/FileInput'; +import { UiLogicError } from '../common'; interface TimelinePostEditImageProps { onSelect: (blob: Blob | null) => void; @@ -96,11 +97,12 @@ const TimelinePostEdit: React.FC = (props) => { const canSend = kind === 'text' || (kind === 'image' && imageBlob != null); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const containerRef = React.useRef(null!); + React.useEffect(() => { if (props.onHeightChange) { - props.onHeightChange( - document.getElementById('timeline-post-edit-area')!.clientHeight - ); + props.onHeightChange(containerRef.current.clientHeight); } return () => { if (props.onHeightChange) { @@ -117,20 +119,31 @@ const TimelinePostEdit: React.FC = (props) => { const onSend = React.useCallback(() => { setState('process'); - const req: CreatePostRequest = - kind === 'text' - ? { + const req: CreatePostRequest = (() => { + switch (kind) { + case 'text': + return { content: { type: 'text', text: text, }, + } as CreatePostRequest; + case 'image': + if (imageBlob == null) { + throw new UiLogicError( + 'Content type is image but image blob is null.' + ); } - : { + return { content: { type: 'image', - data: imageBlob!, + data: imageBlob, }, - }; + } as CreatePostRequest; + default: + throw new UiLogicError('Unknown content type.'); + } + })(); onPost(req).then( (_) => { @@ -155,11 +168,7 @@ const TimelinePostEdit: React.FC = (props) => { }, []); return ( - +
{kind === 'text' ? ( @@ -198,7 +207,7 @@ const TimelinePostEdit: React.FC = (props) => { })()} - +
); }; -- cgit v1.2.3