[WEB-5459] feat(codemods): add function declaration transformer with tests (#8137)

- Add jscodeshift-based codemod to convert arrow function components to function declarations
- Support React.FC, observer-wrapped, and forwardRef components
- Include comprehensive test suite covering edge cases
- Add npm script to run transformer across codebase
- Target only .tsx files in source directories, excluding node_modules and declaration files

* [WEB-5459] chore: updates after running codemod

---------

Co-authored-by: sriramveeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
Aaron 2025-11-20 19:09:40 +07:00 committed by GitHub
parent 90866fb925
commit 83fdebf64d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1771 changed files with 17003 additions and 13856 deletions

View file

@ -34,7 +34,7 @@ const moduleBurnDownChartOptions = [
{ value: "points", i18n_label: "points" },
];
export const ModuleAnalyticsProgress: FC<TModuleAnalyticsProgress> = observer((props) => {
export const ModuleAnalyticsProgress = observer(function ModuleAnalyticsProgress(props: TModuleAnalyticsProgress) {
// props
const { workspaceSlug, projectId, moduleId } = props;
// router

View file

@ -33,7 +33,7 @@ type TModuleProgressStats = {
totalIssuesCount: number;
};
export const ModuleProgressStats: FC<TModuleProgressStats> = observer((props) => {
export const ModuleProgressStats = observer(function ModuleProgressStats(props: TModuleProgressStats) {
const {
distribution,
groupedIssues,

View file

@ -55,7 +55,7 @@ type Props = {
};
// TODO: refactor this component
export const ModuleAnalyticsSidebar: React.FC<Props> = observer((props) => {
export const ModuleAnalyticsSidebar = observer(function ModuleAnalyticsSidebar(props: Props) {
const { moduleId, handleClose, isArchived } = props;
// states
const [moduleLinkModal, setModuleLinkModal] = useState(false);

View file

@ -12,7 +12,7 @@ type Props = {
values: string[];
};
export const AppliedDateFilters: React.FC<Props> = observer((props) => {
export const AppliedDateFilters = observer(function AppliedDateFilters(props: Props) {
const { editable, handleRemove, values } = props;
const getDateLabel = (value: string): string => {

View file

@ -15,7 +15,7 @@ type Props = {
editable: boolean | undefined;
};
export const AppliedMembersFilters: React.FC<Props> = observer((props) => {
export const AppliedMembersFilters = observer(function AppliedMembersFilters(props: Props) {
const { handleRemove, values, editable } = props;
// store hooks
const {

View file

@ -21,7 +21,7 @@ type Props = {
const MEMBERS_FILTERS = ["lead", "members"];
const DATE_FILTERS = ["start_date", "target_date"];
export const ModuleAppliedFiltersList: React.FC<Props> = (props) => {
export function ModuleAppliedFiltersList(props: Props) {
const {
appliedFilters,
isFavoriteFilterApplied,
@ -123,4 +123,4 @@ export const ModuleAppliedFiltersList: React.FC<Props> = (props) => {
</div>
</Header>
);
};
}

View file

@ -13,7 +13,7 @@ type Props = {
editable: boolean | undefined;
};
export const AppliedStatusFilters: React.FC<Props> = observer((props) => {
export const AppliedStatusFilters = observer(function AppliedStatusFilters(props: Props) {
const { handleRemove, values, editable } = props;
const { t } = useTranslation();

View file

@ -19,7 +19,7 @@ import { ModuleFiltersSelection, ModuleOrderByDropdown } from "@/components/modu
import { useMember } from "@/hooks/store/use-member";
import { useModuleFilter } from "@/hooks/store/use-module-filter";
export const ArchivedModulesHeader: FC = observer(() => {
export const ArchivedModulesHeader = observer(function ArchivedModulesHeader() {
// router
const { projectId } = useParams();
// refs

View file

@ -18,7 +18,7 @@ type Props = {
onSubmit?: () => Promise<void>;
};
export const ArchiveModuleModal: React.FC<Props> = (props) => {
export function ArchiveModuleModal(props: Props) {
const { workspaceSlug, projectId, moduleId, isOpen, handleClose } = props;
// router
const router = useAppRouter();
@ -104,4 +104,4 @@ export const ArchiveModuleModal: React.FC<Props> = (props) => {
</Dialog>
</Transition.Root>
);
};
}

View file

@ -15,7 +15,7 @@ import { CycleModuleListLayoutLoader } from "@/components/ui/loader/cycle-module
import { useModule } from "@/hooks/store/use-module";
import { useModuleFilter } from "@/hooks/store/use-module-filter";
export const ArchivedModuleLayoutRoot: React.FC = observer(() => {
export const ArchivedModuleLayoutRoot = observer(function ArchivedModuleLayoutRoot() {
// router
const { workspaceSlug, projectId } = useParams();
// plane hooks

View file

@ -16,7 +16,7 @@ export interface IArchivedModulesView {
projectId: string;
}
export const ArchivedModulesView: FC<IArchivedModulesView> = observer((props) => {
export const ArchivedModulesView = observer(function ArchivedModulesView(props: IArchivedModulesView) {
const { workspaceSlug, projectId } = props;
// store hooks
const { getFilteredArchivedModuleIds, loader } = useModule();

View file

@ -23,7 +23,7 @@ type Props = {
onClose: () => void;
};
export const DeleteModuleModal: React.FC<Props> = observer((props) => {
export const DeleteModuleModal = observer(function DeleteModuleModal(props: Props) {
const { data, isOpen, onClose } = props;
// states
const [isDeleteLoading, setIsDeleteLoading] = useState(false);

View file

@ -20,7 +20,7 @@ type Props = {
searchQuery: string;
};
export const FilterLead: React.FC<Props> = observer((props: Props) => {
export const FilterLead = observer(function FilterLead(props: Props) {
const { appliedFilters, handleUpdate, memberIds, searchQuery } = props;
// states
const [itemsToRender, setItemsToRender] = useState(5);

View file

@ -20,7 +20,7 @@ type Props = {
searchQuery: string;
};
export const FilterMembers: React.FC<Props> = observer((props: Props) => {
export const FilterMembers = observer(function FilterMembers(props: Props) {
const { appliedFilters, handleUpdate, memberIds, searchQuery } = props;
// states
const [itemsToRender, setItemsToRender] = useState(5);

View file

@ -22,7 +22,7 @@ type Props = {
isArchived?: boolean;
};
export const ModuleFiltersSelection: React.FC<Props> = observer((props) => {
export const ModuleFiltersSelection = observer(function ModuleFiltersSelection(props: Props) {
const {
displayFilters,
filters,

View file

@ -15,7 +15,7 @@ type Props = {
searchQuery: string;
};
export const FilterStartDate: React.FC<Props> = observer((props) => {
export const FilterStartDate = observer(function FilterStartDate(props: Props) {
const { appliedFilters, handleUpdate, searchQuery } = props;
const [previewEnabled, setPreviewEnabled] = useState(true);

View file

@ -15,7 +15,7 @@ type Props = {
searchQuery: string;
};
export const FilterStatus: React.FC<Props> = observer((props) => {
export const FilterStatus = observer(function FilterStatus(props: Props) {
const { appliedFilters, handleUpdate, searchQuery } = props;
// states
const [previewEnabled, setPreviewEnabled] = useState(true);

View file

@ -14,7 +14,7 @@ type Props = {
searchQuery: string;
};
export const FilterTargetDate: React.FC<Props> = observer((props) => {
export const FilterTargetDate = observer(function FilterTargetDate(props: Props) {
const { appliedFilters, handleUpdate, searchQuery } = props;
const [previewEnabled, setPreviewEnabled] = useState(true);

View file

@ -18,7 +18,7 @@ type Props = {
value: TModuleOrderByOptions | undefined;
};
export const ModuleOrderByDropdown: React.FC<Props> = (props) => {
export function ModuleOrderByDropdown(props: Props) {
const { onChange, value } = props;
// hooks
const { t } = useTranslation();
@ -79,4 +79,4 @@ export const ModuleOrderByDropdown: React.FC<Props> = (props) => {
)}
</CustomMenu>
);
};
}

View file

@ -36,7 +36,7 @@ const defaultValues: Partial<IModule> = {
member_ids: [],
};
export const ModuleForm: React.FC<Props> = (props) => {
export function ModuleForm(props: Props) {
const { handleFormSubmit, handleClose, status, projectId, setActiveProject, data, isMobile = false } = props;
// store hooks
const { projectsWithCreatePermissions } = useUser();
@ -244,4 +244,4 @@ export const ModuleForm: React.FC<Props> = (props) => {
</div>
</form>
);
};
}

View file

@ -20,7 +20,7 @@ type Props = {
moduleId: string;
};
export const ModuleGanttBlock: React.FC<Props> = observer((props) => {
export const ModuleGanttBlock = observer(function ModuleGanttBlock(props: Props) {
const { moduleId } = props;
// router
const router = useAppRouter();
@ -69,7 +69,7 @@ export const ModuleGanttBlock: React.FC<Props> = observer((props) => {
);
});
export const ModuleGanttSidebarBlock: React.FC<Props> = observer((props) => {
export const ModuleGanttSidebarBlock = observer(function ModuleGanttSidebarBlock(props: Props) {
const { moduleId } = props;
const { workspaceSlug } = useParams();
// store hooks

View file

@ -12,7 +12,7 @@ import { useModule } from "@/hooks/store/use-module";
import { useModuleFilter } from "@/hooks/store/use-module-filter";
import { useProject } from "@/hooks/store/use-project";
export const ModulesListGanttChartView: React.FC = observer(() => {
export const ModulesListGanttChartView = observer(function ModulesListGanttChartView() {
// router
const { workspaceSlug, projectId } = useParams();
// store

View file

@ -23,7 +23,7 @@ const defaultValues: ModuleLink = {
url: "",
};
export const CreateUpdateModuleLinkModal: FC<Props> = (props) => {
export function CreateUpdateModuleLinkModal(props: Props) {
const { isOpen, handleClose, createLink, updateLink, data } = props;
// form info
const {
@ -144,4 +144,4 @@ export const CreateUpdateModuleLinkModal: FC<Props> = (props) => {
</form>
</ModalCore>
);
};
}

View file

@ -20,7 +20,7 @@ type Props = {
link: ILinkDetails;
};
export const ModulesLinksListItem: React.FC<Props> = observer((props) => {
export const ModulesLinksListItem = observer(function ModulesLinksListItem(props: Props) {
const { handleDeleteLink, handleEditLink, isEditingAllowed, link } = props;
// store hooks
const { getUserDetails } = useMember();

View file

@ -15,7 +15,7 @@ type Props = {
moduleId: string;
};
export const ModuleLinksList: React.FC<Props> = observer((props) => {
export const ModuleLinksList = observer(function ModuleLinksList(props: Props) {
const { moduleId, handleDeleteLink, handleEditLink, disabled } = props;
// store hooks
const { getModuleById } = useModule();

View file

@ -36,7 +36,7 @@ const defaultValues: Partial<IModule> = {
member_ids: [],
};
export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
export const CreateUpdateModuleModal = observer(function CreateUpdateModuleModal(props: Props) {
const { isOpen, onClose, data, workspaceSlug, projectId } = props;
// states
const [activeProject, setActiveProject] = useState<string | null>(null);

View file

@ -41,7 +41,7 @@ type Props = {
moduleId: string;
};
export const ModuleCardItem: React.FC<Props> = observer((props) => {
export const ModuleCardItem = observer(function ModuleCardItem(props: Props) {
const { moduleId } = props;
// refs
const parentRef = useRef(null);

View file

@ -11,7 +11,7 @@ interface ILayoutIcon {
withContainer?: boolean;
}
export const ModuleLayoutIcon: React.FC<ILayoutIcon> = (props) => {
export function ModuleLayoutIcon(props: ILayoutIcon) {
const { layoutType, className = "", containerClassName = "", size = 14, withContainer = false } = props;
// get Layout icon
@ -35,4 +35,4 @@ export const ModuleLayoutIcon: React.FC<ILayoutIcon> = (props) => {
)}
</>
);
};
}

View file

@ -42,7 +42,7 @@ type Props = {
parentRef: React.RefObject<HTMLDivElement>;
};
export const ModuleListItemAction: FC<Props> = observer((props) => {
export const ModuleListItemAction = observer(function ModuleListItemAction(props: Props) {
const { moduleId, moduleDetails, parentRef } = props;
// router
const { workspaceSlug, projectId } = useParams();

View file

@ -21,7 +21,7 @@ type Props = {
moduleId: string;
};
export const ModuleListItem: React.FC<Props> = observer((props) => {
export const ModuleListItem = observer(function ModuleListItem(props: Props) {
const { moduleId } = props;
// refs
const parentRef = useRef(null);

View file

@ -14,7 +14,11 @@ type Props = {
isArchived?: boolean;
};
export const ModulePeekOverview: React.FC<Props> = observer(({ projectId, workspaceSlug, isArchived = false }) => {
export const ModulePeekOverview = observer(function ModulePeekOverview({
projectId,
workspaceSlug,
isArchived = false,
}: Props) {
// router
const router = useAppRouter();
const pathname = usePathname();

View file

@ -14,7 +14,7 @@ type Props = {
handleModuleDetailsChange: (payload: Partial<IModule>) => Promise<void>;
};
export const ModuleStatusDropdown: FC<Props> = observer((props: Props) => {
export const ModuleStatusDropdown = observer(function ModuleStatusDropdown(props: Props) {
const { isDisabled, moduleDetails, handleModuleDetailsChange } = props;
const { t } = useTranslation();
const moduleStatus = MODULE_STATUS.find((status) => status.value === moduleDetails.status);

View file

@ -28,7 +28,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
import { ModuleLayoutIcon } from "./module-layout-icon";
// i18n
export const ModuleViewHeader: FC = observer(() => {
export const ModuleViewHeader = observer(function ModuleViewHeader() {
// refs
const inputRef = useRef<HTMLInputElement>(null);
// router

View file

@ -18,7 +18,7 @@ import { useModule } from "@/hooks/store/use-module";
import { useModuleFilter } from "@/hooks/store/use-module-filter";
import { useUserPermissions } from "@/hooks/store/user";
export const ModulesListView: React.FC = observer(() => {
export const ModulesListView = observer(function ModulesListView() {
// router
const { workspaceSlug, projectId } = useParams();
const searchParams = useSearchParams();

View file

@ -36,7 +36,7 @@ type Props = {
customClassName?: string;
};
export const ModuleQuickActions: React.FC<Props> = observer((props) => {
export const ModuleQuickActions = observer(function ModuleQuickActions(props: Props) {
const { parentRef, moduleId, projectId, workspaceSlug, customClassName } = props;
// router
const router = useAppRouter();
@ -161,15 +161,18 @@ export const ModuleQuickActions: React.FC<Props> = observer((props) => {
},
];
const CONTEXT_MENU_ITEMS: TContextMenuItem[] = MENU_ITEMS.map((item) => ({
...item,
onClick: () => {
captureClick({
elementName: MODULE_TRACKER_ELEMENTS.CONTEXT_MENU,
});
item.action();
},
}));
const CONTEXT_MENU_ITEMS = MENU_ITEMS.map(function CONTEXT_MENU_ITEMS(item) {
return {
...item,
onClick: () => {
captureClick({
elementName: MODULE_TRACKER_ELEMENTS.CONTEXT_MENU,
});
item.action();
},
};
});
return (
<>

View file

@ -20,7 +20,7 @@ type Props = {
tabIndex?: number;
};
export const ModuleStatusSelect: React.FC<Props> = ({ control, error, tabIndex }) => {
export function ModuleStatusSelect({ control, error, tabIndex }: Props) {
const { t } = useTranslation();
return (
<Controller
@ -61,4 +61,4 @@ export const ModuleStatusSelect: React.FC<Props> = ({ control, error, tabIndex }
}}
/>
);
};
}

View file

@ -21,7 +21,7 @@ type Props = {
watch: UseFormWatch<Partial<IModule>>;
};
export const SidebarStatusSelect: React.FC<Props> = ({ control, submitChanges, watch }) => {
export function SidebarStatusSelect({ control, submitChanges, watch }: Props) {
const { t } = useTranslation();
return (
<div className="flex flex-wrap items-center py-2">
@ -65,4 +65,4 @@ export const SidebarStatusSelect: React.FC<Props> = ({ control, submitChanges, w
</div>
</div>
);
};
}