2
0

SentCellEditable.tsx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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. import Builder from "../Builder/Builder";
  17. const { Text } = Typography;
  18. export const sentSave = (
  19. data: ISentence,
  20. ok: (res: ISentence) => void,
  21. finish: () => void
  22. ) => {
  23. let url = `/v2/sentence/${data.book}_${data.para}_${data.wordStart}_${data.wordEnd}_${data.channel.id}`;
  24. url += "?mode=edit&html=true";
  25. console.log("save url", url);
  26. const body = {
  27. book: data.book,
  28. para: data.para,
  29. wordStart: data.wordStart,
  30. wordEnd: data.wordEnd,
  31. channel: data.channel.id,
  32. content: data.content,
  33. channels: data.translationChannels?.join(),
  34. };
  35. put<ISentenceRequest, ISentenceResponse>(url, body)
  36. .then((json) => {
  37. if (json.ok) {
  38. const newData: ISentence = {
  39. id: json.data.id,
  40. content: json.data.content,
  41. html: json.data.html,
  42. book: json.data.book,
  43. para: json.data.paragraph,
  44. wordStart: json.data.word_start,
  45. wordEnd: json.data.word_end,
  46. editor: json.data.editor,
  47. channel: json.data.channel,
  48. updateAt: json.data.updated_at,
  49. };
  50. ok(newData);
  51. } else {
  52. message.error(json.message);
  53. }
  54. })
  55. .finally(() => {
  56. finish();
  57. })
  58. .catch((e) => {
  59. console.error("catch", e);
  60. message.error(e.message);
  61. });
  62. };
  63. interface IWidget {
  64. data: ISentence;
  65. isPr?: boolean;
  66. isCreatePr?: boolean;
  67. onSave?: Function;
  68. onClose?: Function;
  69. onCreate?: Function;
  70. }
  71. const SentCellEditableWidget = ({
  72. data,
  73. onSave,
  74. onClose,
  75. onCreate,
  76. isPr = false,
  77. isCreatePr = false,
  78. }: IWidget) => {
  79. const intl = useIntl();
  80. const [value, setValue] = useState(data.content);
  81. const [saving, setSaving] = useState<boolean>(false);
  82. const [termList, setTermList] = useState<string[]>();
  83. const sentWords = useAppSelector(wordList);
  84. useEffect(() => {
  85. const sentId = `${data.book}-${data.para}-${data.wordStart}-${data.wordEnd}`;
  86. setTermList(sentWords.find((value) => value.sentId === sentId)?.words);
  87. }, [data.book, data.para, data.wordEnd, data.wordStart, sentWords]);
  88. const savePr = () => {
  89. setSaving(true);
  90. if (!value) {
  91. return;
  92. }
  93. if (isCreatePr) {
  94. post<ISentencePrRequest, ISentencePrResponse>(`/v2/sentpr`, {
  95. book: data.book,
  96. para: data.para,
  97. begin: data.wordStart,
  98. end: data.wordEnd,
  99. channel: data.channel.id,
  100. text: value,
  101. })
  102. .then((json) => {
  103. setSaving(false);
  104. if (json.ok) {
  105. message.success(intl.formatMessage({ id: "flashes.success" }));
  106. if (typeof onCreate !== "undefined") {
  107. onCreate();
  108. }
  109. } else {
  110. message.error(json.message);
  111. }
  112. })
  113. .catch((e) => {
  114. setSaving(false);
  115. console.error("catch", e);
  116. message.error(e.message);
  117. });
  118. } else {
  119. const url = `/v2/sentpr/${data.id}`;
  120. console.log("url", url);
  121. put<ISentencePrRequest, ISentencePrResponse>(url, {
  122. text: value,
  123. })
  124. .then((json) => {
  125. if (json.ok) {
  126. message.success(intl.formatMessage({ id: "flashes.success" }));
  127. if (typeof onSave !== "undefined") {
  128. onSave();
  129. }
  130. } else {
  131. message.error(json.message);
  132. }
  133. })
  134. .finally(() => {
  135. setSaving(false);
  136. })
  137. .catch((e) => {
  138. console.error("catch", e);
  139. message.error(e.message);
  140. });
  141. }
  142. };
  143. const save = () => {
  144. setSaving(true);
  145. let url = `/v2/sentence/${data.book}_${data.para}_${data.wordStart}_${data.wordEnd}_${data.channel.id}`;
  146. url += "?mode=edit&html=true";
  147. console.log("save url", url);
  148. const body = {
  149. book: data.book,
  150. para: data.para,
  151. wordStart: data.wordStart,
  152. wordEnd: data.wordEnd,
  153. channel: data.channel.id,
  154. content: value,
  155. channels: data.translationChannels?.join(),
  156. };
  157. put<ISentenceRequest, ISentenceResponse>(url, body)
  158. .then((json) => {
  159. if (json.ok) {
  160. message.success(intl.formatMessage({ id: "flashes.success" }));
  161. if (typeof onSave !== "undefined") {
  162. const newData: ISentence = {
  163. id: json.data.id,
  164. content: json.data.content,
  165. html: json.data.html,
  166. book: json.data.book,
  167. para: json.data.paragraph,
  168. wordStart: json.data.word_start,
  169. wordEnd: json.data.word_end,
  170. editor: json.data.editor,
  171. channel: json.data.channel,
  172. updateAt: json.data.updated_at,
  173. };
  174. onSave(newData);
  175. }
  176. } else {
  177. message.error(json.message);
  178. }
  179. })
  180. .finally(() => {
  181. setSaving(false);
  182. })
  183. .catch((e) => {
  184. console.error("catch", e);
  185. message.error(e.message);
  186. });
  187. };
  188. return (
  189. <Typography.Paragraph style={{ width: "100%" }}>
  190. <TermTextArea
  191. value={value ? value : ""}
  192. menuOptions={termList}
  193. onChange={(value: string) => {
  194. setValue(value);
  195. }}
  196. placeholder="请输入"
  197. onClose={() => {
  198. if (typeof onClose !== "undefined") {
  199. onClose();
  200. }
  201. }}
  202. onSave={(value: string) => {
  203. setValue(value);
  204. isPr ? savePr() : save();
  205. }}
  206. />
  207. <div style={{ display: "flex", justifyContent: "space-between" }}>
  208. <div>
  209. <span>
  210. <Text keyboard>esc</Text>=
  211. <Button
  212. size="small"
  213. type="link"
  214. onClick={(e) => {
  215. if (typeof onClose !== "undefined") {
  216. onClose();
  217. }
  218. }}
  219. >
  220. {intl.formatMessage({ id: "buttons.cancel" })}
  221. </Button>
  222. </span>
  223. <span>
  224. <Text keyboard>enter</Text>=
  225. <Button size="small" type="link">
  226. new line
  227. </Button>
  228. </span>
  229. <Text keyboard style={{ cursor: "pointer" }}>
  230. <Builder trigger={"<t>"} />
  231. </Text>
  232. </div>
  233. <div>
  234. <Text keyboard>Ctrl/⌘</Text>➕<Text keyboard>enter</Text>=
  235. <Button
  236. size="small"
  237. type="primary"
  238. icon={<SaveOutlined />}
  239. loading={saving}
  240. onClick={() => (isPr ? savePr() : save())}
  241. >
  242. {intl.formatMessage({ id: "buttons.save" })}
  243. </Button>
  244. </div>
  245. </div>
  246. </Typography.Paragraph>
  247. );
  248. };
  249. export default SentCellEditableWidget;