Skip to content

Commit 251cdc7

Browse files
committed
feat: addressed pr comments and improved yaml generation to rely more on backend schema than opinionated defaults and what fields are actually shown
1 parent fa755f5 commit 251cdc7

File tree

26 files changed

+1469
-586
lines changed

26 files changed

+1469
-586
lines changed

frontend/.claude/skills/frontend-developer/SKILL.md

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ yes | bunx @fumadocs/cli add --dir https://redpanda-ui-registry.netlify.app/r bu
4747
yes | bunx @fumadocs/cli add --dir https://redpanda-ui-registry.netlify.app/r card dialog form
4848

4949
# Then generate yarn.lock
50-
bun i --yarn
50+
bun i && bun i --yarn
5151
```
5252

5353
### 3. Write Component
@@ -90,7 +90,7 @@ export function MyComponent({ title, onSubmit }: Props) {
9090
**Performance:**
9191

9292
- Hoist static content outside component
93-
- Use `useMemo` for expensive computations
93+
- Use `useMemo` for expensive computations - but only when there's a noticeable performance impact
9494
- Use `memo` for components receiving props
9595

9696
### 4. Write Tests
@@ -117,17 +117,40 @@ describe("formatNumber", () => {
117117

118118
```typescript
119119
// component.test.tsx
120-
import { render, screen, fireEvent } from 'test-utils';
120+
import { render, screen, fireEvent, waitFor } from 'test-utils';
121+
import { createRouterTransport } from '@connectrpc/connect';
122+
import { createPipeline } from 'protogen/redpanda/api/console/v1alpha1/pipeline-PipelineService_connectquery';
121123
import { MyComponent } from './component';
122124

123125
describe('MyComponent', () => {
124-
test('should call onSubmit when button clicked', () => {
125-
const onSubmit = vi.fn();
126-
render(<MyComponent onSubmit={onSubmit} />);
127-
128-
fireEvent.click(screen.getByRole('button'));
129-
130-
expect(onSubmit).toHaveBeenCalled();
126+
test('should trigger gRPC mutation when form is submitted', async () => {
127+
// Mock the gRPC service method
128+
const mockCreatePipeline = vi.fn(() =>
129+
Promise.resolve({ id: '123', name: 'test-pipeline' })
130+
);
131+
132+
// Create a mocked transport
133+
const transport = createRouterTransport(({ rpc }) => {
134+
rpc(createPipeline, mockCreatePipeline);
135+
});
136+
137+
// Render with the mocked transport
138+
render(<MyComponent />, { transport });
139+
140+
// Fill out the form
141+
fireEvent.change(screen.getByLabelText('Pipeline Name'), {
142+
target: { value: 'test-pipeline' }
143+
});
144+
145+
// Submit the form
146+
fireEvent.click(screen.getByRole('button', { name: 'Create' }));
147+
148+
// Verify the mutation was called with correct data
149+
await waitFor(() => {
150+
expect(mockCreatePipeline).toHaveBeenCalledWith({
151+
name: 'test-pipeline'
152+
});
153+
});
131154
});
132155
});
133156
```
@@ -150,11 +173,11 @@ const mockFunction = vi.mocked(functionToMock);
150173

151174
```bash
152175
# Run in order
153-
bun run type:check # TypeScript errors
154-
bun run test # All tests
155-
bun run lint # Code quality
156-
bun run build # Production build
157-
bun run start # Dev server - check browser
176+
bun run type:check # TypeScript errors
177+
bun run test # All tests
178+
bun run lint # Code quality
179+
bun run build # Production build
180+
bun run start2 --port=3004 # Dev server - check browser
158181
```
159182

160183
**Success criteria:**
@@ -172,7 +195,6 @@ bun run test # All tests (unit + integration)
172195
bun run test:unit # Unit tests only (.test.ts)
173196
bun run test:integration # Integration tests only (.test.tsx)
174197
bun run test:watch # Watch mode
175-
bun run test:ui # Interactive UI
176198
bun run test:coverage # Coverage report
177199
```
178200

@@ -284,7 +306,7 @@ yes | bunx @fumadocs/cli add --dir https://redpanda-ui-registry.netlify.app/r \
284306
**After package install:**
285307

286308
```bash
287-
bun i --yarn # ALWAYS run this
309+
bun i && bun i --yarn # ALWAYS run this
288310
```
289311

290312
**Testing shortcuts:**

frontend/src/components/pages/connect/overview.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { WaitingRedpanda } from 'components/redpanda-ui/components/waiting-redpa
1717
import { observer, useLocalObservable } from 'mobx-react';
1818
import { Component, type FunctionComponent } from 'react';
1919
import { useKafkaConnectConnectorsQuery } from 'react-query/api/kafka-connect';
20-
import { Navigate, useLocation } from 'react-router-dom';
20+
import { useLocation } from 'react-router-dom';
2121

2222
import {
2323
ConnectorClass,
@@ -29,10 +29,10 @@ import {
2929
TaskState,
3030
TasksColumn,
3131
} from './helper';
32-
import { isFeatureFlagEnabled, isServerless } from '../../../config';
32+
import { isServerless } from '../../../config';
3333
import { ListSecretScopesRequestSchema } from '../../../protogen/redpanda/api/dataplane/v1/secret_pb';
3434
import { appGlobal } from '../../../state/app-global';
35-
import { api, pipelinesApi, rpcnSecretManagerApi } from '../../../state/backend-api';
35+
import { api, rpcnSecretManagerApi } from '../../../state/backend-api';
3636
import type { ClusterConnectorInfo, ClusterConnectors, ClusterConnectorTaskInfo } from '../../../state/rest-interfaces';
3737
import { Features } from '../../../state/supported-features';
3838
import { uiSettings } from '../../../state/ui';
@@ -122,15 +122,6 @@ class KafkaConnectOverview extends PageComponent<{ defaultView: string; isKafkaC
122122
}
123123

124124
render() {
125-
// Redirect to wizard if enableRpcnTiles is enabled, kafka connect is disabled, and there are no existing pipelines
126-
if (
127-
isFeatureFlagEnabled('enableRpcnTiles') &&
128-
pipelinesApi.pipelines?.length === 0 &&
129-
!this.props.isKafkaConnectEnabled
130-
) {
131-
return <Navigate replace to="/rp-connect/wizard" />;
132-
}
133-
134125
const tabs = [
135126
{
136127
key: ConnectView.RedpandaConnect,

frontend/src/components/pages/rp-connect/onboarding/add-secrets-card.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const AddSecretsCard = ({
2323
const [isSecretsDialogOpen, setIsSecretsDialogOpen] = useState(false);
2424

2525
// Fetch secrets
26-
const { data: secretsResponse, refetch: refetchSecrets } = useListSecretsQuery({});
26+
const { data: secretsResponse } = useListSecretsQuery({});
2727
const existingSecrets = useMemo(
2828
() => (secretsResponse?.secrets ? secretsResponse.secrets.map((s) => s?.id || '') : []),
2929
[secretsResponse]
@@ -107,15 +107,6 @@ export const AddSecretsCard = ({
107107
[editorInstance]
108108
);
109109

110-
const handleSecretsCreated = useCallback(() => {
111-
refetchSecrets();
112-
setIsSecretsDialogOpen(false);
113-
}, [refetchSecrets]);
114-
115-
const handleOpenDialog = useCallback(() => {
116-
setIsSecretsDialogOpen(true);
117-
}, []);
118-
119110
const handleUpdateEditorContent = useCallback(
120111
(oldName: string, newName: string) => {
121112
if (!editorInstance) {
@@ -210,7 +201,7 @@ export const AddSecretsCard = ({
210201
<Badge
211202
className="cursor-pointer text-sm hover:opacity-80"
212203
key={secret}
213-
onClick={handleOpenDialog}
204+
onClick={() => setIsSecretsDialogOpen(true)}
214205
variant="red"
215206
>
216207
Create <InlineCode className="bg-transparent">$secrets.{secret}</InlineCode>
@@ -220,7 +211,11 @@ export const AddSecretsCard = ({
220211
</div>
221212
</div>
222213
)}
223-
<Button onClick={handleOpenDialog} size={existingSecrets.length > 0 ? 'sm' : 'default'} variant="outline">
214+
<Button
215+
onClick={() => setIsSecretsDialogOpen(true)}
216+
size={existingSecrets.length > 0 ? 'sm' : 'default'}
217+
variant="outline"
218+
>
224219
{existingSecrets.length > 0 ? 'Add more secrets' : 'Add secret'}
225220
<PlusIcon className="h-4 w-4" />
226221
</Button>
@@ -231,7 +226,7 @@ export const AddSecretsCard = ({
231226
isOpen={isSecretsDialogOpen}
232227
missingSecrets={missingSecrets}
233228
onClose={() => setIsSecretsDialogOpen(false)}
234-
onSecretsCreated={handleSecretsCreated}
229+
onSecretsCreated={() => setIsSecretsDialogOpen(false)}
235230
onUpdateEditorContent={handleUpdateEditorContent}
236231
/>
237232
</Card>

frontend/src/components/pages/rp-connect/pipeline/details.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,30 @@ export function Details({ readonly = false }: DetailsProps) {
115115
<FormItem>
116116
<FormLabel>Compute Units: {field.value}</FormLabel>
117117
<FormControl>
118-
<Slider
119-
max={MAX_TASKS}
120-
min={MIN_TASKS}
121-
onValueChange={(values) => field.onChange(values[0])}
122-
step={1}
123-
value={[field.value]}
124-
/>
118+
<div className="flex items-center gap-2">
119+
<Slider
120+
max={MAX_TASKS}
121+
min={MIN_TASKS}
122+
onValueChange={(values) => field.onChange(values[0])}
123+
step={1}
124+
value={[field.value]}
125+
/>
126+
<Input
127+
className="w-12"
128+
max={MAX_TASKS}
129+
min={MIN_TASKS}
130+
onChange={(e) => {
131+
const value = Number(e.target.value);
132+
if (!Number.isNaN(value) && value >= MIN_TASKS && value <= MAX_TASKS) {
133+
field.onChange(value);
134+
}
135+
}}
136+
showStepControls
137+
step={1}
138+
type="number"
139+
value={field.value}
140+
/>
141+
</div>
125142
</FormControl>
126143
<FormDescription className="text-muted-foreground text-sm">
127144
One compute unit = 0.1 CPU and 400 MB memory

frontend/src/components/pages/rp-connect/pipeline/footer.tsx

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)