import { useEffect, useState } from "react"; import { useIntl } from "react-intl"; import type { Key } from "antd/es/table/interface"; import { Badge, Button, Card, Dropdown, Input, Select, Skeleton, Space, Tag, Tooltip, Tree, } from "antd"; import { GlobalOutlined, EditOutlined, ReloadOutlined, MoreOutlined, CopyOutlined, InfoCircleOutlined, } from "@ant-design/icons"; import { get, post } from "../../request"; import type { IApiResponseChannelList, ISentInChapterListResponse, } from "../../api/Channel"; import type { IItem, IProgressRequest } from "./ChannelPickerTable"; import { LockFillIcon, LockIcon } from "../../assets/icon"; import StudioName from "../auth/Studio"; import ProgressSvg from "./ProgressSvg"; import type { IChannel } from "./Channel"; import CopyToModal from "./CopyToModal"; import type { ArticleType } from "../article/Article"; import { ChannelInfoModal } from "./ChannelInfo"; import TokenModal from "../article/TokenModal"; import NissayaAlignerModal from "../corpus/NissayaAlignerModal"; const { Search } = Input; export const getSentIdInArticle = () => { const sentList: string[] = []; const sentElement = document.querySelectorAll(".pcd_sent"); for (let index = 0; index < sentElement.length; index++) { const element = sentElement[index]; const id = element.id.split("_")[1]; sentList.push(id); } return sentList; }; interface IToken { channelId?: string; articleId?: string; type?: ArticleType; } interface ChannelTreeNode { key: string; title: string | React.ReactNode; channel: IItem; icon?: React.ReactNode; children?: ChannelTreeNode[]; } interface IWidget { type?: ArticleType | "editable"; articleId?: string; selectedKeys?: string[]; style?: React.CSSProperties; onSelect?: Function; } const ChannelMy = ({ type, articleId, selectedKeys = [], style, onSelect, }: IWidget) => { const intl = useIntl(); const [selectedRowKeys, setSelectedRowKeys] = useState(selectedKeys); const [treeData, setTreeData] = useState(); const [dirty, setDirty] = useState(false); const [channels, setChannels] = useState([]); const [owner, setOwner] = useState("all"); const [search, setSearch] = useState(); const [loading, setLoading] = useState(true); const [copyChannel, setCopyChannel] = useState(); const [nissayaOpen, setNissayaOpen] = useState(false); const [copyOpen, setCopyOpen] = useState(false); const [infoOpen, setInfoOpen] = useState(false); const [statistic, setStatistic] = useState(); const [sentenceCount, setSentenceCount] = useState(0); const [sentencesId, setSentencesId] = useState(); const [token, SetToken] = useState(); const [tokenOpen, setTokenOpen] = useState(false); console.debug("ChannelMy render", type, articleId); //TODO remove useEffect useEffect(() => { load(); }, [type, articleId]); useEffect(() => { if (selectedRowKeys.join() !== selectedKeys.join()) { setSelectedRowKeys(selectedKeys); } }, [selectedKeys]); useEffect(() => { sortChannels(channels); }, [channels, selectedRowKeys, owner]); interface IChannelFilter { key?: string; owner?: string; selectedRowKeys?: React.Key[]; } const sortChannels = (channelList: IItem[], filter?: IChannelFilter) => { const mOwner = filter?.owner ?? owner; if (mOwner === "my") { //我自己的 const myChannel = channelList.filter((value) => value.role === "owner"); const data = myChannel.map((item, _index) => { return { key: item.uid, title: item.title, channel: item }; }); setTreeData(data); } else { //当前被选择的 const selectedChannel: IItem[] = []; const mSelectedRowKeys = filter?.selectedRowKeys ?? selectedRowKeys; mSelectedRowKeys.forEach((channelId) => { const channel = channelList.find((value) => value.uid === channelId); if (channel) { selectedChannel.push(channel); } }); let show = mSelectedRowKeys; //有进度的 const progressing = channelList.filter( (value) => value.progress > 0 && !show.includes(value.uid) ); show = [...show, ...progressing.map((item) => item.uid)]; //我自己的 const myChannel = channelList.filter( (value) => value.role === "owner" && !show.includes(value.uid) ); show = [...show, ...myChannel.map((item) => item.uid)]; //其他的 const others = channelList.filter( (value) => !show.includes(value.uid) && value.role !== "member" ); let channelData = [ ...selectedChannel, ...progressing, ...myChannel, ...others, ]; const key = filter?.key ?? search; if (key) { channelData = channelData.filter((value) => value.title.includes(key)); } const data = channelData.map((item, _index) => { return { key: item.uid, title: item.title, channel: item }; }); setTreeData(data); } }; const load = () => { let sentList: string[] = []; if (type === "chapter") { const id = articleId?.split("-"); if (id?.length === 2) { const url = `/v2/sentences-in-chapter?book=${id[0]}¶=${id[1]}`; console.info("ChannelMy url api request", url); get(url) .then((res) => { console.debug( "ChannelMy ISentInChapterListResponse api response", res ); if (res && res.ok) { sentList = res.data.rows.map((item) => { return `${item.book}-${item.paragraph}-${item.word_begin}-${item.word_end}`; }); setSentencesId(sentList); loadChannel(sentList); } else { console.error("res", res); } }) .catch((reason: any) => { console.error(reason); }); } } else { sentList = getSentIdInArticle(); setSentencesId(sentList); loadChannel(sentList); } }; function loadChannel(sentences: string[]) { setSentenceCount(sentences.length); console.debug("sentences", sentences); const currOwner = "all"; const url = `/v2/channel-progress`; console.info("api request", url); setLoading(true); post(url, { sentence: sentences, owner: currOwner, }) .then((res) => { console.debug("progress data api response", res); const items: IItem[] = res.data.rows .filter((value) => value.name.substring(0, 4) !== "_sys") .map((item, id) => { const date = new Date(item.created_at); let all: number = 0; let finished: number = 0; item.final?.forEach((value) => { all += value[0]; finished += value[1] ? value[0] : 0; }); const progress = finished / all; return { id: id, uid: item.uid, title: item.name, summary: item.summary, studio: item.studio, shareType: "my", role: item.role, type: item.type, publicity: item.status, createdAt: date.getTime(), final: item.final, progress: progress, content_created_at: item.content_created_at, content_updated_at: item.content_updated_at, }; }); setChannels(items); }) .finally(() => { setLoading(false); }); } return (
setTokenOpen(false)} /> { console.debug(value); setSearch(value); sortChannels(channels, { key: value }); }} style={{ width: 120 }} />