diff --git a/package-lock.json b/package-lock.json index e188630..34f5b78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,12 +13,12 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@playwright/test": "^1.58.0", + "@playwright/test": "^1.65.0", "@tailwindcss/forms": "^0.5.7", "@vitejs/plugin-react": "^4.3.0", "ajv": "^8.20.0", "autoprefixer": "^10.4.0", - "playwright": "^1.58.0", + "playwright": "^1.65.0", "postcss": "^8.4.0", "tailwindcss": "^3.4.0", "vite": "^5.4.0" @@ -799,19 +799,19 @@ } }, "node_modules/@playwright/test": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.0.tgz", - "integrity": "sha512-fWza+Lpbj6SkQKCrU6si4iu+fD2dD3gxNHFhUPxsfXBPhnv3rRSQVd0NtBUT9Z/RhF/boCBcuUaMUSTRTopjZg==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.65.0.tgz", + "integrity": "sha512-iGURLGuKDLakSEl7Pgfv8h7f+XLT+V861Wfhz0zlEl5nyFuKUopdkFBPKqTllTUp06aOwPuH8iuUEb3yp3MpbQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.58.0" + "playwright": "1.65.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@rolldown/pluginutils": { @@ -2076,50 +2076,32 @@ } }, "node_modules/playwright": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.0.tgz", - "integrity": "sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.65.0.tgz", + "integrity": "sha512-F3AMWcR44qMBt4kq+6Kb6mX7bjGXshktKFOPULd7reED6ZJWevjbNRqysP7q+AATE9kdPEZBibex1BYsvpVoeA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.58.0" + "playwright-core": "1.65.0" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" + "node": ">=20" } }, "node_modules/playwright-core": { - "version": "1.58.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.0.tgz", - "integrity": "sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==", + "version": "1.65.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.65.0.tgz", + "integrity": "sha512-vNSKgH6YqtN7cdT/L334zo0a+YwkrpicyrHJlWWPIm/Q+Nn2SWInil01oT0mbu96U4GgoRtCYQD9CzJQgju+lA==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" - } - }, - "node_modules/playwright/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=20" } }, "node_modules/postcss": { diff --git a/package.json b/package.json index 87c846c..46fa0ee 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,12 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@playwright/test": "^1.58.0", + "@playwright/test": "^1.65.0", "@tailwindcss/forms": "^0.5.7", "@vitejs/plugin-react": "^4.3.0", "ajv": "^8.20.0", "autoprefixer": "^10.4.0", - "playwright": "^1.58.0", + "playwright": "^1.65.0", "postcss": "^8.4.0", "tailwindcss": "^3.4.0", "vite": "^5.4.0" diff --git a/src/components/steps/CommandsStep.jsx b/src/components/steps/CommandsStep.jsx index 81f6e96..c086087 100644 --- a/src/components/steps/CommandsStep.jsx +++ b/src/components/steps/CommandsStep.jsx @@ -3,6 +3,7 @@ import { createCommand, getCommandType, getComponentType } from '../../utils/fac import CommandEditor from '../editors/CommandEditor' import ArrayFieldManager from '../forms/ArrayFieldManager' import Alert from '../common/Alert' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -21,7 +22,7 @@ export default function CommandsStep() { return (
Commands run inside the workspace: exec runs a command line in a container,{' '} apply deploys a component, and composite chains other commands. diff --git a/src/components/steps/ComponentsStep.jsx b/src/components/steps/ComponentsStep.jsx index 8890580..eb89bd3 100644 --- a/src/components/steps/ComponentsStep.jsx +++ b/src/components/steps/ComponentsStep.jsx @@ -2,6 +2,7 @@ import { useSectionList } from '../../hooks/useWizardState' import { createComponent, getComponentType } from '../../utils/factories' import ComponentEditor from '../editors/ComponentEditor' import ArrayFieldManager from '../forms/ArrayFieldManager' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -17,7 +18,7 @@ export default function ComponentsStep() { return (
The containers, volumes, Kubernetes or OpenShift resources and image builds that make up the development environment. diff --git a/src/components/steps/EventsStep.jsx b/src/components/steps/EventsStep.jsx index 6b9e5cf..c9c0e3e 100644 --- a/src/components/steps/EventsStep.jsx +++ b/src/components/steps/EventsStep.jsx @@ -3,6 +3,7 @@ import { EVENT_TYPES } from '../../utils/constants' import { getCommandType } from '../../utils/factories' import Button from '../common/Button' import FormSection from '../forms/FormSection' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -107,7 +108,7 @@ export default function EventsStep() { return (
Bind commands to the workspace lifecycle. Commands bound to an event run in the order listed below.
diff --git a/src/components/steps/MetadataStep.jsx b/src/components/steps/MetadataStep.jsx index 15a8d35..69f5109 100644 --- a/src/components/steps/MetadataStep.jsx +++ b/src/components/steps/MetadataStep.jsx @@ -12,6 +12,7 @@ import FormInput from '../forms/FormInput' import FormSection from '../forms/FormSection' import FormTextarea from '../forms/FormTextarea' import StringListManager from '../forms/StringListManager' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -28,7 +29,7 @@ export default function MetadataStep() { return (Metadata describing the devfile. Everything is optional for the schema, but a name is needed to identify the workspace. diff --git a/src/components/steps/ParentStep.jsx b/src/components/steps/ParentStep.jsx index 7011ab4..d0a4c14 100644 --- a/src/components/steps/ParentStep.jsx +++ b/src/components/steps/ParentStep.jsx @@ -10,7 +10,6 @@ import { getComponentType, getParentSourceType } from '../../utils/factories' -import Badge from '../common/Badge' import CommandEditor from '../editors/CommandEditor' import ComponentEditor from '../editors/ComponentEditor' import ProjectEditor from '../editors/ProjectEditor' @@ -22,6 +21,7 @@ import FormSelect from '../forms/FormSelect' import MapFieldManager from '../forms/MapFieldManager' import Alert from '../common/Alert' import Button from '../common/Button' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -81,10 +81,7 @@ export default function ParentStep() { if (!parent) { return (
A devfile can inherit from a parent devfile and override parts of it. Everything defined here is merged on top of the parent. Most devfiles do not use a parent — skipping this step is perfectly normal and the{' '} @@ -130,15 +127,14 @@ export default function ParentStep() { return (
The parent devfile this one inherits from. Overrides below are merged on top of the parent content, so no field is mandatory in them. Remove the parent to go back to a devfile without inheritance. diff --git a/src/components/steps/ProjectsStep.jsx b/src/components/steps/ProjectsStep.jsx index b84fc3a..ce0d23c 100644 --- a/src/components/steps/ProjectsStep.jsx +++ b/src/components/steps/ProjectsStep.jsx @@ -4,6 +4,7 @@ import ProjectEditor from '../editors/ProjectEditor' import ArrayFieldManager from '../forms/ArrayFieldManager' import CollapsibleSection from '../forms/CollapsibleSection' import Alert from '../common/Alert' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -36,7 +37,7 @@ export default function ProjectsStep() { return (
Source code cloned into the workspace. A devfile can declare the projects it works on, the starter projects a new workspace can be bootstrapped from, and the dependent projects cloned alongside them. diff --git a/src/components/steps/ReviewStep.jsx b/src/components/steps/ReviewStep.jsx index d36b431..67c6861 100644 --- a/src/components/steps/ReviewStep.jsx +++ b/src/components/steps/ReviewStep.jsx @@ -9,6 +9,7 @@ import Badge from '../common/Badge' import Button from '../common/Button' import Card from '../common/Card' import YamlPreview from '../preview/YamlPreview' +import StepHeading from '../wizard/StepHeading' const STEP_INDEX = Object.fromEntries(WIZARD_STEPS.map((step, index) => [step.id, index])) @@ -72,7 +73,7 @@ export default function ReviewStep() { return (
Review the devfile and download it. Errors must be fixed before downloading, warnings are advisory.
diff --git a/src/components/steps/VariablesStep.jsx b/src/components/steps/VariablesStep.jsx index 6261ec4..fe19af9 100644 --- a/src/components/steps/VariablesStep.jsx +++ b/src/components/steps/VariablesStep.jsx @@ -1,6 +1,7 @@ import { useWizard } from '../../hooks/useWizardState' import MapFieldManager from '../forms/MapFieldManager' import Alert from '../common/Alert' +import StepHeading from '../wizard/StepHeading' import StepIssues from '../wizard/StepIssues' import WizardNavigation from '../wizard/WizardNavigation' @@ -12,7 +13,7 @@ export default function VariablesStep() { return (
Values referenced elsewhere in the devfile with the{' '}
{'{{variable-name}}'} syntax.
diff --git a/src/components/wizard/StepHeading.jsx b/src/components/wizard/StepHeading.jsx
new file mode 100644
index 0000000..2f2c7de
--- /dev/null
+++ b/src/components/wizard/StepHeading.jsx
@@ -0,0 +1,27 @@
+import { WIZARD_STEPS } from '../../utils/constants'
+import Badge from '../common/Badge'
+
+const STEP_BY_ID = Object.fromEntries(WIZARD_STEPS.map((step) => [step.id, step]))
+
+/**
+ * Title row shared by every wizard step, so the heading, the `Optional` badge and the
+ * per-step actions are laid out the same way everywhere. Whether a step is optional comes
+ * from `WIZARD_STEPS`, the same place the progress bar reads it from.
+ *
+ * @param {string} stepId - id declared in `WIZARD_STEPS`.
+ * @param {React.ReactNode} [children] - heading text, defaults to the step heading.
+ * @param {React.ReactNode} [actions] - controls rendered on the right of the row.
+ */
+export default function StepHeading({ stepId, children, actions, className = 'mb-2' }) {
+ const step = STEP_BY_ID[stepId]
+
+ return (
+