chore: Update project configuration and enhance code quality
CI / skip-ci-check (push) Successful in 1m27s
CI / skip-ci-check (pull_request) Successful in 1m27s
CI / lint-and-type-check (pull_request) Has been cancelled
CI / python-lint (pull_request) Has been cancelled
CI / test-backend (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / secret-scanning (pull_request) Has been cancelled
CI / dependency-scan (pull_request) Has been cancelled
CI / sast-scan (pull_request) Has been cancelled
CI / workflow-summary (pull_request) Has been cancelled
CI / lint-and-type-check (push) Successful in 2m4s
CI / python-lint (push) Successful in 1m53s
CI / test-backend (push) Successful in 2m37s
CI / build (push) Failing after 2m13s
CI / secret-scanning (push) Successful in 1m40s
CI / dependency-scan (push) Successful in 1m34s
CI / sast-scan (push) Successful in 2m42s
CI / workflow-summary (push) Successful in 1m26s
CI / skip-ci-check (push) Successful in 1m27s
CI / skip-ci-check (pull_request) Successful in 1m27s
CI / lint-and-type-check (pull_request) Has been cancelled
CI / python-lint (pull_request) Has been cancelled
CI / test-backend (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
CI / secret-scanning (pull_request) Has been cancelled
CI / dependency-scan (pull_request) Has been cancelled
CI / sast-scan (pull_request) Has been cancelled
CI / workflow-summary (pull_request) Has been cancelled
CI / lint-and-type-check (push) Successful in 2m4s
CI / python-lint (push) Successful in 1m53s
CI / test-backend (push) Successful in 2m37s
CI / build (push) Failing after 2m13s
CI / secret-scanning (push) Successful in 1m40s
CI / dependency-scan (push) Successful in 1m34s
CI / sast-scan (push) Successful in 2m42s
CI / workflow-summary (push) Successful in 1m26s
This commit modifies the `.gitignore` file to exclude Python library directories while ensuring the viewer-frontend's `lib` directory is not ignored. It also updates the `package.json` to activate the virtual environment during backend tests, improving the testing process. Additionally, the CI workflow is enhanced to prevent duplicate runs for branches with open pull requests. Various components in the viewer frontend are updated to ensure consistent naming conventions and improve type safety. These changes contribute to a cleaner codebase and a more efficient development workflow.
This commit is contained in:
@@ -72,12 +72,12 @@ export function PhotoViewer({ photo, previousId, nextId }: PhotoViewerProps) {
|
||||
router.back();
|
||||
};
|
||||
|
||||
const peopleNames = photo.faces
|
||||
?.map((face) => face.person)
|
||||
.filter((person): person is Person => person !== null)
|
||||
.map((person) => `${person.firstName} ${person.lastName}`.trim()) || [];
|
||||
const peopleNames = (photo as any).faces
|
||||
?.map((face: any) => face.Person)
|
||||
.filter((person: any): person is Person => person !== null)
|
||||
.map((person: Person) => `${person.first_name} ${person.last_name}`.trim()) || [];
|
||||
|
||||
const tags = photo.photoTags?.map((pt) => pt.tag.tagName) || [];
|
||||
const tags = (photo as any).PhotoTagLinkage?.map((pt: any) => pt.Tag.tag_name) || [];
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black">
|
||||
@@ -143,9 +143,9 @@ export function PhotoViewer({ photo, previousId, nextId }: PhotoViewerProps) {
|
||||
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-6 text-white">
|
||||
<div className="container mx-auto">
|
||||
<h2 className="text-xl font-semibold mb-2">{photo.filename}</h2>
|
||||
{photo.dateTaken && (
|
||||
{photo.date_taken && (
|
||||
<p className="text-sm text-gray-300 mb-2">
|
||||
{new Date(photo.dateTaken).toLocaleDateString('en-US', {
|
||||
{new Date(photo.date_taken).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
|
||||
@@ -758,9 +758,10 @@ export function PhotoViewerClient({
|
||||
const face = findFaceAtPoint(e.clientX, e.clientY);
|
||||
|
||||
if (face) {
|
||||
const personName = face.person
|
||||
? `${face.person.firstName} ${face.person.lastName}`.trim()
|
||||
: null;
|
||||
const person = face.person as any;
|
||||
const firstName = person?.first_name || person?.firstName;
|
||||
const lastName = person?.last_name || person?.lastName;
|
||||
const personName = firstName && lastName ? `${firstName} ${lastName}`.trim() : null;
|
||||
|
||||
console.log('[PhotoViewerClient] handleMouseMove: Face detected on hover', {
|
||||
faceId: face.id,
|
||||
@@ -1072,12 +1073,12 @@ export function PhotoViewerClient({
|
||||
}
|
||||
};
|
||||
|
||||
const peopleNames = currentPhoto.faces
|
||||
?.map((face) => face.person)
|
||||
.filter((person): person is Person => person !== null)
|
||||
.map((person) => `${person.firstName} ${person.lastName}`.trim()) || [];
|
||||
const peopleNames = (currentPhoto as any).faces
|
||||
?.map((face: any) => face.Person)
|
||||
.filter((person: any): person is Person => person !== null)
|
||||
.map((person: Person) => `${person.first_name} ${person.last_name}`.trim()) || [];
|
||||
|
||||
const tags = currentPhoto.photoTags?.map((pt) => pt.tag.tagName) || [];
|
||||
const tags = (currentPhoto as any).PhotoTagLinkage?.map((pt: any) => pt.Tag.tag_name) || [];
|
||||
|
||||
const hasPrevious = allPhotos.length > 0 && currentIdx > 0;
|
||||
const hasNext = allPhotos.length > 0 && currentIdx < allPhotos.length - 1;
|
||||
@@ -1481,9 +1482,9 @@ export function PhotoViewerClient({
|
||||
>
|
||||
<div className="container mx-auto p-6 pointer-events-auto">
|
||||
<h2 className="text-xl font-semibold mb-2">{currentPhoto.filename}</h2>
|
||||
{currentPhoto.dateTaken && (
|
||||
{currentPhoto.date_taken && (
|
||||
<p className="text-sm text-gray-300 mb-2">
|
||||
{new Date(currentPhoto.dateTaken).toLocaleDateString('en-US', {
|
||||
{new Date(currentPhoto.date_taken).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
@@ -1522,11 +1523,11 @@ export function PhotoViewerClient({
|
||||
}}
|
||||
faceId={clickedFace.faceId}
|
||||
existingPerson={clickedFace.person ? {
|
||||
firstName: clickedFace.person.firstName,
|
||||
lastName: clickedFace.person.lastName,
|
||||
middleName: clickedFace.person.middleName,
|
||||
maidenName: clickedFace.person.maidenName,
|
||||
dateOfBirth: clickedFace.person.dateOfBirth,
|
||||
firstName: (clickedFace.person as any).first_name || (clickedFace.person as any).firstName,
|
||||
lastName: (clickedFace.person as any).last_name || (clickedFace.person as any).lastName,
|
||||
middleName: (clickedFace.person as any).middle_name || (clickedFace.person as any).middleName,
|
||||
maidenName: (clickedFace.person as any).maiden_name || (clickedFace.person as any).maidenName,
|
||||
dateOfBirth: (clickedFace.person as any).date_of_birth || (clickedFace.person as any).dateOfBirth,
|
||||
} : null}
|
||||
onSave={handleSaveFace}
|
||||
/>
|
||||
|
||||
@@ -44,7 +44,7 @@ export function TagSelectionDialog({
|
||||
return tags;
|
||||
}
|
||||
const query = searchQuery.toLowerCase();
|
||||
return tags.filter((tag) => tag.tagName.toLowerCase().includes(query));
|
||||
return tags.filter((tag) => tag.tag_name.toLowerCase().includes(query));
|
||||
}, [searchQuery, tags]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -93,9 +93,9 @@ export function TagSelectionDialog({
|
||||
setCustomTagInput('');
|
||||
};
|
||||
|
||||
const removeCustomTag = (tagName: string) => {
|
||||
const removeCustomTag = (tag_name: string) => {
|
||||
setCustomTags((prev) =>
|
||||
prev.filter((tag) => tag.toLowerCase() !== tagName.toLowerCase())
|
||||
prev.filter((tag) => tag.toLowerCase() !== tag_name.toLowerCase())
|
||||
);
|
||||
};
|
||||
|
||||
@@ -197,7 +197,7 @@ export function TagSelectionDialog({
|
||||
checked={selectedTagIds.includes(tag.id)}
|
||||
onCheckedChange={() => toggleTagSelection(tag.id)}
|
||||
/>
|
||||
<span className="text-sm">{tag.tagName}</span>
|
||||
<span className="text-sm">{tag.tag_name}</span>
|
||||
</label>
|
||||
))
|
||||
)}
|
||||
@@ -214,7 +214,7 @@ export function TagSelectionDialog({
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
<TagIcon className="h-3 w-3" />
|
||||
{tag.tagName}
|
||||
{tag.tag_name}
|
||||
</Badge>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -24,7 +24,7 @@ export function PeopleFilter({ people, selected, mode, onSelectionChange, onMode
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const filteredPeople = people.filter((person) => {
|
||||
const fullName = `${person.firstName} ${person.lastName}`.toLowerCase();
|
||||
const fullName = `${person.first_name} ${person.last_name}`.toLowerCase();
|
||||
return fullName.includes(searchQuery.toLowerCase());
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ export function PeopleFilter({ people, selected, mode, onSelectionChange, onMode
|
||||
/>
|
||||
</span>
|
||||
<label className="flex-1 cursor-pointer text-sm">
|
||||
{person.firstName} {person.lastName}
|
||||
{person.first_name} {person.last_name}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
@@ -111,7 +111,7 @@ export function PeopleFilter({ people, selected, mode, onSelectionChange, onMode
|
||||
variant="secondary"
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
{person.firstName} {person.lastName}
|
||||
{person.first_name} {person.last_name}
|
||||
<button
|
||||
onClick={() => togglePerson(person.id)}
|
||||
className="ml-1 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
|
||||
@@ -22,8 +22,14 @@ export function TagFilter({ tags, selected, mode, onSelectionChange, onModeChang
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// Helper to safely get tag name, handling potential type mismatches
|
||||
const getTagName = (tag: Tag | any): string => {
|
||||
// Try multiple possible field names
|
||||
return tag.tag_name || tag.tagName || tag.name || '';
|
||||
};
|
||||
|
||||
const filteredTags = tags.filter((tag) => {
|
||||
const tagName = tag.tagName || tag.tag_name || '';
|
||||
const tagName = getTagName(tag);
|
||||
return tagName.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
});
|
||||
|
||||
@@ -91,7 +97,7 @@ export function TagFilter({ tags, selected, mode, onSelectionChange, onModeChang
|
||||
/>
|
||||
</span>
|
||||
<label className="flex-1 cursor-pointer text-sm">
|
||||
{tag.tagName || tag.tag_name || 'Unnamed Tag'}
|
||||
{getTagName(tag) || 'Unnamed Tag'}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
@@ -110,7 +116,7 @@ export function TagFilter({ tags, selected, mode, onSelectionChange, onModeChang
|
||||
variant="secondary"
|
||||
className="flex items-center gap-1"
|
||||
>
|
||||
{tag.tagName || tag.tag_name || 'Unnamed Tag'}
|
||||
{getTagName(tag) || 'Unnamed Tag'}
|
||||
<button
|
||||
onClick={() => toggleTag(tag.id)}
|
||||
className="ml-1 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700"
|
||||
|
||||
Reference in New Issue
Block a user