Compare commits
5 Commits
0412bccffb
...
ba2b5b411c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba2b5b411c | ||
|
|
d603736a16 | ||
|
|
999573fa0c | ||
|
|
470cae3b13 | ||
|
|
ec4850cbb8 |
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
|
@ -12,6 +12,7 @@
|
||||||
"Karim",
|
"Karim",
|
||||||
"katex",
|
"katex",
|
||||||
"Latext",
|
"Latext",
|
||||||
|
"mathml",
|
||||||
"Popconfirm",
|
"Popconfirm",
|
||||||
"queryqlent",
|
"queryqlent",
|
||||||
"registraion",
|
"registraion",
|
||||||
|
|
|
||||||
12
index.html
12
index.html
|
|
@ -4,20 +4,14 @@
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/App/Logo2.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="/App/Logo.svg" />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/App/Logo2.png" />
|
<link rel="icon" type="image/png" sizes="32x32" href="/App/Logo.svg" />
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/App/Logo2.png" />
|
<link rel="icon" type="image/png" sizes="16x16" href="/App/Logo.svg" />
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
<link
|
|
||||||
href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="social networking platform with automated content moderation and context-based authentication system"
|
content="social networking platform with automated content moderation and context-based authentication system"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
<script type="module" src="/src/index.tsx"></script>
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
|
||||||
<title>NERD DASHBOARD</title>
|
<title>NERD DASHBOARD</title>
|
||||||
|
|
|
||||||
4175
package-lock.json
generated
4175
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -16,10 +16,16 @@
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"formik": "^2.4.6",
|
"formik": "^2.4.6",
|
||||||
"i18next": "^23.11.5",
|
"i18next": "^23.11.5",
|
||||||
|
"install": "^0.13.0",
|
||||||
"katex": "^0.16.11",
|
"katex": "^0.16.11",
|
||||||
"lottie-react": "^2.4.0",
|
"lottie-react": "^2.4.0",
|
||||||
|
"mathjax": "^3.2.2",
|
||||||
"mathjax-full": "^3.2.2",
|
"mathjax-full": "^3.2.2",
|
||||||
|
"mathjs": "^13.1.1",
|
||||||
"mathml-to-latex": "^1.4.1",
|
"mathml-to-latex": "^1.4.1",
|
||||||
|
"mathml2latex": "^1.1.3",
|
||||||
|
"mml2tex": "^0.0.2",
|
||||||
|
"npm": "^10.8.3",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|
@ -29,6 +35,9 @@
|
||||||
"react-katex": "^3.0.1",
|
"react-katex": "^3.0.1",
|
||||||
"react-latex": "^2.0.0",
|
"react-latex": "^2.0.0",
|
||||||
"react-latex-next": "^3.0.0",
|
"react-latex-next": "^3.0.0",
|
||||||
|
"react-mathjax": "^1.0.1",
|
||||||
|
"react-mathjax-preview": "^2.2.6",
|
||||||
|
"react-mathjax2": "^0.0.2",
|
||||||
"react-query": "^3.39.3",
|
"react-query": "^3.39.3",
|
||||||
"react-router-dom": "^6.23.1",
|
"react-router-dom": "^6.23.1",
|
||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
38
public/App/Logo.svg
Normal file
38
public/App/Logo.svg
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
<svg width="157" height="119" viewBox="0 0 157 119" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M153.338 33.2514C154.044 33.5665 154.674 33.9951 155.216 34.5497C155.758 35.1043 156.174 35.7345 156.489 36.453C156.804 37.1715 156.956 37.9404 156.956 38.7723V68.9229C156.956 69.7548 156.804 70.5237 156.489 71.2422C156.174 71.9607 155.746 72.5909 155.216 73.1455C154.687 73.7001 154.056 74.1287 153.338 74.4438C152.62 74.7589 151.851 74.9102 151.019 74.9102H122.645C121.813 74.9102 121.045 74.7589 120.326 74.4438C119.608 74.1287 118.99 73.7001 118.448 73.1455C117.906 72.5909 117.49 71.9607 117.175 71.2422C116.86 70.5237 116.708 69.7548 116.708 68.9229V61.2214H143.317V46.5368H135.767C133.057 46.4612 130.687 45.9822 128.633 45.0747C126.578 44.1671 124.826 43.0579 123.376 41.747C122.028 40.5369 120.919 39.2513 120.074 37.8899C119.229 36.5286 118.612 35.3186 118.221 34.2219C117.83 33.1253 117.692 32.2556 117.78 31.6128C117.868 30.9699 118.158 30.7682 118.637 31.0077C119.923 31.5623 121.435 31.9657 123.162 32.2052C124.889 32.4447 126.691 32.6085 128.557 32.6716C130.422 32.7346 132.25 32.7724 134.053 32.7472C135.855 32.722 137.443 32.7472 138.792 32.7724" fill="white"/>
|
||||||
|
<path d="M134.67 20.8736C134.872 24.8819 131.822 28.3104 127.864 28.5121C123.855 28.7137 120.402 25.5121 120.25 21.4534C120.112 17.5837 123.212 14.2182 127.095 14.0166C131.09 13.8149 134.469 16.8778 134.67 20.8736Z" fill="#FDBB2E"/>
|
||||||
|
<path d="M109.393 69.4019C109.608 73.5741 106.431 77.1413 102.31 77.3556C98.1373 77.5698 94.5323 74.2296 94.3811 70.007C94.2298 65.9734 97.4566 62.4693 101.503 62.2676C105.662 62.066 109.179 65.2424 109.393 69.4145V69.4019Z" fill="white"/>
|
||||||
|
<path d="M109.406 15.9451C109.394 20.1299 106.028 23.5206 101.894 23.4954C97.709 23.4827 94.3057 19.9534 94.3814 15.7182C94.457 11.6847 97.8729 8.35701 101.919 8.38222C106.079 8.40743 109.419 11.7729 109.406 15.9451Z" fill="white"/>
|
||||||
|
<path d="M103.293 18.6173L102.953 17.3946H100.848L100.444 18.6173H98.9192L101.062 12.4409H102.738L104.869 18.6173H103.293ZM101.894 13.9787L101.201 16.2224H102.524L101.881 13.9787H101.894Z" fill="#0290D2"/>
|
||||||
|
<path d="M109.406 33.9069C109.394 38.0917 106.028 41.4824 101.894 41.4572C97.709 41.4446 94.3057 37.9153 94.3814 33.6801C94.457 29.6465 97.8729 26.3189 101.919 26.3441C106.079 26.3693 109.419 29.7348 109.406 33.9069Z" fill="white"/>
|
||||||
|
<path d="M99.3604 37.411V30.5162H102.827C104.289 30.5162 104.932 31.2599 104.932 32.3187C104.932 32.9615 104.541 33.4783 104.037 33.68C104.629 33.8817 105.133 34.3858 105.133 35.369C105.133 36.6043 104.339 37.411 102.524 37.411H99.3604ZM100.911 31.8397V33.201H102.587C103.091 33.201 103.369 32.9867 103.369 32.5203C103.369 32.054 103.104 31.8397 102.549 31.8397H100.923H100.911ZM100.911 34.3858V36.1001H102.638C103.23 36.1001 103.558 35.7472 103.558 35.2052C103.558 34.6631 103.23 34.3858 102.638 34.3858H100.898H100.911Z" fill="#0290D2"/>
|
||||||
|
<path d="M109.381 51.8057C109.406 55.9905 106.053 59.4064 101.932 59.419C97.7469 59.4316 94.3185 55.9401 94.3563 51.7049C94.3941 47.6714 97.7848 44.3185 101.831 44.3059C105.99 44.3059 109.356 47.6336 109.381 51.8057Z" fill="#FDBB2E"/>
|
||||||
|
<path d="M105.12 52.9779C104.818 54.6166 103.671 55.7006 101.969 55.7006C100.066 55.7006 98.6038 54.4149 98.6038 51.9317C98.6038 49.4486 99.902 48.0117 101.982 48.0117C103.81 48.0117 104.969 49.1587 105.108 50.6208H103.431C103.242 49.8772 102.675 49.4738 101.994 49.4738C100.822 49.4738 100.305 50.3688 100.305 51.8435C100.305 53.3183 100.81 54.2384 101.919 54.2384C102.763 54.2384 103.23 53.7846 103.431 52.9779H105.108H105.12Z" fill="#0290D2"/>
|
||||||
|
<path d="M99.5366 73.1456V66.4902H102.146C103.974 66.4902 105.272 67.7255 105.272 69.7423C105.272 71.759 104.1 73.1456 102.36 73.1456H99.5492H99.5366ZM102.045 71.8725C103.217 71.8725 103.684 71.1792 103.684 69.7423C103.684 68.3053 103.242 67.7633 101.932 67.7633H101.049V71.8725H102.058H102.045Z" fill="#0290D2"/>
|
||||||
|
<path d="M84.1211 39.1252C83.5665 38.5706 82.9362 38.1421 82.2178 37.8269C81.5119 37.5118 80.7304 37.3606 79.8985 37.3606H56.6805L67.7475 29.054L91.5957 11.2813C90.9025 10.8527 90.1588 11.1174 89.1252 11.9241C86.2009 14.2182 83.1757 16.3988 79.6086 19.0584C79.2935 16.6383 79.0918 16.4997 79.2683 14.4577C79.4447 12.4409 78.2977 12.0502 76.8986 11.483C75.2851 10.8275 75.1969 10.5628 73.1423 9.56703C73.2305 8.98721 73.2053 8.83595 73.2558 8.79814C75.4364 7.14691 77.6422 5.5335 79.7851 3.84446C82.9237 1.38653 83.9698 1.28569 83.264 0L62.882 15.1762L57.1973 19.2223C57.1973 19.2223 57.1216 19.2601 57.0712 19.2853C56.8948 19.3988 56.7813 19.4744 56.7057 19.5248C56.8065 19.4492 56.8443 19.4366 56.1763 19.8525C55.7855 20.1046 54.941 20.7475 53.8948 21.5542L46.1933 27.0246C41.164 30.5918 38.7943 42.6924 42.374 47.7091C42.8782 48.6166 43.5337 49.3099 44.3278 49.8141C45.1219 50.3183 46.0294 50.6586 47.0378 50.8351C48.0462 51.0115 49.0546 51.0746 50.063 51.0494H72.2348V61.9273H33.0339V62.1794C33.0339 61.3475 32.8826 60.5786 32.5675 59.8601C32.2524 59.1416 31.8239 58.5114 31.2945 57.9568C30.7525 57.4022 30.1348 56.9736 29.4163 56.6585C28.7105 56.3434 27.929 56.1921 27.0971 56.1921H19.3325V61.9399C19.4081 63.4651 19.4081 64.8894 19.3325 66.2129C19.2569 67.5364 19.156 68.7591 19.0174 69.9061C18.8787 71.154 18.614 72.2758 18.2359 73.259C17.8578 74.2422 17.3788 75.1371 16.799 75.9186C16.2318 76.7001 15.5889 77.406 14.8704 78.0488C14.1646 78.6916 13.4209 79.2841 12.652 79.8513C11.7192 80.5067 10.7487 81.1496 9.76548 81.7546C8.78231 82.3596 7.79915 83.0025 6.82859 83.6831C5.85802 84.3638 4.92524 85.1075 4.0429 85.9268C3.16057 86.7461 2.37908 87.6915 1.72363 88.7629C1.16902 89.6704 0.753072 90.4771 0.475767 91.2082C0.198461 91.9393 0.0472101 92.5569 0.0093958 93.0611C-0.0284185 93.5653 0.0472132 93.9056 0.24889 94.0821C0.437961 94.2585 0.740478 94.2081 1.15644 93.9308C2.54296 93.0233 3.99249 92.2544 5.50506 91.6115C7.01763 90.9687 8.55542 90.4015 10.1184 89.8973C11.6814 89.3931 13.2444 88.9141 14.8074 88.4603C16.3704 88.0066 17.8956 87.4898 19.3956 86.8974C20.6812 86.4058 21.9165 85.8512 23.1139 85.2083C24.3114 84.5655 25.4332 83.7966 26.4668 82.9142C27.5004 82.0319 28.4458 80.9983 29.2777 79.8135C30.1096 78.6286 30.8281 77.2421 31.4079 75.6539H79.8733C80.7052 75.6539 81.4741 75.5026 82.1925 75.1875C82.8984 74.8724 83.5413 74.4438 84.0959 73.8892C84.6505 73.3346 85.079 72.7044 85.3942 71.9859C85.7093 71.2674 85.8605 70.4985 85.8605 69.6666V43.4235C85.8605 42.5916 85.7093 41.8101 85.3942 41.079C85.079 40.3479 84.6505 39.7051 84.0959 39.1504L84.1211 39.1252Z" fill="white"/>
|
||||||
|
<path d="M85.4824 3.27722C84.4866 4.44947 82.5329 5.68474 81.3228 6.6427C80.0623 7.53764 78.3229 9.05021 76.9111 9.68045C77.9069 8.52081 79.8606 7.27294 81.0707 6.31497C82.3312 5.42003 84.0706 3.90746 85.4824 3.27722Z" fill="#FDBB2E"/>
|
||||||
|
<path d="M87.4614 5.59656C86.6168 6.64275 84.9026 7.71416 83.8438 8.54608C82.7346 9.32757 81.2346 10.6637 79.9741 11.1679C80.8186 10.1217 82.5329 9.05027 83.5917 8.21835C84.7009 7.43686 86.2009 6.10075 87.4614 5.59656Z" fill="#FDBB2E"/>
|
||||||
|
<path d="M88.5327 8.76031C87.726 9.7813 86.0622 10.8149 85.0412 11.6216C83.9698 12.3779 82.5203 13.6762 81.2976 14.1552C82.1043 13.1342 83.7682 12.1006 84.7892 11.2939C85.8606 10.5502 87.3101 9.2393 88.5327 8.76031Z" fill="#FDBB2E"/>
|
||||||
|
<path d="M59.7836 35.0245L51.1941 23.5049L49.9512 24.4317L58.5407 35.9512L59.7836 35.0245Z" fill="url(#paint0_linear_19_2009)"/>
|
||||||
|
<path d="M61.5795 33.7296L52.99 22.21L51.7471 23.1368L60.3366 34.6564L61.5795 33.7296Z" fill="url(#paint1_linear_19_2009)"/>
|
||||||
|
<path d="M24.141 109.118V113.353H11.0698V110.366L18.4814 102.488H11.1959V98.2525H23.9393V101.24L16.5025 109.118H24.141Z" fill="white"/>
|
||||||
|
<path d="M41.649 98.2399V113.353H38.2709V110.328C37.1491 112.408 35.2205 113.706 32.7626 113.706C28.6156 113.706 25.4771 110.303 25.4771 105.79C25.4771 101.278 28.6156 97.8743 32.7626 97.8743C35.2205 97.8743 37.1491 99.1726 38.2709 101.252V98.2273H41.649V98.2399ZM38.2709 105.803C38.2709 103.761 36.2793 102.223 33.6197 102.223C30.9601 102.223 28.9938 103.761 28.9938 105.803C28.9938 107.845 30.9475 109.383 33.6197 109.383C36.2919 109.383 38.2709 107.845 38.2709 105.803Z" fill="white"/>
|
||||||
|
<path d="M50.649 107.492L48.4557 109.093V113.366H45.0776V92.0383H48.4557V103.446H49.1112L54.2035 98.2651H59.8631L53.3464 105.135L60.0395 113.378H55.6531L50.649 107.517V107.492Z" fill="white"/>
|
||||||
|
<path d="M75.6819 107.076H62.9763C63.5939 108.702 65.346 109.748 67.7409 109.748C69.5182 109.748 71.0938 109.244 71.7744 108.588H75.5054C74.3836 111.639 71.3585 113.719 67.6527 113.719C62.9763 113.719 59.4722 110.315 59.4722 105.803C59.4722 101.29 62.9637 97.8869 67.6148 97.8869C72.266 97.8869 75.7576 101.265 75.7576 105.891C75.7576 106.282 75.7323 106.723 75.6693 107.076H75.6819ZM63.0015 104.492H72.3038C71.7114 102.866 69.8711 101.857 67.6275 101.857C65.3838 101.857 63.6317 102.891 63.0015 104.492Z" fill="white"/>
|
||||||
|
<path d="M87.1774 98.0003V103.332C83.5977 103.332 81.6691 104.643 81.6691 107V113.34H78.291V98.2272H81.6691V101.983C82.8539 99.5003 84.7825 97.9877 87.1774 97.9877V98.0003Z" fill="white"/>
|
||||||
|
<path d="M111.29 98.2399V113.353H107.912V110.328C106.79 112.408 104.862 113.706 102.404 113.706C98.2568 113.706 95.1182 110.303 95.1182 105.79C95.1182 101.278 98.2568 97.8743 102.404 97.8743C104.862 97.8743 106.79 99.1726 107.912 101.252V98.2273H111.29V98.2399ZM107.912 105.803C107.912 103.761 105.92 102.223 103.261 102.223C100.601 102.223 98.6349 103.761 98.6349 105.803C98.6349 107.845 100.589 109.383 103.261 109.383C105.933 109.383 107.912 107.845 107.912 105.803Z" fill="white"/>
|
||||||
|
<path d="M130.903 105.803C130.903 110.303 127.79 113.719 123.618 113.719C121.16 113.719 119.206 112.382 118.11 110.315V119H114.731V98.2651H118.11V101.315C119.206 99.2357 121.16 97.9122 123.618 97.9122C127.803 97.9122 130.903 101.315 130.903 105.828V105.803ZM127.399 105.803C127.399 103.761 125.42 102.223 122.748 102.223C120.076 102.223 118.097 103.761 118.097 105.803C118.097 107.845 120.088 109.383 122.748 109.383C125.408 109.383 127.399 107.845 127.399 105.803Z" fill="white"/>
|
||||||
|
<path d="M149.684 105.803C149.684 110.303 146.571 113.719 142.399 113.719C139.941 113.719 137.987 112.382 136.891 110.315V119H133.512V98.2651H136.891V101.315C137.987 99.2357 139.941 97.9122 142.399 97.9122C146.584 97.9122 149.684 101.315 149.684 105.828V105.803ZM146.18 105.803C146.18 103.761 144.201 102.223 141.529 102.223C138.857 102.223 136.878 103.761 136.878 105.803C136.878 107.845 138.87 109.383 141.529 109.383C144.189 109.383 146.18 107.845 146.18 105.803Z" fill="white"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_19_2009" x1="49.9496" y1="29.7083" x2="59.7813" y2="29.7083" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.02" stop-color="#FFD140"/>
|
||||||
|
<stop offset="0.94" stop-color="#F9A61C"/>
|
||||||
|
<stop offset="1" stop-color="#F7941D"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_19_2009" x1="51.7318" y1="28.416" x2="61.5761" y2="28.416" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.02" stop-color="#FFD140"/>
|
||||||
|
<stop offset="0.94" stop-color="#F9A61C"/>
|
||||||
|
<stop offset="1" stop-color="#F7941D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
BIN
public/App/whiteLogo.png
Normal file
BIN
public/App/whiteLogo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
|
|
@ -8,17 +8,17 @@
|
||||||
"theme_color": "#000000",
|
"theme_color": "#000000",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/App/Logo.png",
|
"src": "/App/Logo.svg",
|
||||||
"sizes": "81x113",
|
"sizes": "81x113",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/App/Logo.png",
|
"src": "/App/Logo.svg",
|
||||||
"sizes": "81x113",
|
"sizes": "81x113",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/App/Logo.png",
|
"src": "/App/Logo.svg",
|
||||||
"sizes": "81x113",
|
"sizes": "81x113",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "maskable"
|
"purpose": "maskable"
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,22 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import 'katex/dist/katex.min.css';
|
|
||||||
import { BlockMath } from 'react-katex';
|
import { BlockMath } from 'react-katex';
|
||||||
import { convertMathMLToLaTeX } from '../../utils/convertMathMLToLaTeX';
|
import 'katex/dist/katex.min.css';
|
||||||
|
|
||||||
|
const LatexPreview = ({ latex }: { latex: string }) => {
|
||||||
|
console.log(latex);
|
||||||
|
|
||||||
|
const sanitizedLatex = latex.replace(/\\_/g, '_');
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
|
||||||
const LatexPreview = ({Latex}:{Latex:string}) => {
|
<BlockMath>
|
||||||
|
{sanitizedLatex}
|
||||||
|
</BlockMath>
|
||||||
|
|
||||||
return(
|
|
||||||
<BlockMath math={Latex} />
|
</div>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default LatexPreview;
|
export default LatexPreview;
|
||||||
|
|
@ -15,16 +15,13 @@ const AddLaTexModal = ({name,setLatex,Latex,setIsModalOpen,isModalOpen,setCurren
|
||||||
setCurrentValue:(value:string)=> void
|
setCurrentValue:(value:string)=> void
|
||||||
|
|
||||||
}) => {
|
}) => {
|
||||||
const {values,setFieldValue} = useFormikContext<any>()
|
const {values,setFieldValue,getFieldProps} = useFormikContext<any>()
|
||||||
|
|
||||||
|
|
||||||
|
const currentValue = getFieldProps(name).value
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
console.log(1);
|
const oldValue = currentValue ?? "";
|
||||||
|
|
||||||
const oldValue = values?.[name];
|
|
||||||
const newLatex = convertMathMLToLaTeX(Latex);
|
const newLatex = convertMathMLToLaTeX(Latex);
|
||||||
console.log(newLatex,'Latex');
|
console.log(oldValue);
|
||||||
console.log(newLatex);
|
|
||||||
|
|
||||||
if(newLatex){
|
if(newLatex){
|
||||||
setFieldValue(name, oldValue + " $$ " +newLatex +" $$ ");
|
setFieldValue(name, oldValue + " $$ " +newLatex +" $$ ");
|
||||||
|
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
import TextArea from 'antd/es/input/TextArea'
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
import React, { Suspense, useState } from 'react'
|
|
||||||
import { parseTextAndLatex } from '../../utils/parseTextAndLatex';
|
|
||||||
import LatexPreview from '../../Components/CustomFields/MathComponent';
|
|
||||||
import { Checkbox } from 'antd';
|
|
||||||
import { CheckboxProps } from 'antd/lib';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { FaPlus } from 'react-icons/fa';
|
|
||||||
import { useObjectToEdit } from '../../zustand/ObjectToEditState';
|
|
||||||
import { TextAreaProps } from 'antd/lib/input';
|
|
||||||
import SpinContainer from '../Layout/SpinContainer';
|
|
||||||
const AddLazyModal = React.lazy(()=> import("./AddLaTexModal"));
|
|
||||||
const EditLazyModal = React.lazy(()=> import("./EditLaTexModal"));
|
|
||||||
interface ILaTeXInput extends TextAreaProps {
|
|
||||||
name:string,label:string
|
|
||||||
}
|
|
||||||
const LaTeXInput = ({name,label,...props}:ILaTeXInput) => {
|
|
||||||
|
|
||||||
|
|
||||||
const {values,setFieldValue,getFieldProps} = useFormikContext<any>()
|
|
||||||
const { ShowLatexOption } = useObjectToEdit();
|
|
||||||
const [showPreview, setShowPreview] = useState(false) ;
|
|
||||||
const value = getFieldProps(name)?.value
|
|
||||||
|
|
||||||
const Preview = parseTextAndLatex(value ?? "") ;
|
|
||||||
|
|
||||||
const onPreviewChange: CheckboxProps['onChange'] = (e) => {
|
|
||||||
const value = e.target.checked
|
|
||||||
setShowPreview(value)
|
|
||||||
};
|
|
||||||
const [t] = useTranslation()
|
|
||||||
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
||||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
|
||||||
|
|
||||||
const [Latex, setLatex] = useState<string>("")
|
|
||||||
|
|
||||||
|
|
||||||
const showModal = () => {
|
|
||||||
setIsModalOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const handelEditModal = (item:any)=>{
|
|
||||||
console.log(item);
|
|
||||||
|
|
||||||
setLatex(item)
|
|
||||||
setIsEditModalOpen(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const [curCentValue, setCurrentValue] = useState(value)
|
|
||||||
const handleChangeInput = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
|
||||||
setFieldValue(name, e.target.value);
|
|
||||||
setCurrentValue(e.target.value)
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className='LaTeXInput'>
|
|
||||||
|
|
||||||
<label htmlFor={name} className="text">
|
|
||||||
{t(`${label ? label : name}`)}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div className='LaTeXInputArea'>
|
|
||||||
<TextArea
|
|
||||||
size="large"
|
|
||||||
showCount
|
|
||||||
maxLength={1000}
|
|
||||||
autoSize={{ minRows: 6, maxRows: 10 }}
|
|
||||||
style={{height:"400px"}}
|
|
||||||
onChange={handleChangeInput}
|
|
||||||
value={curCentValue}
|
|
||||||
{...props}
|
|
||||||
|
|
||||||
/>
|
|
||||||
{ShowLatexOption &&
|
|
||||||
<div className='LaTeXInputOptions'>
|
|
||||||
|
|
||||||
<Checkbox onChange={onPreviewChange}>{t("header.show_preview")}</Checkbox>
|
|
||||||
<button type='button' className='addMML' onClick={showModal}> <FaPlus/> {t("MML")} </button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
}
|
|
||||||
{showPreview &&
|
|
||||||
<div className='showPreviewInput'>
|
|
||||||
{Preview?.map((item:any,index:number)=>{
|
|
||||||
if(item?.isLatex){
|
|
||||||
return <div key={index} onClick={()=>handelEditModal(item)} className='LatexPreview'> <LatexPreview Latex={item?.text} /> </div>
|
|
||||||
}
|
|
||||||
return <div key={index}>
|
|
||||||
{item?.text}
|
|
||||||
</div>
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<Suspense fallback={<SpinContainer/>}>
|
|
||||||
<AddLazyModal name={name} Latex={Latex} isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} setLatex={setLatex} />
|
|
||||||
|
|
||||||
<EditLazyModal name={name} Latex={Latex} isModalOpen={isEditModalOpen} setIsModalOpen={setIsEditModalOpen} setLatex={setLatex} />
|
|
||||||
</Suspense>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LaTeXInput
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import TextArea from 'antd/es/input/TextArea';
|
import TextArea from 'antd/es/input/TextArea';
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
import React, { Suspense, useEffect, useState } from 'react';
|
import React, { Suspense, useEffect, useState } from 'react';
|
||||||
import { parseTextAndLatex } from '../../utils/parseTextAndLatex';
|
import { parseTextAndLatex } from '../../utils/parseTextAndLatex';
|
||||||
import LatexPreview from '../CustomFields/MathComponent';
|
import LatexPreview from '../CustomFields/MathComponent';
|
||||||
|
|
@ -49,15 +48,24 @@ const LaTeXInputMemo: React.FC<any> = React.memo(({ field ,form, label, ...prop
|
||||||
setCurrentValue(e.target.value)
|
setCurrentValue(e.target.value)
|
||||||
};
|
};
|
||||||
const onBlur = ()=>{
|
const onBlur = ()=>{
|
||||||
|
if (curCentValue !== value) {
|
||||||
setFieldValue(name, curCentValue);
|
setFieldValue(name, curCentValue);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(Success){
|
if(Success){
|
||||||
setCurrentValue(null)
|
setCurrentValue(null)
|
||||||
}
|
}
|
||||||
}, [Success])
|
}, [Success])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(value){
|
||||||
|
setCurrentValue(value)
|
||||||
|
}
|
||||||
|
}, [value])
|
||||||
|
|
||||||
|
|
||||||
const isError = !!touched?.[name] && !!errors?.[name];
|
const isError = !!touched?.[name] && !!errors?.[name];
|
||||||
const errorMessage = isError ? errors?.[name] as string ?? "" : "" ;
|
const errorMessage = isError ? errors?.[name] as string ?? "" : "" ;
|
||||||
return (
|
return (
|
||||||
|
|
@ -92,10 +100,12 @@ const LaTeXInputMemo: React.FC<any> = React.memo(({ field ,form, label, ...prop
|
||||||
<div className='showPreviewInput'>
|
<div className='showPreviewInput'>
|
||||||
{Preview?.map((item: any, index: number) => {
|
{Preview?.map((item: any, index: number) => {
|
||||||
if (item?.isLatex) {
|
if (item?.isLatex) {
|
||||||
|
console.log(item?.text);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index} onClick={() => handleEditModal(item)} className='LatexPreview'>
|
<span dir='ltr' key={index} onClick={() => handleEditModal(item)} className='LatexPreview'>
|
||||||
<LatexPreview Latex={item?.text} />
|
<LatexPreview latex={item?.text} />
|
||||||
</div>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <div key={index}>{item?.text}</div>;
|
return <div key={index}>{item?.text}</div>;
|
||||||
|
|
@ -104,9 +114,10 @@ const LaTeXInputMemo: React.FC<any> = React.memo(({ field ,form, label, ...prop
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Suspense fallback={<SpinContainer />}>
|
||||||
<AddLazyModal name={name} Latex={Latex} isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} setLatex={setLatex} setCurrentValue={setCurrentValue} />
|
<AddLazyModal name={name} Latex={Latex} isModalOpen={isModalOpen} setIsModalOpen={setIsModalOpen} setLatex={setLatex} setCurrentValue={setCurrentValue} />
|
||||||
<EditLazyModal name={name} Latex={Latex} isModalOpen={isEditModalOpen} setIsModalOpen={setIsEditModalOpen} setLatex={setLatex} />
|
<EditLazyModal name={name} Latex={Latex} isModalOpen={isEditModalOpen} setIsModalOpen={setIsEditModalOpen} setLatex={setLatex} />
|
||||||
<Suspense fallback={<SpinContainer />}>
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
42
src/Hooks/useUnsavedChangesWarning.tsx
Normal file
42
src/Hooks/useUnsavedChangesWarning.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const useUnsavedChangesWarning = (unsavedChanges: boolean) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
|
if (unsavedChanges) {
|
||||||
|
// Prevent default action and stop the event
|
||||||
|
event.preventDefault();
|
||||||
|
// Optionally set returnValue to an empty string
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNavigation = (event: MouseEvent) => {
|
||||||
|
if (unsavedChanges) {
|
||||||
|
console.log(t("Access denied: You have unsaved changes!"));
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
// Intercept link clicks (example for <a> elements)
|
||||||
|
document.querySelectorAll('a').forEach(link => {
|
||||||
|
link.addEventListener('click', handleNavigation);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||||||
|
|
||||||
|
// Clean up event listeners
|
||||||
|
document.querySelectorAll('a').forEach(link => {
|
||||||
|
link.removeEventListener('click', handleNavigation);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [unsavedChanges, t]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useUnsavedChangesWarning;
|
||||||
|
|
@ -34,7 +34,7 @@ const SideBar = ({
|
||||||
return (
|
return (
|
||||||
<div className={isOpen ? "side_bar" : "side_bar side_bar_closed"}>
|
<div className={isOpen ? "side_bar" : "side_bar side_bar_closed"}>
|
||||||
<div className="side_bar_header">
|
<div className="side_bar_header">
|
||||||
<img src={isOpen ? "/App/Logo.png" : "/App/Logo2.png"} alt="" />
|
<img src={isOpen ? "/App/Logo.svg" : "/App/Logo.svg"} alt="" />
|
||||||
<HiMenuAlt3 onClick={toggleSidebar} />
|
<HiMenuAlt3 onClick={toggleSidebar} />
|
||||||
</div>
|
</div>
|
||||||
{/* <Divider /> */}
|
{/* <Divider /> */}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ const Form = () => {
|
||||||
<Row className="w-100">
|
<Row className="w-100">
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField placeholder="name" label="name" name="name" />
|
<ValidationField placeholder="name" label="name" name="name" />
|
||||||
<ValidationField placeholder="created_at" label="created_at" name="created_at" />
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
29
src/Pages/Admin/Roles/Permissions/FormTable.tsx
Normal file
29
src/Pages/Admin/Roles/Permissions/FormTable.tsx
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import React from 'react'
|
||||||
|
import DataTable from '../../../../Layout/Dashboard/Table/DataTable'
|
||||||
|
import { useColumns } from './useTableColumns'
|
||||||
|
import { useFormikContext } from 'formik'
|
||||||
|
|
||||||
|
const FormTable = ({response}:{response:any}) => {
|
||||||
|
const {values} = useFormikContext<any>()
|
||||||
|
console.log(response);
|
||||||
|
const data = response?.data?.data?.abilities ;
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
response={response}
|
||||||
|
useColumns={useColumns}
|
||||||
|
dataSource={data}
|
||||||
|
pagination={false}
|
||||||
|
loading={false}
|
||||||
|
rowKey={"name"}
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormTable
|
||||||
|
|
@ -4,8 +4,6 @@ import { Spin } from "antd";
|
||||||
import useSetPageTitle from "../../../../Hooks/useSetPageTitle";
|
import useSetPageTitle from "../../../../Hooks/useSetPageTitle";
|
||||||
import PageHeader from "../../../../Layout/Dashboard/PageHeader";
|
import PageHeader from "../../../../Layout/Dashboard/PageHeader";
|
||||||
import FilterLayout from "../../../../Layout/Dashboard/FilterLayout";
|
import FilterLayout from "../../../../Layout/Dashboard/FilterLayout";
|
||||||
import FormikForm from "../../../../Layout/Dashboard/FormikForm";
|
|
||||||
import { getInitialValues } from "./Model/formUtil";
|
|
||||||
const Table = lazy(() => import("./Table"));
|
const Table = lazy(() => import("./Table"));
|
||||||
|
|
||||||
const TableHeader = () => {
|
const TableHeader = () => {
|
||||||
|
|
@ -29,12 +27,8 @@ const TableHeader = () => {
|
||||||
filterTitle="page_header.permissions"
|
filterTitle="page_header.permissions"
|
||||||
haveFilter={false}
|
haveFilter={false}
|
||||||
/>
|
/>
|
||||||
<FormikForm
|
|
||||||
initialValues={getInitialValues}
|
|
||||||
handleSubmit={()=>(console.log(1))}>
|
|
||||||
<Table />
|
|
||||||
|
|
||||||
</FormikForm>
|
<Table />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,109 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import DataTable from "../../../../Layout/Dashboard/Table/DataTable";
|
|
||||||
import { useColumns } from "./useTableColumns";
|
|
||||||
import { useFilterState } from "../../../../Components/Utils/Filter/FilterState";
|
import { useFilterState } from "../../../../Components/Utils/Filter/FilterState";
|
||||||
import { useFilterStateState } from "../../../../zustand/Filter";
|
import { useFilterStateState } from "../../../../zustand/Filter";
|
||||||
|
import { useAddPermissions, useGetAllPermissions } from "../../../../api/Permissions";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { ParamsEnum } from "../../../../enums/params";
|
||||||
|
import { Form, Formik } from "formik";
|
||||||
|
import FormTable from "./FormTable";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { useGetAllRole } from "../../../../api/role";
|
import { useGetAllRole } from "../../../../api/role";
|
||||||
import { useGetAllTag } from "../../../../api/tags";
|
|
||||||
const App: React.FC = () => {
|
|
||||||
|
|
||||||
|
const App: React.FC = () => {
|
||||||
|
const { role_id } = useParams<ParamsEnum>();
|
||||||
const { filterState } = useFilterState();
|
const { filterState } = useFilterState();
|
||||||
const { Filter } = useFilterStateState();
|
const { Filter } = useFilterStateState();
|
||||||
const name = Filter?.name ;
|
const name = Filter?.name;
|
||||||
const sort_by = Filter?.sort_by ;
|
const sort_by = Filter?.sort_by;
|
||||||
|
|
||||||
const response = useGetAllTag({
|
const Data = [
|
||||||
|
"absence::delete",
|
||||||
|
"absence::index",
|
||||||
|
"absence::show",
|
||||||
|
"absence::store",
|
||||||
|
"absence::update",
|
||||||
|
"admin::delete",
|
||||||
|
"admin::index",
|
||||||
|
"admin::show",
|
||||||
|
"admin::update",
|
||||||
|
];
|
||||||
|
|
||||||
|
const response = useGetAllRole({
|
||||||
pagination: true,
|
pagination: true,
|
||||||
|
show:role_id,
|
||||||
name,
|
name,
|
||||||
sort_by,
|
sort_by,
|
||||||
...filterState,
|
...filterState,
|
||||||
});
|
});
|
||||||
|
/// time complexity O(n) -_-
|
||||||
|
|
||||||
return <DataTable response={response} useColumns={useColumns} />;
|
const changePermissionShape = (Data:string[])=>{
|
||||||
|
const newArray: Array<{ name: any; [key: string]: boolean }> = [];
|
||||||
|
const hashMap = new Map<string, number>();
|
||||||
|
|
||||||
|
for (let i = 0; i < Data.length; i++) {
|
||||||
|
const [permission, value] = Data[i].split("::");
|
||||||
|
const existingIndex = hashMap.get(permission);
|
||||||
|
|
||||||
|
if (existingIndex !== undefined) {
|
||||||
|
newArray[existingIndex][value] = true;
|
||||||
|
if(newArray[existingIndex]["index"] && newArray[existingIndex]["show"] && newArray[existingIndex]["store"] && newArray[existingIndex]["update"] && newArray[existingIndex]["delete"]){
|
||||||
|
newArray[existingIndex]["ALL"] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newObject = { name: permission, [value]: true } as any;
|
||||||
|
newArray.push(newObject);
|
||||||
|
hashMap.set(permission, newArray.length - 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newArray
|
||||||
|
}
|
||||||
|
const newShapeArray = changePermissionShape(Data)
|
||||||
|
|
||||||
|
const [t] = useTranslation()
|
||||||
|
|
||||||
|
console.log(response,"response");
|
||||||
|
|
||||||
|
const reverseChangePermissionShape = (
|
||||||
|
newArray: Array<{ name: any; [key: string]: boolean }>
|
||||||
|
): string[] => {
|
||||||
|
const Data: string[] = [];
|
||||||
|
|
||||||
|
newArray.forEach((obj) => {
|
||||||
|
const permission = obj.name;
|
||||||
|
Object.keys(obj).forEach((key) => {
|
||||||
|
if (key !== "name" && key !== "ALL" && obj[key]) {
|
||||||
|
Data.push(`${permission}::${key}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return Data;
|
||||||
|
};
|
||||||
|
const {mutate} = useAddPermissions()
|
||||||
|
const handelSubmit = (values:any)=>{
|
||||||
|
const dataToSend = reverseChangePermissionShape(values);
|
||||||
|
mutate(dataToSend)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik initialValues={newShapeArray} onSubmit={handelSubmit} enableReinitialize>
|
||||||
|
{({handleSubmit})=>{
|
||||||
|
return (
|
||||||
|
<Form>
|
||||||
|
|
||||||
|
<FormTable response={response} />
|
||||||
|
<div className="permissions_submit_button">
|
||||||
|
<button className="button" onClick={()=> handleSubmit()
|
||||||
|
} type="submit" >{t("practical.submit")}</button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,94 @@
|
||||||
import { TableColumnsType } from "antd";
|
import { Checkbox, TableColumnsType } from "antd";
|
||||||
import { useObjectToEdit } from "../../../../zustand/ObjectToEditState";
|
|
||||||
import { useModalState } from "../../../../zustand/Modal";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Role } from "../../../../types/App";
|
import { ABILITIES_VALUES_ENUM } from "../../../../enums/abilities";
|
||||||
import { ModalEnum } from "../../../../enums/Model";
|
import { useFormikContext } from "formik";
|
||||||
import ValidationField from "../../../../Components/ValidationField/ValidationField";
|
|
||||||
|
|
||||||
export const useColumns = () => {
|
export const useColumns = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
const {values,setValues} = useFormikContext<any>()
|
||||||
|
|
||||||
const { setIsOpen } = useModalState((state) => state);
|
const onChange = (type:any,index:any) => {
|
||||||
|
const cloneValue = JSON.parse(JSON.stringify(values))
|
||||||
const { setObjectToEdit } = useObjectToEdit((state) => state);
|
if (!cloneValue[index]) {
|
||||||
const handleEdit = (record: any) => {
|
cloneValue[index] = {};
|
||||||
setObjectToEdit(record);
|
}
|
||||||
setIsOpen(ModalEnum?.ROLE_EDIT);
|
cloneValue[index][type] = !cloneValue[index][type];
|
||||||
|
setValues(cloneValue)
|
||||||
};
|
};
|
||||||
const columns: TableColumnsType<Role> = [
|
|
||||||
// {
|
const onChangeAll = (index:any) => {
|
||||||
// title: <ValidationField name="empty" type="Checkbox"/>,
|
const cloneValue = JSON.parse(JSON.stringify(values))
|
||||||
// dataIndex: "id",
|
if (!cloneValue[index]) {
|
||||||
// key: "id",
|
cloneValue[index] = {};
|
||||||
// align: "center",
|
}
|
||||||
// render: (_text) => {
|
if(cloneValue[index]["ALL"]){
|
||||||
// return (
|
cloneValue[index] = {
|
||||||
// <ValidationField name="empty" type="Checkbox"/>
|
name:cloneValue[index]?.name ,
|
||||||
// );
|
delete: false,
|
||||||
// },
|
index: false,
|
||||||
// },
|
show: false,
|
||||||
|
store: false,
|
||||||
|
update: false,
|
||||||
|
ALL: false
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
cloneValue[index] = {
|
||||||
|
name:cloneValue[index]?.name ,
|
||||||
|
delete: true,
|
||||||
|
index: true,
|
||||||
|
show: true,
|
||||||
|
store: true,
|
||||||
|
update: true,
|
||||||
|
ALL: true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
setValues(cloneValue)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const CheckBoxFieldALL = ({record,index}:{record:any,index:any})=>{
|
||||||
|
const isChecked = record?.ALL ;
|
||||||
|
|
||||||
|
return <Checkbox onChange={()=>onChangeAll(index)} checked={isChecked} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CheckBoxField = ({record,type,index}:{record:any,type:string,index:number})=>{
|
||||||
|
|
||||||
|
|
||||||
|
const isChecked = record?.[type] ;
|
||||||
|
|
||||||
|
return <Checkbox onChange={()=>onChange(type,index)} checked={isChecked} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const CheckBoxFieldALLPermissions = ()=>{
|
||||||
|
const cloneValue = JSON.parse(JSON.stringify(values)) ;
|
||||||
|
const IsAllValuesTrue = cloneValue?.every((item:any)=>{
|
||||||
|
return !!item?.index && !!item?.show && !!item?.store && !!item?.update && !!item?.delete
|
||||||
|
})
|
||||||
|
const onChangeAllPermissions = ()=>{
|
||||||
|
const newShape =cloneValue?.map((item:any)=>{
|
||||||
|
if(IsAllValuesTrue){
|
||||||
|
return {...item,delete: false,index: false,show: false,store: false,update: false,ALL: false}
|
||||||
|
}else{
|
||||||
|
return {...item,delete: true,index: true,show: true,store: true,update: true,ALL: true}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
setValues(newShape)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Checkbox onChange={()=>onChangeAllPermissions()} checked={IsAllValuesTrue} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const columns: TableColumnsType<any> = [
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("columns.units"),
|
title: <div className="df"> <CheckBoxFieldALLPermissions/> {t("columns.units")} </div>,
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
key: "name",
|
key: "name",
|
||||||
align: "center",
|
align: "center",
|
||||||
|
|
@ -39,9 +98,9 @@ export const useColumns = () => {
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text) => {
|
render: (_text,record,index) => {
|
||||||
return (
|
return (
|
||||||
<ValidationField name="empty" type="Checkbox"/>
|
<CheckBoxField record={record} index={index} type={ABILITIES_VALUES_ENUM.STORE} />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -50,9 +109,9 @@ export const useColumns = () => {
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text) => {
|
render: (_text,record,index) => {
|
||||||
return (
|
return (
|
||||||
<ValidationField name="empty" type="Checkbox"/>
|
<CheckBoxField record={record} index={index} type={ABILITIES_VALUES_ENUM.INDEX} />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -61,9 +120,9 @@ export const useColumns = () => {
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text) => {
|
render: (_text,record,index) => {
|
||||||
return (
|
return (
|
||||||
<ValidationField name="empty" type="Checkbox"/>
|
<CheckBoxField record={record} index={index} type={ABILITIES_VALUES_ENUM.UPDATE} />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -72,23 +131,36 @@ export const useColumns = () => {
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text) => {
|
render: (_text,record,index) => {
|
||||||
return (
|
return (
|
||||||
<ValidationField name="empty" type="Checkbox"/>
|
<CheckBoxField record={record} index={index} type={ABILITIES_VALUES_ENUM.DELETE} />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("columns.show"),
|
||||||
|
dataIndex: "id",
|
||||||
|
key: "id",
|
||||||
|
align: "center",
|
||||||
|
render: (_text,record,index) => {
|
||||||
|
return (
|
||||||
|
<CheckBoxField record={record} index={index} type={ABILITIES_VALUES_ENUM.SHOW} />
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("columns.allow_everyone"),
|
title: t("columns.allow_everyone"),
|
||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
key: "id",
|
key: "id",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_text) => {
|
render: (_text,record,index) => {
|
||||||
return (
|
return (
|
||||||
<ValidationField name="empty" type="Checkbox"/>
|
<CheckBoxFieldALL record={record} index={index} />
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return columns;
|
return columns;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useGetAllTag } from "../../../api/tags";
|
|
||||||
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
|
import DataTable from "../../../Layout/Dashboard/Table/DataTable";
|
||||||
import { useColumns } from "./useTableColumns";
|
import { useColumns } from "./useTableColumns";
|
||||||
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
import { useFilterState } from "../../../Components/Utils/Filter/FilterState";
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { ModalEnum } from "../../../enums/Model";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { useModalState } from "../../../zustand/Modal";
|
import { useModalState } from "../../../zustand/Modal";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { canDeleteRole,canEditRole } from "../../../utils/hasAbilityFn";
|
import { canDeleteRole,canEditRole, canShowRole } from "../../../utils/hasAbilityFn";
|
||||||
import ActionButtons from "../../../Components/Table/ActionButtons";
|
import ActionButtons from "../../../Components/Table/ActionButtons";
|
||||||
import { Role } from "../../../types/App";
|
import { Role } from "../../../types/App";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
@ -18,7 +18,7 @@ export const useColumns = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handelShow = (record: Role) => {
|
const handelShow = (record: Role) => {
|
||||||
navigate(`/${record?.id}`);
|
navigate(`${record?.id}/${ABILITIES_ENUM?.PERMISSIONS}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handelDelete = (record: any) => {
|
const handelDelete = (record: any) => {
|
||||||
|
|
@ -61,9 +61,11 @@ export const useColumns = () => {
|
||||||
<ActionButtons
|
<ActionButtons
|
||||||
canDelete={canEditRole}
|
canDelete={canEditRole}
|
||||||
canEdit={canDeleteRole}
|
canEdit={canDeleteRole}
|
||||||
|
canShow={canShowRole}
|
||||||
index={index}
|
index={index}
|
||||||
onDelete={() => handelDelete(record)}
|
onDelete={() => handelDelete(record)}
|
||||||
onEdit={() => handleEdit(record)}
|
onEdit={() => handleEdit(record)}
|
||||||
|
onShow={()=>handelShow(record)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ const DynamicTags = () => {
|
||||||
if (currentElement) {
|
if (currentElement) {
|
||||||
currentElement.focus(); // Set focus on the element
|
currentElement.focus(); // Set focus on the element
|
||||||
}
|
}
|
||||||
console.log(currentElement,"currentElement");
|
|
||||||
}, [lastElementIndex])
|
}, [lastElementIndex])
|
||||||
|
|
||||||
// console.log(formik?.values);
|
// console.log(formik?.values);
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,6 @@ const DrapableTable: React.FC = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const columns = useColumns();
|
const columns = useColumns();
|
||||||
const sortedDataSource = dataSource.sort((a, b) => a.order - b.order);
|
const sortedDataSource = dataSource.sort((a, b) => a.order - b.order);
|
||||||
console.log(sortedDataSource, "sortedDataSource");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,26 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { Spin } from "antd";
|
|
||||||
import {
|
import {
|
||||||
getInitialValues,
|
|
||||||
getValidationSchema,
|
|
||||||
getInitialValuesBase,
|
|
||||||
getValidationSchemaBase,
|
|
||||||
processTags,
|
processTags,
|
||||||
} from "./formUtil";
|
} from "./formUtil";
|
||||||
import { useAddQuestion, useAddQuestionAsync } from "../../../api/Question";
|
import { useAddQuestion, useAddQuestionAsync } from "../../../api/Question";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useParams } from "react-router-dom";
|
||||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
|
||||||
import { ParamsEnum } from "../../../enums/params";
|
import { ParamsEnum } from "../../../enums/params";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
|
|
||||||
import Header from "../../../Components/exercise/Header";
|
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
import BaseForm from "./Model/Malty/Form";
|
import BaseFormContainer from "./Model/AddForm/BaseForm";
|
||||||
import ModelForm from "./Model/ModelForm";
|
import FormContainer from "./Model/AddForm/Form";
|
||||||
import { toast } from "react-toastify";
|
import { handleValidateBaseQuestion, handleValidateSingleQuestion } from "./Model/AddForm/ValidationFn";
|
||||||
import { Form, Formik } from "formik";
|
import useUnsavedChangesWarning from "../../../Hooks/useUnsavedChangesWarning";
|
||||||
import { MdOutlineArrowForwardIos } from "react-icons/md";
|
import { useFormikContext } from "formik";
|
||||||
|
|
||||||
const AddPage: React.FC = () => {
|
const AddPage: React.FC = () => {
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
const { mutateAsync,isLoading:LoadingAsync } = useAddQuestionAsync();
|
const { mutateAsync, isLoading: LoadingAsync } = useAddQuestionAsync();
|
||||||
const { mutate, isLoading, isSuccess } = useAddQuestion();
|
const { mutate, isLoading, isSuccess } = useAddQuestion();
|
||||||
const { isBseQuestion, setTagsSearch, setSuccess } =
|
const { isBseQuestion, setTagsSearch, setSuccess } = useObjectToEdit();
|
||||||
useObjectToEdit();
|
|
||||||
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const { subject_id, lesson_id } = useParams<ParamsEnum>();
|
const { subject_id, lesson_id } = useParams<ParamsEnum>();
|
||||||
|
|
||||||
const handleFormSubmit = ( values: any) => {
|
const handleFormSubmit = (values: any) => {
|
||||||
const DataToSend = structuredClone(values);
|
const DataToSend = structuredClone(values);
|
||||||
setTagsSearch(null);
|
setTagsSearch(null);
|
||||||
|
|
||||||
|
|
@ -100,215 +88,26 @@ const AddPage: React.FC = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any)=>{
|
|
||||||
const haveMoreThanOneAnswer = values?.answers?.length > 1;
|
|
||||||
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
|
|
||||||
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
|
||||||
const content = values.content ;
|
|
||||||
const content_image = values.content_image ;
|
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
|
||||||
console.log(haveImageOrContent,"haveImageOrContent");
|
|
||||||
if(!haveContentOrContentImage){
|
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!haveMoreThanOneAnswer){
|
|
||||||
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
if(!haveOneAnswerRight){
|
|
||||||
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
if(haveImageOrContent){
|
|
||||||
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
if(isValid){
|
|
||||||
handleSubmit(values)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any) => {
|
|
||||||
const content = values.content ;
|
|
||||||
const content_image = values.content_image ;
|
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
|
||||||
console.log(2);
|
|
||||||
|
|
||||||
if(!haveContentOrContentImage){
|
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
|
|
||||||
|
|
||||||
|
|
||||||
const content = Question.content ;
|
|
||||||
const content_image = Question.content_image ;
|
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
|
||||||
if(!haveContentOrContentImage){
|
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//// answers
|
|
||||||
const answers = Question?.answers;
|
|
||||||
const haveAnswers = answers?.length > 0;
|
|
||||||
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
|
||||||
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
|
||||||
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!haveAnswers) {
|
|
||||||
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveMoreThanOneAnswer) {
|
|
||||||
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!haveOneAnswerRight) {
|
|
||||||
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(haveImageOrContent){
|
|
||||||
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(1);
|
|
||||||
|
|
||||||
if(isValid && isValidate){
|
|
||||||
console.log(2);
|
|
||||||
handleSubmit(values)
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const handleNavigateToPage = () => {
|
|
||||||
const cleanedUrl = location.pathname?.replace("/Question/add", "");
|
|
||||||
navigate(cleanedUrl);
|
|
||||||
};
|
|
||||||
const handleCancel = () => {
|
|
||||||
navigate(-1);
|
|
||||||
};
|
|
||||||
const Loading = LoadingAsync || isLoading;
|
const Loading = LoadingAsync || isLoading;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
setSuccess(true);
|
setSuccess(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [isSuccess]);
|
}, [isSuccess]);
|
||||||
|
|
||||||
if (isBseQuestion) {
|
if (isBseQuestion) {
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div className="QuestionPractical">
|
<BaseFormContainer Loading={Loading} handleFormSubmit={handleFormSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} />
|
||||||
<header>
|
|
||||||
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.add_new_question")}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div className="exercise_add">
|
|
||||||
<Formik
|
|
||||||
onSubmit={handleFormSubmit}
|
|
||||||
initialValues={getInitialValuesBase({} as any)}
|
|
||||||
validationSchema={getValidationSchemaBase}
|
|
||||||
enableReinitialize
|
|
||||||
|
|
||||||
>
|
|
||||||
{({ values,isValid,handleSubmit }) => (
|
|
||||||
|
|
||||||
<Form className="w-100">
|
|
||||||
<main className="w-100 exercise_add_main">
|
|
||||||
<Header />
|
|
||||||
<BaseForm />
|
|
||||||
|
|
||||||
<div className="exercise_add_buttons">
|
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
|
||||||
<button disabled={Loading} className="relative" type="button"
|
|
||||||
onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
|
||||||
onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
|
||||||
>
|
|
||||||
{t("practical.add")}
|
|
||||||
|
|
||||||
{Loading && (
|
|
||||||
<span className="Spinier_Div">
|
|
||||||
<Spin />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<div className="QuestionPractical">
|
<FormContainer Loading={Loading} handleFormSubmit={handleFormSubmit} handleValidateSingleQuestion={handleValidateSingleQuestion} />
|
||||||
<header>
|
|
||||||
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.add_new_question")}
|
|
||||||
</header>
|
|
||||||
<div className="exercise_add">
|
|
||||||
<Formik
|
|
||||||
enableReinitialize={true}
|
|
||||||
initialValues={getInitialValues({} as any)}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
validateOnMount={true}
|
|
||||||
onSubmit={(values) => {
|
|
||||||
handleFormSubmit(values);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ values,isValid ,handleSubmit}) => (
|
|
||||||
<Form className="w-100">
|
|
||||||
<main className="w-100 exercise_add_main">
|
|
||||||
<Header />
|
|
||||||
<ModelForm />
|
|
||||||
|
|
||||||
<div className="exercise_add_buttons">
|
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
|
||||||
<div
|
|
||||||
className="relative"
|
|
||||||
onClick={()=>{ handleSubmit() }}
|
|
||||||
>
|
|
||||||
{t("practical.add")}
|
|
||||||
|
|
||||||
{Loading && (
|
|
||||||
<span className="Spinier_Div">
|
|
||||||
<Spin />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { Checkbox, Modal, Popover, Spin } from "antd";
|
|
||||||
import {
|
import {
|
||||||
getInitialValues,
|
|
||||||
getValidationSchema,
|
|
||||||
getInitialValuesBase,
|
|
||||||
getValidationSchemaBase,
|
|
||||||
processTags,
|
processTags,
|
||||||
} from "./formUtil";
|
} from "./formUtil";
|
||||||
import {
|
import {
|
||||||
|
|
@ -19,25 +14,20 @@ import { ParamsEnum } from "../../../enums/params";
|
||||||
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
import { useObjectToEdit } from "../../../zustand/ObjectToEditState";
|
||||||
import { removeStringKeys } from "../../../utils/removeStringKeys";
|
import { removeStringKeys } from "../../../utils/removeStringKeys";
|
||||||
import SpinContainer from "../../../Components/Layout/SpinContainer";
|
import SpinContainer from "../../../Components/Layout/SpinContainer";
|
||||||
import ModelForm from "./Model/ModelForm";
|
|
||||||
import BaseForm from "./Model/Malty/Form";
|
|
||||||
import { Question } from "../../../types/Item";
|
import { Question } from "../../../types/Item";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import { deletePathSegments } from "../../../utils/deletePathSegments";
|
import { deletePathSegments } from "../../../utils/deletePathSegments";
|
||||||
import { Form, Formik } from "formik";
|
import BaseFormContainer from "./Model/EditForm/BaseFormContainer";
|
||||||
import { MdOutlineArrowForwardIos } from "react-icons/md";
|
import FormContainer from "./Model/EditForm/FormContainer";
|
||||||
import { SettingFilled } from "@ant-design/icons";
|
|
||||||
import { CheckboxProps } from "antd/lib";
|
|
||||||
import { LocalStorageEnum } from "../../../enums/LocalStorageEnum";
|
|
||||||
|
|
||||||
const EditPage: React.FC = () => {
|
const EditPage: React.FC = () => {
|
||||||
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
|
const { subject_id, lesson_id, question_id } = useParams<ParamsEnum>();
|
||||||
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions , ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
|
const { isBseQuestion, setIsBseQuestion, setTagsSearch, DeletedQuestions, ShowHint, setShowHint, ShowLatexOption, setShowLatexOption } =
|
||||||
useObjectToEdit();
|
useObjectToEdit();
|
||||||
|
|
||||||
const { mutate, isSuccess, isLoading } = useUpdateQuestion();
|
const { mutate, isSuccess, isLoading } = useUpdateQuestion();
|
||||||
const { mutate: DeleteQuestion } = useDeleteQuestion();
|
const { mutate: DeleteQuestion } = useDeleteQuestion();
|
||||||
const { mutate: mutateAdd , isLoading:LoadingAsync } = useAddQuestion();
|
const { mutate: mutateAdd, isLoading: LoadingAsync } = useAddQuestion();
|
||||||
|
|
||||||
const { data, isLoading: dataLoading } = useGetAllQuestion({
|
const { data, isLoading: dataLoading } = useGetAllQuestion({
|
||||||
show: question_id,
|
show: question_id,
|
||||||
|
|
@ -46,7 +36,7 @@ const EditPage: React.FC = () => {
|
||||||
const { data: Questions, isLoading: QuestionsDataLoading } =
|
const { data: Questions, isLoading: QuestionsDataLoading } =
|
||||||
useGetAllQuestion({
|
useGetAllQuestion({
|
||||||
parent_id: question_id,
|
parent_id: question_id,
|
||||||
isPaginated:false
|
isPaginated: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const objectToEdit = { ...data?.data, Questions: Questions?.data };
|
const objectToEdit = { ...data?.data, Questions: Questions?.data };
|
||||||
|
|
@ -79,7 +69,7 @@ const EditPage: React.FC = () => {
|
||||||
console.log(DeletedQuestions, "DeletedQuestions");
|
console.log(DeletedQuestions, "DeletedQuestions");
|
||||||
console.log(UpdateBseQuestion);
|
console.log(UpdateBseQuestion);
|
||||||
|
|
||||||
// mutate(UpdateBseQuestion);
|
mutate(UpdateBseQuestion);
|
||||||
|
|
||||||
DeletedQuestions?.map((item: any) => {
|
DeletedQuestions?.map((item: any) => {
|
||||||
DeleteQuestion({ id: item?.id });
|
DeleteQuestion({ id: item?.id });
|
||||||
|
|
@ -93,7 +83,7 @@ const EditPage: React.FC = () => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
const itemToSend = structuredClone(item);
|
const itemToSend = structuredClone(item);
|
||||||
const keysToRemove = ["content_image"];
|
const keysToRemove = ["content_image"];
|
||||||
console.log(itemToSend,"itemToSend");
|
console.log(itemToSend, "itemToSend");
|
||||||
|
|
||||||
const updatedObject = removeStringKeys(itemToSend, keysToRemove);
|
const updatedObject = removeStringKeys(itemToSend, keysToRemove);
|
||||||
console.log(updatedObject, "updatedObject");
|
console.log(updatedObject, "updatedObject");
|
||||||
|
|
@ -102,13 +92,13 @@ const EditPage: React.FC = () => {
|
||||||
const oldAnswers = [] as any;
|
const oldAnswers = [] as any;
|
||||||
const newAnswers = [] as any;
|
const newAnswers = [] as any;
|
||||||
|
|
||||||
if(updatedObject?.content_image === null){
|
if (updatedObject?.content_image === null) {
|
||||||
updatedObject["content_image"] = ""
|
updatedObject["content_image"] = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedObject?.answers?.forEach((item: any) => {
|
updatedObject?.answers?.forEach((item: any) => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
if(item?.content_image === null){
|
if (item?.content_image === null) {
|
||||||
item["content_image"] = ""
|
item["content_image"] = ""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -126,15 +116,15 @@ const EditPage: React.FC = () => {
|
||||||
mutate({
|
mutate({
|
||||||
...updatedObject,
|
...updatedObject,
|
||||||
answers,
|
answers,
|
||||||
tags:tagToSend,
|
tags: tagToSend,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(values?.id);
|
console.log(values?.id);
|
||||||
|
|
||||||
const tags = processTags(item);
|
const tags = processTags(item);
|
||||||
console.log(item,"DataToSend");
|
console.log(item, "DataToSend");
|
||||||
|
|
||||||
console.log(tags,"tags");
|
console.log(tags, "tags");
|
||||||
mutateAdd({
|
mutateAdd({
|
||||||
...item,
|
...item,
|
||||||
subject_id: subject_id,
|
subject_id: subject_id,
|
||||||
|
|
@ -158,12 +148,12 @@ const EditPage: React.FC = () => {
|
||||||
const newAnswers = [] as any;
|
const newAnswers = [] as any;
|
||||||
updatedObject?.answers?.forEach((item: any) => {
|
updatedObject?.answers?.forEach((item: any) => {
|
||||||
if (item?.id) {
|
if (item?.id) {
|
||||||
console.log(item,"item");
|
console.log(item, "item");
|
||||||
const deletedImage = item?.content_image === null
|
const deletedImage = item?.content_image === null
|
||||||
if(deletedImage){
|
if (deletedImage) {
|
||||||
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0, content_image:"" });
|
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0, content_image: "" });
|
||||||
|
|
||||||
}else{
|
} else {
|
||||||
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
oldAnswers.push({ ...item, isCorrect: item?.isCorrect ? 1 : 0 });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -187,50 +177,47 @@ const EditPage: React.FC = () => {
|
||||||
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const handleCancel = () => {
|
|
||||||
navigate(-1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any)=>{
|
const handleValidateSingleQuestion = (values: any, isValid: boolean, handleSubmit: any) => {
|
||||||
const haveMoreThanOneAnswer = values?.answers?.length > 1;
|
const haveMoreThanOneAnswer = values?.answers?.length > 1;
|
||||||
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
|
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true)
|
||||||
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item: any) => !(item?.content) && !(item.content_image))
|
||||||
const content = values.content ;
|
const content = values.content;
|
||||||
const content_image = values.content_image ;
|
const content_image = values.content_image;
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
const haveContentOrContentImage = !!content || !!content_image;
|
||||||
console.log(haveImageOrContent,"haveImageOrContent");
|
console.log(haveImageOrContent, "haveImageOrContent");
|
||||||
if(!haveContentOrContentImage){
|
if (!haveContentOrContentImage) {
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!haveMoreThanOneAnswer){
|
if (!haveMoreThanOneAnswer) {
|
||||||
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
|
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
||||||
return false ;
|
return false;
|
||||||
}
|
}
|
||||||
if(!haveOneAnswerRight){
|
if (!haveOneAnswerRight) {
|
||||||
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
|
||||||
return false ;
|
return false;
|
||||||
}
|
}
|
||||||
if(haveImageOrContent){
|
if (haveImageOrContent) {
|
||||||
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(1);
|
console.log(1);
|
||||||
|
|
||||||
if(isValid){
|
if (isValid) {
|
||||||
handleSubmit(values)
|
handleSubmit(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any) => {
|
const handleValidateBaseQuestion = (values: any, isValid: boolean, handleSubmit: any) => {
|
||||||
const content = values.content ;
|
const content = values.content;
|
||||||
const content_image = values.content_image ;
|
const content_image = values.content_image;
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
const haveContentOrContentImage = !!content || !!content_image;
|
||||||
console.log(2);
|
console.log(2);
|
||||||
|
|
||||||
if(!haveContentOrContentImage){
|
if (!haveContentOrContentImage) {
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -239,10 +226,10 @@ const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any
|
||||||
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
|
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
|
||||||
|
|
||||||
|
|
||||||
const content = Question.content ;
|
const content = Question.content;
|
||||||
const content_image = Question.content_image ;
|
const content_image = Question.content_image;
|
||||||
const haveContentOrContentImage = !!content || !!content_image ;
|
const haveContentOrContentImage = !!content || !!content_image;
|
||||||
if(!haveContentOrContentImage){
|
if (!haveContentOrContentImage) {
|
||||||
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +240,7 @@ const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any
|
||||||
const haveAnswers = answers?.length > 0;
|
const haveAnswers = answers?.length > 0;
|
||||||
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
||||||
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
||||||
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
const haveImageOrContent = haveOneAnswerRight && answers?.some((item: any) => !(item?.content) && !(item.content_image))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -273,7 +260,7 @@ const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(haveImageOrContent){
|
if (haveImageOrContent) {
|
||||||
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -283,17 +270,12 @@ const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any
|
||||||
|
|
||||||
console.log(1);
|
console.log(1);
|
||||||
|
|
||||||
if(isValid && isValidate){
|
if (isValid && isValidate) {
|
||||||
console.log(2);
|
console.log(2);
|
||||||
handleSubmit(values)
|
handleSubmit(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNavigateToPage = () => {
|
|
||||||
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
|
|
||||||
navigate(cleanedUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
|
|
@ -302,31 +284,6 @@ const handleNavigateToPage = () => {
|
||||||
}
|
}
|
||||||
}, [isSuccess]);
|
}, [isSuccess]);
|
||||||
|
|
||||||
const onChangeHint: CheckboxProps['onChange'] = (e) => {
|
|
||||||
setShowHint(e.target.checked);
|
|
||||||
localStorage?.setItem(LocalStorageEnum.HINT_INPUT,e.target.checked ? "true" : "false" )
|
|
||||||
};
|
|
||||||
|
|
||||||
const onChangeLatexOption: CheckboxProps['onChange'] = (e) => {
|
|
||||||
setShowLatexOption(e.target.checked);
|
|
||||||
localStorage?.setItem(LocalStorageEnum.LATEX_OPTION_INPUT,e.target.checked ? "true" : "false" )
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const contentSetting = (
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<Checkbox checked={ShowHint} onChange={onChangeHint}>
|
|
||||||
{ t("header.show_hint")}
|
|
||||||
</Checkbox>
|
|
||||||
|
|
||||||
<Checkbox checked={ShowLatexOption} onChange={onChangeLatexOption}>
|
|
||||||
{ t("header.show_MMl")}
|
|
||||||
</Checkbox>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -337,119 +294,13 @@ const handleNavigateToPage = () => {
|
||||||
}
|
}
|
||||||
if (objectToEdit?.isBase) {
|
if (objectToEdit?.isBase) {
|
||||||
return (
|
return (
|
||||||
|
<BaseFormContainer t={t} Loading={Loading} handleSubmit={handleSubmit} handleValidateBaseQuestion={handleValidateBaseQuestion} objectToEdit={objectToEdit} />
|
||||||
|
|
||||||
<div className="QuestionPractical">
|
|
||||||
<header>
|
|
||||||
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div className="exercise_add">
|
|
||||||
<Formik
|
|
||||||
onSubmit={handleSubmit}
|
|
||||||
initialValues={getInitialValuesBase(objectToEdit)}
|
|
||||||
validationSchema={getValidationSchemaBase}
|
|
||||||
enableReinitialize
|
|
||||||
>
|
|
||||||
{({ values,isValid,handleSubmit }) => (
|
|
||||||
|
|
||||||
<Form className="w-100">
|
|
||||||
<main className="w-100 exercise_add_main">
|
|
||||||
{/* <Header/> */}
|
|
||||||
<header className="exercise_add_header mb-4">
|
|
||||||
<div>
|
|
||||||
{t("practical.edit")} {t("models.exercise")}{" "}
|
|
||||||
</div>
|
|
||||||
<div className="SettingEdit">
|
|
||||||
<Popover trigger="click" content={contentSetting}>
|
|
||||||
<SettingFilled/>
|
|
||||||
|
|
||||||
</Popover>
|
|
||||||
<div>{t("header.exercise")}</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<BaseForm />
|
|
||||||
<div className="exercise_add_buttons">
|
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
|
||||||
<button disabled={Loading} className="relative" type="button"
|
|
||||||
onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
|
||||||
onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
|
||||||
> {t("practical.edit")}
|
|
||||||
|
|
||||||
{Loading && (
|
|
||||||
<span className="Spinier_Div">
|
|
||||||
<Spin />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<FormContainer t={t} Loading={Loading} handleSubmit={handleSubmit} handleValidateSingleQuestion={handleValidateSingleQuestion} objectToEdit={objectToEdit} />
|
||||||
<div className="QuestionPractical">
|
|
||||||
<header>
|
|
||||||
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
|
|
||||||
</header>
|
|
||||||
<div className="exercise_add">
|
|
||||||
|
|
||||||
<Formik
|
|
||||||
enableReinitialize={true}
|
|
||||||
initialValues={getInitialValues(objectToEdit)}
|
|
||||||
validationSchema={getValidationSchema}
|
|
||||||
onSubmit={(values) => {
|
|
||||||
handleSubmit(values);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ values , dirty,isValid,handleSubmit }) => (
|
|
||||||
<Form className="w-100">
|
|
||||||
<main className="w-100 exercise_add_main">
|
|
||||||
{/* <Header/> */}
|
|
||||||
<header className="exercise_add_header mb-4">
|
|
||||||
<div>
|
|
||||||
{t("practical.edit")} {t("models.exercise")}{" "}
|
|
||||||
</div>
|
|
||||||
<div className="SettingEdit">
|
|
||||||
|
|
||||||
<Popover trigger="click" content={contentSetting}>
|
|
||||||
<SettingFilled/>
|
|
||||||
|
|
||||||
</Popover>
|
|
||||||
<div>{t("header.exercise")}</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<ModelForm />
|
|
||||||
<div className="exercise_add_buttons">
|
|
||||||
<div onClick={handleCancel}>{t("practical.back")}</div>
|
|
||||||
<div
|
|
||||||
className="relative"
|
|
||||||
onClick={()=>{ Loading ? ()=>{} : handleValidateSingleQuestion(values,isValid,handleSubmit) }}
|
|
||||||
> {t("practical.edit")}
|
|
||||||
{Loading && (
|
|
||||||
<span className="Spinier_Div">
|
|
||||||
<Spin />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
72
src/Pages/Admin/question/Model/AddForm/BaseForm.tsx
Normal file
72
src/Pages/Admin/question/Model/AddForm/BaseForm.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Form, Formik, useFormikContext } from 'formik'
|
||||||
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { MdOutlineArrowForwardIos } from 'react-icons/md'
|
||||||
|
import { getInitialValuesBase, getValidationSchemaBase } from '../../formUtil'
|
||||||
|
import Header from '../../../../../Components/exercise/Header'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { Spin } from 'antd'
|
||||||
|
import BaseForm from "../../Model/Malty/Form";
|
||||||
|
|
||||||
|
const BaseFormContainer = ({handleFormSubmit,Loading,handleValidateBaseQuestion}:{handleFormSubmit:any,Loading:any,handleValidateBaseQuestion:any}) => {
|
||||||
|
const [t] = useTranslation()
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleNavigateToPage = () => {
|
||||||
|
const cleanedUrl = location.pathname?.replace("/Question/add", "");
|
||||||
|
navigate(cleanedUrl);
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="QuestionPractical">
|
||||||
|
<header>
|
||||||
|
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.add_new_question")}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="exercise_add">
|
||||||
|
<Formik
|
||||||
|
onSubmit={handleFormSubmit}
|
||||||
|
initialValues={getInitialValuesBase({} as any)}
|
||||||
|
validationSchema={getValidationSchemaBase}
|
||||||
|
enableReinitialize
|
||||||
|
|
||||||
|
>
|
||||||
|
{({ values,isValid,handleSubmit ,dirty}) => (
|
||||||
|
|
||||||
|
<Form className="w-100">
|
||||||
|
<main className="w-100 exercise_add_main">
|
||||||
|
<Header />
|
||||||
|
<BaseForm />
|
||||||
|
|
||||||
|
<div className="exercise_add_buttons">
|
||||||
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
<button disabled={Loading} className={`relative ${dirty ? "" : "disabled"}`} type="button"
|
||||||
|
onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit,t) }}
|
||||||
|
>
|
||||||
|
{t("practical.add")}
|
||||||
|
|
||||||
|
{Loading && (
|
||||||
|
<span className="Spinier_Div">
|
||||||
|
<Spin />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BaseFormContainer
|
||||||
72
src/Pages/Admin/question/Model/AddForm/Form.tsx
Normal file
72
src/Pages/Admin/question/Model/AddForm/Form.tsx
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Form, Formik, useFormikContext } from 'formik'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { MdOutlineArrowForwardIos } from 'react-icons/md'
|
||||||
|
import { getInitialValues, getValidationSchema } from '../../formUtil'
|
||||||
|
import Header from '../../../../../Components/exercise/Header'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import { Spin } from 'antd'
|
||||||
|
import ModelForm from "../../Model/ModelForm";
|
||||||
|
|
||||||
|
const FormContainer = ({handleFormSubmit,Loading,handleValidateSingleQuestion}:{handleFormSubmit:any,Loading:any,handleValidateSingleQuestion:any}) => {
|
||||||
|
const [t] = useTranslation()
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleNavigateToPage = () => {
|
||||||
|
const cleanedUrl = location.pathname?.replace("/Question/add", "");
|
||||||
|
navigate(cleanedUrl);
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="QuestionPractical">
|
||||||
|
<header>
|
||||||
|
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.add_new_question")}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="exercise_add">
|
||||||
|
<Formik
|
||||||
|
enableReinitialize={true}
|
||||||
|
initialValues={getInitialValues({} as any)}
|
||||||
|
validationSchema={getValidationSchema}
|
||||||
|
validateOnMount={true}
|
||||||
|
onSubmit={(values) => {
|
||||||
|
handleFormSubmit(values);
|
||||||
|
}}
|
||||||
|
|
||||||
|
>
|
||||||
|
{({ values,isValid ,handleSubmit,dirty}) => (
|
||||||
|
<Form className="w-100">
|
||||||
|
<main className="w-100 exercise_add_main">
|
||||||
|
<Header />
|
||||||
|
<ModelForm />
|
||||||
|
|
||||||
|
<div className="exercise_add_buttons">
|
||||||
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
<div
|
||||||
|
className={`relative ${dirty ? "" : "disabled"}`}
|
||||||
|
onClick={()=>{ Loading ? ()=>{} : handleValidateSingleQuestion(values,isValid,handleSubmit,t) }}
|
||||||
|
>
|
||||||
|
{t("practical.add")}
|
||||||
|
|
||||||
|
{Loading && (
|
||||||
|
<span className="Spinier_Div">
|
||||||
|
<Spin />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormContainer
|
||||||
100
src/Pages/Admin/question/Model/AddForm/ValidationFn.ts
Normal file
100
src/Pages/Admin/question/Model/AddForm/ValidationFn.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any,t:any)=>{
|
||||||
|
const haveMoreThanOneAnswer = values?.answers?.length > 1;
|
||||||
|
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
|
||||||
|
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
||||||
|
const content = values.content ;
|
||||||
|
const content_image = values.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
console.log(haveImageOrContent,"haveImageOrContent");
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!haveMoreThanOneAnswer){
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if(!haveOneAnswerRight){
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
if(isValid){
|
||||||
|
handleSubmit(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any,t:any) => {
|
||||||
|
const content = values.content ;
|
||||||
|
const content_image = values.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
console.log(2);
|
||||||
|
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
|
||||||
|
|
||||||
|
|
||||||
|
const content = Question.content ;
|
||||||
|
const content_image = Question.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// answers
|
||||||
|
const answers = Question?.answers;
|
||||||
|
const haveAnswers = answers?.length > 0;
|
||||||
|
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
||||||
|
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
||||||
|
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!haveAnswers) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveMoreThanOneAnswer) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveOneAnswerRight) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
if(isValid && isValidate){
|
||||||
|
console.log(2);
|
||||||
|
handleSubmit(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
108
src/Pages/Admin/question/Model/EditForm/BaseFormContainer.tsx
Normal file
108
src/Pages/Admin/question/Model/EditForm/BaseFormContainer.tsx
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
import { Form, Formik } from 'formik';
|
||||||
|
import React from 'react'
|
||||||
|
import { MdOutlineArrowForwardIos } from 'react-icons/md';
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import { getInitialValuesBase, getValidationSchemaBase } from '../../formUtil';
|
||||||
|
import { Checkbox, Popover, Spin } from 'antd';
|
||||||
|
import { SettingFilled } from '@ant-design/icons';
|
||||||
|
import { CheckboxProps } from 'antd/lib';
|
||||||
|
import { LocalStorageEnum } from '../../../../../enums/LocalStorageEnum';
|
||||||
|
import { useObjectToEdit } from '../../../../../zustand/ObjectToEditState';
|
||||||
|
import ModelForm from "../../Model/Malty/Form";
|
||||||
|
|
||||||
|
const BaseFormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateBaseQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateBaseQuestion:any,t:any}) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
|
||||||
|
useObjectToEdit();
|
||||||
|
const handleCancel = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
const handleNavigateToPage = () => {
|
||||||
|
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
|
||||||
|
navigate(cleanedUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeHint: CheckboxProps['onChange'] = (e) => {
|
||||||
|
setShowHint(e.target.checked);
|
||||||
|
localStorage?.setItem(LocalStorageEnum.HINT_INPUT,e.target.checked ? "true" : "false" )
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeLatexOption: CheckboxProps['onChange'] = (e) => {
|
||||||
|
setShowLatexOption(e.target.checked);
|
||||||
|
localStorage?.setItem(LocalStorageEnum.LATEX_OPTION_INPUT,e.target.checked ? "true" : "false" )
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const contentSetting = (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Checkbox checked={ShowHint} onChange={onChangeHint}>
|
||||||
|
{ t("header.show_hint")}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Checkbox checked={ShowLatexOption} onChange={onChangeLatexOption}>
|
||||||
|
{ t("header.show_MMl")}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="QuestionPractical">
|
||||||
|
<header>
|
||||||
|
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className="exercise_add">
|
||||||
|
<Formik
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
initialValues={getInitialValuesBase(objectToEdit)}
|
||||||
|
validationSchema={getValidationSchemaBase}
|
||||||
|
enableReinitialize
|
||||||
|
>
|
||||||
|
{({ values,isValid,handleSubmit,dirty }) => (
|
||||||
|
|
||||||
|
<Form className="w-100">
|
||||||
|
<main className="w-100 exercise_add_main">
|
||||||
|
{/* <Header/> */}
|
||||||
|
<header className="exercise_add_header mb-4">
|
||||||
|
<div>
|
||||||
|
{t("practical.edit")} {t("models.exercise")}{" "}
|
||||||
|
</div>
|
||||||
|
<div className="SettingEdit">
|
||||||
|
<Popover trigger="click" content={contentSetting}>
|
||||||
|
<SettingFilled/>
|
||||||
|
|
||||||
|
</Popover>
|
||||||
|
<div>{t("header.exercise")}</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<ModelForm />
|
||||||
|
<div className="exercise_add_buttons">
|
||||||
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
<button disabled={Loading} className={`relative ${dirty ? "" : "disabled"}`} type="button"
|
||||||
|
onClick={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
||||||
|
onSubmit={()=>{handleValidateBaseQuestion(values,isValid,handleSubmit) }}
|
||||||
|
> {t("practical.edit")}
|
||||||
|
|
||||||
|
{Loading && (
|
||||||
|
<span className="Spinier_Div">
|
||||||
|
<Spin />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BaseFormContainer
|
||||||
110
src/Pages/Admin/question/Model/EditForm/FormContainer.tsx
Normal file
110
src/Pages/Admin/question/Model/EditForm/FormContainer.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
import { Form, Formik } from 'formik';
|
||||||
|
import React from 'react'
|
||||||
|
import { MdOutlineArrowForwardIos } from 'react-icons/md';
|
||||||
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
import { getInitialValues, getValidationSchema } from '../../formUtil';
|
||||||
|
import { Checkbox, Popover, Spin } from 'antd';
|
||||||
|
import { SettingFilled } from '@ant-design/icons';
|
||||||
|
import { CheckboxProps } from 'antd/lib';
|
||||||
|
import { LocalStorageEnum } from '../../../../../enums/LocalStorageEnum';
|
||||||
|
import { useObjectToEdit } from '../../../../../zustand/ObjectToEditState';
|
||||||
|
import ModelForm from "../../Model/ModelForm";
|
||||||
|
|
||||||
|
const FormContainer = ({objectToEdit,handleSubmit,Loading,handleValidateSingleQuestion,t}:{objectToEdit:any,handleSubmit:any,Loading:any,handleValidateSingleQuestion:any,t:any}) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { ShowHint,setShowHint , ShowLatexOption,setShowLatexOption } =
|
||||||
|
useObjectToEdit();
|
||||||
|
const handleCancel = () => {
|
||||||
|
navigate(-1);
|
||||||
|
};
|
||||||
|
const handleNavigateToPage = () => {
|
||||||
|
const cleanedUrl = location.pathname.replace(/\/Question\/\d+$/, "");
|
||||||
|
navigate(cleanedUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeHint: CheckboxProps['onChange'] = (e) => {
|
||||||
|
setShowHint(e.target.checked);
|
||||||
|
localStorage?.setItem(LocalStorageEnum.HINT_INPUT,e.target.checked ? "true" : "false" )
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeLatexOption: CheckboxProps['onChange'] = (e) => {
|
||||||
|
setShowLatexOption(e.target.checked);
|
||||||
|
localStorage?.setItem(LocalStorageEnum.LATEX_OPTION_INPUT,e.target.checked ? "true" : "false" )
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const contentSetting = (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<Checkbox checked={ShowHint} onChange={onChangeHint}>
|
||||||
|
{ t("header.show_hint")}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Checkbox checked={ShowLatexOption} onChange={onChangeLatexOption}>
|
||||||
|
{ t("header.show_MMl")}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="QuestionPractical">
|
||||||
|
<header>
|
||||||
|
<MdOutlineArrowForwardIos onClick={handleNavigateToPage} /> {t("header.edit_question")}
|
||||||
|
</header>
|
||||||
|
<div className="exercise_add">
|
||||||
|
|
||||||
|
<Formik
|
||||||
|
enableReinitialize={true}
|
||||||
|
initialValues={getInitialValues(objectToEdit)}
|
||||||
|
validationSchema={getValidationSchema}
|
||||||
|
onSubmit={(values) => {
|
||||||
|
handleSubmit(values);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ values , dirty,isValid,handleSubmit }) => (
|
||||||
|
<Form className="w-100">
|
||||||
|
<main className="w-100 exercise_add_main">
|
||||||
|
{/* <Header/> */}
|
||||||
|
<header className="exercise_add_header mb-4">
|
||||||
|
<div>
|
||||||
|
{t("practical.edit")} {t("models.exercise")}{" "}
|
||||||
|
</div>
|
||||||
|
<div className="SettingEdit">
|
||||||
|
|
||||||
|
<Popover trigger="click" content={contentSetting}>
|
||||||
|
<SettingFilled/>
|
||||||
|
|
||||||
|
</Popover>
|
||||||
|
<div>{t("header.exercise")}</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<ModelForm />
|
||||||
|
<div className="exercise_add_buttons">
|
||||||
|
<div onClick={handleCancel}>{t("practical.back")}</div>
|
||||||
|
<div
|
||||||
|
className={`relative ${dirty ? "" : "disabled"}`}
|
||||||
|
onClick={()=>{ Loading ? ()=>{} : handleValidateSingleQuestion(values,isValid,handleSubmit,t) }}
|
||||||
|
> {t("practical.edit")}
|
||||||
|
{Loading && (
|
||||||
|
<span className="Spinier_Div">
|
||||||
|
<Spin />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FormContainer
|
||||||
100
src/Pages/Admin/question/Model/EditForm/ValidationFn.ts
Normal file
100
src/Pages/Admin/question/Model/EditForm/ValidationFn.ts
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
export const handleValidateSingleQuestion = (values:any,isValid:boolean,handleSubmit:any,t:any)=>{
|
||||||
|
const haveMoreThanOneAnswer = values?.answers?.length > 1;
|
||||||
|
const haveOneAnswerRight = haveMoreThanOneAnswer && values?.answers?.some((item:any)=> item?.isCorrect === 1 || item.isCorrect === true )
|
||||||
|
const haveImageOrContent = haveOneAnswerRight && values?.answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
||||||
|
const content = values.content ;
|
||||||
|
const content_image = values.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
console.log(haveImageOrContent,"haveImageOrContent");
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!haveMoreThanOneAnswer){
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers")) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if(!haveOneAnswerRight){
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers")) ;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
if(isValid){
|
||||||
|
handleSubmit(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
export const handleValidateBaseQuestion = (values: any,isValid:boolean,handleSubmit:any,t:any) => {
|
||||||
|
const content = values.content ;
|
||||||
|
const content_image = values.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
console.log(2);
|
||||||
|
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
const isValidate = values?.Questions?.every((Question: any, QuestionsIndex: number) => {
|
||||||
|
|
||||||
|
|
||||||
|
const content = Question.content ;
|
||||||
|
const content_image = Question.content_image ;
|
||||||
|
const haveContentOrContentImage = !!content || !!content_image ;
|
||||||
|
if(!haveContentOrContentImage){
|
||||||
|
toast.error(`${t("validation.one_of_image_and_content_should_be_enter_in_question")}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//// answers
|
||||||
|
const answers = Question?.answers;
|
||||||
|
const haveAnswers = answers?.length > 0;
|
||||||
|
const haveMoreThanOneAnswer = haveAnswers && answers?.length > 1;
|
||||||
|
const haveOneAnswerRight = haveMoreThanOneAnswer && answers?.some((item: any) => item?.isCorrect === 1 || item.isCorrect === true);
|
||||||
|
const haveImageOrContent = haveOneAnswerRight && answers?.some((item:any)=> !(item?.content) && !(item.content_image) )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!haveAnswers) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveMoreThanOneAnswer) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!haveOneAnswerRight) {
|
||||||
|
toast.error(t("validation.it_should_have_more_than_one_correct_answers"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(haveImageOrContent){
|
||||||
|
toast.error(t("validation.one_of_image_and_content_should_be_enter_in_answer"))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(1);
|
||||||
|
|
||||||
|
if(isValid && isValidate){
|
||||||
|
console.log(2);
|
||||||
|
handleSubmit(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -21,7 +21,6 @@ const ChoiceFields = React.memo(
|
||||||
setFieldValue:any;
|
setFieldValue:any;
|
||||||
values:any
|
values:any
|
||||||
}) => {
|
}) => {
|
||||||
console.log(567)
|
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
const { ShowHint } = useObjectToEdit();
|
const { ShowHint } = useObjectToEdit();
|
||||||
const handleDeleteChoice = () => {
|
const handleDeleteChoice = () => {
|
||||||
|
|
@ -120,7 +119,6 @@ const ChoiceFields = React.memo(
|
||||||
}
|
}
|
||||||
, (prevProps, nextProps) => {
|
, (prevProps, nextProps) => {
|
||||||
console.log(prevProps.values?.Questions?.[prevProps?.parent_index]?.answers?.[prevProps?.index] === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers?.[prevProps?.index]);
|
console.log(prevProps.values?.Questions?.[prevProps?.parent_index]?.answers?.[prevProps?.index] === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers?.[prevProps?.index]);
|
||||||
console.log(2255);
|
|
||||||
|
|
||||||
return prevProps.values?.Questions?.[prevProps?.parent_index]?.answers?.[prevProps?.index] === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers?.[prevProps?.index];
|
return prevProps.values?.Questions?.[prevProps?.parent_index]?.answers?.[prevProps?.index] === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers?.[prevProps?.index];
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,6 @@ const Choices = React.memo( ({setFieldValue ,values,parent_index }:any) => {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}, (prevProps, nextProps) => {
|
}, (prevProps, nextProps) => {
|
||||||
console.log(prevProps.values?.Questions?.[prevProps?.parent_index]?.answers === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers);
|
|
||||||
console.log(22);
|
|
||||||
|
|
||||||
return prevProps.values?.Questions?.[prevProps?.parent_index]?.answers === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers;
|
return prevProps.values?.Questions?.[prevProps?.parent_index]?.answers === nextProps.values?.Questions?.[nextProps?.parent_index]?.answers;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { CombinationKeyEnum } from "../../../../../enums/CombinationKeyEnum";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import MainInputs from "./components/MainInputs";
|
import MainInputs from "./components/MainInputs";
|
||||||
import Questions from "./components/Questions";
|
import Questions from "./components/Questions";
|
||||||
|
import useUnsavedChangesWarning from "../../../../../Hooks/useUnsavedChangesWarning";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const formik = useFormikContext<any>();
|
const formik = useFormikContext<any>();
|
||||||
|
|
@ -64,6 +65,8 @@ const Form = () => {
|
||||||
|
|
||||||
|
|
||||||
const lastQuestions = formik?.values?.Questions?.length - 1;
|
const lastQuestions = formik?.values?.Questions?.length - 1;
|
||||||
|
|
||||||
|
////////////// hooks
|
||||||
useKeyCombination(
|
useKeyCombination(
|
||||||
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
|
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -77,8 +80,10 @@ const lastQuestions = formik?.values?.Questions?.length - 1;
|
||||||
handleAddQuestion(true);
|
handleAddQuestion(true);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
useUnsavedChangesWarning(formik.dirty);
|
||||||
|
|
||||||
|
|
||||||
|
//////////////
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
formik.resetForm()
|
formik.resetForm()
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import { CombinationKeyEnum } from "../../../../enums/CombinationKeyEnum";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import LaTeXInputMemo from "../../../../Components/LatextInput/LaTeXInputMemo";
|
import LaTeXInputMemo from "../../../../Components/LatextInput/LaTeXInputMemo";
|
||||||
import ImageBoxFieldMemo from "../../../../Components/CustomFields/ImageBoxField/ImageBoxFieldMemo";
|
import ImageBoxFieldMemo from "../../../../Components/CustomFields/ImageBoxField/ImageBoxFieldMemo";
|
||||||
|
import useUnsavedChangesWarning from "../../../../Hooks/useUnsavedChangesWarning";
|
||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
@ -33,6 +34,10 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////// hooks
|
||||||
|
|
||||||
|
|
||||||
useKeyCombination(
|
useKeyCombination(
|
||||||
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
|
{ ctrlKey: true, shiftKey: true, code: CombinationKeyEnum.CHOICE },
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -40,6 +45,10 @@ const Form = () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useUnsavedChangesWarning(formik.dirty);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Success) {
|
if (Success) {
|
||||||
formik.resetForm()
|
formik.resetForm()
|
||||||
|
|
@ -47,8 +56,6 @@ const Form = () => {
|
||||||
}
|
}
|
||||||
}, [Success]);
|
}, [Success]);
|
||||||
|
|
||||||
console.log(formik.errors);
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="w-100 exercise_form_container">
|
<Row className="w-100 exercise_form_container">
|
||||||
|
|
@ -58,7 +65,6 @@ const Form = () => {
|
||||||
component={LaTeXInputMemo}
|
component={LaTeXInputMemo}
|
||||||
label={t("input.answer_content")}
|
label={t("input.answer_content")}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Field
|
<Field
|
||||||
component={ImageBoxFieldMemo}
|
component={ImageBoxFieldMemo}
|
||||||
name="content_image"
|
name="content_image"
|
||||||
|
|
@ -87,7 +93,6 @@ const Form = () => {
|
||||||
autoSize={{ minRows: 2, maxRows: 10 }}
|
autoSize={{ minRows: 2, maxRows: 10 }}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
}
|
}
|
||||||
<SelectTag />
|
<SelectTag />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const FormField = ({ isLoading }: FormFieldType) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className="AuthForm">
|
<Form className="AuthForm">
|
||||||
{/* <Image style={{background:"#000"}} src="../App/Logo.png" /> */}
|
{/* <Image style={{background:"#000"}} src="../App/Logo.svg" /> */}
|
||||||
<h2>{t("تسجيل الدخول إلى حسابك")}</h2>
|
<h2>{t("تسجيل الدخول إلى حسابك")}</h2>
|
||||||
|
|
||||||
<ValidationField name="username" label="username" />
|
<ValidationField name="username" label="username" />
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import { Formik,Form, Field } from "formik";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import LaTeXInputMemo from "./LaTeXInputMemo";
|
import MathMLPreview from "./MathMLPreview";
|
||||||
|
|
||||||
const Dummy = () => {
|
const Dummy = () => {
|
||||||
const [t] = useTranslation();
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="DummyHomePage">
|
<div className="DummyHomePage">
|
||||||
|
|
||||||
|
<MathMLPreview/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const LaTeXInputMemo: React.FC<any> = React.memo(({ field ,form, label, ...prop
|
||||||
const { setFieldValue } = form;
|
const { setFieldValue } = form;
|
||||||
const [curCentValue, setCurrentValue] = useState(value)
|
const [curCentValue, setCurrentValue] = useState(value)
|
||||||
const handleChangeInput = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
const handleChangeInput = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||||
setFieldValue(name, e.target.value);
|
// setFieldValue(name, e.target.value);
|
||||||
setCurrentValue(e.target.value)
|
setCurrentValue(e.target.value)
|
||||||
};
|
};
|
||||||
console.log(name,"name");
|
console.log(name,"name");
|
||||||
|
|
@ -24,6 +24,7 @@ const LaTeXInputMemo: React.FC<any> = React.memo(({ field ,form, label, ...prop
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className='LaTeXInputArea'>
|
<div className='LaTeXInputArea'>
|
||||||
|
|
||||||
<TextArea
|
<TextArea
|
||||||
size="large"
|
size="large"
|
||||||
showCount
|
showCount
|
||||||
|
|
|
||||||
31
src/Pages/Home/MathMLPreview.tsx
Normal file
31
src/Pages/Home/MathMLPreview.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { MathJax, MathJaxContext } from 'better-react-mathjax';
|
||||||
|
|
||||||
|
const MathMLPreview = () => {
|
||||||
|
const [mathML, setMathML] = useState('<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>x</mi><mo>=</mo><mn>5</mn></math>');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Any logic to handle input updates and preview refresh can be added here
|
||||||
|
}, [mathML]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<textarea
|
||||||
|
value={mathML}
|
||||||
|
onChange={(e) => setMathML(e.target.value)}
|
||||||
|
rows={5}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
<MathJaxContext>
|
||||||
|
<div>
|
||||||
|
<h3>Preview:</h3>
|
||||||
|
<MathJax dynamic>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: mathML }} />
|
||||||
|
</MathJax>
|
||||||
|
</div>
|
||||||
|
</MathJaxContext>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MathMLPreview;
|
||||||
|
|
@ -166,16 +166,16 @@ export const menuItems: TMenuItem[] = [
|
||||||
// abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
// abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
// prevPath: 0,
|
// prevPath: 0,
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// header: "page_header.roles",
|
header: "page_header.roles",
|
||||||
// element: <Roles />,
|
element: <Roles />,
|
||||||
// icon: <FaUserShield />,
|
icon: <FaUserShield />,
|
||||||
// text: "sidebar.role",
|
text: "sidebar.role",
|
||||||
// path: `/${ABILITIES_ENUM?.ROLE}`,
|
path: `/${ABILITIES_ENUM?.ROLE}`,
|
||||||
// abilities: ABILITIES_ENUM?.ROLE,
|
abilities: ABILITIES_ENUM?.ROLE,
|
||||||
// abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
// prevPath: 0,
|
prevPath: 0,
|
||||||
// },
|
},
|
||||||
|
|
||||||
|
|
||||||
/// RESELLER /////
|
/// RESELLER /////
|
||||||
|
|
@ -310,8 +310,8 @@ export const CrudRoute: TCrudRoute[] = [
|
||||||
{
|
{
|
||||||
header: "page_header.permissions",
|
header: "page_header.permissions",
|
||||||
element: <Permissions />,
|
element: <Permissions />,
|
||||||
path: `/${ABILITIES_ENUM?.PERMISSIONS}`,
|
path: `/${ABILITIES_ENUM?.ROLE}/:${ParamsEnum?.ROLE_ID}/${ABILITIES_ENUM?.PERMISSIONS}`,
|
||||||
abilities: ABILITIES_ENUM?.PERMISSIONS,
|
abilities: ABILITIES_ENUM?.ROLE,
|
||||||
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
abilities_value: ABILITIES_VALUES_ENUM.INDEX,
|
||||||
prevPath: 0,
|
prevPath: 0,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -115,3 +115,6 @@ svg{
|
||||||
.LaTeXRenderer{
|
.LaTeXRenderer{
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
}
|
}
|
||||||
|
.ant-input,.LaTeXInputArea,input{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
:root {
|
:root {
|
||||||
--primary: #3d5ee1;
|
--primary: #0290d2;
|
||||||
--secondary: #303972;
|
--secondary: #303972;
|
||||||
--field: #b0d9ff;
|
--field: #b0d9ff;
|
||||||
--text: #202C4B;
|
--text: #202C4B;
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,7 @@
|
||||||
svg {
|
svg {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
};
|
||||||
@include Flex;
|
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border: 2px solid var(--borderColor);
|
border: 2px solid var(--borderColor);
|
||||||
|
|
@ -66,6 +65,7 @@
|
||||||
img {
|
img {
|
||||||
width: 1.5vw;
|
width: 1.5vw;
|
||||||
}
|
}
|
||||||
|
@include Flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,3 +101,8 @@
|
||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled{
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
@ -364,7 +364,7 @@
|
||||||
|
|
||||||
.LaTeXInput{
|
.LaTeXInput{
|
||||||
.text{
|
.text{
|
||||||
display: flex !important;
|
// display: flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
.error_message{
|
.error_message{
|
||||||
|
|
|
||||||
|
|
@ -153,3 +153,10 @@
|
||||||
.ant-pagination .ant-pagination-next .ant-pagination-item-link {
|
.ant-pagination .ant-pagination-next .ant-pagination-item-link {
|
||||||
rotate: 180deg !important;
|
rotate: 180deg !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.permissions_submit_button{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
@ -72,3 +72,14 @@
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.katex .msupsub{
|
||||||
|
text-align: end !important;
|
||||||
|
}
|
||||||
|
.mtight{
|
||||||
|
|
||||||
|
font-size: 10px !important;
|
||||||
|
}
|
||||||
|
.katex .delimcenter, .katex .op-symbol{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
21
src/api/Permissions.ts
Normal file
21
src/api/Permissions.ts
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
import useAddMutation from "./helper/useAddMutation";
|
||||||
|
import useDeleteMutation from "./helper/useDeleteMutation";
|
||||||
|
import useGetQuery from "./helper/useGetQuery";
|
||||||
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
|
|
||||||
|
const API = {
|
||||||
|
GET: "/permissions",
|
||||||
|
ADD: "/permissions",
|
||||||
|
DELETE: "/permissions",
|
||||||
|
UPDATE: "/permissions",
|
||||||
|
};
|
||||||
|
|
||||||
|
const KEY = "Permissions";
|
||||||
|
|
||||||
|
export const useGetAllPermissions = (params?: any, options?: any) =>
|
||||||
|
useGetQuery(KEY, API.GET, params, options);
|
||||||
|
export const useAddPermissions = () => useAddMutation(KEY, API.ADD);
|
||||||
|
export const useUpdatePermissions = (params?: any) =>
|
||||||
|
useUpdateMutation(KEY, API.GET);
|
||||||
|
export const useDeletePermissions = (params?: any) =>
|
||||||
|
useDeleteMutation(KEY, API.DELETE);
|
||||||
|
|
@ -27,3 +27,6 @@ function useAddMutation(
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useAddMutation;
|
export default useAddMutation;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,6 @@ export enum ABILITIES_VALUES_ENUM {
|
||||||
UPDATE = "update",
|
UPDATE = "update",
|
||||||
DELETE = "delete",
|
DELETE = "delete",
|
||||||
SHOW = "show",
|
SHOW = "show",
|
||||||
ME = "me",
|
PASS = "PASS"
|
||||||
IMPORT_STUDENT_DATA = "importStudentData",
|
|
||||||
MOVE_STUDENTS = "moveStudents",
|
|
||||||
IMPORT_STUDENTS = "importStudents",
|
|
||||||
OVERVIEW = "overview",
|
|
||||||
PRESENCE = "presence",
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@
|
||||||
"File_size_exceeds_2_MB_limit.":"حجم الملف يتجاوز الحد الأقصى البالغ 2 ميجابايت",
|
"File_size_exceeds_2_MB_limit.":"حجم الملف يتجاوز الحد الأقصى البالغ 2 ميجابايت",
|
||||||
"one_of_image_and_content_should_be_enter_in_answer":"يجب إدخال صورة أو محتوى واحد على الأقل في الاجابة",
|
"one_of_image_and_content_should_be_enter_in_answer":"يجب إدخال صورة أو محتوى واحد على الأقل في الاجابة",
|
||||||
"one_of_image_and_content_should_be_enter_in_question":"يجب إدخال صورة أو محتوى واحد على الأقل في السؤال",
|
"one_of_image_and_content_should_be_enter_in_question":"يجب إدخال صورة أو محتوى واحد على الأقل في السؤال",
|
||||||
"that_is_not_a_valid_mml":"هذا ليس mml صالح"
|
"that_is_not_a_valid_mml":"هذا ليس mml صالح",
|
||||||
|
"Are_you_sure_you_want_to_leave_Your_changes_may_not_be_saved":"هل أنت متأكد من أنك تريد المغادرة ؟ قد لا يتم حفظ التغييرات التي أجريتها"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"register_students": "تسجيل الطلاب",
|
"register_students": "تسجيل الطلاب",
|
||||||
|
|
@ -231,7 +232,8 @@
|
||||||
"edit":"تعديل",
|
"edit":"تعديل",
|
||||||
"delete":"حذف",
|
"delete":"حذف",
|
||||||
"read":"قراءة",
|
"read":"قراءة",
|
||||||
"managers":"مدراء"
|
"managers":"مدراء",
|
||||||
|
"show":"عرض"
|
||||||
},
|
},
|
||||||
"practical": {
|
"practical": {
|
||||||
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
"to_confirm_deletion_please_re_enter": "لتأكيد الحذف، يرجى إعادة الإدخال",
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export interface Response {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataTableProps {
|
export interface DataTableProps extends TableProps {
|
||||||
response: any;
|
response: any;
|
||||||
useColumns: any;
|
useColumns: any;
|
||||||
dataSource?: any;
|
dataSource?: any;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import { MathMLToLaTeX } from 'mathml-to-latex';
|
import { MathMLToLaTeX } from 'mathml-to-latex';
|
||||||
|
|
||||||
export function convertMathMLToLaTeX(mathml: string): string {
|
export function convertMathMLToLaTeX(mathml: string): string {
|
||||||
|
console.log(MathMLToLaTeX.convert(mathml));
|
||||||
|
console.log(mathml);
|
||||||
|
|
||||||
|
|
||||||
return MathMLToLaTeX.convert(mathml);
|
return MathMLToLaTeX.convert(mathml);
|
||||||
}
|
}
|
||||||
|
|
@ -132,6 +132,10 @@ export const canDeleteRole = hasAbility(
|
||||||
ABILITIES_VALUES_ENUM.DELETE,
|
ABILITIES_VALUES_ENUM.DELETE,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const canShowRole = hasAbility(
|
||||||
|
ABILITIES_ENUM.ROLE,
|
||||||
|
ABILITIES_VALUES_ENUM.SHOW,
|
||||||
|
);
|
||||||
/// Payment
|
/// Payment
|
||||||
|
|
||||||
export const canIndexPayment = hasAbility(
|
export const canIndexPayment = hasAbility(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user