diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 0317cc74fb..7c1eb01707 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,11 +9,12 @@ "version": "2.0.0", "license": "Apache 2.0", "dependencies": { - "@cloudscape-design/chat-components": "^1.0.19", - "@cloudscape-design/collection-hooks": "^1.0.56", - "@cloudscape-design/components": "^3.0.856", - "@cloudscape-design/design-tokens": "^3.0.51", - "@cloudscape-design/global-styles": "^1.0.33", + "@cloudscape-design/chat-components": "^1.0.62", + "@cloudscape-design/collection-hooks": "^1.0.74", + "@cloudscape-design/component-toolkit": "^1.0.0-beta.120", + "@cloudscape-design/components": "^3.0.1091", + "@cloudscape-design/design-tokens": "^3.0.60", + "@cloudscape-design/global-styles": "^1.0.45", "@hookform/resolvers": "^2.9.10", "@reduxjs/toolkit": "^1.9.1", "ace-builds": "^1.36.3", @@ -2069,9 +2070,10 @@ } }, "node_modules/@cloudscape-design/chat-components": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/@cloudscape-design/chat-components/-/chat-components-1.0.19.tgz", - "integrity": "sha512-0fjmOQ1Pnw6YW+xVF9ULgTd4bxPZN0tMonHB1yLZ6uq7gMvdHYnvn4DfZUSHBGAgMQgza5bAnNqoDo7eoODUxw==", + "version": "1.0.62", + "resolved": "https://registry.npmjs.org/@cloudscape-design/chat-components/-/chat-components-1.0.62.tgz", + "integrity": "sha512-8Tqc5JqLmSMQe2nG0q1I7Q8m08kfuLJCFhTqgfYZDKu9g/HVP8d8Q42FPCcHesGWq1xM+S1wSioxJ5uhdzWE8A==", + "license": "Apache-2.0", "dependencies": { "@cloudscape-design/component-toolkit": "^1.0.0-beta", "@cloudscape-design/test-utils-core": "^1.0.0", @@ -2079,32 +2081,33 @@ }, "peerDependencies": { "@cloudscape-design/components": "^3", - "@cloudscape-design/design-tokens": "^3", - "react": "^18.2.0", - "react-dom": "^18.2.0" + "react": ">=18.2.0" } }, "node_modules/@cloudscape-design/collection-hooks": { - "version": "1.0.56", - "resolved": "https://registry.npmjs.org/@cloudscape-design/collection-hooks/-/collection-hooks-1.0.56.tgz", - "integrity": "sha512-1nDayJZTXMwb/MDcPzmfr12t423V+leKQI+apA0rb5j19SJhqz9AMUYF9QWBGmHsTV2FlKZI6yghbZBkVWDL6Q==", + "version": "1.0.74", + "resolved": "https://registry.npmjs.org/@cloudscape-design/collection-hooks/-/collection-hooks-1.0.74.tgz", + "integrity": "sha512-yAcD7vjFqbwqMCamUcKRXp403u8RcmC9izyPEYiWod9elt7x0GT1ypPyo9ZRyQuFrBsv2nwubBUrChcYaWooZw==", + "license": "Apache-2.0", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "react": ">=16.8.0" } }, "node_modules/@cloudscape-design/component-toolkit": { - "version": "1.0.0-beta.79", - "resolved": "https://registry.npmjs.org/@cloudscape-design/component-toolkit/-/component-toolkit-1.0.0-beta.79.tgz", - "integrity": "sha512-gNc71f/tFW83vjGM11w5YO1LiyW6M1U/vRAYMqbbq71EFIw+JeJDwYBddiy2d/jkBHkCtJt/RL2TVH5YqPOMow==", + "version": "1.0.0-beta.120", + "resolved": "https://registry.npmjs.org/@cloudscape-design/component-toolkit/-/component-toolkit-1.0.0-beta.120.tgz", + "integrity": "sha512-QQfquFjubZvDpJ+Tlt3UHI3KWGvMhwoksY6tG7E41qOrS9y+YbDJuJyiqaCbm5S2PzZ33JBL0bWsXrJesZu6tA==", + "license": "Apache-2.0", "dependencies": { "@juggle/resize-observer": "^3.3.1", "tslib": "^2.3.1" } }, "node_modules/@cloudscape-design/components": { - "version": "3.0.856", - "resolved": "https://registry.npmjs.org/@cloudscape-design/components/-/components-3.0.856.tgz", - "integrity": "sha512-e0dK7mibvvdsJOppuCCe29XJzsYcTCDqiuf8bXCafDgaomsgTahPA8TXj3aQyC3rZwEjuLbFj0Uil407mfALIw==", + "version": "3.0.1091", + "resolved": "https://registry.npmjs.org/@cloudscape-design/components/-/components-3.0.1091.tgz", + "integrity": "sha512-ESV83m/laX9OkuITjeucYRBi4WQSu9w8yniRZjRapiTH+zTlBxQv8Gcnvr9UYPo3cbYyig2HIdbAlOagDplgfA==", + "license": "Apache-2.0", "dependencies": { "@cloudscape-design/collection-hooks": "^1.0.0", "@cloudscape-design/component-toolkit": "^1.0.0-beta", @@ -2113,7 +2116,6 @@ "@dnd-kit/core": "^6.0.8", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.1", - "@juggle/resize-observer": "^3.3.1", "ace-builds": "^1.34.0", "balanced-match": "^1.0.2", "clsx": "^1.1.0", @@ -2121,25 +2123,26 @@ "date-fns": "^2.25.0", "intl-messageformat": "^10.3.1", "mnth": "^2.0.0", - "react-keyed-flatten-children": "^1.3.0", + "react-keyed-flatten-children": "^2.2.1", "react-transition-group": "^4.4.2", "tslib": "^2.4.0", "weekstart": "^1.1.0" }, "peerDependencies": { - "react": "^16.8 || ^17 || ^18", - "react-dom": "^16.8 || ^17 || ^18" + "react": ">=16.8.0" } }, "node_modules/@cloudscape-design/design-tokens": { - "version": "3.0.51", - "resolved": "https://registry.npmjs.org/@cloudscape-design/design-tokens/-/design-tokens-3.0.51.tgz", - "integrity": "sha512-s+qNFxw/FfdMCky86nz6xSIQV4UugRkNQYcT3h/EJAak3PUL37nE3tiPnV5OqOU6ZWfg4dcQMdQ+P1ohBnw9eQ==" + "version": "3.0.60", + "resolved": "https://registry.npmjs.org/@cloudscape-design/design-tokens/-/design-tokens-3.0.60.tgz", + "integrity": "sha512-ybj8FfjdhuHZflVDA//ooHJdwc+vny9MESvB95AJpVDhf6PXoaOpWAObn4hkMC770Wk/YwXtKXbx7rjJJQr6ZA==", + "license": "Apache-2.0" }, "node_modules/@cloudscape-design/global-styles": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/@cloudscape-design/global-styles/-/global-styles-1.0.33.tgz", - "integrity": "sha512-6bg18XIxkRS2ojMNGxVA8mV35rqkiHDXwOJjfHhYPzg6LjFagZWyg/hRRGuP5MExszB748m2HYYdXT0EejxiPA==" + "version": "1.0.45", + "resolved": "https://registry.npmjs.org/@cloudscape-design/global-styles/-/global-styles-1.0.45.tgz", + "integrity": "sha512-fSrbVpK9W+bg8tmUYqU9Wh2JGciUCGEByVUQDbgMY6feXtYEUKRP2MBL6kEHvoJB7lssZbHdh5/gYaiyxg+P5w==", + "license": "Apache-2.0" }, "node_modules/@cloudscape-design/test-utils-core": { "version": "1.0.44", @@ -20779,21 +20782,17 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" }, "node_modules/react-keyed-flatten-children": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-1.3.0.tgz", - "integrity": "sha512-qB7A6n+NHU0x88qTZGAJw6dsqwI941jcRPBB640c/CyWqjPQQ+YUmXOuzPziuHb7iqplM3xksWAbGYwkQT0tXA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-2.2.1.tgz", + "integrity": "sha512-6yBLVO6suN8c/OcJk1mzIrUHdeEzf5rtRVBhxEXAHO49D7SlJ70cG4xrSJrBIAG7MMeQ+H/T151mM2dRDNnFaA==", + "license": "MIT", "dependencies": { - "react-is": "^16.8.6" + "react-is": "^18.2.0" }, "peerDependencies": { "react": ">=15.0.0" } }, - "node_modules/react-keyed-flatten-children/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-redux": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index f3b7069248..a4d4d18be3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -96,11 +96,12 @@ "webpack-nano": "^1.1.1" }, "dependencies": { - "@cloudscape-design/chat-components": "^1.0.19", - "@cloudscape-design/collection-hooks": "^1.0.56", - "@cloudscape-design/components": "^3.0.856", - "@cloudscape-design/design-tokens": "^3.0.51", - "@cloudscape-design/global-styles": "^1.0.33", + "@cloudscape-design/chat-components": "^1.0.62", + "@cloudscape-design/collection-hooks": "^1.0.74", + "@cloudscape-design/component-toolkit": "^1.0.0-beta.120", + "@cloudscape-design/components": "^3.0.1091", + "@cloudscape-design/design-tokens": "^3.0.60", + "@cloudscape-design/global-styles": "^1.0.45", "@hookform/resolvers": "^2.9.10", "@reduxjs/toolkit": "^1.9.1", "ace-builds": "^1.36.3", diff --git a/frontend/src/components/index.ts b/frontend/src/components/index.ts index e24d6bd3ee..049aff7b0b 100644 --- a/frontend/src/components/index.ts +++ b/frontend/src/components/index.ts @@ -13,6 +13,7 @@ export { default as SpaceBetween } from '@cloudscape-design/components/space-bet export { default as Container } from '@cloudscape-design/components/container'; export { default as Spinner } from '@cloudscape-design/components/spinner'; export { default as Cards } from '@cloudscape-design/components/cards'; +export type { CardsProps } from '@cloudscape-design/components/cards'; export { default as Header } from '@cloudscape-design/components/header'; export { default as Link } from '@cloudscape-design/components/link'; export type { LinkProps } from '@cloudscape-design/components/link'; @@ -32,6 +33,8 @@ export { default as CheckboxCSD } from '@cloudscape-design/components/checkbox'; export { default as InputCSD } from '@cloudscape-design/components/input'; export { default as SelectCSD } from '@cloudscape-design/components/select'; export type { SelectProps as SelectCSDProps } from '@cloudscape-design/components/select'; +export { default as MultiselectCSD } from '@cloudscape-design/components/multiselect'; +export type { MultiselectProps } from '@cloudscape-design/components/multiselect'; export { default as StatusIndicator } from '@cloudscape-design/components/status-indicator'; export type { StatusIndicatorProps } from '@cloudscape-design/components/status-indicator'; export { default as Popover } from '@cloudscape-design/components/popover'; diff --git a/frontend/src/libs/filters.ts b/frontend/src/libs/filters.ts index d3f06c98df..7546f8d821 100644 --- a/frontend/src/libs/filters.ts +++ b/frontend/src/libs/filters.ts @@ -101,3 +101,23 @@ export const requestParamsToTokens = ({ tokens, }; }; + +export const requestParamsToArray = ({ + searchParams, + paramName, +}: { + searchParams: URLSearchParams; + paramName: Key; +}) => { + const paramValues: string[] = []; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + + for (const [paramKey, paramValue] of searchParams.entries()) { + if (paramKey === paramName) { + paramValues.push(paramValue); + } + } + + return paramValues; +}; diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index 7c40a16bd9..8f6f95ba31 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -364,7 +364,7 @@ "quickstart_message_text": "Check out the quickstart guide to get started with dstack", "nomatch_message_title": "No matches", "nomatch_message_text": "We can't find a match. Try to change project or clear filter", - "filter_property_placeholder": "Filter runs by properties", + "filter_property_placeholder": "Filter by properties", "project": "Project", "project_placeholder": "Filtering by project", "repo": "Repository", @@ -449,11 +449,11 @@ }, "offer": { "title": "Offers", - "filter_property_placeholder": "Filter offers by properties", + "filter_property_placeholder": "Filter by properties", "backend": "Backend", "backend_plural": "Backends", "availability": "Availability", - "groupBy": "Group by", + "groupBy": "Group by properties", "region": "Region", "count": "Count", "price": "$/GPU", @@ -461,6 +461,8 @@ "spot": "Spot policy", "empty_message_title_select_project": "Select a project", "empty_message_text_select_project": "Use the filter above to select a project", + "empty_message_title_select_groupBy": "Select a group by", + "empty_message_text_select_groupBy": "Use the field above to select a group by", "empty_message_title": "No offers", "empty_message_text": "No offers to display.", "nomatch_message_title": "No matches", @@ -509,7 +511,7 @@ "nomatch_message_text": "We can't find a match.", "nomatch_message_button_label": "Clear filter", "active_only": "Active fleets", - "filter_property_placeholder": "Filter fleets by properties", + "filter_property_placeholder": "Filter by properties", "statuses": { "active": "Active", "submitted": "Submitted", @@ -519,7 +521,7 @@ }, "instances": { "active_only": "Active instances", - "filter_property_placeholder": "Filter instances by properties", + "filter_property_placeholder": "Filter by properties", "title": "Instances", "empty_message_title": "No instances", "empty_message_text": "No instances to display.", @@ -557,7 +559,7 @@ "delete_volumes_confirm_title": "Delete volumes", "delete_volumes_confirm_message": "Are you sure you want to delete these volumes?", "active_only": "Active volumes", - "filter_property_placeholder": "Filter volumes by properties", + "filter_property_placeholder": "Filter by properties", "name": "Name", "project": "Project name", diff --git a/frontend/src/pages/Offers/List/hooks/useEmptyMessages.tsx b/frontend/src/pages/Offers/List/hooks/useEmptyMessages.tsx index f978b8bc69..1d6ba07efb 100644 --- a/frontend/src/pages/Offers/List/hooks/useEmptyMessages.tsx +++ b/frontend/src/pages/Offers/List/hooks/useEmptyMessages.tsx @@ -7,10 +7,12 @@ export const useEmptyMessages = ({ clearFilter, isDisabledClearFilter, projectNameSelected, + groupBySelected, }: { clearFilter?: () => void; isDisabledClearFilter?: boolean; projectNameSelected?: boolean; + groupBySelected?: boolean; }) => { const { t } = useTranslation(); @@ -24,6 +26,15 @@ export const useEmptyMessages = ({ ); } + if (!groupBySelected) { + return ( + + ); + } + return (