mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-14 22:52:15 +02:00
restore custom actions API service and wire to ActionPicker
This commit is contained in:
parent
041401aefc
commit
11374248d8
3 changed files with 114 additions and 1 deletions
|
|
@ -21,6 +21,8 @@ import {
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
|
|
||||||
|
import type { QuickAskActionRead } from "@/contracts/types/quick-ask-actions.types";
|
||||||
|
import { quickAskActionsApiService } from "@/lib/apis/quick-ask-actions-api.service";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
export interface ActionPickerRef {
|
export interface ActionPickerRef {
|
||||||
|
|
@ -62,11 +64,24 @@ const DEFAULT_ACTIONS: { name: string; prompt: string; mode: "transform" | "expl
|
||||||
export const ActionPicker = forwardRef<ActionPickerRef, ActionPickerProps>(
|
export const ActionPicker = forwardRef<ActionPickerRef, ActionPickerProps>(
|
||||||
function ActionPicker({ onSelect, onDone, externalSearch = "", containerStyle }, ref) {
|
function ActionPicker({ onSelect, onDone, externalSearch = "", containerStyle }, ref) {
|
||||||
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
||||||
|
const [customActions, setCustomActions] = useState<QuickAskActionRead[]>([]);
|
||||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const shouldScrollRef = useRef(false);
|
const shouldScrollRef = useRef(false);
|
||||||
const itemRefs = useRef<Map<number, HTMLButtonElement>>(new Map());
|
const itemRefs = useRef<Map<number, HTMLButtonElement>>(new Map());
|
||||||
|
|
||||||
const allActions = DEFAULT_ACTIONS;
|
useEffect(() => {
|
||||||
|
quickAskActionsApiService.list().then(setCustomActions).catch(() => {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const allActions = useMemo(() => {
|
||||||
|
const customs = customActions.map((a) => ({
|
||||||
|
name: a.name,
|
||||||
|
prompt: a.prompt,
|
||||||
|
mode: a.mode as "transform" | "explore",
|
||||||
|
icon: a.icon || "zap",
|
||||||
|
}));
|
||||||
|
return [...DEFAULT_ACTIONS, ...customs];
|
||||||
|
}, [customActions]);
|
||||||
|
|
||||||
const filtered = useMemo(() => {
|
const filtered = useMemo(() => {
|
||||||
if (!externalSearch) return allActions;
|
if (!externalSearch) return allActions;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,44 @@
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
export type QuickAskActionMode = "transform" | "explore";
|
export type QuickAskActionMode = "transform" | "explore";
|
||||||
|
|
||||||
|
export const quickAskActionRead = z.object({
|
||||||
|
id: z.number(),
|
||||||
|
name: z.string(),
|
||||||
|
prompt: z.string(),
|
||||||
|
mode: z.enum(["transform", "explore"]),
|
||||||
|
icon: z.string().nullable(),
|
||||||
|
search_space_id: z.number().nullable(),
|
||||||
|
created_at: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type QuickAskActionRead = z.infer<typeof quickAskActionRead>;
|
||||||
|
|
||||||
|
export const quickAskActionsListResponse = z.array(quickAskActionRead);
|
||||||
|
|
||||||
|
export const quickAskActionCreateRequest = z.object({
|
||||||
|
name: z.string().min(1).max(200),
|
||||||
|
prompt: z.string().min(1),
|
||||||
|
mode: z.enum(["transform", "explore"]),
|
||||||
|
icon: z.string().max(50).nullable().optional(),
|
||||||
|
search_space_id: z.number().nullable().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type QuickAskActionCreateRequest = z.infer<typeof quickAskActionCreateRequest>;
|
||||||
|
|
||||||
|
export const quickAskActionUpdateRequest = z.object({
|
||||||
|
name: z.string().min(1).max(200).optional(),
|
||||||
|
prompt: z.string().min(1).optional(),
|
||||||
|
mode: z.enum(["transform", "explore"]).optional(),
|
||||||
|
icon: z.string().max(50).nullable().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type QuickAskActionUpdateRequest = z.infer<typeof quickAskActionUpdateRequest>;
|
||||||
|
|
||||||
|
export const quickAskActionDeleteResponse = z.object({
|
||||||
|
success: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
export interface QuickAskAction {
|
export interface QuickAskAction {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|
|
||||||
59
surfsense_web/lib/apis/quick-ask-actions-api.service.ts
Normal file
59
surfsense_web/lib/apis/quick-ask-actions-api.service.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import {
|
||||||
|
type QuickAskActionCreateRequest,
|
||||||
|
type QuickAskActionUpdateRequest,
|
||||||
|
quickAskActionCreateRequest,
|
||||||
|
quickAskActionDeleteResponse,
|
||||||
|
quickAskActionRead,
|
||||||
|
quickAskActionUpdateRequest,
|
||||||
|
quickAskActionsListResponse,
|
||||||
|
} from "@/contracts/types/quick-ask-actions.types";
|
||||||
|
import { ValidationError } from "@/lib/error";
|
||||||
|
import { baseApiService } from "./base-api.service";
|
||||||
|
|
||||||
|
class QuickAskActionsApiService {
|
||||||
|
list = async (searchSpaceId?: number) => {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (searchSpaceId !== undefined) {
|
||||||
|
params.set("search_space_id", String(searchSpaceId));
|
||||||
|
}
|
||||||
|
const queryString = params.toString();
|
||||||
|
const url = queryString
|
||||||
|
? `/api/v1/quick-ask-actions?${queryString}`
|
||||||
|
: "/api/v1/quick-ask-actions";
|
||||||
|
|
||||||
|
return baseApiService.get(url, quickAskActionsListResponse);
|
||||||
|
};
|
||||||
|
|
||||||
|
create = async (request: QuickAskActionCreateRequest) => {
|
||||||
|
const parsed = quickAskActionCreateRequest.safeParse(request);
|
||||||
|
if (!parsed.success) {
|
||||||
|
const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", ");
|
||||||
|
throw new ValidationError(`Invalid request: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseApiService.post("/api/v1/quick-ask-actions", quickAskActionRead, {
|
||||||
|
body: parsed.data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
update = async (actionId: number, request: QuickAskActionUpdateRequest) => {
|
||||||
|
const parsed = quickAskActionUpdateRequest.safeParse(request);
|
||||||
|
if (!parsed.success) {
|
||||||
|
const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", ");
|
||||||
|
throw new ValidationError(`Invalid request: ${errorMessage}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseApiService.put(`/api/v1/quick-ask-actions/${actionId}`, quickAskActionRead, {
|
||||||
|
body: parsed.data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
delete = async (actionId: number) => {
|
||||||
|
return baseApiService.delete(
|
||||||
|
`/api/v1/quick-ask-actions/${actionId}`,
|
||||||
|
quickAskActionDeleteResponse
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const quickAskActionsApiService = new QuickAskActionsApiService();
|
||||||
Loading…
Add table
Add a link
Reference in a new issue