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 Agents CRUD capabilities #50

Merged
merged 39 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e78b439
Bump hashicorp/random from 3.4.3 to 3.6.3 in /infra (#5)
dependabot[bot] Jan 21, 2025
2ac8bec
Bump hashicorp/azuread from 3.0.2 to 3.1.0 in /infra (#6)
dependabot[bot] Jan 21, 2025
3e1aa75
Bump hashicorp/azurerm from 4.14.0 to 4.16.0 in /infra (#15)
dependabot[bot] Jan 21, 2025
423e1b5
Bump azure/azapi from 2.1.0 to 2.2.0 in /infra (#18)
dependabot[bot] Jan 21, 2025
64237be
Bump eslint from 9.17.0 to 9.18.0 in /app/ui (#17)
dependabot[bot] Jan 23, 2025
afa8bb8
Bump fastapi-azure-auth from 5.0.0 to 5.0.1 in /app/api (#8)
dependabot[bot] Jan 23, 2025
78a21c0
Bump uvicorn[standard] from 0.32.0 to 0.34.0 in /app/api (#9)
dependabot[bot] Jan 23, 2025
7fea087
Bump azure-cosmos from 4.7.0 to 4.9.0 in /app/api (#12)
dependabot[bot] Jan 23, 2025
74dd07e
Bump opencensus-ext-azure from 1.1.13 to 1.1.14 in /app/api (#7)
dependabot[bot] Jan 23, 2025
61542c5
Bump azure-identity from 1.17.1 to 1.19.0 in /app/api (#10)
dependabot[bot] Jan 23, 2025
8cd898d
Bump @azure/identity from 4.5.0 to 4.6.0 in /app/ui (#13)
dependabot[bot] Jan 23, 2025
9449436
Bump react-router-dom from 7.1.1 to 7.1.3 in /app/ui (#11)
dependabot[bot] Jan 23, 2025
5fd621b
Bump vite from 6.0.7 to 6.0.11 in /app/ui in the npm_and_yarn group (…
dependabot[bot] Jan 23, 2025
689ee65
Bump @types/node from 20.17.12 to 22.10.9 in /app/ui (#33)
dependabot[bot] Jan 23, 2025
99c3c57
Add pages and navigation
Jan 23, 2025
b0b9ea4
Update styles
Jan 23, 2025
493dfe8
Revert non-intentional changes
Jan 23, 2025
cbad559
Revert mitakenly upgraded packages
Jan 23, 2025
620ca4c
Add compoenents and pages needed for CRUD agents
Jan 24, 2025
895cf8f
Merge branch 'feature/admin-agent-manager' into jedheaj314/agents-ui
Jan 24, 2025
794705e
Add Agent dialog
Jan 26, 2025
f8f8a66
Fix issues with CRUD - working now
Jan 26, 2025
44c0892
Fix dismiss button on error message
Jan 27, 2025
5ccdfbc
Update delete modal and lading icons
Jan 27, 2025
073fb03
Change edit button and view
Jan 28, 2025
0af78c6
Duplicate now add copy at the end of name
Jan 28, 2025
8dc7979
Minor code improvemets in react components
Jan 28, 2025
89cea4e
Merge branch 'feature/admin-agent-manager' into jedheaj314/agents-ui
Jan 28, 2025
9bac7a9
Add missing reference to an icon
Jan 28, 2025
a9d865f
Change copy prompt button place
Jan 28, 2025
b4751f3
Fix long card header title
Jan 28, 2025
15462ca
Change button name from Apply to Save
jedheaj314 Jan 29, 2025
1465040
Merge branch 'feature/admin-agent-manager' into jedheaj314/agents-ui
jedheaj314 Jan 29, 2025
be0689e
Update aftr runing prettier
Jan 29, 2025
f0a16b4
Extract Agent interface
Jan 29, 2025
4ff1b64
Update to use shared and makeStyles
Jan 30, 2025
bc41d3d
Use comman error component
Jan 31, 2025
647b7b1
Remove view mode (UI)
Jan 31, 2025
1667ac3
Use handlers directly
jjgriff93 Jan 31, 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
18 changes: 14 additions & 4 deletions app/ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { IPublicClientApplication } from "@azure/msal-browser";
import { MsalAuthenticationTemplate, MsalProvider } from "@azure/msal-react";
import { Button, makeStyles } from "@fluentui/react-components";
import { Avatar, Button, makeStyles } from "@fluentui/react-components";
import { ChevronLeft20Regular } from "@fluentui/react-icons";
import { useLocation, useNavigate } from "react-router-dom";
import logo from './assets/Azure.svg';
import { interactionType, loginRequest } from "./authConfig";
import { NavMenu, Pages } from "./Navigation";


type AppProps = {
pca: IPublicClientApplication;
};

const useStyles = makeStyles({
app: { backgroundColor: '#f5f5f5', color: '#fff', minHeight: '100vh' },
header: { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', padding: '8px' },
app: { backgroundColor: '#f5f5f5', color: '#fff', minHeight: '100vh', overflowX: 'hidden'},
header: { display: 'flex', flexDirection: 'row', justifyContent: 'space-between', padding: '8px', width: '100%', boxSizing: 'border-box' },
logo: {
display: 'flex',
alignItems: 'center',
Expand All @@ -29,6 +30,11 @@ const useStyles = makeStyles({
},
logoText: { textDecoration: 'none', color: '#000' },
main: { display: 'flex', flexDirection: 'column', alignItems: 'center' },
rightSection: {
display: 'flex',
alignItems: 'center',
gap: '16px',
},
});

function App({ pca }: AppProps) {
Expand All @@ -49,7 +55,11 @@ function App({ pca }: AppProps) {
<img src={logo} alt="logo" />
<h3>AI Document Review</h3>
</div>
<NavMenu />
<div className={classes.rightSection}>
<NavMenu />
<Avatar aria-label="User" size={32} />
</div>

</header>

<main className={classes.main}>
Expand Down
28 changes: 11 additions & 17 deletions app/ui/src/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
MenuGroup,
MenuGroupHeader,
MenuDivider,
Avatar,
MenuItemLink,
} from "@fluentui/react-components";
import {
Expand All @@ -19,11 +18,12 @@ import {
DocumentBulletListFilled,
} from "@fluentui/react-icons";
import { useNavigate, useLocation, Routes, Route } from "react-router-dom";
import Agents from "./pages/admin/Agents";
import AgentManager from "./pages/admin/AgentManager";
import Files from "./pages/files/Files";
import Review from "./pages/review/Review";
import Settings from "./pages/admin/Settings";
import useStyles from "./styles/useStyles";
import SettingManager from "./pages/admin/SettingManager";
import { DOCUMENTATION_URL } from "./constants";
import { sharedStyles } from "./styles/sharedStyles";


// paths
Expand All @@ -34,12 +34,11 @@ const paths = {
settings: "/admin/settings",
};

const documentation_url = "https://github.com/Azure-Samples/ai-document-review";

const NavMenu = () => {
const navigate = useNavigate();
const location = useLocation();
const classes = useStyles()
const sharedClasses = sharedStyles();

const isSelected = (path: string) => location.pathname === path;

Expand All @@ -54,7 +53,7 @@ const NavMenu = () => {
<MenuItem
icon={<Home20Filled />}
onClick={() => navigate(paths.home)}
className={isSelected(paths.home) ? classes.selected : ""}
className={isSelected(paths.home) ? sharedClasses.selected : ""}
>
Home
</MenuItem>
Expand All @@ -67,27 +66,22 @@ const NavMenu = () => {
<MenuItem
icon={<Prompt20Filled />}
onClick={() => navigate(paths.adminAgents)}
className={isSelected(paths.adminAgents) ? classes.selected : ""}
className={isSelected(paths.adminAgents) ? sharedClasses.selected : ""}
>
Agents Manager
</MenuItem>
<MenuItem
icon={<Settings20Filled />}
onClick={() => navigate(paths.settings)}
className={isSelected(paths.settings) ? classes.selected : ""}
className={isSelected(paths.settings) ? sharedClasses.selected : ""}
>
Settings
</MenuItem>
</MenuGroup>
<MenuDivider />
<MenuItemLink icon={<DocumentBulletListFilled />} href={documentation_url} target="_blank" rel="noopener noreferrer">
<MenuItemLink icon={<DocumentBulletListFilled />} href={DOCUMENTATION_URL} target="_blank" rel="noopener noreferrer">
Documentation
</MenuItemLink>

{/* Account */}
<MenuItem>
<Avatar aria-label="User" size={32} />
</MenuItem>
</MenuList>
</MenuPopover>
</Menu>
Expand All @@ -98,8 +92,8 @@ const Pages = () => (
<Routes>
<Route path={paths.home} element={<Files />} />
<Route path={paths.review} element={<Review />} />
<Route path={paths.adminAgents} element={<Agents />} />
<Route path={paths.settings} element={<Settings />} />
<Route path={paths.adminAgents} element={<AgentManager />} />
<Route path={paths.settings} element={<SettingManager />} />
</Routes>
);

Expand Down
46 changes: 46 additions & 0 deletions app/ui/src/components/AddCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Card, makeStyles, Text, tokens } from '@fluentui/react-components'
import { AddRegular } from '@fluentui/react-icons'


interface AddCardProps {
onClick: () => void
labelText: string
}

const componentSyles = makeStyles({
addIconText: {
textAlign: 'center',
fontWeight: tokens.fontWeightSemibold
},
disabledCard: {
width: '200px',
maxWidth: '100%',
height: '260px'
},
addIcon: {
fontSize: '72px',
color: tokens.colorNeutralForeground3,
margin: 'auto',
opacity: 0.5,
pointerEvents: 'none'
}
})

const AddCard: React.FC<AddCardProps> = ({ onClick, labelText }) => {
const componentClasses = componentSyles()

return (
<Card
aria-label={labelText}
role="button"
className={componentClasses.disabledCard}
appearance="filled-alternative"
onClick={() => onClick()}
>
<AddRegular className={componentClasses.addIcon} />
<Text className={componentClasses.addIconText}>{labelText}</Text>
</Card>
)
}

export default AddCard
113 changes: 113 additions & 0 deletions app/ui/src/components/AgentCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {
Button,
Caption1,
Card,
CardFooter,
CardHeader,
CardPreview,
Text,
Tooltip,
makeStyles
} from '@fluentui/react-components'
import { DeleteRegular, SquareMultipleRegular } from '@fluentui/react-icons'
import React from 'react'
import { sharedStyles } from '../styles/sharedStyles'
import { PromptAgent } from '../types/prompt-agent'


const componentSyles = makeStyles({
cardHeaderTitle: {
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: '165px',
},
cardFooter: {
marginTop: "auto",
display: "flex",
justifyContent: "flex-end",
gap: "8px"
},
cardbody: {
padding: '12px',
width: '175px',
textAlign: 'left',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
WebkitLineClamp: 3,
overflow: 'hidden',
textOverflow: 'ellipsis',
wordBreak: 'break-word',
maxWidth: '175px',
maxHeight: '125px'
}
})

interface AgentCardProps {
agent: PromptAgent
onViewAgent: (agent: PromptAgent) => void
onDeleteAgent: (id: string) => void
onEditAgent: (id: string) => void
onDuplicateAgent: (id: string) => void
}

const AgentCard: React.FC<AgentCardProps> = ({
agent,
onViewAgent,
onDeleteAgent,
onDuplicateAgent
}) => {
const extractDate = (dateString: string | number | Date | undefined) => {
const date = new Date(dateString || '')
return !isNaN(date.getTime()) ? date.toLocaleDateString() : 'Date not available'
}

const componentClasses = componentSyles()
const sharedClasses = sharedStyles()

return (
<Card onClick={() => onViewAgent(agent)} key={agent.id} className={sharedClasses.card}>
<CardHeader
header={
<Text weight="semibold" className={componentClasses.cardHeaderTitle}>
{agent.name}
</Text>
}
description={
<Caption1 className={sharedClasses.caption}>
{agent.updated_at_UTC
? `Updated: ${extractDate(agent.updated_at_UTC)}`
: `Created: ${extractDate(agent.created_at_UTC)}`}
</Caption1>
}
/>
<CardPreview>
<Text className={componentClasses.cardbody}>{agent.guideline_prompt}</Text>
</CardPreview>
<CardFooter className={componentClasses.cardFooter}>
<Tooltip content="Delete Agent" relationship="label">
<Button
onClick={(e) => {
e.stopPropagation()
onDeleteAgent(agent.id)
}}
icon={<DeleteRegular />}
aria-label="Delete Agent"
/>
</Tooltip>
<Tooltip content="Duplicate Agent" relationship="label">
<Button
onClick={(e) => {
e.stopPropagation()
onDuplicateAgent(agent.id)
}}
icon={<SquareMultipleRegular />}
aria-label="Duplicate Agent"
/>
</Tooltip>
</CardFooter>
</Card>
)
}

export default AgentCard
Loading