UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: auth screens, error pages и новый канон внешних контуров
This commit is contained in:
parent
df68c96795
commit
c6ace8b9cc
|
|
@ -20,9 +20,9 @@
|
||||||
<path d="M251.986 120.208L219.029 103.439C217.488 102.654 216.238 100.767 216.238 99.2268C216.238 97.6866 217.488 97.0743 219.029 97.8598L251.986 114.629C253.527 115.414 254.777 117.301 254.777 118.841C254.777 120.381 253.527 120.993 251.986 120.208Z" fill="#E4E6E7"/>
|
<path d="M251.986 120.208L219.029 103.439C217.488 102.654 216.238 100.767 216.238 99.2268C216.238 97.6866 217.488 97.0743 219.029 97.8598L251.986 114.629C253.527 115.414 254.777 117.301 254.777 118.841C254.777 120.381 253.527 120.993 251.986 120.208Z" fill="#E4E6E7"/>
|
||||||
<path d="M194.035 105.963L161.078 89.1941C159.537 88.4085 158.287 86.5219 158.287 84.9818C158.287 83.4416 159.537 82.8292 161.078 83.6148L194.035 100.384C195.576 101.169 196.826 103.056 196.826 104.596C196.826 106.136 195.576 106.748 194.035 105.963Z" fill="#E4E6E7"/>
|
<path d="M194.035 105.963L161.078 89.1941C159.537 88.4085 158.287 86.5219 158.287 84.9818C158.287 83.4416 159.537 82.8292 161.078 83.6148L194.035 100.384C195.576 101.169 196.826 103.056 196.826 104.596C196.826 106.136 195.576 106.748 194.035 105.963Z" fill="#E4E6E7"/>
|
||||||
<path d="M150.992 100.192L147.799 98.565C147.168 98.2433 146.66 97.4764 146.66 96.8454V93.6538C146.66 93.0228 147.174 92.7754 147.799 93.0909L150.992 94.7176C151.623 95.0393 152.13 95.8063 152.13 96.4372V99.6289C152.13 100.26 151.617 100.507 150.992 100.192Z" fill="#E4E6E7"/>
|
<path d="M150.992 100.192L147.799 98.565C147.168 98.2433 146.66 97.4764 146.66 96.8454V93.6538C146.66 93.0228 147.174 92.7754 147.799 93.0909L150.992 94.7176C151.623 95.0393 152.13 95.8063 152.13 96.4372V99.6289C152.13 100.26 151.617 100.507 150.992 100.192Z" fill="#E4E6E7"/>
|
||||||
<path d="M65.971 0.698973L203.091 70.5264C206.383 72.2027 208.462 75.5861 208.462 79.285V197.427C208.456 201.095 204.576 203.47 201.302 201.806L64.1951 131.966C60.9031 130.29 58.8301 126.907 58.8301 123.208V5.07826C58.8301 1.4103 62.7099 -0.964911 65.9772 0.698973H65.971Z" fill="#2892CC" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M65.971 0.698973L203.091 70.5264C206.383 72.2027 208.462 75.5861 208.462 79.285V197.427C208.456 201.095 204.576 203.47 201.302 201.806L64.1951 131.966C60.9031 130.29 58.8301 126.907 58.8301 123.208V5.07826C58.8301 1.4103 62.7099 -0.964911 65.9772 0.698973H65.971Z" fill="#C3FF66" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M62.8831 2.28247L200.003 72.1099C203.295 73.7862 205.374 77.1696 205.374 80.8685V199.01C205.368 202.678 201.488 205.054 198.214 203.39L61.1072 133.55C57.8152 131.874 55.7422 128.49 55.7422 124.791V6.66176C55.7422 2.99379 59.6221 0.618585 62.8893 2.28247H62.8831Z" fill="#0F0F10" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M62.8831 2.28247L200.003 72.1099C203.295 73.7862 205.374 77.1696 205.374 80.8685V199.01C205.368 202.678 201.488 205.054 198.214 203.39L61.1072 133.55C57.8152 131.874 55.7422 128.49 55.7422 124.791V6.66176C55.7422 2.99379 59.6221 0.618585 62.8893 2.28247H62.8831Z" fill="#0F0F10" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M198.381 200.569L63.0869 131.725C60.5437 130.432 58.4583 126.783 58.4274 123.573L58.2912 19.6141C58.2665 16.41 60.3023 14.8574 62.8518 16.1502L198.146 84.9941C200.689 86.2869 202.775 89.9363 202.806 93.1466L202.942 197.105C202.966 200.309 200.931 201.862 198.381 200.569Z" fill="#0F0F10" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M198.381 200.569L63.0869 131.725C60.5437 130.432 58.4583 126.783 58.4274 123.573L58.2912 19.6141C58.2665 16.41 60.3023 14.8574 62.8518 16.1502L198.146 84.9941C200.689 86.2869 202.775 89.9363 202.806 93.1466L202.942 197.105C202.966 200.309 200.931 201.862 198.381 200.569Z" fill="#0F0F10" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M153.084 208.425C153.084 208.957 153.356 209.482 153.901 209.761L157.168 211.425L158.041 211.87C159.328 212.526 160.844 212.526 162.131 211.87L163.016 211.418L166.295 209.754C166.84 209.476 167.118 208.95 167.118 208.418C167.118 207.886 166.846 207.355 166.295 207.076L162.131 204.967C160.844 204.317 159.328 204.317 158.047 204.973L153.907 207.082C153.362 207.361 153.09 207.893 153.09 208.418L153.084 208.425Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M153.084 208.425C153.084 208.957 153.356 209.482 153.901 209.761L157.168 211.425L158.041 211.87C159.328 212.526 160.844 212.526 162.131 211.87L163.016 211.418L166.295 209.754C166.84 209.476 167.118 208.95 167.118 208.418C167.118 207.886 166.846 207.355 166.295 207.076L162.131 204.967C160.844 204.317 159.328 204.317 158.047 204.973L153.907 207.082C153.362 207.361 153.09 207.893 153.09 208.418L153.084 208.425Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M153.084 208.425V214.431C153.084 214.963 153.357 215.488 153.901 215.767L158.035 217.876C159.322 218.532 160.838 218.532 162.125 217.876L166.289 215.761C166.834 215.482 167.112 214.956 167.112 214.424V208.418C167.112 208.944 166.834 209.476 166.289 209.754L163.01 211.418L162.125 211.87C160.838 212.526 159.322 212.526 158.035 211.87L157.162 211.425L153.895 209.761C153.35 209.482 153.078 208.95 153.078 208.425H153.084Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M153.084 208.425V214.431C153.084 214.963 153.357 215.488 153.901 215.767L158.035 217.876C159.322 218.532 160.838 218.532 162.125 217.876L166.289 215.761C166.834 215.482 167.112 214.956 167.112 214.424V208.418C167.112 208.944 166.834 209.476 166.289 209.754L163.01 211.418L162.125 211.87C160.838 212.526 159.322 212.526 158.035 211.87L157.162 211.425L153.895 209.761C153.35 209.482 153.078 208.95 153.078 208.425H153.084Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M163.418 213.682C163.418 214.214 163.69 214.74 164.235 215.018L167.502 216.682L168.375 217.128C169.662 217.783 171.178 217.783 172.465 217.128L173.35 216.676L176.629 215.012C177.174 214.734 177.452 214.208 177.452 213.676C177.452 213.144 177.18 212.612 176.629 212.334L172.465 210.225C171.178 209.575 169.662 209.575 168.381 210.231L164.241 212.34C163.696 212.618 163.424 213.15 163.424 213.676L163.418 213.682Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M163.418 213.682C163.418 214.214 163.69 214.74 164.235 215.018L167.502 216.682L168.375 217.128C169.662 217.783 171.178 217.783 172.465 217.128L173.35 216.676L176.629 215.012C177.174 214.734 177.452 214.208 177.452 213.676C177.452 213.144 177.18 212.612 176.629 212.334L172.465 210.225C171.178 209.575 169.662 209.575 168.381 210.231L164.241 212.34C163.696 212.618 163.424 213.15 163.424 213.676L163.418 213.682Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
<path d="M371.205 121.55C371.205 118.6 373.42 115.655 377.839 113.404L446.921 78.2211C455.77 73.7181 470.114 73.7181 478.957 78.2211L548.039 113.404C552.47 115.662 554.673 118.618 554.673 121.575C554.673 124.531 552.458 127.47 548.039 129.721L478.957 164.904C470.108 169.407 455.764 169.407 446.921 164.904L377.839 129.721C373.408 127.463 371.205 124.507 371.205 121.55Z" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M371.205 121.55C371.205 118.6 373.42 115.655 377.839 113.404L446.921 78.2211C455.77 73.7181 470.114 73.7181 478.957 78.2211L548.039 113.404C552.47 115.662 554.673 118.618 554.673 121.575C554.673 124.531 552.458 127.47 548.039 129.721L478.957 164.904C470.108 169.407 455.764 169.407 446.921 164.904L377.839 129.721C373.408 127.463 371.205 124.507 371.205 121.55Z" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M554.68 121.575V232.053" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M554.68 121.575V232.053" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M371.205 121.55V231.082" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M371.205 121.55V231.082" stroke="#4E555A" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M131.613 92.7631C131.613 91.4147 132.782 91.1301 133.772 92.2373L150.071 110.453C151.334 111.864 152.132 113.843 152.132 115.563V131.379C152.132 132.727 150.962 133.012 149.972 131.905L140.808 121.661V109.798C140.808 108.078 140.01 106.099 138.747 104.689L131.613 96.7156V92.7693V92.7631ZM108.971 81.2272C108.971 79.8788 110.14 79.5943 111.13 80.7015L120.289 90.9384V102.808C120.289 104.528 121.087 106.507 122.349 107.917L129.49 115.897V119.843C129.49 121.191 128.321 121.476 127.33 120.369L111.031 102.153C109.769 100.742 108.971 98.763 108.971 97.0434V81.2272ZM120.289 86.9921C120.289 85.6436 121.458 85.3591 122.448 86.4663L131.613 96.7032V108.573C131.613 110.293 132.411 112.272 133.673 113.682L140.808 121.655V125.608C140.808 126.956 139.638 127.241 138.648 126.134L129.49 115.897V104.027C129.49 102.307 128.692 100.328 127.429 98.9176L120.289 90.9384V86.9921Z" fill="#2892CC"/>
|
<path d="M131.613 92.7631C131.613 91.4147 132.782 91.1301 133.772 92.2373L150.071 110.453C151.334 111.864 152.132 113.843 152.132 115.563V131.379C152.132 132.727 150.962 133.012 149.972 131.905L140.808 121.661V109.798C140.808 108.078 140.01 106.099 138.747 104.689L131.613 96.7156V92.7693V92.7631ZM108.971 81.2272C108.971 79.8788 110.14 79.5943 111.13 80.7015L120.289 90.9384V102.808C120.289 104.528 121.087 106.507 122.349 107.917L129.49 115.897V119.843C129.49 121.191 128.321 121.476 127.33 120.369L111.031 102.153C109.769 100.742 108.971 98.763 108.971 97.0434V81.2272ZM120.289 86.9921C120.289 85.6436 121.458 85.3591 122.448 86.4663L131.613 96.7032V108.573C131.613 110.293 132.411 112.272 133.673 113.682L140.808 121.655V125.608C140.808 126.956 139.638 127.241 138.648 126.134L129.49 115.897V104.027C129.49 102.307 128.692 100.328 127.429 98.9176L120.289 90.9384V86.9921Z" fill="#C3FF66"/>
|
||||||
<path d="M0.154297 120.443C0.154297 121.179 0.537952 121.921 1.29289 122.305L5.84725 124.63L7.06009 125.249C8.84842 126.164 10.9709 126.164 12.7592 125.249L13.9968 124.624L18.5698 122.299C19.3309 121.915 19.7145 121.179 19.7145 120.443C19.7145 119.701 19.3371 118.958 18.5698 118.569L12.7592 115.624C10.9709 114.721 8.85461 114.721 7.06628 115.637L1.29908 118.581C0.537952 118.971 0.160485 119.707 0.160485 120.443H0.154297Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M0.154297 120.443C0.154297 121.179 0.537952 121.921 1.29289 122.305L5.84725 124.63L7.06009 125.249C8.84842 126.164 10.9709 126.164 12.7592 125.249L13.9968 124.624L18.5698 122.299C19.3309 121.915 19.7145 121.179 19.7145 120.443C19.7145 119.701 19.3371 118.958 18.5698 118.569L12.7592 115.624C10.9709 114.721 8.85461 114.721 7.06628 115.637L1.29908 118.581C0.537952 118.971 0.160485 119.707 0.160485 120.443H0.154297Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M0.154625 120.443V128.812C0.154625 129.548 0.538281 130.29 1.29322 130.674L7.05423 133.612C8.84256 134.527 10.965 134.527 12.7534 133.612L18.5639 130.661C19.325 130.278 19.7087 129.542 19.7087 128.806V120.437C19.7087 121.173 19.325 121.909 18.5639 122.292L13.991 124.618L12.7534 125.243C10.965 126.158 8.84256 126.152 7.05423 125.243L5.84139 124.624L1.28703 122.299C0.525905 121.909 0.148438 121.173 0.148438 120.437L0.154625 120.443Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M0.154625 120.443V128.812C0.154625 129.548 0.538281 130.29 1.29322 130.674L7.05423 133.612C8.84256 134.527 10.965 134.527 12.7534 133.612L18.5639 130.661C19.325 130.278 19.7087 129.542 19.7087 128.806V120.437C19.7087 121.173 19.325 121.909 18.5639 122.292L13.991 124.618L12.7534 125.243C10.965 126.158 8.84256 126.152 7.05423 125.243L5.84139 124.624L1.28703 122.299C0.525905 121.909 0.148438 121.173 0.148438 120.437L0.154625 120.443Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M346.904 96.3506C346.904 97.0867 347.288 97.8289 348.043 98.2124L352.597 100.538L353.81 101.157C355.598 102.072 357.721 102.072 359.509 101.157L360.747 100.532L365.32 98.2062C366.081 97.8227 366.465 97.0867 366.465 96.3506C366.465 95.6084 366.087 94.8661 365.32 94.4764L359.509 91.5322C357.721 90.6291 355.605 90.6291 353.816 91.5445L348.049 94.4888C347.288 94.8785 346.91 95.6145 346.91 96.3506H346.904Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M346.904 96.3506C346.904 97.0867 347.288 97.8289 348.043 98.2124L352.597 100.538L353.81 101.157C355.598 102.072 357.721 102.072 359.509 101.157L360.747 100.532L365.32 98.2062C366.081 97.8227 366.465 97.0867 366.465 96.3506C366.465 95.6084 366.087 94.8661 365.32 94.4764L359.509 91.5322C357.721 90.6291 355.605 90.6291 353.816 91.5445L348.049 94.4888C347.288 94.8785 346.91 95.6145 346.91 96.3506H346.904Z" fill="#0F0F10" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
|
@ -20,9 +20,9 @@
|
||||||
<path d="M251.986 120.208L219.029 103.439C217.488 102.654 216.238 100.767 216.238 99.2268C216.238 97.6866 217.488 97.0743 219.029 97.8598L251.986 114.629C253.527 115.414 254.777 117.301 254.777 118.841C254.777 120.381 253.527 120.993 251.986 120.208Z" fill="#CCD0D2"/>
|
<path d="M251.986 120.208L219.029 103.439C217.488 102.654 216.238 100.767 216.238 99.2268C216.238 97.6866 217.488 97.0743 219.029 97.8598L251.986 114.629C253.527 115.414 254.777 117.301 254.777 118.841C254.777 120.381 253.527 120.993 251.986 120.208Z" fill="#CCD0D2"/>
|
||||||
<path d="M194.035 105.963L161.078 89.1941C159.537 88.4085 158.287 86.5219 158.287 84.9818C158.287 83.4416 159.537 82.8292 161.078 83.6148L194.035 100.384C195.576 101.169 196.826 103.056 196.826 104.596C196.826 106.136 195.576 106.748 194.035 105.963Z" fill="#CCD0D2"/>
|
<path d="M194.035 105.963L161.078 89.1941C159.537 88.4085 158.287 86.5219 158.287 84.9818C158.287 83.4416 159.537 82.8292 161.078 83.6148L194.035 100.384C195.576 101.169 196.826 103.056 196.826 104.596C196.826 106.136 195.576 106.748 194.035 105.963Z" fill="#CCD0D2"/>
|
||||||
<path d="M150.992 100.192L147.799 98.565C147.168 98.2433 146.66 97.4764 146.66 96.8454V93.6538C146.66 93.0228 147.174 92.7754 147.799 93.0909L150.992 94.7176C151.623 95.0393 152.13 95.8063 152.13 96.4372V99.6289C152.13 100.26 151.617 100.507 150.992 100.192Z" fill="#CCD0D2"/>
|
<path d="M150.992 100.192L147.799 98.565C147.168 98.2433 146.66 97.4764 146.66 96.8454V93.6538C146.66 93.0228 147.174 92.7754 147.799 93.0909L150.992 94.7176C151.623 95.0393 152.13 95.8063 152.13 96.4372V99.6289C152.13 100.26 151.617 100.507 150.992 100.192Z" fill="#CCD0D2"/>
|
||||||
<path d="M65.971 0.698973L203.091 70.5264C206.383 72.2027 208.462 75.5861 208.462 79.285V197.427C208.456 201.095 204.576 203.47 201.302 201.806L64.1951 131.966C60.9031 130.29 58.8301 126.907 58.8301 123.208V5.07826C58.8301 1.4103 62.7099 -0.964911 65.9772 0.698973H65.971Z" fill="#2892CC" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M65.971 0.698973L203.091 70.5264C206.383 72.2027 208.462 75.5861 208.462 79.285V197.427C208.456 201.095 204.576 203.47 201.302 201.806L64.1951 131.966C60.9031 130.29 58.8301 126.907 58.8301 123.208V5.07826C58.8301 1.4103 62.7099 -0.964911 65.9772 0.698973H65.971Z" fill="#C3FF66" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M62.8831 2.28247L200.003 72.1099C203.295 73.7862 205.374 77.1696 205.374 80.8685V199.01C205.368 202.678 201.488 205.054 198.214 203.39L61.1072 133.55C57.8152 131.874 55.7422 128.49 55.7422 124.791V6.66176C55.7422 2.99379 59.6221 0.618585 62.8893 2.28247H62.8831Z" fill="white" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M62.8831 2.28247L200.003 72.1099C203.295 73.7862 205.374 77.1696 205.374 80.8685V199.01C205.368 202.678 201.488 205.054 198.214 203.39L61.1072 133.55C57.8152 131.874 55.7422 128.49 55.7422 124.791V6.66176C55.7422 2.99379 59.6221 0.618585 62.8893 2.28247H62.8831Z" fill="white" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M198.381 200.569L63.0869 131.725C60.5437 130.432 58.4583 126.783 58.4274 123.573L58.2912 19.6141C58.2665 16.41 60.3023 14.8574 62.8518 16.1502L198.146 84.9941C200.689 86.2869 202.775 89.9363 202.806 93.1466L202.942 197.105C202.966 200.309 200.931 201.862 198.381 200.569Z" fill="white" stroke="#2892CC" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M198.381 200.569L63.0869 131.725C60.5437 130.432 58.4583 126.783 58.4274 123.573L58.2912 19.6141C58.2665 16.41 60.3023 14.8574 62.8518 16.1502L198.146 84.9941C200.689 86.2869 202.775 89.9363 202.806 93.1466L202.942 197.105C202.966 200.309 200.931 201.862 198.381 200.569Z" fill="white" stroke="#C3FF66" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M153.084 208.425C153.084 208.957 153.356 209.482 153.901 209.761L157.168 211.425L158.041 211.87C159.328 212.526 160.844 212.526 162.131 211.87L163.016 211.418L166.295 209.754C166.84 209.476 167.118 208.95 167.118 208.418C167.118 207.886 166.846 207.355 166.295 207.076L162.131 204.967C160.844 204.317 159.328 204.317 158.047 204.973L153.907 207.082C153.362 207.361 153.09 207.893 153.09 208.418L153.084 208.425Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M153.084 208.425C153.084 208.957 153.356 209.482 153.901 209.761L157.168 211.425L158.041 211.87C159.328 212.526 160.844 212.526 162.131 211.87L163.016 211.418L166.295 209.754C166.84 209.476 167.118 208.95 167.118 208.418C167.118 207.886 166.846 207.355 166.295 207.076L162.131 204.967C160.844 204.317 159.328 204.317 158.047 204.973L153.907 207.082C153.362 207.361 153.09 207.893 153.09 208.418L153.084 208.425Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M153.084 208.425V214.431C153.084 214.963 153.357 215.488 153.901 215.767L158.035 217.876C159.322 218.532 160.838 218.532 162.125 217.876L166.289 215.761C166.834 215.482 167.112 214.956 167.112 214.424V208.418C167.112 208.944 166.834 209.476 166.289 209.754L163.01 211.418L162.125 211.87C160.838 212.526 159.322 212.526 158.035 211.87L157.162 211.425L153.895 209.761C153.35 209.482 153.078 208.95 153.078 208.425H153.084Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M153.084 208.425V214.431C153.084 214.963 153.357 215.488 153.901 215.767L158.035 217.876C159.322 218.532 160.838 218.532 162.125 217.876L166.289 215.761C166.834 215.482 167.112 214.956 167.112 214.424V208.418C167.112 208.944 166.834 209.476 166.289 209.754L163.01 211.418L162.125 211.87C160.838 212.526 159.322 212.526 158.035 211.87L157.162 211.425L153.895 209.761C153.35 209.482 153.078 208.95 153.078 208.425H153.084Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M163.418 213.682C163.418 214.214 163.69 214.74 164.235 215.018L167.502 216.682L168.375 217.128C169.662 217.783 171.178 217.783 172.465 217.128L173.35 216.676L176.629 215.012C177.174 214.734 177.452 214.208 177.452 213.676C177.452 213.144 177.18 212.612 176.629 212.334L172.465 210.225C171.178 209.575 169.662 209.575 168.381 210.231L164.241 212.34C163.696 212.618 163.424 213.15 163.424 213.676L163.418 213.682Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M163.418 213.682C163.418 214.214 163.69 214.74 164.235 215.018L167.502 216.682L168.375 217.128C169.662 217.783 171.178 217.783 172.465 217.128L173.35 216.676L176.629 215.012C177.174 214.734 177.452 214.208 177.452 213.676C177.452 213.144 177.18 212.612 176.629 212.334L172.465 210.225C171.178 209.575 169.662 209.575 168.381 210.231L164.241 212.34C163.696 212.618 163.424 213.15 163.424 213.676L163.418 213.682Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
<path d="M371.205 121.55C371.205 118.6 373.42 115.655 377.839 113.404L446.921 78.2211C455.77 73.7181 470.114 73.7181 478.957 78.2211L548.039 113.404C552.47 115.662 554.673 118.618 554.673 121.575C554.673 124.531 552.458 127.47 548.039 129.721L478.957 164.904C470.108 169.407 455.764 169.407 446.921 164.904L377.839 129.721C373.408 127.463 371.205 124.507 371.205 121.55Z" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M371.205 121.55C371.205 118.6 373.42 115.655 377.839 113.404L446.921 78.2211C455.77 73.7181 470.114 73.7181 478.957 78.2211L548.039 113.404C552.47 115.662 554.673 118.618 554.673 121.575C554.673 124.531 552.458 127.47 548.039 129.721L478.957 164.904C470.108 169.407 455.764 169.407 446.921 164.904L377.839 129.721C373.408 127.463 371.205 124.507 371.205 121.55Z" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M554.68 121.575V232.053" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M554.68 121.575V232.053" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M371.205 121.55V231.082" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
<path d="M371.205 121.55V231.082" stroke="#99A1A6" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="3 5 3 5"/>
|
||||||
<path d="M131.613 92.7631C131.613 91.4147 132.782 91.1301 133.772 92.2373L150.071 110.453C151.334 111.864 152.132 113.843 152.132 115.563V131.379C152.132 132.727 150.962 133.012 149.972 131.905L140.808 121.661V109.798C140.808 108.078 140.01 106.099 138.747 104.689L131.613 96.7156V92.7693V92.7631ZM108.971 81.2272C108.971 79.8788 110.14 79.5943 111.13 80.7015L120.289 90.9384V102.808C120.289 104.528 121.087 106.507 122.349 107.917L129.49 115.897V119.843C129.49 121.191 128.321 121.476 127.33 120.369L111.031 102.153C109.769 100.742 108.971 98.763 108.971 97.0434V81.2272ZM120.289 86.9921C120.289 85.6436 121.458 85.3591 122.448 86.4663L131.613 96.7032V108.573C131.613 110.293 132.411 112.272 133.673 113.682L140.808 121.655V125.608C140.808 126.956 139.638 127.241 138.648 126.134L129.49 115.897V104.027C129.49 102.307 128.692 100.328 127.429 98.9176L120.289 90.9384V86.9921Z" fill="#2892CC"/>
|
<path d="M131.613 92.7631C131.613 91.4147 132.782 91.1301 133.772 92.2373L150.071 110.453C151.334 111.864 152.132 113.843 152.132 115.563V131.379C152.132 132.727 150.962 133.012 149.972 131.905L140.808 121.661V109.798C140.808 108.078 140.01 106.099 138.747 104.689L131.613 96.7156V92.7693V92.7631ZM108.971 81.2272C108.971 79.8788 110.14 79.5943 111.13 80.7015L120.289 90.9384V102.808C120.289 104.528 121.087 106.507 122.349 107.917L129.49 115.897V119.843C129.49 121.191 128.321 121.476 127.33 120.369L111.031 102.153C109.769 100.742 108.971 98.763 108.971 97.0434V81.2272ZM120.289 86.9921C120.289 85.6436 121.458 85.3591 122.448 86.4663L131.613 96.7032V108.573C131.613 110.293 132.411 112.272 133.673 113.682L140.808 121.655V125.608C140.808 126.956 139.638 127.241 138.648 126.134L129.49 115.897V104.027C129.49 102.307 128.692 100.328 127.429 98.9176L120.289 90.9384V86.9921Z" fill="#C3FF66"/>
|
||||||
<path d="M0.154297 120.443C0.154297 121.179 0.537952 121.921 1.29289 122.305L5.84725 124.63L7.06009 125.249C8.84842 126.164 10.9709 126.164 12.7592 125.249L13.9968 124.624L18.5698 122.299C19.3309 121.915 19.7145 121.179 19.7145 120.443C19.7145 119.701 19.3371 118.958 18.5698 118.569L12.7592 115.624C10.9709 114.721 8.85461 114.721 7.06628 115.637L1.29908 118.581C0.537952 118.971 0.160485 119.707 0.160485 120.443H0.154297Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M0.154297 120.443C0.154297 121.179 0.537952 121.921 1.29289 122.305L5.84725 124.63L7.06009 125.249C8.84842 126.164 10.9709 126.164 12.7592 125.249L13.9968 124.624L18.5698 122.299C19.3309 121.915 19.7145 121.179 19.7145 120.443C19.7145 119.701 19.3371 118.958 18.5698 118.569L12.7592 115.624C10.9709 114.721 8.85461 114.721 7.06628 115.637L1.29908 118.581C0.537952 118.971 0.160485 119.707 0.160485 120.443H0.154297Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M0.154625 120.443V128.812C0.154625 129.548 0.538281 130.29 1.29322 130.674L7.05423 133.612C8.84256 134.527 10.965 134.527 12.7534 133.612L18.5639 130.661C19.325 130.278 19.7087 129.542 19.7087 128.806V120.437C19.7087 121.173 19.325 121.909 18.5639 122.292L13.991 124.618L12.7534 125.243C10.965 126.158 8.84256 126.152 7.05423 125.243L5.84139 124.624L1.28703 122.299C0.525905 121.909 0.148438 121.173 0.148438 120.437L0.154625 120.443Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M0.154625 120.443V128.812C0.154625 129.548 0.538281 130.29 1.29322 130.674L7.05423 133.612C8.84256 134.527 10.965 134.527 12.7534 133.612L18.5639 130.661C19.325 130.278 19.7087 129.542 19.7087 128.806V120.437C19.7087 121.173 19.325 121.909 18.5639 122.292L13.991 124.618L12.7534 125.243C10.965 126.158 8.84256 126.152 7.05423 125.243L5.84139 124.624L1.28703 122.299C0.525905 121.909 0.148438 121.173 0.148438 120.437L0.154625 120.443Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M346.904 96.3506C346.904 97.0867 347.288 97.8289 348.043 98.2124L352.597 100.538L353.81 101.157C355.598 102.072 357.721 102.072 359.509 101.157L360.747 100.532L365.32 98.2062C366.081 97.8227 366.465 97.0867 366.465 96.3506C366.465 95.6084 366.087 94.8661 365.32 94.4764L359.509 91.5322C357.721 90.6291 355.605 90.6291 353.816 91.5445L348.049 94.4888C347.288 94.8785 346.91 95.6145 346.91 96.3506H346.904Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M346.904 96.3506C346.904 97.0867 347.288 97.8289 348.043 98.2124L352.597 100.538L353.81 101.157C355.598 102.072 357.721 102.072 359.509 101.157L360.747 100.532L365.32 98.2062C366.081 97.8227 366.465 97.0867 366.465 96.3506C366.465 95.6084 366.087 94.8661 365.32 94.4764L359.509 91.5322C357.721 90.6291 355.605 90.6291 353.816 91.5445L348.049 94.4888C347.288 94.8785 346.91 95.6145 346.91 96.3506H346.904Z" fill="white" stroke="#808A8F" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
|
@ -4,11 +4,9 @@
|
||||||
* See the LICENSE file for details.
|
* See the LICENSE file for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// plane imports
|
|
||||||
import { isRouteErrorResponse } from "react-router";
|
import { isRouteErrorResponse } from "react-router";
|
||||||
import { Banner } from "@plane/propel/banner";
|
import { Banner } from "@plane/propel/banner";
|
||||||
import { Button } from "@plane/propel/button";
|
import { Button } from "@plane/propel/button";
|
||||||
import { Card, ECardVariant } from "@plane/propel/card";
|
|
||||||
import { InfoFillIcon } from "@plane/propel/icons";
|
import { InfoFillIcon } from "@plane/propel/icons";
|
||||||
|
|
||||||
interface ErrorActionsProps {
|
interface ErrorActionsProps {
|
||||||
|
|
@ -19,12 +17,12 @@ interface ErrorActionsProps {
|
||||||
function ErrorActions({ onGoHome, onReload }: ErrorActionsProps) {
|
function ErrorActions({ onGoHome, onReload }: ErrorActionsProps) {
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-3 pt-2">
|
<div className="flex gap-3 pt-2">
|
||||||
<Button variant="primary" size="lg" onClick={onGoHome}>
|
<Button variant="primary" size="lg" onClick={onGoHome} className="nodedc-error-primary">
|
||||||
Go to home
|
На главную
|
||||||
</Button>
|
</Button>
|
||||||
{onReload && (
|
{onReload && (
|
||||||
<Button variant="secondary" size="lg" onClick={onReload}>
|
<Button variant="secondary" size="lg" onClick={onReload} className="nodedc-empty-state-secondary">
|
||||||
Reload page
|
Обновить страницу
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -37,19 +35,17 @@ interface DevErrorComponentProps {
|
||||||
onReload: () => void;
|
onReload: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ErrorShell = ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<div className="nodedc-error-shell transition-none">{children}</div>
|
||||||
|
);
|
||||||
|
|
||||||
export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorComponentProps) {
|
export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorComponentProps) {
|
||||||
if (isRouteErrorResponse(error)) {
|
if (isRouteErrorResponse(error)) {
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-start justify-center bg-surface-2 p-6 transition-none">
|
<div className="flex min-h-screen items-start justify-center bg-surface-2 p-6 transition-none">
|
||||||
<div className="mt-12 w-full max-w-4xl space-y-4 transition-none">
|
<div className="mt-12 w-full max-w-4xl space-y-4 transition-none">
|
||||||
<Banner
|
<Banner variant="error" icon={<InfoFillIcon className="size-5" />} title="Ошибка маршрута" animationDuration={0} />
|
||||||
variant="error"
|
<ErrorShell>
|
||||||
icon={<InfoFillIcon className="size-5" />}
|
|
||||||
title="Route Error Response"
|
|
||||||
animationDuration={0}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Card variant={ECardVariant.WITH_SHADOW} className="!p-6 transition-none">
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="mb-2 text-20 font-semibold text-danger-primary">
|
<h2 className="mb-2 text-20 font-semibold text-danger-primary">
|
||||||
|
|
@ -59,15 +55,15 @@ export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorCompone
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Error Data</h3>
|
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Данные ошибки</h3>
|
||||||
<div className="rounded-md bg-layer-1 p-4">
|
<div className="rounded-[1.1rem] bg-white/5 p-4">
|
||||||
<p className="font-code text-13 text-secondary">{error.data}</p>
|
<p className="font-code text-13 text-secondary">{error.data}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</ErrorShell>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -80,27 +76,27 @@ export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorCompone
|
||||||
<Banner
|
<Banner
|
||||||
variant="error"
|
variant="error"
|
||||||
icon={<InfoFillIcon className="size-5" />}
|
icon={<InfoFillIcon className="size-5" />}
|
||||||
title="Runtime Error"
|
title="Ошибка выполнения"
|
||||||
animationDuration={0}
|
animationDuration={0}
|
||||||
/>
|
/>
|
||||||
<Card variant={ECardVariant.WITH_SHADOW} className="!p-6 transition-none">
|
<ErrorShell>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="mb-2 text-20 font-semibold text-danger-primary">Error</h2>
|
<h2 className="mb-2 text-20 font-semibold text-danger-primary">Ошибка</h2>
|
||||||
<div className="bg-subtle-1 h-px w-full" />
|
<div className="bg-subtle-1 h-px w-full" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Message</h3>
|
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Сообщение</h3>
|
||||||
<div className="rounded-md bg-layer-1 p-4">
|
<div className="rounded-[1.1rem] bg-white/5 p-4">
|
||||||
<p className="text-13 font-medium text-primary">{error.message}</p>
|
<p className="text-13 font-medium text-primary">{error.message}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error.stack && (
|
{error.stack && (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Stack Trace</h3>
|
<h3 className="text-13 font-medium tracking-wide text-tertiary uppercase">Стек вызовов</h3>
|
||||||
<div className="max-h-96 overflow-auto rounded-md border border-subtle bg-layer-1">
|
<div className="max-h-96 overflow-auto rounded-[1.1rem] bg-white/5">
|
||||||
<pre className="p-4 font-code text-11 break-words whitespace-pre-wrap text-secondary">
|
<pre className="p-4 font-code text-11 break-words whitespace-pre-wrap text-secondary">
|
||||||
{error.stack}
|
{error.stack}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
@ -110,20 +106,20 @@ export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorCompone
|
||||||
|
|
||||||
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</ErrorShell>
|
||||||
|
|
||||||
<Card variant={ECardVariant.WITHOUT_SHADOW} className="bg-layer-1 !p-4 transition-none">
|
<div className="nodedc-external-panel p-4 transition-none">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<InfoFillIcon className="mt-0.5 size-5 flex-shrink-0 text-tertiary" />
|
<InfoFillIcon className="mt-0.5 size-5 flex-shrink-0 text-tertiary" />
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<p className="text-13 font-medium text-secondary">Development Mode</p>
|
<p className="text-13 font-medium text-secondary">Режим разработки</p>
|
||||||
<p className="text-11 text-tertiary">
|
<p className="text-11 text-tertiary">
|
||||||
This detailed error view is only visible in development. In production, users will see a friendly
|
Этот подробный экран ошибок виден только в разработке. В production пользователи увидят упрощённую
|
||||||
error page.
|
страницу ошибки.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -132,29 +128,24 @@ export function DevErrorComponent({ error, onGoHome, onReload }: DevErrorCompone
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen items-start justify-center bg-surface-2 p-6 transition-none">
|
<div className="flex min-h-screen items-start justify-center bg-surface-2 p-6 transition-none">
|
||||||
<div className="mt-12 w-full max-w-4xl space-y-4 transition-none">
|
<div className="mt-12 w-full max-w-4xl space-y-4 transition-none">
|
||||||
<Banner
|
<Banner variant="error" icon={<InfoFillIcon className="size-5" />} title="Неизвестная ошибка" animationDuration={0} />
|
||||||
variant="error"
|
<ErrorShell>
|
||||||
icon={<InfoFillIcon className="size-5" />}
|
|
||||||
title="Unknown Error"
|
|
||||||
animationDuration={0}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Card variant={ECardVariant.WITH_SHADOW} className="!p-6">
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="mb-2 text-20 font-semibold text-primary">Unknown Error</h2>
|
<h2 className="mb-2 text-20 font-semibold text-primary">Неизвестная ошибка</h2>
|
||||||
<div className="bg-subtle-1 h-px w-full" />
|
<div className="bg-subtle-1 h-px w-full" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="rounded-md bg-layer-1 p-4">
|
<div className="rounded-[1.1rem] bg-white/5 p-4">
|
||||||
<p className="text-13 text-secondary">
|
<p className="text-13 text-secondary">
|
||||||
An unknown error occurred. Please try refreshing the page or contact support if the problem persists.
|
Произошла неизвестная ошибка. Обновите страницу. Если проблема сохранится, обратитесь в службу
|
||||||
|
поддержки.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
<ErrorActions onGoHome={onGoHome} onReload={onReload} />
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</ErrorShell>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,8 @@ import DefaultLayout from "@/layouts/default-layout";
|
||||||
const linkMap = [
|
const linkMap = [
|
||||||
{
|
{
|
||||||
key: "mail_to",
|
key: "mail_to",
|
||||||
label: "Contact Support",
|
label: "Служба поддержки",
|
||||||
value: "mailto:support@plane.so",
|
value: "https://nodedc.dctouch.ru/",
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "status",
|
|
||||||
label: "Status Page",
|
|
||||||
value: "https://status.plane.so/",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "twitter_handle",
|
|
||||||
label: "@planepowers",
|
|
||||||
value: "https://x.com/planepowers",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -45,22 +35,20 @@ export function ProdErrorComponent({ onGoHome }: ProdErrorComponentProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DefaultLayout>
|
<DefaultLayout>
|
||||||
<div className="relative container mx-auto flex h-full w-full max-w-xl flex-col items-center justify-center gap-2 gap-y-6 bg-surface-1 px-6 text-center">
|
<div className="relative container mx-auto flex h-full w-full max-w-3xl items-center justify-center px-6 py-10">
|
||||||
<div className="relative w-full">
|
<div className="nodedc-error-shell relative flex w-full flex-col gap-6 text-left">
|
||||||
<img
|
<img
|
||||||
src={maintenanceModeImage}
|
src={maintenanceModeImage}
|
||||||
height="176"
|
height="176"
|
||||||
width="288"
|
width="288"
|
||||||
alt="ProjectSettingImg"
|
alt="ProjectSettingImg"
|
||||||
className="h-full w-full object-fill object-center"
|
className="mx-auto h-full w-full max-w-[18rem] object-fill object-center"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div className="relative mt-4 flex w-full flex-col gap-4">
|
|
||||||
<div className="flex flex-col gap-2.5">
|
<div className="flex flex-col gap-2.5">
|
||||||
<h1 className="text-left text-18 font-semibold text-primary">🚧 Looks like something went wrong!</h1>
|
<h1 className="text-18 font-semibold text-primary">🚧 Похоже, что-то пошло не так.</h1>
|
||||||
<span className="text-left text-14 font-medium text-secondary">
|
<span className="text-14 font-medium text-secondary">
|
||||||
We track these errors automatically and working on getting things back up and running. If the problem
|
Мы уже зафиксировали ошибку и пытаемся восстановить работу. Если проблема сохраняется, обратитесь в
|
||||||
persists feel free to contact us. In the meantime, try refreshing.
|
службу поддержки и обновите страницу.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -71,7 +59,7 @@ export function ProdErrorComponent({ onGoHome }: ProdErrorComponentProps) {
|
||||||
href={link.value}
|
href={link.value}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-13 text-accent-primary hover:underline"
|
className="nodedc-error-link text-13"
|
||||||
>
|
>
|
||||||
{link.label}
|
{link.label}
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -80,8 +68,8 @@ export function ProdErrorComponent({ onGoHome }: ProdErrorComponentProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-start gap-6">
|
<div className="flex items-center justify-start gap-6">
|
||||||
<Button variant="primary" size="lg" onClick={onGoHome}>
|
<Button variant="primary" size="lg" onClick={onGoHome} className="nodedc-error-primary">
|
||||||
Go to home
|
На главную
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,18 @@ export function MaintenanceMessage() {
|
||||||
const linkMap = [
|
const linkMap = [
|
||||||
{
|
{
|
||||||
key: "mail_to",
|
key: "mail_to",
|
||||||
label: "Contact Support",
|
label: "Служба поддержки",
|
||||||
value: "mailto:support@plane.so",
|
value: "https://nodedc.dctouch.ru/",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col gap-2.5">
|
<div className="flex flex-col gap-2.5">
|
||||||
<h1 className="text-left text-18 font-semibold text-primary">
|
<h1 className="text-left text-18 font-semibold text-primary">🚧 NODE.DC запустился с ошибкой.</h1>
|
||||||
🚧 Looks like NODE.DC didn't start up correctly!
|
|
||||||
</h1>
|
|
||||||
<span className="text-left text-14 font-medium text-secondary">
|
<span className="text-left text-14 font-medium text-secondary">
|
||||||
Some services might have failed to start. Please check your container logs to identify and resolve the issue.
|
Часть сервисов могла не подняться. Проверьте логи контейнеров и устраните причину. Если нужна помощь,
|
||||||
If you're stuck, reach out to our support team for more help.
|
переходите в службу поддержки.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-1 flex items-center justify-start gap-6">
|
<div className="mt-1 flex items-center justify-start gap-6">
|
||||||
|
|
@ -31,7 +29,7 @@ export function MaintenanceMessage() {
|
||||||
href={link.value}
|
href={link.value}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="text-13 text-accent-primary hover:underline"
|
className="nodedc-error-link text-13"
|
||||||
>
|
>
|
||||||
{link.label}
|
{link.label}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ export const ExternalContoursIssueContentProperties = observer(function External
|
||||||
if (!issue || !issue?.id) return <></>;
|
if (!issue || !issue?.id) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full flex-col divide-y-2 divide-subtle-1">
|
<div className="nodedc-external-section flex w-full flex-col px-4 py-4">
|
||||||
<div className="w-full overflow-y-auto">
|
<div className="w-full overflow-y-auto">
|
||||||
<h5 className="mb-2 text-body-sm-medium">{t("external_contours_page.properties.section_title")}</h5>
|
<h5 className="mb-2 text-body-sm-medium">{t("external_contours_page.properties.section_title")}</h5>
|
||||||
<div className={`divide-y-2 divide-subtle-1 ${!isEditable ? "opacity-60" : ""}`}>
|
<div className={`${!isEditable ? "opacity-60" : ""}`}>
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<div className="flex h-8 items-center gap-2">
|
<div className="nodedc-external-panel flex min-h-12 items-center gap-3 px-4 py-3">
|
||||||
<div className="flex w-2/5 flex-shrink-0 items-center gap-1 text-13 text-tertiary">
|
<div className="flex w-2/5 flex-shrink-0 items-center gap-1.5 text-13 text-tertiary">
|
||||||
<PriorityPropertyIcon className="h-4 w-4 flex-shrink-0" />
|
<PriorityPropertyIcon className="h-4 w-4 flex-shrink-0" />
|
||||||
<span>{t("priority")}</span>
|
<span>{t("priority")}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -44,14 +44,14 @@ export const ExternalContoursIssueContentProperties = observer(function External
|
||||||
onChange={(val) => issue?.id && issueOperations.update(workspaceSlug, targetProjectId, issue.id, { priority: val })}
|
onChange={(val) => issue?.id && issueOperations.update(workspaceSlug, targetProjectId, issue.id, { priority: val })}
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
className="w-3/5 flex-grow rounded-sm px-2 hover:bg-layer-1"
|
className="w-3/5 flex-grow rounded-full px-3 hover:bg-white/6"
|
||||||
buttonContainerClassName="w-full text-left"
|
buttonContainerClassName="w-full text-left"
|
||||||
buttonClassName="h-auto w-min whitespace-nowrap"
|
buttonClassName="h-auto w-min whitespace-nowrap"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex min-h-8 items-center gap-2">
|
<div className="nodedc-external-panel flex min-h-12 items-center gap-3 px-4 py-3">
|
||||||
<div className="flex w-2/5 flex-shrink-0 items-center gap-1 text-13 text-tertiary">
|
<div className="flex w-2/5 flex-shrink-0 items-center gap-1.5 text-13 text-tertiary">
|
||||||
<LabelPropertyIcon className="h-4 w-4 flex-shrink-0" />
|
<LabelPropertyIcon className="h-4 w-4 flex-shrink-0" />
|
||||||
<span>{t("labels")}</span>
|
<span>{t("labels")}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import { useEffect, useMemo, useRef } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import type { EditorRefApi } from "@plane/editor";
|
import type { EditorRefApi } from "@plane/editor";
|
||||||
import { useTranslation } from "@plane/i18n";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { Badge } from "@plane/propel/badge";
|
|
||||||
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
|
||||||
import type { TExternalContourRequest, TIssue, TNameDescriptionLoader } from "@plane/types";
|
import type { TExternalContourRequest, TIssue, TNameDescriptionLoader } from "@plane/types";
|
||||||
import { EFileAssetType } from "@plane/types";
|
import { EFileAssetType } from "@plane/types";
|
||||||
|
|
@ -139,8 +138,8 @@ export const ExternalContoursIssueMainContent = observer(function ExternalContou
|
||||||
|
|
||||||
if (!hasDirectTargetAccess) {
|
if (!hasDirectTargetAccess) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="space-y-4">
|
||||||
<div className="space-y-4 pb-4">
|
<div className="nodedc-external-section space-y-4 p-5">
|
||||||
{isSourceEditable ? (
|
{isSourceEditable ? (
|
||||||
<>
|
<>
|
||||||
<IssueTitleInput
|
<IssueTitleInput
|
||||||
|
|
@ -190,23 +189,23 @@ export const ExternalContoursIssueMainContent = observer(function ExternalContou
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="py-4">
|
|
||||||
<ExternalContoursRequestTraceability contourRequest={contourRequest} />
|
<ExternalContoursRequestTraceability contourRequest={contourRequest} />
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="py-4">
|
<div className="nodedc-external-section flex flex-col gap-3 px-4 py-4">
|
||||||
<div className="mb-2 text-body-sm-medium">{t("external_contours_page.properties.section_title")}</div>
|
<div className="text-body-sm-medium">{t("external_contours_page.properties.section_title")}</div>
|
||||||
<div className="flex flex-col gap-3 text-13 text-secondary">
|
<div className="flex flex-col gap-3 text-13 text-secondary">
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="nodedc-external-panel flex flex-wrap items-center gap-2 px-4 py-3">
|
||||||
<span className="text-tertiary">{t("priority")}</span>
|
<span className="text-tertiary">{t("priority")}</span>
|
||||||
<Badge variant="neutral">{issue.priority || t("none")}</Badge>
|
<span className="rounded-full bg-white/6 px-3 py-1.5 text-12 font-medium text-primary">
|
||||||
|
{issue.priority || t("none")}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="nodedc-external-panel flex flex-wrap items-center gap-2 px-4 py-3">
|
||||||
<span className="text-tertiary">{t("labels")}</span>
|
<span className="text-tertiary">{t("labels")}</span>
|
||||||
{issue.label_details?.length ? (
|
{issue.label_details?.length ? (
|
||||||
issue.label_details.map((label) => (
|
issue.label_details.map((label) => (
|
||||||
<div key={label.id} className="flex items-center gap-1 rounded-sm border border-strong px-2 py-1 text-11">
|
<div key={label.id} className="flex items-center gap-1 rounded-full bg-white/6 px-3 py-1.5 text-11">
|
||||||
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: label.color }} />
|
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: label.color }} />
|
||||||
<span>{label.name}</span>
|
<span>{label.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -230,8 +229,12 @@ export const ExternalContoursIssueMainContent = observer(function ExternalContou
|
||||||
|
|
||||||
<ExternalContoursMirroredActivity activity={mirroredActivity} />
|
<ExternalContoursMirroredActivity activity={mirroredActivity} />
|
||||||
|
|
||||||
{!isSourceEditable && <div className="py-4 text-13 text-secondary">{t("external_contours_page.readonly_source_view")}</div>}
|
{!isSourceEditable && (
|
||||||
</>
|
<div className="nodedc-external-empty px-4 py-4 text-13 text-secondary">
|
||||||
|
{t("external_contours_page.readonly_source_view")}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,15 @@ export const ExternalContoursListItem = observer(function ExternalContoursListIt
|
||||||
onClick={(e) => handleIssueRedirection(e, request.id)}
|
onClick={(e) => handleIssueRedirection(e, request.id)}
|
||||||
>
|
>
|
||||||
<Row
|
<Row
|
||||||
|
data-active={selectedInboxIssueId === request.id}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-pointer flex-col gap-2 border border-t-transparent border-r-transparent border-b-subtle-1 border-l-transparent py-4 transition-all hover:bg-accent-primary/5",
|
"nodedc-external-card relative flex cursor-pointer flex-col gap-4 px-4 py-4 transition-all hover:bg-white/5",
|
||||||
{ "border border-accent-strong": selectedInboxIssueId === request.id }
|
{ "ring-1 ring-accent-primary/35": selectedInboxIssueId === request.id }
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="space-y-1">
|
<div className="space-y-2">
|
||||||
<div className="relative flex items-center justify-between gap-2">
|
<div className="relative flex items-center justify-between gap-2">
|
||||||
<div className="flex items-center gap-2 text-11 font-medium text-tertiary">
|
<div className="flex min-w-0 items-center gap-2 text-11 font-medium text-tertiary">
|
||||||
<span>
|
<span>
|
||||||
{issue.project_detail?.identifier || "REQ"}-{issue.sequence_id}
|
{issue.project_detail?.identifier || "REQ"}-{issue.sequence_id}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -71,9 +72,11 @@ export const ExternalContoursListItem = observer(function ExternalContoursListIt
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="shrink-0">
|
||||||
<ExternalContourStatePill request={request} />
|
<ExternalContourStatePill request={request} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="w-full truncate text-13">{issue.name}</h3>
|
</div>
|
||||||
|
<h3 className="w-full text-15 leading-6 font-semibold text-primary">{issue.name}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
|
|
@ -93,7 +96,7 @@ export const ExternalContoursListItem = observer(function ExternalContoursListIt
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{visibleLabels.map((label) => (
|
{visibleLabels.map((label) => (
|
||||||
<div key={label.id} className="relative flex !h-[17.5px] items-center gap-1 rounded-sm border border-strong px-1 text-11">
|
<div key={label.id} className="relative flex h-6 items-center gap-1 rounded-full bg-white/6 px-2 text-11">
|
||||||
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: label.color }} />
|
<span className="h-2 w-2 rounded-full" style={{ backgroundColor: label.color }} />
|
||||||
<span className="max-w-28 truncate normal-case">{label.name}</span>
|
<span className="max-w-28 truncate normal-case">{label.name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -107,7 +110,7 @@ export const ExternalContoursListItem = observer(function ExternalContoursListIt
|
||||||
key={assignee.id}
|
key={assignee.id}
|
||||||
src={assignee.avatar_url || ""}
|
src={assignee.avatar_url || ""}
|
||||||
name={assignee.display_name || "NODE.DC"}
|
name={assignee.display_name || "NODE.DC"}
|
||||||
size="md"
|
size="lg"
|
||||||
showTooltip
|
showTooltip
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -65,20 +65,20 @@ export const ExternalContoursMirroredActivity = observer(function ExternalContou
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3 py-4">
|
<div className="nodedc-external-section space-y-3 px-4 py-4">
|
||||||
<div className="text-body-sm-medium">{t("external_contours_page.mirror.activity_title")}</div>
|
<div className="text-body-sm-medium">{t("external_contours_page.mirror.activity_title")}</div>
|
||||||
|
|
||||||
{activity.length > 0 ? (
|
{activity.length > 0 ? (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{activity.map((item) => (
|
{activity.map((item) => (
|
||||||
<div key={item.id} className="rounded-md border border-subtle bg-surface-1 px-4 py-3">
|
<div key={item.id} className="nodedc-external-panel px-4 py-3">
|
||||||
<div className="text-13 text-primary">{renderMessage(item)}</div>
|
<div className="text-13 text-primary">{renderMessage(item)}</div>
|
||||||
<div className="mt-1 text-11 text-secondary">{renderFormattedDate(item.created_at)}</div>
|
<div className="mt-1 text-11 text-secondary">{renderFormattedDate(item.created_at)}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="rounded-md border border-dashed border-subtle px-4 py-6 text-13 text-secondary">
|
<div className="nodedc-external-empty px-4 py-6 text-13 text-secondary">
|
||||||
{t("external_contours_page.mirror.activity_empty")}
|
{t("external_contours_page.mirror.activity_empty")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export const ExternalContoursMirroredAttachments = observer(function ExternalCon
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3 py-4">
|
<div className="nodedc-external-section space-y-3 px-4 py-4">
|
||||||
<div className="text-body-sm-medium">{t("external_contours_page.mirror.attachments_title")}</div>
|
<div className="text-body-sm-medium">{t("external_contours_page.mirror.attachments_title")}</div>
|
||||||
|
|
||||||
{attachments.length > 0 ? (
|
{attachments.length > 0 ? (
|
||||||
|
|
@ -36,7 +36,7 @@ export const ExternalContoursMirroredAttachments = observer(function ExternalCon
|
||||||
href={attachment.download_url || "#"}
|
href={attachment.download_url || "#"}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="flex min-h-[60px] items-center justify-between gap-3 rounded-md border-[2px] border-subtle bg-surface-1 px-4 py-2 text-13 transition-colors hover:bg-surface-2"
|
className="nodedc-external-panel flex min-h-[72px] items-center justify-between gap-3 px-4 py-3 text-13 transition-colors hover:bg-white/6"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3 overflow-hidden">
|
<div className="flex items-center gap-3 overflow-hidden">
|
||||||
<div className="h-7 w-7 flex-shrink-0">{fileIcon}</div>
|
<div className="h-7 w-7 flex-shrink-0">{fileIcon}</div>
|
||||||
|
|
@ -55,7 +55,7 @@ export const ExternalContoursMirroredAttachments = observer(function ExternalCon
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="rounded-md border border-dashed border-subtle px-4 py-6 text-13 text-secondary">
|
<div className="nodedc-external-empty px-4 py-6 text-13 text-secondary">
|
||||||
{t("external_contours_page.mirror.attachments_empty")}
|
{t("external_contours_page.mirror.attachments_empty")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export const ExternalContoursMirroredComments = observer(function ExternalContou
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3 py-4">
|
<div className="nodedc-external-section space-y-3 px-4 py-4">
|
||||||
<div className="text-body-sm-medium">{t("external_contours_page.mirror.comments_title")}</div>
|
<div className="text-body-sm-medium">{t("external_contours_page.mirror.comments_title")}</div>
|
||||||
|
|
||||||
{comments.length > 0 ? (
|
{comments.length > 0 ? (
|
||||||
|
|
@ -27,7 +27,7 @@ export const ExternalContoursMirroredComments = observer(function ExternalContou
|
||||||
{comments.map((comment) => {
|
{comments.map((comment) => {
|
||||||
const actorName = comment.actor_detail?.display_name || t("external_contours_page.mirror.system_actor");
|
const actorName = comment.actor_detail?.display_name || t("external_contours_page.mirror.system_actor");
|
||||||
return (
|
return (
|
||||||
<div key={comment.id} className="rounded-md border border-subtle bg-surface-1 p-4">
|
<div key={comment.id} className="nodedc-external-panel p-4">
|
||||||
<div className="mb-3 flex items-center justify-between gap-3">
|
<div className="mb-3 flex items-center justify-between gap-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Avatar src={comment.actor_detail?.avatar_url || ""} name={actorName} size="md" />
|
<Avatar src={comment.actor_detail?.avatar_url || ""} name={actorName} size="md" />
|
||||||
|
|
@ -49,7 +49,7 @@ export const ExternalContoursMirroredComments = observer(function ExternalContou
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="rounded-md border border-dashed border-subtle px-4 py-6 text-13 text-secondary">
|
<div className="nodedc-external-empty px-4 py-6 text-13 text-secondary">
|
||||||
{t("external_contours_page.mirror.comments_empty")}
|
{t("external_contours_page.mirror.comments_empty")}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,9 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const TraceabilityCell = ({ label, children }: { label: string; children: ReactNode }) => (
|
const TraceabilityCell = ({ label, children }: { label: string; children: ReactNode }) => (
|
||||||
<div className="rounded-md border border-subtle bg-surface-1 p-3">
|
<div className="nodedc-external-panel p-4">
|
||||||
<div className="text-11 font-medium text-tertiary">{label}</div>
|
<div className="text-11 font-medium text-tertiary">{label}</div>
|
||||||
<div className="mt-1 min-h-6 text-13 font-medium text-secondary">{children}</div>
|
<div className="mt-2 min-h-6 text-13 font-medium text-secondary">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -41,7 +41,7 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
const assigneeDetails = issue.assignee_details ?? [];
|
const assigneeDetails = issue.assignee_details ?? [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="rounded-lg border border-subtle bg-surface-2 p-4">
|
<div className="nodedc-external-section p-5">
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<h5 className="text-body-sm-medium">{t("external_contours_page.traceability.title")}</h5>
|
<h5 className="text-body-sm-medium">{t("external_contours_page.traceability.title")}</h5>
|
||||||
<p className="mt-1 text-12 text-tertiary">{t("external_contours_page.traceability.description")}</p>
|
<p className="mt-1 text-12 text-tertiary">{t("external_contours_page.traceability.description")}</p>
|
||||||
|
|
@ -73,7 +73,7 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
{assigneeDetails.map((assignee) => (
|
{assigneeDetails.map((assignee) => (
|
||||||
<div key={assignee.id} className="flex items-center gap-2">
|
<div key={assignee.id} className="flex items-center gap-2">
|
||||||
<Avatar src={assignee.avatar_url || ""} name={assignee.display_name || t("common.none")} size="sm" showTooltip />
|
<Avatar src={assignee.avatar_url || ""} name={assignee.display_name || t("common.none")} size="sm" showTooltip />
|
||||||
<span className="text-12 font-medium text-secondary">{assignee.display_name}</span>
|
<span className="text-13 font-medium text-secondary">{assignee.display_name}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -90,13 +90,13 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
{requestedAt ? renderFormattedDate(requestedAt) : t("common.none")}
|
{requestedAt ? renderFormattedDate(requestedAt) : t("common.none")}
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.last_updated")}>
|
|
||||||
{lastUpdatedAt ? renderFormattedDate(lastUpdatedAt) : t("common.none")}
|
|
||||||
</TraceabilityCell>
|
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.due_date")}>
|
<TraceabilityCell label={t("external_contours_page.traceability.due_date")}>
|
||||||
{dueDate}
|
{dueDate}
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
|
<TraceabilityCell label={t("external_contours_page.traceability.last_updated")}>
|
||||||
|
{lastUpdatedAt ? renderFormattedDate(lastUpdatedAt) : t("common.none")}
|
||||||
|
</TraceabilityCell>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -97,11 +97,15 @@ export const ExternalContoursRoot = observer(function ExternalContoursRoot(props
|
||||||
inboxIssueId={inboxIssueId.toString()}
|
inboxIssueId={inboxIssueId.toString()}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="flex h-full w-full items-center justify-center px-8">
|
||||||
|
<div className="nodedc-external-section max-w-xl px-8 py-10">
|
||||||
<EmptyStateCompact
|
<EmptyStateCompact
|
||||||
assetKey="intake"
|
assetKey="intake"
|
||||||
title={t("external_contours_page.empty_state.detail_title")}
|
title={t("external_contours_page.empty_state.detail_title")}
|
||||||
assetClassName="size-20"
|
assetClassName="size-20"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import { useTranslation } from "@plane/i18n";
|
||||||
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
import { EmptyStateDetailed } from "@plane/propel/empty-state";
|
||||||
import type { TInboxIssueCurrentTab } from "@plane/types";
|
import type { TInboxIssueCurrentTab } from "@plane/types";
|
||||||
import { EInboxIssueCurrentTab } from "@plane/types";
|
import { EInboxIssueCurrentTab } from "@plane/types";
|
||||||
import { EHeaderVariant, Header } from "@plane/ui";
|
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours";
|
import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours";
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
|
|
@ -42,18 +41,20 @@ export const ExternalContoursSidebar = observer(function ExternalContoursSidebar
|
||||||
}
|
}
|
||||||
}, [currentTab, filteredRequestIds, inboxIssueId, projectId, router, workspaceSlug]);
|
}, [currentTab, filteredRequestIds, inboxIssueId, projectId, router, workspaceSlug]);
|
||||||
|
|
||||||
const currentCount = currentTab === EInboxIssueCurrentTab.CLOSED ? closedRequestIds.length : openRequestIds.length;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-full flex-shrink-0 border-r border-strong bg-surface-1">
|
<div className="nodedc-external-sidebar-shell h-full w-full flex-shrink-0 border-r border-strong/40">
|
||||||
<div className="relative flex h-full w-full flex-col overflow-hidden">
|
<div className="relative flex h-full w-full flex-col overflow-hidden">
|
||||||
<Header variant={EHeaderVariant.SECONDARY}>
|
<div className="px-4 py-4">
|
||||||
{tabNavigationOptions.map((option) => (
|
<div className="nodedc-filter-row-shell flex items-center gap-2 p-1">
|
||||||
<div
|
{tabNavigationOptions.map((option) => {
|
||||||
|
const count = option.key === EInboxIssueCurrentTab.CLOSED ? closedRequestIds.length : openRequestIds.length;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
key={option.key}
|
key={option.key}
|
||||||
|
data-active={currentTab === option.key}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex h-full cursor-pointer items-center gap-1 px-3 text-13 font-medium transition-all",
|
"nodedc-external-tab flex flex-1 items-center justify-center gap-2 text-13 font-medium transition-all"
|
||||||
currentTab === option.key ? "text-accent-primary" : "hover:text-secondary"
|
|
||||||
)}
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (currentTab !== option.key) {
|
if (currentTab !== option.key) {
|
||||||
|
|
@ -63,24 +64,24 @@ export const ExternalContoursSidebar = observer(function ExternalContoursSidebar
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>{t(option.i18n_label)}</div>
|
<div>{t(option.i18n_label)}</div>
|
||||||
{currentTab === option.key && (
|
|
||||||
<div className="rounded-full bg-accent-primary/20 px-1.5 py-0.5 text-11 font-semibold text-accent-primary">
|
|
||||||
{currentCount}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"absolute right-0 bottom-0 left-0 rounded-t-md border",
|
"rounded-full px-1.5 py-0.5 text-11 font-semibold",
|
||||||
currentTab === option.key ? "border-accent-strong" : "border-transparent"
|
currentTab === option.key ? "bg-accent-primary/15 text-accent-primary" : "bg-white/5 text-secondary"
|
||||||
)}
|
)}
|
||||||
/>
|
>
|
||||||
|
{count}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</Header>
|
|
||||||
|
|
||||||
<div className="vertical-scrollbar scrollbar-md h-full w-full overflow-hidden overflow-y-auto">
|
<div className="vertical-scrollbar scrollbar-md h-full w-full overflow-hidden overflow-y-auto px-4 pb-4">
|
||||||
{filteredRequestIds.length > 0 ? (
|
{filteredRequestIds.length > 0 ? (
|
||||||
filteredRequestIds.map((requestId) => (
|
<div className="space-y-3">
|
||||||
|
{filteredRequestIds.map((requestId) => (
|
||||||
<ExternalContoursListItem
|
<ExternalContoursListItem
|
||||||
key={requestId}
|
key={requestId}
|
||||||
setIsMobileSidebar={setIsMobileSidebar}
|
setIsMobileSidebar={setIsMobileSidebar}
|
||||||
|
|
@ -88,7 +89,8 @@ export const ExternalContoursSidebar = observer(function ExternalContoursSidebar
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
requestId={requestId}
|
requestId={requestId}
|
||||||
/>
|
/>
|
||||||
))
|
))}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-full w-full items-center justify-center">
|
<div className="flex h-full w-full items-center justify-center">
|
||||||
{currentTab === EInboxIssueCurrentTab.OPEN ? (
|
{currentTab === EInboxIssueCurrentTab.OPEN ? (
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export const ExternalContoursSourceReplyBox = observer(function ExternalContours
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3 py-4">
|
<div className="nodedc-external-section space-y-3 px-4 py-4">
|
||||||
<div className="text-body-sm-medium">{t("external_contours_page.reply.title")}</div>
|
<div className="text-body-sm-medium">{t("external_contours_page.reply.title")}</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
value={comment}
|
value={comment}
|
||||||
|
|
@ -55,9 +55,15 @@ export const ExternalContoursSourceReplyBox = observer(function ExternalContours
|
||||||
rows={4}
|
rows={4}
|
||||||
placeholder={t("external_contours_page.reply.placeholder")}
|
placeholder={t("external_contours_page.reply.placeholder")}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
|
className="nodedc-modal-input min-h-[7rem] resize-none !rounded-[1.2rem] !border-0 !bg-white/4"
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button variant="primary" onClick={handleSubmit} disabled={isSubmitting || !comment.trim()}>
|
<Button
|
||||||
|
variant="primary"
|
||||||
|
onClick={handleSubmit}
|
||||||
|
disabled={isSubmitting || !comment.trim()}
|
||||||
|
className="nodedc-modal-primary-button"
|
||||||
|
>
|
||||||
{t("external_contours_page.reply.submit")}
|
{t("external_contours_page.reply.submit")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -23,21 +23,18 @@ export function AuthBanner(props: TAuthBanner) {
|
||||||
|
|
||||||
if (!message) return <></>;
|
if (!message) return <></>;
|
||||||
return (
|
return (
|
||||||
<div
|
<div role="alert" className="nodedc-auth-banner relative flex items-center gap-2 p-3">
|
||||||
role="alert"
|
|
||||||
className="relative flex items-center gap-2 rounded-md border border-accent-strong/50 bg-accent-primary/10 p-2"
|
|
||||||
>
|
|
||||||
<div className="grid size-4 flex-shrink-0 place-items-center">
|
<div className="grid size-4 flex-shrink-0 place-items-center">
|
||||||
<Info size={16} className="text-accent-primary" />
|
<Info size={16} className="text-current" />
|
||||||
</div>
|
</div>
|
||||||
<p className="w-full text-13 font-medium text-accent-primary">{message}</p>
|
<p className="w-full text-13 font-medium text-current">{message}</p>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="relative ml-auto grid size-6 place-items-center rounded-xs text-accent-primary/80 transition-all hover:bg-accent-primary/20"
|
className="relative ml-auto grid size-6 place-items-center rounded-full text-current/80 transition-all hover:bg-white/10"
|
||||||
onClick={() => handleBannerData?.(undefined)}
|
onClick={() => handleBannerData?.(undefined)}
|
||||||
aria-label={t("aria_labels.auth_forms.close_alert")}
|
aria-label={t("aria_labels.auth_forms.close_alert")}
|
||||||
>
|
>
|
||||||
<CloseIcon className="size-4" />
|
<CloseIcon className="size-4 text-current" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,9 @@ type TAuthHeaderBase = {
|
||||||
|
|
||||||
export function AuthHeaderBase(props: TAuthHeaderBase) {
|
export function AuthHeaderBase(props: TAuthHeaderBase) {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-2">
|
||||||
<span className="text-h4-semibold text-primary">{props.header}</span>
|
<span className="text-[2rem] leading-10 font-semibold text-primary">{props.header}</span>
|
||||||
<span className="text-h4-semibold text-placeholder">{props.subHeader}</span>
|
<span className="text-[1.9rem] leading-10 font-semibold text-placeholder">{props.subHeader}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,8 +157,8 @@ export const AuthRoot = observer(function AuthRoot(props: TAuthRoot) {
|
||||||
|
|
||||||
function AuthContainer({ children }: { children: React.ReactNode }) {
|
function AuthContainer({ children }: { children: React.ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="mt-10 flex w-full flex-grow flex-col items-center justify-center py-6">
|
<div className="mt-6 flex w-full flex-grow flex-col items-center justify-center py-8">
|
||||||
<div className="relative flex w-full max-w-[22.5rem] flex-col gap-6">{children}</div>
|
<div className="nodedc-auth-shell relative flex w-full max-w-[28rem] flex-col gap-6">{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,10 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
`relative flex items-center rounded-md border bg-surface-1`,
|
"nodedc-auth-input-shell relative flex items-center",
|
||||||
!isFocused && Boolean(emailError?.email) ? `border-danger-strong` : `border-strong`
|
!isFocused && Boolean(emailError?.email) && "border-danger-strong/0"
|
||||||
)}
|
)}
|
||||||
|
data-error={!isFocused && Boolean(emailError?.email)}
|
||||||
onFocus={() => {
|
onFocus={() => {
|
||||||
setIsFocused(true);
|
setIsFocused(true);
|
||||||
}}
|
}}
|
||||||
|
|
@ -73,7 +74,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
placeholder={t("auth.common.email.placeholder")}
|
placeholder={t("auth.common.email.placeholder")}
|
||||||
className={`h-10 w-full border-0 disable-autofill-style placeholder:text-placeholder autofill:bg-danger-primary focus:bg-none active:bg-transparent`}
|
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style autofill:bg-danger-primary focus:bg-none active:bg-transparent"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoFocus
|
autoFocus
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
|
@ -100,7 +101,7 @@ export const AuthEmailForm = observer(function AuthEmailForm(props: TAuthEmailFo
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("common.continue")}
|
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("common.continue")}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
<Link
|
<Link
|
||||||
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
|
data-ph-element={AUTH_TRACKER_ELEMENTS.FORGOT_PASSWORD_FROM_SIGNIN}
|
||||||
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
|
href={`/accounts/forgot-password?email=${encodeURIComponent(email)}`}
|
||||||
className="text-11 font-medium text-accent-primary"
|
className="nodedc-auth-link text-11 font-medium"
|
||||||
>
|
>
|
||||||
{t("auth.common.forgot_password")}
|
{t("auth.common.forgot_password")}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -174,7 +174,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
<label htmlFor="email" className="text-13 font-medium text-tertiary">
|
<label htmlFor="email" className="text-13 font-medium text-tertiary">
|
||||||
{t("auth.common.email.label")}
|
{t("auth.common.email.label")}
|
||||||
</label>
|
</label>
|
||||||
<div className={`relative flex items-center rounded-md border border-strong bg-surface-1`}>
|
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||||
<Input
|
<Input
|
||||||
id="email"
|
id="email"
|
||||||
name="email"
|
name="email"
|
||||||
|
|
@ -182,7 +182,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
value={passwordFormData.email}
|
value={passwordFormData.email}
|
||||||
onChange={(e) => handleFormChange("email", e.target.value)}
|
onChange={(e) => handleFormChange("email", e.target.value)}
|
||||||
placeholder={t("auth.common.email.placeholder")}
|
placeholder={t("auth.common.email.placeholder")}
|
||||||
className={`h-10 w-full border-0 disable-autofill-style placeholder:text-placeholder`}
|
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
{passwordFormData.email.length > 0 && (
|
{passwordFormData.email.length > 0 && (
|
||||||
|
|
@ -202,7 +202,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
<label htmlFor="password" className="text-13 font-medium text-tertiary">
|
<label htmlFor="password" className="text-13 font-medium text-tertiary">
|
||||||
{mode === EAuthModes.SIGN_IN ? t("auth.common.password.label") : t("auth.common.password.set_password")}
|
{mode === EAuthModes.SIGN_IN ? t("auth.common.password.label") : t("auth.common.password.set_password")}
|
||||||
</label>
|
</label>
|
||||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||||
<Input
|
<Input
|
||||||
type={showPassword?.password ? "text" : "password"}
|
type={showPassword?.password ? "text" : "password"}
|
||||||
id="password"
|
id="password"
|
||||||
|
|
@ -210,7 +210,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
value={passwordFormData.password}
|
value={passwordFormData.password}
|
||||||
onChange={(e) => handleFormChange("password", e.target.value)}
|
onChange={(e) => handleFormChange("password", e.target.value)}
|
||||||
placeholder={t("auth.common.password.placeholder")}
|
placeholder={t("auth.common.password.placeholder")}
|
||||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
|
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||||
onFocus={() => setIsPasswordInputFocused(true)}
|
onFocus={() => setIsPasswordInputFocused(true)}
|
||||||
onBlur={() => setIsPasswordInputFocused(false)}
|
onBlur={() => setIsPasswordInputFocused(false)}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
|
@ -239,7 +239,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
<label htmlFor="confirm-password" className="text-13 font-medium text-tertiary">
|
<label htmlFor="confirm-password" className="text-13 font-medium text-tertiary">
|
||||||
{t("auth.common.password.confirm_password.label")}
|
{t("auth.common.password.confirm_password.label")}
|
||||||
</label>
|
</label>
|
||||||
<div className="relative flex items-center rounded-md bg-surface-1">
|
<div className="nodedc-auth-input-shell relative flex items-center">
|
||||||
<Input
|
<Input
|
||||||
type={showPassword?.retypePassword ? "text" : "password"}
|
type={showPassword?.retypePassword ? "text" : "password"}
|
||||||
id="confirm-password"
|
id="confirm-password"
|
||||||
|
|
@ -247,7 +247,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
value={passwordFormData.confirm_password}
|
value={passwordFormData.confirm_password}
|
||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
placeholder={t("auth.common.password.confirm_password.placeholder")}
|
||||||
className="h-10 w-full border border-strong !bg-surface-1 pr-12 disable-autofill-style placeholder:text-placeholder"
|
className="nodedc-auth-input h-12 w-full pr-12 disable-autofill-style"
|
||||||
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
|
@ -280,7 +280,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
{mode === EAuthModes.SIGN_IN ? (
|
{mode === EAuthModes.SIGN_IN ? (
|
||||||
<>
|
<>
|
||||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||||
{isSubmitting ? (
|
{isSubmitting ? (
|
||||||
<Spinner height="20px" width="20px" />
|
<Spinner height="20px" width="20px" />
|
||||||
) : isSMTPConfigured ? (
|
) : isSMTPConfigured ? (
|
||||||
|
|
@ -295,7 +295,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
|
data-ph-element={AUTH_TRACKER_ELEMENTS.SIGN_IN_WITH_UNIQUE_CODE}
|
||||||
onClick={redirectToUniqueCodeSignIn}
|
onClick={redirectToUniqueCodeSignIn}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="w-full"
|
className="nodedc-empty-state-secondary w-full"
|
||||||
size="xl"
|
size="xl"
|
||||||
>
|
>
|
||||||
{t("auth.common.sign_in_with_unique_code")}
|
{t("auth.common.sign_in_with_unique_code")}
|
||||||
|
|
@ -303,7 +303,7 @@ export const AuthPasswordForm = observer(function AuthPasswordForm(props: Props)
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Button type="submit" variant="primary" className="w-full" size="xl" disabled={isButtonDisabled}>
|
<Button type="submit" variant="primary" className="nodedc-auth-primary-button" size="xl" disabled={isButtonDisabled}>
|
||||||
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("auth_actions.sign_up")}
|
{isSubmitting ? <Spinner height="20px" width="20px" /> : t("auth_actions.sign_up")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ type AuthBaseProps = {
|
||||||
|
|
||||||
export function AuthBase({ authType }: AuthBaseProps) {
|
export function AuthBase({ authType }: AuthBaseProps) {
|
||||||
return (
|
return (
|
||||||
<div className="relative z-10 flex h-screen w-screen flex-col items-center overflow-hidden overflow-y-auto px-8 pt-6 pb-10">
|
<div className="relative z-10 flex h-screen w-screen flex-col items-center overflow-hidden overflow-y-auto bg-canvas px-8 pt-8 pb-10">
|
||||||
<AuthHeader type={authType} />
|
<AuthHeader type={authType} />
|
||||||
<AuthRoot authMode={authType} />
|
<AuthRoot authMode={authType} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ export const AuthHeader = observer(function AuthHeader({ type }: AuthHeaderProps
|
||||||
<Link
|
<Link
|
||||||
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
|
data-ph-element={AUTH_TRACKER_ELEMENTS.NAVIGATE_TO_SIGN_UP}
|
||||||
href={authContentMap[type].linkHref}
|
href={authContentMap[type].linkHref}
|
||||||
className="text-body-sm-semibold text-accent-primary hover:underline"
|
className="nodedc-auth-link text-body-sm-semibold"
|
||||||
>
|
>
|
||||||
{t(authContentMap[type].linkText)}
|
{t(authContentMap[type].linkText)}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -71,9 +71,9 @@ export function AuthHeaderBase(props: TAuthHeaderBase) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle + " - NODE.DC"} />
|
<PageHead title={pageTitle + " - NODE.DC"} />
|
||||||
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6">
|
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6 px-2 py-1">
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
<PlaneLockup height={20} width={95} className="text-primary" />
|
<PlaneLockup height={40} width={190} className="text-primary transition-opacity hover:opacity-90" />
|
||||||
</Link>
|
</Link>
|
||||||
{additionalAction}
|
{additionalAction}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
// plane imports
|
|
||||||
import { SUPPORT_EMAIL } from "@plane/constants";
|
|
||||||
|
|
||||||
export enum EPageTypes {
|
export enum EPageTypes {
|
||||||
PUBLIC = "PUBLIC",
|
PUBLIC = "PUBLIC",
|
||||||
|
|
@ -37,7 +35,6 @@ export enum EErrorAlertType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EAuthenticationErrorCodes {
|
export enum EAuthenticationErrorCodes {
|
||||||
// Global
|
|
||||||
INSTANCE_NOT_CONFIGURED = "5000",
|
INSTANCE_NOT_CONFIGURED = "5000",
|
||||||
INVALID_EMAIL = "5005",
|
INVALID_EMAIL = "5005",
|
||||||
EMAIL_REQUIRED = "5010",
|
EMAIL_REQUIRED = "5010",
|
||||||
|
|
@ -45,32 +42,27 @@ export enum EAuthenticationErrorCodes {
|
||||||
MAGIC_LINK_LOGIN_DISABLED = "5016",
|
MAGIC_LINK_LOGIN_DISABLED = "5016",
|
||||||
PASSWORD_LOGIN_DISABLED = "5018",
|
PASSWORD_LOGIN_DISABLED = "5018",
|
||||||
USER_ACCOUNT_DEACTIVATED = "5019",
|
USER_ACCOUNT_DEACTIVATED = "5019",
|
||||||
// Password strength
|
|
||||||
INVALID_PASSWORD = "5020",
|
INVALID_PASSWORD = "5020",
|
||||||
PASSWORD_TOO_WEAK = "5021",
|
PASSWORD_TOO_WEAK = "5021",
|
||||||
SMTP_NOT_CONFIGURED = "5025",
|
SMTP_NOT_CONFIGURED = "5025",
|
||||||
// Sign Up
|
|
||||||
USER_ALREADY_EXIST = "5030",
|
USER_ALREADY_EXIST = "5030",
|
||||||
AUTHENTICATION_FAILED_SIGN_UP = "5035",
|
AUTHENTICATION_FAILED_SIGN_UP = "5035",
|
||||||
REQUIRED_EMAIL_PASSWORD_SIGN_UP = "5040",
|
REQUIRED_EMAIL_PASSWORD_SIGN_UP = "5040",
|
||||||
INVALID_EMAIL_SIGN_UP = "5045",
|
INVALID_EMAIL_SIGN_UP = "5045",
|
||||||
INVALID_EMAIL_MAGIC_SIGN_UP = "5050",
|
INVALID_EMAIL_MAGIC_SIGN_UP = "5050",
|
||||||
MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED = "5055",
|
MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED = "5055",
|
||||||
// Sign In
|
|
||||||
USER_DOES_NOT_EXIST = "5060",
|
USER_DOES_NOT_EXIST = "5060",
|
||||||
AUTHENTICATION_FAILED_SIGN_IN = "5065",
|
AUTHENTICATION_FAILED_SIGN_IN = "5065",
|
||||||
REQUIRED_EMAIL_PASSWORD_SIGN_IN = "5070",
|
REQUIRED_EMAIL_PASSWORD_SIGN_IN = "5070",
|
||||||
INVALID_EMAIL_SIGN_IN = "5075",
|
INVALID_EMAIL_SIGN_IN = "5075",
|
||||||
INVALID_EMAIL_MAGIC_SIGN_IN = "5080",
|
INVALID_EMAIL_MAGIC_SIGN_IN = "5080",
|
||||||
MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED = "5085",
|
MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED = "5085",
|
||||||
// Both Sign in and Sign up for magic
|
|
||||||
INVALID_MAGIC_CODE_SIGN_IN = "5090",
|
INVALID_MAGIC_CODE_SIGN_IN = "5090",
|
||||||
INVALID_MAGIC_CODE_SIGN_UP = "5092",
|
INVALID_MAGIC_CODE_SIGN_UP = "5092",
|
||||||
EXPIRED_MAGIC_CODE_SIGN_IN = "5095",
|
EXPIRED_MAGIC_CODE_SIGN_IN = "5095",
|
||||||
EXPIRED_MAGIC_CODE_SIGN_UP = "5097",
|
EXPIRED_MAGIC_CODE_SIGN_UP = "5097",
|
||||||
EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN = "5100",
|
EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN = "5100",
|
||||||
EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP = "5102",
|
EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP = "5102",
|
||||||
// Oauth
|
|
||||||
OAUTH_NOT_CONFIGURED = "5104",
|
OAUTH_NOT_CONFIGURED = "5104",
|
||||||
GOOGLE_NOT_CONFIGURED = "5105",
|
GOOGLE_NOT_CONFIGURED = "5105",
|
||||||
GITHUB_NOT_CONFIGURED = "5110",
|
GITHUB_NOT_CONFIGURED = "5110",
|
||||||
|
|
@ -78,16 +70,12 @@ export enum EAuthenticationErrorCodes {
|
||||||
GOOGLE_OAUTH_PROVIDER_ERROR = "5115",
|
GOOGLE_OAUTH_PROVIDER_ERROR = "5115",
|
||||||
GITHUB_OAUTH_PROVIDER_ERROR = "5120",
|
GITHUB_OAUTH_PROVIDER_ERROR = "5120",
|
||||||
GITLAB_OAUTH_PROVIDER_ERROR = "5121",
|
GITLAB_OAUTH_PROVIDER_ERROR = "5121",
|
||||||
// Reset Password
|
|
||||||
INVALID_PASSWORD_TOKEN = "5125",
|
INVALID_PASSWORD_TOKEN = "5125",
|
||||||
EXPIRED_PASSWORD_TOKEN = "5130",
|
EXPIRED_PASSWORD_TOKEN = "5130",
|
||||||
// Change password
|
|
||||||
INCORRECT_OLD_PASSWORD = "5135",
|
INCORRECT_OLD_PASSWORD = "5135",
|
||||||
MISSING_PASSWORD = "5138",
|
MISSING_PASSWORD = "5138",
|
||||||
INVALID_NEW_PASSWORD = "5140",
|
INVALID_NEW_PASSWORD = "5140",
|
||||||
// set password
|
|
||||||
PASSWORD_ALREADY_SET = "5145",
|
PASSWORD_ALREADY_SET = "5145",
|
||||||
// Admin
|
|
||||||
ADMIN_ALREADY_EXIST = "5150",
|
ADMIN_ALREADY_EXIST = "5150",
|
||||||
REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME = "5155",
|
REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME = "5155",
|
||||||
INVALID_ADMIN_EMAIL = "5160",
|
INVALID_ADMIN_EMAIL = "5160",
|
||||||
|
|
@ -97,7 +85,6 @@ export enum EAuthenticationErrorCodes {
|
||||||
ADMIN_USER_ALREADY_EXIST = "5180",
|
ADMIN_USER_ALREADY_EXIST = "5180",
|
||||||
ADMIN_USER_DOES_NOT_EXIST = "5185",
|
ADMIN_USER_DOES_NOT_EXIST = "5185",
|
||||||
ADMIN_USER_DEACTIVATED = "5190",
|
ADMIN_USER_DEACTIVATED = "5190",
|
||||||
// Rate limit
|
|
||||||
RATE_LIMIT_EXCEEDED = "5900",
|
RATE_LIMIT_EXCEEDED = "5900",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,267 +95,246 @@ export type TAuthErrorInfo = {
|
||||||
message: ReactNode;
|
message: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: move all error messages to translation files
|
const authLinkClass = "nodedc-auth-link font-medium";
|
||||||
|
|
||||||
const errorCodeMessages: {
|
const errorCodeMessages: {
|
||||||
[key in EAuthenticationErrorCodes]: { title: string; message: (email?: string) => ReactNode };
|
[key in EAuthenticationErrorCodes]: { title: string; message: (email?: string) => ReactNode };
|
||||||
} = {
|
} = {
|
||||||
// global
|
|
||||||
[EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED]: {
|
||||||
title: `Instance not configured`,
|
title: "Пространство не настроено",
|
||||||
message: () => `Instance not configured. Please contact your administrator.`,
|
message: () => "Пространство не настроено. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_EMAIL]: {
|
[EAuthenticationErrorCodes.INVALID_EMAIL]: {
|
||||||
title: `Invalid email`,
|
title: "Некорректный e-mail",
|
||||||
message: () => `Invalid email. Please try again.`,
|
message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
|
[EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
|
||||||
title: `Email required`,
|
title: "Нужен e-mail",
|
||||||
message: () => `Email required. Please try again.`,
|
message: () => "Укажите e-mail и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.SIGNUP_DISABLED]: {
|
[EAuthenticationErrorCodes.SIGNUP_DISABLED]: {
|
||||||
title: `Sign up disabled`,
|
title: "Регистрация отключена",
|
||||||
message: () => `Sign up disabled. Please contact your administrator.`,
|
message: () => "Регистрация отключена. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.MAGIC_LINK_LOGIN_DISABLED]: {
|
[EAuthenticationErrorCodes.MAGIC_LINK_LOGIN_DISABLED]: {
|
||||||
title: `Magic link login disabled`,
|
title: "Вход по коду отключён",
|
||||||
message: () => `Magic link login disabled. Please contact your administrator.`,
|
message: () => "Вход по коду отключён. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.PASSWORD_LOGIN_DISABLED]: {
|
[EAuthenticationErrorCodes.PASSWORD_LOGIN_DISABLED]: {
|
||||||
title: `Password login disabled`,
|
title: "Вход по паролю отключён",
|
||||||
message: () => `Password login disabled. Please contact your administrator.`,
|
message: () => "Вход по паролю отключён. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
|
[EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
|
||||||
title: `User account deactivated`,
|
title: "Аккаунт деактивирован",
|
||||||
message: () => `User account deactivated. Please contact ${SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
|
message: () => "Аккаунт деактивирован. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_PASSWORD]: {
|
[EAuthenticationErrorCodes.INVALID_PASSWORD]: {
|
||||||
title: `Invalid password`,
|
title: "Неверный пароль",
|
||||||
message: () => `Invalid password. Please try again.`,
|
message: () => "Неверный пароль. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.PASSWORD_TOO_WEAK]: {
|
[EAuthenticationErrorCodes.PASSWORD_TOO_WEAK]: {
|
||||||
title: `Password too weak`,
|
title: "Слишком простой пароль",
|
||||||
message: () => `Password must include upper-case, lower-case, number, special character, and must not be predictable.`,
|
message: () => "Пароль должен содержать строчные и заглавные буквы, цифру и специальный символ.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED]: {
|
||||||
title: `SMTP not configured`,
|
title: "Почта не настроена",
|
||||||
message: () => `SMTP not configured. Please contact your administrator.`,
|
message: () => "Почтовый сервис не настроен. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// sign up
|
|
||||||
[EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
|
[EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
|
||||||
title: `User already exists`,
|
title: "Аккаунт уже существует",
|
||||||
message: (email = undefined) => (
|
message: (email = undefined) => (
|
||||||
<div>
|
<div>
|
||||||
Your account is already registered.
|
Аккаунт уже зарегистрирован.
|
||||||
<Link
|
<Link className={authLinkClass} href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}>
|
||||||
className="font-medium underline underline-offset-4 transition-all hover:font-bold"
|
Войти
|
||||||
href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
|
||||||
>
|
|
||||||
Sign In
|
|
||||||
</Link>
|
</Link>
|
||||||
now.
|
сейчас.
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP]: {
|
|
||||||
title: `Email and password required`,
|
|
||||||
message: () => `Email and password required. Please try again.`,
|
|
||||||
},
|
|
||||||
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
|
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
|
||||||
title: `Authentication failed`,
|
title: "Не удалось выполнить вход",
|
||||||
message: () => `Authentication failed. Please try again.`,
|
message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
|
||||||
|
},
|
||||||
|
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP]: {
|
||||||
|
title: "Нужны e-mail и пароль",
|
||||||
|
message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
|
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
|
||||||
title: `Invalid email`,
|
title: "Некорректный e-mail",
|
||||||
message: () => `Invalid email. Please try again.`,
|
message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
|
||||||
},
|
|
||||||
[EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
|
|
||||||
title: `Email and code required`,
|
|
||||||
message: () => `Email and code required. Please try again.`,
|
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
|
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
|
||||||
title: `Invalid email`,
|
title: "Некорректный e-mail",
|
||||||
message: () => `Invalid email. Please try again.`,
|
message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
|
||||||
|
},
|
||||||
|
[EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
|
||||||
|
title: "Нужны e-mail и код",
|
||||||
|
message: () => "Укажите e-mail и код подтверждения, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
|
|
||||||
[EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
|
[EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
|
||||||
title: `User does not exist`,
|
title: "Аккаунт не найден",
|
||||||
message: (email = undefined) => (
|
message: (email = undefined) => (
|
||||||
<div>
|
<div>
|
||||||
No account found.
|
Аккаунт не найден.
|
||||||
<Link
|
<Link className={authLinkClass} href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}>
|
||||||
className="font-medium underline underline-offset-4 transition-all hover:font-bold"
|
Создать аккаунт
|
||||||
href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
|
||||||
>
|
|
||||||
Create one
|
|
||||||
</Link>
|
</Link>
|
||||||
to get started.
|
для начала работы.
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
|
|
||||||
title: `Email and password required`,
|
|
||||||
message: () => `Email and password required. Please try again.`,
|
|
||||||
},
|
|
||||||
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
|
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
|
||||||
title: `Authentication failed`,
|
title: "Не удалось выполнить вход",
|
||||||
message: () => `Authentication failed. Please try again.`,
|
message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
|
||||||
|
},
|
||||||
|
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
|
||||||
|
title: "Нужны e-mail и пароль",
|
||||||
|
message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
|
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
|
||||||
title: `Invalid email`,
|
title: "Некорректный e-mail",
|
||||||
message: () => `Invalid email. Please try again.`,
|
message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
|
||||||
},
|
|
||||||
[EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
|
|
||||||
title: `Email and code required`,
|
|
||||||
message: () => `Email and code required. Please try again.`,
|
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
|
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
|
||||||
title: `Invalid email`,
|
title: "Некорректный e-mail",
|
||||||
message: () => `Invalid email. Please try again.`,
|
message: () => "Некорректный e-mail. Проверьте адрес и попробуйте снова.",
|
||||||
|
},
|
||||||
|
[EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
|
||||||
|
title: "Нужны e-mail и код",
|
||||||
|
message: () => "Укажите e-mail и код подтверждения, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Both Sign in and Sign up
|
|
||||||
[EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_IN]: {
|
[EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_IN]: {
|
||||||
title: `Authentication failed`,
|
title: "Неверный код подтверждения",
|
||||||
message: () => `Invalid magic code. Please try again.`,
|
message: () => "Код подтверждения неверный. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_UP]: {
|
[EAuthenticationErrorCodes.INVALID_MAGIC_CODE_SIGN_UP]: {
|
||||||
title: `Authentication failed`,
|
title: "Неверный код подтверждения",
|
||||||
message: () => `Invalid magic code. Please try again.`,
|
message: () => "Код подтверждения неверный. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_IN]: {
|
[EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_IN]: {
|
||||||
title: `Expired magic code`,
|
title: "Код подтверждения истёк",
|
||||||
message: () => `Expired magic code. Please try again.`,
|
message: () => "Код подтверждения истёк. Запросите новый и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_UP]: {
|
[EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE_SIGN_UP]: {
|
||||||
title: `Expired magic code`,
|
title: "Код подтверждения истёк",
|
||||||
message: () => `Expired magic code. Please try again.`,
|
message: () => "Код подтверждения истёк. Запросите новый и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN]: {
|
[EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_IN]: {
|
||||||
title: `Expired magic code`,
|
title: "Лимит попыток исчерпан",
|
||||||
message: () => `Expired magic code. Please try again.`,
|
message: () => "Лимит попыток ввода кода исчерпан. Запросите новый код.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP]: {
|
[EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED_SIGN_UP]: {
|
||||||
title: `Expired magic code`,
|
title: "Лимит попыток исчерпан",
|
||||||
message: () => `Expired magic code. Please try again.`,
|
message: () => "Лимит попыток ввода кода исчерпан. Запросите новый код.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Oauth
|
|
||||||
[EAuthenticationErrorCodes.OAUTH_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.OAUTH_NOT_CONFIGURED]: {
|
||||||
title: `OAuth not configured`,
|
title: "OAuth не настроен",
|
||||||
message: () => `OAuth not configured. Please contact your administrator.`,
|
message: () => "OAuth не настроен. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
|
||||||
title: `Google not configured`,
|
title: "Google OAuth не настроен",
|
||||||
message: () => `Google not configured. Please contact your administrator.`,
|
message: () => "Google OAuth не настроен. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
|
||||||
title: `GitHub not configured`,
|
title: "GitHub OAuth не настроен",
|
||||||
message: () => `GitHub not configured. Please contact your administrator.`,
|
message: () => "GitHub OAuth не настроен. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GITLAB_NOT_CONFIGURED]: {
|
[EAuthenticationErrorCodes.GITLAB_NOT_CONFIGURED]: {
|
||||||
title: `GitLab not configured`,
|
title: "GitLab OAuth не настроен",
|
||||||
message: () => `GitLab not configured. Please contact your administrator.`,
|
message: () => "GitLab OAuth не настроен. Обратитесь к администратору.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
|
[EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
|
||||||
title: `Google OAuth provider error`,
|
title: "Ошибка Google OAuth",
|
||||||
message: () => `Google OAuth provider error. Please try again.`,
|
message: () => "Не удалось авторизоваться через Google. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
|
[EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
|
||||||
title: `GitHub OAuth provider error`,
|
title: "Ошибка GitHub OAuth",
|
||||||
message: () => `GitHub OAuth provider error. Please try again.`,
|
message: () => "Не удалось авторизоваться через GitHub. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.GITLAB_OAUTH_PROVIDER_ERROR]: {
|
[EAuthenticationErrorCodes.GITLAB_OAUTH_PROVIDER_ERROR]: {
|
||||||
title: `GitLab OAuth provider error`,
|
title: "Ошибка GitLab OAuth",
|
||||||
message: () => `GitLab OAuth provider error. Please try again.`,
|
message: () => "Не удалось авторизоваться через GitLab. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Reset Password
|
|
||||||
[EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
|
[EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
|
||||||
title: `Invalid password token`,
|
title: "Некорректный токен",
|
||||||
message: () => `Invalid password token.`,
|
message: () => "Токен сброса пароля некорректен.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
|
[EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
|
||||||
title: `Expired password token`,
|
title: "Токен истёк",
|
||||||
message: () => `Expired password token. Please try again.`,
|
message: () => "Токен сброса пароля истёк. Запросите новый.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Change password
|
|
||||||
[EAuthenticationErrorCodes.MISSING_PASSWORD]: {
|
[EAuthenticationErrorCodes.MISSING_PASSWORD]: {
|
||||||
title: `Password required`,
|
title: "Нужен пароль",
|
||||||
message: () => `Password required. Please try again.`,
|
message: () => "Укажите пароль и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
|
[EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
|
||||||
title: `Incorrect old password`,
|
title: "Неверный старый пароль",
|
||||||
message: () => `Incorrect old password. Please try again.`,
|
message: () => "Неверный старый пароль. Попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
|
[EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
|
||||||
title: `Invalid new password`,
|
title: "Некорректный новый пароль",
|
||||||
message: () => `Invalid new password. Please try again.`,
|
message: () => "Некорректный новый пароль. Проверьте требования и попробуйте снова.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// set password
|
|
||||||
[EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
|
[EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
|
||||||
title: `Password already set`,
|
title: "Пароль уже установлен",
|
||||||
message: () => `Password already set. Please try again.`,
|
message: () => "Пароль уже установлен. Попробуйте войти в систему.",
|
||||||
},
|
},
|
||||||
|
|
||||||
// admin
|
|
||||||
[EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
|
[EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
|
||||||
title: `Admin already exists`,
|
title: "Администратор уже существует",
|
||||||
message: () => `Admin already exists. Please try again.`,
|
message: () => "Администратор уже существует. Проверьте данные и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
|
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
|
||||||
title: `Email, password and first name required`,
|
title: "Нужны имя, e-mail и пароль",
|
||||||
message: () => `Email, password and first name required. Please try again.`,
|
message: () => "Укажите имя, e-mail и пароль, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
|
[EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
|
||||||
title: `Invalid admin email`,
|
title: "Некорректный e-mail администратора",
|
||||||
message: () => `Invalid admin email. Please try again.`,
|
message: () => "Некорректный e-mail администратора. Проверьте адрес и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
|
[EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
|
||||||
title: `Invalid admin password`,
|
title: "Некорректный пароль администратора",
|
||||||
message: () => `Invalid admin password. Please try again.`,
|
message: () => "Некорректный пароль администратора. Проверьте данные и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
|
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
|
||||||
title: `Email and password required`,
|
title: "Нужны e-mail и пароль",
|
||||||
message: () => `Email and password required. Please try again.`,
|
message: () => "Укажите e-mail и пароль, затем попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
|
[EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
|
||||||
title: `Authentication failed`,
|
title: "Не удалось выполнить вход",
|
||||||
message: () => `Authentication failed. Please try again.`,
|
message: () => "Не удалось выполнить вход. Проверьте данные и попробуйте снова.",
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST]: {
|
[EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST]: {
|
||||||
title: `Admin user already exists`,
|
title: "Администратор уже существует",
|
||||||
message: () => (
|
message: () => (
|
||||||
<div>
|
<div>
|
||||||
Admin user already exists.
|
Администратор уже существует.
|
||||||
<Link className="font-medium underline underline-offset-4 transition-all hover:font-bold" href={`/admin`}>
|
<Link className={authLinkClass} href="/admin">
|
||||||
Sign In
|
Войти
|
||||||
</Link>
|
</Link>
|
||||||
now.
|
сейчас.
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
|
[EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
|
||||||
title: `Admin user does not exist`,
|
title: "Администратор не найден",
|
||||||
message: () => (
|
message: () => (
|
||||||
<div>
|
<div>
|
||||||
Admin user does not exist.
|
Администратор не найден.
|
||||||
<Link className="font-medium underline underline-offset-4 transition-all hover:font-bold" href={`/admin`}>
|
<Link className={authLinkClass} href="/admin">
|
||||||
Sign In
|
Войти
|
||||||
</Link>
|
</Link>
|
||||||
now.
|
сейчас.
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED]: {
|
[EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED]: {
|
||||||
title: `Admin user deactivated`,
|
title: "Аккаунт администратора деактивирован",
|
||||||
message: () => <div>Your account is deactivated</div>,
|
message: () => <div>Аккаунт администратора деактивирован.</div>,
|
||||||
},
|
},
|
||||||
[EAuthenticationErrorCodes.RATE_LIMIT_EXCEEDED]: {
|
[EAuthenticationErrorCodes.RATE_LIMIT_EXCEEDED]: {
|
||||||
title: "",
|
title: "",
|
||||||
message: () => `Rate limit exceeded. Please try again later.`,
|
message: () => "Слишком много попыток. Повторите позже.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -427,13 +393,14 @@ export const authErrorHandler = (errorCode: EAuthenticationErrorCodes, email?: s
|
||||||
EAuthenticationErrorCodes.PASSWORD_TOO_WEAK,
|
EAuthenticationErrorCodes.PASSWORD_TOO_WEAK,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (bannerAlertErrorCodes.includes(errorCode))
|
if (bannerAlertErrorCodes.includes(errorCode)) {
|
||||||
return {
|
return {
|
||||||
type: EErrorAlertType.BANNER_ALERT,
|
type: EErrorAlertType.BANNER_ALERT,
|
||||||
code: errorCode,
|
code: errorCode,
|
||||||
title: errorCodeMessages[errorCode]?.title || "Error",
|
title: errorCodeMessages[errorCode]?.title || "Ошибка",
|
||||||
message: errorCodeMessages[errorCode]?.message(email) || "Something went wrong. Please try again.",
|
message: errorCodeMessages[errorCode]?.message(email) || "Что-то пошло не так. Попробуйте снова.",
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -795,4 +795,239 @@
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
border-radius: 0.95rem !important;
|
border-radius: 0.95rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-shell {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 28rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.75rem !important;
|
||||||
|
padding: 1.75rem !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.04) 0%, rgba(255, 255, 255, 0.015) 100%),
|
||||||
|
rgba(10, 10, 12, 0.82) !important;
|
||||||
|
-webkit-backdrop-filter: blur(34px);
|
||||||
|
backdrop-filter: blur(34px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-banner {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.15rem !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.038) 0%, rgba(255, 255, 255, 0.014) 100%),
|
||||||
|
rgba(var(--nodedc-accent-rgb), 0.12) !important;
|
||||||
|
color: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
-webkit-backdrop-filter: blur(24px);
|
||||||
|
backdrop-filter: blur(24px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-input-shell {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.15rem !important;
|
||||||
|
min-height: 3rem;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.028) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
rgba(255, 255, 255, 0.03) !important;
|
||||||
|
-webkit-backdrop-filter: blur(18px);
|
||||||
|
backdrop-filter: blur(18px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-input-shell[data-error="true"] {
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
rgba(255, 82, 82, 0.08) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-input {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
background: transparent !important;
|
||||||
|
color: var(--text-color-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-input::placeholder {
|
||||||
|
color: var(--text-color-placeholder) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-link {
|
||||||
|
color: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-link:hover {
|
||||||
|
color: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 82%, white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-primary-button {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 3.25rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.25rem !important;
|
||||||
|
background: rgb(var(--nodedc-card-active-rgb)) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-auth-primary-button:hover {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-card-active-rgb)) 82%, white) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-error-shell {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 36rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.9rem !important;
|
||||||
|
padding: 2rem !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.04) 0%, rgba(255, 255, 255, 0.015) 100%),
|
||||||
|
rgba(10, 10, 12, 0.82) !important;
|
||||||
|
-webkit-backdrop-filter: blur(36px);
|
||||||
|
backdrop-filter: blur(36px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-error-link {
|
||||||
|
color: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-error-link:hover {
|
||||||
|
color: color-mix(in srgb, rgb(var(--nodedc-accent-rgb)) 82%, white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-error-primary {
|
||||||
|
min-height: 3rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.2rem !important;
|
||||||
|
background: rgb(var(--nodedc-card-active-rgb)) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
padding-inline: 1.35rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-error-primary:hover {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-card-active-rgb)) 82%, white) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-empty-state-primary {
|
||||||
|
min-height: 3rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.2rem !important;
|
||||||
|
background: rgb(var(--nodedc-card-active-rgb)) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
padding-inline: 1.35rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-empty-state-primary:hover {
|
||||||
|
background: color-mix(in srgb, rgb(var(--nodedc-card-active-rgb)) 82%, white) !important;
|
||||||
|
color: #0b1117 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-empty-state-secondary {
|
||||||
|
min-height: 3rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.2rem !important;
|
||||||
|
background: rgba(255, 255, 255, 0.06) !important;
|
||||||
|
color: var(--text-color-primary) !important;
|
||||||
|
padding-inline: 1.25rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-empty-state-secondary:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.1) !important;
|
||||||
|
color: var(--text-color-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-sidebar-shell {
|
||||||
|
border: 0 !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, rgba(255, 255, 255, 0.01) 100%),
|
||||||
|
rgba(8, 8, 11, 0.82) !important;
|
||||||
|
-webkit-backdrop-filter: blur(26px);
|
||||||
|
backdrop-filter: blur(26px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-tab {
|
||||||
|
min-height: 2.8rem;
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 999px !important;
|
||||||
|
background: transparent !important;
|
||||||
|
color: rgba(255, 255, 255, 0.78) !important;
|
||||||
|
padding-inline: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-tab:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.05) !important;
|
||||||
|
color: var(--text-color-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-tab[data-active="true"] {
|
||||||
|
background: rgba(255, 255, 255, 0.06) !important;
|
||||||
|
color: rgb(var(--nodedc-accent-rgb)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-card {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.9rem !important;
|
||||||
|
background: rgb(var(--nodedc-card-passive-rgb)) !important;
|
||||||
|
color: var(--text-color-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-card[data-active="true"] {
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.028) 0%, rgba(255, 255, 255, 0.01) 100%),
|
||||||
|
rgba(255, 255, 255, 0.04) !important;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(var(--nodedc-accent-rgb), 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-panel {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.6rem !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.03) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
rgba(255, 255, 255, 0.028) !important;
|
||||||
|
-webkit-backdrop-filter: blur(22px);
|
||||||
|
backdrop-filter: blur(22px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-section {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.5rem !important;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(255, 255, 255, 0.028) 0%, rgba(255, 255, 255, 0.012) 100%),
|
||||||
|
rgba(255, 255, 255, 0.024) !important;
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodedc-external-empty {
|
||||||
|
border: 0 !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border-radius: 1.35rem !important;
|
||||||
|
background: rgba(255, 255, 255, 0.035) !important;
|
||||||
|
color: var(--text-color-secondary) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,16 @@ export function EmptyStateDetailed({
|
||||||
{actions.map((action, index) => {
|
{actions.map((action, index) => {
|
||||||
const { label, variant, ...rest } = action;
|
const { label, variant, ...rest } = action;
|
||||||
return (
|
return (
|
||||||
<Button key={index} variant={variant} size="xl" {...rest}>
|
<Button
|
||||||
|
key={index}
|
||||||
|
variant={variant}
|
||||||
|
size="xl"
|
||||||
|
className={cn({
|
||||||
|
"nodedc-empty-state-primary": variant === "primary",
|
||||||
|
"nodedc-empty-state-secondary": variant === "secondary",
|
||||||
|
})}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue