Batch C: Fix medium-priority 'any' in UI components (vibe-kanban) (#1312)
* ## ✅ Batch C Complete All medium-priority TypeScript `any` types have been fixed across 7 files: 1. **[markdown-renderer.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/ui/markdown-renderer.tsx)** - Replaced 11 `any` with `React.ComponentProps<'tag'>` 2. **[ExecutorConfigForm.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/ExecutorConfigForm.tsx)** - Used `unknown` for form data, `IChangeEvent<unknown>` for handlers 3. **[FormTemplate.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/rjsf/templates/FormTemplate.tsx)** - Replaced with `React.PropsWithChildren` 4. **[ArrayFieldTemplate.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/rjsf/templates/ArrayFieldTemplate.tsx)** - Created minimal `ArrayItemWithButtons` type for RJSF v6 beta 5. **[DiffsPanel.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/panels/DiffsPanel.tsx)** - Used `Diff[]` and typed `t` function properly 6. **[DiffCard.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/DiffCard.tsx)** - Used existing `ReviewComment` type from context 7. **[useGitOperations.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/hooks/useGitOperations.ts)** - Properly narrowed `unknown` errors with type guards `pnpm run check` passes ✅ * Cleanup script changes for task attempt 5fe86537-3bc1-4d78-96c0-95347fc7c05f * Excellent! The build succeeds. Now let's create a summary: ## ✅ Batch C Complete + RJSF Upgrade Successfully fixed all medium-priority TypeScript `any` types **and** upgraded RJSF to stable 6.1.1: ### Type Fixes (7 files) 1. **[markdown-renderer.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/ui/markdown-renderer.tsx)** - Replaced 11 `any` with `React.ComponentProps<'tag'>` 2. **[ExecutorConfigForm.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/ExecutorConfigForm.tsx)** - Used `unknown` and `IChangeEvent<unknown>` 3. **[FormTemplate.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/rjsf/templates/FormTemplate.tsx)** - Used `React.PropsWithChildren` 4. **[ArrayFieldTemplate.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/rjsf/templates/ArrayFieldTemplate.tsx)** - Migrated to stable RJSF v6 API with `ArrayFieldItemTemplate` 5. **[DiffsPanel.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/panels/DiffsPanel.tsx)** - Used `Diff[]` and proper `t` function type 6. **[DiffCard.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/components/DiffCard.tsx)** - Used `ReviewComment` type from context 7. **[useGitOperations.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/5fe8-batch-c-fix-medi/frontend/src/hooks/useGitOperations.ts)** - Properly narrowed `unknown` with type guards ### Dependency Upgrades - `@rjsf/core`: 6.0.0-beta.11 → **6.1.1** (stable) - `@rjsf/utils`: 6.0.0-beta.11 → **6.1.1** (stable) - `@rjsf/validator-ajv8`: 6.0.0-beta.11 → **6.1.1** (stable) - `@rjsf/shadcn`: 6.0.0-beta.10 → **6.1.1** (stable) ### RJSF Migration Updated to v6 stable API: - Removed workaround type (no longer needed) - Added `ArrayFieldItemTemplate` for proper item rendering - Updated to use `onRemoveItem` callback instead of deprecated `onDropIndexClick` All checks pass ✅ * Cleanup script changes for task attempt 5fe86537-3bc1-4d78-96c0-95347fc7c05f
This commit is contained in:
committed by
GitHub
parent
870a166c38
commit
41376eba94
@@ -22,7 +22,11 @@ import {
|
||||
import '@/styles/diff-style-overrides.css';
|
||||
import { attemptsApi } from '@/lib/api';
|
||||
import type { TaskAttempt } from 'shared/types';
|
||||
import { useReview, type ReviewDraft } from '@/contexts/ReviewProvider';
|
||||
import {
|
||||
useReview,
|
||||
type ReviewDraft,
|
||||
type ReviewComment,
|
||||
} from '@/contexts/ReviewProvider';
|
||||
import { CommentWidgetLine } from '@/components/diff/CommentWidgetLine';
|
||||
import { ReviewCommentRenderer } from '@/components/diff/ReviewCommentRenderer';
|
||||
import {
|
||||
@@ -149,9 +153,8 @@ export default function DiffCard({
|
||||
|
||||
// Transform comments to git-diff-view extendData format
|
||||
const extendData = useMemo(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const oldFileData: Record<string, { data: any }> = {};
|
||||
const newFileData: Record<string, { data: any }> = {};
|
||||
const oldFileData: Record<string, { data: ReviewComment }> = {};
|
||||
const newFileData: Record<string, { data: ReviewComment }> = {};
|
||||
|
||||
commentsForFile.forEach((comment) => {
|
||||
const lineKey = String(comment.lineNumber);
|
||||
@@ -181,7 +184,11 @@ export default function DiffCard({
|
||||
setDraft(widgetKey, draft);
|
||||
};
|
||||
|
||||
const renderWidgetLine = (props: any) => {
|
||||
const renderWidgetLine = (props: {
|
||||
side: SplitSide;
|
||||
lineNumber: number;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const widgetKey = `${filePath}-${props.side}-${props.lineNumber}`;
|
||||
const draft = drafts[widgetKey];
|
||||
if (!draft) return null;
|
||||
@@ -197,7 +204,7 @@ export default function DiffCard({
|
||||
);
|
||||
};
|
||||
|
||||
const renderExtendLine = (lineData: any) => {
|
||||
const renderExtendLine = (lineData: { data: ReviewComment }) => {
|
||||
return (
|
||||
<ReviewCommentRenderer comment={lineData.data} projectId={projectId} />
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMemo, useEffect, useState } from 'react';
|
||||
import Form from '@rjsf/core';
|
||||
import type { IChangeEvent } from '@rjsf/core';
|
||||
import { RJSFValidationError } from '@rjsf/utils';
|
||||
import validator from '@rjsf/validator-ajv8';
|
||||
|
||||
@@ -22,10 +23,10 @@ type ExecutorType =
|
||||
|
||||
interface ExecutorConfigFormProps {
|
||||
executor: ExecutorType;
|
||||
value: any;
|
||||
onSubmit?: (formData: any) => void;
|
||||
onChange?: (formData: any) => void;
|
||||
onSave?: (formData: any) => Promise<void>;
|
||||
value: unknown;
|
||||
onSubmit?: (formData: unknown) => void;
|
||||
onChange?: (formData: unknown) => void;
|
||||
onSave?: (formData: unknown) => Promise<void>;
|
||||
disabled?: boolean;
|
||||
isSaving?: boolean;
|
||||
isDirty?: boolean;
|
||||
@@ -43,7 +44,7 @@ export function ExecutorConfigForm({
|
||||
isSaving = false,
|
||||
isDirty = false,
|
||||
}: ExecutorConfigFormProps) {
|
||||
const [formData, setFormData] = useState(value || {});
|
||||
const [formData, setFormData] = useState<unknown>(value || {});
|
||||
const [validationErrors, setValidationErrors] = useState<
|
||||
RJSFValidationError[]
|
||||
>([]);
|
||||
@@ -57,14 +58,16 @@ export function ExecutorConfigForm({
|
||||
setValidationErrors([]);
|
||||
}, [value, executor]);
|
||||
|
||||
const handleChange = ({ formData: newFormData }: any) => {
|
||||
const handleChange = (event: IChangeEvent<unknown>) => {
|
||||
const newFormData = event.formData;
|
||||
setFormData(newFormData);
|
||||
if (onChange) {
|
||||
onChange(newFormData);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async ({ formData: submitData }: any) => {
|
||||
const handleSubmit = async (event: IChangeEvent<unknown>) => {
|
||||
const submitData = event.formData;
|
||||
setValidationErrors([]);
|
||||
if (onSave) {
|
||||
await onSave(submitData);
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
import type { TaskAttempt } from 'shared/types';
|
||||
import type { TaskAttempt, Diff } from 'shared/types';
|
||||
import GitOperations, {
|
||||
type GitOperationsInputs,
|
||||
} from '@/components/tasks/Toolbar/GitOperations.tsx';
|
||||
@@ -125,7 +125,7 @@ export function DiffsPanel({ selectedAttempt, gitOps }: DiffsPanelProps) {
|
||||
}
|
||||
|
||||
interface DiffsPanelContentProps {
|
||||
diffs: any[];
|
||||
diffs: Diff[];
|
||||
fileCount: number;
|
||||
added: number;
|
||||
deleted: number;
|
||||
@@ -136,7 +136,7 @@ interface DiffsPanelContentProps {
|
||||
selectedAttempt: TaskAttempt | null;
|
||||
gitOps?: GitOperationsInputs;
|
||||
loading: boolean;
|
||||
t: (key: string, params?: any) => string;
|
||||
t: (key: string, params?: Record<string, unknown>) => string;
|
||||
}
|
||||
|
||||
function DiffsPanelContent({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
import type {
|
||||
ArrayFieldTemplateProps,
|
||||
ArrayFieldTemplateItemType,
|
||||
ArrayFieldItemTemplateProps,
|
||||
} from '@rjsf/utils';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Plus, X } from 'lucide-react';
|
||||
@@ -14,17 +14,7 @@ export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
{items.length > 0 &&
|
||||
items.map((element: ArrayFieldTemplateItemType) => (
|
||||
<ArrayItem
|
||||
key={element.key}
|
||||
element={element}
|
||||
disabled={disabled}
|
||||
readonly={readonly}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div>{items}</div>
|
||||
|
||||
{canAdd && (
|
||||
<Button
|
||||
@@ -43,30 +33,21 @@ export const ArrayFieldTemplate = (props: ArrayFieldTemplateProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
interface ArrayItemProps {
|
||||
element: ArrayFieldTemplateItemType;
|
||||
disabled?: boolean;
|
||||
readonly?: boolean;
|
||||
}
|
||||
|
||||
const ArrayItem = ({ element, disabled, readonly }: ArrayItemProps) => {
|
||||
const { children } = element;
|
||||
const elementAny = element as any; // Type assertion needed for RJSF v6 beta properties
|
||||
export const ArrayFieldItemTemplate = (props: ArrayFieldItemTemplateProps) => {
|
||||
const { children, buttonsProps, disabled, readonly } = props;
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1">{children}</div>
|
||||
|
||||
{/* Remove button */}
|
||||
{elementAny.buttonsProps?.hasRemove && (
|
||||
{buttonsProps.hasRemove && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={elementAny.buttonsProps.onDropIndexClick(
|
||||
elementAny.buttonsProps.index
|
||||
)}
|
||||
disabled={disabled || readonly || elementAny.buttonsProps.disabled}
|
||||
onClick={buttonsProps.onRemoveItem}
|
||||
disabled={disabled || readonly || buttonsProps.disabled}
|
||||
className="h-8 w-8 p-0 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-all duration-200 shrink-0"
|
||||
title="Remove item"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export const FormTemplate = (props: any) => {
|
||||
const { children } = props;
|
||||
|
||||
export const FormTemplate = ({ children }: React.PropsWithChildren) => {
|
||||
return <div className="w-full">{children}</div>;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
export { ArrayFieldTemplate } from './ArrayFieldTemplate';
|
||||
export {
|
||||
ArrayFieldTemplate,
|
||||
ArrayFieldItemTemplate,
|
||||
} from './ArrayFieldTemplate';
|
||||
export { FieldTemplate } from './FieldTemplate';
|
||||
export { ObjectFieldTemplate } from './ObjectFieldTemplate';
|
||||
export { FormTemplate } from './FormTemplate';
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from './widgets';
|
||||
import {
|
||||
ArrayFieldTemplate,
|
||||
ArrayFieldItemTemplate,
|
||||
FieldTemplate,
|
||||
ObjectFieldTemplate,
|
||||
FormTemplate,
|
||||
@@ -22,6 +23,7 @@ export const customWidgets: RegistryWidgetsType = {
|
||||
|
||||
export const customTemplates = {
|
||||
ArrayFieldTemplate,
|
||||
ArrayFieldItemTemplate,
|
||||
FieldTemplate,
|
||||
ObjectFieldTemplate,
|
||||
FormTemplate,
|
||||
|
||||
@@ -85,7 +85,11 @@ function LinkOverride({
|
||||
);
|
||||
}
|
||||
|
||||
function InlineCodeOverride({ children, className, ...props }: any) {
|
||||
function InlineCodeOverride({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<'code'>) {
|
||||
// Only highlight inline code, not fenced code blocks
|
||||
const hasLanguage =
|
||||
typeof className === 'string' && /\blanguage-/.test(className);
|
||||
@@ -123,28 +127,28 @@ function MarkdownRenderer({
|
||||
a: { component: LinkOverride },
|
||||
code: { component: InlineCodeOverride },
|
||||
strong: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'strong'>) => (
|
||||
<span {...props} className="">
|
||||
{children}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
em: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'em'>) => (
|
||||
<em {...props} className="italic">
|
||||
{children}
|
||||
</em>
|
||||
),
|
||||
},
|
||||
p: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'p'>) => (
|
||||
<p {...props} className="leading-tight my-2">
|
||||
{children}
|
||||
</p>
|
||||
),
|
||||
},
|
||||
h1: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'h1'>) => (
|
||||
<h1
|
||||
{...props}
|
||||
className="text-lg font-medium leading-tight mt-4 mb-2"
|
||||
@@ -154,7 +158,7 @@ function MarkdownRenderer({
|
||||
),
|
||||
},
|
||||
h2: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'h2'>) => (
|
||||
<h2
|
||||
{...props}
|
||||
className="text-base font-medium leading-tight mt-4 mb-2"
|
||||
@@ -164,14 +168,14 @@ function MarkdownRenderer({
|
||||
),
|
||||
},
|
||||
h3: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'h3'>) => (
|
||||
<h3 {...props} className="text-sm leading-tight mt-3 mb-2">
|
||||
{children}
|
||||
</h3>
|
||||
),
|
||||
},
|
||||
ul: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'ul'>) => (
|
||||
<ul
|
||||
{...props}
|
||||
className="list-disc list-outside ps-6 my-3 space-y-1.5"
|
||||
@@ -181,7 +185,7 @@ function MarkdownRenderer({
|
||||
),
|
||||
},
|
||||
ol: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'ol'>) => (
|
||||
<ol
|
||||
{...props}
|
||||
className="list-decimal list-outside ps-6 my-3 space-y-1.5"
|
||||
@@ -191,14 +195,14 @@ function MarkdownRenderer({
|
||||
),
|
||||
},
|
||||
li: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'li'>) => (
|
||||
<li {...props} className="leading-tight">
|
||||
{children}
|
||||
</li>
|
||||
),
|
||||
},
|
||||
pre: {
|
||||
component: ({ children, ...props }: any) => (
|
||||
component: ({ children, ...props }: React.ComponentProps<'pre'>) => (
|
||||
<pre
|
||||
{...props}
|
||||
className="overflow-x-auto whitespace-pre-wrap break-words font-mono text-sm bg-muted/50 rounded-sm p-2 my-2"
|
||||
|
||||
@@ -32,16 +32,24 @@ export function useGitOperations(
|
||||
const merge = useMerge(
|
||||
attemptId,
|
||||
() => setError(null),
|
||||
(err: any) => {
|
||||
setError(err?.message || 'Failed to merge');
|
||||
(err: unknown) => {
|
||||
const message =
|
||||
err && typeof err === 'object' && 'message' in err
|
||||
? String(err.message)
|
||||
: 'Failed to merge';
|
||||
setError(message);
|
||||
}
|
||||
);
|
||||
|
||||
const push = usePush(
|
||||
attemptId,
|
||||
() => setError(null),
|
||||
(err: any) => {
|
||||
setError(err?.message || 'Failed to push');
|
||||
(err: unknown) => {
|
||||
const message =
|
||||
err && typeof err === 'object' && 'message' in err
|
||||
? String(err.message)
|
||||
: 'Failed to push';
|
||||
setError(message);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -49,8 +57,12 @@ export function useGitOperations(
|
||||
attemptId,
|
||||
projectId,
|
||||
() => setError(null),
|
||||
(err: any) => {
|
||||
setError(err?.message || 'Failed to change target branch');
|
||||
(err: unknown) => {
|
||||
const message =
|
||||
err && typeof err === 'object' && 'message' in err
|
||||
? String(err.message)
|
||||
: 'Failed to change target branch';
|
||||
setError(message);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user