feat: convert components to dynamic imports for improved performance (#22614)

This commit is contained in:
Wu Tianwei
2025-07-18 11:43:37 +08:00
committed by GitHub
parent 1f9cd99bc2
commit b035f3f884
37 changed files with 493 additions and 472 deletions

View File

@@ -1,5 +1,3 @@
'use client'
import WorkflowApp from '@/app/components/workflow-app' import WorkflowApp from '@/app/components/workflow-app'
const Page = () => { const Page = () => {

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 4V8M8 8V12M8 8H12M8 8H4" stroke="#6B7280" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 206 B

View File

@@ -1,4 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.631586 8.25C0.631586 6.46656 2.04586 5 3.8158 5C5.58573 5 7.00001 6.46656 7.00001 8.25C7.00001 10.0334 5.58573 11.5 3.8158 11.5C3.45197 11.5 3.10149 11.4375 2.77474 11.3222C2.72073 11.3031 2.68723 11.2913 2.66266 11.2832C2.65821 11.2817 2.65456 11.2806 2.65164 11.2796L2.64892 11.2799C2.63177 11.2818 2.60839 11.285 2.56507 11.2909L1.06766 11.4954C0.905637 11.5175 0.743029 11.459 0.632239 11.3387C0.521449 11.2185 0.476481 11.0516 0.511825 10.8919L0.817497 9.51109C0.828118 9.46311 0.833802 9.43722 0.837453 9.41817C0.83766 9.4171 0.838022 9.41517 0.838022 9.41517C0.837114 9.412 0.835963 9.40808 0.834525 9.40332C0.826292 9.37605 0.814183 9.33888 0.794499 9.27863C0.688657 8.95463 0.631586 8.60857 0.631586 8.25Z" fill="#98A2B3"/>
<path d="M2.57377 4.1863C2.96256 4.06535 3.37698 4 3.80894 4C6.16566 4 8.00006 5.94534 8.00006 8.24999C8.00006 8.65682 7.9429 9.05245 7.8358 9.42816C8.10681 9.37948 8.36964 9.30678 8.6219 9.21229C8.65748 9.19897 8.69298 9.18534 8.72893 9.17304C8.75795 9.17641 8.78684 9.18093 8.81574 9.18517L10.4222 9.42065C10.498 9.43179 10.5841 9.44444 10.6591 9.4487C10.7422 9.45343 10.8713 9.45292 11.0081 9.39408C11.1789 9.32061 11.3164 9.18628 11.3938 9.01716C11.4558 8.88174 11.4593 8.75269 11.4564 8.66955C11.4539 8.59442 11.4433 8.5081 11.4339 8.43202L11.2309 6.78307C11.2256 6.7402 11.2229 6.71768 11.2213 6.70118C11.23 6.66505 11.2466 6.6301 11.2598 6.59546C11.4492 6.09896 11.5526 5.56093 11.5526 5C11.5526 2.51163 9.52304 0.5 7.02632 0.5C4.80843 0.5 2.95915 2.08742 2.57377 4.1863Z" fill="#98A2B3"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.1667 6.66634H15.8333C16.2754 6.66634 16.6993 6.84194 17.0118 7.1545C17.3244 7.46706 17.5 7.89098 17.5 8.33301V13.333C17.5 13.775 17.3244 14.199 17.0118 14.5115C16.6993 14.8241 16.2754 14.9997 15.8333 14.9997H14.1667V18.333L10.8333 14.9997H7.5C7.28111 14.9999 7.06433 14.9569 6.86211 14.8731C6.6599 14.7893 6.47623 14.6663 6.32167 14.5113M6.32167 14.5113L9.16667 11.6663H12.5C12.942 11.6663 13.366 11.4907 13.6785 11.1782C13.9911 10.8656 14.1667 10.4417 14.1667 9.99967V4.99967C14.1667 4.55765 13.9911 4.13372 13.6785 3.82116C13.366 3.5086 12.942 3.33301 12.5 3.33301H4.16667C3.72464 3.33301 3.30072 3.5086 2.98816 3.82116C2.67559 4.13372 2.5 4.55765 2.5 4.99967V9.99967C2.5 10.4417 2.67559 10.8656 2.98816 11.1782C3.30072 11.4907 3.72464 11.6663 4.16667 11.6663H5.83333V14.9997L6.32167 14.5113Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1002 B

View File

@@ -1,4 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.5 1.00779C6.5 0.994638 6.5 0.988062 6.49943 0.976137C6.48764 0.729248 6.27052 0.51224 6.02363 0.50056C6.01171 0.499996 6.0078 0.499998 6.00001 0.5H4.37933C3.97686 0.499995 3.64468 0.49999 3.37409 0.522098C3.09304 0.545061 2.83469 0.594343 2.59202 0.717989C2.2157 0.909735 1.90973 1.2157 1.71799 1.59202C1.59434 1.83469 1.54506 2.09304 1.5221 2.37409C1.49999 2.64468 1.49999 2.97686 1.5 3.37934V8.62066C1.49999 9.02313 1.49999 9.35532 1.5221 9.62591C1.54506 9.90696 1.59434 10.1653 1.71799 10.408C1.90973 10.7843 2.2157 11.0903 2.59202 11.282C2.83469 11.4057 3.09304 11.4549 3.37409 11.4779C3.64468 11.5 3.97686 11.5 4.37934 11.5H7.62066C8.02314 11.5 8.35532 11.5 8.62591 11.4779C8.90696 11.4549 9.16531 11.4057 9.40798 11.282C9.78431 11.0903 10.0903 10.7843 10.282 10.408C10.4057 10.1653 10.4549 9.90696 10.4779 9.62591C10.5 9.35532 10.5 9.02314 10.5 8.62066V4.99997C10.5 4.9922 10.5 4.98832 10.4994 4.97641C10.4878 4.72949 10.2707 4.51236 10.0238 4.50057C10.0119 4.50001 10.0054 4.50001 9.99225 4.50001L7.78404 4.50001C7.65786 4.50002 7.53496 4.50004 7.43089 4.49153C7.31659 4.48219 7.18172 4.46016 7.04601 4.39101C6.85785 4.29514 6.70487 4.14216 6.609 3.954C6.53985 3.81828 6.51781 3.68342 6.50848 3.56912C6.49997 3.46504 6.49999 3.34215 6.5 3.21596L6.5 1.00779ZM4 6.5C3.72386 6.5 3.5 6.72386 3.5 7C3.5 7.27614 3.72386 7.5 4 7.5H8C8.27614 7.5 8.5 7.27614 8.5 7C8.5 6.72386 8.27614 6.5 8 6.5H4ZM4 8.5C3.72386 8.5 3.5 8.72386 3.5 9C3.5 9.27614 3.72386 9.5 4 9.5H7C7.27614 9.5 7.5 9.27614 7.5 9C7.5 8.72386 7.27614 8.5 7 8.5H4Z" fill="#98A2B3"/>
<path d="M9.45398 3.5C9.60079 3.5 9.67419 3.5 9.73432 3.46314C9.81925 3.41107 9.87002 3.28842 9.84674 3.19157C9.83025 3.12299 9.78238 3.07516 9.68665 2.97952L8.02049 1.31336C7.92484 1.21762 7.87701 1.16975 7.80843 1.15326C7.71158 1.12998 7.58893 1.18075 7.53687 1.26567C7.5 1.3258 7.5 1.39921 7.5 1.54602L7.5 3.09998C7.5 3.23999 7.5 3.30999 7.52725 3.36347C7.55122 3.41051 7.58946 3.44876 7.6365 3.47272C7.68998 3.49997 7.75998 3.49997 7.9 3.49998L9.45398 3.5Z" fill="#98A2B3"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,3 +0,0 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.25 11.875V9.6875C16.25 8.1342 14.9908 6.875 13.4375 6.875H12.1875C11.6697 6.875 11.25 6.45527 11.25 5.9375V4.6875C11.25 3.1342 9.9908 1.875 8.4375 1.875H6.875M6.875 12.5H13.125M6.875 15H10M8.75 1.875H4.6875C4.16973 1.875 3.75 2.29473 3.75 2.8125V17.1875C3.75 17.7053 4.16973 18.125 4.6875 18.125H15.3125C15.8303 18.125 16.25 17.7053 16.25 17.1875V9.375C16.25 5.23286 12.8921 1.875 8.75 1.875Z" stroke="#1F2A37" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 595 B

View File

@@ -1,3 +0,0 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.0101 4.50191C20.3529 3.74154 18.5759 3.18133 16.7179 2.86048C16.6841 2.85428 16.6503 2.86976 16.6328 2.90071C16.4043 3.30719 16.1511 3.83748 15.9738 4.25429C13.9754 3.95511 11.9873 3.95511 10.0298 4.25429C9.85253 3.82822 9.59019 3.30719 9.36062 2.90071C9.34319 2.87079 9.30939 2.85532 9.27555 2.86048C7.41857 3.18031 5.64152 3.74051 3.98335 4.50191C3.96899 4.5081 3.95669 4.51843 3.94852 4.53183C0.577841 9.56755 -0.345529 14.4795 0.107445 19.3306C0.109495 19.3543 0.122817 19.377 0.141265 19.3914C2.36514 21.0246 4.51935 22.0161 6.63355 22.6732C6.66739 22.6836 6.70324 22.6712 6.72477 22.6433C7.22489 21.9604 7.6707 21.2402 8.05293 20.4829C8.07549 20.4386 8.05396 20.386 8.00785 20.3684C7.30073 20.1002 6.6274 19.7731 5.97971 19.4017C5.92848 19.3718 5.92437 19.2985 5.9715 19.2635C6.1078 19.1613 6.24414 19.0551 6.37428 18.9478C6.39783 18.9282 6.43064 18.924 6.45833 18.9364C10.7134 20.8791 15.32 20.8791 19.5249 18.9364C19.5525 18.923 19.5854 18.9272 19.6099 18.9467C19.7401 19.054 19.8764 19.1613 20.0137 19.2635C20.0609 19.2985 20.0578 19.3718 20.0066 19.4017C19.3589 19.7804 18.6855 20.1002 17.9774 20.3674C17.9313 20.3849 17.9108 20.4386 17.9333 20.4829C18.3238 21.2392 18.7696 21.9593 19.2605 22.6423C19.281 22.6712 19.3179 22.6836 19.3517 22.6732C21.4761 22.0161 23.6303 21.0246 25.8542 19.3914C25.8737 19.377 25.886 19.3553 25.8881 19.3316C26.4302 13.7232 24.98 8.85156 22.0439 4.53286C22.0367 4.51843 22.0245 4.5081 22.0101 4.50191ZM8.68836 16.3768C7.40729 16.3768 6.35173 15.2007 6.35173 13.7563C6.35173 12.3119 7.38682 11.1358 8.68836 11.1358C10.0001 11.1358 11.0455 12.3222 11.025 13.7563C11.025 15.2007 9.98986 16.3768 8.68836 16.3768ZM17.3276 16.3768C16.0466 16.3768 14.991 15.2007 14.991 13.7563C14.991 12.3119 16.0261 11.1358 17.3276 11.1358C18.6394 11.1358 19.6847 12.3222 19.6643 13.7563C19.6643 15.2007 18.6394 16.3768 17.3276 16.3768Z" fill="#5865F2"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,17 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_131_1011)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0003 0.5C9.15149 0.501478 6.39613 1.51046 4.22687 3.34652C2.05761 5.18259 0.615903 7.72601 0.159545 10.522C-0.296814 13.318 0.261927 16.1842 1.73587 18.6082C3.20981 21.0321 5.50284 22.8558 8.20493 23.753C8.80105 23.8636 9.0256 23.4941 9.0256 23.18C9.0256 22.8658 9.01367 21.955 9.0097 20.9592C5.6714 21.6804 4.96599 19.5505 4.96599 19.5505C4.42152 18.1674 3.63464 17.8039 3.63464 17.8039C2.54571 17.065 3.71611 17.0788 3.71611 17.0788C4.92227 17.1637 5.55616 18.3097 5.55616 18.3097C6.62521 20.1333 8.36389 19.6058 9.04745 19.2976C9.15475 18.5251 9.46673 17.9995 9.8105 17.7012C7.14383 17.4008 4.34204 16.3774 4.34204 11.8054C4.32551 10.6197 4.76802 9.47305 5.57801 8.60268C5.45481 8.30236 5.04348 7.08923 5.69524 5.44143C5.69524 5.44143 6.7027 5.12135 8.9958 6.66444C10.9627 6.12962 13.0379 6.12962 15.0047 6.66444C17.2958 5.12135 18.3013 5.44143 18.3013 5.44143C18.9551 7.08528 18.5437 8.29841 18.4205 8.60268C19.2331 9.47319 19.6765 10.6218 19.6585 11.8094C19.6585 16.3912 16.8507 17.4008 14.1801 17.6952C14.6093 18.0667 14.9928 18.7918 14.9928 19.9061C14.9928 21.5026 14.9789 22.7868 14.9789 23.18C14.9789 23.4981 15.1955 23.8695 15.8035 23.753C18.5059 22.8557 20.7992 21.0317 22.2731 18.6073C23.747 16.183 24.3055 13.3163 23.8486 10.5201C23.3917 7.7238 21.9493 5.18035 19.7793 3.34461C17.6093 1.50886 14.8533 0.500541 12.0042 0.5H12.0003Z" fill="#191717"/>
<path d="M4.54444 17.6321C4.5186 17.6914 4.42322 17.7092 4.34573 17.6677C4.26823 17.6262 4.21061 17.5491 4.23843 17.4879C4.26625 17.4266 4.35964 17.4108 4.43714 17.4523C4.51463 17.4938 4.57424 17.5729 4.54444 17.6321Z" fill="#191717"/>
<path d="M5.03123 18.1714C4.99008 18.192 4.943 18.1978 4.89805 18.1877C4.8531 18.1776 4.81308 18.1523 4.78483 18.1161C4.70734 18.0331 4.69143 17.9185 4.75104 17.8671C4.81066 17.8157 4.91797 17.8395 4.99546 17.9224C5.07296 18.0054 5.09084 18.12 5.03123 18.1714Z" fill="#191717"/>
<path d="M5.50425 18.857C5.43072 18.9084 5.30553 18.857 5.23598 18.7543C5.21675 18.7359 5.20146 18.7138 5.19101 18.6893C5.18056 18.6649 5.17517 18.6386 5.17517 18.612C5.17517 18.5855 5.18056 18.5592 5.19101 18.5347C5.20146 18.5103 5.21675 18.4882 5.23598 18.4698C5.3095 18.4204 5.4347 18.4698 5.50425 18.5705C5.57379 18.6713 5.57578 18.8057 5.50425 18.857V18.857Z" fill="#191717"/>
<path d="M6.14612 19.5207C6.08054 19.5939 5.94741 19.5741 5.83812 19.4753C5.72883 19.3765 5.70299 19.2422 5.76857 19.171C5.83414 19.0999 5.96727 19.1197 6.08054 19.2165C6.1938 19.3133 6.21566 19.4496 6.14612 19.5207V19.5207Z" fill="#191717"/>
<path d="M7.04617 19.9081C7.01637 20.001 6.88124 20.0425 6.74612 20.003C6.611 19.9635 6.52158 19.8528 6.54741 19.758C6.57325 19.6631 6.71036 19.6197 6.84747 19.6631C6.98457 19.7066 7.07201 19.8113 7.04617 19.9081Z" fill="#191717"/>
<path d="M8.02783 19.9752C8.02783 20.072 7.91656 20.155 7.77349 20.1569C7.63042 20.1589 7.51318 20.0799 7.51318 19.9831C7.51318 19.8863 7.62445 19.8033 7.76752 19.8013C7.91059 19.7993 8.02783 19.8764 8.02783 19.9752Z" fill="#191717"/>
<path d="M8.9419 19.8232C8.95978 19.92 8.86042 20.0207 8.71735 20.0445C8.57428 20.0682 8.4491 20.0109 8.43121 19.916C8.41333 19.8212 8.51666 19.7185 8.65576 19.6928C8.79485 19.6671 8.92401 19.7264 8.9419 19.8232Z" fill="#191717"/>
</g>
<defs>
<clipPath id="clip0_131_1011">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,3 +0,0 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.41663 3.75033H3.24996C2.96264 3.75033 2.68709 3.86446 2.48393 4.06763C2.28076 4.27079 2.16663 4.54634 2.16663 4.83366V10.2503C2.16663 10.5376 2.28076 10.8132 2.48393 11.0164C2.68709 11.2195 2.96264 11.3337 3.24996 11.3337H8.66663C8.95394 11.3337 9.22949 11.2195 9.43266 11.0164C9.63582 10.8132 9.74996 10.5376 9.74996 10.2503V8.08366M7.58329 2.66699H10.8333M10.8333 2.66699V5.91699M10.8333 2.66699L5.41663 8.08366" stroke="#9CA3AF" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 596 B

View File

@@ -1,3 +0,0 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.41663 3.75008H3.24996C2.96264 3.75008 2.68709 3.86422 2.48393 4.06738C2.28076 4.27055 2.16663 4.5461 2.16663 4.83341V10.2501C2.16663 10.5374 2.28076 10.8129 2.48393 11.0161C2.68709 11.2193 2.96264 11.3334 3.24996 11.3334H8.66663C8.95394 11.3334 9.22949 11.2193 9.43266 11.0161C9.63582 10.8129 9.74996 10.5374 9.74996 10.2501V8.08341M7.58329 2.66675H10.8333M10.8333 2.66675V5.91675M10.8333 2.66675L5.41663 8.08341" stroke="#1C64F2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 595 B

View File

@@ -1,3 +0,0 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 2.5L10.5 6M10.5 6L7 9.5M10.5 6H1.5" stroke="#1C64F2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 217 B

View File

@@ -1,12 +0,0 @@
'use client'
import useDocumentTitle from '@/hooks/use-document-title'
import { useTranslation } from 'react-i18next'
export default function DatasetsLayout({ children }: { children: React.ReactNode }) {
const { t } = useTranslation()
useDocumentTitle(t('common.menus.apps'))
return (<>
{children}
</>)
}

View File

@@ -1,32 +1,8 @@
'use client' import Apps from '@/app/components/apps'
import { useTranslation } from 'react-i18next'
import { RiDiscordFill, RiGithubFill } from '@remixicon/react'
import Link from 'next/link'
import style from '../list.module.css'
import Apps from './Apps'
import { useEducationInit } from '@/app/education-apply/hooks'
import { useGlobalPublicStore } from '@/context/global-public-context'
const AppList = () => { const AppList = () => {
const { t } = useTranslation()
useEducationInit()
const { systemFeatures } = useGlobalPublicStore()
return ( return (
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'> <Apps />
<Apps />
{!systemFeatures.branding.enabled && <footer className='shrink-0 grow-0 px-12 py-6'>
<h3 className='text-gradient text-xl font-semibold leading-tight'>{t('app.join')}</h3>
<p className='system-sm-regular mt-1 text-text-tertiary'>{t('app.communityIntro')}</p>
<div className='mt-3 flex items-center gap-2'>
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://github.com/langgenius/dify'>
<RiGithubFill className='h-5 w-5 text-text-tertiary' />
</Link>
<Link className={style.socialMediaLink} target='_blank' rel='noopener noreferrer' href='https://discord.gg/FngNHpbcY7'>
<RiDiscordFill className='h-5 w-5 text-text-tertiary' />
</Link>
</div>
</footer>}
</div >
) )
} }

View File

@@ -1,217 +0,0 @@
.listItem {
@apply col-span-1 bg-white border-2 border-solid border-transparent rounded-xl shadow-xs min-h-[160px] flex flex-col transition-all duration-200 ease-in-out cursor-pointer hover:shadow-lg;
}
.listItem.newItemCard {
@apply outline outline-1 outline-gray-200 -outline-offset-1 hover:shadow-sm hover:bg-white;
background-color: rgba(229, 231, 235, 0.5);
}
.listItem.selectable {
@apply relative bg-gray-50 outline outline-1 outline-gray-200 -outline-offset-1 shadow-none hover:bg-none hover:shadow-none hover:outline-primary-200 transition-colors;
}
.listItem.selectable * {
@apply relative;
}
.listItem.selectable::before {
content: "";
@apply absolute top-0 left-0 block w-full h-full rounded-lg pointer-events-none opacity-0 transition-opacity duration-200 ease-in-out hover:opacity-100;
background: linear-gradient(0deg,
rgba(235, 245, 255, 0.5),
rgba(235, 245, 255, 0.5)),
#ffffff;
}
.listItem.selectable:hover::before {
@apply opacity-100;
}
.listItem.selected {
@apply border-primary-600 hover:border-primary-600 border-2;
}
.listItem.selected::before {
@apply opacity-100;
}
.appIcon {
@apply flex items-center justify-center w-8 h-8 bg-pink-100 rounded-lg grow-0 shrink-0;
}
.appIcon.medium {
@apply w-9 h-9;
}
.appIcon.large {
@apply w-10 h-10;
}
.newItemIcon {
@apply flex items-center justify-center w-8 h-8 transition-colors duration-200 ease-in-out border border-gray-200 rounded-lg hover:bg-white grow-0 shrink-0;
}
.listItem:hover .newItemIcon {
@apply bg-gray-50 border-primary-100;
}
.newItemCard .newItemIcon {
@apply bg-gray-100;
}
.newItemCard:hover .newItemIcon {
@apply bg-white;
}
.selectable .newItemIcon {
@apply bg-gray-50;
}
.selectable:hover .newItemIcon {
@apply bg-primary-50;
}
.newItemIconImage {
@apply grow-0 shrink-0 block w-4 h-4 bg-center bg-contain transition-colors duration-200 ease-in-out;
color: #1f2a37;
}
.listItem:hover .newIconImage {
@apply text-primary-600;
}
.newItemIconAdd {
background-image: url("./apps/assets/add.svg");
}
/* .newItemIconChat {
background-image: url("~@/app/components/base/icons/assets/public/header-nav/studio/Robot.svg");
}
.selected .newItemIconChat {
background-image: url("~@/app/components/base/icons/assets/public/header-nav/studio/Robot-Active.svg");
} */
.newItemIconComplete {
background-image: url("./apps/assets/completion.svg");
}
.listItemTitle {
@apply flex pt-[14px] px-[14px] pb-3 h-[66px] items-center gap-3 grow-0 shrink-0;
}
.listItemHeading {
@apply relative h-8 text-sm font-medium leading-8 grow;
}
.listItemHeadingContent {
@apply absolute top-0 left-0 w-full h-full overflow-hidden text-ellipsis whitespace-nowrap;
}
.actionIconWrapper {
@apply hidden h-8 w-8 p-2 rounded-md border-none hover:bg-gray-100 !important;
}
.listItem:hover .actionIconWrapper {
@apply !inline-flex;
}
.deleteDatasetIcon {
@apply hidden grow-0 shrink-0 basis-8 w-8 h-8 rounded-lg transition-colors duration-200 ease-in-out bg-white border border-gray-200 hover:bg-gray-100 bg-center bg-no-repeat;
background-size: 16px;
background-image: url('~@/assets/delete.svg');
}
.listItem:hover .deleteDatasetIcon {
@apply block;
}
.listItemDescription {
@apply mb-3 px-[14px] h-9 text-xs leading-normal text-gray-500 line-clamp-2;
}
.listItemDescription.noClip {
@apply line-clamp-none;
}
.listItemFooter {
@apply flex items-center flex-wrap min-h-[42px] px-[14px] pt-2 pb-[10px];
}
.listItemFooter.datasetCardFooter {
@apply flex items-center gap-4 text-xs text-gray-500;
}
.listItemStats {
@apply flex items-center gap-1;
}
.listItemFooterIcon {
@apply block w-3 h-3 bg-center bg-contain;
}
.solidChatIcon {
background-image: url("./apps/assets/chat-solid.svg");
}
.solidCompletionIcon {
background-image: url("./apps/assets/completion-solid.svg");
}
.newItemCardHeading {
@apply transition-colors duration-200 ease-in-out;
}
.listItem:hover .newItemCardHeading {
@apply text-primary-600;
}
.listItemLink {
@apply inline-flex items-center gap-1 text-xs text-gray-400 transition-colors duration-200 ease-in-out;
}
.listItem:hover .listItemLink {
@apply text-primary-600;
}
.linkIcon {
@apply block w-[13px] h-[13px] bg-center bg-contain;
background-image: url("./apps/assets/link.svg");
}
.linkIcon.grayLinkIcon {
background-image: url("./apps/assets/link-gray.svg");
}
.listItem:hover .grayLinkIcon {
background-image: url("./apps/assets/link.svg");
}
.rightIcon {
@apply block w-[13px] h-[13px] bg-center bg-contain;
background-image: url("./apps/assets/right-arrow.svg");
}
.socialMediaLink {
@apply flex items-center justify-center w-8 h-8 cursor-pointer hover:opacity-80 transition-opacity duration-200 ease-in-out;
}
.socialMediaIcon {
@apply block w-6 h-6 bg-center bg-contain;
}
/* #region new app dialog */
.newItemCaption {
@apply inline-flex items-center mb-2 text-sm font-medium;
}
/* #endregion new app dialog */
.unavailable {
@apply opacity-50;
}
.listItem:hover .unavailable {
@apply opacity-100;
}

View File

@@ -12,23 +12,17 @@ import {
RiFileUploadLine, RiFileUploadLine,
} from '@remixicon/react' } from '@remixicon/react'
import AppIcon from '../base/app-icon' import AppIcon from '../base/app-icon'
import SwitchAppModal from '../app/switch-app-modal'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import Confirm from '@/app/components/base/confirm'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import AppsContext, { useAppContext } from '@/context/app-context' import AppsContext, { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps' import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import DuplicateAppModal from '@/app/components/app/duplicate-modal'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal' import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
import CreateAppModal from '@/app/components/explore/create-app-modal'
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal' import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import { getRedirection } from '@/utils/app-redirection' import { getRedirection } from '@/utils/app-redirection'
import UpdateDSLModal from '@/app/components/workflow/update-dsl-modal'
import type { EnvironmentVariable } from '@/app/components/workflow/types' import type { EnvironmentVariable } from '@/app/components/workflow/types'
import DSLExportConfirmModal from '@/app/components/workflow/dsl-export-confirm-modal'
import { fetchWorkflowDraft } from '@/service/workflow' import { fetchWorkflowDraft } from '@/service/workflow'
import ContentDialog from '@/app/components/base/content-dialog' import ContentDialog from '@/app/components/base/content-dialog'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
@@ -36,6 +30,26 @@ import CardView from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overvie
import Divider from '../base/divider' import Divider from '../base/divider'
import type { Operation } from './app-operations' import type { Operation } from './app-operations'
import AppOperations from './app-operations' import AppOperations from './app-operations'
import dynamic from 'next/dynamic'
const SwitchAppModal = dynamic(() => import('@/app/components/app/switch-app-modal'), {
ssr: false,
})
const CreateAppModal = dynamic(() => import('@/app/components/explore/create-app-modal'), {
ssr: false,
})
const DuplicateAppModal = dynamic(() => import('@/app/components/app/duplicate-modal'), {
ssr: false,
})
const Confirm = dynamic(() => import('@/app/components/base/confirm'), {
ssr: false,
})
const UpdateDSLModal = dynamic(() => import('@/app/components/workflow/update-dsl-modal'), {
ssr: false,
})
const DSLExportConfirmModal = dynamic(() => import('@/app/components/workflow/dsl-export-confirm-modal'), {
ssr: false,
})
export type IAppInfoProps = { export type IAppInfoProps = {
expand: boolean expand: boolean

View File

@@ -6,6 +6,7 @@ import {
} from 'react' } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import { import {
RiArrowDownSLine, RiArrowDownSLine,
RiArrowRightSLine, RiArrowRightSLine,
@@ -48,6 +49,7 @@ import { useAppWhiteListSubjects, useGetUserCanAccessApp } from '@/service/acces
import { AccessMode } from '@/models/access-control' import { AccessMode } from '@/models/access-control'
import { fetchAppDetail } from '@/service/apps' import { fetchAppDetail } from '@/service/apps'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
dayjs.extend(relativeTime)
export type AppPublisherProps = { export type AppPublisherProps = {
disabled?: boolean disabled?: boolean
@@ -116,6 +118,7 @@ const AppPublisher = ({
} }
}, [appAccessSubjects, appDetail]) }, [appAccessSubjects, appDetail])
const language = useGetLanguage() const language = useGetLanguage()
const formatTimeFromNow = useCallback((time: number) => { const formatTimeFromNow = useCallback((time: number) => {
return dayjs(time).locale(language === 'zh_Hans' ? 'zh-cn' : language.replace('_', '-')).fromNow() return dayjs(time).locale(language === 'zh_Hans' ? 'zh-cn' : language.replace('_', '-')).fromNow()
}, [language]) }, [language])
@@ -180,8 +183,7 @@ const AppPublisher = ({
if (publishDisabled || published) if (publishDisabled || published)
return return
handlePublish() handlePublish()
}, }, { exactMatch: true, useCapture: true })
{ exactMatch: true, useCapture: true })
return ( return (
<> <>

View File

@@ -20,8 +20,8 @@ const SuggestedAction = ({ icon, link, disabled, children, className, onClick, .
target='_blank' target='_blank'
rel='noreferrer' rel='noreferrer'
className={classNames( className={classNames(
'flex justify-start items-center gap-2 py-2 px-2.5 bg-background-section-burn rounded-lg text-text-secondary transition-colors [&:not(:first-child)]:mt-1', 'flex items-center justify-start gap-2 rounded-lg bg-background-section-burn px-2.5 py-2 text-text-secondary transition-colors [&:not(:first-child)]:mt-1',
disabled ? 'shadow-xs opacity-30 cursor-not-allowed' : 'text-text-secondary hover:bg-state-accent-hover hover:text-text-accent cursor-pointer', disabled ? 'cursor-not-allowed opacity-30 shadow-xs' : 'cursor-pointer text-text-secondary hover:bg-state-accent-hover hover:text-text-accent',
className, className,
)} )}
onClick={handleClick} onClick={handleClick}

View File

@@ -65,6 +65,44 @@ const AppTypeSelector = ({ value, onChange }: AppSelectorProps) => {
export default AppTypeSelector export default AppTypeSelector
type AppTypeIconProps = {
type: AppMode
style?: React.CSSProperties
className?: string
wrapperClassName?: string
}
export const AppTypeIcon = React.memo(({ type, className, wrapperClassName, style }: AppTypeIconProps) => {
const wrapperClassNames = cn('inline-flex h-5 w-5 items-center justify-center rounded-md border border-divider-regular', wrapperClassName)
const iconClassNames = cn('h-3.5 w-3.5 text-components-avatar-shape-fill-stop-100', className)
if (type === 'chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-blue-solid')}>
<ChatBot className={iconClassNames} />
</div>
}
if (type === 'agent-chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-violet-solid')}>
<Logic className={iconClassNames} />
</div>
}
if (type === 'advanced-chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-blue-light-solid')}>
<BubbleTextMod className={iconClassNames} />
</div>
}
if (type === 'workflow') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-indigo-solid')}>
<RiExchange2Fill className={iconClassNames} />
</div>
}
if (type === 'completion') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-teal-solid')}>
<ListSparkle className={iconClassNames} />
</div>
}
return null
})
function AppTypeSelectTrigger({ values }: { values: AppSelectorProps['value'] }) { function AppTypeSelectTrigger({ values }: { values: AppSelectorProps['value'] }) {
const { t } = useTranslation() const { t } = useTranslation()
if (!values || values.length === 0) { if (!values || values.length === 0) {
@@ -108,44 +146,6 @@ function AppTypeSelectorItem({ checked, type, onClick }: AppTypeSelectorItemProp
</li> </li>
} }
type AppTypeIconProps = {
type: AppMode
style?: React.CSSProperties
className?: string
wrapperClassName?: string
}
export function AppTypeIcon({ type, className, wrapperClassName, style }: AppTypeIconProps) {
const wrapperClassNames = cn('inline-flex h-5 w-5 items-center justify-center rounded-md border border-divider-regular', wrapperClassName)
const iconClassNames = cn('h-3.5 w-3.5 text-components-avatar-shape-fill-stop-100', className)
if (type === 'chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-blue-solid')}>
<ChatBot className={iconClassNames} />
</div>
}
if (type === 'agent-chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-violet-solid')}>
<Logic className={iconClassNames} />
</div>
}
if (type === 'advanced-chat') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-blue-light-solid')}>
<BubbleTextMod className={iconClassNames} />
</div>
}
if (type === 'workflow') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-indigo-solid')}>
<RiExchange2Fill className={iconClassNames} />
</div>
}
if (type === 'completion') {
return <div style={style} className={cn(wrapperClassNames, 'bg-components-icon-bg-teal-solid')}>
<ListSparkle className={iconClassNames} />
</div>
}
return null
}
type AppTypeLabelProps = { type AppTypeLabelProps = {
type: AppMode type: AppMode
className?: string className?: string

View File

@@ -1,16 +1,14 @@
'use client' 'use client'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useContext, useContextSelector } from 'use-context-selector' import { useContext, useContextSelector } from 'use-context-selector'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react' import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import type { App } from '@/types/app' import type { App } from '@/types/app'
import Confirm from '@/app/components/base/confirm'
import Toast, { ToastContext } from '@/app/components/base/toast' import Toast, { ToastContext } from '@/app/components/base/toast'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps' import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import DuplicateAppModal from '@/app/components/app/duplicate-modal'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal' import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
import AppIcon from '@/app/components/base/app-icon' import AppIcon from '@/app/components/base/app-icon'
import AppsContext, { useAppContext } from '@/context/app-context' import AppsContext, { useAppContext } from '@/context/app-context'
@@ -22,21 +20,37 @@ import { getRedirection } from '@/utils/app-redirection'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { NEED_REFRESH_APP_LIST_KEY } from '@/config' import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal' import type { CreateAppModalProps } from '@/app/components/explore/create-app-modal'
import EditAppModal from '@/app/components/explore/create-app-modal'
import SwitchAppModal from '@/app/components/app/switch-app-modal'
import type { Tag } from '@/app/components/base/tag-management/constant' import type { Tag } from '@/app/components/base/tag-management/constant'
import TagSelector from '@/app/components/base/tag-management/selector' import TagSelector from '@/app/components/base/tag-management/selector'
import type { EnvironmentVariable } from '@/app/components/workflow/types' import type { EnvironmentVariable } from '@/app/components/workflow/types'
import DSLExportConfirmModal from '@/app/components/workflow/dsl-export-confirm-modal'
import { fetchWorkflowDraft } from '@/service/workflow' import { fetchWorkflowDraft } from '@/service/workflow'
import { fetchInstalledAppList } from '@/service/explore' import { fetchInstalledAppList } from '@/service/explore'
import { AppTypeIcon } from '@/app/components/app/type-selector' import { AppTypeIcon } from '@/app/components/app/type-selector'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import AccessControl from '@/app/components/app/app-access-control'
import { AccessMode } from '@/models/access-control' import { AccessMode } from '@/models/access-control'
import { useGlobalPublicStore } from '@/context/global-public-context' import { useGlobalPublicStore } from '@/context/global-public-context'
import { formatTime } from '@/utils/time' import { formatTime } from '@/utils/time'
import { useGetUserCanAccessApp } from '@/service/access-control' import { useGetUserCanAccessApp } from '@/service/access-control'
import dynamic from 'next/dynamic'
const EditAppModal = dynamic(() => import('@/app/components/explore/create-app-modal'), {
ssr: false,
})
const DuplicateAppModal = dynamic(() => import('@/app/components/app/duplicate-modal'), {
ssr: false,
})
const SwitchAppModal = dynamic(() => import('@/app/components/app/switch-app-modal'), {
ssr: false,
})
const Confirm = dynamic(() => import('@/app/components/base/confirm'), {
ssr: false,
})
const DSLExportConfirmModal = dynamic(() => import('@/app/components/workflow/dsl-export-confirm-modal'), {
ssr: false,
})
const AccessControl = dynamic(() => import('@/app/components/app/app-access-control'), {
ssr: false,
})
export type AppCardProps = { export type AppCardProps = {
app: App app: App
@@ -483,4 +497,4 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
) )
} }
export default AppCard export default React.memo(AppCard)

View File

@@ -0,0 +1,35 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
const DefaultCards = React.memo(() => {
const renderArray = Array.from({ length: 36 })
return (
<>
{
renderArray.map((_, index) => (
<div
key={index}
className='inline-flex h-[160px] rounded-xl bg-background-default-lighter'
/>
))
}
</>
)
})
const Empty = () => {
const { t } = useTranslation()
return (
<>
<DefaultCards />
<div className='absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-gradient-to-t from-background-body to-transparent'>
<span className='system-md-medium text-text-tertiary'>
{t('app.newApp.noAppsFound')}
</span>
</div>
</>
)
}
export default React.memo(Empty)

View File

@@ -0,0 +1,46 @@
import React from 'react'
import Link from 'next/link'
import { RiDiscordFill, RiGithubFill } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
type CustomLinkProps = {
href: string
children: React.ReactNode
}
const CustomLink = React.memo(({
href,
children,
}: CustomLinkProps) => {
return (
<Link
className='flex h-8 w-8 cursor-pointer items-center justify-center transition-opacity duration-200 ease-in-out hover:opacity-80'
target='_blank'
rel='noopener noreferrer'
href={href}
>
{children}
</Link>
)
})
const Footer = () => {
const { t } = useTranslation()
return (
<footer className='shrink-0 grow-0 px-12 py-6'>
<h3 className='text-gradient text-xl font-semibold leading-tight'>{t('app.join')}</h3>
<p className='system-sm-regular mt-1 text-text-tertiary'>{t('app.communityIntro')}</p>
<div className='mt-3 flex items-center gap-2'>
<CustomLink href='https://github.com/langgenius/dify'>
<RiGithubFill className='h-5 w-5 text-text-tertiary' />
</CustomLink>
<CustomLink href='https://discord.gg/FngNHpbcY7'>
<RiDiscordFill className='h-5 w-5 text-text-tertiary' />
</CustomLink>
</div>
</footer>
)
}
export default React.memo(Footer)

View File

@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'
type DSLDragDropHookProps = { type DSLDragDropHookProps = {
onDSLFileDropped: (file: File) => void onDSLFileDropped: (file: File) => void
containerRef: React.RefObject<HTMLDivElement> containerRef: React.RefObject<HTMLDivElement | null>
enabled?: boolean enabled?: boolean
} }

View File

@@ -0,0 +1,26 @@
'use client'
import { useEducationInit } from '@/app/education-apply/hooks'
import { useGlobalPublicStore } from '@/context/global-public-context'
import List from './list'
import Footer from './footer'
import useDocumentTitle from '@/hooks/use-document-title'
import { useTranslation } from 'react-i18next'
const Apps = () => {
const { t } = useTranslation()
const { systemFeatures } = useGlobalPublicStore()
useDocumentTitle(t('common.menus.apps'))
useEducationInit()
return (
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
<List />
{!systemFeatures.branding.enabled && (
<Footer />
)}
</div >
)
}
export default Apps

View File

@@ -15,8 +15,8 @@ import {
RiMessage3Line, RiMessage3Line,
RiRobot3Line, RiRobot3Line,
} from '@remixicon/react' } from '@remixicon/react'
import AppCard from './AppCard' import AppCard from './app-card'
import NewAppCard from './NewAppCard' import NewAppCard from './new-app-card'
import useAppsQueryState from './hooks/use-apps-query-state' import useAppsQueryState from './hooks/use-apps-query-state'
import { useDSLDragDrop } from './hooks/use-dsl-drag-drop' import { useDSLDragDrop } from './hooks/use-dsl-drag-drop'
import type { AppListResponse } from '@/models/app' import type { AppListResponse } from '@/models/app'
@@ -28,10 +28,17 @@ import TabSliderNew from '@/app/components/base/tab-slider-new'
import { useTabSearchParams } from '@/hooks/use-tab-searchparams' import { useTabSearchParams } from '@/hooks/use-tab-searchparams'
import Input from '@/app/components/base/input' import Input from '@/app/components/base/input'
import { useStore as useTagStore } from '@/app/components/base/tag-management/store' import { useStore as useTagStore } from '@/app/components/base/tag-management/store'
import TagManagementModal from '@/app/components/base/tag-management'
import TagFilter from '@/app/components/base/tag-management/filter' import TagFilter from '@/app/components/base/tag-management/filter'
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label' import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
import CreateFromDSLModal from '@/app/components/app/create-from-dsl-modal' import dynamic from 'next/dynamic'
import Empty from './empty'
const TagManagementModal = dynamic(() => import('@/app/components/base/tag-management'), {
ssr: false,
})
const CreateFromDSLModal = dynamic(() => import('@/app/components/app/create-from-dsl-modal'), {
ssr: false,
})
const getKey = ( const getKey = (
pageIndex: number, pageIndex: number,
@@ -57,7 +64,7 @@ const getKey = (
return null return null
} }
const Apps = () => { const List = () => {
const { t } = useTranslation() const { t } = useTranslation()
const router = useRouter() const router = useRouter()
const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext() const { isCurrentWorkspaceEditor, isCurrentWorkspaceDatasetOperator } = useAppContext()
@@ -209,7 +216,7 @@ const Apps = () => {
: <div className='relative grid grow grid-cols-1 content-start gap-4 overflow-hidden px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6'> : <div className='relative grid grow grid-cols-1 content-start gap-4 overflow-hidden px-12 pt-2 sm:grid-cols-1 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-5 2k:grid-cols-6'>
{isCurrentWorkspaceEditor {isCurrentWorkspaceEditor
&& <NewAppCard ref={newAppCardRef} className='z-10' onSuccess={mutate} />} && <NewAppCard ref={newAppCardRef} className='z-10' onSuccess={mutate} />}
<NoAppsFound /> <Empty />
</div>} </div>}
{isCurrentWorkspaceEditor && ( {isCurrentWorkspaceEditor && (
@@ -248,22 +255,4 @@ const Apps = () => {
) )
} }
export default Apps export default List
function NoAppsFound() {
const { t } = useTranslation()
function renderDefaultCard() {
const defaultCards = Array.from({ length: 36 }, (_, index) => (
<div key={index} className='inline-flex h-[160px] rounded-xl bg-background-default-lighter'></div>
))
return defaultCards
}
return (
<>
{renderDefaultCard()}
<div className='absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center bg-gradient-to-t from-background-body to-transparent'>
<span className='system-md-medium text-text-tertiary'>{t('app.newApp.noAppsFound')}</span>
</div>
</>
)
}

View File

@@ -1,32 +1,38 @@
'use client' 'use client'
import { useMemo, useState } from 'react' import React, { useMemo, useState } from 'react'
import { import {
useRouter, useRouter,
useSearchParams, useSearchParams,
} from 'next/navigation' } from 'next/navigation'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import CreateAppTemplateDialog from '@/app/components/app/create-app-dialog' import { CreateFromDSLModalTab } from '@/app/components/app/create-from-dsl-modal'
import CreateAppModal from '@/app/components/app/create-app-modal'
import CreateFromDSLModal, { CreateFromDSLModalTab } from '@/app/components/app/create-from-dsl-modal'
import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import { FileArrow01, FilePlus01, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files' import { FileArrow01, FilePlus01, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import dynamic from 'next/dynamic'
const CreateAppModal = dynamic(() => import('@/app/components/app/create-app-modal'), {
ssr: false,
})
const CreateAppTemplateDialog = dynamic(() => import('@/app/components/app/create-app-dialog'), {
ssr: false,
})
const CreateFromDSLModal = dynamic(() => import('@/app/components/app/create-from-dsl-modal'), {
ssr: false,
})
export type CreateAppCardProps = { export type CreateAppCardProps = {
className?: string className?: string
onSuccess?: () => void onSuccess?: () => void
ref: React.RefObject<HTMLDivElement | null>
} }
const CreateAppCard = ( const CreateAppCard = ({
{ ref,
ref, className,
className, onSuccess,
onSuccess, }: CreateAppCardProps) => {
}: CreateAppCardProps & {
ref: React.RefObject<HTMLDivElement>;
},
) => {
const { t } = useTranslation() const { t } = useTranslation()
const { onPlanInfoChanged } = useProviderContext() const { onPlanInfoChanged } = useProviderContext()
const searchParams = useSearchParams() const searchParams = useSearchParams()
@@ -67,52 +73,58 @@ const CreateAppCard = (
</button> </button>
</div> </div>
<CreateAppModal {showNewAppModal && (
show={showNewAppModal} <CreateAppModal
onClose={() => setShowNewAppModal(false)} show={showNewAppModal}
onSuccess={() => { onClose={() => setShowNewAppModal(false)}
onPlanInfoChanged() onSuccess={() => {
if (onSuccess) onPlanInfoChanged()
onSuccess() if (onSuccess)
}} onSuccess()
onCreateFromTemplate={() => { }}
setShowNewAppTemplateDialog(true) onCreateFromTemplate={() => {
setShowNewAppModal(false) setShowNewAppTemplateDialog(true)
}} setShowNewAppModal(false)
/> }}
<CreateAppTemplateDialog />
show={showNewAppTemplateDialog} )}
onClose={() => setShowNewAppTemplateDialog(false)} {showNewAppTemplateDialog && (
onSuccess={() => { <CreateAppTemplateDialog
onPlanInfoChanged() show={showNewAppTemplateDialog}
if (onSuccess) onClose={() => setShowNewAppTemplateDialog(false)}
onSuccess() onSuccess={() => {
}} onPlanInfoChanged()
onCreateFromBlank={() => { if (onSuccess)
setShowNewAppModal(true) onSuccess()
setShowNewAppTemplateDialog(false) }}
}} onCreateFromBlank={() => {
/> setShowNewAppModal(true)
<CreateFromDSLModal setShowNewAppTemplateDialog(false)
show={showCreateFromDSLModal} }}
onClose={() => { />
setShowCreateFromDSLModal(false) )}
{showCreateFromDSLModal && (
<CreateFromDSLModal
show={showCreateFromDSLModal}
onClose={() => {
setShowCreateFromDSLModal(false)
if (dslUrl) if (dslUrl)
replace('/') replace('/')
}} }}
activeTab={activeTab} activeTab={activeTab}
dslUrl={dslUrl} dslUrl={dslUrl}
onSuccess={() => { onSuccess={() => {
onPlanInfoChanged() onPlanInfoChanged()
if (onSuccess) if (onSuccess)
onSuccess() onSuccess()
}} }}
/> />
)}
</div> </div>
) )
} }
CreateAppCard.displayName = 'CreateAppCard' CreateAppCard.displayName = 'CreateAppCard'
export default CreateAppCard
export { CreateAppCard } export default React.memo(CreateAppCard)

View File

@@ -1,5 +1,6 @@
'use client' 'use client'
import React from 'react'
import type { FC } from 'react' import type { FC } from 'react'
import { init } from 'emoji-mart' import { init } from 'emoji-mart'
import data from '@emoji-mart/data' import data from '@emoji-mart/data'
@@ -71,4 +72,4 @@ const AppIcon: FC<AppIconProps> = ({
</span> </span>
} }
export default AppIcon export default React.memo(AppIcon)

View File

@@ -5,10 +5,7 @@ import {
import type { EnvironmentVariable } from '@/app/components/workflow/types' import type { EnvironmentVariable } from '@/app/components/workflow/types'
import { DSL_EXPORT_CHECK } from '@/app/components/workflow/constants' import { DSL_EXPORT_CHECK } from '@/app/components/workflow/constants'
import { useStore } from '@/app/components/workflow/store' import { useStore } from '@/app/components/workflow/store'
import Features from '@/app/components/workflow/features'
import PluginDependency from '@/app/components/workflow/plugin-dependency' import PluginDependency from '@/app/components/workflow/plugin-dependency'
import UpdateDSLModal from '@/app/components/workflow/update-dsl-modal'
import DSLExportConfirmModal from '@/app/components/workflow/dsl-export-confirm-modal'
import { import {
useDSL, useDSL,
usePanelInteractions, usePanelInteractions,
@@ -16,6 +13,17 @@ import {
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import WorkflowHeader from './workflow-header' import WorkflowHeader from './workflow-header'
import WorkflowPanel from './workflow-panel' import WorkflowPanel from './workflow-panel'
import dynamic from 'next/dynamic'
const Features = dynamic(() => import('@/app/components/workflow/features'), {
ssr: false,
})
const UpdateDSLModal = dynamic(() => import('@/app/components/workflow/update-dsl-modal'), {
ssr: false,
})
const DSLExportConfirmModal = dynamic(() => import('@/app/components/workflow/dsl-export-confirm-modal'), {
ssr: false,
})
const WorkflowChildren = () => { const WorkflowChildren = () => {
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()

View File

@@ -4,17 +4,35 @@ import { useStore } from '@/app/components/workflow/store'
import { import {
useIsChatMode, useIsChatMode,
} from '../hooks' } from '../hooks'
import DebugAndPreview from '@/app/components/workflow/panel/debug-and-preview'
import Record from '@/app/components/workflow/panel/record'
import WorkflowPreview from '@/app/components/workflow/panel/workflow-preview'
import ChatRecord from '@/app/components/workflow/panel/chat-record'
import ChatVariablePanel from '@/app/components/workflow/panel/chat-variable-panel'
import GlobalVariablePanel from '@/app/components/workflow/panel/global-variable-panel'
import VersionHistoryPanel from '@/app/components/workflow/panel/version-history-panel'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import MessageLogModal from '@/app/components/base/message-log-modal'
import type { PanelProps } from '@/app/components/workflow/panel' import type { PanelProps } from '@/app/components/workflow/panel'
import Panel from '@/app/components/workflow/panel' import Panel from '@/app/components/workflow/panel'
import dynamic from 'next/dynamic'
const MessageLogModal = dynamic(() => import('@/app/components/base/message-log-modal'), {
ssr: false,
})
const Record = dynamic(() => import('@/app/components/workflow/panel/record'), {
ssr: false,
})
const ChatRecord = dynamic(() => import('@/app/components/workflow/panel/chat-record'), {
ssr: false,
})
const DebugAndPreview = dynamic(() => import('@/app/components/workflow/panel/debug-and-preview'), {
ssr: false,
})
const WorkflowPreview = dynamic(() => import('@/app/components/workflow/panel/workflow-preview'), {
ssr: false,
})
const ChatVariablePanel = dynamic(() => import('@/app/components/workflow/panel/chat-variable-panel'), {
ssr: false,
})
const GlobalVariablePanel = dynamic(() => import('@/app/components/workflow/panel/global-variable-panel'), {
ssr: false,
})
const VersionHistoryPanel = dynamic(() => import('@/app/components/workflow/panel/version-history-panel'), {
ssr: false,
})
const WorkflowPanelOnLeft = () => { const WorkflowPanelOnLeft = () => {
const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({ const { currentLogItem, setCurrentLogItem, showMessageLogModal, setShowMessageLogModal, currentLogModalActiveTab } = useAppStore(useShallow(state => ({

View File

@@ -1,3 +1,5 @@
'use client'
import { import {
useMemo, useMemo,
} from 'react' } from 'react'

View File

@@ -50,8 +50,7 @@ const HeaderInNormal = ({
setShowDebugAndPreviewPanel(false) setShowDebugAndPreviewPanel(false)
setShowVariableInspectPanel(false) setShowVariableInspectPanel(false)
setShowChatVariablePanel(false) setShowChatVariablePanel(false)
}, [handleBackupDraft, workflowStore, handleNodeSelect, selectedNode, }, [workflowStore, handleBackupDraft, selectedNode, handleNodeSelect, setShowWorkflowVersionHistoryPanel, setShowEnvPanel, setShowDebugAndPreviewPanel, setShowVariableInspectPanel, setShowChatVariablePanel])
setShowWorkflowVersionHistoryPanel, setShowEnvPanel, setShowDebugAndPreviewPanel, setShowVariableInspectPanel])
return ( return (
<> <>

View File

@@ -4,10 +4,17 @@ import {
} from '../hooks' } from '../hooks'
import type { HeaderInNormalProps } from './header-in-normal' import type { HeaderInNormalProps } from './header-in-normal'
import HeaderInNormal from './header-in-normal' import HeaderInNormal from './header-in-normal'
import HeaderInHistory from './header-in-view-history'
import type { HeaderInRestoringProps } from './header-in-restoring' import type { HeaderInRestoringProps } from './header-in-restoring'
import HeaderInRestoring from './header-in-restoring'
import { useStore } from '../store' import { useStore } from '../store'
import dynamic from 'next/dynamic'
const HeaderInHistory = dynamic(() => import('./header-in-view-history'), {
ssr: false,
})
const HeaderInRestoring = dynamic(() => import('./header-in-restoring'), {
ssr: false,
})
export type HeaderProps = { export type HeaderProps = {
normal?: HeaderInNormalProps normal?: HeaderInNormalProps
restoring?: HeaderInRestoringProps restoring?: HeaderInRestoringProps

View File

@@ -79,10 +79,14 @@ import {
} from './constants' } from './constants'
import { WorkflowHistoryProvider } from './workflow-history-store' import { WorkflowHistoryProvider } from './workflow-history-store'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import Confirm from '@/app/components/base/confirm'
import DatasetsDetailProvider from './datasets-detail-store/provider' import DatasetsDetailProvider from './datasets-detail-store/provider'
import { HooksStoreContextProvider } from './hooks-store' import { HooksStoreContextProvider } from './hooks-store'
import type { Shape as HooksStoreShape } from './hooks-store' import type { Shape as HooksStoreShape } from './hooks-store'
import dynamic from 'next/dynamic'
const Confirm = dynamic(() => import('@/app/components/base/confirm'), {
ssr: false,
})
const nodeTypes = { const nodeTypes = {
[CUSTOM_NODE]: CustomNode, [CUSTOM_NODE]: CustomNode,

View File

@@ -4,13 +4,6 @@ import type { Dispatch, SetStateAction } from 'react'
import { useCallback, useState } from 'react' import { useCallback, useState } from 'react'
import { createContext, useContext, useContextSelector } from 'use-context-selector' import { createContext, useContext, useContextSelector } from 'use-context-selector'
import { useRouter, useSearchParams } from 'next/navigation' import { useRouter, useSearchParams } from 'next/navigation'
import AccountSetting from '@/app/components/header/account-setting'
import ApiBasedExtensionModal from '@/app/components/header/account-setting/api-based-extension-page/modal'
import ModerationSettingModal from '@/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal'
import ExternalDataToolModal from '@/app/components/app/configuration/tools/external-data-tool-modal'
import AnnotationFullModal from '@/app/components/billing/annotation-full/modal'
import ModelModal from '@/app/components/header/account-setting/model-provider-page/model-modal'
import ExternalAPIModal from '@/app/components/datasets/external-api/external-api-modal'
import type { import type {
ConfigurationMethodEnum, ConfigurationMethodEnum,
CustomConfigurationModelFixedFields, CustomConfigurationModelFixedFields,
@@ -20,23 +13,56 @@ import type {
import { import {
EDUCATION_VERIFYING_LOCALSTORAGE_ITEM, EDUCATION_VERIFYING_LOCALSTORAGE_ITEM,
} from '@/app/education-apply/constants' } from '@/app/education-apply/constants'
import Pricing from '@/app/components/billing/pricing'
import type { ModerationConfig, PromptVariable } from '@/models/debug' import type { ModerationConfig, PromptVariable } from '@/models/debug'
import type { import type {
ApiBasedExtension, ApiBasedExtension,
ExternalDataTool, ExternalDataTool,
} from '@/models/common' } from '@/models/common'
import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations' import type { CreateExternalAPIReq } from '@/app/components/datasets/external-api/declarations'
import ModelLoadBalancingEntryModal from '@/app/components/header/account-setting/model-provider-page/model-modal/model-load-balancing-entry-modal'
import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal' import type { ModelLoadBalancingModalProps } from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
import ModelLoadBalancingModal from '@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'
import OpeningSettingModal from '@/app/components/base/features/new-feature-panel/conversation-opener/modal'
import type { OpeningStatement } from '@/app/components/base/features/types' import type { OpeningStatement } from '@/app/components/base/features/types'
import type { InputVar } from '@/app/components/workflow/types' import type { InputVar } from '@/app/components/workflow/types'
import type { UpdatePluginPayload } from '@/app/components/plugins/types' import type { UpdatePluginPayload } from '@/app/components/plugins/types'
import UpdatePlugin from '@/app/components/plugins/update-plugin'
import { removeSpecificQueryParam } from '@/utils' import { removeSpecificQueryParam } from '@/utils'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import dynamic from 'next/dynamic'
const AccountSetting = dynamic(() => import('@/app/components/header/account-setting'), {
ssr: false,
})
const ApiBasedExtensionModal = dynamic(() => import('@/app/components/header/account-setting/api-based-extension-page/modal'), {
ssr: false,
})
const ModerationSettingModal = dynamic(() => import('@/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal'), {
ssr: false,
})
const ExternalDataToolModal = dynamic(() => import('@/app/components/app/configuration/tools/external-data-tool-modal'), {
ssr: false,
})
const Pricing = dynamic(() => import('@/app/components/billing/pricing'), {
ssr: false,
})
const AnnotationFullModal = dynamic(() => import('@/app/components/billing/annotation-full/modal'), {
ssr: false,
})
const ModelModal = dynamic(() => import('@/app/components/header/account-setting/model-provider-page/model-modal'), {
ssr: false,
})
const ExternalAPIModal = dynamic(() => import('@/app/components/datasets/external-api/external-api-modal'), {
ssr: false,
})
const ModelLoadBalancingModal = dynamic(() => import('@/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal'), {
ssr: false,
})
const ModelLoadBalancingEntryModal = dynamic(() => import('@/app/components/header/account-setting/model-provider-page/model-modal/model-load-balancing-entry-modal'), {
ssr: false,
})
const OpeningSettingModal = dynamic(() => import('@/app/components/base/features/new-feature-panel/conversation-opener/modal'), {
ssr: false,
})
const UpdatePlugin = dynamic(() => import('@/app/components/plugins/update-plugin'), {
ssr: false,
})
export type ModalState<T> = { export type ModalState<T> = {
payload: T payload: T

View File

@@ -12,6 +12,9 @@ const withMDX = require('@next/mdx')({
// providerImportSource: "@mdx-js/react", // providerImportSource: "@mdx-js/react",
}, },
}) })
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
// the default url to prevent parse url error when running jest // the default url to prevent parse url error when running jest
const hasSetWebPrefix = process.env.NEXT_PUBLIC_WEB_PREFIX const hasSetWebPrefix = process.env.NEXT_PUBLIC_WEB_PREFIX
@@ -66,4 +69,4 @@ const nextConfig = {
output: 'standalone', output: 'standalone',
} }
module.exports = withMDX(nextConfig) module.exports = withBundleAnalyzer(withMDX(nextConfig))

View File

@@ -36,7 +36,8 @@
"test:watch": "jest --watch", "test:watch": "jest --watch",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build", "build-storybook": "storybook build",
"preinstall": "npx only-allow pnpm" "preinstall": "npx only-allow pnpm",
"analyze": "ANALYZE=true pnpm build"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.22.3", "@babel/runtime": "^7.22.3",
@@ -159,6 +160,7 @@
"@eslint/js": "^9.20.0", "@eslint/js": "^9.20.0",
"@faker-js/faker": "^9.0.3", "@faker-js/faker": "^9.0.3",
"@happy-dom/jest-environment": "^17.4.4", "@happy-dom/jest-environment": "^17.4.4",
"@next/bundle-analyzer": "^15.4.1",
"@next/eslint-plugin-next": "~15.3.5", "@next/eslint-plugin-next": "~15.3.5",
"@rgrove/parse-xml": "^4.1.0", "@rgrove/parse-xml": "^4.1.0",
"@storybook/addon-essentials": "8.5.0", "@storybook/addon-essentials": "8.5.0",

114
web/pnpm-lock.yaml generated
View File

@@ -402,6 +402,9 @@ importers:
'@happy-dom/jest-environment': '@happy-dom/jest-environment':
specifier: ^17.4.4 specifier: ^17.4.4
version: 17.6.3 version: 17.6.3
'@next/bundle-analyzer':
specifier: ^15.4.1
version: 15.4.1
'@next/eslint-plugin-next': '@next/eslint-plugin-next':
specifier: ~15.3.5 specifier: ~15.3.5
version: 15.3.5 version: 15.3.5
@@ -1316,6 +1319,10 @@ packages:
resolution: {integrity: sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==} resolution: {integrity: sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==}
engines: {node: '>17.0.0'} engines: {node: '>17.0.0'}
'@discoveryjs/json-ext@0.5.7':
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
engines: {node: '>=10.0.0'}
'@emnapi/core@1.4.4': '@emnapi/core@1.4.4':
resolution: {integrity: sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==} resolution: {integrity: sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==}
@@ -2099,6 +2106,9 @@ packages:
'@napi-rs/wasm-runtime@0.2.12': '@napi-rs/wasm-runtime@0.2.12':
resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
'@next/bundle-analyzer@15.4.1':
resolution: {integrity: sha512-O5R3iPLR3/oQWFIXl+Mnd02IyhvWBterTlXcceIGw29QHWL/gjvyO0eIVEvrJPS7zzE6/NSu1TiSVgi8mxotlw==}
'@next/env@15.3.5': '@next/env@15.3.5':
resolution: {integrity: sha512-7g06v8BUVtN2njAX/r8gheoVffhiKFVt4nx74Tt6G4Hqw9HCLYQVx/GkH2qHvPtAHZaUNZ0VXAa0pQP6v1wk7g==} resolution: {integrity: sha512-7g06v8BUVtN2njAX/r8gheoVffhiKFVt4nx74Tt6G4Hqw9HCLYQVx/GkH2qHvPtAHZaUNZ0VXAa0pQP6v1wk7g==}
@@ -2459,6 +2469,9 @@ packages:
webpack-plugin-serve: webpack-plugin-serve:
optional: true optional: true
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
'@react-aria/focus@3.20.5': '@react-aria/focus@3.20.5':
resolution: {integrity: sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==} resolution: {integrity: sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==}
peerDependencies: peerDependencies:
@@ -4341,6 +4354,9 @@ packages:
dayjs@1.11.13: dayjs@1.11.13:
resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
debounce@1.2.1:
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
debug@3.2.7: debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies: peerDependencies:
@@ -4498,6 +4514,9 @@ packages:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'} engines: {node: '>=12'}
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
echarts-for-react@3.0.2: echarts-for-react@3.0.2:
resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==} resolution: {integrity: sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==}
peerDependencies: peerDependencies:
@@ -5250,6 +5269,10 @@ packages:
graphemer@1.4.0: graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
gzip-size@6.0.0:
resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
engines: {node: '>=10'}
hachure-fill@0.5.2: hachure-fill@0.5.2:
resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
@@ -5563,6 +5586,10 @@ packages:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'} engines: {node: '>=12'}
is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
is-stream@2.0.1: is-stream@2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -6299,6 +6326,10 @@ packages:
monaco-editor@0.52.2: monaco-editor@0.52.2:
resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==} resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==}
mrmime@2.0.1:
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
engines: {node: '>=10'}
ms@2.1.3: ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -6454,6 +6485,10 @@ packages:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
opener@1.5.2:
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
hasBin: true
optionator@0.9.4: optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@@ -7358,6 +7393,10 @@ packages:
simple-swizzle@0.2.2: simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
sirv@2.0.4:
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
engines: {node: '>= 10'}
sisteransi@1.0.5: sisteransi@1.0.5:
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -7679,6 +7718,10 @@ packages:
resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
tr46@0.0.3: tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
@@ -7994,6 +8037,11 @@ packages:
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
engines: {node: '>=12'} engines: {node: '>=12'}
webpack-bundle-analyzer@4.10.1:
resolution: {integrity: sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==}
engines: {node: '>= 10.13.0'}
hasBin: true
webpack-code-inspector-plugin@0.18.3: webpack-code-inspector-plugin@0.18.3:
resolution: {integrity: sha512-3782rsJhBnRiw0IpR6EqnyGDQoiSq0CcGeLJ52rZXlszYCe8igXtcujq7OhI0byaivWQ1LW7sXKyMEoVpBhq0w==} resolution: {integrity: sha512-3782rsJhBnRiw0IpR6EqnyGDQoiSq0CcGeLJ52rZXlszYCe8igXtcujq7OhI0byaivWQ1LW7sXKyMEoVpBhq0w==}
@@ -8064,6 +8112,18 @@ packages:
resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
ws@7.5.10:
resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==}
engines: {node: '>=8.3.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ^5.0.2
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
ws@8.18.3: ws@8.18.3:
resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@@ -9100,6 +9160,8 @@ snapshots:
'@dagrejs/graphlib@2.2.4': {} '@dagrejs/graphlib@2.2.4': {}
'@discoveryjs/json-ext@0.5.7': {}
'@emnapi/core@1.4.4': '@emnapi/core@1.4.4':
dependencies: dependencies:
'@emnapi/wasi-threads': 1.0.3 '@emnapi/wasi-threads': 1.0.3
@@ -10072,6 +10134,13 @@ snapshots:
'@tybys/wasm-util': 0.10.0 '@tybys/wasm-util': 0.10.0
optional: true optional: true
'@next/bundle-analyzer@15.4.1':
dependencies:
webpack-bundle-analyzer: 4.10.1
transitivePeerDependencies:
- bufferutil
- utf-8-validate
'@next/env@15.3.5': {} '@next/env@15.3.5': {}
'@next/eslint-plugin-next@15.3.5': '@next/eslint-plugin-next@15.3.5':
@@ -10361,6 +10430,8 @@ snapshots:
type-fest: 2.19.0 type-fest: 2.19.0
webpack-hot-middleware: 2.26.1 webpack-hot-middleware: 2.26.1
'@polka/url@1.0.0-next.29': {}
'@react-aria/focus@3.20.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': '@react-aria/focus@3.20.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies: dependencies:
'@react-aria/interactions': 3.25.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-aria/interactions': 3.25.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -12629,6 +12700,8 @@ snapshots:
dayjs@1.11.13: {} dayjs@1.11.13: {}
debounce@1.2.1: {}
debug@3.2.7: debug@3.2.7:
dependencies: dependencies:
ms: 2.1.3 ms: 2.1.3
@@ -12756,6 +12829,8 @@ snapshots:
dotenv@16.6.1: {} dotenv@16.6.1: {}
duplexer@0.1.2: {}
echarts-for-react@3.0.2(echarts@5.6.0)(react@19.1.0): echarts-for-react@3.0.2(echarts@5.6.0)(react@19.1.0):
dependencies: dependencies:
echarts: 5.6.0 echarts: 5.6.0
@@ -13775,6 +13850,10 @@ snapshots:
graphemer@1.4.0: {} graphemer@1.4.0: {}
gzip-size@6.0.0:
dependencies:
duplexer: 0.1.2
hachure-fill@0.5.2: {} hachure-fill@0.5.2: {}
happy-dom@17.6.3: happy-dom@17.6.3:
@@ -14149,6 +14228,8 @@ snapshots:
is-plain-obj@4.1.0: {} is-plain-obj@4.1.0: {}
is-plain-object@5.0.0: {}
is-stream@2.0.1: {} is-stream@2.0.1: {}
is-stream@3.0.0: {} is-stream@3.0.0: {}
@@ -15373,6 +15454,8 @@ snapshots:
monaco-editor@0.52.2: {} monaco-editor@0.52.2: {}
mrmime@2.0.1: {}
ms@2.1.3: {} ms@2.1.3: {}
mz@2.7.0: mz@2.7.0:
@@ -15536,6 +15619,8 @@ snapshots:
is-docker: 2.2.1 is-docker: 2.2.1
is-wsl: 2.2.0 is-wsl: 2.2.0
opener@1.5.2: {}
optionator@0.9.4: optionator@0.9.4:
dependencies: dependencies:
deep-is: 0.1.4 deep-is: 0.1.4
@@ -16599,6 +16684,12 @@ snapshots:
dependencies: dependencies:
is-arrayish: 0.3.2 is-arrayish: 0.3.2
sirv@2.0.4:
dependencies:
'@polka/url': 1.0.0-next.29
mrmime: 2.0.1
totalist: 3.0.1
sisteransi@1.0.5: {} sisteransi@1.0.5: {}
size-sensor@1.0.2: {} size-sensor@1.0.2: {}
@@ -16913,6 +17004,8 @@ snapshots:
dependencies: dependencies:
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
totalist@3.0.1: {}
tr46@0.0.3: tr46@0.0.3:
optional: true optional: true
@@ -17246,6 +17339,25 @@ snapshots:
webidl-conversions@7.0.0: {} webidl-conversions@7.0.0: {}
webpack-bundle-analyzer@4.10.1:
dependencies:
'@discoveryjs/json-ext': 0.5.7
acorn: 8.15.0
acorn-walk: 8.3.4
commander: 7.2.0
debounce: 1.2.1
escape-string-regexp: 4.0.0
gzip-size: 6.0.0
html-escaper: 2.0.2
is-plain-object: 5.0.0
opener: 1.5.2
picocolors: 1.1.1
sirv: 2.0.4
ws: 7.5.10
transitivePeerDependencies:
- bufferutil
- utf-8-validate
webpack-code-inspector-plugin@0.18.3: webpack-code-inspector-plugin@0.18.3:
dependencies: dependencies:
code-inspector-core: 0.18.3 code-inspector-core: 0.18.3
@@ -17348,6 +17460,8 @@ snapshots:
imurmurhash: 0.1.4 imurmurhash: 0.1.4
signal-exit: 3.0.7 signal-exit: 3.0.7
ws@7.5.10: {}
ws@8.18.3: {} ws@8.18.3: {}
xml-name-validator@4.0.0: {} xml-name-validator@4.0.0: {}