aboutsummaryrefslogtreecommitdiff
path: root/Timeline
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-06-05 21:32:16 +0800
committercrupest <crupest@outlook.com>2020-06-05 21:32:16 +0800
commit926372d503c8522c1b1c9cdfeb6b891b7f96e08d (patch)
tree0b828d3f885d6211449c7ebbbbd40bc6322d65cb /Timeline
parente1ccc1cfe43a44e975dba3a412522f8ea5760ca4 (diff)
downloadtimeline-926372d503c8522c1b1c9cdfeb6b891b7f96e08d.tar.gz
timeline-926372d503c8522c1b1c9cdfeb6b891b7f96e08d.tar.bz2
timeline-926372d503c8522c1b1c9cdfeb6b891b7f96e08d.zip
feat(front): Fix #73 .
Diffstat (limited to 'Timeline')
-rw-r--r--Timeline/ClientApp/src/locales/en/translation.ts7
-rw-r--r--Timeline/ClientApp/src/locales/scheme.ts6
-rw-r--r--Timeline/ClientApp/src/locales/zh/translation.ts6
-rw-r--r--Timeline/ClientApp/src/timeline/Timeline.tsx14
-rw-r--r--Timeline/ClientApp/src/timeline/TimelineItem.tsx112
5 files changed, 111 insertions, 34 deletions
diff --git a/Timeline/ClientApp/src/locales/en/translation.ts b/Timeline/ClientApp/src/locales/en/translation.ts
index 803f8ea6..6faf1121 100644
--- a/Timeline/ClientApp/src/locales/en/translation.ts
+++ b/Timeline/ClientApp/src/locales/en/translation.ts
@@ -81,6 +81,13 @@ const translation: TranslationResource = {
'This is a dangerous action. If you are sure to delete timeline<1>{{name}}</1>, please input its name below and click confirm button.',
notMatch: 'Name does not match.',
},
+ post: {
+ deleteDialog: {
+ title: 'Confirm Delete',
+ prompt:
+ 'Are you sure to delete the post? This operation is not recoverable.',
+ },
+ },
},
user: {
username: 'username',
diff --git a/Timeline/ClientApp/src/locales/scheme.ts b/Timeline/ClientApp/src/locales/scheme.ts
index 6e2a3669..fef39a8e 100644
--- a/Timeline/ClientApp/src/locales/scheme.ts
+++ b/Timeline/ClientApp/src/locales/scheme.ts
@@ -75,6 +75,12 @@ export default interface TranslationResource {
inputPrompt: string;
notMatch: string;
};
+ post: {
+ deleteDialog: {
+ title: string;
+ prompt: string;
+ };
+ };
};
user: {
username: string;
diff --git a/Timeline/ClientApp/src/locales/zh/translation.ts b/Timeline/ClientApp/src/locales/zh/translation.ts
index d1789f3c..130ee297 100644
--- a/Timeline/ClientApp/src/locales/zh/translation.ts
+++ b/Timeline/ClientApp/src/locales/zh/translation.ts
@@ -79,6 +79,12 @@ const translation: TranslationResource = {
'这是一个危险的操作。如果您确认要删除时间线<1>{{name}}</1>,请在下面输入它的名字并点击确认。',
notMatch: '名字不匹配',
},
+ post: {
+ deleteDialog: {
+ title: '确认删除',
+ prompt: '确定删除这个消息?这个操作不可撤销。',
+ },
+ },
},
user: {
username: '用户名',
diff --git a/Timeline/ClientApp/src/timeline/Timeline.tsx b/Timeline/ClientApp/src/timeline/Timeline.tsx
index defca4c3..acc3ba0a 100644
--- a/Timeline/ClientApp/src/timeline/Timeline.tsx
+++ b/Timeline/ClientApp/src/timeline/Timeline.tsx
@@ -65,14 +65,22 @@ const Timeline: React.FC<TimelineProps> = (props) => {
? avatarVersion
: undefined;
+ const toggleMore = onToggleDelete[i];
+
return (
<TimelineItem
post={post}
key={post.id}
current={length - 1 === i}
- showDeleteButton={indexShowDeleteButton === i}
- toggleMore={onToggleDelete[i]}
- onDelete={onItemDelete[i]}
+ more={
+ toggleMore
+ ? {
+ isOpen: indexShowDeleteButton === i,
+ toggle: toggleMore,
+ onDelete: onItemDelete[i],
+ }
+ : undefined
+ }
onClick={onItemClick}
avatarVersion={av}
/>
diff --git a/Timeline/ClientApp/src/timeline/TimelineItem.tsx b/Timeline/ClientApp/src/timeline/TimelineItem.tsx
index 0d2722c0..7d488826 100644
--- a/Timeline/ClientApp/src/timeline/TimelineItem.tsx
+++ b/Timeline/ClientApp/src/timeline/TimelineItem.tsx
@@ -1,18 +1,58 @@
import React from 'react';
-import { useTranslation } from 'react-i18next';
import clsx from 'clsx';
-import { Row, Col } from 'reactstrap';
+import {
+ Row,
+ Col,
+ Modal,
+ ModalHeader,
+ ModalBody,
+ ModalFooter,
+ Button,
+} from 'reactstrap';
import { Link } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
import { TimelinePostInfo } from '../data/timeline';
import { useAvatarUrlWithGivenVersion } from '../user/api';
+const TimelinePostDeleteConfirmDialog: React.FC<{
+ toggle: () => void;
+ onConfirm: () => void;
+}> = ({ toggle, onConfirm }) => {
+ const { t } = useTranslation();
+
+ return (
+ <Modal toggle={toggle} isOpen centered>
+ <ModalHeader className="text-danger">
+ {t('timeline.post.deleteDialog.title')}
+ </ModalHeader>
+ <ModalBody>{t('timeline.post.deleteDialog.prompt')}</ModalBody>
+ <ModalFooter>
+ <Button color="secondary" onClick={toggle}>
+ {t('operationDialog.cancel')}
+ </Button>
+ <Button
+ color="danger"
+ onClick={() => {
+ onConfirm();
+ toggle();
+ }}
+ >
+ {t('operationDialog.confirm')}
+ </Button>
+ </ModalFooter>
+ </Modal>
+ );
+};
+
export interface TimelineItemProps {
post: TimelinePostInfo;
- showDeleteButton?: boolean;
current?: boolean;
- toggleMore?: () => void;
- onDelete?: () => void;
+ more?: {
+ isOpen: boolean;
+ toggle: () => void;
+ onDelete: () => void;
+ };
onClick?: () => void;
avatarVersion?: number;
}
@@ -22,25 +62,18 @@ const TimelineItem: React.FC<TimelineItemProps> = (props) => {
const current = props.current === true;
- const { toggleMore: toggleDelete } = props;
+ const { more } = props;
const avatarUrl = useAvatarUrlWithGivenVersion(
props.avatarVersion,
props.post.author._links.avatar
);
- const onOpenMore = React.useMemo<
- React.MouseEventHandler<HTMLElement> | undefined
- >(() => {
- if (toggleDelete == null) {
- return undefined;
- } else {
- return (e) => {
- toggleDelete();
- e.stopPropagation();
- };
- }
- }, [toggleDelete]);
+ const [deleteDialog, setDeleteDialog] = React.useState<boolean>(false);
+ const toggleDeleteDialog = React.useCallback(
+ () => setDeleteDialog((old) => !old),
+ []
+ );
return (
<Row
@@ -67,11 +100,14 @@ const TimelineItem: React.FC<TimelineItemProps> = (props) => {
</small>
</Row>
</div>
- {props.toggleMore != null ? (
+ {more != null ? (
<div className="col-auto px-2 d-flex justify-content-center align-items-center">
<i
className="fas fa-chevron-circle-down text-info icon-button"
- onClick={onOpenMore}
+ onClick={(e) => {
+ more.toggle();
+ e.stopPropagation();
+ }}
/>
</div>
) : null}
@@ -95,17 +131,31 @@ const TimelineItem: React.FC<TimelineItemProps> = (props) => {
})()}
</p>
</Col>
- {props.showDeleteButton ? (
- <div
- className="position-absolute position-lt w-100 h-100 mask d-flex justify-content-center align-items-center"
- onClick={props.toggleMore}
- >
- <i
- className="fas fa-trash text-danger large-icon"
- onClick={props.onDelete}
- />
- </div>
- ) : undefined}
+ {more != null && more.isOpen ? (
+ <>
+ <div
+ className="position-absolute position-lt w-100 h-100 mask d-flex justify-content-center align-items-center"
+ onClick={more.toggle}
+ >
+ <i
+ className="fas fa-trash text-danger large-icon"
+ onClick={(e) => {
+ toggleDeleteDialog();
+ e.stopPropagation();
+ }}
+ />
+ </div>
+ {deleteDialog ? (
+ <TimelinePostDeleteConfirmDialog
+ toggle={() => {
+ toggleDeleteDialog();
+ more.toggle();
+ }}
+ onConfirm={more.onDelete}
+ />
+ ) : null}
+ </>
+ ) : null}
</Row>
);
};