Skip to content

Commit

Permalink
implement stats for agents (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
umihai29 authored Feb 19, 2025
1 parent 9dca47c commit 23d4217
Show file tree
Hide file tree
Showing 15 changed files with 170 additions and 111 deletions.
42 changes: 42 additions & 0 deletions src/domain/usecases/agents/edit-agent-status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Tracer } from '@infra/tracer';
import { RootStore } from '@store/root';
import { AgentService } from '@domain/services/agent/agent.service';

export class EditAgentStatusUsecase {
private service = new AgentService();
private root = RootStore.getInstance();

constructor(private readonly agentId: string) {
this.toggleActive = this.toggleActive.bind(this);
}

get agent() {
return this.root.agents.getById(this.agentId);
}

toggleActive() {
const span = Tracer.span('AgentViewUsecase.toggleActive');

if (!this.agent) {
console.error('AgentViewUsecase.toggleActive: Agent not found. Aborting');

return;
}
this.agent.toggleStatus();
this.service.saveAgent(this.agent).then(() => {
if (this.agent?.value.isActive) {
this.root.ui.toastSuccess(
`${this.agent?.value.name} is now turned on`,
'agent-status-toggle-on',
);
} else {
this.root.ui.toastSuccess(
`${this.agent?.value.name} is now turned off`,
'agent-status-toggle-off',
);
}
});

span.end();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class RenameAgentUsecase {

constructor(private id?: string) {
this.execute = this.execute.bind(this);
this.inputValue = this.agent?.value.name ?? '';
this.setInputValue = this.setInputValue.bind(this);
}

Expand All @@ -38,10 +39,7 @@ export class RenameAgentUsecase {
}

const span = Tracer.span('RenameAgentUsecase.execute', {
payload: {
agent,
name: this.inputValue,
},
agentName: agent.value.name,
});

// Default to 'Name me maybe' if the input is empty
Expand All @@ -60,13 +58,10 @@ export class RenameAgentUsecase {
agent.setName(prevName);
console.error('RenameAgentUsecase.execute: Could not rename agent', err);
span.end();

return;
}

if (res?.agent_Save) {
this.isSaving = false;
agent.put(res?.agent_Save);
this.root.ui.commandMenu.setType('AgentCommands');
this.root.ui.commandMenu.setOpen(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type SaveAgentMutation = {
createdAt: any;
updatedAt: any;
error?: string | null;
metric: string;
color: string;
scope: Types.AgentScope;
icon: string;
Expand Down
1 change: 1 addition & 0 deletions src/infra/repositories/agent/mutations/saveAgent.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mutation saveAgent($input: AgentSaveInput!) {
createdAt
updatedAt
error
metric
color
scope
icon
Expand Down
1 change: 1 addition & 0 deletions src/infra/repositories/agent/queries/agent.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type AgentQuery = {
visible: boolean;
createdAt: any;
updatedAt: any;
metric: string;
error?: string | null;
color: string;
icon: string;
Expand Down
1 change: 1 addition & 0 deletions src/infra/repositories/agent/queries/agent.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ query agent($id: ID!) {
visible
createdAt
updatedAt
metric
error
color
icon
Expand Down
1 change: 1 addition & 0 deletions src/infra/repositories/agent/queries/agents.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type AgentsQuery = {
visible: boolean;
createdAt: any;
updatedAt: any;
metric: string;
error?: string | null;
color: string;
icon: string;
Expand Down
1 change: 1 addition & 0 deletions src/infra/repositories/agent/queries/agents.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ query agents {
visible
createdAt
updatedAt
metric
error
color
icon
Expand Down
153 changes: 60 additions & 93 deletions src/routes/agents/components/AgentCard/AgentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { useMemo, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

import { useKeys } from 'rooks';
import { observer } from 'mobx-react-lite';
import { AgentViewUsecase } from '@domain/usecases/agents/agent-view.usecase';

import { cn } from '@ui/utils/cn';
import { Icon, IconName } from '@ui/media/Icon';
import { useStore } from '@shared/hooks/useStore';
import { useModKey } from '@shared/hooks/useModKey';
import { Tag, TagLabel } from '@ui/presentation/Tag';

interface AgentCardProps {
id: string;
name: string;
icon?: string;
metric?: string;
hasError?: boolean;
defaultName: string;
status: 'ON' | 'OFF';
Expand All @@ -26,6 +23,7 @@ export const AgentCard = observer(
id,
name,
icon,
metric,
status,
hasError,
defaultName,
Expand Down Expand Up @@ -58,51 +56,6 @@ export const AgentCard = observer(
}
};

useEffect(() => {
return () => {
store.ui.commandMenu.clearContext();
store.ui.commandMenu.setType('AgentsCommands');
};
}, []);

const usecase = useMemo(() => new AgentViewUsecase(id), [id]);

useKeys(
['Shift', 'S'],
(e) => {
e.stopPropagation();
e.preventDefault();
usecase.toggleActive();
},
{
when: store.ui.commandMenu.context.ids?.[0] === id,
},
);

useKeys(
['Shift', 'R'],
(e) => {
e.stopPropagation();
e.preventDefault();
store.ui.commandMenu.setType('RenameAgent');
store.ui.commandMenu.setOpen(true);
},
{
when: store.ui.commandMenu.context.ids?.[0] === id,
},
);

useModKey(
'Backspace',
() => {
store.ui.commandMenu.setType('ArchiveAgent');
store.ui.commandMenu.setOpen(true);
},
{
when: store.ui.commandMenu.context.ids?.[0] === id,
},
);

return (
<div
tabIndex={0}
Expand All @@ -113,54 +66,68 @@ export const AgentCard = observer(
onMouseEnter={() => handleStateChange(true)}
onMouseLeave={() => handleStateChange(false)}
className={cn(
'p-3 min-w-[372px] flex-1 rounded-lg flex items-center gap-2 ring-0 border cursor-pointer group hover:bg-white hover:shadow-lg transition-all ring-grayModern-200 hover:ring-1',
' min-w-[372px] flex-1 rounded-lg flex items-center gap-2 ring-0 border cursor-pointer group hover:bg-white hover:shadow-lg flex-col transition-all ring-grayModern-200 hover:ring-1',
ring,
)}
>
<div
className={cn(
'p-2 flex items-center rounded-lg bg-grayModern-50',
bg,
)}
>
<Icon
name={(icon as IconName) ?? 'radar'}
className={cn('size-6 text-grayModern-500', iconColor)}
/>
</div>

<div className='flex justify-between w-full'>
<div className='flex flex-col justify-center'>
{name.toLowerCase() !== defaultName.toLowerCase() && (
<p className='line-clamp-1 text-xs text-grayModern-500'>
{defaultName}
</p>
)}
<p className='line-clamp-2 text-sm font-medium'>
{name || defaultName}
</p>
</div>
<div className='flex items-center'>
<Tag colorScheme={tagColor}>
<TagLabel className='flex items-center gap-1'>
<Icon
stroke={hasError && status === 'ON' ? 'currentColor' : 'none'}
className={cn('size-3', {
'text-warning-500': hasError && status === 'ON',
'text-gray-500': status === 'OFF',
})}
name={
hasError && status === 'ON'
? 'alert-triangle'
: status === 'OFF'
? 'dot-single'
: 'dot-live-success'
}
/>
{status}
</TagLabel>
</Tag>
<div className='flex flex-col w-full gap-2'>
<div className='flex items-center justify-between gap-2 w-full px-3 pt-3'>
<div
className={cn(
'p-2 flex items-center rounded-lg bg-grayModern-50',
bg,
)}
>
<Icon
name={(icon as IconName) ?? 'radar'}
className={cn('size-6 text-grayModern-500', iconColor)}
/>
</div>
<div className='flex justify-between w-full'>
<div className='flex flex-col justify-center'>
{name.toLowerCase() !== defaultName.toLowerCase() && (
<p className='line-clamp-1 text-xs text-grayModern-500'>
{defaultName}
</p>
)}
<p className='line-clamp-2 text-sm font-medium'>
{name || defaultName}
</p>
</div>
<div className='flex items-center'>
<Tag colorScheme={tagColor}>
<TagLabel className='flex items-center gap-1'>
<Icon
stroke={
hasError && status === 'ON' ? 'currentColor' : 'none'
}
className={cn('size-3', {
'text-warning-500': hasError && status === 'ON',
'text-gray-500': status === 'OFF',
})}
name={
hasError && status === 'ON'
? 'alert-triangle'
: status === 'OFF'
? 'dot-single'
: 'dot-live-success'
}
/>
{status}
</TagLabel>
</Tag>
</div>
</div>
</div>

{metric && (
<div className='flex items-center gap-2 bg-grayModern-50 w-full py-2 rounded-b-lg px-6'>
<div className='flex items-center gap-2'>
<Icon name='clock' className='size-3 text-grayModern-500' />
<p className='text-xs'>{metric}</p>
</div>
</div>
)}
</div>
</div>
);
Expand Down
Loading

0 comments on commit 23d4217

Please sign in to comment.