dify
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66683C11.2865 2.66683 11.5965 2.66683 11.8508 2.73498C12.541 2.91991 13.0801 3.45901 13.265 4.14919C13.3332 4.40352 13.3332 4.71352 13.3332 5.3335V11.4668C13.3332 12.5869 13.3332 13.147 13.1152 13.5748C12.9234 13.9511 12.6175 14.2571 12.2412 14.4488C11.8133 14.6668 11.2533 14.6668 10.1332 14.6668H5.8665C4.7464 14.6668 4.18635 14.6668 3.75852 14.4488C3.3822 14.2571 3.07624 13.9511 2.88449 13.5748C2.6665 13.147 2.6665 12.5869 2.6665 11.4668V5.3335C2.6665 4.71352 2.6665 4.40352 2.73465 4.14919C2.91959 3.45901 3.45868 2.91991 4.14887 2.73498C4.4032 2.66683 4.71319 2.66683 5.33317 2.66683M5.99984 10.0002L7.33317 11.3335L10.3332 8.3335M6.39984 4.00016H9.59984C9.9732 4.00016 10.1599 4.00016 10.3025 3.9275C10.4279 3.86359 10.5299 3.7616 10.5938 3.63616C10.6665 3.49355 10.6665 3.30686 10.6665 2.9335V2.40016C10.6665 2.02679 10.6665 1.84011 10.5938 1.6975C10.5299 1.57206 10.4279 1.47007 10.3025 1.40616C10.1599 1.3335 9.97321 1.3335 9.59984 1.3335H6.39984C6.02647 1.3335 5.83978 1.3335 5.69718 1.40616C5.57174 1.47007 5.46975 1.57206 5.40583 1.6975C5.33317 1.84011 5.33317 2.02679 5.33317 2.40016V2.9335C5.33317 3.30686 5.33317 3.49355 5.40583 3.63616C5.46975 3.7616 5.57174 3.86359 5.69718 3.9275C5.83978 4.00016 6.02647 4.00016 6.39984 4.00016Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66634H11.9998C12.3535 2.66634 12.6926 2.80682 12.9426 3.05687C13.1927 3.30691 13.3332 3.64605 13.3332 3.99967V13.333C13.3332 13.6866 13.1927 14.0258 12.9426 14.2758C12.6926 14.5259 12.3535 14.6663 11.9998 14.6663H3.99984C3.64622 14.6663 3.30708 14.5259 3.05703 14.2758C2.80698 14.0258 2.6665 13.6866 2.6665 13.333V3.99967C2.6665 3.64605 2.80698 3.30691 3.05703 3.05687C3.30708 2.80682 3.64622 2.66634 3.99984 2.66634H5.33317M5.99984 1.33301H9.99984C10.368 1.33301 10.6665 1.63148 10.6665 1.99967V3.33301C10.6665 3.7012 10.368 3.99967 9.99984 3.99967H5.99984C5.63165 3.99967 5.33317 3.7012 5.33317 3.33301V1.99967C5.33317 1.63148 5.63165 1.33301 5.99984 1.33301Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 875 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66634H11.9998C12.3535 2.66634 12.6926 2.80682 12.9426 3.05687C13.1927 3.30691 13.3332 3.64605 13.3332 3.99967V13.333C13.3332 13.6866 13.1927 14.0258 12.9426 14.2758C12.6926 14.5259 12.3535 14.6663 11.9998 14.6663H3.99984C3.64622 14.6663 3.30708 14.5259 3.05703 14.2758C2.80698 14.0258 2.6665 13.6866 2.6665 13.333V3.99967C2.6665 3.64605 2.80698 3.30691 3.05703 3.05687C3.30708 2.80682 3.64622 2.66634 3.99984 2.66634H5.33317M5.99984 1.33301H9.99984C10.368 1.33301 10.6665 1.63148 10.6665 1.99967V3.33301C10.6665 3.7012 10.368 3.99967 9.99984 3.99967H5.99984C5.63165 3.99967 5.33317 3.7012 5.33317 3.33301V1.99967C5.33317 1.63148 5.63165 1.33301 5.99984 1.33301Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 875 B |
10
dify/web/app/components/develop/secret-key/assets/pause.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_129_2189)">
|
||||
<path d="M10.6666 14V10M13.3333 14V10M18.6666 12C18.6666 15.6819 15.6819 18.6667 12 18.6667C8.31808 18.6667 5.33331 15.6819 5.33331 12C5.33331 8.3181 8.31808 5.33333 12 5.33333C15.6819 5.33333 18.6666 8.3181 18.6666 12Z" stroke="#155EEF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_129_2189">
|
||||
<rect width="16" height="16" fill="white" transform="translate(4 4)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 580 B |
11
dify/web/app/components/develop/secret-key/assets/play.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_129_107)">
|
||||
<path d="M7.99998 14.6666C11.6819 14.6666 14.6666 11.6819 14.6666 7.99998C14.6666 4.31808 11.6819 1.33331 7.99998 1.33331C4.31808 1.33331 1.33331 4.31808 1.33331 7.99998C1.33331 11.6819 4.31808 14.6666 7.99998 14.6666Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.66665 5.33331L10.6666 7.99998L6.66665 10.6666V5.33331Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_129_107">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 703 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.33333 4.33333H4.34M11.6667 4.33333H11.6733M4.33333 11.6667H4.34M8.66667 8.66667H8.67333M11.6667 11.6667H11.6733M11.3333 14H14V11.3333M9.33333 11V14M14 9.33333H11M10.4 6.66667H12.9333C13.3067 6.66667 13.4934 6.66667 13.636 6.594C13.7614 6.53009 13.8634 6.4281 13.9273 6.30266C14 6.16005 14 5.97337 14 5.6V3.06667C14 2.6933 14 2.50661 13.9273 2.36401C13.8634 2.23856 13.7614 2.13658 13.636 2.07266C13.4934 2 13.3067 2 12.9333 2H10.4C10.0266 2 9.83995 2 9.69734 2.07266C9.5719 2.13658 9.46991 2.23856 9.406 2.36401C9.33333 2.50661 9.33333 2.6933 9.33333 3.06667V5.6C9.33333 5.97337 9.33333 6.16005 9.406 6.30266C9.46991 6.4281 9.5719 6.53009 9.69734 6.594C9.83995 6.66667 10.0266 6.66667 10.4 6.66667ZM3.06667 6.66667H5.6C5.97337 6.66667 6.16005 6.66667 6.30266 6.594C6.4281 6.53009 6.53009 6.4281 6.594 6.30266C6.66667 6.16005 6.66667 5.97337 6.66667 5.6V3.06667C6.66667 2.6933 6.66667 2.50661 6.594 2.36401C6.53009 2.23856 6.4281 2.13658 6.30266 2.07266C6.16005 2 5.97337 2 5.6 2H3.06667C2.6933 2 2.50661 2 2.36401 2.07266C2.23856 2.13658 2.13658 2.23856 2.07266 2.36401C2 2.50661 2 2.6933 2 3.06667V5.6C2 5.97337 2 6.16005 2.07266 6.30266C2.13658 6.4281 2.23856 6.53009 2.36401 6.594C2.50661 6.66667 2.6933 6.66667 3.06667 6.66667ZM3.06667 14H5.6C5.97337 14 6.16005 14 6.30266 13.9273C6.4281 13.8634 6.53009 13.7614 6.594 13.636C6.66667 13.4934 6.66667 13.3067 6.66667 12.9333V10.4C6.66667 10.0266 6.66667 9.83995 6.594 9.69734C6.53009 9.5719 6.4281 9.46991 6.30266 9.406C6.16005 9.33333 5.97337 9.33333 5.6 9.33333H3.06667C2.6933 9.33333 2.50661 9.33333 2.36401 9.406C2.23856 9.46991 2.13658 9.5719 2.07266 9.69734C2 9.83995 2 10.0266 2 10.4V12.9333C2 13.3067 2 13.4934 2.07266 13.636C2.13658 13.7614 2.23856 13.8634 2.36401 13.9273C2.50661 14 2.6933 14 3.06667 14Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.33333 4.33333H4.34M11.6667 4.33333H11.6733M4.33333 11.6667H4.34M8.66667 8.66667H8.67333M11.6667 11.6667H11.6733M11.3333 14H14V11.3333M9.33333 11V14M14 9.33333H11M10.4 6.66667H12.9333C13.3067 6.66667 13.4934 6.66667 13.636 6.594C13.7614 6.53009 13.8634 6.4281 13.9273 6.30266C14 6.16005 14 5.97337 14 5.6V3.06667C14 2.6933 14 2.50661 13.9273 2.36401C13.8634 2.23856 13.7614 2.13658 13.636 2.07266C13.4934 2 13.3067 2 12.9333 2H10.4C10.0266 2 9.83995 2 9.69734 2.07266C9.5719 2.13658 9.46991 2.23856 9.406 2.36401C9.33333 2.50661 9.33333 2.6933 9.33333 3.06667V5.6C9.33333 5.97337 9.33333 6.16005 9.406 6.30266C9.46991 6.4281 9.5719 6.53009 9.69734 6.594C9.83995 6.66667 10.0266 6.66667 10.4 6.66667ZM3.06667 6.66667H5.6C5.97337 6.66667 6.16005 6.66667 6.30266 6.594C6.4281 6.53009 6.53009 6.4281 6.594 6.30266C6.66667 6.16005 6.66667 5.97337 6.66667 5.6V3.06667C6.66667 2.6933 6.66667 2.50661 6.594 2.36401C6.53009 2.23856 6.4281 2.13658 6.30266 2.07266C6.16005 2 5.97337 2 5.6 2H3.06667C2.6933 2 2.50661 2 2.36401 2.07266C2.23856 2.13658 2.13658 2.23856 2.07266 2.36401C2 2.50661 2 2.6933 2 3.06667V5.6C2 5.97337 2 6.16005 2.07266 6.30266C2.13658 6.4281 2.23856 6.53009 2.36401 6.594C2.50661 6.66667 2.6933 6.66667 3.06667 6.66667ZM3.06667 14H5.6C5.97337 14 6.16005 14 6.30266 13.9273C6.4281 13.8634 6.53009 13.7614 6.594 13.636C6.66667 13.4934 6.66667 13.3067 6.66667 12.9333V10.4C6.66667 10.0266 6.66667 9.83995 6.594 9.69734C6.53009 9.5719 6.4281 9.46991 6.30266 9.406C6.16005 9.33333 5.97337 9.33333 5.6 9.33333H3.06667C2.6933 9.33333 2.50661 9.33333 2.36401 9.406C2.23856 9.46991 2.13658 9.5719 2.07266 9.69734C2 9.83995 2 10.0266 2 10.4V12.9333C2 13.3067 2 13.4934 2.07266 13.636C2.13658 13.7614 2.23856 13.8634 2.36401 13.9273C2.50661 14 2.6933 14 3.06667 14Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1694177685288" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4415" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M192 384h640a42.666667 42.666667 0 0 1 42.666667 42.666667v362.666666a42.666667 42.666667 0 0 1-42.666667 42.666667H192v106.666667a21.333333 21.333333 0 0 0 21.333333 21.333333h725.333334a21.333333 21.333333 0 0 0 21.333333-21.333333V308.821333L949.909333 298.666667h-126.528A98.048 98.048 0 0 1 725.333333 200.618667V72.661333L716.714667 64H213.333333a21.333333 21.333333 0 0 0-21.333333 21.333333v298.666667zM128 832H42.666667a42.666667 42.666667 0 0 1-42.666667-42.666667V426.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h85.333333V85.333333a85.333333 85.333333 0 0 1 85.333333-85.333333h530.026667L1024 282.453333V938.666667a85.333333 85.333333 0 0 1-85.333333 85.333333H213.333333a85.333333 85.333333 0 0 1-85.333333-85.333333v-106.666667z m61.376-364.885333c-27.434667 0-49.898667 6.528-67.712 19.968-19.221333 13.824-28.501333 33.024-28.501333 57.216s9.621333 42.624 29.226666 55.296c7.466667 4.608 27.093333 12.288 58.432 23.04 28.138667 9.216 44.522667 15.36 49.514667 18.048 15.68 8.448 23.872 19.968 23.872 34.56 0 11.52-5.696 20.352-16.384 27.264-10.688 6.528-25.664 9.984-44.181333 9.984-21.013333 0-36.352-4.224-46.314667-11.904-11.050667-8.832-17.813333-23.808-20.672-44.544H85.333333c1.792 34.944 13.546667 60.288 34.922667 76.416 17.450667 13.056 42.026667 19.584 73.386667 19.584 32.426667 0 57.706667-7.296 75.52-21.12 17.813333-14.208 26.730667-33.792 26.730666-58.368 0-25.344-11.050667-44.928-33.130666-59.136-9.984-6.144-32.064-15.36-66.624-26.88-23.509333-8.064-38.122667-13.824-43.477334-16.896-12.096-6.912-17.813333-16.512-17.813333-28.032 0-13.056 4.992-22.656 15.68-28.416 8.554667-4.992 20.672-7.296 36.693333-7.296 18.538667 0 32.789333 3.456 42.048 11.136 9.258667 7.296 16.021333 19.584 19.584 36.48h41.344c-2.496-29.952-12.821333-52.224-30.656-66.432-16.725333-13.44-40.256-19.968-70.186666-19.968z m118.976 5.376L398.848 746.666667h50.24l90.496-274.176h-45.226667l-69.845333 223.488h-1.066667l-69.845333-223.488h-45.226667z m368.405333-5.376c-37.76 0-67.690667 13.824-89.792 42.24-21.013333 26.496-31.36 60.288-31.36 101.376 0 40.704 10.346667 74.112 31.36 99.84 22.442667 27.648 53.802667 41.472 94.421334 41.472 22.805333 0 43.093333-3.072 61.632-9.216A143.829333 143.829333 0 0 0 789.333333 716.714667V600.746667h-109.013333v38.4h67.328v56.448c-8.533333 5.376-17.450667 9.6-27.434667 12.672a123.285333 123.285333 0 0 1-34.197333 4.608c-30.997333 0-53.802667-9.216-68.416-27.648-13.525333-17.28-20.309333-42.24-20.309333-74.496 0-33.792 7.488-59.52 22.826666-77.952 13.866667-17.664 32.768-26.112 56.64-26.112 19.221333 0 34.901333 4.224 46.656 13.056 11.413333 8.832 19.242667 21.888 22.826667 39.552h42.026667c-4.629333-30.72-16.042667-53.376-34.197334-68.736-18.88-15.744-44.544-23.424-77.312-23.424z" fill="#8a8a8a" p-id="4416"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1694177378730" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4206" width="16" height="16" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M192 384h640a42.666667 42.666667 0 0 1 42.666667 42.666667v362.666666a42.666667 42.666667 0 0 1-42.666667 42.666667H192v106.666667a21.333333 21.333333 0 0 0 21.333333 21.333333h725.333334a21.333333 21.333333 0 0 0 21.333333-21.333333V308.821333L949.909333 298.666667h-126.528A98.048 98.048 0 0 1 725.333333 200.618667V72.661333L716.714667 64H213.333333a21.333333 21.333333 0 0 0-21.333333 21.333333v298.666667zM128 832H42.666667a42.666667 42.666667 0 0 1-42.666667-42.666667V426.666667a42.666667 42.666667 0 0 1 42.666667-42.666667h85.333333V85.333333a85.333333 85.333333 0 0 1 85.333333-85.333333h530.026667L1024 282.453333V938.666667a85.333333 85.333333 0 0 1-85.333333 85.333333H213.333333a85.333333 85.333333 0 0 1-85.333333-85.333333v-106.666667z m61.376-364.885333c-27.434667 0-49.898667 6.528-67.712 19.968-19.221333 13.824-28.501333 33.024-28.501333 57.216s9.621333 42.624 29.226666 55.296c7.466667 4.608 27.093333 12.288 58.432 23.04 28.138667 9.216 44.522667 15.36 49.514667 18.048 15.68 8.448 23.872 19.968 23.872 34.56 0 11.52-5.696 20.352-16.384 27.264-10.688 6.528-25.664 9.984-44.181333 9.984-21.013333 0-36.352-4.224-46.314667-11.904-11.050667-8.832-17.813333-23.808-20.672-44.544H85.333333c1.792 34.944 13.546667 60.288 34.922667 76.416 17.450667 13.056 42.026667 19.584 73.386667 19.584 32.426667 0 57.706667-7.296 75.52-21.12 17.813333-14.208 26.730667-33.792 26.730666-58.368 0-25.344-11.050667-44.928-33.130666-59.136-9.984-6.144-32.064-15.36-66.624-26.88-23.509333-8.064-38.122667-13.824-43.477334-16.896-12.096-6.912-17.813333-16.512-17.813333-28.032 0-13.056 4.992-22.656 15.68-28.416 8.554667-4.992 20.672-7.296 36.693333-7.296 18.538667 0 32.789333 3.456 42.048 11.136 9.258667 7.296 16.021333 19.584 19.584 36.48h41.344c-2.496-29.952-12.821333-52.224-30.656-66.432-16.725333-13.44-40.256-19.968-70.186666-19.968z m118.976 5.376L398.848 746.666667h50.24l90.496-274.176h-45.226667l-69.845333 223.488h-1.066667l-69.845333-223.488h-45.226667z m368.405333-5.376c-37.76 0-67.690667 13.824-89.792 42.24-21.013333 26.496-31.36 60.288-31.36 101.376 0 40.704 10.346667 74.112 31.36 99.84 22.442667 27.648 53.802667 41.472 94.421334 41.472 22.805333 0 43.093333-3.072 61.632-9.216A143.829333 143.829333 0 0 0 789.333333 716.714667V600.746667h-109.013333v38.4h67.328v56.448c-8.533333 5.376-17.450667 9.6-27.434667 12.672a123.285333 123.285333 0 0 1-34.197333 4.608c-30.997333 0-53.802667-9.216-68.416-27.648-13.525333-17.28-20.309333-42.24-20.309333-74.496 0-33.792 7.488-59.52 22.826666-77.952 13.866667-17.664 32.768-26.112 56.64-26.112 19.221333 0 34.901333 4.224 46.656 13.056 11.413333 8.832 19.242667 21.888 22.826667 39.552h42.026667c-4.629333-30.72-16.042667-53.376-34.197334-68.736-18.88-15.744-44.544-23.424-77.312-23.424z" fill="#1A8EF7" p-id="4207"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 2H10M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4M6.66667 7V10.3333M9.33333 7V10.3333" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 548 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 2H10M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4M6.66667 7V10.3333M9.33333 7V10.3333" stroke="#D92D20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 550 B |
57
dify/web/app/components/develop/secret-key/input-copy.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
'use client'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { t } from 'i18next'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
|
||||
type IInputCopyProps = {
|
||||
value?: string
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const InputCopy = ({
|
||||
value = '',
|
||||
className,
|
||||
children,
|
||||
}: IInputCopyProps) => {
|
||||
const [isCopied, setIsCopied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (isCopied) {
|
||||
const timeout = setTimeout(() => {
|
||||
setIsCopied(false)
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [isCopied])
|
||||
|
||||
return (
|
||||
<div className={`flex items-center rounded-lg bg-components-input-bg-normal py-2 hover:bg-state-base-hover ${className}`}>
|
||||
<div className="flex h-5 grow items-center">
|
||||
{children}
|
||||
<div className='relative h-full grow text-[13px]'>
|
||||
<div className='r-0 absolute left-0 top-0 w-full cursor-pointer truncate pl-2 pr-2' onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}>
|
||||
<Tooltip
|
||||
popupContent={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
|
||||
position='bottom'
|
||||
>
|
||||
<span className='text-text-secondary'>{value}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="h-4 w-px shrink-0 bg-divider-regular" />
|
||||
<div className='mx-1'><CopyFeedback content={value} /></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputCopy
|
||||
@@ -0,0 +1,35 @@
|
||||
'use client'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiKey2Line } from '@remixicon/react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal'
|
||||
|
||||
type ISecretKeyButtonProps = {
|
||||
className?: string
|
||||
appId?: string
|
||||
textCls?: string
|
||||
}
|
||||
|
||||
const SecretKeyButton = ({ className, appId, textCls }: ISecretKeyButtonProps) => {
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
className={`px-3 ${className}`}
|
||||
onClick={() => setVisible(true)}
|
||||
size='small'
|
||||
variant='ghost'
|
||||
>
|
||||
<div className={'flex h-3.5 w-3.5 items-center justify-center'}>
|
||||
<RiKey2Line className='h-3.5 w-3.5 text-text-tertiary' />
|
||||
</div>
|
||||
<div className={`system-xs-medium px-[3px] text-text-tertiary ${textCls}`}>{t('appApi.apiKey')}</div>
|
||||
</Button>
|
||||
<SecretKeyModal isShow={isVisible} onClose={() => setVisible(false)} appId={appId} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyButton
|
||||
@@ -0,0 +1,43 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import InputCopy from './input-copy'
|
||||
import s from './style.module.css'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
|
||||
type ISecretKeyGenerateModalProps = {
|
||||
isShow: boolean
|
||||
onClose: () => void
|
||||
newKey?: CreateApiKeyResponse
|
||||
className?: string
|
||||
}
|
||||
|
||||
const SecretKeyGenerateModal = ({
|
||||
isShow = false,
|
||||
onClose,
|
||||
newKey,
|
||||
className,
|
||||
}: ISecretKeyGenerateModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`px-8 ${className}`}>
|
||||
<div className="-mr-2 -mt-6 mb-4 flex justify-end">
|
||||
<XMarkIcon className="h-6 w-6 cursor-pointer text-text-tertiary" onClick={onClose} />
|
||||
</div>
|
||||
<p className='mt-1 text-[13px] font-normal leading-5 text-text-tertiary'>{t('appApi.apiKeyModal.generateTips')}</p>
|
||||
<div className='my-4'>
|
||||
<InputCopy className='w-full' value={newKey?.token} />
|
||||
</div>
|
||||
<div className='my-4 flex justify-end'>
|
||||
<Button className={`shrink-0 ${s.w64}`} onClick={onClose}>
|
||||
<span className='text-xs font-medium text-text-secondary'>{t('appApi.actionMsg.ok')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</Modal >
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyGenerateModal
|
||||
149
dify/web/app/components/develop/secret-key/secret-key-modal.tsx
Normal file
@@ -0,0 +1,149 @@
|
||||
'use client'
|
||||
import {
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { RiDeleteBinLine } from '@remixicon/react'
|
||||
import { PlusIcon, XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import useSWR, { useSWRConfig } from 'swr'
|
||||
import SecretKeyGenerateModal from './secret-key-generate'
|
||||
import s from './style.module.css'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import CopyFeedback from '@/app/components/base/copy-feedback'
|
||||
import {
|
||||
createApikey as createAppApikey,
|
||||
delApikey as delAppApikey,
|
||||
fetchApiKeysList as fetchAppApiKeysList,
|
||||
} from '@/service/apps'
|
||||
import {
|
||||
createApikey as createDatasetApikey,
|
||||
delApikey as delDatasetApikey,
|
||||
fetchApiKeysList as fetchDatasetApiKeysList,
|
||||
} from '@/service/datasets'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import useTimestamp from '@/hooks/use-timestamp'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
||||
type ISecretKeyModalProps = {
|
||||
isShow: boolean
|
||||
appId?: string
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const SecretKeyModal = ({
|
||||
isShow = false,
|
||||
appId,
|
||||
onClose,
|
||||
}: ISecretKeyModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { formatTime } = useTimestamp()
|
||||
const { currentWorkspace, isCurrentWorkspaceManager, isCurrentWorkspaceEditor } = useAppContext()
|
||||
const [showConfirmDelete, setShowConfirmDelete] = useState(false)
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const [newKey, setNewKey] = useState<CreateApiKeyResponse | undefined>(undefined)
|
||||
const { mutate } = useSWRConfig()
|
||||
const commonParams = appId
|
||||
? { url: `/apps/${appId}/api-keys`, params: {} }
|
||||
: { url: '/datasets/api-keys', params: {} }
|
||||
const fetchApiKeysList = appId ? fetchAppApiKeysList : fetchDatasetApiKeysList
|
||||
const { data: apiKeysList } = useSWR(commonParams, fetchApiKeysList)
|
||||
|
||||
const [delKeyID, setDelKeyId] = useState('')
|
||||
|
||||
const onDel = async () => {
|
||||
setShowConfirmDelete(false)
|
||||
if (!delKeyID)
|
||||
return
|
||||
|
||||
const delApikey = appId ? delAppApikey : delDatasetApikey
|
||||
const params = appId
|
||||
? { url: `/apps/${appId}/api-keys/${delKeyID}`, params: {} }
|
||||
: { url: `/datasets/api-keys/${delKeyID}`, params: {} }
|
||||
await delApikey(params)
|
||||
mutate(commonParams)
|
||||
}
|
||||
|
||||
const onCreate = async () => {
|
||||
const params = appId
|
||||
? { url: `/apps/${appId}/api-keys`, body: {} }
|
||||
: { url: '/datasets/api-keys', body: {} }
|
||||
const createApikey = appId ? createAppApikey : createDatasetApikey
|
||||
const res = await createApikey(params)
|
||||
setVisible(true)
|
||||
setNewKey(res)
|
||||
mutate(commonParams)
|
||||
}
|
||||
|
||||
const generateToken = (token: string) => {
|
||||
return `${token.slice(0, 3)}...${token.slice(-20)}`
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`${s.customModal} flex flex-col px-8`}>
|
||||
<div className="-mr-2 -mt-6 mb-4 flex justify-end">
|
||||
<XMarkIcon className="h-6 w-6 cursor-pointer text-text-tertiary" onClick={onClose} />
|
||||
</div>
|
||||
<p className='mt-1 shrink-0 text-[13px] font-normal leading-5 text-text-tertiary'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
|
||||
{!apiKeysList && <div className='mt-4'><Loading /></div>}
|
||||
{
|
||||
!!apiKeysList?.data?.length && (
|
||||
<div className='mt-4 flex grow flex-col overflow-hidden'>
|
||||
<div className='flex h-9 shrink-0 items-center border-b border-divider-regular text-xs font-semibold text-text-tertiary'>
|
||||
<div className='w-64 shrink-0 px-3'>{t('appApi.apiKeyModal.secretKey')}</div>
|
||||
<div className='w-[200px] shrink-0 px-3'>{t('appApi.apiKeyModal.created')}</div>
|
||||
<div className='w-[200px] shrink-0 px-3'>{t('appApi.apiKeyModal.lastUsed')}</div>
|
||||
<div className='grow px-3'></div>
|
||||
</div>
|
||||
<div className='grow overflow-auto'>
|
||||
{apiKeysList.data.map(api => (
|
||||
<div className='flex h-9 items-center border-b border-divider-regular text-sm font-normal text-text-secondary' key={api.id}>
|
||||
<div className='w-64 shrink-0 truncate px-3 font-mono'>{generateToken(api.token)}</div>
|
||||
<div className='w-[200px] shrink-0 truncate px-3'>{formatTime(Number(api.created_at), t('appLog.dateTimeFormat') as string)}</div>
|
||||
<div className='w-[200px] shrink-0 truncate px-3'>{api.last_used_at ? formatTime(Number(api.last_used_at), t('appLog.dateTimeFormat') as string) : t('appApi.never')}</div>
|
||||
<div className='flex grow space-x-2 px-3'>
|
||||
<CopyFeedback content={api.token} />
|
||||
{isCurrentWorkspaceManager && (
|
||||
<ActionButton
|
||||
onClick={() => {
|
||||
setDelKeyId(api.id)
|
||||
setShowConfirmDelete(true)
|
||||
}}
|
||||
>
|
||||
<RiDeleteBinLine className='h-4 w-4' />
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='flex'>
|
||||
<Button className={`mt-4 flex shrink-0 ${s.autoWidth}`} onClick={onCreate} disabled={!currentWorkspace || !isCurrentWorkspaceEditor}>
|
||||
<PlusIcon className='mr-1 flex h-4 w-4 shrink-0' />
|
||||
<div className='text-xs font-medium text-text-secondary'>{t('appApi.apiKeyModal.createNewSecretKey')}</div>
|
||||
</Button>
|
||||
</div>
|
||||
<SecretKeyGenerateModal className='shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
|
||||
{showConfirmDelete && (
|
||||
<Confirm
|
||||
title={`${t('appApi.actionMsg.deleteConfirmTitle')}`}
|
||||
content={`${t('appApi.actionMsg.deleteConfirmTips')}`}
|
||||
isShow={showConfirmDelete}
|
||||
onConfirm={onDel}
|
||||
onCancel={() => {
|
||||
setDelKeyId('')
|
||||
setShowConfirmDelete(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Modal >
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyModal
|
||||
57
dify/web/app/components/develop/secret-key/style.module.css
Normal file
@@ -0,0 +1,57 @@
|
||||
.customModal {
|
||||
max-width: 800px !important;
|
||||
max-height: calc(100vh - 80px);
|
||||
}
|
||||
|
||||
.close {
|
||||
top: 1.5rem;
|
||||
right: 1.5rem;
|
||||
}
|
||||
|
||||
.trash {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.w64 {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.customApi {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.autoWidth {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.trashIcon {
|
||||
background-color: transparent;
|
||||
background-image: url(./assets/trash-gray.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.trashIcon:hover {
|
||||
background-color: rgba(254, 228, 226, 1);
|
||||
background-image: url(./assets/trash-red.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.copyIcon {
|
||||
background-image: url(./assets/copy.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.copyIcon:hover {
|
||||
background-image: url(./assets/copy-hover.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.copyIcon.copied {
|
||||
background-image: url(./assets/copied.svg);
|
||||
}
|
||||