SentCellEditable.tsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import { useEffect, useState } from "react";
  2. import { useIntl } from "react-intl";
  3. import { Button, message, Typography } from "antd";
  4. import { SaveOutlined } from "@ant-design/icons";
  5. import { post, put } from "../../../request";
  6. import {
  7. ISentencePrRequest,
  8. ISentencePrResponse,
  9. ISentenceRequest,
  10. ISentenceResponse,
  11. } from "../../api/Corpus";
  12. import { ISentence } from "../SentEdit";
  13. import TermTextArea from "../../general/TermTextArea";
  14. import { useAppSelector } from "../../../hooks";
  15. import { wordList } from "../../../reducers/sent-word";
  16. const { Text } = Typography;
  17. interface IWidget {
  18. data: ISentence;
  19. isPr?: boolean;
  20. onSave?: Function;
  21. onClose?: Function;
  22. onCreate?: Function;
  23. }
  24. const SentCellEditableWidget = ({
  25. data,
  26. onSave,
  27. onClose,
  28. onCreate,
  29. isPr = false,
  30. }: IWidget) => {
  31. const intl = useIntl();
  32. const [value, setValue] = useState(data.content);
  33. const [saving, setSaving] = useState<boolean>(false);
  34. const [termList, setTermList] = useState<string[]>();
  35. const sentWords = useAppSelector(wordList);
  36. useEffect(() => {
  37. const sentId = `${data.book}-${data.para}-${data.wordStart}-${data.wordEnd}`;
  38. setTermList(sentWords.find((value) => value.sentId === sentId)?.words);
  39. }, [data.book, data.para, data.wordEnd, data.wordStart, sentWords]);
  40. const savePr = () => {
  41. setSaving(true);
  42. post<ISentencePrRequest, ISentencePrResponse>(`/v2/sentpr`, {
  43. book: data.book,
  44. para: data.para,
  45. begin: data.wordStart,
  46. end: data.wordEnd,
  47. channel: data.channel.id,
  48. text: value,
  49. })
  50. .then((json) => {
  51. setSaving(false);
  52. if (json.ok) {
  53. message.success(intl.formatMessage({ id: "flashes.success" }));
  54. if (typeof onCreate !== "undefined") {
  55. onCreate();
  56. }
  57. } else {
  58. message.error(json.message);
  59. }
  60. })
  61. .catch((e) => {
  62. setSaving(false);
  63. console.error("catch", e);
  64. message.error(e.message);
  65. });
  66. };
  67. const save = () => {
  68. setSaving(true);
  69. let url = `/v2/sentence/${data.book}_${data.para}_${data.wordStart}_${data.wordEnd}_${data.channel.id}`;
  70. url += "?mode=edit&html=true";
  71. console.log("save url", url);
  72. const body = {
  73. book: data.book,
  74. para: data.para,
  75. wordStart: data.wordStart,
  76. wordEnd: data.wordEnd,
  77. channel: data.channel.id,
  78. content: value,
  79. channels: data.translationChannels?.join(),
  80. };
  81. put<ISentenceRequest, ISentenceResponse>(url, body)
  82. .then((json) => {
  83. setSaving(false);
  84. if (json.ok) {
  85. message.success(intl.formatMessage({ id: "flashes.success" }));
  86. if (typeof onSave !== "undefined") {
  87. const newData: ISentence = {
  88. id: json.data.id,
  89. content: json.data.content,
  90. html: json.data.html,
  91. book: json.data.book,
  92. para: json.data.paragraph,
  93. wordStart: json.data.word_start,
  94. wordEnd: json.data.word_end,
  95. editor: json.data.editor,
  96. channel: json.data.channel,
  97. updateAt: json.data.updated_at,
  98. };
  99. onSave(newData);
  100. }
  101. } else {
  102. message.error(json.message);
  103. }
  104. })
  105. .catch((e) => {
  106. setSaving(false);
  107. console.error("catch", e);
  108. message.error(e.message);
  109. });
  110. };
  111. return (
  112. <Typography.Paragraph>
  113. <TermTextArea
  114. value={value}
  115. menuOptions={termList}
  116. onChange={(value: string) => {
  117. setValue(value);
  118. }}
  119. placeholder="请输入"
  120. onClose={() => {
  121. if (typeof onClose !== "undefined") {
  122. onClose();
  123. }
  124. }}
  125. onSave={(value: string) => {
  126. setValue(value);
  127. isPr ? savePr() : save();
  128. }}
  129. />
  130. <div style={{ display: "flex", justifyContent: "space-between" }}>
  131. <div>
  132. <span>
  133. <Text keyboard>esc</Text>=
  134. <Button
  135. size="small"
  136. type="link"
  137. onClick={(e) => {
  138. if (typeof onClose !== "undefined") {
  139. onClose();
  140. }
  141. }}
  142. >
  143. {intl.formatMessage({ id: "buttons.cancel" })}
  144. </Button>
  145. </span>
  146. <span>
  147. <Text keyboard>enter</Text>=
  148. <Button size="small" type="link">
  149. new line
  150. </Button>
  151. </span>
  152. </div>
  153. <div>
  154. <Text keyboard>Ctrl/⌘</Text>➕<Text keyboard>enter</Text>=
  155. <Button
  156. size="small"
  157. type="primary"
  158. icon={<SaveOutlined />}
  159. loading={saving}
  160. onClick={() => (isPr ? savePr() : save())}
  161. >
  162. {intl.formatMessage({ id: "buttons.save" })}
  163. </Button>
  164. </div>
  165. </div>
  166. </Typography.Paragraph>
  167. );
  168. };
  169. export default SentCellEditableWidget;