Kaynağa Gözat

Merge pull request #2022 from visuddhinanda/agile

textbook 不显示版本选择提示
visuddhinanda 2 yıl önce
ebeveyn
işleme
b171c584f7

+ 1 - 1
dashboard/src/components/article/AnthologyInfoEdit.tsx

@@ -133,7 +133,7 @@ const AnthologyInfoEditWidget = ({
 
 
       <ProForm.Group>
       <ProForm.Group>
         <LangSelect width="md" />
         <LangSelect width="md" />
-        <PublicitySelect width="md" />
+        <PublicitySelect width="md" disable={["public_no_list"]} />
       </ProForm.Group>
       </ProForm.Group>
       <ProForm.Group>
       <ProForm.Group>
         <ProFormSelect
         <ProFormSelect

+ 1 - 1
dashboard/src/components/article/ArticleEdit.tsx

@@ -189,7 +189,7 @@ const ArticleEditWidget = ({
         </ProForm.Group>
         </ProForm.Group>
         <ProForm.Group>
         <ProForm.Group>
           <LangSelect width="md" />
           <LangSelect width="md" />
-          <PublicitySelect width="md" />
+          <PublicitySelect width="md" disable={["public_no_list"]} />
         </ProForm.Group>
         </ProForm.Group>
         <ProForm.Group>
         <ProForm.Group>
           <ProFormTextArea
           <ProFormTextArea

+ 7 - 1
dashboard/src/components/channel/ChannelAlert.tsx

@@ -23,7 +23,13 @@ const ChannelAlertWidget = ({ channels, onChannelChange }: IWidget) => {
       closable
       closable
       action={
       action={
         <ChannelPicker
         <ChannelPicker
-          trigger={<Button type="primary">选择版本</Button>}
+          trigger={
+            <Button type="primary">
+              {intl.formatMessage({
+                id: "buttons.select.channel",
+              })}
+            </Button>
+          }
           defaultOwner="my"
           defaultOwner="my"
           onSelect={(channels: IChannel[]) => {
           onSelect={(channels: IChannel[]) => {
             if (typeof onChannelChange !== "undefined") {
             if (typeof onChannelChange !== "undefined") {

+ 6 - 2
dashboard/src/components/channel/ChannelPicker.tsx

@@ -1,9 +1,10 @@
 import React, { useEffect, useState } from "react";
 import React, { useEffect, useState } from "react";
-import { Button, Modal } from "antd";
+import { Modal } from "antd";
 
 
 import ChannelPickerTable from "./ChannelPickerTable";
 import ChannelPickerTable from "./ChannelPickerTable";
 import { IChannel } from "./Channel";
 import { IChannel } from "./Channel";
 import { ArticleType } from "../article/Article";
 import { ArticleType } from "../article/Article";
+import { useIntl } from "react-intl";
 
 
 interface IWidget {
 interface IWidget {
   trigger?: React.ReactNode;
   trigger?: React.ReactNode;
@@ -26,6 +27,7 @@ const ChannelPickerWidget = ({
   onSelect,
   onSelect,
 }: IWidget) => {
 }: IWidget) => {
   const [isModalOpen, setIsModalOpen] = useState(open);
   const [isModalOpen, setIsModalOpen] = useState(open);
+  const intl = useIntl();
 
 
   useEffect(() => {
   useEffect(() => {
     setIsModalOpen(open);
     setIsModalOpen(open);
@@ -54,7 +56,9 @@ const ChannelPickerWidget = ({
       <Modal
       <Modal
         width={"80%"}
         width={"80%"}
         style={{ maxWidth: 600 }}
         style={{ maxWidth: 600 }}
-        title="选择版本风格"
+        title={intl.formatMessage({
+          id: "buttons.select.channel",
+        })}
         footer={false}
         footer={false}
         open={isModalOpen}
         open={isModalOpen}
         onOk={handleOk}
         onOk={handleOk}

+ 5 - 1
dashboard/src/components/channel/ChannelTableModal.tsx

@@ -7,6 +7,7 @@ import { useAppSelector } from "../../hooks";
 import { currentUser as _currentUser } from "../../reducers/current-user";
 import { currentUser as _currentUser } from "../../reducers/current-user";
 import { IChannel } from "./Channel";
 import { IChannel } from "./Channel";
 import { TChannelType } from "../api/Channel";
 import { TChannelType } from "../api/Channel";
+import { useIntl } from "react-intl";
 
 
 interface IWidget {
 interface IWidget {
   trigger?: React.ReactNode;
   trigger?: React.ReactNode;
@@ -31,6 +32,7 @@ const ChannelTableModalWidget = ({
   onSelect,
   onSelect,
 }: IWidget) => {
 }: IWidget) => {
   const [isModalOpen, setIsModalOpen] = useState(open);
   const [isModalOpen, setIsModalOpen] = useState(open);
+  const intl = useIntl();
   const user = useAppSelector(_currentUser);
   const user = useAppSelector(_currentUser);
 
 
   useEffect(() => {
   useEffect(() => {
@@ -59,7 +61,9 @@ const ChannelTableModalWidget = ({
       <span onClick={showModal}>{trigger}</span>
       <span onClick={showModal}>{trigger}</span>
       <Modal
       <Modal
         width={"90%"}
         width={"90%"}
-        title="选择版本风格"
+        title={intl.formatMessage({
+          id: "buttons.select.channel",
+        })}
         footer={false}
         footer={false}
         open={isModalOpen}
         open={isModalOpen}
         onOk={handleOk}
         onOk={handleOk}

+ 4 - 1
dashboard/src/components/channel/Edit.tsx

@@ -88,7 +88,10 @@ const EditWidget = ({ studioName, channelId, onLoad }: IWidget) => {
           <LangSelect readonly={isSystem ? true : false} />
           <LangSelect readonly={isSystem ? true : false} />
         </ProForm.Group>
         </ProForm.Group>
         <ProForm.Group>
         <ProForm.Group>
-          <PublicitySelect readonly={isSystem ? true : false} />
+          <PublicitySelect
+            readonly={isSystem ? true : false}
+            disable={["public_no_list"]}
+          />
         </ProForm.Group>
         </ProForm.Group>
 
 
         <ProForm.Group>
         <ProForm.Group>

+ 1 - 0
dashboard/src/components/course/CourseInfoEdit.tsx

@@ -398,6 +398,7 @@ const CourseInfoEditWidget = ({
               }
               }
               return (
               return (
                 <ProFormSelect
                 <ProFormSelect
+                  hidden
                   tooltip="要求查看经验值,需要学生同意才会生效。"
                   tooltip="要求查看经验值,需要学生同意才会生效。"
                   options={option}
                   options={option}
                   width="md"
                   width="md"

+ 1 - 1
dashboard/src/components/course/LecturerList.tsx

@@ -52,7 +52,7 @@ const LecturerListWidget = () => {
         <List.Item>
         <List.Item>
           <Card
           <Card
             hoverable
             hoverable
-            style={{ width: "100%", height: 300 }}
+            style={{ width: "100%", height: 350 }}
             cover={
             cover={
               <Image
               <Image
                 alt="example"
                 alt="example"

+ 93 - 80
dashboard/src/components/course/SelectChannel.tsx

@@ -1,5 +1,5 @@
 import { ModalForm, ProForm, ProFormSelect } from "@ant-design/pro-components";
 import { ModalForm, ProForm, ProFormSelect } from "@ant-design/pro-components";
-import { Button, message } from "antd";
+import { Alert, Button, message } from "antd";
 import { GlobalOutlined } from "@ant-design/icons";
 import { GlobalOutlined } from "@ant-design/icons";
 
 
 import { useAppSelector } from "../../hooks";
 import { useAppSelector } from "../../hooks";
@@ -9,7 +9,8 @@ import { get, put } from "../../request";
 import { IApiResponseChannelList } from "../api/Channel";
 import { IApiResponseChannelList } from "../api/Channel";
 import { LockIcon } from "../../assets/icon";
 import { LockIcon } from "../../assets/icon";
 import { ICourseMemberData, ICourseMemberResponse } from "../api/Course";
 import { ICourseMemberData, ICourseMemberResponse } from "../api/Course";
-import { useNavigate, useParams } from "react-router-dom";
+import { useParams } from "react-router-dom";
+import { useIntl } from "react-intl";
 interface IWidget {
 interface IWidget {
   courseId?: string | null;
   courseId?: string | null;
   exerciseId?: string;
   exerciseId?: string;
@@ -27,91 +28,103 @@ const SelectChannelWidget = ({
   onOpenChange,
   onOpenChange,
 }: IWidget) => {
 }: IWidget) => {
   const user = useAppSelector(_currentUser);
   const user = useAppSelector(_currentUser);
+  const intl = useIntl();
   const { id } = useParams(); //url 参数
   const { id } = useParams(); //url 参数
-  const navigate = useNavigate();
 
 
   return (
   return (
-    <ModalForm<{
-      channel: string;
-    }>
-      title="选择作业的存放位置"
-      trigger={<Button>做练习</Button>}
-      autoFocusFirstInput
-      modalProps={{
-        destroyOnClose: true,
-        onCancel: () => console.log("run"),
-      }}
-      submitTimeout={2000}
-      onFinish={async (values) => {
-        console.log(values.channel);
-        console.log("id", id);
-
-        if (user && courseId) {
-          const url = `/v2/course-member_set-channel`;
-          const data = {
-            user_id: user.id,
-            course_id: courseId,
-            channel_id: values.channel,
-          };
-          console.debug("course select channel", url, data);
-          const json = await put<ICourseMemberData, ICourseMemberResponse>(
-            url,
-            data
-          );
-          if (json.ok) {
-            message.success("提交成功");
-            if (typeof onSelected !== "undefined") {
-              onSelected();
-            }
-          } else {
-            message.error(json.message);
+    <Alert
+      message={`请选择作业的存放位置`}
+      type="warning"
+      action={
+        <ModalForm<{
+          channel: string;
+        }>
+          title="请选择作业的存放位置"
+          trigger={
+            <Button type="primary">
+              {intl.formatMessage({
+                id: "buttons.select",
+              })}
+            </Button>
           }
           }
-        } else {
-          console.log("select channel error:", user, courseId);
-        }
+          autoFocusFirstInput
+          modalProps={{
+            destroyOnClose: true,
+            onCancel: () => console.log("run"),
+          }}
+          submitTimeout={2000}
+          onFinish={async (values) => {
+            console.log(values.channel);
+            console.log("id", id);
 
 
-        return true;
-      }}
-      onOpenChange={(visible: boolean) => {
-        if (typeof onOpenChange !== "undefined") {
-          onOpenChange(visible);
-        }
-      }}
-    >
-      <div>
-        您还没有选择版本。您将用一个版本保存自己的作业。这个版本里面的内容将会被老师,助理老师看到。
-      </div>
-      <ProForm.Group>
-        <ProFormSelect
-          rules={[
-            {
-              required: true,
-            },
-          ]}
-          request={async () => {
-            const channelData = await get<IApiResponseChannelList>(
-              `/v2/channel?view=studio&name=${user?.realName}`
-            );
-            const channel = channelData.data.rows.map((item) => {
-              const icon =
-                item.status === 30 ? <GlobalOutlined /> : <LockIcon />;
-              return {
-                value: item.uid,
-                label: (
-                  <>
-                    {icon} {item.name}
-                  </>
-                ),
+            if (user && courseId) {
+              const url = `/v2/course-member_set-channel`;
+              const data = {
+                user_id: user.id,
+                course_id: courseId,
+                channel_id: values.channel,
               };
               };
-            });
-            return channel;
+              console.debug("course select channel", url, data);
+              const json = await put<ICourseMemberData, ICourseMemberResponse>(
+                url,
+                data
+              );
+              if (json.ok) {
+                message.success("提交成功");
+                if (typeof onSelected !== "undefined") {
+                  onSelected();
+                }
+              } else {
+                message.error(json.message);
+              }
+            } else {
+              console.log("select channel error:", user, courseId);
+            }
+
+            return true;
+          }}
+          onOpenChange={(visible: boolean) => {
+            if (typeof onOpenChange !== "undefined") {
+              onOpenChange(visible);
+            }
           }}
           }}
-          width="md"
-          name="channel"
-          label="版本风格"
-        />
-      </ProForm.Group>
-    </ModalForm>
+        >
+          <div>
+            您还没有选择版本。您将用一个版本保存自己的作业。这个版本里面的内容将会被老师,助理老师看到。
+          </div>
+          <ProForm.Group>
+            <ProFormSelect
+              rules={[
+                {
+                  required: true,
+                },
+              ]}
+              request={async () => {
+                const channelData = await get<IApiResponseChannelList>(
+                  `/v2/channel?view=studio&name=${user?.realName}`
+                );
+                const channel = channelData.data.rows.map((item) => {
+                  const icon =
+                    item.status === 30 ? <GlobalOutlined /> : <LockIcon />;
+                  return {
+                    value: item.uid,
+                    label: (
+                      <>
+                        {icon} {item.name}
+                      </>
+                    ),
+                  };
+                });
+                return channel;
+              }}
+              width="md"
+              name="channel"
+              label="版本风格"
+            />
+          </ProForm.Group>
+        </ModalForm>
+      }
+    />
   );
   );
 };
 };
 
 

+ 15 - 1
dashboard/src/components/studio/PublicitySelect.tsx

@@ -1,10 +1,14 @@
 import { ProFormSelect } from "@ant-design/pro-components";
 import { ProFormSelect } from "@ant-design/pro-components";
 import { useIntl } from "react-intl";
 import { useIntl } from "react-intl";
+
+export type TPublicity = "disable" | "private" | "public_no_list" | "public";
+
 interface IWidget {
 interface IWidget {
   width?: number | "md" | "sm" | "xl" | "xs" | "lg";
   width?: number | "md" | "sm" | "xl" | "xs" | "lg";
+  disable?: TPublicity[];
   readonly?: boolean;
   readonly?: boolean;
 }
 }
-const PublicitySelectWidget = ({ width, readonly }: IWidget) => {
+const PublicitySelectWidget = ({ width, disable = [], readonly }: IWidget) => {
   const intl = useIntl();
   const intl = useIntl();
 
 
   const options = [
   const options = [
@@ -13,18 +17,28 @@ const PublicitySelectWidget = ({ width, readonly }: IWidget) => {
       label: intl.formatMessage({
       label: intl.formatMessage({
         id: "forms.fields.publicity.disable.label",
         id: "forms.fields.publicity.disable.label",
       }),
       }),
+      disable: disable.includes("disable"),
     },
     },
     {
     {
       value: 10,
       value: 10,
       label: intl.formatMessage({
       label: intl.formatMessage({
         id: "forms.fields.publicity.private.label",
         id: "forms.fields.publicity.private.label",
       }),
       }),
+      disable: disable.includes("private"),
+    },
+    {
+      value: 20,
+      label: intl.formatMessage({
+        id: "forms.fields.publicity.public_no_list.label",
+      }),
+      disable: disable.includes("public_no_list"),
     },
     },
     {
     {
       value: 30,
       value: 30,
       label: intl.formatMessage({
       label: intl.formatMessage({
         id: "forms.fields.publicity.public.label",
         id: "forms.fields.publicity.public.label",
       }),
       }),
+      disable: disable.includes("public"),
     },
     },
   ];
   ];
   return (
   return (

+ 1 - 0
dashboard/src/locales/en-US/buttons.ts

@@ -89,6 +89,7 @@ const items = {
   "buttons.reset.wbw": "reset wbw",
   "buttons.reset.wbw": "reset wbw",
   "buttons.reset.password": "reset password",
   "buttons.reset.password": "reset password",
   "buttons.forgot.password": "forgot password",
   "buttons.forgot.password": "forgot password",
+  "buttons.select.channel": "Select Channel",
 };
 };
 
 
 export default items;
 export default items;

+ 1 - 0
dashboard/src/locales/en-US/forms.ts

@@ -21,6 +21,7 @@ const items = {
   "forms.fields.publicity.label": "publicity",
   "forms.fields.publicity.label": "publicity",
   "forms.fields.publicity.disable.label": "disable",
   "forms.fields.publicity.disable.label": "disable",
   "forms.fields.publicity.private.label": "private",
   "forms.fields.publicity.private.label": "private",
+  "forms.fields.publicity.public_no_list.label": "public no list",
   "forms.fields.publicity.public.label": "public",
   "forms.fields.publicity.public.label": "public",
   "forms.fields.teacher.label": "teacher",
   "forms.fields.teacher.label": "teacher",
   "forms.fields.studentsassistant.label": "students / assistant",
   "forms.fields.studentsassistant.label": "students / assistant",

+ 1 - 0
dashboard/src/locales/zh-Hans/buttons.ts

@@ -89,6 +89,7 @@ const items = {
   "buttons.reset.wbw": "重置逐词解析",
   "buttons.reset.wbw": "重置逐词解析",
   "buttons.reset.password": "重置密码",
   "buttons.reset.password": "重置密码",
   "buttons.forgot.password": "忘记密码",
   "buttons.forgot.password": "忘记密码",
+  "buttons.select.channel": "选择版本风格",
 };
 };
 
 
 export default items;
 export default items;

+ 1 - 0
dashboard/src/locales/zh-Hans/forms.ts

@@ -21,6 +21,7 @@ const items = {
   "forms.fields.publicity.label": "公开性",
   "forms.fields.publicity.label": "公开性",
   "forms.fields.publicity.disable.label": "禁用",
   "forms.fields.publicity.disable.label": "禁用",
   "forms.fields.publicity.private.label": "私有",
   "forms.fields.publicity.private.label": "私有",
+  "forms.fields.publicity.public_no_list.label": "公开不列出",
   "forms.fields.publicity.public.label": "公开",
   "forms.fields.publicity.public.label": "公开",
   "forms.fields.teacher.label": "主讲人",
   "forms.fields.teacher.label": "主讲人",
   "forms.fields.studentsassistant.label": "学生与助教",
   "forms.fields.studentsassistant.label": "学生与助教",

+ 20 - 15
dashboard/src/pages/library/article/show.tsx

@@ -332,21 +332,26 @@ const Widget = () => {
             style={{ marginLeft: "auto", marginRight: "auto", width: 1100 }}
             style={{ marginLeft: "auto", marginRight: "auto", width: 1100 }}
           >
           >
             <LoginAlertModal mode={currMode} />
             <LoginAlertModal mode={currMode} />
-            <ChannelAlert
-              channels={searchParams.get("channel")}
-              onChannelChange={(channels: IChannel[]) => {
-                let output: any = {
-                  channel: channels.map((item) => item.id).join("_"),
-                };
-                searchParams.forEach((value, key) => {
-                  console.log(value, key);
-                  if (key !== "channel") {
-                    output[key] = value;
-                  }
-                });
-                setSearchParams(output);
-              }}
-            />
+            {type !== "textbook" ? (
+              <ChannelAlert
+                channels={searchParams.get("channel")}
+                onChannelChange={(channels: IChannel[]) => {
+                  let output: any = {
+                    channel: channels.map((item) => item.id).join("_"),
+                  };
+                  searchParams.forEach((value, key) => {
+                    console.log(value, key);
+                    if (key !== "channel") {
+                      output[key] = value;
+                    }
+                  });
+                  setSearchParams(output);
+                }}
+              />
+            ) : (
+              <></>
+            )}
+
             <Article
             <Article
               active={true}
               active={true}
               type={type as ArticleType}
               type={type as ArticleType}

+ 6 - 18
dashboard/src/pages/library/course/list.tsx

@@ -23,26 +23,14 @@ const Widget = () => {
         <Row>
         <Row>
           <Col flex="auto"></Col>
           <Col flex="auto"></Col>
           <Col flex="960px">
           <Col flex="960px">
-            <Row>
-              <Title level={4}>最新</Title>
-            </Row>
-            <Row>
-              <LecturerList />
-            </Row>
+            <Title level={4}>最新</Title>
+            <LecturerList />
             <Divider />
             <Divider />
-            <Row>
-              <Title level={4}>开放报名</Title>
-            </Row>
-            <Row>
-              <CourseList type="open" />
-            </Row>
+            <Title level={4}>开放报名</Title>
+            <CourseList type="open" />
             <Divider />
             <Divider />
-            <Row>
-              <Title level={4}>历史课程</Title>
-            </Row>
-            <Row>
-              <CourseList type="close" />
-            </Row>
+            <Title level={4}>历史课程</Title>
+            <CourseList type="close" />
           </Col>
           </Col>
           <Col flex="auto"></Col>
           <Col flex="auto"></Col>
         </Row>
         </Row>

+ 1 - 0
dashboard/src/pages/studio/course/list.tsx

@@ -243,6 +243,7 @@ const Widget = () => {
                   mainButton = (
                   mainButton = (
                     <Link
                     <Link
                       to={`/studio/${studioname}/course/${row.id}/edit`}
                       to={`/studio/${studioname}/course/${row.id}/edit`}
+                      target="_blank"
                       key={index}
                       key={index}
                     >
                     >
                       {intl.formatMessage({
                       {intl.formatMessage({