Article.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { Card, Collapse, Modal, Space } from "antd";
  2. import { Typography } from "antd";
  3. import { useState } from "react";
  4. import Article, { ArticleType } from "../article/Article";
  5. import { Link } from "react-router-dom";
  6. import { fullUrl } from "../../utils";
  7. import { useIntl } from "react-intl";
  8. const { Text } = Typography;
  9. export type TDisplayStyle =
  10. | "modal"
  11. | "card"
  12. | "toggle"
  13. | "link"
  14. | "window"
  15. | "popover";
  16. interface IWidgetChapterCtl {
  17. type?: ArticleType;
  18. id?: string;
  19. book?: string;
  20. paragraphs?: string;
  21. channel?: string;
  22. title?: React.ReactNode;
  23. focus?: string | null;
  24. style?: TDisplayStyle;
  25. modalExtra?: React.ReactNode;
  26. }
  27. export const ArticleCtl = ({
  28. type,
  29. id,
  30. channel,
  31. title,
  32. focus,
  33. book,
  34. paragraphs,
  35. style = "modal",
  36. modalExtra,
  37. }: IWidgetChapterCtl) => {
  38. const intl = useIntl();
  39. const [isModalOpen, setIsModalOpen] = useState(false);
  40. const showModal = () => {
  41. setIsModalOpen(true);
  42. };
  43. const handleOk = () => {
  44. setIsModalOpen(false);
  45. };
  46. const handleCancel = () => {
  47. setIsModalOpen(false);
  48. };
  49. const aTitle = title ? title : "chapter" + id;
  50. const article = (
  51. <Article
  52. active={true}
  53. type={type}
  54. articleId={id}
  55. book={book}
  56. para={paragraphs}
  57. channelId={channel}
  58. focus={focus}
  59. mode="read"
  60. />
  61. );
  62. let output = <></>;
  63. let articleLink = `/article/${type}/${id}?mode=read`;
  64. articleLink += channel ? `&channel=${channel}` : "";
  65. switch (style) {
  66. case "modal":
  67. output = (
  68. <>
  69. <Typography.Link
  70. onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
  71. if (event.ctrlKey || event.metaKey) {
  72. let link = `/article/${type}/${id}?mode=read`;
  73. link += channel ? `&channel=${channel}` : "";
  74. window.open(fullUrl(link), "_blank");
  75. } else {
  76. showModal();
  77. }
  78. }}
  79. >
  80. {aTitle}
  81. </Typography.Link>
  82. <Modal
  83. width={"80%"}
  84. style={{ maxWidth: 1000, top: 20 }}
  85. title={
  86. <div
  87. style={{
  88. display: "flex",
  89. justifyContent: "space-between",
  90. marginRight: 30,
  91. }}
  92. >
  93. <Text>{aTitle}</Text>
  94. <Space>
  95. <Link to={articleLink} target="_blank">
  96. {intl.formatMessage({
  97. id: "buttons.open.in.new.tab",
  98. })}
  99. </Link>
  100. {modalExtra}
  101. </Space>
  102. </div>
  103. }
  104. open={isModalOpen}
  105. onOk={handleOk}
  106. onCancel={handleCancel}
  107. footer={[]}
  108. >
  109. {article}
  110. </Modal>
  111. </>
  112. );
  113. break;
  114. case "card":
  115. output = <Card title={aTitle}>{article}</Card>;
  116. break;
  117. case "toggle":
  118. output = (
  119. <Collapse bordered={false}>
  120. <Collapse.Panel header={aTitle} key="parent2">
  121. {article}
  122. </Collapse.Panel>
  123. </Collapse>
  124. );
  125. break;
  126. case "link":
  127. let link = `/article/${type}/${id}?mode=read`;
  128. link += channel ? `&channel=${channel}` : "";
  129. output = (
  130. <Link to={link} target="_blank">
  131. {aTitle}
  132. </Link>
  133. );
  134. break;
  135. default:
  136. break;
  137. }
  138. return output;
  139. };
  140. interface IWidget {
  141. props: string;
  142. children?: React.ReactNode;
  143. }
  144. const ArticleWidget = ({ props, children }: IWidget) => {
  145. const prop = JSON.parse(atob(props)) as IWidgetChapterCtl;
  146. return <ArticleCtl {...prop} />;
  147. };
  148. export default ArticleWidget;