fix(desktop): switching app & add error page and skeleton screen (#2390)

This commit is contained in:
zhujingyang
2023-01-13 12:01:02 +08:00
committed by GitHub
parent a74f8473d0
commit 89299d9997
31 changed files with 661 additions and 208 deletions
+1
View File
@@ -35,6 +35,7 @@
"next-pwa": "^5.6.0",
"qrcode.react": "^3.1.0",
"react": "18.2.0",
"react-content-loader": "^6.2.0",
"react-dom": "18.2.0",
"react-draggable": "^4.4.5",
"react-hook-form": "^7.40.0",
+14
View File
@@ -31,6 +31,7 @@ specifiers:
postcss: ^8.4.20
qrcode.react: ^3.1.0
react: 18.2.0
react-content-loader: ^6.2.0
react-dom: 18.2.0
react-draggable: ^4.4.5
react-hook-form: ^7.40.0
@@ -65,6 +66,7 @@ dependencies:
next-pwa: 5.6.0_next@13.1.0
qrcode.react: 3.1.0_react@18.2.0
react: 18.2.0
react-content-loader: registry.npmmirror.com/react-content-loader/6.2.0_react@18.2.0
react-dom: 18.2.0_react@18.2.0
react-draggable: 4.4.5_biqbaboplfbrettd7655fr4n2y
react-hook-form: 7.41.0_react@18.2.0
@@ -8252,3 +8254,15 @@ packages:
oidc-token-hash: 5.0.1
dev: false
optional: true
registry.npmmirror.com/react-content-loader/6.2.0_react@18.2.0:
resolution: {integrity: sha512-r1dI6S+uHNLW68qraLE2njJYOuy6976PpCExuCZUcABWbfnF3FMcmuESRI8L4Bj45wnZ7n8g71hkPLzbma7/Cw==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/react-content-loader/-/react-content-loader-6.2.0.tgz}
id: registry.npmmirror.com/react-content-loader/6.2.0
name: react-content-loader
version: 6.2.0
engines: {node: '>=10'}
peerDependencies:
react: '>=16.0.0'
dependencies:
react: 18.2.0
dev: false
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

@@ -0,0 +1,210 @@
<svg width="247" height="195" viewBox="0 0 247 195" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.8" d="M35.7865 57.5107C34.8311 52.3904 30.358 48.7128 25.1995 48.8064C22.4396 48.7935 19.7758 49.8292 17.7369 51.7079C16.5944 51.1878 15.3557 50.9183 14.1026 50.9172C10.1319 50.854 6.65578 53.5972 5.75651 57.5035C2.70494 58.1848 0.50447 60.8766 0.419922 64.0317C0.537258 67.871 3.69933 70.896 7.50186 70.8065H34.0196C37.8237 70.9 40.9881 67.8728 41.1016 64.0317C41.0187 60.8849 38.8284 58.1977 35.7865 57.5107Z" fill="url(#paint0_linear_5_835)"/>
<path opacity="0.8" d="M189.683 21.9639C188.304 19.8043 185.973 18.4628 183.438 18.3703C181.961 16.0855 179.432 14.7287 176.739 14.7766C174.58 14.7548 172.503 15.6157 170.977 17.1651C170.278 16.939 169.549 16.8232 168.816 16.8218C165.423 16.8218 162.621 19.2029 162.333 22.2122C159.747 22.8373 157.885 25.1282 157.773 27.8218C157.773 31.0649 160.705 33.709 164.256 33.709H189.157C192.758 33.709 195.64 31.0649 195.64 27.8218C195.697 24.7395 193.032 22.2049 189.683 21.9639Z" fill="url(#paint1_linear_5_835)"/>
<path opacity="0.8" d="M235.97 13.942C233.539 8.93344 228.464 5.74623 222.892 5.72898C219.789 5.73565 216.77 6.74086 214.283 8.59566C211.324 2.83009 204.898 -0.277582 198.536 0.980289C192.174 2.23816 187.417 7.5568 186.879 14.0137C180.035 16.1711 175.788 22.9921 176.877 30.0787C177.965 37.1652 184.064 42.4001 191.241 42.4082H231.73C238.949 42.4218 245.084 37.1438 246.142 30.0107C247.201 22.8776 242.861 16.0488 235.949 13.9707L235.97 13.942Z" fill="url(#paint2_linear_5_835)"/>
<path opacity="0.385356" d="M146.482 138.718L190 169.536L113.47 194.172L76.6074 128.759L129.766 128.759L146.482 138.718Z" fill="url(#paint3_linear_5_835)"/>
<path d="M75.7543 73.0077H56.0029V64.3377C56.0029 64.3377 55.5047 56 67.5302 56C79.1414 56 75.7543 73.0077 75.7543 73.0077Z" fill="url(#paint4_linear_5_835)"/>
<path d="M67.0696 56C67.0696 56 74.6556 56.9273 74.6556 66.7203C74.6556 76.5133 74.6556 123.455 74.6556 123.455C74.6556 123.455 74.492 130.777 82.3825 130.777C90.2701 130.777 105.121 130.777 105.121 130.777L116.628 96.8068V69.1002C116.628 69.1002 117.499 56.0027 105.699 56.0027C95.1188 56 67.0696 56 67.0696 56Z" fill="url(#paint5_linear_5_835)"/>
<g filter="url(#filter0_d_5_835)">
<path d="M108.271 64.6418H82.6007C81.9482 64.6418 81.4192 65.1708 81.4192 65.8233V68.501C81.4192 69.1535 81.9482 69.6825 82.6007 69.6825H108.271C108.923 69.6825 109.452 69.1535 109.452 68.501V65.8233C109.452 65.1708 108.923 64.6418 108.271 64.6418Z" fill="url(#paint6_linear_5_835)"/>
</g>
<g filter="url(#filter1_d_5_835)">
<path d="M100.407 74.6173H82.6007C81.9482 74.6173 81.4192 75.1463 81.4192 75.7988V78.4765C81.4192 79.129 81.9482 79.6579 82.6007 79.6579H100.407C101.06 79.6579 101.589 79.129 101.589 78.4765V75.7988C101.589 75.1463 101.06 74.6173 100.407 74.6173Z" fill="url(#paint7_linear_5_835)"/>
</g>
<g filter="url(#filter2_d_5_835)">
<path d="M100.407 84.5922H82.6007C81.9482 84.5922 81.4192 85.1211 81.4192 85.7736V88.4513C81.4192 89.1038 81.9482 89.6328 82.6007 89.6328H100.407C101.06 89.6328 101.589 89.1038 101.589 88.4513V85.7736C101.589 85.1211 101.06 84.5922 100.407 84.5922Z" fill="url(#paint8_linear_5_835)"/>
</g>
<path d="M85.3584 130.777H120.492L116.602 102.454C116.602 102.454 111.709 95.5712 102.087 95.5712C91.248 95.5712 91.7759 105.828 91.7759 106.358C91.7759 106.889 91.7759 124.028 91.7759 124.028C91.7759 124.028 91.7025 130.777 85.3584 130.777Z" fill="url(#paint9_linear_5_835)"/>
<path d="M146.482 138.718H114.179V106.865C114.179 106.865 114.968 95.5714 102.204 95.5714C116.685 95.5714 132.373 95.5714 132.373 95.5714C132.373 95.5714 146.482 95.2177 146.482 109.687C146.482 124.157 146.482 138.718 146.482 138.718Z" fill="url(#paint10_linear_5_835)"/>
<g filter="url(#filter3_d_5_835)">
<path d="M139.436 105.562H121.585C120.933 105.562 120.404 106.091 120.404 106.744V109.422C120.404 110.074 120.933 110.603 121.585 110.603H139.436C140.089 110.603 140.618 110.074 140.618 109.422V106.744C140.618 106.091 140.089 105.562 139.436 105.562Z" fill="url(#paint11_linear_5_835)"/>
</g>
<g filter="url(#filter4_d_5_835)">
<path d="M135.105 115.538H121.585C120.933 115.538 120.404 116.067 120.404 116.719V119.397C120.404 120.05 120.933 120.578 121.585 120.578H135.105C135.757 120.578 136.286 120.05 136.286 119.397V116.719C136.286 116.067 135.757 115.538 135.105 115.538Z" fill="url(#paint12_linear_5_835)"/>
</g>
<g filter="url(#filter5_d_5_835)">
<path d="M137.03 125.513H121.585C120.933 125.513 120.404 126.042 120.404 126.695V129.372C120.404 130.025 120.933 130.554 121.585 130.554H137.03C137.682 130.554 138.211 130.025 138.211 129.372V126.695C138.211 126.042 137.682 125.513 137.03 125.513Z" fill="url(#paint13_linear_5_835)"/>
</g>
<path d="M161.3 128.762C168.106 121.956 168.106 110.921 161.3 104.115C154.494 97.3094 143.46 97.3094 136.653 104.115C129.847 110.921 129.847 121.956 136.653 128.762C143.46 135.568 154.494 135.568 161.3 128.762Z" fill="url(#paint14_linear_5_835)"/>
<path d="M150.719 100.524C157.144 100.521 162.938 104.377 165.399 110.291C167.86 116.206 166.502 123.015 161.959 127.544C157.417 132.072 150.584 133.428 144.647 130.978C138.711 128.528 134.84 122.756 134.84 116.353C134.85 107.615 141.956 100.534 150.725 100.524H150.719ZM150.725 97.3041C140.167 97.3041 131.609 105.833 131.609 116.353C131.609 126.874 140.167 135.402 150.725 135.402C161.282 135.402 169.841 126.874 169.841 116.353C169.841 105.833 161.282 97.3041 150.725 97.3041Z" fill="#0478ED"/>
<path d="M161.791 127.755C161.15 127.755 160.534 128.009 160.079 128.462L159.956 128.585C159.5 129.04 159.243 129.658 159.243 130.302C159.243 130.947 159.5 131.565 159.956 132.019L171.072 143.14C171.527 143.596 172.144 143.853 172.789 143.853C173.433 143.853 174.05 143.596 174.505 143.14L174.628 143.017C175.084 142.562 175.341 141.944 175.341 141.3C175.341 140.655 175.084 140.037 174.628 139.583L163.506 128.462C163.051 128.008 162.434 127.754 161.791 127.755Z" fill="#63A6F9"/>
<path d="M162.865 127.755C162.223 127.755 161.607 128.009 161.152 128.462L161.029 128.585C160.573 129.04 160.316 129.658 160.316 130.302C160.316 130.947 160.573 131.565 161.029 132.019L172.145 143.14C172.6 143.596 173.218 143.853 173.862 143.853C174.506 143.853 175.124 143.596 175.578 143.14L175.701 143.017C176.158 142.562 176.414 141.944 176.414 141.3C176.414 140.655 176.158 140.037 175.701 139.583L164.579 128.462C164.124 128.008 163.507 127.754 162.865 127.755Z" fill="#3597FB"/>
<path d="M149.92 133.792C159.588 133.792 167.426 126.014 167.426 116.42C167.426 106.825 159.588 99.0475 149.92 99.0475C140.251 99.0475 132.414 106.825 132.414 116.42C132.414 126.014 140.251 133.792 149.92 133.792Z" fill="url(#paint15_linear_5_835)"/>
<path d="M149.914 100.255C156.339 100.253 162.133 104.108 164.594 110.023C167.054 115.938 165.697 122.747 161.154 127.275C156.612 131.804 149.779 133.159 143.842 130.709C137.906 128.26 134.035 122.487 134.035 116.085C134.045 107.347 141.151 100.265 149.92 100.255H149.914ZM149.92 97.0356C139.362 97.0356 130.804 105.564 130.804 116.085C130.804 126.605 139.362 135.134 149.92 135.134C160.477 135.134 169.036 126.605 169.036 116.085C169.036 105.564 160.477 97.0356 149.92 97.0356Z" fill="url(#paint16_linear_5_835)"/>
<path d="M144.249 118.154C145.415 119.807 147.828 119.66 147.828 119.66C147.224 119.093 146.832 118.574 146.792 117.097C146.752 115.619 145.888 115.228 145.888 115.228C147.436 114.279 146.883 113.251 146.832 112.106C146.802 111.392 147.235 110.864 147.576 110.56C145.609 110.847 143.832 111.862 142.614 113.393C141.397 114.925 140.834 116.854 141.043 118.78C141.183 118.398 143.174 116.627 144.249 118.154Z" fill="url(#paint17_linear_5_835)"/>
<path d="M158.454 115.288C158.402 115.124 158.339 114.963 158.264 114.808V114.798C157.915 114.088 157.337 113.517 156.623 113.177C155.909 112.837 155.102 112.748 154.331 112.925C153.56 113.103 152.872 113.535 152.378 114.153C151.884 114.77 151.613 115.537 151.609 116.328C151.609 116.577 151.636 116.825 151.689 117.068C151.689 117.072 151.689 117.075 151.689 117.078C151.709 117.178 151.739 117.278 151.769 117.378C151.947 118.083 151.982 118.816 151.871 119.535C151.76 120.253 151.505 120.941 151.123 121.559C150.74 122.177 150.237 122.711 149.643 123.129C149.05 123.548 148.378 123.843 147.668 123.996C146.959 124.15 146.225 124.158 145.512 124.021C144.799 123.885 144.12 123.606 143.517 123.201C142.914 122.796 142.399 122.274 142.002 121.665C141.605 121.057 141.334 120.374 141.207 119.659C141.387 120.899 141.826 122.087 142.495 123.147C143.163 124.207 144.047 125.114 145.088 125.81C146.129 126.507 147.305 126.976 148.539 127.189C149.773 127.402 151.038 127.353 152.252 127.045C153.466 126.738 154.601 126.178 155.586 125.403C156.57 124.629 157.381 123.656 157.965 122.547C158.55 121.439 158.896 120.22 158.98 118.97C159.064 117.719 158.885 116.465 158.454 115.288Z" fill="url(#paint18_linear_5_835)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M157.138 117.648C157.138 121.961 153.571 125.457 149.17 125.457C146.834 125.457 144.733 124.472 143.276 122.903C143.364 122.969 143.455 123.032 143.547 123.093C144.157 123.494 144.842 123.77 145.563 123.905C146.284 124.041 147.025 124.032 147.742 123.88C148.46 123.729 149.139 123.437 149.738 123.023C150.338 122.608 150.847 122.08 151.234 121.468C151.62 120.857 151.877 120.176 151.99 119.465C152.102 118.754 152.067 118.029 151.887 117.331C151.856 117.232 151.826 117.133 151.806 117.034C151.806 117.031 151.806 117.028 151.806 117.025C151.752 116.784 151.725 116.538 151.725 116.292C151.729 115.509 152.003 114.75 152.502 114.139C153.002 113.528 153.697 113.1 154.476 112.925C154.797 112.852 155.125 112.825 155.45 112.841C156.507 114.166 157.138 115.835 157.138 117.648Z" fill="url(#paint19_linear_5_835)"/>
<path d="M155.973 109.601V109.454C155.973 109.246 156.016 109.055 156.111 108.882C156.189 108.726 156.31 108.57 156.475 108.431C156.882 108.076 157.125 107.851 157.203 107.756C157.42 107.478 157.532 107.123 157.532 106.698C157.532 106.178 157.359 105.763 157.012 105.459C156.666 105.147 156.215 105 155.661 105C155.019 105 154.517 105.182 154.153 105.555C153.789 105.919 153.607 106.412 153.607 107.045H154.517C154.517 106.664 154.595 106.369 154.751 106.161C154.924 105.91 155.21 105.789 155.6 105.789C155.912 105.789 156.163 105.875 156.336 106.048C156.501 106.222 156.588 106.456 156.588 106.759C156.588 106.984 156.501 107.192 156.345 107.392L156.198 107.556C155.661 108.033 155.331 108.388 155.219 108.631C155.097 108.856 155.045 109.133 155.045 109.454V109.601H155.973ZM155.505 111.308C155.678 111.308 155.834 111.248 155.955 111.135C156.076 111.014 156.146 110.866 156.146 110.684C156.146 110.502 156.085 110.355 155.964 110.242C155.843 110.121 155.687 110.069 155.505 110.069C155.331 110.069 155.175 110.121 155.054 110.242C154.933 110.355 154.872 110.502 154.872 110.684C154.872 110.858 154.933 111.005 155.054 111.126C155.175 111.248 155.331 111.308 155.505 111.308Z" fill="url(#paint20_linear_5_835)"/>
<path d="M155.598 109.601V109.454C155.598 109.246 155.642 109.055 155.737 108.882C155.815 108.726 155.936 108.57 156.101 108.431C156.508 108.076 156.751 107.851 156.829 107.756C157.045 107.478 157.158 107.123 157.158 106.698C157.158 106.178 156.985 105.763 156.638 105.459C156.291 105.147 155.841 105 155.286 105C154.645 105 154.143 105.182 153.779 105.555C153.415 105.919 153.233 106.412 153.233 107.045H154.143C154.143 106.664 154.22 106.369 154.376 106.161C154.55 105.91 154.836 105.789 155.226 105.789C155.538 105.789 155.789 105.875 155.962 106.048C156.127 106.222 156.213 106.456 156.213 106.759C156.213 106.984 156.127 107.192 155.971 107.392L155.824 107.556C155.286 108.033 154.957 108.388 154.844 108.631C154.723 108.856 154.671 109.133 154.671 109.454V109.601H155.598ZM155.13 111.308C155.304 111.308 155.46 111.248 155.581 111.135C155.702 111.014 155.772 110.866 155.772 110.684C155.772 110.502 155.711 110.355 155.59 110.242C155.468 110.121 155.312 110.069 155.13 110.069C154.957 110.069 154.801 110.121 154.68 110.242C154.558 110.355 154.498 110.502 154.498 110.684C154.498 110.858 154.558 111.005 154.68 111.126C154.801 111.248 154.957 111.308 155.13 111.308Z" fill="url(#paint21_linear_5_835)"/>
<defs>
<filter id="filter0_d_5_835" x="81.4192" y="64.6418" width="28.7332" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<filter id="filter1_d_5_835" x="81.4192" y="74.6173" width="20.8697" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<filter id="filter2_d_5_835" x="81.4192" y="84.5922" width="20.8697" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<filter id="filter3_d_5_835" x="120.404" y="105.562" width="20.9141" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<filter id="filter4_d_5_835" x="120.404" y="115.538" width="16.5826" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<filter id="filter5_d_5_835" x="120.404" y="125.513" width="18.5076" height="5.74065" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="0.5" dy="0.5"/>
<feGaussianBlur stdDeviation="0.1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0156863 0 0 0 0 0.470588 0 0 0 0 0.929412 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_835"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_5_835" result="shape"/>
</filter>
<linearGradient id="paint0_linear_5_835" x1="20.7464" y1="70.8357" x2="20.7464" y2="48.7917" gradientUnits="userSpaceOnUse">
<stop offset="0.208333" stop-color="white" stop-opacity="0"/>
<stop offset="0.494792" stop-color="#F7FAFF" stop-opacity="0.213439"/>
<stop offset="0.755208" stop-color="#EFF6FF" stop-opacity="0.409091"/>
<stop offset="1" stop-color="#D9E9FF"/>
</linearGradient>
<linearGradient id="paint1_linear_5_835" x1="176.661" y1="33.722" x2="176.661" y2="14.7633" gradientUnits="userSpaceOnUse">
<stop offset="0.0207315" stop-color="white" stop-opacity="0"/>
<stop offset="0.404824" stop-color="#F5F9FF" stop-opacity="0.1"/>
<stop offset="0.571948" stop-color="#EEF5FF" stop-opacity="0.3"/>
<stop offset="0.772394" stop-color="#E4EFFF" stop-opacity="0.74"/>
<stop offset="1" stop-color="#D9E9FF"/>
</linearGradient>
<linearGradient id="paint2_linear_5_835" x1="211.419" y1="42.4369" x2="211.419" y2="0.676424" gradientUnits="userSpaceOnUse">
<stop offset="0.0207315" stop-color="white" stop-opacity="0"/>
<stop offset="0.404824" stop-color="#F5F9FF" stop-opacity="0.1"/>
<stop offset="0.571948" stop-color="#EEF5FF" stop-opacity="0.3"/>
<stop offset="0.772394" stop-color="#E4EFFF" stop-opacity="0.74"/>
<stop offset="1" stop-color="#D9E9FF"/>
</linearGradient>
<linearGradient id="paint3_linear_5_835" x1="133.007" y1="175.307" x2="124.579" y2="143.583" gradientUnits="userSpaceOnUse">
<stop stop-color="white" stop-opacity="0"/>
<stop offset="1" stop-color="#8EC3FF"/>
</linearGradient>
<linearGradient id="paint4_linear_5_835" x1="76.6075" y1="86.369" x2="56" y2="47.8655" gradientUnits="userSpaceOnUse">
<stop stop-color="#F6FBFF"/>
<stop offset="1" stop-color="#ACD2FA"/>
</linearGradient>
<linearGradient id="paint5_linear_5_835" x1="66.846" y1="56" x2="104.545" y2="98.7528" gradientUnits="userSpaceOnUse">
<stop stop-color="#EDF5FF"/>
<stop offset="1" stop-color="#2692FF"/>
</linearGradient>
<linearGradient id="paint6_linear_5_835" x1="106.977" y1="70.0998" x2="103.606" y2="59.5272" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint7_linear_5_835" x1="99.8076" y1="80.0753" x2="95.4935" y2="70.3396" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint8_linear_5_835" x1="99.8076" y1="90.0501" x2="95.4935" y2="80.3144" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint9_linear_5_835" x1="128.126" y1="130.838" x2="85.2869" y2="95.0426" gradientUnits="userSpaceOnUse">
<stop stop-color="#F5FBFF"/>
<stop offset="1" stop-color="#89BEF8"/>
</linearGradient>
<linearGradient id="paint10_linear_5_835" x1="96.6729" y1="99.9266" x2="135.719" y2="120.534" gradientUnits="userSpaceOnUse">
<stop stop-color="#EDF7FF"/>
<stop offset="1" stop-color="#2792FF"/>
</linearGradient>
<linearGradient id="paint11_linear_5_835" x1="138.832" y1="111.02" x2="134.525" y2="101.278" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint12_linear_5_835" x1="134.883" y1="120.996" x2="129.905" y2="112.15" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint13_linear_5_835" x1="136.639" y1="130.971" x2="131.969" y2="121.668" gradientUnits="userSpaceOnUse">
<stop stop-color="#D9E9FF"/>
<stop offset="0.31" stop-color="#DFECFF"/>
<stop offset="0.73" stop-color="#F0F6FF"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
<linearGradient id="paint14_linear_5_835" x1="166.053" y1="113.783" x2="131.968" y2="113.914" gradientUnits="userSpaceOnUse">
<stop stop-color="#D2E8FF"/>
<stop offset="1" stop-color="#D2E8FF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="paint15_linear_5_835" x1="141.141" y1="99.3843" x2="166.087" y2="129.211" gradientUnits="userSpaceOnUse">
<stop stop-color="#E3F1FF"/>
<stop offset="1" stop-color="#D2E8FF"/>
</linearGradient>
<linearGradient id="paint16_linear_5_835" x1="136.078" y1="103.699" x2="159.749" y2="131.393" gradientUnits="userSpaceOnUse">
<stop stop-color="#ACD4FE"/>
<stop offset="1" stop-color="#379AFF"/>
</linearGradient>
<linearGradient id="paint17_linear_5_835" x1="141.765" y1="112.114" x2="144.208" y2="120.774" gradientUnits="userSpaceOnUse">
<stop stop-color="#C8E0FF"/>
<stop offset="1" stop-color="#4CA2FD"/>
</linearGradient>
<linearGradient id="paint18_linear_5_835" x1="148.635" y1="114.156" x2="154" y2="125.914" gradientUnits="userSpaceOnUse">
<stop stop-color="#B7D9FE"/>
<stop offset="1" stop-color="#3597FB"/>
</linearGradient>
<linearGradient id="paint19_linear_5_835" x1="151.178" y1="112.924" x2="153.474" y2="127.879" gradientUnits="userSpaceOnUse">
<stop stop-color="#C9E0FF"/>
<stop offset="0.35936" stop-color="#8ABDFF"/>
<stop offset="1" stop-color="#3094FF"/>
</linearGradient>
<linearGradient id="paint20_linear_5_835" x1="155.57" y1="105" x2="155.57" y2="111.308" gradientUnits="userSpaceOnUse">
<stop stop-color="#3E9DFC"/>
<stop offset="1" stop-color="#0478ED"/>
</linearGradient>
<linearGradient id="paint21_linear_5_835" x1="153.233" y1="105" x2="156.912" y2="110.257" gradientUnits="userSpaceOnUse">
<stop stop-color="#94CDF3"/>
<stop offset="1" stop-color="#378DF2"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

@@ -0,0 +1,24 @@
<svg width="104" height="110" viewBox="0 0 104 110" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M95.6398 35.9114C95.3711 35.0494 95.041 34.2082 94.6525 33.394V33.3416C92.8389 29.6178 89.8319 26.6216 86.1194 24.8389C82.4066 23.0563 78.2063 22.592 74.1992 23.5209C70.1922 24.4499 66.6138 26.718 64.0443 29.957C61.4747 33.1962 60.0649 37.2164 60.0434 41.3656C60.0437 42.6706 60.1832 43.9719 60.4592 45.2467C60.4605 45.264 60.4605 45.2816 60.4592 45.2991C60.563 45.8236 60.7189 46.348 60.875 46.8724C61.8023 50.5669 61.9829 54.4121 61.4054 58.1785C60.8282 61.9449 59.505 65.5553 57.5146 68.7943C55.5244 72.0331 52.908 74.8343 49.8216 77.0301C46.7352 79.2262 43.242 80.7722 39.5504 81.5758C35.859 82.3794 32.0449 82.4242 28.3359 81.7076C24.627 80.9908 21.0991 79.5274 17.9629 77.4045C14.8266 75.2815 12.1463 72.5428 10.0819 69.3513C8.01747 66.1601 6.61129 62.5817 5.94727 58.83C6.88627 65.3334 9.16805 71.5655 12.6449 77.1224C16.1218 82.6796 20.7163 87.4379 26.1309 91.0891C31.5453 94.7406 37.6593 97.2036 44.0769 98.319C50.4947 99.4345 57.0728 99.1774 63.3858 97.5643C69.6986 95.9512 75.6055 93.0181 80.724 88.9549C85.8424 84.8919 90.0585 79.7891 93.0989 73.9773C96.1394 68.1655 97.9367 61.7739 98.3744 55.2166C98.8121 48.6593 97.8804 42.0822 95.6398 35.9114Z" fill="url(#paint0_linear_992_3384)"/>
<path d="M21.7968 51.6973C27.8248 60.5606 40.2965 59.7738 40.2965 59.7738C37.1787 56.7321 35.152 53.9526 34.9441 46.0333C34.7362 38.1141 30.2673 36.0163 30.2673 36.0163C38.27 30.9292 35.4119 25.4224 35.152 19.2863C34.9961 15.4578 37.2305 12.6258 38.9975 11C28.8281 12.5373 19.6393 17.9767 13.3464 26.1839C7.05351 34.3913 4.14234 44.7334 5.21982 55.0539C5.94733 53.0085 16.2365 43.5159 21.7968 51.6973Z" fill="url(#paint1_linear_992_3384)"/>
<path d="M95.6398 35.9114C95.3711 35.0494 95.041 34.2082 94.6525 33.394V33.3416C92.8389 29.6178 89.8319 26.6216 86.1194 24.8389C82.4066 23.0563 78.2063 22.592 74.1992 23.5209C70.1922 24.4499 66.6138 26.718 64.0443 29.957C61.4747 33.1962 60.0649 37.2164 60.0434 41.3656C60.0438 42.6706 60.1832 43.9719 60.4592 45.2467C60.4605 45.264 60.4605 45.2816 60.4592 45.2991C60.563 45.8236 60.7189 46.348 60.875 46.8724C61.8023 50.5669 61.9829 54.4121 61.4054 58.1785C60.8282 61.9449 59.505 65.5553 57.5146 68.7943C55.5244 72.0331 52.908 74.8343 49.8216 77.0301C46.7352 79.2262 43.242 80.7722 39.5504 81.5758C35.859 82.3794 32.0449 82.4242 28.3359 81.7076C24.627 80.9908 21.0991 79.5274 17.9629 77.4045C14.8266 75.2815 12.1463 72.5428 10.0819 69.3513C8.01747 66.1601 6.61129 62.5817 5.94727 58.83C6.88627 65.3334 9.16805 71.5655 12.6449 77.1224C16.1218 82.6796 20.7163 87.4379 26.1309 91.0891C31.5453 94.7406 37.6593 97.2036 44.0769 98.319C50.4947 99.4345 57.0728 99.1774 63.3858 97.5643C69.6986 95.9512 75.6055 93.0181 80.724 88.9549C85.8424 84.8919 90.0585 79.7891 93.0989 73.9773C96.1394 68.1655 97.9367 61.7739 98.3744 55.2166C98.8121 48.6593 97.8804 42.0822 95.6398 35.9114Z" fill="url(#paint2_linear_992_3384)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M87.8971 48.5506C87.8971 71.4037 69.5403 89.9299 46.8962 89.9299C34.8777 89.9299 24.067 84.711 16.5676 76.3962C17.0219 76.7462 17.4872 77.0824 17.963 77.4045C21.0992 79.5275 24.6271 80.9908 28.336 81.7076C32.0452 82.4242 35.8591 82.3795 39.5505 81.5759C43.2421 80.7722 46.7353 79.2262 49.8217 77.0302C52.9081 74.8343 55.5246 72.0331 57.5149 68.7943C59.5051 65.5553 60.8283 61.945 61.4057 58.1785C61.983 54.4121 61.8024 50.5669 60.875 46.8724C60.7192 46.348 60.5631 45.8236 60.4593 45.2992C60.4606 45.2816 60.4606 45.264 60.4593 45.2467C60.1833 43.9719 60.0438 42.6707 60.0435 41.3657C60.065 37.2164 61.4748 33.1962 64.0444 29.957C66.6139 26.718 70.1923 24.4499 74.1993 23.5209C75.8524 23.1377 77.5384 22.9916 79.2094 23.0773C84.6528 30.1003 87.8971 38.9431 87.8971 48.5506Z" fill="url(#paint3_linear_992_3384)"/>
<defs>
<linearGradient id="paint0_linear_992_3384" x1="91.2488" y1="28.4748" x2="24.3277" y2="90.8058" gradientUnits="userSpaceOnUse">
<stop stop-color="#6378FF"/>
<stop offset="1" stop-color="#6312FF"/>
</linearGradient>
<linearGradient id="paint1_linear_992_3384" x1="9.40376" y1="31.7721" x2="40.0444" y2="51.8157" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEEFF"/>
<stop offset="1" stop-color="#ACD4FF"/>
</linearGradient>
<linearGradient id="paint2_linear_992_3384" x1="112.247" y1="101.124" x2="59.341" y2="23.4234" gradientUnits="userSpaceOnUse">
<stop stop-color="#97CCFF"/>
<stop offset="1" stop-color="#D0E7FF"/>
</linearGradient>
<linearGradient id="paint3_linear_992_3384" x1="87.5038" y1="81.8221" x2="61.6229" y2="22.7447" gradientUnits="userSpaceOnUse">
<stop stop-color="#C4DBFB"/>
<stop offset="1" stop-color="#F1F6FE"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

@@ -28,8 +28,9 @@ $background-max-hover: rgba(255, 255, 255, 0.65);
}
.backgroundWrap {
background-image: url('/images/appstore/appstore_background.png');
background-image: url('/images/appstore/background.png');
background-size: cover;
background-position: top;
}
.baseCard {
@@ -27,6 +27,7 @@ export type TAppDetail = {
name: string;
tags: TTag[];
size: number;
type: 'cluster-image' | 'cloud-image';
};
export const ImagehubLabels = [
@@ -47,6 +48,14 @@ export type TImageLabels = {
checked: boolean;
};
export type TAppInfo = {
icon: string;
keywords: string[];
name: string;
description?: string;
size: number;
};
export function handleImageName(imageName: string): { name: string; tag: string } {
let result = imageName.split(':');
return { name: result[0], tag: result[1] };
@@ -68,3 +77,17 @@ export function getSelectLabels(labels: TImageLabels[]): string {
.filter((item) => item)
.join(',');
}
export function sortByName(arr: TAppInfo[]) {
const map = new Map();
const result = [];
for (const item of arr) {
map.set(item.name, item);
}
let mapKeys = [...map.keys()];
mapKeys.sort();
for (const name of mapKeys) {
result.push(map.get(name));
}
return result;
}
@@ -0,0 +1,7 @@
import Image from 'next/image';
function Error() {
return <Image src={'/images/appstore/error.svg'} alt="err" width={240} height={240} />;
}
export default Error;
@@ -0,0 +1,41 @@
import React from 'react';
import ContentLoader from 'react-content-loader';
const CardLoader = (props: any) => (
<ContentLoader
speed={2}
width={500}
height={160}
viewBox="0 0 600 160"
backgroundColor="#d9e2ef"
foregroundColor="#daebfa"
{...props}
>
<rect x="155" y="30" rx="8" ry="8" width="120" height="20" />
<circle cx="75" cy="80" r="55" />
<rect x="156" y="60" rx="8" ry="8" width="300" height="12" />
<rect x="156" y="80" rx="8" ry="8" width="300" height="12" />
</ContentLoader>
);
const ListContextLoading = () => {
const count = ['one', 'two', 'three', 'four', 'five'];
const cardStyle = {
background: 'rgba(255, 255, 255, 0.75)',
borderRadius: '12px',
height: '160px'
};
return (
<div className="flex flex-col space-y-4 absolute w-full pb-8">
{count.map((i) => {
return (
<div className={'mr-8'} style={cardStyle} key={i}>
<CardLoader />
</div>
);
})}
</div>
);
};
export { ListContextLoading };
@@ -20,9 +20,11 @@
.xLabels {
display: flex;
height: 32px;
align-items: center;
border-radius: 8px;
background: rgba(255, 255, 255, 0.75);
padding: 6px 16px;
padding: 0 16px;
margin-bottom: 12px;
& .tag + .tag {
.border1px {
@@ -35,15 +37,17 @@
color: rgba(35, 155, 242, 1);
}
.deleteIcon svg {
width: 12px;
height: 12px;
margin-left: 8px;
}
.border1px {
display: none;
border-right: 1px solid rgba(218, 218, 218, 1);
height: 12px;
margin: 0 8px;
}
.clearLabels {
cursor: pointer;
margin-left: 24px;
font-weight: 500;
font-size: 14px;
color: #8b949e;
}
@@ -12,10 +12,11 @@ type TLabels = {
display: 'column' | 'row';
labels: TImageLabels[];
onChange: (value: string) => void;
onClear?: () => void;
};
function Labels(props: TLabels) {
const { display, labels, onChange } = props;
const { display, labels, onChange, onClear } = props;
if (display === 'row' && labels?.length > 0) {
return (
@@ -31,12 +32,15 @@ function Labels(props: TLabels) {
>
<span className={styles.border1px}></span>
<span> {item.value} </span>
<span className={styles.deleteIcon}>
<Iconfont iconName="icon-delete-grey-copy" />
<span className="ml-2">
<Iconfont iconName="icon-delete" color="#8B949E" />
</span>
</div>
);
})}
<span className={styles.clearLabels} onClick={onClear}>
清空
</span>
</div>
);
}
@@ -2,10 +2,6 @@
.appHeader {
padding: 8px 16px 16px 16px;
.nav svg {
width: 26px;
height: 26px;
}
}
.mainLeft {
@@ -14,16 +10,18 @@
}
.mainRight {
flex: 1 1 260px;
flex: 0 1 260px;
}
.tag {
cursor: pointer;
height: 42px;
display: flex;
align-items: center;
padding: 0 12px;
background: rgba(255, 255, 255, 0.8);
border-radius: 8px;
border: 1px solid transparent;
}
.markDownWrap div {
@@ -42,7 +40,7 @@
.markdownTitle {
margin-left: 12px;
font-weight: 600;
font-weight: 500;
font-size: 16px;
line-height: 22px;
color: #0d1a2d;
@@ -109,3 +107,48 @@
margin-left: 16px;
}
}
.activeTag {
border: 1px solid #239bf2;
color: #239bf2;
}
.appCommand {
background-color: #4d5060;
border-radius: 8px;
padding: 16px;
color: #ffffff;
font-size: 12px;
line-height: 20px;
position: relative;
.copyBtn {
position: absolute;
top: 10px;
right: 18px;
width: 24px;
height: 24px;
border-radius: 8px;
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
}
}
.popover {
opacity: 0;
position: absolute;
padding: 8px;
width: 80px;
border-radius: 16px;
background: #ffffff;
bottom: 40px;
color: #333333;
text-align: center;
transition: all 0.5 ease;
}
.active {
opacity: 1;
}
@@ -1,10 +1,8 @@
/* eslint-disable @next/next/no-img-element */
import { DocumentOnePage20Filled, Tag16Filled } from '@fluentui/react-icons';
import { useQuery } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import clsx from 'clsx';
import Iconfont from 'components/iconfont';
import MarkDown from 'components/markdown';
import produce from 'immer';
import { useEffect, useRef, useState } from 'react';
import request from 'services/request';
import useSessionStore from 'stores/session';
@@ -18,97 +16,90 @@ export default function DetailPage() {
const appRef = useRef<HTMLDivElement>(null);
const [isFixed, setFixed] = useState(false);
const { kubeconfig } = useSessionStore((state) => state.getSession());
const [appDetailStatus, setAppDetailStatus] = useState(false);
const [appTags, setAppTags] = useState<TTag[]>();
const [selectTag, setSelectTag] = useState('');
const [selectTag, setSelectTag] = useState(handleImageName(detailAppName).tag);
let fullImageName: string = handleImageName(detailAppName).name + ':' + selectTag;
let imageCommand: string = 'sealos run ' + fullImageName;
const [open, setOpen] = useState(false);
const queryClient = useQueryClient();
const { data } = useQuery(
['getAppDetail'],
const { data, isLoading, isSuccess } = useQuery(
['getAppDetail', fullImageName],
async () => {
const res = await request.post('/api/image_hub/get_detail', {
kubeconfig,
image_name: detailAppName
image_name: fullImageName
});
if (res.data.code === 200) {
setAppDetailStatus(true);
}
return res;
},
{
refetchInterval: !appDetailStatus ? 2 * 1000 : false,
enabled: !appDetailStatus
onSuccess: (data) => {
if (data.status === 201) {
queryClient.invalidateQueries({ queryKey: ['getAppDetail', fullImageName] });
}
}
}
);
let appDetail = {} as TAppDetail;
if (appDetailStatus) {
appDetail = data?.data?.items[0];
if (data?.status === 200) {
appDetail = data.data[0];
}
const handleCopy = (value: string) => {
let timer: number;
setOpen((s) => {
if (!open) {
timer = window.setTimeout(() => setOpen(false), 1000);
} else {
window.clearTimeout(timer);
}
return !s;
});
navigator.clipboard.writeText(value);
};
const handleScrollEvent = () => {
const scrollTop = appRef.current?.scrollTop;
if (scrollTop && scrollTop > 20) {
setFixed(true);
} else {
setFixed(false);
}
};
const handleSelectTag = (tagName: string) => {
setAppTags(
produce((draft) => {
const lastItem = draft?.find((item) => item.checked === true);
if (lastItem) {
lastItem.checked = false;
}
const selectItem = draft?.find((item) => item.name === tagName);
if (selectItem) {
setSelectTag(selectItem.name);
selectItem.checked = true;
}
})
);
setFixed(Boolean(scrollTop && scrollTop > 20));
};
useEffect(() => {
appRef.current?.addEventListener('scroll', handleScrollEvent);
if (appDetail.tags && appDetail.tags.length > 0) {
setAppTags(
produce(appDetail.tags, (draft) => {
draft[0].checked = true;
})
);
setSelectTag(appDetail.tags[0].name);
}
}, [appDetail.tags]);
return () => {
appRef.current?.removeEventListener('scroll', handleScrollEvent);
};
}, []);
return (
<div className={clsx(styles.backgroundWrap, 'flex flex-col grow h-full p-8 pb-0')}>
<div className={clsx(styles.baseCard, styles.appHeader, 'w-full')}>
<div
className={clsx(styles.nav, 'cursor-pointer ')}
className={clsx('cursor-pointer w-60')}
onClick={() => toPage(EPageType.StorePage, '')}
>
<Iconfont iconName="icon-back" />
</div>
<div className={clsx(styles.appInfo, { [styles.fixed]: isFixed })}>
<div className={styles.image}>
<img src={appDetail?.icon} alt={appDetail?.name} />
<img
src={appDetail?.icon ?? '/images/appstore/image_empty.svg'}
alt={appDetail?.name}
/>
</div>
<div className={clsx(styles.appDesc)}>
<div className={clsx(styles.title, 'flex items-center')}>
<div>{selectTag && handleImageName(appDetail?.name).name + ':' + selectTag}</div>
<div>{fullImageName}</div>
<div className={styles.fingerPrint}>
<Iconfont iconName="icon-hash" />
<Iconfont iconName="icon-hash" color="#239BF2" />
<span className={styles.imageId}>{appDetail.ID?.substring(0, 12)}</span>
</div>
</div>
<p className={styles.text}>{appDetail?.description}</p>
<div className={styles.installBtn}>
{/* <div className={styles.installBtn}>
<Button handleClick={() => {}} type="primary">
安装 | {selectTag}
</Button>
</div>
</div> */}
<div className={clsx(styles.imageLabels, 'flex space-x-4 mb-4')}>
{appDetail?.keywords?.map((item) => {
return (
@@ -119,10 +110,10 @@ export default function DetailPage() {
})}
</div>
</div>
<div className={styles.rightInfo}>
{/* <div className={styles.rightInfo}>
<span className={styles.imageSizeText}> 19.1K </span>
<span className="text-stone-500 text-xs mt-2">下载量</span>
</div>
</div> */}
<div className={clsx(styles.rightInfo, 'ml-4')}>
<span className={styles.imageSizeText}>
{appDetail.size ? formattedSize(appDetail.size) : 'empty'}
@@ -134,11 +125,11 @@ export default function DetailPage() {
{appDetail.size ? formattedSize(appDetail.size) : ''}
</span>
</div>
<div className={clsx(styles.fixedRightInfo)}>
{/* <div className={clsx(styles.fixedRightInfo)}>
<Button handleClick={() => {}} type="primary">
安装 | {selectTag}
</Button>
</div>
</div> */}
</div>
</div>
<div className={clsx('flex grow my-4')}>
@@ -149,10 +140,19 @@ export default function DetailPage() {
<div className="absolute w-full py-8 px-6 ">
<div className={clsx('flex items-center mb-4')}>
<div className={styles.iconBtn}>
<DocumentOnePage20Filled primaryFill=" #717D8A" />
<Iconfont iconName="icon-overview" />
</div>
<span className={styles.markdownTitle}>概况</span>
<span className={styles.markdownTitle}>概览</span>
</div>
{appDetail.type === 'cluster-image' ? (
<div className={styles.appCommand}>
<div className={styles.copyBtn} onClick={() => handleCopy(imageCommand)}>
<Iconfont iconName="icon-copy" />
<div className={clsx(styles.popover, open ? styles.active : '')}>copyed</div>
</div>
<div>{imageCommand}</div>
</div>
) : null}
<div className={styles.markDownWrap}>
<MarkDown text={appDetail?.docs} isShowCopyBtn={false}></MarkDown>
</div>
@@ -162,24 +162,23 @@ export default function DetailPage() {
<div className="absolute w-full pt-8 px-6 ">
<div className={clsx('flex items-center mb-4')}>
<div className={styles.iconBtn}>
<Tag16Filled primaryFill=" #717D8A" />
<Iconfont iconName="icon-tag" />
</div>
<div className="text-lg ml-4 font-medium">Tags</div>
<div></div>
<div className={styles.markdownTitle}>Tags</div>
</div>
<div className={clsx('w-full space-y-2')}>
{appTags?.map((item) => {
{appDetail.tags?.map((item) => {
return (
<div
className={styles.tag}
key={item.name}
onClick={() => handleSelectTag(item.name)}
className={clsx(styles.tag, { [styles.activeTag]: selectTag === item.name })}
onClick={() => setSelectTag(item.name)}
>
<div className={clsx('w-12', { 'opacity-0': !item.checked })}>
<Iconfont iconName="icon-checked" />
<Iconfont iconName={'icon-checked'} color={'#239BF2'} />
</div>
<div>{item.name}</div>
<div className="ml-auto">size</div>
{/* <div className="ml-auto">size</div> */}
</div>
);
})}
@@ -29,7 +29,7 @@ export default function AppStore() {
return (
<ApppStoreContext.Provider value={{ toPage, detailAppName }}>
<div className={clsx(styles.backgroundWrap, 'flex grow flex-col h-full p-6')}>
<div className={clsx(styles.backgroundWrap, 'flex grow flex-col h-full p-6 pb-0')}>
{pageId === EPageType.StorePage && <StorePage />}
{pageId === EPageType.OrganizationPage && <OrganizationPage />}
{pageId === EPageType.MinePage && <MinePage />}
@@ -13,20 +13,16 @@ import {
handleImageName,
ImagehubLabels,
TImageLabels,
getSelectLabels
getSelectLabels,
TAppInfo,
sortByName
} from './app_store_common';
import Button from './components/button';
import Labels from './components/labels';
import Error from './components/error';
import { useAppStoreContext } from './index';
import styles from './store_page.module.scss';
type TAppInfo = {
icon: string;
keywords: string[];
name: string;
description?: string;
size: number;
};
import { ListContextLoading } from './components/imagehub_loading';
function StorePage() {
const { toPage } = useAppStoreContext();
@@ -46,13 +42,16 @@ function StorePage() {
},
{
onSuccess: (data) => {
if (data.data.code === 201) {
if (data.status === 201) {
queryClient.invalidateQueries({ queryKey: ['getAppLists', selectedLabels] });
}
}
}
);
const appLists = data?.data?.items as TAppInfo[];
let appLists: TAppInfo[] = [];
if (data?.status === 200) {
appLists = sortByName(data.data);
}
const handleLabelsChange = (value: string) => {
setImageLabels(
@@ -65,6 +64,12 @@ function StorePage() {
);
};
const handleLabelsClear = () => {
setImageLabels(
produce((draft: TImageLabels[]) => draft.forEach((item) => (item.checked = false)))
);
};
return (
<div className="grow flex">
<div className={clsx(styles.labelsScrollWrap)}>
@@ -78,14 +83,16 @@ function StorePage() {
display="row"
labels={imageLabels.filter((item) => item.checked)}
onChange={handleLabelsChange}
onClear={handleLabelsClear}
/>
</div>
{isLoading && (
{isError && (
<div className="w-full h-full flex justify-center items-center">
<Spinner />
<Error />
</div>
)}
<div className={clsx(styles.pageWrapperScroll, styles.hiddenScrollWrap)}>
{isLoading && <ListContextLoading />}
{isSuccess && (
<div className="absolute w-full space-y-4 pb-10">
{appLists?.map((item: TAppInfo) => {
@@ -96,13 +103,18 @@ function StorePage() {
onClick={() => toPage(EPageType.DetailPage, item.name)}
>
<div className="p-8 pl-6 flex items-center justify-center shrink-0">
<img width={110} height={110} src={item?.icon} alt={item?.name} />
<img
width={110}
height={110}
src={item?.icon ?? '/images/appstore/image_empty.svg'}
alt={item?.name}
/>
</div>
<div className={clsx(styles.appDesc)}>
<div className={clsx(styles.title, 'pt-6 flex items-center')}>
<div>{handleImageName(item?.name).name}</div>
<div className={styles.fingerPrint}>
<Iconfont iconName="icon-hash" />
<Iconfont iconName="icon-hash" color="#239BF2" />
</div>
</div>
<div className={styles.description}>{item?.description}</div>
@@ -121,10 +133,11 @@ function StorePage() {
</div>
<div className="pr-10">
<div className="flex pt-6 space-x-2">
<div className={clsx('w-20 h-20 text-right')}>
{/* <div className={clsx('w-20 h-20 text-right')}>
<div className={styles.imageSizeText}> 19.1K </div>
<span className="text-stone-500 text-xs pt-2">下载量</span>
</div>
</div> */}
<div className="w-20 h-20"></div>
<div className="w-20 h-20 text-right">
<div className={styles.imageSizeText}>
{item.size ? formattedSize(item.size) : 'empty'}
@@ -132,11 +145,11 @@ function StorePage() {
<span className="text-stone-500 text-xs pt-2">大小</span>
</div>
</div>
<div className="flex justify-end mt-4">
{/* <div className="flex justify-end mt-4">
<Button type="primary" size="medium" handleClick={() => {}}>
安装
</Button>
</div>
</div> */}
</div>
</div>
);
@@ -347,3 +347,10 @@ body[data-theme='dark'] .win11Scroll,
}
}
}
.appMask {
position: absolute;
width: 100%;
height: 100%;
z-index: 4;
}
@@ -16,10 +16,13 @@ export default function AppWindow(props: {
}) {
const wnapp = props.app;
const { closeApp, updateAppInfo, switchApp } = useAppStore((state) => state);
const { closeApp, updateAppInfo, switchApp, currentApp, openedApps } = useAppStore(
(state) => state
);
const dragDom = useRef(null);
const [dragging, setDragging] = useState(false);
const [position, setPosition] = useState({ x: 0, y: 0 });
// console.log(position);
return (
<Draggable
@@ -50,10 +53,10 @@ export default function AppWindow(props: {
<div
className={styles.toolbar}
onClick={(e) => {
switchApp(wnapp, 'clickHeader');
switchApp({ ...wnapp, mask: false }, 'clickMask');
}}
style={{
background: wnapp.style?.bg || '#fff'
background: '#fff'
}}
>
<div className={clsx(styles.topInfo, 'flex flex-grow items-center ml-4')}>
@@ -121,8 +124,18 @@ export default function AppWindow(props: {
</div>
</div>
<div className={clsx(tabStyles.windowScreen, 'flex flex-col')}>
<div className="restWindow flex-grow flex flex-col">
<div className="flex-grow overflow-hidden">{props.children}</div>
<div className="restWindow flex-grow flex flex-col relative">
<div className="flex-grow overflow-hidden">
{wnapp.mask && (
<div
className={styles.appMask}
onClick={() => {
switchApp({ ...wnapp, mask: false }, 'clickMask');
}}
></div>
)}
{props.children}
</div>
</div>
</div>
</div>
@@ -79,6 +79,9 @@
}
&[data-size='minimize'] {
left: 20%;
height: 80%;
width: 60%;
top: calc(100% + 10px);
transform: scale(0.6);
transform-origin: bottom;
@@ -1,7 +0,0 @@
.icon {
width: 16px;
height: 16px;
vertical-align: middle;
fill: currentColor;
overflow: hidden;
}
@@ -1,19 +1,18 @@
import clsx from 'clsx';
import styles from './index.module.scss';
type TIconfont = {
iconName: string;
color?: string;
};
function Iconfont(props: TIconfont) {
const { iconName } = props;
const { iconName, color } = props;
const style = {
fill: color
};
return (
<>
<svg className={clsx(styles.icon)} aria-hidden="true">
<use xlinkHref={`#${iconName}`}></use>
</svg>
</>
<svg className="icon" aria-hidden="true" style={style}>
<use xlinkHref={`#${iconName}`}></use>
</svg>
);
}
@@ -43,7 +43,7 @@ const Taskbar = () => {
return (
<div
onClick={() => {
switchApp(item);
switchApp({ ...item, mask: false });
}}
key={index}
className={clsx({
+81 -63
View File
@@ -20,7 +20,9 @@ const installedApps: TApp[] = [
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
},
cacheSize: 'maximize',
mask: true
},
{
name: 'App Store',
@@ -37,9 +39,11 @@ const installedApps: TApp[] = [
size: 'maximize',
menu: {
nameColor: 'text-black',
helpDropDown: true,
helpDropDown: false,
helpDocs: false
}
},
cacheSize: 'maximize',
mask: true
},
// {
// name: 'Python Compiler',
@@ -87,7 +91,9 @@ const installedApps: TApp[] = [
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
},
cacheSize: 'maximize',
mask: true
},
{
name: 'Kubernetes Dashboard',
@@ -106,28 +112,32 @@ const installedApps: TApp[] = [
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
},
{
name: 'Kuboard',
icon: '/images/kuboard.svg',
type: APPTYPE.IFRAME,
data: {
url: '',
desc: 'sealos Cloud Kuboard'
},
gallery: [
'https: //cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
'https: //www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
],
size: 'maximize',
menu: {
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
cacheSize: 'maximize',
mask: true
},
// {
// name: 'Kuboard',
// icon: '/images/kuboard.svg',
// type: APPTYPE.IFRAME,
// data: {
// url: '',
// desc: 'sealos Cloud Kuboard'
// },
// gallery: [
// 'https: //cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
// 'https: //www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
// ],
// size: 'maximize',
// menu: {
// nameColor: 'text-black',
// helpDropDown: true,
// helpDocs: false
// },
// cacheSize: 'maximize',
// mask: true
// },
// {
// name: 'Prometheus',
// icon: '/images/prometheus.svg',
// type: APPTYPE.IFRAME,
@@ -155,25 +165,27 @@ const installedApps: TApp[] = [
// ],
// size: 'maximize'
// },
{
name: 'Redis',
icon: '/images/redis.svg',
type: APPTYPE.IFRAME,
data: {
url: '',
desc: 'redis operator'
},
gallery: [
'https://cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
'https://www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
],
size: 'maximize',
menu: {
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
},
// {
// name: 'Redis',
// icon: '/images/redis.svg',
// type: APPTYPE.IFRAME,
// data: {
// url: '',
// desc: 'redis operator'
// },
// gallery: [
// 'https://cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
// 'https://www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
// ],
// size: 'maximize',
// menu: {
// nameColor: 'text-black',
// helpDropDown: true,
// helpDocs: false
// },
// cacheSize: 'maximize',
// mask: true
// },
// {
// name: 'Postgres',
// icon: '/images/pgadmin.svg',
@@ -223,28 +235,32 @@ const installedApps: TApp[] = [
menu: {
nameColor: '#0073D7',
helpDropDown: false,
helpDocs: true
}
},
{
name: 'AFFiNE',
icon: '/images/affine.svg',
type: APPTYPE.IFRAME,
data: {
url: '',
desc: 'AFFiNE operator'
},
gallery: [
'https: //cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
'https: //www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
],
size: 'maximize',
menu: {
nameColor: 'text-black',
helpDropDown: true,
helpDocs: false
}
},
cacheSize: 'maximize',
mask: true
},
// {
// name: 'AFFiNE',
// icon: '/images/affine.svg',
// type: APPTYPE.IFRAME,
// data: {
// url: '',
// desc: 'AFFiNE operator'
// },
// gallery: [
// 'https: //cdn.programiz.com/cdn/farfuture/IwFGGPqycIxTfzLl7mPdcaqUaircnStXfipaHd4EBik/mtime:1605833048/sites/all/themes/programiz/assets/compiler.png',
// 'https: //www.programiz.com/blog/content/images/2020/07/programiz-online-compiler.png'
// ],
// size: 'maximize',
// menu: {
// nameColor: 'text-black',
// helpDropDown: true,
// helpDocs: false
// },
// cacheSize: 'maximize',
// mask: true
// },
{
name: 'Postgres',
icon: '/images/pgadmin.svg',
@@ -257,7 +273,9 @@ const installedApps: TApp[] = [
data: {
url: '',
desc: 'postgres operator'
}
},
cacheSize: 'maximize',
mask: true
}
];
+1 -5
View File
@@ -56,11 +56,7 @@ class MyDocument extends Document {
<link rel="manifest" href="/manifest.json" />
<link rel="mask-icon" href="/icons/safari-pinned-tab.svg" color="#5bbad5" />
<link rel="shortcut icon" href="/favicon.ico" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=optional"
/>
<script src="//at.alicdn.com/t/c/font_3832498_k0ajol52vnd.js" defer></script>
<script src="/iconfont/iconfont.js" async></script>
</Head>
<body>
<Main />
@@ -4,7 +4,13 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import { ApplyYaml, GetClusterObject, K8sApi } from 'services/backend/kubernetes';
import { CRDTemplateBuilder } from 'services/backend/wrapper';
import { hashAny } from 'utils/strings';
import { BadRequestResp, InternalErrorResp, JsonResp, UnprocessableResp } from '../response';
import {
BadRequestResp,
InternalErrorResp,
JsonResp,
UnprocessableResp,
CreatedJsonResp
} from '../response';
type DataPackDesc = {
codes: number;
@@ -41,7 +47,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
const datapackDesc = dataDesc.body.status as DataPackDesc;
if (datapackDesc.codes === DataPackStatus.Ok) {
let result = Object.values(datapackDesc.datas);
return JsonResp({ items: result, code: 200 }, resp);
return JsonResp(result, resp);
}
return JsonResp(datapackDesc, resp);
}
@@ -58,7 +64,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
try {
const result = await ApplyYaml(kc, datapackCRD);
return JsonResp({ ...result, code: 201 }, resp);
return CreatedJsonResp(result, resp);
} catch (err) {
return InternalErrorResp(String(err), resp);
}
@@ -14,7 +14,13 @@ import {
} from 'services/backend/kubernetes';
import { CRDTemplateBuilder } from 'services/backend/wrapper';
import { hashAny } from 'utils/strings';
import { BadRequestResp, InternalErrorResp, JsonResp, UnprocessableResp } from '../response';
import {
BadRequestResp,
InternalErrorResp,
JsonResp,
UnprocessableResp,
CreatedJsonResp
} from '../response';
type repositoryStatus = {
items: {
@@ -66,9 +72,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
images_names.push(item.spec.name + ':' + item.status.latestTag.name);
}
}
// return JsonResp(repositoryDesc.body, resp);
} catch (err) {
console.log(err, 'list');
if (err instanceof k8s.HttpError) {
return InternalErrorResp(err.body.message, resp);
}
@@ -83,7 +87,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
const datapackDesc = dataDesc.body.status as DataPackDesc;
if (datapackDesc.codes === DataPackStatus.Ok) {
let result = Object.values(datapackDesc.datas);
return JsonResp({ items: result, code: 200 }, resp);
return JsonResp(result, resp);
}
return JsonResp(datapackDesc, resp);
}
@@ -100,7 +104,7 @@ export default async function handler(req: NextApiRequest, resp: NextApiResponse
try {
const result = await ApplyYaml(kc, datapackCRD);
return JsonResp({ ...result, code: 201 }, resp);
return CreatedJsonResp(result, resp);
} catch (err) {
return InternalErrorResp(String(err), resp);
}
+13 -1
View File
@@ -56,6 +56,17 @@ const InternalErrorResp = (str: string, resp?: NextApiResponse) =>
const JsonResp = (data: any, resp?: NextApiResponse) =>
CommonResp({ code: 200, message: 'ok', data: data, statusCode: 200 }, resp);
const CreatedJsonResp = (data: any, resp?: NextApiResponse) =>
CommonResp(
{
code: 201,
message: 'the resource has been created and needs to be requested again',
data: data,
statusCode: 201
},
resp
);
export {
BadRequestResp,
BadAuthResp,
@@ -64,5 +75,6 @@ export {
MethodNotAllowedResp,
InternalErrorResp,
CommonResp,
JsonResp
JsonResp,
CreatedJsonResp
};
+2 -1
View File
@@ -101,7 +101,8 @@ request.interceptors.response.use(
// UnWrap
const apiResp = data as ApiResp;
if (apiResp.code !== 200) {
const successfulCode = [200, 201];
if (!successfulCode.includes(apiResp.code)) {
return Promise.reject(new Error(apiResp.code + ':' + apiResp.message));
}
+12 -5
View File
@@ -18,6 +18,7 @@ export type TAppFront = {
}
| {};
cacheSize: 'maximize' | 'maxmin' | 'minimize';
mask: boolean;
};
const initialFrantState: TAppFront = {
@@ -25,6 +26,7 @@ const initialFrantState: TAppFront = {
zIndex: 1,
size: 'maximize',
cacheSize: 'maximize',
mask: true,
style: {}
};
@@ -78,7 +80,7 @@ type TOSState = {
openApp(app: TApp): void;
// switch the app
switchApp(app: TApp, type?: 'clickHeader'): void;
switchApp(app: TApp, type?: 'clickMask'): void;
updateAppInfo(app: TApp): void;
@@ -141,6 +143,7 @@ const useAppStore = create<TOSState>()(
updateAppInfo: (app: TApp) => {
set((state) => {
state.openedApps = state.openedApps.map((_app) => {
_app.mask = true;
return _app.name === app.name ? app : _app;
});
@@ -148,9 +151,9 @@ const useAppStore = create<TOSState>()(
return _app.name === app.name ? app : _app;
});
const temp = state.openedApps.filter((item) => item.size !== 'minimize');
temp.sort((a, b) => b.zIndex - a.zIndex);
state.currentApp = temp[0];
const activeApps = state.openedApps.filter((item) => item.size !== 'minimize');
activeApps.sort((a, b) => b.zIndex - a.zIndex);
state.currentApp = activeApps[0];
});
},
@@ -164,6 +167,7 @@ const useAppStore = create<TOSState>()(
_app.zIndex = zIndex;
_app.isShow = true;
_app.size = 'maximize';
_app.mask = false;
get().updateAppInfo(_app);
@@ -181,13 +185,16 @@ const useAppStore = create<TOSState>()(
const _app: TApp = JSON.parse(JSON.stringify(app));
_app.zIndex = zIndex;
_app.isShow = true;
if (type !== 'clickHeader') {
if (type !== 'clickMask') {
if (get().currentApp?.name === _app.name) {
_app.size === 'minimize' ? (_app.size = _app.cacheSize) : (_app.size = 'minimize');
} else {
_app.size = _app.cacheSize;
}
}
get().updateAppInfo(_app);
set((state) => {
// repalce app info
state.openedApps = state.openedApps.map((item) => {
+9
View File
@@ -3,6 +3,7 @@
@tailwind utilities;
@import './highlight.scss';
html {
font-size: 12px;
scrollbar-color: transparent transparent;
@@ -115,3 +116,11 @@ body::-webkit-scrollbar {
--hover-bg: rgba(0, 178, 255, 0.16);
--focus-bg: rgba(0, 183, 255, 0.25);
}
.icon {
width: 16px;
height: 16px;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}