MingruiZhang commited on
Commit
dfa7532
1 Parent(s): cb6fbf2

feat: class list in project viewer (#29)

Browse files

<img width="1904" alt="image"
src="https://github.com/landing-ai/vision-agent-ui/assets/5669963/ed78e0f0-1bed-4480-aa0d-1d40a3b4d9b2">

app/project/[projectId]/page.tsx CHANGED
@@ -1,6 +1,7 @@
1
  import MediaGrid from '@/components/project/MediaGrid';
2
- import { fetchProjectMedia } from '@/lib/fetch';
3
  import ProjectChat from '@/components/project/ProjectChat';
 
4
 
5
  interface PageProps {
6
  params: {
@@ -11,12 +12,16 @@ interface PageProps {
11
  export default async function Page({ params }: PageProps) {
12
  const { projectId } = params;
13
 
14
- const mediaList = await fetchProjectMedia({ projectId: Number(projectId) });
 
 
 
15
 
16
  return (
17
  <div className="pt-4 md:pt-10 h-full">
18
  <div className="flex h-full">
19
  <div className="w-1/2 relative border-r border-gray-300 overflow-auto">
 
20
  <MediaGrid mediaList={mediaList} />
21
  </div>
22
  <div className="w-1/2 relative overflow-auto">
 
1
  import MediaGrid from '@/components/project/MediaGrid';
2
+ import { fetchProjectClass, fetchProjectMedia } from '@/lib/fetch';
3
  import ProjectChat from '@/components/project/ProjectChat';
4
+ import ClassBar from '@/components/project/ClassBar';
5
 
6
  interface PageProps {
7
  params: {
 
12
  export default async function Page({ params }: PageProps) {
13
  const { projectId } = params;
14
 
15
+ const [mediaList, classList] = await Promise.all([
16
+ fetchProjectMedia({ projectId: Number(projectId) }),
17
+ fetchProjectClass({ projectId: Number(projectId) }),
18
+ ]);
19
 
20
  return (
21
  <div className="pt-4 md:pt-10 h-full">
22
  <div className="flex h-full">
23
  <div className="w-1/2 relative border-r border-gray-300 overflow-auto">
24
+ <ClassBar classList={classList} />
25
  <MediaGrid mediaList={mediaList} />
26
  </div>
27
  <div className="w-1/2 relative overflow-auto">
components/project/ClassBar.tsx ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ClassDetails } from '@/lib/fetch';
2
+ import Chip from '../ui/Chip';
3
+
4
+ export interface ClassBarProps {
5
+ classList: ClassDetails[];
6
+ }
7
+
8
+ export default async function ClassBar({ classList }: ClassBarProps) {
9
+ return (
10
+ <div className="border-b border-gray-300 px-3 pb-3 max-w-3xl mx-auto">
11
+ {classList.map(classItem => {
12
+ return (
13
+ <Chip
14
+ key={classItem.id}
15
+ value={classItem.name}
16
+ className="px-3 py-1 my-1"
17
+ />
18
+ );
19
+ })}
20
+ </div>
21
+ );
22
+ }
components/project/MediaGrid.tsx CHANGED
@@ -7,8 +7,8 @@ export default function MediaGrid({
7
  mediaList: MediaDetails[];
8
  }) {
9
  return (
10
- <div className="relative size-full p-6 max-w-3xl mx-auto">
11
- <div className="columns-1 sm:columns-1 md:columns-2 lg:columns-2 xl:columns:3 gap-4 [&>img:not(:first-child)]:mt-4">
12
  {mediaList.map(media => (
13
  <MediaTile key={media.id} media={media} />
14
  ))}
 
7
  mediaList: MediaDetails[];
8
  }) {
9
  return (
10
+ <div className="relative size-full p-3 max-w-3xl mx-auto">
11
+ <div className="columns-1 sm:columns-1 md:columns-2 lg:columns-2 xl:columns:3 gap-3 [&>img:not(:first-child)]:mt-3">
12
  {mediaList.map(media => (
13
  <MediaTile key={media.id} media={media} />
14
  ))}
components/ui/Chip.tsx CHANGED
@@ -7,14 +7,17 @@ export interface ChipProps {
7
  className?: string;
8
  }
9
 
10
- const Chip: React.FC<ChipProps> = ({ label, value, className, color }) => {
 
 
 
 
 
11
  return (
12
  <div
13
  className={cn(
14
- `inline-flex items-center px-1.5 rounded-full text-xs bg-gray-100 text-gray-500 mr-2`,
15
- color === 'blue' && 'bg-blue-100 text-blue-500',
16
- color === 'yellow' && 'bg-yellow-100 text-yellow-500',
17
- color === 'purple' && 'bg-purple-100 text-purple-500',
18
  className,
19
  )}
20
  >
 
7
  className?: string;
8
  }
9
 
10
+ const Chip: React.FC<ChipProps> = ({
11
+ label,
12
+ value,
13
+ className,
14
+ color = 'gray',
15
+ }) => {
16
  return (
17
  <div
18
  className={cn(
19
+ 'inline-flex items-center px-1.5 rounded-full text-xs mr-2',
20
+ `bg-${color}-100 text-${color}-500`,
 
 
21
  className,
22
  )}
23
  >
lib/fetch/index.ts CHANGED
@@ -121,3 +121,23 @@ export const fetchProjectMedia = clefApiBuilder<
121
  { projectId: number },
122
  MediaDetails[]
123
  >('api/admin/vision-agent/project/media');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  { projectId: number },
122
  MediaDetails[]
123
  >('api/admin/vision-agent/project/media');
124
+
125
+ export type ClassDetails = {
126
+ id: number;
127
+ name: string;
128
+ descriptionText?: string | null;
129
+ orgId: number;
130
+ projectId: number;
131
+ createdAt: string;
132
+ updatedAt: string | null;
133
+ color?: string | null;
134
+ };
135
+
136
+ /**
137
+ * Fetch all active classes of a given project
138
+ * @author https://github.com/landing-ai/landing-platform/blob/mingrui-04-08-meaningful-project/packages/server-clef/src/main_app/controllers/admin/get_admin_meaningful_project_controller.ts
139
+ */
140
+ export const fetchProjectClass = clefApiBuilder<
141
+ { projectId: number },
142
+ ClassDetails[]
143
+ >('api/admin/vision-agent/project/class');