From c3c4ae1f282b0fd90b5857eaf0b03f3d474f3f9b Mon Sep 17 00:00:00 2001 From: barreiro Date: Fri, 27 Dec 2024 02:35:58 +0000 Subject: [PATCH 01/11] Upgrade to latest patterfly 5.x --- horreum-web/package-lock.json | 101 ++++++++++++++++------------------ horreum-web/package.json | 7 ++- 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/horreum-web/package-lock.json b/horreum-web/package-lock.json index 5bc7bea4c..d39756b03 100644 --- a/horreum-web/package-lock.json +++ b/horreum-web/package-lock.json @@ -9,9 +9,10 @@ "version": "0.1.0", "dependencies": { "@monaco-editor/react": "4.6.0", - "@patternfly/patternfly": "5.2.1", - "@patternfly/react-core": "5.2.3", - "@patternfly/react-table": "5.4.0", + "@patternfly/patternfly": "5.4.2", + "@patternfly/react-core": "5.4.12", + "@patternfly/react-table": "5.4.13", + "@patternfly/react-templates": "1.1.13", "@types/jsonpath": "0.2.4", "@types/luxon": "3.2.0", "@types/react": "17.0.74", @@ -964,21 +965,21 @@ } }, "node_modules/@patternfly/patternfly": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.2.1.tgz", - "integrity": "sha512-n5xFjyj1J4eIFZ7XeU6K44POKRAuDlO5yALPbn084y+jPy1j861AaQ+zIUbzCi4IzBlHrvoXVKij7p1zy7Ditg==" + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-5.4.2.tgz", + "integrity": "sha512-+BaokNR8/AmTYMESxby9UtQXPGACg449BXQd0KejAvW/uGxlgO6mY1X1205DeBEHoK3e/vXkYXjvZPpv/tcxSA==" }, "node_modules/@patternfly/react-core": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.2.3.tgz", - "integrity": "sha512-MJeOLyJFbZPV+cj4LjL15nUuhJUwFuqLFiv6f2YubRqHl/+z05oM0byhwfm/qu2VnKByY6X6lu3Hp+hMTZcbOA==", - "dependencies": { - "@patternfly/react-icons": "^5.2.1", - "@patternfly/react-styles": "^5.2.1", - "@patternfly/react-tokens": "^5.2.1", - "focus-trap": "7.5.2", + "version": "5.4.12", + "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.4.12.tgz", + "integrity": "sha512-RI1xS1JGJdE/FvpkMzawaE21oeTc/e+WbxvFXqZfLhTz60P8RzVG1nYWXDL747Onkz3SYtY79PhQ8nsLeO5sJQ==", + "dependencies": { + "@patternfly/react-icons": "^5.4.2", + "@patternfly/react-styles": "^5.4.1", + "@patternfly/react-tokens": "^5.4.1", + "focus-trap": "7.6.2", "react-dropzone": "^14.2.3", - "tslib": "^2.5.0" + "tslib": "^2.7.0" }, "peerDependencies": { "react": "^17 || ^18", @@ -986,65 +987,57 @@ } }, "node_modules/@patternfly/react-icons": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.4.0.tgz", - "integrity": "sha512-2M3qN/naultvRHeG2laJMmoIroFCGAyfwTVrnCjSkG6/KnRoXV0+dqd+Xrh7xzpzvIJB1klvifC0oX42cEkDrA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-5.4.2.tgz", + "integrity": "sha512-CMQ5oHYzW6TPVTs2jpNJmP2vGCAKR/YeTPwHGO9dLkAUej1IcIxtCCWK2Fdo2UJsnBjuZihasyw2b6ehvbUm9Q==", "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, "node_modules/@patternfly/react-styles": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.4.0.tgz", - "integrity": "sha512-4ZE0s6LkX/0KsN0FOeogrDoj18m+BPA73YKnabZGB4SDRzrBNeBh2a6bSt546ZseEjkoJ+S81kOG0G8YckPQYg==" + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-5.4.1.tgz", + "integrity": "sha512-XA8PXksD8uiA3RTwxdUwJXOCf+V6sVd+2HKapWAdRLvtSV+Sdk7NgCvalb4IAQncsddLopjPQD8gAHA298+N8w==" }, "node_modules/@patternfly/react-table": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.4.0.tgz", - "integrity": "sha512-HkXxVEPeI6nRVSUSHb5BungF41IfjB8W2VqaA3SX+6fGxQAW0e/Hb58ctUdPR2VJ/S2YZFcIcqCCWQtQEf+xKA==", - "dependencies": { - "@patternfly/react-core": "^5.4.0", - "@patternfly/react-icons": "^5.4.0", - "@patternfly/react-styles": "^5.4.0", - "@patternfly/react-tokens": "^5.4.0", + "version": "5.4.13", + "resolved": "https://registry.npmjs.org/@patternfly/react-table/-/react-table-5.4.13.tgz", + "integrity": "sha512-cYw+pgpZXKGg3dZxudteUURqmj5O0ec7aNE80NLqFTcnI0MAOnfrFzCNApXJErn+MjD0VolMcC+H48eaRkT8TA==", + "dependencies": { + "@patternfly/react-core": "^5.4.12", + "@patternfly/react-icons": "^5.4.2", + "@patternfly/react-styles": "^5.4.1", + "@patternfly/react-tokens": "^5.4.1", "lodash": "^4.17.21", - "tslib": "^2.6.3" + "tslib": "^2.7.0" }, "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, - "node_modules/@patternfly/react-table/node_modules/@patternfly/react-core": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-5.4.0.tgz", - "integrity": "sha512-Tz2Y9V4G2pnwrylc/4/FyxIRFvxiA8BEBIG6UBwXxrstnJmJaHgAIy6QJdJmERzVx3GVDz6/rM0PnMqa5R6auQ==", + "node_modules/@patternfly/react-templates": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@patternfly/react-templates/-/react-templates-1.1.13.tgz", + "integrity": "sha512-DoQ54y4eWpsYDM3CgG0Ro8pEK7u73PD2t5kgMmbn1nhuura14M5qsk1kUWX23JeJ4frcYUdMhLH/2wu6bC/Bqw==", + "license": "MIT", "dependencies": { - "@patternfly/react-icons": "^5.4.0", - "@patternfly/react-styles": "^5.4.0", - "@patternfly/react-tokens": "^5.4.0", - "focus-trap": "7.5.4", - "react-dropzone": "^14.2.3", - "tslib": "^2.6.3" + "@patternfly/react-core": "^5.4.12", + "@patternfly/react-icons": "^5.4.2", + "@patternfly/react-styles": "^5.4.1", + "@patternfly/react-tokens": "^5.4.1", + "tslib": "^2.7.0" }, "peerDependencies": { "react": "^17 || ^18", "react-dom": "^17 || ^18" } }, - "node_modules/@patternfly/react-table/node_modules/focus-trap": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", - "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", - "dependencies": { - "tabbable": "^6.2.0" - } - }, "node_modules/@patternfly/react-tokens": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.4.0.tgz", - "integrity": "sha512-KONkwCVOMyklhuuaYeYgcAsGtCBQXnsBGZeolhOdSzr2Mj0RVSW0oMrQPgZuPVzhhC/kbqgClHJJl6xuG9xheA==" + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-5.4.1.tgz", + "integrity": "sha512-eygdHE7Krta1mijAv/E8RHiKIgysD0eeNTo8EXUYC8/M4e5K6sqpr2p6rQBF8QiRMN8FnbXvZT3K2OQ28pYt9Q==" }, "node_modules/@remix-run/router": { "version": "1.17.1", @@ -2833,9 +2826,9 @@ "dev": true }, "node_modules/focus-trap": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz", - "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.2.tgz", + "integrity": "sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==", "dependencies": { "tabbable": "^6.2.0" } diff --git a/horreum-web/package.json b/horreum-web/package.json index a8c1bb72f..9cbf32a79 100644 --- a/horreum-web/package.json +++ b/horreum-web/package.json @@ -5,9 +5,10 @@ "type": "module", "dependencies": { "@monaco-editor/react": "4.6.0", - "@patternfly/patternfly": "5.2.1", - "@patternfly/react-core": "5.2.3", - "@patternfly/react-table": "5.4.0", + "@patternfly/patternfly": "5.4.2", + "@patternfly/react-core": "5.4.12", + "@patternfly/react-table": "5.4.13", + "@patternfly/react-templates": "1.1.13", "@types/jsonpath": "0.2.4", "@types/luxon": "3.2.0", "@types/react": "17.0.74", From ccece60beb7e5947542ce52acec35737ec8cb60f Mon Sep 17 00:00:00 2001 From: barreiro Date: Sat, 28 Dec 2024 05:05:19 +0000 Subject: [PATCH 02/11] Remove EnumSelect.tsx --- .../src/components/ConditionComponent.tsx | 10 ++- horreum-web/src/components/EnumSelect.tsx | 36 --------- horreum-web/src/components/Labels.tsx | 10 ++- horreum-web/src/components/LogModal.tsx | 10 ++- .../domain/actions/ActionComponentForm.tsx | 77 +++++++++++-------- horreum-web/src/domain/tests/Experiments.tsx | 13 +++- horreum-web/src/domain/tests/VariableForm.tsx | 13 ++-- 7 files changed, 78 insertions(+), 91 deletions(-) delete mode 100644 horreum-web/src/components/EnumSelect.tsx diff --git a/horreum-web/src/components/ConditionComponent.tsx b/horreum-web/src/components/ConditionComponent.tsx index 811d31dc2..2acb2fa89 100644 --- a/horreum-web/src/components/ConditionComponent.tsx +++ b/horreum-web/src/components/ConditionComponent.tsx @@ -4,8 +4,8 @@ import { Alert, FormGroup, Switch, FormHelperText } from "@patternfly/react-core" import { ConditionComponent as ConditionComponentDef } from "../api" import LogSlider from "./LogSlider" -import EnumSelect from "./EnumSelect" import NumberBound from "./NumberBound" +import {SimpleSelect} from "@patternfly/react-templates"; type ConditionComponentProps = { value: any @@ -35,10 +35,12 @@ export default function ConditionComponent({ value, onChange, properties, isTest break case "ENUM": component = ( - ( + {value: name, content: title, selected: name === value} + ))} selected={value} - onSelect={onChange} + onSelect={(_, item) => onChange(item as string)} isDisabled={!isTester} /> ) diff --git a/horreum-web/src/components/EnumSelect.tsx b/horreum-web/src/components/EnumSelect.tsx deleted file mode 100644 index 16311df52..000000000 --- a/horreum-web/src/components/EnumSelect.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { ReactNode, useState } from "react" - -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; - -type EnumSelectProps = { - options: Record - selected: string | undefined - onSelect(option: string): void - isDisabled?: boolean -} - -export default function EnumSelect({options, selected, onSelect, isDisabled}: EnumSelectProps) { - const [isOpen, setOpen] = useState(false) - return ( - - ) -} diff --git a/horreum-web/src/components/Labels.tsx b/horreum-web/src/components/Labels.tsx index 856244336..b27f6b619 100644 --- a/horreum-web/src/components/Labels.tsx +++ b/horreum-web/src/components/Labels.tsx @@ -16,10 +16,10 @@ import { ExclamationCircleIcon } from "@patternfly/react-icons" import {LabelInfo, schemaApi} from "../api" -import EnumSelect from "./EnumSelect" import NameUri from "./NameUri" import {AppContext} from "../context/appContext"; import {AppContextType} from "../context/@types/appContextTypes"; +import {SimpleSelect} from "@patternfly/react-templates"; type LabelsProps = { labels: string[] @@ -123,10 +123,12 @@ export default function Labels({ labels, onChange, isReadOnly, error, defaultMet Filter by schema: - ( + {value: name, content: title, selected: name === schemaFilter}) + )} selected={schemaFilter} - onSelect={setSchemaFilter} + onSelect={(_, item) => setSchemaFilter(item as string)} /> diff --git a/horreum-web/src/components/LogModal.tsx b/horreum-web/src/components/LogModal.tsx index 82cb40c2e..5c64f4bbd 100644 --- a/horreum-web/src/components/LogModal.tsx +++ b/horreum-web/src/components/LogModal.tsx @@ -19,10 +19,10 @@ import { import TimeRangeSelect, { TimeRange } from "./TimeRangeSelect" import ConfirmDeleteModal from "./ConfirmDeleteModal" -import EnumSelect from "./EnumSelect" import {AppContext} from "../context/appContext"; import {AppContextType} from "../context/@types/appContextTypes"; import {IRow, IRowCell, OuterScrollContainer, Table, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table"; +import {SimpleSelect} from "@patternfly/react-templates"; export type CommonLogModalProps = { title: string @@ -136,10 +136,12 @@ export default function LogModal(props: LogModalProps) { {props.deleteLogs && ( - ( + {value: name, content: title, selected: name === level.toString()} + ))} selected={level.toString()} - onSelect={value => setLevel(parseInt(value))} + onSelect={(_, value) => setLevel(value as number)} /> diff --git a/horreum-web/src/domain/actions/ActionComponentForm.tsx b/horreum-web/src/domain/actions/ActionComponentForm.tsx index 625cac551..0cb986bd1 100644 --- a/horreum-web/src/domain/actions/ActionComponentForm.tsx +++ b/horreum-web/src/domain/actions/ActionComponentForm.tsx @@ -30,9 +30,9 @@ import { GithubIssueCreateActionConfigFromJSON, SlackChannelMessageActionConfigFromJSON, } from "../../api" -import EnumSelect from "../../components/EnumSelect" import HttpActionUrlSelector from "../../components/HttpActionUrlSelector" import { CHANGE_NEW, EXPERIMENT_RESULT_NEW, TEST_NEW } from "./reducers" +import {SimpleSelect} from "@patternfly/react-templates"; function defaultConfig(type: string): ActionConfig { var config @@ -89,18 +89,17 @@ export default function ActionComponentForm(props: ActionComponentFormProps) { - ({... option, selected: option.value === props.action.type }))} selected={props.action.type} - onSelect={type => { - update({ type: type, config: defaultConfig(type) }) - }} + onSelect={(_, value) => update({type: value as string, config: defaultConfig(value as string)})} isDisabled={!props.isTester} + toggleWidth="100%" /> @@ -196,14 +195,18 @@ export default function ActionComponentForm(props: ActionComponentFormProps) { )} - ({...o, selected: o.value == (props.action.config as GithubIssueComment).formatter}) + ) } selected={(props.action.config as GithubIssueComment).formatter} - onSelect={formatter => updateConfig({ formatter })} + onSelect={(_, value) => updateConfig({formatter: value as string})} + toggleWidth="100%" /> @@ -237,12 +240,18 @@ export default function ActionComponentForm(props: ActionComponentFormProps) { /> - ({...o, selected: o.value === (props.action.config as GithubIssueCreate).formatter}) + ) } selected={(props.action.config as GithubIssueCreate).formatter} - onSelect={formatter => updateConfig({ formatter })} + onSelect={(_, value) => updateConfig({formatter: value as string})} + toggleWidth="100%" /> @@ -262,18 +271,22 @@ export default function ActionComponentForm(props: ActionComponentFormProps) { /> - ({...o, selected: o.value == (props.action.config as SlackChannelMessage).formatter}) + ) } - selected={(props.action.config as SlackChannelMessage)?.formatter} - onSelect={formatter => updateConfig({ formatter })} + selected={(props.action.config as SlackChannelMessage).formatter} + onSelect={(_, value) => updateConfig({formatter: value as string})} + toggleWidth="100%" /> diff --git a/horreum-web/src/domain/tests/Experiments.tsx b/horreum-web/src/domain/tests/Experiments.tsx index 48e1d8b29..4c61bd221 100644 --- a/horreum-web/src/domain/tests/Experiments.tsx +++ b/horreum-web/src/domain/tests/Experiments.tsx @@ -31,9 +31,9 @@ import SplitForm from "../../components/SplitForm" import { ExperimentProfile } from "../../generated/models/ExperimentProfile" import OptionalFunction from "../../components/OptionalFunction" import ConditionComponent from "../../components/ConditionComponent" -import EnumSelect from "../../components/EnumSelect" import {AppContext} from "../../context/appContext"; import {AppContextType} from "../../context/@types/appContextTypes"; +import {SimpleSelect} from "@patternfly/react-templates"; type ExperimentsProps = { @@ -368,10 +368,15 @@ export default function Experiments(props: ExperimentsProps) { {tabs} - ({ ...acc, [m.name]: m.title }), {})} + ({value: m.name, content: m.title, selected: m.name === modelToAdd}) + ) + } selected={modelToAdd} - onSelect={setModelToAdd} + onSelect={(_, value) => setModelToAdd(value as string)} + toggleWidth="100%" /> {variables.length === 0 && ( diff --git a/horreum-web/src/domain/tests/VariableForm.tsx b/horreum-web/src/domain/tests/VariableForm.tsx index e4286abc6..7cf8dffb1 100644 --- a/horreum-web/src/domain/tests/VariableForm.tsx +++ b/horreum-web/src/domain/tests/VariableForm.tsx @@ -25,10 +25,10 @@ import { import { AddCircleOIcon } from "@patternfly/react-icons" import ConditionComponent from "../../components/ConditionComponent" -import EnumSelect from "../../components/EnumSelect" import Labels from "../../components/Labels" import OptionalFunction from "../../components/OptionalFunction" import HelpButton from "../../components/HelpButton" +import {SimpleSelect} from "@patternfly/react-templates"; type VariableFormProps = { variable: Variable @@ -165,13 +165,12 @@ export default function VariableForm(props: VariableFormProps) { } > - { - acc[m.name] = m.title - return acc - }, {} as any)} + ({value: m.name, content: m.title, selected: m.name === newModel})) + } selected={newModel} - onSelect={setNewModel} + onSelect={(_, value) => setNewModel(value as string)} /> , ]} > -
+ - + ({value: g, content: g}))} + onSelect={(_,item) => setFrom(item as string)} + selected={from} + isScrollable + maxMenuHeight="45vh" + toggleWidth="100%" + popperProps={{enableFlip: false, preventOverflow: true}} + /> setTo(val)} /> From 60f4ecdb5350db07fcaab6cb0266ab4ff5817cec Mon Sep 17 00:00:00 2001 From: barreiro Date: Sat, 28 Dec 2024 05:22:44 +0000 Subject: [PATCH 06/11] Remove use of deprecated Select from Changes.tsx --- horreum-web/src/domain/alerting/Changes.tsx | 66 +++++++-------------- 1 file changed, 21 insertions(+), 45 deletions(-) diff --git a/horreum-web/src/domain/alerting/Changes.tsx b/horreum-web/src/domain/alerting/Changes.tsx index 562b6475c..c1286510e 100644 --- a/horreum-web/src/domain/alerting/Changes.tsx +++ b/horreum-web/src/domain/alerting/Changes.tsx @@ -30,11 +30,7 @@ import { EmptyStateBody, Spinner, EmptyStateHeader, EmptyStateFooter, } from '@patternfly/react-core'; -import { - Select, - SelectOption, - SelectOptionObject -} from '@patternfly/react-core/deprecated'; +import {SimpleSelect} from "@patternfly/react-templates"; import { useNavigate } from "react-router-dom" import {AppContext} from "../../context/appContext"; import {AppContextType} from "../../context/@types/appContextTypes"; @@ -45,8 +41,9 @@ type TimespanSelectProps = { onChange(span: number): void } -type Timespan = SelectOptionObject & { +type Timespan = { seconds: number + toString: () => string } function makeTimespan(title: string, seconds: number): Timespan { @@ -54,7 +51,6 @@ function makeTimespan(title: string, seconds: number): Timespan { } const TimespanSelect = (props: TimespanSelectProps) => { - const [isExpanded, setExpanded] = useState(false) const options = useMemo( () => [ makeTimespan("all", 2000000000), @@ -68,26 +64,16 @@ const TimespanSelect = (props: TimespanSelectProps) => { ], [] ) - const defaultOption = options.find((t, _) => { return t.seconds === props.value }) - const [selected, setSelected] = useState(defaultOption ?? options[4]) + const [selected, setSelected] = useState((options.find(t => t.seconds === props.value) ?? options[4]).seconds) return ( - + selected={selected} + /> ) } @@ -96,8 +82,9 @@ type LineTypeSelectProps = { onChange(type: string): void } -type LineType = SelectOptionObject & { +type LineType = { type: string + toString: () => string } function makeLineType(title: string, type: string): LineType { @@ -105,7 +92,6 @@ function makeLineType(title: string, type: string): LineType { } const LineTypeSelect = (props: LineTypeSelectProps) => { - const [isExpanded, setExpanded] = useState(false) const options = useMemo( () => [ makeLineType("steps", "stepAfter"), @@ -114,26 +100,16 @@ const LineTypeSelect = (props: LineTypeSelectProps) => { ], [] ) - const defaultOption = options.find((l, _) => { return l.type === props.value }) - const [selected, setSelected] = useState(defaultOption ?? options[1]) + const [selected, setSelected] = useState((options.find(l => l.type === props.value) ?? options[1]).type) return ( - + selected={selected} + /> ) } From 01c2966bf1db8cbf1722b2a5875f4b8a4b5da4e2 Mon Sep 17 00:00:00 2001 From: barreiro Date: Fri, 27 Dec 2024 19:33:11 +0000 Subject: [PATCH 07/11] Remove use of deprecated Select from NotificationMethodSelect.tsx, TimeRangeSelct.tsx and ViewSelect.tsx --- .../tools/horreum/svc/LogServiceImpl.java | 2 +- horreum-web/src/components/LogModal.tsx | 4 +- .../components/NotificationMethodSelect.tsx | 28 ++++-------- .../src/components/TimeRangeSelect.tsx | 43 ++++--------------- horreum-web/src/components/ViewSelect.tsx | 31 +++---------- .../src/domain/alerting/RecalculateModal.tsx | 2 +- 6 files changed, 28 insertions(+), 82 deletions(-) diff --git a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/LogServiceImpl.java b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/LogServiceImpl.java index 9af81e33a..bf1f082e9 100644 --- a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/LogServiceImpl.java +++ b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/LogServiceImpl.java @@ -169,7 +169,7 @@ public long getActionLogCount(int testId, int level) { public void deleteActionLogs(int testId, Long from, Long to) { Instant fromTs = from == null ? EPOCH_START : Instant.ofEpochMilli(from); Instant toTs = to == null ? FAR_FUTURE : Instant.ofEpochMilli(to); - long deleted = ActionLogDAO.delete("test.id = ?1 AND timestamp >= ?2 AND timestamp < ?3", testId, fromTs, toTs); + long deleted = ActionLogDAO.delete("testId = ?1 AND timestamp >= ?2 AND timestamp < ?3", testId, fromTs, toTs); log.debugf("Deleted %d logs for test %d", deleted, testId); } diff --git a/horreum-web/src/components/LogModal.tsx b/horreum-web/src/components/LogModal.tsx index 5c64f4bbd..da043d9c4 100644 --- a/horreum-web/src/components/LogModal.tsx +++ b/horreum-web/src/components/LogModal.tsx @@ -145,11 +145,11 @@ export default function LogModal(props: LogModalProps) { /> - + diff --git a/horreum-web/src/components/NotificationMethodSelect.tsx b/horreum-web/src/components/NotificationMethodSelect.tsx index 5aa31b026..c235dd67a 100644 --- a/horreum-web/src/components/NotificationMethodSelect.tsx +++ b/horreum-web/src/components/NotificationMethodSelect.tsx @@ -1,9 +1,6 @@ -import { useEffect, useState } from "react" +import {useEffect, useState} from "react" +import {SimpleSelect} from "@patternfly/react-templates"; -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; import {notificationsApi} from "../api" type NotificationMethodSelectProps = { @@ -13,26 +10,17 @@ type NotificationMethodSelectProps = { } export default function NotificationMethodSelect({isDisabled, method, onChange}: NotificationMethodSelectProps) { - const [methodOpen, setMethodOpen] = useState(false) const [methods, setMethods] = useState([]) useEffect(() => { notificationsApi.methods().then(response => setMethods(response)) }, []) return ( - + toggleWidth="100%" + /> ) } diff --git a/horreum-web/src/components/TimeRangeSelect.tsx b/horreum-web/src/components/TimeRangeSelect.tsx index e7ecea50d..d517f9886 100644 --- a/horreum-web/src/components/TimeRangeSelect.tsx +++ b/horreum-web/src/components/TimeRangeSelect.tsx @@ -1,13 +1,7 @@ -import { useState, useEffect } from "react" - -import { - Select, - SelectOption, - SelectOptionObject -} from '@patternfly/react-core/deprecated'; +import {SimpleSelect} from "@patternfly/react-templates"; type TimeRangeSelectProps = { - selection?: TimeRange + selection: TimeRange onSelect(range: TimeRange): void options: TimeRange[] } @@ -15,33 +9,14 @@ type TimeRangeSelectProps = { export type TimeRange = { from?: number to?: number -} & SelectOptionObject +} -function TimeRangeSelect(props: TimeRangeSelectProps) { - const [isOpen, setOpen] = useState(false) - const selection = props.selection - const onSelect = props.onSelect - useEffect(() => { - if (!selection) { - onSelect(props.options[0]) - } - }, [props.options, selection, onSelect]) +export default function TimeRangeSelect(props: TimeRangeSelectProps) { return ( - + ({value: i, content: o.toString(), selected: o === props.selection}))} + onSelect={(_, item) => props.onSelect(props.options[item as number])} + selected={props.selection} + /> ) } - -export default TimeRangeSelect diff --git a/horreum-web/src/components/ViewSelect.tsx b/horreum-web/src/components/ViewSelect.tsx index 60c777f35..dddc73702 100644 --- a/horreum-web/src/components/ViewSelect.tsx +++ b/horreum-web/src/components/ViewSelect.tsx @@ -1,10 +1,5 @@ -import { useState } from "react" -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; - -import { View } from "../api" +import {View} from "../api" +import {SimpleSelect} from "@patternfly/react-templates"; type ViewSelectProps = { views: View[] @@ -13,23 +8,11 @@ type ViewSelectProps = { } export default function ViewSelect({views, viewId, onChange}: ViewSelectProps) { - const [isOpen, setOpen] = useState(false) - const selected = views.find(v => v.id === viewId) return ( - + ({value: v.id, content: v.name, selected: v.id === viewId}))} + onSelect={(_, item) => onChange(item as number)} + selected={viewId} + /> ) } diff --git a/horreum-web/src/domain/alerting/RecalculateModal.tsx b/horreum-web/src/domain/alerting/RecalculateModal.tsx index 41851be11..1d6c57285 100644 --- a/horreum-web/src/domain/alerting/RecalculateModal.tsx +++ b/horreum-web/src/domain/alerting/RecalculateModal.tsx @@ -141,7 +141,7 @@ export default function RecalculateModal({ title, recalculate, cancel, message, {message} - + setClearDatapoints(val)} /> From 71e586f8f49360267c9c10deb2db193686812a9e Mon Sep 17 00:00:00 2001 From: barreiro Date: Sat, 28 Dec 2024 01:47:18 +0000 Subject: [PATCH 08/11] Remove use of deprecated Select from Experiments.tsx and VariablleForm.tsx --- horreum-web/src/domain/tests/Experiments.tsx | 140 +++++++----------- horreum-web/src/domain/tests/VariableForm.tsx | 47 +++--- 2 files changed, 75 insertions(+), 112 deletions(-) diff --git a/horreum-web/src/domain/tests/Experiments.tsx b/horreum-web/src/domain/tests/Experiments.tsx index 4c61bd221..d62936ad5 100644 --- a/horreum-web/src/domain/tests/Experiments.tsx +++ b/horreum-web/src/domain/tests/Experiments.tsx @@ -1,26 +1,20 @@ import {useState, useEffect, useContext} from "react" import { NavLink } from "react-router-dom" -import {JSXElementConstructor, ReactElement } from 'react'; import { Alert, Button, Flex, FlexItem, + Form, FormGroup, FormSection, List, ListItem, Popover, Tab, - TabProps, Tabs, - TabsProps, - TextInput + TextInput } from '@patternfly/react-core'; -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; import {alertingApi, ConditionConfig, experimentApi, Test, Variable} from "../../api" import { useTester } from "../../auth" @@ -94,56 +88,64 @@ export default function Experiments(props: ExperimentsProps) { } return ( - - - - {usedModel.title} - + + + - - - - {isTester && ( - - + + - )} - - - { - c.variableId = v.id - update({ comparisons: [...selected.comparisons] }) - }} - /> - {usedModel.ui.map(comp => ( - { - (c.config as any)[comp.name] = value - update({ comparisons: [...selected.comparisons] }) - }} - /> - ))} + {isTester && ( + + + + )} + + + + ({value: v.id, content: v.name, selected: v.id === c.variableId}))} + onSelect={(_, item) => { + c.variableId = item as number + update({comparisons: [...selected.comparisons]}) + }} + selected={c.variableId} + isScrollable + maxMenuHeight="40vh" + toggleWidth="100%" + popperProps={{enableFlip: false, preventOverflow: true}} + /> + + {usedModel.ui.map(comp => ( + { + (c.config as any)[comp.name] = value + update({comparisons: [...selected.comparisons]}) + }} + /> + ))} +
) }) @@ -440,31 +442,3 @@ export default function Experiments(props: ExperimentsProps) { ) } - -type VariableSelectProps = { - variables: Variable[] - selectedId: number | undefined - onChange(variable: Variable): void -} - -function VariableSelect(props: VariableSelectProps) { - const [open, setOpen] = useState(false) - return ( - - ) -} diff --git a/horreum-web/src/domain/tests/VariableForm.tsx b/horreum-web/src/domain/tests/VariableForm.tsx index 7cf8dffb1..2d6652b19 100644 --- a/horreum-web/src/domain/tests/VariableForm.tsx +++ b/horreum-web/src/domain/tests/VariableForm.tsx @@ -17,10 +17,6 @@ import { TextInput, Title } from '@patternfly/react-core'; -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; import { AddCircleOIcon } from "@patternfly/react-icons" @@ -28,7 +24,7 @@ import ConditionComponent from "../../components/ConditionComponent" import Labels from "../../components/Labels" import OptionalFunction from "../../components/OptionalFunction" import HelpButton from "../../components/HelpButton" -import {SimpleSelect} from "@patternfly/react-templates"; +import {SimpleSelect, TypeaheadSelect} from "@patternfly/react-templates"; type VariableFormProps = { variable: Variable @@ -48,7 +44,6 @@ function checkVariable(v: Variable) { } export default function VariableForm(props: VariableFormProps) { - const [groupOpen, setGroupOpen] = useState(false) const [changeDetection, setChangeDetection] = useState() const [adding, setAdding] = useState(false) const [newModel, setNewModel] = useState() @@ -78,7 +73,7 @@ export default function VariableForm(props: VariableFormProps) { /> )); return ( -
+ - + onClearSelection={() => props.onChange({...props.variable, group: undefined})} + selected={props.variable.group} + isCreatable + isScrollable + maxMenuHeight="40vh" + toggleWidth="100%" + popperProps={{enableFlip: false, preventOverflow: true}} + /> Date: Sat, 28 Dec 2024 04:58:16 +0000 Subject: [PATCH 09/11] Remove use of deprecated Select from SchemaSelect.tsx and ChangeSchemaModal.tsx --- horreum-web/src/components/SchemaSelect.tsx | 81 ++++++------------- .../src/domain/runs/ChangeSchemaModal.tsx | 80 ++++++------------ .../src/domain/schemas/Transformers.tsx | 6 +- 3 files changed, 50 insertions(+), 117 deletions(-) diff --git a/horreum-web/src/components/SchemaSelect.tsx b/horreum-web/src/components/SchemaSelect.tsx index ca0278c39..7b2422c95 100644 --- a/horreum-web/src/components/SchemaSelect.tsx +++ b/horreum-web/src/components/SchemaSelect.tsx @@ -1,10 +1,6 @@ -import { useState, useEffect } from "react" +import {useState, useEffect} from "react" -import { - Select, - SelectOption, - SelectOptionObject -} from '@patternfly/react-core/deprecated'; +import {TypeaheadSelect} from "@patternfly/react-templates"; import {schemaApi} from "../api" @@ -16,75 +12,46 @@ type SchemaSelectProps = { isCreatable?: boolean } -interface Schema extends SelectOptionObject { +interface Schema { name: string id: number uri: string + toString: () => string } export default function SchemaSelect({value, onChange, disabled, noSchemaOption, isCreatable}: SchemaSelectProps) { - const [isExpanded, setExpanded] = useState(false) const [options, setOptions] = useState([]) const noSchemaAllowed = noSchemaOption || false useEffect(() => { - if (options.length > 0) { - return - } - schemaApi.descriptors().then(response => { - const schemas = response.map(s => { - return { ...s, toString: () => `${s.name} (${s.uri})` } - }) + options.length || schemaApi.descriptors().then(response => { + const schemas = response.map(s => ({...s, toString: () => `${s.name === s.uri ? "" : s.name} [${s.uri}]`})) setOptions(schemas) if (!noSchemaAllowed && !value && schemas.length > 0) { onChange(schemas[0].uri, schemas[0].id) } }) }, [onChange, value, noSchemaAllowed]) - const extraOptions: Schema[] = [] - if (noSchemaAllowed) { - extraOptions.push({ name: "", id: 0, uri: "", toString: () => "-- no schema --" }) - } return ( - + isCreatable={isCreatable} + createOptionMessage={(item) => `Use new schema URI: ${item}`} + isScrollable + toggleWidth="100%" + maxMenuHeight="45vh" + popperProps={{enableFlip: false, preventOverflow: true, maxWidth: "200px"}} + /> ) } diff --git a/horreum-web/src/domain/runs/ChangeSchemaModal.tsx b/horreum-web/src/domain/runs/ChangeSchemaModal.tsx index 67a694437..666d0d73e 100644 --- a/horreum-web/src/domain/runs/ChangeSchemaModal.tsx +++ b/horreum-web/src/domain/runs/ChangeSchemaModal.tsx @@ -1,14 +1,7 @@ import { useEffect, useState } from "react" -import { - Button, - Modal, - Spinner -} from '@patternfly/react-core'; -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; +import {Button, Form, FormGroup, Modal, Spinner} from '@patternfly/react-core'; +import {SimpleSelect} from "@patternfly/react-templates"; import SchemaSelect from "../../components/SchemaSelect" @@ -17,51 +10,8 @@ type InitialSchema = { id: number } -type PathSelectProps = { - hasRoot: boolean - paths: string[] - value?: string - onChange(path: string | undefined): void -} - const ROOT_PATH = "__root_path__" -function PathSelect(props: PathSelectProps) { - const [isExpanded, setExpanded] = useState(false) - const options = [] - if (props.hasRoot) { - options.push( - - Root schema - - ) - } - props.paths.forEach((option, index) => options.push()) - return ( - - ) -} - type ChangeSchemaModalProps = { isOpen: boolean onClose(): void @@ -87,7 +37,7 @@ export default function ChangeSchemaModal(props: ChangeSchemaModalProps) { }, [props.initialSchema]) return ( {!updating && ( - <> - - - + + + 0 ? "Select path..." : "No paths available"} + initialOptions={ + (props.hasRoot ? [{value:ROOT_PATH, content: "Root schema", selected: path === undefined}] : []) + .concat(props.paths.map(p => ({value: p, content: p, selected: p === path}))) + } + onSelect={(_, item) => setPath(item === ROOT_PATH ? undefined : item as string)} + selected={path ? path : props.hasRoot ? ROOT_PATH : undefined} + isScrollable + toggleWidth="100%" + maxMenuHeight="45vh" + popperProps={{enableFlip: false, preventOverflow: true}} + /> + + + + + )} {updating && } diff --git a/horreum-web/src/domain/schemas/Transformers.tsx b/horreum-web/src/domain/schemas/Transformers.tsx index d107cf8cc..31d0506a3 100644 --- a/horreum-web/src/domain/schemas/Transformers.tsx +++ b/horreum-web/src/domain/schemas/Transformers.tsx @@ -230,9 +230,9 @@ export default function Transformers(props: TransformersProps) { update({ targetSchemaUri })} - noSchemaOption={true} - isCreatable={true} - > + noSchemaOption + isCreatable + /> ) : ( )} From a7fd18c379e791d94f5ed1b7cd5726db821ce932 Mon Sep 17 00:00:00 2001 From: barreiro Date: Mon, 30 Dec 2024 07:55:42 +0000 Subject: [PATCH 10/11] Remove use of deprecated Select from Labels.tsx and LabelsSelect.tsx --- .../components/LabelFilter/LabelFilter.tsx | 10 +- horreum-web/src/components/Labels.tsx | 210 +++++++----------- horreum-web/src/components/LabelsSelect.tsx | 71 +++--- 3 files changed, 112 insertions(+), 179 deletions(-) diff --git a/horreum-web/src/components/LabelFilter/LabelFilter.tsx b/horreum-web/src/components/LabelFilter/LabelFilter.tsx index 9b9cdd56c..2d6a9ee01 100644 --- a/horreum-web/src/components/LabelFilter/LabelFilter.tsx +++ b/horreum-web/src/components/LabelFilter/LabelFilter.tsx @@ -5,11 +5,6 @@ import { teamsSelector } from "../../auth" import { ToolbarGroup, ToolbarItem, ToolbarToggleGroup } from '@patternfly/react-core'; -import { - Select, - SelectOption, - SelectOptionObject -} from '@patternfly/react-core/deprecated'; import { deepEquals, noop } from "../../utils" import FilterIcon from "@patternfly/react-icons/dist/esm/icons/filter-icon"; @@ -49,7 +44,9 @@ function convertPartial(value: any) { return value } -export type SelectedLabels = SelectOptionObject | null +export type SelectedLabels = { + toString(): string +} type LabelsSelectProps = { disabled?: boolean @@ -166,4 +163,3 @@ export default function LabelFilter({selection, onSelect, source, emptyPlacehold } } - diff --git a/horreum-web/src/components/Labels.tsx b/horreum-web/src/components/Labels.tsx index b27f6b619..49910dfdd 100644 --- a/horreum-web/src/components/Labels.tsx +++ b/horreum-web/src/components/Labels.tsx @@ -1,25 +1,16 @@ -import React, {ReactNode, RefObject, useContext, useEffect, useMemo, useRef, useState} from "react" +import React, {useContext, useEffect, useMemo, useState} from "react" -import { NavLink } from "react-router-dom" +import {NavLink} from "react-router-dom" -import { - Checkbox, - Flex, - FlexItem, - Tooltip -} from '@patternfly/react-core'; -import { - Select, - SelectOption -} from '@patternfly/react-core/deprecated'; -import { ExclamationCircleIcon } from "@patternfly/react-icons" +import {Checkbox, HelperText, HelperTextItem, Label, Split, SplitItem, Tooltip} from '@patternfly/react-core'; +import {ExclamationCircleIcon} from "@patternfly/react-icons" import {LabelInfo, schemaApi} from "../api" -import NameUri from "./NameUri" import {AppContext} from "../context/appContext"; import {AppContextType} from "../context/@types/appContextTypes"; -import {SimpleSelect} from "@patternfly/react-templates"; +import {MultiTypeaheadSelect, SimpleDropdown, TypeaheadSelect} from "@patternfly/react-templates"; +import FilterIcon from "@patternfly/react-icons/dist/esm/icons/filter-icon"; type LabelsProps = { labels: string[] @@ -34,30 +25,22 @@ const ALL_SCHEMAS = "__all__" export default function Labels({ labels, onChange, isReadOnly, error, defaultMetrics, defaultFiltering }: LabelsProps) { const { alerting } = useContext(AppContext) as AppContextType; - const [isExpanded, setExpanded] = useState(false) const [options, setOptions] = useState([]) const [schemaFilter, setSchemaFilter] = useState(ALL_SCHEMAS) - const [schemaFilterOptions, setSchemaFilterOptions] = useState>({ - __all__: "All schemas", - }) + const [schemaFilterOptions, setSchemaFilterOptions] = useState>({__all__: "All schemas",}) const [metrics, setMetrics] = useState(defaultMetrics === undefined || defaultMetrics) const [filtering, setFiltering] = useState(defaultFiltering === undefined || defaultFiltering) useEffect(() => { schemaApi.allLabels().then( labels => { - setOptions(labels) - const sfo: Record = { ...schemaFilterOptions } - labels.flatMap(l => l.schemas).forEach(s => (sfo[s.uri] = )) + setOptions(labels.sort()) + const sfo: Record = {...schemaFilterOptions} + labels.flatMap(l => l.schemas).forEach(s => (sfo[s.uri] = `${s.name === s.uri ? "" : s.name} [${s.uri}]`)) setSchemaFilterOptions(sfo) }, error => alerting.dispatchError(error, "LIST_ALL_LABELS", "Failed to list available labels.") ) }, []) - useEffect(() => { - if (!isExpanded) { - setSchemaFilter(ALL_SCHEMAS) - } - }, [isExpanded]) const selected = labels.map(l => { const o = options.find(l2 => l2.name === l) if (!o) { @@ -69,123 +52,82 @@ export default function Labels({ labels, onChange, isReadOnly, error, defaultMet toString: () => l, } } - return { ...o, toString: () => o.name } + return {...o, toString: () => o.name} }) - const footerRef = useRef() - function ensureFooterInView() { - setTimeout(() => { - if (footerRef.current) { - const { bottom } = footerRef.current.getBoundingClientRect() - if (bottom > (window.innerHeight || document.documentElement.clientHeight)) { - footerRef.current.scrollIntoView({ behavior: "smooth", block: "end" }) - } - } - }, 300) - } const filteredOptions = useMemo( - () => - options - .filter(o => schemaFilter === "__all__" || o.schemas.some(s => s.uri === schemaFilter)) - .filter(o => !labels.includes(o.name) && ((o.metrics && metrics) || (o.filtering && filtering))) - .sort() - .map((o, index) => ), - [options, schemaFilter, labels] + () => (schemaFilter === ALL_SCHEMAS + ? options + : options.filter(o => labels.includes(o.name) || (o.schemas.some(s => s.uri === schemaFilter) && ((o.metrics && metrics) || (o.filtering && filtering)))) + ).map(o => ({value: o.name, content: o.name, selected: labels.includes(o.name)})), + [options, schemaFilter, metrics, filtering, labels] ) return ( <> - - {error && ( - - {error} - - )} - {selected.map(o => ( -
- - {o.name} - {" "} + + + } + {error && {error}} + {selected.length == 0 + ? <>No labels + : selected.map(o => ( +
+ is valid for schemas:{"\u00A0"} {o.schemas.length === 0 && ( - + )} {o.schemas.map((d, i) => ( diff --git a/horreum-web/src/components/LabelsSelect.tsx b/horreum-web/src/components/LabelsSelect.tsx index b4d227f47..471c90de1 100644 --- a/horreum-web/src/components/LabelsSelect.tsx +++ b/horreum-web/src/components/LabelsSelect.tsx @@ -8,11 +8,7 @@ import { Split, SplitItem } from '@patternfly/react-core'; -import { - Select, - SelectOption, - SelectOptionObject -} from '@patternfly/react-core/deprecated'; +import {SimpleSelect, TypeaheadSelect} from "@patternfly/react-templates"; import { deepEquals, noop } from "../utils" @@ -49,7 +45,9 @@ function convertPartial(value: any) { return value } -export type SelectedLabels = SelectOptionObject | null +export type SelectedLabels = { + toString(): string +} type LabelsSelectProps = { disabled?: boolean @@ -86,7 +84,7 @@ export default function LabelsSelect({disabled, selection, onSelect, source, emp } }, noop) }, [source, onSelect, teams, optionForAll]) - const all: SelectOptionObject = useMemo( + const all: SelectedLabels = useMemo( () => ({ toString: () => optionForAll || "", }), @@ -200,8 +198,8 @@ export default function LabelsSelect({disabled, selection, onSelect, source, emp