Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add : search pipe history #1389

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
25 changes: 25 additions & 0 deletions pipes/search/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ body {
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--radius: 0.5rem;
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
.dark {
--background: 0 0% 3.9%;
Expand All @@ -59,6 +67,14 @@ body {
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--sidebar-background: 240 5.9% 10%;
--sidebar-foreground: 240 4.8% 95.9%;
--sidebar-primary: 224.3 76.3% 48%;
--sidebar-primary-foreground: 0 0% 100%;
--sidebar-accent: 240 3.7% 15.9%;
--sidebar-accent-foreground: 240 4.8% 95.9%;
--sidebar-border: 240 3.7% 15.9%;
--sidebar-ring: 217.2 91.2% 59.8%;
}
}

Expand All @@ -81,3 +97,12 @@ body {
transform: translate(-50%, -50%) !important;
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

21 changes: 17 additions & 4 deletions pipes/search/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { Toaster } from "@/components/ui/toaster";
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
import { HistorySidebar } from "@/components/history-sidebar"

const geistSans = Geist({
variable: "--font-geist-sans",
Expand All @@ -27,11 +29,22 @@ export default function RootLayout({
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
className={`${geistSans.variable} ${geistMono.variable} antialiased `}
>
{children}

<Toaster />
<SidebarProvider defaultOpen={true}>
<div className="flex w-full h-full">
<div className="absolute left-0 top-0 h-full z-[9000]">
<HistorySidebar />
</div>
<div className="fixed left-0 top-2 z-[10000] ">
<SidebarTrigger />
</div>
<div className="flex-1 overflow-auto">
{children}
</div>
</div>
</SidebarProvider>
<Toaster />
</body>
</html>
);
Expand Down
31 changes: 16 additions & 15 deletions pipes/search/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ import { useSettings } from "@/lib/hooks/use-settings";
import { Terminal } from "lucide-react";
import { SearchChat } from "@/components/search-chat";


export default function SearchPage() {

const { settings } = useSettings();
const aiDisabled = settings.aiProviderType === "screenpipe-cloud" && !settings.user.token;

return (
<div className={`flex flex-col gap-4 items-center justify-center h-full ${aiDisabled ? "mt-2" : "mt-12"}`}>
{aiDisabled &&(
<Alert className="w-[70%] shadow-sm">
<Terminal className="h-4 w-4" />
<AlertTitle>heads up!</AlertTitle>
<AlertDescription className="text-muted-foreground">
your ai provider is set to &apos;screenpipe-cloud&apos; and you don&apos;t have logged in <br/>
please login to use this pipe, go to app &gt; settings &gt; login
</AlertDescription>
</Alert>
)}
<p className="text-2xl font-bold">where pixels become magic</p>
<SearchChat />
</div>
<>
<div className={`flex flex-col gap-4 items-center justify-center h-full ${aiDisabled ? "mt-2" : "mt-12"}`}>
{aiDisabled && (
<Alert className="w-[70%] shadow-sm">
<Terminal className="h-4 w-4" />
<AlertTitle>heads up!</AlertTitle>
<AlertDescription className="text-muted-foreground">
your ai provider is set to &apos;screenpipe-cloud&apos; and you don&apos;t have logged in <br />
please login to use this pipe, go to app &gt; settings &gt; login
</AlertDescription>
</Alert>
)}
<p className="text-2xl font-bold">where pixels become magic</p>
<SearchChat />
</div>
</>
);
}
148 changes: 148 additions & 0 deletions pipes/search/src/components/history-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
"use client";
import React, { useEffect, useState } from "react";
import { Plus, Trash2 } from "lucide-react";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarGroupAction,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarHeader,
} from "@/components/ui/sidebar";
import { SearchForm } from "@/components/search-form";
import { listHistory, HistoryItem, deleteHistoryItem } from "@/hooks/actions/history";


export function HistorySidebar() {
const [todayItems, setTodayItems] = useState<HistoryItem[]>([]);
const [yesterdayItems, setYesterdayItems] = useState<HistoryItem[]>([]);
const [previous7DaysItems, setPrevious7DaysItems] = useState<HistoryItem[]>([]);
const [searchQuery, setSearchQuery] = useState("");
useEffect(() => {
const handleHistoryUpdate = () => {
fetchHistory();
};
window.addEventListener("historyCreated", handleHistoryUpdate);
return () => {
window.removeEventListener("historyCreated", handleHistoryUpdate);
};
}, []);
const fetchHistory = async () => {
const history: HistoryItem[] = await listHistory();
history.sort((a: HistoryItem, b: HistoryItem) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
const today = new Date();
const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
const sevenDaysAgo = new Date(today);
sevenDaysAgo.setDate(today.getDate() - 7);

const todayItems: HistoryItem[] = [];
const yesterdayItems: HistoryItem[] = [];
const previous7DaysItems: HistoryItem[] = [];

history.forEach((item: HistoryItem) => {
const itemDate = new Date(item.timestamp);
if (itemDate.toDateString() === today.toDateString()) {
todayItems.push(item);
} else if (itemDate.toDateString() === yesterday.toDateString()) {
yesterdayItems.push(item);
} else if (itemDate >= sevenDaysAgo && itemDate < today) {
previous7DaysItems.push(item);
}
});

setTodayItems(todayItems);
setYesterdayItems(yesterdayItems);
setPrevious7DaysItems(previous7DaysItems);
};

useEffect(() => {
fetchHistory();
}, []);

const handleDeleteHistory = async (id: string) => {
await deleteHistoryItem(id);
fetchHistory();
};
const handleHistoryClick = (id: string) => {
localStorage.setItem("historyId", id);
window.dispatchEvent(new Event("historyUpdated"));
};

const handleNewChat = () => {
localStorage.removeItem('historyId');
location.reload();
};
const handleSearchChange = (event: React.FormEvent<HTMLFormElement>) => {
const target = event.target as HTMLInputElement;
setSearchQuery(target.value);
};
const filterItems = (items: HistoryItem[]) => {
return items.filter(item => item.title.toLowerCase().includes(searchQuery.toLowerCase()));
};

const renderHistoryItems = (items: HistoryItem[]) => (
filterItems(items).map(item => (
<SidebarMenuItem key={item.id}>
<SidebarMenuButton asChild>
<div className="p-1">
<a className="" href="#" onClick={() => handleHistoryClick(item.id)}>
<span>{item.title.substring(0, 30)}...</span>
</a>
<Trash2
className="absolute right-0 ml-2 cursor-pointer"
onClick={() => handleDeleteHistory(item.id)}
/>
</div>
</SidebarMenuButton>
</SidebarMenuItem>
))
);

return (
<Sidebar >
<SidebarHeader>
<div className="pl-4">
<SearchForm onChange={handleSearchChange} />
</div>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Today</SidebarGroupLabel>
<SidebarGroupAction title="New Chat" onClick={handleNewChat} >
<Plus /> <span className="sr-only">New Chat</span>
</SidebarGroupAction>
<SidebarGroupContent>
<SidebarMenu>
{renderHistoryItems(todayItems)}
</SidebarMenu>
</SidebarGroupContent>
{yesterdayItems.length > 0 && (
<>
<SidebarGroupLabel>Yesterday</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{renderHistoryItems(yesterdayItems)}
</SidebarMenu>
</SidebarGroupContent>
</>
)}
{previous7DaysItems.length > 0 && (
<>
< SidebarGroupLabel > Previous 7 days</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{renderHistoryItems(previous7DaysItems)}
</SidebarMenu>
</SidebarGroupContent>
</>
)}
</SidebarGroup>
</SidebarContent>
</Sidebar >
);
}
Loading
Loading