SentEdit.tsx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import { Card } from "antd";
  2. import { useEffect, useRef, useState } from "react";
  3. import { IStudio } from "../auth/StudioName";
  4. import type { IUser } from "../auth/User";
  5. import { IChannel } from "../channel/Channel";
  6. import { TContentType } from "../discussion/DiscussionCreate";
  7. import { ITocPathNode } from "../corpus/TocPath";
  8. import SentContent from "./SentEdit/SentContent";
  9. import SentTab from "./SentEdit/SentTab";
  10. import { IWbw } from "./Wbw/WbwWord";
  11. import { ArticleMode } from "../article/Article";
  12. import { TChannelType } from "../api/Channel";
  13. import { useAppSelector } from "../../hooks";
  14. import { currFocus } from "../../reducers/focus";
  15. export interface IResNumber {
  16. translation?: number;
  17. nissaya?: number;
  18. commentary?: number;
  19. origin?: number;
  20. sim?: number;
  21. }
  22. export interface ISuggestionCount {
  23. suggestion?: number;
  24. discussion?: number;
  25. }
  26. export interface ISentence {
  27. id?: string;
  28. content: string | null;
  29. contentType?: TContentType;
  30. html: string;
  31. book: number;
  32. para: number;
  33. wordStart: number;
  34. wordEnd: number;
  35. editor: IUser;
  36. acceptor?: IUser;
  37. prEditAt?: string;
  38. channel: IChannel;
  39. studio?: IStudio;
  40. updateAt: string;
  41. createdAt?: string;
  42. suggestionCount?: ISuggestionCount;
  43. openInEditMode?: boolean;
  44. translationChannels?: string[];
  45. }
  46. export interface ISentenceId {
  47. book: number;
  48. para: number;
  49. wordStart: number;
  50. wordEnd: number;
  51. }
  52. export interface IWidgetSentEditInner {
  53. id: string;
  54. book: number;
  55. para: number;
  56. wordStart: number;
  57. wordEnd: number;
  58. channels?: string[];
  59. origin?: ISentence[];
  60. translation?: ISentence[];
  61. path?: ITocPathNode[];
  62. layout?: "row" | "column";
  63. tranNum?: number;
  64. nissayaNum?: number;
  65. commNum?: number;
  66. originNum: number;
  67. simNum?: number;
  68. compact?: boolean;
  69. mode?: ArticleMode;
  70. wbwProgress?: boolean;
  71. }
  72. export const SentEditInner = ({
  73. id,
  74. book,
  75. para,
  76. wordStart,
  77. wordEnd,
  78. channels,
  79. origin,
  80. translation,
  81. path,
  82. layout = "column",
  83. tranNum,
  84. nissayaNum,
  85. commNum,
  86. originNum,
  87. simNum,
  88. compact = false,
  89. mode,
  90. wbwProgress = false,
  91. }: IWidgetSentEditInner) => {
  92. const [wbwData, setWbwData] = useState<IWbw[]>();
  93. const [magicDict, setMagicDict] = useState<string>();
  94. const [magicDictLoading, setMagicDictLoading] = useState(false);
  95. const [isCompact, setIsCompact] = useState(compact);
  96. const [articleMode, setArticleMode] = useState<ArticleMode | undefined>(mode);
  97. const [loadedRes, setLoadedRes] = useState<IResNumber>();
  98. const [isFocus, setIsFocus] = useState(false);
  99. const focus = useAppSelector(currFocus);
  100. const divRef = useRef<HTMLDivElement>(null);
  101. useEffect(() => {
  102. if (focus) {
  103. if (focus.focus?.type === "sentence") {
  104. if (focus.focus.id === id) {
  105. setIsFocus(true);
  106. divRef.current?.scrollIntoView({
  107. behavior: "smooth",
  108. block: "nearest",
  109. inline: "nearest",
  110. });
  111. } else {
  112. setIsFocus(false);
  113. }
  114. }
  115. } else {
  116. setIsFocus(false);
  117. }
  118. }, [focus, id]);
  119. useEffect(() => {
  120. const validRes = (value: ISentence, type: TChannelType) =>
  121. value.channel.type === type &&
  122. value.content &&
  123. value.content.trim().length > 0;
  124. if (translation) {
  125. const res = {
  126. translation: translation.filter((value) =>
  127. validRes(value, "translation")
  128. ).length,
  129. nissaya: translation.filter((value) => validRes(value, "nissaya"))
  130. .length,
  131. commentary: translation.filter((value) => validRes(value, "commentary"))
  132. .length,
  133. };
  134. setLoadedRes(res);
  135. }
  136. }, [translation]);
  137. useEffect(() => {
  138. const content = origin?.find(
  139. (value) => value.contentType === "json"
  140. )?.content;
  141. if (content) {
  142. setWbwData(JSON.parse(content));
  143. }
  144. }, []);
  145. const channelsId = translation?.map((item) => item.channel.id);
  146. return (
  147. <Card
  148. ref={divRef}
  149. bodyStyle={{ paddingBottom: 0, paddingLeft: 0, paddingRight: 0 }}
  150. style={{
  151. border: isFocus
  152. ? "2px solid rgb(0 0 200 / 50%)"
  153. : "1px solid rgb(128 128 128 / 10%)",
  154. marginTop: 4,
  155. borderRadius: 6,
  156. backgroundColor: "rgb(255 255 255 / 8%)",
  157. }}
  158. size="small"
  159. >
  160. <SentContent
  161. sid={id}
  162. book={book}
  163. para={para}
  164. wordStart={wordStart}
  165. wordEnd={wordEnd}
  166. origin={origin}
  167. translation={translation}
  168. layout={layout}
  169. magicDict={magicDict}
  170. compact={isCompact}
  171. mode={articleMode}
  172. wbwProgress={wbwProgress}
  173. onWbwChange={(data: IWbw[]) => {
  174. setWbwData(data);
  175. }}
  176. onMagicDictDone={() => {
  177. setMagicDictLoading(false);
  178. setMagicDict(undefined);
  179. }}
  180. />
  181. <SentTab
  182. id={id}
  183. book={book}
  184. para={para}
  185. wordStart={wordStart}
  186. wordEnd={wordEnd}
  187. channelsId={channelsId}
  188. path={path}
  189. tranNum={tranNum}
  190. nissayaNum={nissayaNum}
  191. commNum={commNum}
  192. originNum={originNum}
  193. simNum={simNum}
  194. loadedRes={loadedRes}
  195. wbwData={wbwData}
  196. magicDictLoading={magicDictLoading}
  197. compact={isCompact}
  198. mode={articleMode}
  199. onMagicDict={(type: string) => {
  200. setMagicDict(type);
  201. setMagicDictLoading(true);
  202. }}
  203. onCompact={(value: boolean) => setIsCompact(value)}
  204. onModeChange={(value: ArticleMode | undefined) => setArticleMode(value)}
  205. />
  206. </Card>
  207. );
  208. };
  209. interface IWidgetSentEdit {
  210. props: string;
  211. }
  212. const Widget = ({ props }: IWidgetSentEdit) => {
  213. const prop = JSON.parse(atob(props)) as IWidgetSentEditInner;
  214. //console.log("sent data", prop);
  215. return <SentEditInner {...prop} />;
  216. };
  217. export default Widget;