diff --git a/js-packages/web-console/src/assets/fonts/feldera-material-icons.css b/js-packages/web-console/src/assets/fonts/feldera-material-icons.css index 8284f29ff7b..22b32d51e98 100644 --- a/js-packages/web-console/src/assets/fonts/feldera-material-icons.css +++ b/js-packages/web-console/src/assets/fonts/feldera-material-icons.css @@ -2,8 +2,8 @@ font-family: "feldera-material-icons"; font-display: block; src: - url("feldera-material-icons.woff2?7e3c6a8d23bb66b7a89348ec07b22a96") format("woff2"), - url("feldera-material-icons.woff?7e3c6a8d23bb66b7a89348ec07b22a96") format("woff"); + url("feldera-material-icons.woff2?06f8372fd6db29f5f189dc16b2f9c8af") format("woff2"), + url("feldera-material-icons.woff?06f8372fd6db29f5f189dc16b2f9c8af") format("woff"); } .fd { @@ -20,201 +20,201 @@ .fd-chevron-down:before { content: "\f101"; } -.fd-arrow-down:before { +.fd-square:before { content: "\f102"; } -.fd-pencil-line:before { +.fd-wine:before { content: "\f103"; } -.fd-save:before { +.fd-trash-2:before { content: "\f104"; } -.fd-more_horiz:before { +.fd-book-open:before { content: "\f105"; } -.fd-menu:before { +.fd-moon:before { content: "\f106"; } -.fd-panel-right:before { +.fd-circle-x:before { content: "\f107"; } -.fd-dot:before { +.fd-mic-off:before { content: "\f108"; } -.fd-chevron-left:before { +.fd-plus:before { content: "\f109"; } -.fd-server-off:before { +.fd-circle-play:before { content: "\f10a"; } -.fd-circle-x:before { +.fd-chevron-left:before { content: "\f10b"; } -.fd-server-cog:before { +.fd-triangle-alert:before { content: "\f10c"; } -.fd-log-out:before { +.fd-paintbrush:before { content: "\f10d"; } -.fd-copy:before { +.fd-circle-stop:before { content: "\f10e"; } -.fd-file-down:before { +.fd-chevron-right:before { content: "\f10f"; } -.fd-play:before { +.fd-mic:before { content: "\f110"; } -.fd-message-circle-question:before { +.fd-square-power:before { content: "\f111"; } -.fd-chevron-right:before { +.fd-circle-check-big:before { content: "\f112"; } -.fd-lock-open:before { +.fd-circle-dot:before { content: "\f113"; } -.fd-lightbulb:before { +.fd-panel-right:before { content: "\f114"; } -.fd-key:before { +.fd-user:before { content: "\f115"; } -.fd-circle-play:before { +.fd-circle-stop-locked:before { content: "\f116"; } -.fd-square-power:before { +.fd-sliders-horizontal:before { content: "\f117"; } -.fd-circle-stop:before { +.fd-panel-left:before { content: "\f118"; } -.fd-network:before { +.fd-pencil-line:before { content: "\f119"; } -.fd-square:before { +.fd-info:before { content: "\f11a"; } -.fd-panel-bottom:before { +.fd-database-off:before { content: "\f11b"; } -.fd-database-off:before { +.fd-sun:before { content: "\f11c"; } .fd-file-text:before { content: "\f11d"; } -.fd-book-marked:before { +.fd-panel-bottom:before { content: "\f11e"; } -.fd-settings:before { +.fd-x:before { content: "\f11f"; } .fd-layout-panel-top:before { content: "\f120"; } -.fd-circle-user:before { +.fd-settings:before { content: "\f121"; } -.fd-eraser:before { +.fd-play:before { content: "\f122"; } -.fd-circle-pause:before { +.fd-rocket:before { content: "\f123"; } -.fd-trash-2:before { +.fd-server:before { content: "\f124"; } -.fd-plus:before { +.fd-circle-plus:before { content: "\f125"; } -.fd-moon:before { +.fd-more_horiz:before { content: "\f126"; } -.fd-mic-off:before { +.fd-key:before { content: "\f127"; } -.fd-wine:before { +.fd-copy:before { content: "\f128"; } -.fd-sun:before { +.fd-arrow-down:before { content: "\f129"; } -.fd-database:before { +.fd-circle-pause:before { content: "\f12a"; } -.fd-paintbrush:before { +.fd-menu:before { content: "\f12b"; } -.fd-circle-check-big:before { +.fd-lightbulb:before { content: "\f12c"; } -.fd-layout-panel-left:before { +.fd-server-cog:before { content: "\f12d"; } -.fd-arrow-right:before { +.fd-save:before { content: "\f12e"; } -.fd-x:before { +.fd-database:before { content: "\f12f"; } -.fd-circle-slash:before { +.fd-lock-open:before { content: "\f130"; } -.fd-panel-left:before { +.fd-log-out:before { content: "\f131"; } -.fd-circle-dot:before { +.fd-layout-panel-left:before { content: "\f132"; } -.fd-pause:before { +.fd-server-off:before { content: "\f133"; } -.fd-triangle-alert:before { +.fd-circle-slash:before { content: "\f134"; } -.fd-circle-divide:before { +.fd-arrow-right:before { content: "\f135"; } -.fd-info:before { +.fd-construction:before { content: "\f136"; } -.fd-construction:before { +.fd-file-down:before { content: "\f137"; } -.fd-rocket:before { +.fd-circle-divide:before { content: "\f138"; } -.fd-heart-crack:before { +.fd-network:before { content: "\f139"; } -.fd-circle-plus:before { +.fd-pause:before { content: "\f13a"; } -.fd-server:before { +.fd-copy-plus:before { content: "\f13b"; } -.fd-circle-stop-locked:before { +.fd-book-marked:before { content: "\f13c"; } -.fd-receipt-text:before { +.fd-dot:before { content: "\f13d"; } -.fd-check:before { +.fd-circle-user:before { content: "\f13e"; } -.fd-book-open:before { +.fd-circle-alert:before { content: "\f13f"; } -.fd-user:before { +.fd-message-circle-question:before { content: "\f140"; } -.fd-sliders-horizontal:before { +.fd-receipt-text:before { content: "\f141"; } -.fd-mic:before { +.fd-eraser:before { content: "\f142"; } -.fd-circle-alert:before { +.fd-check:before { content: "\f143"; } diff --git a/js-packages/web-console/src/assets/fonts/feldera-material-icons.svg b/js-packages/web-console/src/assets/fonts/feldera-material-icons.svg index 2e25e399e40..88d9035756f 100644 --- a/js-packages/web-console/src/assets/fonts/feldera-material-icons.svg +++ b/js-packages/web-console/src/assets/fonts/feldera-material-icons.svg @@ -13,402 +13,402 @@ - - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + - - - - - - - + + - - + + - - - - - - - + horiz-adv-x="128" d="M60.16 122.4373333333333C52.3573333333333 121.952 45.3546666666667 120.064 38.08 116.48C31.904 113.44 27.4186666666667 110.2293333333333 22.5973333333333 105.4026666666667C17.7706666666667 100.5813333333333 14.56 96.096 11.52 89.92C7.824 82.4213333333333 6.0533333333333 75.7013333333333 5.5466666666667 67.2693333333333C4.9333333333333 57.1413333333333 6.928 47.392 11.52 38.08C14.56 31.904 17.7706666666667 27.4186666666667 22.5973333333333 22.5973333333333C27.4133333333333 17.7813333333333 31.888 14.576 38.08 11.5093333333333C46.4693333333333 7.36 54.464 5.5093333333333 64 5.5093333333333C73.536 5.5093333333333 81.5306666666667 7.36 89.92 11.5093333333333C96.112 14.576 100.5866666666667 17.7813333333333 105.4026666666667 22.5973333333333C110.2186666666667 27.4133333333333 113.424 31.888 116.4906666666667 38.08C120.64 46.4693333333333 122.4906666666667 54.464 122.4906666666667 64C122.4906666666667 73.536 120.64 81.5306666666667 116.4906666666667 89.92C113.424 96.112 110.2186666666667 100.5866666666667 105.4026666666667 105.4026666666667C100.5813333333333 110.2293333333333 96.096 113.44 89.92 116.48C82.448 120.1653333333333 75.728 121.9413333333333 67.3173333333333 122.4586666666667C63.8026666666667 122.672 63.9786666666667 122.6773333333333 60.16 122.4373333333333M69.2906666666667 111.7706666666667C87.872 109.7226666666667 103.808 96.7626666666667 109.6586666666667 78.9333333333333C113.3706666666667 67.6213333333333 112.6986666666667 55.1893333333333 107.776 44.2133333333333C103.856 35.4666666666667 96.848 27.648 88.4266666666667 22.6346666666667C76.7253333333333 15.664 62.0906666666667 14.064 49.0666666666667 18.3413333333333C34.5706666666667 23.0986666666667 23.0986666666667 34.576 18.336 49.072C16.7306666666667 53.9626666666667 16 58.6293333333333 16 64C16 67.8133333333333 16.2613333333333 70.4426666666667 16.992 73.9146666666667C19.7386666666667 86.9866666666667 27.9893333333333 98.464 39.616 105.392C45.0613333333333 108.6346666666667 52.2133333333333 111.056 58.4533333333333 111.7653333333333C60.8 112.032 66.9013333333333 112.032 69.2906666666667 111.7706666666667M46.9333333333333 85.136C45.3653333333333 84.816 44.064 83.792 43.232 82.2453333333333C42.7733333333333 81.3866666666667 42.7733333333333 81.3813333333334 42.7733333333333 64C42.7733333333333 46.6186666666667 42.7733333333333 46.6133333333333 43.232 45.7546666666667C43.8133333333333 44.6666666666667 44.6666666666667 43.8133333333333 45.7546666666667 43.232C46.6133333333333 42.7733333333333 46.6186666666667 42.7733333333333 64 42.7733333333333C81.3813333333333 42.7733333333333 81.3866666666667 42.7733333333333 82.2453333333333 43.232C83.3333333333333 43.8133333333333 84.1866666666667 44.6666666666667 84.768 45.7546666666667C85.2266666666667 46.6133333333333 85.2266666666667 46.6186666666667 85.2266666666667 64C85.2266666666667 81.3813333333334 85.2266666666667 81.3866666666667 84.768 82.2453333333333C84.1866666666667 83.3333333333333 83.3333333333333 84.1866666666667 82.2453333333333 84.768C81.3866666666667 85.2266666666667 81.3386666666667 85.2266666666667 64.5333333333333 85.2586666666667C55.264 85.2746666666667 47.344 85.2213333333333 46.9333333333333 85.136M74.6666666666667 64L74.6666666666667 53.3333333333333L64 53.3333333333333L53.3333333333333 53.3333333333333L53.3333333333333 64L53.3333333333333 74.6666666666667L64 74.6666666666667L74.6666666666667 74.6666666666667L74.6666666666667 64" /> + - - - - - - - - + + - + + + + + + + + + + + + - - + + - - + + - - - + horiz-adv-x="128" d="M60.16 122.4373333333333C48.3626666666667 121.7066666666667 36.6826666666667 117.1786666666667 27.312 109.712C24.704 107.632 20.368 103.296 18.288 100.688C13.088 94.16 9.0293333333333 85.904 7.0666666666667 77.8346666666667C4.9173333333333 69.0346666666667 4.9173333333333 58.9653333333333 7.0666666666667 50.1653333333333C9.0293333333333 42.096 13.088 33.84 18.288 27.312C20.368 24.704 24.704 20.368 27.312 18.288C32.192 14.4 39.0506666666667 10.608 44.7253333333333 8.6666666666667C59.7493333333333 3.52 75.8186666666667 4.5333333333333 89.92 11.5093333333333C96.112 14.576 100.5866666666667 17.7813333333333 105.4026666666667 22.5973333333333C110.2186666666667 27.4133333333333 113.424 31.888 116.4906666666667 38.08C120.64 46.4693333333333 122.4906666666667 54.464 122.4906666666667 64C122.4906666666667 73.536 120.64 81.5306666666667 116.4906666666667 89.92C113.424 96.112 110.2186666666667 100.5866666666667 105.4026666666667 105.4026666666667C100.5813333333333 110.2293333333333 96.096 113.44 89.92 116.48C82.448 120.1653333333333 75.728 121.9413333333333 67.3173333333333 122.4586666666667C63.8026666666667 122.672 63.9786666666667 122.6773333333333 60.16 122.4373333333333M69.2906666666667 111.7706666666667C87.872 109.7226666666667 103.808 96.7626666666667 109.6586666666667 78.9333333333333C113.3706666666667 67.6213333333333 112.6986666666667 55.1893333333333 107.776 44.2133333333333C103.856 35.4666666666667 96.848 27.648 88.4266666666667 22.6346666666667C76.7253333333333 15.664 62.0906666666667 14.064 49.0666666666667 18.3413333333333C34.5706666666667 23.0986666666667 23.0986666666667 34.576 18.336 49.072C16.7306666666667 53.9626666666667 16 58.6293333333333 16 64C16 67.8133333333333 16.2613333333333 70.4426666666667 16.992 73.9146666666667C19.7386666666667 86.9866666666667 27.9893333333333 98.464 39.616 105.392C45.0613333333333 108.6346666666667 52.2133333333333 111.056 58.4533333333333 111.7653333333333C60.8 112.032 66.9013333333333 112.032 69.2906666666667 111.7706666666667M62.9333333333333 90.4693333333333C58.9013333333333 89.6426666666667 57.3813333333333 84.544 60.2933333333333 81.6266666666667C61.7706666666667 80.1546666666667 64.4 79.6746666666667 66.24 80.5493333333333C67.9946666666667 81.3813333333334 69.3333333333333 83.4506666666667 69.3333333333333 85.3333333333333C69.3333333333333 87.1786666666667 67.9893333333333 89.3013333333333 66.336 90.064C65.4133333333333 90.4906666666667 63.9093333333333 90.6666666666667 62.9333333333333 90.4693333333333M62.9333333333333 69.136C61.3706666666667 68.816 60.064 67.792 59.232 66.2453333333333C58.7786666666667 65.3973333333333 58.7733333333333 65.2586666666667 58.7733333333333 53.3333333333333C58.7733333333333 41.408 58.7786666666667 41.2693333333333 59.232 40.4213333333333C60.2773333333333 38.4693333333333 61.8773333333333 37.4826666666667 64 37.4826666666667C66.1226666666667 37.4826666666667 67.7226666666667 38.4693333333333 68.768 40.4213333333333C69.2213333333333 41.2693333333333 69.2266666666667 41.408 69.2266666666667 53.3333333333333C69.2266666666667 65.2586666666667 69.2213333333333 65.3973333333333 68.768 66.2453333333333C67.584 68.4533333333334 65.248 69.6106666666667 62.9333333333333 69.136" /> + + + - - - + + - + horiz-adv-x="128" d="M29.9573333333333 100.816C28.944 100.3786666666667 27.7066666666667 99.1893333333333 27.28 98.24C26.8053333333333 97.2 26.7573333333333 95.008 27.184 93.9786666666667C27.5786666666667 93.04 30.0053333333333 90.5173333333333 44.4693333333333 76L56.4266666666667 64L44.4693333333333 52C29.8613333333333 37.344 27.5786666666667 34.96 27.1626666666667 33.968C26.7413333333333 32.9653333333334 26.752 31.0453333333333 27.184 30.032C27.6053333333333 29.04 28.672 27.808 29.472 27.3973333333333C30.48 26.8746666666667 32 26.6773333333333 33.136 26.9173333333333C33.8666666666667 27.072 34.5386666666667 27.4506666666667 35.4826666666667 28.2293333333333C36.208 28.832 42.9226666666667 35.4133333333333 50.4 42.8533333333333L64 56.384L77.6 42.8533333333333C85.0826666666667 35.4133333333333 91.792 28.832 92.5173333333333 28.2293333333333C94.0533333333333 26.96 95.28 26.5813333333333 96.9013333333333 26.8906666666667C98.2453333333333 27.1413333333333 98.9973333333333 27.552 99.808 28.4746666666667C100.7413333333333 29.536 101.152 30.6186666666667 101.1573333333333 32.0106666666667C101.168 34.3893333333333 101.856 33.6106666666667 83.424 52.1066666666667L71.5733333333333 64L83.424 75.8933333333334C98.08 90.6026666666667 100.4266666666667 93.0453333333333 100.8373333333333 94.0266666666667C101.3173333333333 95.1786666666667 101.2533333333333 96.9973333333333 100.688 98.2026666666667C99.8026666666667 100.0906666666667 98.08 101.12 95.808 101.12C93.5733333333333 101.12 94.2933333333333 101.76 76 83.5306666666667L64 71.5733333333333L52.32 83.216C36.6453333333333 98.832 34.7786666666667 100.6133333333334 33.7706666666667 100.8906666666667C32.6613333333333 101.2 30.752 101.1626666666667 29.9573333333333 100.816" /> + - - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - + + - - + + + + + + + + + + + + - - - - + + + + - - - - + + - - - - - - - - - - - - + horiz-adv-x="128" d="M61.9573333333333 106.1493333333333C60.944 105.712 59.7066666666667 104.5226666666667 59.28 103.5733333333333C58.8053333333333 102.528 58.7573333333333 100.336 59.184 99.312C59.5733333333333 98.3786666666667 62.064 95.792 76.544 81.2586666666667L88.3626666666667 69.3973333333333L56.7786666666667 69.2853333333333L25.1946666666667 69.1733333333334L24.2773333333333 68.6346666666667C22.3573333333333 67.4986666666667 21.5466666666667 66.128 21.5466666666667 64C21.5466666666667 61.7973333333333 22.5386666666667 60.224 24.5813333333333 59.1786666666667L25.584 58.6666666666667L57.008 58.6666666666667L88.4266666666667 58.6666666666667L76.4693333333333 46.6666666666667C61.8613333333333 32.0106666666667 59.5786666666667 29.6266666666667 59.1626666666667 28.6346666666667C58.7413333333333 27.632 58.752 25.712 59.184 24.6986666666667C59.6746666666667 23.5413333333333 60.7786666666667 22.384 61.84 21.9146666666667C62.976 21.4133333333333 64.88 21.36 65.9306666666667 21.808C67.728 22.5706666666667 105.4186666666667 60.224 106.16 62.0053333333333C106.5386666666667 62.9066666666667 106.5386666666667 65.0933333333333 106.1653333333333 65.9893333333333C105.7013333333333 67.0986666666667 87.136 86.0053333333333 73.3386666666667 99.424C67.9786666666667 104.6346666666667 66.4 106.0533333333333 65.7653333333333 106.2293333333333C64.6613333333333 106.5333333333333 62.7466666666667 106.496 61.9573333333333 106.1493333333333" /> + - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + - - - - - - - - - - diff --git a/js-packages/web-console/src/assets/fonts/feldera-material-icons.ttf b/js-packages/web-console/src/assets/fonts/feldera-material-icons.ttf index 2b05d6f7f9c..8b1d7fa9769 100644 Binary files a/js-packages/web-console/src/assets/fonts/feldera-material-icons.ttf and b/js-packages/web-console/src/assets/fonts/feldera-material-icons.ttf differ diff --git a/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff b/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff index ff6b30eee3a..3e552c9e818 100644 Binary files a/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff and b/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff differ diff --git a/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff2 b/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff2 index 929b374f02b..199c0aa8dd6 100644 Binary files a/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff2 and b/js-packages/web-console/src/assets/fonts/feldera-material-icons.woff2 differ diff --git a/js-packages/web-console/src/assets/fonts/generic-icons.css b/js-packages/web-console/src/assets/fonts/generic-icons.css index c2124d9fa4d..34ae10699cb 100644 --- a/js-packages/web-console/src/assets/fonts/generic-icons.css +++ b/js-packages/web-console/src/assets/fonts/generic-icons.css @@ -2,8 +2,8 @@ font-family: "generic-icons"; font-display: block; src: - url("generic-icons.woff2?204a1f3771f46f1024a2c650b43800c5") format("woff2"), - url("generic-icons.woff?204a1f3771f46f1024a2c650b43800c5") format("woff"); + url("generic-icons.woff2?93adf303867ea39c2b4e5835c473116a") format("woff2"), + url("generic-icons.woff?93adf303867ea39c2b4e5835c473116a") format("woff"); } .gc { @@ -17,18 +17,18 @@ vertical-align: top; } -.gc-boiling-flask:before { +.gc-layout-panel-right:before { content: "\f101"; } -.gc-http-get:before { +.gc-circle-solid:before { content: "\f102"; } -.gc-circle-solid:before { +.gc-loader-alt:before { content: "\f103"; } -.gc-loader-alt:before { +.gc-boiling-flask:before { content: "\f104"; } -.gc-layout-panel-right:before { +.gc-http-get:before { content: "\f105"; } diff --git a/js-packages/web-console/src/assets/fonts/generic-icons.svg b/js-packages/web-console/src/assets/fonts/generic-icons.svg index e89c317f776..b3269604155 100644 --- a/js-packages/web-console/src/assets/fonts/generic-icons.svg +++ b/js-packages/web-console/src/assets/fonts/generic-icons.svg @@ -7,36 +7,36 @@ units-per-em="128" ascent="128" descent="0" /> - - - - + horiz-adv-x="128" d="M91.818 92H36.1818C32.7818 92 30 89.2 30 85.7776V42.2224C30 38.8 32.7818 36 36.1818 36H91.818C95.218 36 98 38.8 98 42.2224V85.7776C98 89.2 95.218 92 91.818 92zM91.818 42.2224H36.1818V85.7776H91.818V42.2224zM74 82H88V45.3332H74V82z" /> + - + + - + horiz-adv-x="128" d="" /> + diff --git a/js-packages/web-console/src/assets/fonts/generic-icons.ttf b/js-packages/web-console/src/assets/fonts/generic-icons.ttf index 9f8f3f55f57..e9db6e59e2d 100644 Binary files a/js-packages/web-console/src/assets/fonts/generic-icons.ttf and b/js-packages/web-console/src/assets/fonts/generic-icons.ttf differ diff --git a/js-packages/web-console/src/assets/fonts/generic-icons.woff b/js-packages/web-console/src/assets/fonts/generic-icons.woff index 5de327d83e7..102d845addb 100644 Binary files a/js-packages/web-console/src/assets/fonts/generic-icons.woff and b/js-packages/web-console/src/assets/fonts/generic-icons.woff differ diff --git a/js-packages/web-console/src/assets/fonts/generic-icons.woff2 b/js-packages/web-console/src/assets/fonts/generic-icons.woff2 index 310e19f57ce..0a75081b4e8 100644 Binary files a/js-packages/web-console/src/assets/fonts/generic-icons.woff2 and b/js-packages/web-console/src/assets/fonts/generic-icons.woff2 differ diff --git a/js-packages/web-console/src/assets/icons/feldera-material-icons/copy-plus.svg b/js-packages/web-console/src/assets/icons/feldera-material-icons/copy-plus.svg new file mode 100755 index 00000000000..b22ed9668b7 --- /dev/null +++ b/js-packages/web-console/src/assets/icons/feldera-material-icons/copy-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/js-packages/web-console/src/lib/components/dialogs/GenericDialog.svelte.spec.ts b/js-packages/web-console/src/lib/components/dialogs/GenericDialog.svelte.spec.ts index 34d2e8381bf..5d343fde28c 100644 --- a/js-packages/web-console/src/lib/components/dialogs/GenericDialog.svelte.spec.ts +++ b/js-packages/web-console/src/lib/components/dialogs/GenericDialog.svelte.spec.ts @@ -18,6 +18,10 @@ async function renderDialog( return render(GenericDialog, { content, ...opts }) } +const clickButton = (locator: ReturnType) => { + ;(locator.element() as HTMLButtonElement).click() +} + describe('GenericDialog.svelte', () => { describe('A. Basic rendering', () => { it('renders title', async () => { @@ -79,7 +83,7 @@ describe('GenericDialog.svelte', () => { onSuccess: { name: 'Confirm', callback: onSuccess, 'data-testid': 'btn-dialog-success' } }) ) - await page.getByTestId('btn-dialog-success').click() + clickButton(page.getByTestId('btn-dialog-success')) expect(onSuccess).toHaveBeenCalledOnce() }) @@ -149,7 +153,7 @@ describe('GenericDialog.svelte', () => { onCancel: { name: 'Back', callback: onCancel } }) ) - await page.getByTestId('btn-dialog-cancel').click() + clickButton(page.getByTestId('btn-dialog-cancel')) expect(onCancel).toHaveBeenCalledOnce() }) @@ -160,7 +164,7 @@ describe('GenericDialog.svelte', () => { onCancel: { callback: onCancel } }) ) - await page.getByLabelText('Close dialog').click() + ;(page.getByLabelText('Close dialog').element() as HTMLButtonElement).click() expect(onCancel).toHaveBeenCalledOnce() }) }) diff --git a/js-packages/web-console/src/lib/components/pipelines/List.svelte.spec.ts b/js-packages/web-console/src/lib/components/pipelines/List.svelte.spec.ts index d80f33b86ef..1ad1a1d52df 100644 --- a/js-packages/web-console/src/lib/components/pipelines/List.svelte.spec.ts +++ b/js-packages/web-console/src/lib/components/pipelines/List.svelte.spec.ts @@ -1,3 +1,4 @@ +import { tick } from 'svelte' import { describe, expect, it } from 'vitest' import { page } from 'vitest/browser' import { render } from 'vitest-browser-svelte' @@ -19,9 +20,18 @@ const visibleNames = () => .elements() .map((el) => el.textContent?.trim()) +const setSearch = async (value: string) => { + const search = page.getByPlaceholder('Search pipelines...') + await expect.element(search).toBeInTheDocument() + const input = search.element() as HTMLInputElement + input.value = value + input.dispatchEvent(new Event('input', { bubbles: true })) + await tick() +} + describe('pipeline list search', () => { it('lists every pipeline before any search term is entered', async () => { - render(List, { pipelineName: '', pipelines }) + await render(List, { pipelineName: '', pipelines }) await expect.element(page.getByText('orders')).toBeInTheDocument() await expect.element(page.getByText('payments')).toBeInTheDocument() @@ -30,9 +40,9 @@ describe('pipeline list search', () => { }) it('filters to pipelines whose name contains the search term', async () => { - render(List, { pipelineName: '', pipelines }) + await render(List, { pipelineName: '', pipelines }) - await page.getByPlaceholder('Search pipelines...').fill('pay') + await setSearch('pay') await expect.element(page.getByText('payments')).toBeInTheDocument() await expect.element(page.getByText('orders')).not.toBeInTheDocument() @@ -41,37 +51,36 @@ describe('pipeline list search', () => { }) it('matches case-insensitively', async () => { - render(List, { pipelineName: '', pipelines }) + await render(List, { pipelineName: '', pipelines }) - await page.getByPlaceholder('Search pipelines...').fill('PAY') + await setSearch('PAY') expect(visibleNames()).toEqual(['payments']) }) it('matches a substring anywhere in the name, not only a prefix', async () => { - render(List, { pipelineName: '', pipelines }) + await render(List, { pipelineName: '', pipelines }) - await page.getByPlaceholder('Search pipelines...').fill('detect') + await setSearch('detect') expect(visibleNames()).toEqual(['fraud-detection']) }) it('shows no pipelines when the term matches nothing', async () => { - render(List, { pipelineName: '', pipelines }) + await render(List, { pipelineName: '', pipelines }) - await page.getByPlaceholder('Search pipelines...').fill('no-such-pipeline') + await setSearch('no-such-pipeline') expect(visibleNames()).toHaveLength(0) }) it('restores the full list when the search term is cleared', async () => { - render(List, { pipelineName: '', pipelines }) - const search = page.getByPlaceholder('Search pipelines...') + await render(List, { pipelineName: '', pipelines }) - await search.fill('pay') + await setSearch('pay') expect(visibleNames()).toEqual(['payments']) - await search.fill('') + await setSearch('') expect(visibleNames()).toHaveLength(3) }) }) diff --git a/js-packages/web-console/src/lib/components/pipelines/editor/performance/CheckpointDialog.svelte.spec.ts b/js-packages/web-console/src/lib/components/pipelines/editor/performance/CheckpointDialog.svelte.spec.ts index e02008598ad..65ffbc6dc8c 100644 --- a/js-packages/web-console/src/lib/components/pipelines/editor/performance/CheckpointDialog.svelte.spec.ts +++ b/js-packages/web-console/src/lib/components/pipelines/editor/performance/CheckpointDialog.svelte.spec.ts @@ -3,6 +3,10 @@ import { page } from 'vitest/browser' import { render } from 'vitest-browser-svelte' import CheckpointDialog from './CheckpointDialog.svelte' +const clickButton = (locator: ReturnType) => { + ;(locator.element() as HTMLButtonElement).click() +} + describe('CheckpointDialog.svelte', () => { describe('A. Content', () => { it('renders the title', async () => { @@ -31,14 +35,14 @@ describe('CheckpointDialog.svelte', () => { it('calls onConfirm when Checkpoint is clicked', async () => { const onConfirm = vi.fn() await render(CheckpointDialog, { onConfirm }) - await page.getByTestId('btn-confirm-checkpoint').click() + clickButton(page.getByTestId('btn-confirm-checkpoint')) expect(onConfirm).toHaveBeenCalledOnce() }) it('does not call onConfirm when Cancel is clicked', async () => { const onConfirm = vi.fn() await render(CheckpointDialog, { onConfirm }) - await page.getByTestId('btn-dialog-cancel').click() + clickButton(page.getByTestId('btn-dialog-cancel')) expect(onConfirm).not.toHaveBeenCalled() }) }) diff --git a/js-packages/web-console/src/lib/components/pipelines/list/Actions.svelte b/js-packages/web-console/src/lib/components/pipelines/list/Actions.svelte index 14c95abdd03..448a2251f97 100644 --- a/js-packages/web-console/src/lib/components/pipelines/list/Actions.svelte +++ b/js-packages/web-console/src/lib/components/pipelines/list/Actions.svelte @@ -49,9 +49,14 @@ groups related actions into multi-action dropdowns when multiple options are ava import DeleteDialog, { deleteDialogProps } from '$lib/components/dialogs/DeleteDialog.svelte' import JSONDialog from '$lib/components/dialogs/JSONDialog.svelte' import PipelineConfigurationsPopup from '$lib/components/layout/pipelines/PipelineConfigurationsPopup.svelte' + import { duplicatePipeline, duplicatePipelineTooltip } from '$lib/compositions/duplicatePipeline' import { useGlobalDialog } from '$lib/compositions/layout/useGlobalDialog.svelte' import { useIsMobile } from '$lib/compositions/layout/useIsMobile.svelte' import { usePipelineActionCallbacks } from '$lib/compositions/pipelines/usePipelineActionCallbacks.svelte' + import { + usePipelineList, + useUpdatePipelineList + } from '$lib/compositions/pipelines/usePipelineList.svelte' import { getPipelineAction } from '$lib/compositions/usePipelineAction.svelte' import { usePipelineManager } from '$lib/compositions/usePipelineManager.svelte' import { usePremiumFeatures } from '$lib/compositions/usePremiumFeatures.svelte' @@ -84,11 +89,26 @@ groups related actions into multi-action dropdowns when multiple options are ava const globalDialog = useGlobalDialog() const api = usePipelineManager() + const pipelineList = usePipelineList() + const { discardPendingListRefresh, updatePipeline, updatePipelines } = useUpdatePipelineList() const deletePipeline = async (pipelineName: string) => { await api.deletePipeline(pipelineName) onDeletePipeline?.(pipelineName) goto(resolve('/')) } + const duplicateCurrentPipeline = async () => { + const pipelines = pipelineList.pipelines + if (!pipelines || unsavedChanges) { + return + } + + const newPipeline = await duplicatePipeline(api, pipeline.current, pipelines, { + discardPendingListRefresh, + updatePipeline, + updatePipelines + }) + await goto(resolve(`/pipelines/${encodeURIComponent(newPipeline.name)}/`)) + } const { toastError } = useToast() const actions = { @@ -105,7 +125,8 @@ groups related actions into multi-action dropdowns when multiple options are ava _stop, _multiStop, _multiStart, - _delete, + _duplicate, + _more, _spacer_short, _spacer_long, _spinner, @@ -135,7 +156,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Preparing', 'Provisioning', 'Initializing', () => [ '_kill', @@ -143,7 +164,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Pausing', 'Resuming', () => [ ...stopButtons, @@ -151,7 +172,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Unavailable', () => [ ...stopButtons, @@ -159,7 +180,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Running', () => [ ...stopButtons, @@ -167,7 +188,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Paused', () => [ ...stopButtons, @@ -175,7 +196,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Suspending', () => [ '_kill', @@ -183,7 +204,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Suspended', () => [ '_spinner', @@ -191,7 +212,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Standby', () => [ '_kill', @@ -199,7 +220,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Bootstrapping', () => [ '_kill', @@ -207,7 +228,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Replaying', () => [ '_kill', @@ -215,14 +236,14 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('AwaitingApproval', () => [ '_kill', '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with('Stopping', () => [ '_kill', @@ -230,7 +251,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .with( { Queued: P.any }, @@ -243,7 +264,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ] ) .with('SqlError', 'RustError', 'SystemError', () => [ @@ -251,7 +272,7 @@ groups related actions into multi-action dropdowns when multiple options are ava '_saveFile', '_configurations', '_storage_indicator', - '_delete' + '_more' ]) .exhaustive() } @@ -288,7 +309,7 @@ groups related actions into multi-action dropdowns when multiple options are ava const active = $derived.by(() => { const rawActions = getRawActions(pipeline.current.status) // Group actions into dropdowns - return processActionsForDropdowns(rawActions) + return [...processActionsForDropdowns(rawActions), '_duplicate' as const] }) function processActionsForDropdowns( @@ -637,18 +658,52 @@ groups related actions into multi-action dropdowns when multiple options are ava {/snippet} --> -{#snippet _delete()} -
- -
- {#if editConfigDisabled} - Stop the pipeline to delete it - {/if} +{#snippet _more()} + + {#snippet trigger(toggle)} + + {/snippet} + {#snippet content(close)} +
+ +
+ {/snippet} +
+{/snippet} +{#snippet _duplicate()} + + + {#if unsavedChanges} + Save the program before duplicating. + {:else} + {duplicatePipelineTooltip} + {/if} + {/snippet} {#snippet start({ text, diff --git a/js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte b/js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte index 43f410c7c2d..cac7709db28 100644 --- a/js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte +++ b/js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte @@ -2,6 +2,7 @@ import { join } from 'array-join' import { match, P } from 'ts-pattern' import DeleteDialog, { deleteDialogProps } from '$lib/components/dialogs/DeleteDialog.svelte' + import { duplicatePipeline, duplicatePipelineTooltip } from '$lib/compositions/duplicatePipeline' import { useGlobalDialog } from '$lib/compositions/layout/useGlobalDialog.svelte' import { useUpdatePipelineList } from '$lib/compositions/pipelines/usePipelineList.svelte' import { getPipelineAction } from '$lib/compositions/usePipelineAction.svelte' @@ -15,9 +16,10 @@ pipelines, selectedPipelines = $bindable() }: { pipelines: PipelineThumb[]; selectedPipelines: string[] } = $props() - const { updatePipeline } = useUpdatePipelineList() + const { discardPendingListRefresh, updatePipeline, updatePipelines } = useUpdatePipelineList() const sortedSelectedPipelines = $derived([...selectedPipelines].sort()) const availableActions = [ + 'duplicate' as const, 'start' as const, 'resume' as const, 'pause' as const, @@ -26,12 +28,14 @@ 'delete' as const, 'clear' as const ] + type AvailableAction = (typeof availableActions)[number] + type StatusAction = Exclude const isPremium = usePremiumFeatures() const stop = isPremium.value ? ['stop' as const] : [] const statusActions = ({ status, storageStatus }: (typeof selected)[number]) => { const storageAction = storageStatus === 'InUse' ? ['clear' as const] : [] return match(status) - .returnType<(typeof availableActions)[number][]>() + .returnType() .with( { Queued: P.any }, { CompilingSql: P.any }, @@ -69,7 +73,7 @@ (_, p) => p ) ) - const eligibleFor = (action: (typeof availableActions)[number]) => + const eligibleFor = (action: StatusAction) => selected .filter((pipeline) => statusActions(pipeline).includes(action)) .map((p) => p.name) @@ -78,11 +82,15 @@ if (selected.length === 0) { return [] } - const supportedByAny = new Set(selected.flatMap(statusActions)) + const supportedByAny = new Set(selected.flatMap(statusActions)) + if (selected.length === 1) { + supportedByAny.add('duplicate') + } return availableActions .filter((action) => supportedByAny.has(action)) .map((action) => match(action) + .with('duplicate', () => btnDuplicate) .with('start', () => btnStart) .with('resume', () => btnResume) .with('pause', () => btnPause) @@ -96,7 +104,7 @@ const globalDialog = useGlobalDialog() const api = usePipelineManager() - const postPipelinesAction = (action: Exclude<(typeof availableActions)[number], 'delete'>) => { + const postPipelinesAction = (action: Exclude) => { selected .filter((pipeline) => statusActions(pipeline).includes(action)) .forEach((pipeline) => { @@ -128,6 +136,20 @@ }) selectedPipelines = [] } + + const duplicateSelectedPipeline = async () => { + const pipeline = selected[0] + if (!pipeline) { + return + } + + await duplicatePipeline(api, pipeline, pipelines, { + discardPendingListRefresh, + updatePipeline, + updatePipelines + }) + selectedPipelines = [] + } {#snippet btnStart()} @@ -166,6 +188,16 @@ Delete {/snippet} +{#snippet btnDuplicate()} + +{/snippet} {#snippet btnClear()}