app/javascript/components/Attachments/List.tsx
import Attachment from "./Attachment";import Deleted from "./Deleted";import Placeholder from "./Placeholder";import FileUploadButton from "../FileUploadButton";import { post } from "../../lib/request";import * as Attachments from "../../types/Attachments";import * as Drag from "../../types/Drag"; import { createDraggable, draggedOrder, useDragUploader } from "../drag"; type Props = Attachments.Options & { state: Attachments.State;}; function filenameToName(str: string): string { return str.replace(/\.[\w\d]+$/, "").replace(/_/g, " ");} Function `List` has 121 lines of code (exceeds 25 allowed). Consider refactoring.
Function `List` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.export default function List(props: Props) { const { collection, deleted, setDeleted } = props.state; const locales = props.locales ? Object.keys(props.locales) : [props.locale]; const uploadAttachment = (file: File) => { const name = {}; locales.forEach((l) => (name[l] = file.name)); const draggable = createDraggable<Attachments.Record>({ attachment: { filename: file.name, name: name }, uploading: true }); const data = new FormData(); data.append("attachment[file]", file); locales.forEach((l) => { data.append(`attachment[name][${l}]`, filenameToName(file.name)); }); void post("/admin/attachments.json", data).then( (json: Attachments.Resource) => { collection.dispatch({ type: "update", payload: { ...draggable, record: { attachment: json, uploading: false } } }); } ); return draggable; }; const receiveFiles = (files: File[]) => { collection.dispatch({ type: "append", payload: files.map((f) => uploadAttachment(f)) }); }; const dragEnd = ( dragState: Drag.State<Attachments.Record>, files: File[] ) => { collection.dispatch({ type: "reorder", payload: draggedOrder(collection, dragState) }); collection.dispatch({ type: "insertFiles", payload: files.map((f) => uploadAttachment(f)) }); }; const [dragState, dragStart, listeners] = useDragUploader( [collection], dragEnd ); const position = (record: Attachments.Record) => { return ( [ ...collection.draggables.map( (d: Drag.Draggable<Attachments.Record>) => d.record ), ...deleted ].indexOf(record) + 1 ); }; Similar blocks of code found in 2 locations. Consider refactoring. const attrName = (record: Attachments.Record) => { return `${props.attribute}[${position(record)}]`; }; const update = (draggable: Drag.Draggable<Attachments.Record>) => (attachment: Partial<Attachments.Resource>) => { const { record } = draggable; const updated = { ...draggable, record: { ...record, attachment: { ...record.attachment, ...attachment } } }; collection.dispatch({ type: "update", payload: updated }); }; const remove = (draggable: Drag.Draggable<Attachments.Record>) => () => { collection.dispatch({ type: "remove", payload: draggable }); if (draggable.record.id) { setDeleted([...deleted, draggable.record]); } }; const attachment = (draggable: Drag.DraggableOrFiles<Attachments.Record>) => { const { dragging } = dragState; if (draggable === "Files") { return <Placeholder key="placeholder" />; } return ( <Attachment key={draggable.handle} draggable={draggable} locale={props.locale} locales={props.locales} showEmbed={props.showEmbed} startDrag={dragStart} position={position(draggable.record)} onUpdate={update(draggable)} deleteRecord={remove(draggable)} attributeName={attrName(draggable.record)} placeholder={dragging && dragging == draggable} /> ); }; const dragOrder = draggedOrder(collection, dragState); const classes = ["attachments"]; if (dragState.dragging) { classes.push("dragover"); } return ( <div className={classes.join(" ")} ref={collection.ref} {...listeners}> <div className="files">{dragOrder.map((d) => attachment(d))}</div> <Deleted attributeName={attrName} deleted={deleted} /> <div className="drop-target"> <FileUploadButton multiple={true} multiline={true} callback={receiveFiles} /> </div> </div> );}