import React, { useRef, useState } from "react";
import PropTypes from "prop-types";
import FileUploadButton from "./FileUploadButton";
import DragElement from "./ImageGrid/DragElement";
import FilePlaceholder from "./ImageGrid/FilePlaceholder";
import GridImage from "./ImageGrid/GridImage";
import useToastStore from "../stores/useToastStore";
import { post } from "../lib/request";
import {
createDraggable,
collectionOrder,
useDragCollection,
useDragUploader
} from "./drag";
function filterFiles(files) {
const validMimeTypes = [
"image/gif",
"image/jpeg",
"image/pjpeg",
"image/png",
"image/tiff"
];
return files.filter((f) => validMimeTypes.indexOf(f.type) !== -1);
}
function draggedImageOrder(primaryCollection, imagesCollection, dragState) {
const [primary, ...rest] = collectionOrder(primaryCollection, dragState);
let images = [...rest, ...collectionOrder(imagesCollection, dragState)];
if (
dragState.dragging &&
[primary, ...images].indexOf(dragState.dragging) === -1
) {
if (
dragState.y < imagesCollection.ref.current.getBoundingClientRect().top
) {
images = [dragState.dragging, ...images];
} else {
images.push(dragState.dragging);
}
}
return [primary, images];
}
function initRecords(props) {
const primary = props.enablePrimary
? props.records.filter((r) => r.primary).slice(0, 1)
: [];
return [primary, props.records.filter((r) => primary.indexOf(r) === -1)];
}
export default function ImageGrid(props) {
const [initPrimary, initImages] = initRecords(props);
const primary = useDragCollection(initPrimary);
const images = useDragCollection(initImages);
const [deleted, setDeleted] = useState([]);
const error = useToastStore((state) => state.error);
const containerRef = useRef();
const dispatchAll = (action) => {
primary.dispatch(action);
images.dispatch(action);
};
const dragEnd = (dragState, files) => {
const [draggedPrimary, draggedImages] = draggedImageOrder(
primary,
images,
dragState
);
primary.dispatch({
type: "reorder",
payload: draggedPrimary ? [draggedPrimary] : []
});
images.dispatch({ type: "reorder", payload: draggedImages });
if (files) {
const uploads = filterFiles(files).map((f) => uploadImage(f));
dispatchAll({ type: "insertFiles", payload: uploads });
}
};
const [dragState, dragStart, listeners] = useDragUploader(
[primary, images],
dragEnd
);
const position = (record) => {
return (
[
...primary.draggables.map((d) => d.record),
...images.draggables.map((d) => d.record),
...deleted
].indexOf(record) + 1
);
};
const attrName = (record) => {
return `${props.attribute}[${position(record)}]`;
};
const uploadImage = (file) => {
const draggable = createDraggable({ image: null, file: file });
let data = new FormData();
data.append("image[file]", file);
post("/admin/images.json", data).then((json) => {
if (json.status === "error") {
error("Error uploading image: " + json.error);
dispatchAll({ type: "remove", payload: draggable });
} else {
dispatchAll({
type: "update",
payload: { ...draggable, record: { image: json } }
});
}
});
return draggable;
};
const update = (draggable) => (image) => {
const { record } = draggable;
const updated = {
...draggable,
record: {
...record,
image: { ...record.image, ...image }
}
};
dispatchAll({ type: "update", payload: updated });
};
const remove = (draggable) => () => {
dispatchAll({ type: "remove", payload: draggable });
if (draggable.record.id) {
setDeleted([...deleted, draggable.record]);
}
};
const renderImage = (draggable, isPrimary) => {
const { dragging } = dragState;
if (draggable === "Files") {
return