Clean up and fixes
This commit is contained in:
@@ -11,7 +11,10 @@ import { Box, Text, useInput } from 'ink';
|
||||
import { useNavigation } from '../hooks/useNavigation.js';
|
||||
import { useAppContext, useStatus } from '../hooks/useAppContext.js';
|
||||
import { colors, logoSmall } from '../theme.js';
|
||||
import type { XOTemplate, XOTemplateStartingActions } from '@xo-cash/types';
|
||||
|
||||
// XO Imports
|
||||
import { generateTemplateIdentifier } from '@xo-cash/engine';
|
||||
import type { XOTemplate, XOTemplateActionRoleRequirement, XOTemplateStartingActions } from '@xo-cash/types';
|
||||
|
||||
/**
|
||||
* Template item with metadata.
|
||||
@@ -28,7 +31,7 @@ interface TemplateItem {
|
||||
*/
|
||||
export function TemplateListScreen(): React.ReactElement {
|
||||
const { navigate } = useNavigation();
|
||||
const { walletController, showError } = useAppContext();
|
||||
const { appService, showError } = useAppContext();
|
||||
const { setStatus } = useStatus();
|
||||
|
||||
// State
|
||||
@@ -39,20 +42,24 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
/**
|
||||
* Loads templates from the wallet controller.
|
||||
* Loads templates from the engine.
|
||||
*/
|
||||
const loadTemplates = useCallback(async () => {
|
||||
if (!appService) {
|
||||
showError('AppService not initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
setStatus('Loading templates...');
|
||||
|
||||
const templateList = await walletController.getTemplates();
|
||||
const { generateTemplateIdentifier } = await import('@xo-cash/engine');
|
||||
const templateList = await appService.engine.listImportedTemplates();
|
||||
|
||||
const loadedTemplates = await Promise.all(
|
||||
templateList.map(async (template) => {
|
||||
const templateIdentifier = generateTemplateIdentifier(template);
|
||||
const startingActions = await walletController.getStartingActions(templateIdentifier);
|
||||
const startingActions = await appService.engine.listStartingActions(templateIdentifier);
|
||||
return { template, templateIdentifier, startingActions };
|
||||
})
|
||||
);
|
||||
@@ -66,7 +73,7 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
showError(`Failed to load templates: ${error instanceof Error ? error.message : String(error)}`);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [walletController, setStatus, showError]);
|
||||
}, [appService, setStatus, showError]);
|
||||
|
||||
// Load templates on mount
|
||||
useEffect(() => {
|
||||
@@ -127,31 +134,39 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
});
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" flexGrow={1}>
|
||||
<Box flexDirection='column' flexGrow={1}>
|
||||
{/* Header */}
|
||||
<Box borderStyle="single" borderColor={colors.secondary} paddingX={1}>
|
||||
<Box borderStyle='single' borderColor={colors.secondary} paddingX={1}>
|
||||
<Text color={colors.primary} bold>{logoSmall} - Select Template & Action</Text>
|
||||
</Box>
|
||||
|
||||
{/* Main content - two columns */}
|
||||
<Box flexDirection="row" marginTop={1} flexGrow={1}>
|
||||
<Box flexDirection='row' marginTop={1} flexGrow={1}>
|
||||
{/* Left column: Template list */}
|
||||
<Box flexDirection="column" width="40%" paddingRight={1}>
|
||||
<Box flexDirection='column' width='40%' paddingRight={1}>
|
||||
<Box
|
||||
borderStyle="single"
|
||||
borderStyle='single'
|
||||
borderColor={focusedPanel === 'templates' ? colors.focus : colors.primary}
|
||||
flexDirection="column"
|
||||
flexDirection='column'
|
||||
paddingX={1}
|
||||
flexGrow={1}
|
||||
>
|
||||
<Text color={colors.primary} bold> Templates </Text>
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
{isLoading ? (
|
||||
<Text color={colors.textMuted}>Loading...</Text>
|
||||
) : templates.length === 0 ? (
|
||||
<Text color={colors.textMuted}>No templates imported</Text>
|
||||
) : (
|
||||
templates.map((item, index) => (
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
|
||||
{(() => {
|
||||
// Loading State
|
||||
if (isLoading) {
|
||||
return <Text color={colors.textMuted}>Loading...</Text>;
|
||||
}
|
||||
|
||||
// No templates state
|
||||
if (templates.length === 0) {
|
||||
return <Text color={colors.textMuted}>No templates imported</Text>;
|
||||
}
|
||||
|
||||
// Templates state
|
||||
return templates.map((item, index) => (
|
||||
<Text
|
||||
key={item.templateIdentifier}
|
||||
color={index === selectedTemplateIndex ? colors.focus : colors.text}
|
||||
@@ -160,29 +175,43 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
{index === selectedTemplateIndex && focusedPanel === 'templates' ? '▸ ' : ' '}
|
||||
{index + 1}. {item.template.name || 'Unnamed Template'}
|
||||
</Text>
|
||||
))
|
||||
)}
|
||||
));
|
||||
})()}
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Right column: Actions list */}
|
||||
<Box flexDirection="column" width="60%" paddingLeft={1}>
|
||||
<Box flexDirection='column' width='60%' paddingLeft={1}>
|
||||
<Box
|
||||
borderStyle="single"
|
||||
borderStyle='single'
|
||||
borderColor={focusedPanel === 'actions' ? colors.focus : colors.border}
|
||||
flexDirection="column"
|
||||
flexDirection='column'
|
||||
paddingX={1}
|
||||
flexGrow={1}
|
||||
>
|
||||
<Text color={colors.primary} bold> Starting Actions </Text>
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
{!currentTemplate ? (
|
||||
<Text color={colors.textMuted}>Select a template...</Text>
|
||||
) : currentActions.length === 0 ? (
|
||||
<Text color={colors.textMuted}>No starting actions available</Text>
|
||||
) : (
|
||||
currentActions.map((action, index) => {
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
|
||||
{(() => {
|
||||
// Loading state
|
||||
if (isLoading) {
|
||||
return <Text color={colors.textMuted}>Loading...</Text>;
|
||||
}
|
||||
|
||||
// No template selected state
|
||||
if (!currentTemplate) {
|
||||
return <Text color={colors.textMuted}>Select a template...</Text>;
|
||||
}
|
||||
|
||||
// No starting actions state
|
||||
if (currentActions.length === 0) {
|
||||
return <Text color={colors.textMuted}>No starting actions available</Text>;
|
||||
}
|
||||
|
||||
// Starting actions state
|
||||
return currentActions.map((action, index) => {
|
||||
const actionDef = currentTemplate.template.actions?.[action.action];
|
||||
const name = actionDef?.name || action.action;
|
||||
return (
|
||||
@@ -195,8 +224,9 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
{index + 1}. {name} (as {action.role})
|
||||
</Text>
|
||||
);
|
||||
})
|
||||
)}
|
||||
});
|
||||
})()}
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -205,16 +235,18 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
{/* Description box */}
|
||||
<Box marginTop={1}>
|
||||
<Box
|
||||
borderStyle="single"
|
||||
borderStyle='single'
|
||||
borderColor={colors.border}
|
||||
flexDirection="column"
|
||||
flexDirection='column'
|
||||
paddingX={1}
|
||||
paddingY={1}
|
||||
width="100%"
|
||||
width='100%'
|
||||
>
|
||||
<Text color={colors.primary} bold> Description </Text>
|
||||
{currentTemplate ? (
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
|
||||
{/* Show template description when templates panel is focused */}
|
||||
{focusedPanel === 'templates' && currentTemplate ? (
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
<Text color={colors.text} bold>
|
||||
{currentTemplate.template.name || 'Unnamed Template'}
|
||||
</Text>
|
||||
@@ -227,7 +259,7 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
</Text>
|
||||
)}
|
||||
{currentTemplate.template.roles && (
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
<Text color={colors.text}>Roles:</Text>
|
||||
{Object.entries(currentTemplate.template.roles).map(([roleId, role]) => (
|
||||
<Text key={roleId} color={colors.textMuted}>
|
||||
@@ -237,9 +269,70 @@ export function TemplateListScreen(): React.ReactElement {
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
) : (
|
||||
) : focusedPanel === 'templates' && !currentTemplate ? (
|
||||
<Text color={colors.textMuted}>Select a template to see details</Text>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
{/* Show action description when actions panel is focused */}
|
||||
{focusedPanel === 'actions' && currentTemplate && currentActions.length > 0 ? (
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
{(() => {
|
||||
const action = currentActions[selectedActionIndex];
|
||||
if (!action) return null;
|
||||
|
||||
const actionDef = currentTemplate.template.actions?.[action.action];
|
||||
const roleDef = currentTemplate.template.roles?.[action.role];
|
||||
|
||||
// if (!actionDef || !roleDef) return null;
|
||||
|
||||
const [_roleName, role] = Object.entries(actionDef?.roles ?? {}).find(([roleId, role]) => roleId === action.role) || [];
|
||||
|
||||
console.log(JSON.stringify(role, null, 2));
|
||||
|
||||
const variableKeys = role?.requirements?.variables || []
|
||||
|
||||
console.log('variables', variableKeys);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text color={colors.text} bold>
|
||||
{actionDef?.name || action.action}
|
||||
</Text>
|
||||
<Text color={colors.textMuted}>
|
||||
{actionDef?.description || 'No description available'}
|
||||
</Text>
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
<Text color={colors.text}>
|
||||
Role: {roleDef?.name || action.role}
|
||||
</Text>
|
||||
{roleDef?.description && (
|
||||
<Text color={colors.textMuted}>
|
||||
{' '}{roleDef.description}
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
{/* Display variables if available */}
|
||||
{
|
||||
variableKeys.length > 0 && (
|
||||
<Box marginTop={1} flexDirection='column'>
|
||||
<Text color={colors.text}>Variables:</Text>
|
||||
{variableKeys.map((variableKey) => (
|
||||
<Text key={variableKey} color={colors.text}>
|
||||
- {currentTemplate.template.variables?.[variableKey]?.name || variableKey}: {currentTemplate.template.variables?.[variableKey]?.description || 'No description'}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</Box>
|
||||
) : focusedPanel === 'actions' && !currentTemplate ? (
|
||||
<Text color={colors.textMuted}>Select a template first</Text>
|
||||
) : focusedPanel === 'actions' && currentActions.length === 0 ? (
|
||||
<Text color={colors.textMuted}>No starting actions available</Text>
|
||||
) : null}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user