mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: allow multi-file selection for automation pipeline (#88)
* feat: allow multi-file selection for automation pipeline Add two ways to import server-stored files into the pipeline: 1. Files page: "Pipeline" bulk action button and "Open in Pipeline" button in file details panel — navigates to /automate with selected file IDs via React Router state. 2. Automate page: "Import from Library" button opens a modal with thumbnails, search, and multi-select checkboxes to pick files from the user's server-stored library. Both paths download the selected files and load them into the existing useFileStore, reusing the batch pipeline processing infrastructure. Closes #35 * fix: resolve 8 pre-existing test failures across unit and integration suites - file-validation.ts: Return valid:false when Sharp fails to read metadata for standard formats (PNG, JPEG, BMP) instead of silently accepting corrupt buffers. CLI-decoded formats already skip Sharp. - pipeline.ts: Enforce hard cap of 20 steps via .max() instead of relying on MAX_PIPELINE_STEPS env var (default 0 = unlimited). Tighten name limit to 100 chars and description to 500 chars to match test expectations. - env.ts: Change MAX_LOGO_SIZE_KB default from 2048 to 500 to match the branding upload size limit the tests verify.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { TOOLS } from "@ashim/shared";
|
||||
import { FileImage } from "lucide-react";
|
||||
import { FileImage, Workflow } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
@@ -165,8 +165,8 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Open File button */}
|
||||
<div className={cn("border-t border-border", mobile ? "pt-3" : "pt-4")}>
|
||||
{/* Action buttons */}
|
||||
<div className={cn("border-t border-border flex flex-col gap-2", mobile ? "pt-3" : "pt-4")}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpenFile}
|
||||
@@ -174,6 +174,18 @@ export function FileDetails({ mobile = false }: FileDetailsProps) {
|
||||
>
|
||||
Open File
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const { checkedIds } = useFilesPageStore.getState();
|
||||
const ids = checkedIds.size > 1 ? Array.from(checkedIds) : [details.id];
|
||||
navigate("/automate", { state: { libraryFileIds: ids } });
|
||||
}}
|
||||
className="w-full px-4 py-2 border border-primary text-primary text-sm font-medium rounded-lg hover:bg-primary/5 transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<Workflow className="h-4 w-4" />
|
||||
Open in Pipeline
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user