Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2794f7d
Initial UI Commit
CodeByKarthik May 29, 2025
5243fe7
Added Condition Logic & Comments
CodeByKarthik May 29, 2025
627629f
Changes Button Name & Size
CodeByKarthik May 30, 2025
da5c8ad
Added comments for upcoming works
CodeByKarthik Jun 2, 2025
c173261
Testing Commit
CodeByKarthik Jun 23, 2025
4a59239
Test Commit docker
CodeByKarthik Jun 23, 2025
d76aa8f
Merge branch 'master' into Frontend-UI-for-AI-Mapping-Suggestions
AndrewThien Jun 24, 2025
8b26983
modify constants and vars
AndrewThien Jun 24, 2025
56d797a
fix and move API
AndrewThien Jun 24, 2025
ff43c70
fix and move recommendation components
AndrewThien Jun 24, 2025
30dba10
add columns for table inside dialog
AndrewThien Jun 24, 2025
5d514de
add type for AI recommendations
AndrewThien Jun 24, 2025
b82fed5
clean up
AndrewThien Jun 24, 2025
aa76c7b
modify request
AndrewThien Jun 24, 2025
e10982c
clean up magic ui
AndrewThien Jun 24, 2025
6f7a1fb
add apply concept
AndrewThien Jun 24, 2025
d26c1da
add variable
AndrewThien Jun 24, 2025
fdab92d
update info
AndrewThien Jun 24, 2025
4b23744
update endpoint to use vocab
AndrewThien Jun 24, 2025
168710b
improve tooltip
AndrewThien Jun 24, 2025
e71bd14
enable choosing vocab for searching
AndrewThien Jun 24, 2025
9ef35fe
improve details line
AndrewThien Jun 24, 2025
78abce6
add accuracy and improve
AndrewThien Jun 24, 2025
1c15516
add vocab constants
AndrewThien Jun 24, 2025
da23563
improve component structure
AndrewThien Jun 24, 2025
cd533da
swap vocab for domain
AndrewThien Jun 24, 2025
0e1c98a
add link to Athena to value's name
AndrewThien Jun 25, 2025
d5909a3
modify tooltips
AndrewThien Jun 25, 2025
6b01f4e
update text
AndrewThien Jun 25, 2025
12942c4
make domains based on allowed domains
AndrewThien Jun 25, 2025
7883532
add side for tooltip
AndrewThien Jun 25, 2025
9420cc6
move unsion base url out
AndrewThien Jun 25, 2025
9bd42e9
fix naming
AndrewThien Jun 25, 2025
7cbc456
add ai suggestions at the field level
AndrewThien Jun 25, 2025
f942d39
centralise env vars
AndrewThien Jun 25, 2025
3212058
clean up
AndrewThien Jun 25, 2025
b4eaf41
remove tooltips provider at layout
AndrewThien Jun 25, 2025
b1bd935
update tooltips content
AndrewThien Jun 25, 2025
3eddd10
add max h for dialog
AndrewThien Jun 25, 2025
cf5db3d
Merge branch 'master' into Frontend-UI-for-AI-Mapping-Suggestions
AndrewThien Jun 25, 2025
25cc45e
add env var to workflow
AndrewThien Jun 25, 2025
761fbb0
fix the workflow's env var
AndrewThien Jun 25, 2025
e97e011
revert workflow change
AndrewThien Jun 25, 2025
8424820
fix contentType at field and value level
AndrewThien Jun 25, 2025
9f18455
Merge branch 'master' into Frontend-UI-for-AI-Mapping-Suggestions
AndrewThien Jun 26, 2025
e94ad1e
update naming to camel case
AndrewThien Jun 26, 2025
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
37 changes: 37 additions & 0 deletions app/next-client-app/api/recommendations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"use server";

import request from "@/lib/api/request";
import {
unisonBaseUrl,
unisonApiKey,
recommendationService,
} from "@/constants";
import { UnisonConceptResponse } from "@/types/recommendation";

export const getConceptRecommendationsUnison = async (
// Unison can query by concept name, or concept code (exact match).
// The latter is used first in searching, then the former.
queryValue: string,
domainId: string
): Promise<UnisonConceptResponse> => {
try {
if (recommendationService === "unison") {
const endpoint = `${queryValue}?apiKey=${unisonApiKey}&domain=${domainId}`;
return await request<UnisonConceptResponse>(endpoint, {
baseUrl: unisonBaseUrl,
headers: {
Accept: "application/json",
},
});
}
// TODO: Implement Lettuce recommendation service
else if (recommendationService === "lettuce") {
console.log("Lettuce recommendation service");
}

throw new Error("Recommendation service not supported");
} catch (error) {
console.error("Error fetching recommendations:", error);
throw error;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,114 +11,147 @@ import { usePathname } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import CopyButton from "@/components/core/CopyButton";
import { enableAIRecommendation } from "@/constants";
import { Tooltips } from "@/components/core/Tooltips";
import { AISuggestionsButton } from "@/components/recommendations/ai-suggesions-button";

export const columns = (
addSR: (concept: ScanReportConcept, c: Concept) => void,
deleteSR: (id: number) => void
): ColumnDef<ScanReportField>[] => [
{
id: "Name",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Field" sortName="name" />
),
enableHiding: true,
enableSorting: true,
cell: ({ row }) => {
const { id, name } = row.original;
const prePath = usePathname();
return (
<div className="flex items-center gap-2">
<Link
href={`${
prePath.endsWith("/") ? prePath : prePath + "/"
}fields/${id}`}
>
<Button variant="link" className="font-bold text-black dark:text-white">
{name}
</Button>
</Link>
<CopyButton textToCopy={name} />
</div>
);
}
},
{
id: "description",
accessorKey: "description_column",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title="Description"
sortName="description_column"
/>
),
enableHiding: true,
enableSorting: true
},
{
id: "Data Type",
accessorKey: "type_column",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title="Data Type"
sortName="type_column"
/>
),
enableHiding: true,
enableSorting: true
},
{
id: "Concepts",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Concepts" />
),
enableHiding: true,
enableSorting: false,
cell: ({ row }) => {
const { concepts } = row.original;
return (
// Just in case the concepts tags need more time to load some data
// --> showing skeleton having same width with the concept tag area
<Suspense fallback={<Skeleton className="h-5 w-[250px]" />}>
<ConceptTags concepts={concepts ?? []} deleteSR={deleteSR} />
</Suspense>
);
}
},
{
id: "Add Concept",
header: "",
cell: ({ row }) => {
const { scan_report_table, id, permissions } = row.original;
const canEdit =
permissions.includes("CanEdit") || permissions.includes("CanAdmin");
return (
<AddConcept
rowId={id}
tableId={scan_report_table.toString()}
contentType="scanreportfield"
disabled={canEdit ? false : true}
addSR={addSR}
): ColumnDef<ScanReportField>[] => {
const baseColumns: ColumnDef<ScanReportField>[] = [
{
id: "Name",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Field" sortName="name" />
),
enableHiding: true,
enableSorting: true,
cell: ({ row }) => {
const { id, name } = row.original;
const prePath = usePathname();
return (
<div className="flex items-center gap-2">
<Link
href={`${
prePath.endsWith("/") ? prePath : prePath + "/"
}fields/${id}`}
>
<Button variant="link" className="font-bold">
{name}
</Button>
</Link>
<CopyButton textToCopy={name} />
</div>
);
},
},
{
id: "description",
accessorKey: "description_column",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title="Description"
sortName="description_column"
/>
);
}
},
{
id: "edit",
header: "",
cell: ({ row }) => {
const { id, permissions } = row.original;
const path = usePathname();

return (
<EditButton
prePath={path}
fieldID={id}
type="field"
permissions={permissions}
),
enableHiding: true,
enableSorting: true,
},
{
id: "Data Type",
accessorKey: "type_column",
header: ({ column }) => (
<DataTableColumnHeader
column={column}
title="Data Type"
sortName="type_column"
/>
);
}
),
enableHiding: true,
enableSorting: true,
},
{
id: "Concepts",
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Concepts" />
),
enableHiding: true,
enableSorting: false,
cell: ({ row }) => {
const { concepts } = row.original;
return (
// Just in case the concepts tags need more time to load some data
// --> showing skeleton having same width with the concept tag area
<Suspense fallback={<Skeleton className="h-5 w-[250px]" />}>
<ConceptTags concepts={concepts ?? []} deleteSR={deleteSR} />
</Suspense>
);
},
},
{
id: "Add Concept",
header: "",
cell: ({ row }) => {
const { scan_report_table, id, permissions } = row.original;
const canEdit =
permissions.includes("CanEdit") || permissions.includes("CanAdmin");
return (
<AddConcept
rowId={id}
tableId={scan_report_table.toString()}
contentType="scanreportfield"
disabled={canEdit ? false : true}
addSR={addSR}
/>
);
},
},
];

// AI Suggestions Column & setting as 4th Column
if (enableAIRecommendation === "true") {
baseColumns.splice(3, 0, {
id: "AI Suggestions",
header: ({ column }) => (
<div className="flex items-center">
<DataTableColumnHeader column={column} title="AI Suggestions" />
<Tooltips content="Get AI-powered Standard Concept Suggestions for the field name. To get the better results, please select the most relevant domain." />
</div>
),
enableHiding: true,
enableSorting: false,
cell: ({ row }) => {
const { name, id, scan_report_table } = row.original;
return (
<AISuggestionsButton
value={name}
tableId={scan_report_table.toString()}
rowId={id}
contentType="scanreportfield"
/>
);
},
});
} else {
baseColumns.splice(5, 0, {
id: "edit",
header: "",
cell: ({ row }) => {
const { id, permissions } = row.original;
const path = usePathname();

return (
<EditButton
prePath={path}
fieldID={id}
type="field"
permissions={permissions}
/>
);
},
});
}
];
return baseColumns;
};
Loading
Loading