Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.20",
"babel-jest": "^29.7.0",
"baseline-browser-mapping": "^2.9.11",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if baseline-browser-mapping is referenced anywhere in the codebase

echo "Searching for baseline-browser-mapping usage in source files..."
rg -n "baseline-browser-mapping" --type ts --type tsx --type js --type json -g '!package*.json'

echo -e "\nSearching for any imports or requires of this package..."
rg -n "from ['\"]baseline-browser-mapping['\"]" --type ts --type tsx --type js
rg -n "require\(['\"]baseline-browser-mapping['\"]\)" --type ts --type tsx --type js

echo -e "\nChecking package.json references..."
rg -n "baseline-browser-mapping" frontend/package.json

Repository: AOSSIE-Org/PictoPy

Length of output: 367


Remove the unused baseline-browser-mapping devDependency.

The package is added to package.json but is not imported or used anywhere in the codebase. Unused dependencies bloat the project and increase build time. Either use this package as part of the collapsible folder feature or remove it from package.json.

🤖 Prompt for AI Agents
In @frontend/package.json at line 91, The devDependency
"baseline-browser-mapping" is unused and should be removed to avoid bloat; edit
package.json to delete the "baseline-browser-mapping": "^2.9.11" entry from the
devDependencies (or, if you intend to keep it, add actual imports/usages where
the collapsible folder or related code references baseline-browser-mapping so
the package is justified), then run package manager prune/install to update
lockfile.

"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-config-react-app": "^7.0.1",
Expand Down
204 changes: 114 additions & 90 deletions frontend/src/pages/SettingsPage/components/FolderManagementCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Folder, Trash2, Check } from 'lucide-react';
import { Folder, Trash2, Check, ChevronDown, ChevronUp } from 'lucide-react';
import { useState } from 'react';

import { Switch } from '@/components/ui/switch';
import { Button } from '@/components/ui/button';
Expand All @@ -25,6 +26,8 @@ const FolderManagementCard: React.FC = () => {
deleteFolderPending,
} = useFolderOperations();

const [isExpanded, setIsExpanded] = useState(true);

const taggingStatus = useSelector(
(state: RootState) => state.folders.taggingStatus,
);
Expand All @@ -34,103 +37,124 @@ const FolderManagementCard: React.FC = () => {
icon={Folder}
title="Folder Management"
description="Configure your photo library folders and AI settings"
action={
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0"
onClick={() => setIsExpanded(!isExpanded)}
>
{isExpanded ? (
<ChevronUp className="h-4 w-4" />
) : (
<ChevronDown className="h-4 w-4" />
)}
</Button>
}
>
{folders.length > 0 ? (
<div className="space-y-3">
{folders.map((folder: FolderDetails, index: number) => (
<div
key={index}
className="group border-border bg-background/50 relative rounded-lg border p-4 transition-all hover:border-gray-300 hover:shadow-sm dark:hover:border-gray-600"
>
<div className="flex items-center justify-between">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-3">
<Folder className="h-4 w-4 flex-shrink-0 text-gray-500 dark:text-gray-400" />
<span className="text-foreground truncate">
{folder.folder_path}
</span>
</div>
</div>
{isExpanded && (
<div className="animate-in fade-in slide-in-from-top-2 duration-200">
{folders.length > 0 ? (
<div className="space-y-3">
{folders.map((folder: FolderDetails, index: number) => (
<div
key={index}
className="group border-border bg-background/50 relative rounded-lg border p-4 transition-all hover:border-gray-300 hover:shadow-sm dark:hover:border-gray-600"
>
<div className="flex items-center justify-between">
<div className="min-w-0 flex-1">
<div className="flex items-center gap-3">
<Folder className="h-4 w-4 flex-shrink-0 text-gray-500 dark:text-gray-400" />
<span className="text-foreground truncate">
{folder.folder_path}
</span>
</div>
</div>

<div className="ml-4 flex items-center gap-4">
<div className="flex items-center gap-3">
<span className="text-muted-foreground text-sm">
AI Tagging
</span>
<Switch
className="cursor-pointer"
checked={folder.AI_Tagging}
onCheckedChange={() => toggleAITagging(folder)}
disabled={
enableAITaggingPending || disableAITaggingPending
}
/>
</div>

<Button
onClick={() => deleteFolder(folder.folder_id)}
variant="outline"
size="sm"
className="h-8 w-8 cursor-pointer text-gray-500 hover:border-red-300 hover:text-red-600 dark:text-gray-400 dark:hover:text-red-400"
disabled={deleteFolderPending}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
<div className="ml-4 flex items-center gap-4">
<div className="flex items-center gap-3">
<span className="text-muted-foreground text-sm">
AI Tagging
</span>
<Switch
className="cursor-pointer"
checked={folder.AI_Tagging}
onCheckedChange={() => toggleAITagging(folder)}
disabled={
enableAITaggingPending || disableAITaggingPending
}
/>
</div>

{folder.AI_Tagging && (
<div className="mt-3">
<div className="text-muted-foreground mb-1 flex items-center justify-between text-xs">
<span>AI Tagging Progress</span>
<span
className={
(taggingStatus[folder.folder_id]?.tagging_percentage ??
0) >= 100
? 'flex items-center gap-1 text-green-500'
: 'text-muted-foreground'
}
>
{(taggingStatus[folder.folder_id]?.tagging_percentage ??
0) >= 100 && <Check className="h-3 w-3" />}
{Math.round(
taggingStatus[folder.folder_id]?.tagging_percentage ??
0,
)}
%
</span>
<Button
onClick={() => deleteFolder(folder.folder_id)}
variant="outline"
size="sm"
className="h-8 w-8 cursor-pointer text-gray-500 hover:border-red-300 hover:text-red-600 dark:text-gray-400 dark:hover:text-red-400"
disabled={deleteFolderPending}
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</div>
<Progress
value={
taggingStatus[folder.folder_id]?.tagging_percentage ?? 0
}
indicatorClassName={
(taggingStatus[folder.folder_id]?.tagging_percentage ??
0) >= 100
? 'bg-green-500'
: 'bg-blue-500'
}
/>

{folder.AI_Tagging && (
<div className="mt-3">
<div className="text-muted-foreground mb-1 flex items-center justify-between text-xs">
<span>AI Tagging Progress</span>
<span
className={
(taggingStatus[folder.folder_id]
?.tagging_percentage ?? 0) >= 100
? 'flex items-center gap-1 text-green-500'
: 'text-muted-foreground'
}
>
{(taggingStatus[folder.folder_id]
?.tagging_percentage ?? 0) >= 100 && (
<Check className="h-3 w-3" />
)}
{Math.round(
taggingStatus[folder.folder_id]
?.tagging_percentage ?? 0,
)}
%
</span>
</div>
<Progress
value={
taggingStatus[folder.folder_id]?.tagging_percentage ??
0
}
indicatorClassName={
(taggingStatus[folder.folder_id]
?.tagging_percentage ?? 0) >= 100
? 'bg-green-500'
: 'bg-blue-500'
}
/>
</div>
)}
</div>
)}
))}
</div>
))}
</div>
) : (
<div className="py-8 text-center">
<Folder className="mx-auto mb-3 h-12 w-12 text-gray-400" />
<h3 className="text-foreground mb-1 text-lg font-medium">
No folders configured
</h3>
<p className="text-muted-foreground text-sm">
Add your first photo library folder to get started
</p>
) : (
<div className="py-8 text-center">
<Folder className="mx-auto mb-3 h-12 w-12 text-gray-400" />
<h3 className="text-foreground mb-1 text-lg font-medium">
No folders configured
</h3>
<p className="text-muted-foreground text-sm">
Add your first photo library folder to get started
</p>
</div>
)}

<div className="border-border mt-6 border-t pt-6">
<FolderPicker />
</div>
</div>
)}

<div className="border-border mt-6 border-t pt-6">
<FolderPicker />
</div>
</SettingsCard>
);
};
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/pages/SettingsPage/components/SettingsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ interface SettingsCardProps {
* Card description
*/
description?: string;
/**
* Optional action element to display in the header
*/
action?: React.ReactNode;
/**
* Card content
*/
Expand All @@ -27,6 +31,7 @@ const SettingsCard: React.FC<SettingsCardProps> = ({
icon: Icon,
title,
description,
action,
children,
}) => {
return (
Expand All @@ -39,6 +44,7 @@ const SettingsCard: React.FC<SettingsCardProps> = ({
<p className="text-muted-foreground text-sm">{description}</p>
)}
</div>
{action && <div className="ml-auto">{action}</div>}
</div>
{children}
</div>
Expand Down