Explorar o código

Merge pull request #1921 from visuddhinanda/agile

支持多个句子发布更新
visuddhinanda %!s(int64=2) %!d(string=hai) anos
pai
achega
b8a5b9321f

+ 2 - 6
dashboard/src/components/api/Corpus.ts

@@ -131,7 +131,7 @@ export interface ISentenceDiffData {
   word_start: number;
   word_end: number;
   channel_uid: string;
-  content: string;
+  content: string | null;
   editor_uid: string;
   updated_at: string;
 }
@@ -190,11 +190,7 @@ export interface ISentenceNewRequest {
   copy?: boolean;
   fork_from?: string;
 }
-export interface ISentenceNewMultiResponse {
-  ok: boolean;
-  message: string;
-  data: number;
-}
+
 export interface IPaliToc {
   book: number;
   paragraph: number;

+ 15 - 7
dashboard/src/components/channel/ChannelSentDiff.tsx

@@ -7,19 +7,22 @@ import {
   ISentenceDiffData,
   ISentenceDiffRequest,
   ISentenceDiffResponse,
-  ISentenceNewMultiResponse,
+  ISentenceListResponse,
   ISentenceNewRequest,
 } from "../api/Corpus";
 import { IChannel } from "./Channel";
+import { ISentence, toISentence } from "../template/SentEdit";
+import store from "../../store";
+import { accept } from "../../reducers/accept-pr";
 
 const { Text } = Typography;
 
 interface IDataType {
   key: React.Key;
   sentId: string;
-  pali?: string;
-  srcContent?: string;
-  destContent?: string;
+  pali?: string | null;
+  srcContent?: string | null;
+  destContent?: string | null;
 }
 
 interface IWidget {
@@ -84,7 +87,7 @@ const ChannelSentDiffWidget = ({
             }
             if (
               typeof destContent === "undefined" ||
-              destContent.content.trim().length === 0
+              destContent.content?.trim().length === 0
             ) {
               emptyRows.push(item);
             }
@@ -197,9 +200,14 @@ const ChannelSentDiffWidget = ({
               fork_from: srcChannel.id,
             };
             console.debug("fork post", url, postData);
-            post<ISentenceNewRequest, ISentenceNewMultiResponse>(url, postData)
+            post<ISentenceNewRequest, ISentenceListResponse>(url, postData)
               .then((json) => {
                 if (json.ok) {
+                  //发布数据
+                  const newData: ISentence[] = json.data.rows.map((item) =>
+                    toISentence(item)
+                  );
+                  store.dispatch(accept(newData));
                   if (typeof onSubmit !== "undefined") {
                     onSubmit();
                   }
@@ -237,7 +245,7 @@ const ChannelSentDiffWidget = ({
               setSelectedRowKeys(selectedRowKeys);
             },
             getCheckboxProps: (record: IDataType) => ({
-              name: record.pali,
+              name: record.pali ? record.pali : undefined,
             }),
           }}
           columns={[

+ 18 - 0
dashboard/src/components/template/SentEdit.tsx

@@ -13,6 +13,7 @@ import { ArticleMode } from "../article/Article";
 import { TChannelType } from "../api/Channel";
 import { useAppSelector } from "../../hooks";
 import { currFocus } from "../../reducers/focus";
+import { ISentenceData } from "../api/Corpus";
 
 export interface IResNumber {
   translation?: number;
@@ -53,6 +54,23 @@ export interface ISentenceId {
   wordStart: number;
   wordEnd: number;
 }
+
+export const toISentence = (apiData: ISentenceData): ISentence => ({
+  id: apiData.id,
+  content: apiData.content,
+  html: apiData.html,
+  book: apiData.book,
+  para: apiData.paragraph,
+  wordStart: apiData.word_start,
+  wordEnd: apiData.word_end,
+  editor: apiData.editor,
+  channel: apiData.channel,
+  updateAt: apiData.updated_at,
+  acceptor: apiData.acceptor,
+  prEditAt: apiData.pr_edit_at,
+  forkAt: apiData.fork_at,
+  suggestionCount: apiData.suggestionCount,
+});
 export interface IWidgetSentEditInner {
   id: string;
   book: number;

+ 1 - 5
dashboard/src/components/template/SentEdit/EditInfo.tsx

@@ -76,12 +76,8 @@ interface IMergeButton {
 }
 const MergeButton = ({ data }: IMergeButton) => {
   if (data.forkAt) {
-    const fork = moment.utc(data.forkAt);
-    const fork_iso8610 = moment(data.forkAt, moment.ISO_8601);
+    const fork = moment(data.forkAt);
     const updated = moment(data.updateAt);
-    const diff = updated.diff(fork_iso8610, "seconds");
-    const diff1 = updated.diff(fork, "seconds");
-    console.debug("edit info time diff fork_iso8610 vs utc", diff, diff1);
     if (fork.isSame(updated)) {
       return <Fork sentId={data.id} highlight />;
     } else {

+ 4 - 17
dashboard/src/components/template/SentEdit/PrAcceptButton.tsx

@@ -5,7 +5,7 @@ import { CheckOutlined } from "@ant-design/icons";
 
 import { put } from "../../../request";
 import { ISentenceRequest, ISentenceResponse } from "../../api/Corpus";
-import { ISentence } from "../SentEdit";
+import { ISentence, toISentence } from "../SentEdit";
 import store from "../../../store";
 import { accept } from "../../../reducers/accept-pr";
 
@@ -41,22 +41,9 @@ const PrAcceptButtonWidget = ({ data, onAccept }: IWidget) => {
         if (json.ok) {
           message.success(intl.formatMessage({ id: "flashes.success" }));
 
-          const newData: ISentence = {
-            id: json.data.id,
-            content: json.data.content,
-            html: json.data.html,
-            book: json.data.book,
-            para: json.data.paragraph,
-            wordStart: json.data.word_start,
-            wordEnd: json.data.word_end,
-            editor: json.data.editor,
-            channel: json.data.channel,
-            updateAt: json.data.updated_at,
-            acceptor: json.data.acceptor,
-            prEditAt: json.data.pr_edit_at,
-            suggestionCount: json.data.suggestionCount,
-          };
-          store.dispatch(accept(newData));
+          const newData: ISentence = toISentence(json.data);
+
+          store.dispatch(accept([newData]));
           if (typeof onAccept !== "undefined") {
             onAccept(newData);
           }

+ 22 - 10
dashboard/src/components/template/SentEdit/SentCell.tsx

@@ -10,7 +10,7 @@ import MdView from "../MdView";
 import EditInfo, { Details } from "./EditInfo";
 import SuggestionToolbar from "./SuggestionToolbar";
 import { useAppSelector } from "../../../hooks";
-import { sentence } from "../../../reducers/accept-pr";
+import { dirtySent, remove, sentence } from "../../../reducers/accept-pr";
 import { IWbw } from "../Wbw/WbwWord";
 import { my_to_roman } from "../../code/my";
 import SentWbwEdit, { sentSave } from "./SentWbwEdit";
@@ -25,6 +25,7 @@ import { delete_ } from "../../../request";
 import "./style.css";
 import StudioName from "../../auth/StudioName";
 import CopyToModal from "../../channel/CopyToModal";
+import store from "../../../store";
 
 interface IWidget {
   initValue?: ISentence;
@@ -56,6 +57,8 @@ const SentCellWidget = ({
   const [bgColor, setBgColor] = useState<string>();
   const endings = useAppSelector(getEnding);
   const acceptPr = useAppSelector(sentence);
+  const removed = useAppSelector(dirtySent);
+
   const [prOpen, setPrOpen] = useState(false);
   const discussionMessage = useAppSelector(message);
   const anchorInfo = useAppSelector(anchor);
@@ -95,17 +98,24 @@ const SentCellWidget = ({
   }, [value]);
 
   useEffect(() => {
+    if (removed?.includes(sid)) {
+      return;
+    }
     if (typeof acceptPr !== "undefined" && !isPr && sentData) {
-      if (
-        acceptPr.book === sentData.book &&
-        acceptPr.para === sentData.para &&
-        acceptPr.wordStart === sentData.wordStart &&
-        acceptPr.wordEnd === sentData.wordEnd &&
-        acceptPr.channel.id === sentData.channel.id
-      )
-        setSentData(acceptPr);
+      const found = acceptPr.findIndex(
+        (value) =>
+          value.book === sentData.book &&
+          value.para === sentData.para &&
+          value.wordStart === sentData.wordStart &&
+          value.wordEnd === sentData.wordEnd &&
+          value.channel.id === sentData.channel.id
+      );
+      if (found !== -1) {
+        setSentData(acceptPr[found]);
+        store.dispatch(remove(sid));
+      }
     }
-  }, [acceptPr, sentData, isPr]);
+  }, [acceptPr, sentData, isPr, removed, sid]);
 
   const deletePr = (id: string) => {
     delete_<IDeleteResponse>(`/v2/sentpr/${id}`)
@@ -288,6 +298,7 @@ const SentCellWidget = ({
                       setIsEditMode(false);
                     }}
                     onSave={(data: ISentence) => {
+                      console.debug("sent cell onSave", data);
                       setSentData(data);
                     }}
                   />
@@ -299,6 +310,7 @@ const SentCellWidget = ({
                       setIsEditMode(false);
                     }}
                     onSave={(data: ISentence) => {
+                      console.debug("sent cell onSave", data);
                       setIsEditMode(false);
                       setSentData(data);
                       if (typeof onChange !== "undefined") {

+ 18 - 7
dashboard/src/reducers/accept-pr.ts

@@ -7,24 +7,35 @@ import { ISentence } from "../components/template/SentEdit";
 import type { RootState } from "../store";
 
 interface IState {
-  sentence?: ISentence;
+  sentences?: ISentence[];
+  dirty: string[];
 }
 
-const initialState: IState = {};
+const initialState: IState = { dirty: [] };
 
 export const slice = createSlice({
   name: "accept-pr",
   initialState,
   reducers: {
-    accept: (state, action: PayloadAction<ISentence>) => {
-      state.sentence = action.payload;
+    accept: (state, action: PayloadAction<ISentence[]>) => {
+      state.sentences = action.payload;
+      state.dirty = [];
+    },
+
+    remove: (state, action: PayloadAction<string>) => {
+      if (!state.dirty.includes(action.payload)) {
+        state.dirty.push(action.payload);
+      }
     },
   },
 });
 
-export const { accept } = slice.actions;
+export const { accept, remove } = slice.actions;
+
+export const sentence = (state: RootState): ISentence[] | undefined =>
+  state.acceptPr.sentences;
 
-export const sentence = (state: RootState): ISentence | undefined =>
-  state.acceptPr.sentence;
+export const dirtySent = (state: RootState): string[] | undefined =>
+  state.acceptPr.dirty;
 
 export default slice.reducer;