diff --git a/e2e/playwright/projects.spec.ts b/e2e/playwright/projects.spec.ts
index 22e23525c..1870c1ef3 100644
--- a/e2e/playwright/projects.spec.ts
+++ b/e2e/playwright/projects.spec.ts
@@ -1343,7 +1343,7 @@ test(
await test.step('should be shorted by modified initially', async () => {
const lastModifiedButton = page.getByRole('button', {
- name: 'Last Modified',
+ name: 'Age',
})
await expect(lastModifiedButton).toBeVisible()
await expect(lastModifiedButton.getByLabel('arrow down')).toBeVisible()
@@ -1364,7 +1364,7 @@ test(
await test.step('Reverse modified order', async () => {
const lastModifiedButton = page.getByRole('button', {
- name: 'Last Modified',
+ name: 'Age',
})
await lastModifiedButton.click()
await expect(lastModifiedButton).toBeVisible()
diff --git a/src/components/HomeSearchBar.tsx b/src/components/HomeSearchBar.tsx
index ace2c3a3c..5b1422278 100644
--- a/src/components/HomeSearchBar.tsx
+++ b/src/components/HomeSearchBar.tsx
@@ -5,7 +5,7 @@ import { useHotkeys } from 'react-hotkeys-hook'
import { CustomIcon } from '@src/components/CustomIcon'
import type { Project } from '@src/lib/project'
-import type { Prompt } from '@src/machines/mlEphantManagerMachine'
+import type { Prompt } from '@src/lib/prompt'
export type HomeItem = Project | Prompt
export type HomeItems = Project[] | Prompt[]
@@ -17,7 +17,7 @@ export const areHomeItemsProjects = (items: HomeItems): items is Project[] => {
export const areHomeItemsPrompts = (items: HomeItems): items is Prompt[] => {
const item = items[0]
- return item !== undefined && typeof item.prompt === 'string'
+ return item !== undefined && 'prompt' in item
}
export function useHomeSearch(initialSearchResults: HomeItems) {
@@ -34,6 +34,8 @@ export function useHomeSearch(initialSearchResults: HomeItems) {
? 'name'
: 'prompt'
+ // Fuse is not happy with HomeItems
+ // @ts-expect-error
const fuse = new Fuse(items, {
keys: [{ name: nameKeyToMatchAgainst, weight: 0.7 }],
includeScore: true,
diff --git a/src/components/PromptCard.tsx b/src/components/PromptCard.tsx
index 790c7ba59..4e18b2b0b 100644
--- a/src/components/PromptCard.tsx
+++ b/src/components/PromptCard.tsx
@@ -1,5 +1,5 @@
import ms from 'ms'
-import { Prompt } from '@src/lib/prompt'
+import type { Prompt } from '@src/lib/prompt'
interface PromptCardProps extends Prompt {
onAction?: (id: Prompt['id']) => void
@@ -8,16 +8,27 @@ interface PromptCardProps extends Prompt {
}
export const PromptFeedback = (props: {
+ id: Prompt['id']
selected: Prompt['feedback']
onFeedback: (id: Prompt['id'], feedback: Prompt['feedback']) => void
}) => {
- const cssUp = 'border-green-500'
- const cssDown = 'border-red-500'
+ const cssUp = 'border-green-300'
+ const cssDown = 'border-red-300'
return (
- Good
- Bad
+ props.onFeedback(props.id, 'thumbs_up')}
+ className={cssUp}
+ >
+ Good
+
+ props.onFeedback(props.id, 'thumbs_down')}
+ className={cssDown}
+ >
+ Bad
+
)
}
@@ -45,8 +56,9 @@ export const PromptCard = (props: PromptCardProps) => {
props.onDelete?.(props.id)}>Delete
props.onFeedback?.(...args)}
/>
diff --git a/src/lib/prompt.ts b/src/lib/prompt.ts
index a0e5c75e6..d888a537b 100644
--- a/src/lib/prompt.ts
+++ b/src/lib/prompt.ts
@@ -1,6 +1,6 @@
import type { Models } from '@kittycad/lib'
-export type Prompt = Models['TextToCad_Type']
+export type Prompt = Models['TextToCad_type']
// export interface TextToCad_type {
// code?: string;
@@ -100,21 +100,22 @@ export const generateFakeSubmittedPrompt = () => ({
created_at: new Date(Math.random() * 100000000).toISOString(),
error: Math.random().toString(),
// declare type MlFeedback_type = 'thumbs_up' | 'thumbs_down' | 'accepted' | 'rejected';
- feedback: 'thumbs_up',
+ feedback: 'thumbs_up' as Prompt['feedback'],
id: Math.random().toString(),
kcl_version: Math.random().toString(),
- // export declare type TextToCadModel_type = 'cad' | 'kcl' | 'kcl_iteration'; model : 'kcl',
model_version: Math.random().toString(),
+ // export declare type TextToCadModel_type = 'cad' | 'kcl' | 'kcl_iteration'; model : 'kcl',
+ model: 'kcl' as Prompt['model'],
// export declare type FileExportFormat_type = 'fbx' | 'glb' | 'gltf' | 'obj' | 'ply' | 'step' | 'stl';
- output_format: 'glb',
+ output_format: 'glb' as Prompt['output_format'],
outputs: {
[Math.random().toString()]: Math.random().toString(),
},
prompt: PROMPTS[parseInt((Math.random() * 10).toString()[0])],
started_at: new Date(Math.random()).toISOString(),
// declare type ApiCallStatus_type = 'queued' | 'uploaded' | 'in_progress' | 'completed' | 'failed';
- status: 'completed',
- updated_at: Math.random(),
+ status: 'completed' as Prompt['status'],
+ updated_at: Math.random().toString(),
// declare type ApiTokenUuid_type = string;
user_id: Math.random().toString(),
})
diff --git a/src/lib/sorting.ts b/src/lib/sorting.ts
index 02af6d09b..d7e4ec217 100644
--- a/src/lib/sorting.ts
+++ b/src/lib/sorting.ts
@@ -1,5 +1,6 @@
import type { CustomIconName } from '@src/components/CustomIcon'
import type { Project } from '@src/lib/project'
+import type { Prompt } from '@src/lib/prompt'
const DESC = ':desc'
@@ -25,7 +26,7 @@ export function getNextSearchParams(currentSort: string, newSort: string) {
}
}
-export function getSortFunction(sortBy: string) {
+export function getProjectSortFunction(sortBy: string) {
const sortByName = (a: Project, b: Project) => {
if (a.name && b.name) {
return sortBy.includes('desc')
@@ -52,3 +53,33 @@ export function getSortFunction(sortBy: string) {
return sortByModified
}
}
+
+// Below is to keep the same behavior as above but for prompts.
+// Do NOT take it as actually "sort by modified" but more like "sort by time".
+export function getPromptSortFunction(sortBy: string) {
+ const sortByName = (a: Prompt, b: Prompt) => {
+ if (a.prompt && b.prompt) {
+ return sortBy.includes('desc')
+ ? a.prompt.localeCompare(b.prompt)
+ : b.prompt.localeCompare(a.prompt)
+ }
+ return 0
+ }
+
+ const sortByModified = (a: Prompt, b: Prompt) => {
+ if (a.created_at && b.created_at) {
+ const aDate = new Date(a.created_at)
+ const bDate = new Date(b.created_at)
+ return !sortBy || sortBy.includes('desc')
+ ? bDate.getTime() - aDate.getTime()
+ : aDate.getTime() - bDate.getTime()
+ }
+ return 0
+ }
+
+ if (sortBy?.includes('name')) {
+ return sortByName
+ } else {
+ return sortByModified
+ }
+}
diff --git a/src/machines/mlEphantManagerMachine.ts b/src/machines/mlEphantManagerMachine.ts
index 7aa4f08df..92a71d63d 100644
--- a/src/machines/mlEphantManagerMachine.ts
+++ b/src/machines/mlEphantManagerMachine.ts
@@ -1,4 +1,6 @@
+import { setup, fromPromise } from 'xstate'
import type { Prompt } from '@src/lib/prompt'
+import { generateFakeSubmittedPrompt } from '@src/lib/prompt'
export enum MlEphantManagerTransitionStates {
GetPromptsThatCreatedProjects = 'get-prompts-that-created-projects',
@@ -47,9 +49,9 @@ export enum MlEphantManagerStates {
}
export interface MlEphantManagerContext {
- promptsThatCreatedProjects: Map
+ promptsThatCreatedProjects: Map
// If no project is selected: undefined.
- promptsBelongingToProject?: Map
+ promptsBelongingToProject?: Map
}
export const mlEphantDefaultContext = Object.freeze({
@@ -58,13 +60,25 @@ export const mlEphantDefaultContext = Object.freeze({
hasPendingPrompts: false,
})
-const machine = setup({
+export const mlEphantManagerMachine = setup({
types: {
context: {} as MlEphantManagerContext,
events: {} as MlEphantManagerEvents,
},
+ actors: {
+ [MlEphantManagerTransitionStates.GetPromptsThatCreatedProjects]:
+ fromPromise(async function (args) {
+ console.log(arguments)
+ return {
+ promptsThatCreatedProjects: new Array(13)
+ .fill(undefined)
+ .map(generateFakeSubmittedPrompt),
+ }
+ }),
+ },
}).createMachine({
initial: MlEphantManagerStates.Idle,
+ context: mlEphantDefaultContext,
states: {
[MlEphantManagerStates.Idle]: {
on: {
@@ -77,15 +91,8 @@ const machine = setup({
states: {
[MlEphantManagerTransitionStates.GetPromptsThatCreatedProjects]: {
invoke: {
- input: (args) => args,
- src: fromPromise(async function (args) {
- console.log(arguments)
- return {
- promptsThatCreatedProjects: new Array(13)
- .fill(undefined)
- .map(generateFakeSubmittedPrompt),
- }
- }),
+ input: (args: any) => args,
+ src: MlEphantManagerTransitionStates.GetPromptsThatCreatedProjects,
onDone: { target: MlEphantManagerStates.Idle },
onError: { target: MlEphantManagerStates.Idle },
},
diff --git a/src/routes/Home.tsx b/src/routes/Home.tsx
index 772b82f9b..320279d73 100644
--- a/src/routes/Home.tsx
+++ b/src/routes/Home.tsx
@@ -17,10 +17,10 @@ import { PromptCard } from '@src/components/PromptCard'
import {
HomeSearchBar,
useHomeSearch,
- HomeItems,
areHomeItemsProjects,
areHomeItemsPrompts,
} from '@src/components/HomeSearchBar'
+import type { HomeItems } from '@src/components/HomeSearchBar'
import { BillingDialog } from '@src/components/BillingDialog'
import { useQueryParamEffects } from '@src/hooks/useQueryParamEffects'
import { useMenuListener } from '@src/hooks/useMenu'
@@ -32,7 +32,8 @@ import type { Prompt } from '@src/lib/prompt'
import { generateFakeSubmittedPrompt } from '@src/lib/prompt'
import {
getNextSearchParams,
- getSortFunction,
+ getProjectSortFunction,
+ getPromptSortFunction,
getSortIcon,
} from '@src/lib/sorting'
import { reportRejection } from '@src/lib/trap'
@@ -216,7 +217,7 @@ const Home = () => {
}
)
const projects = useFolders()
- const prompts = [
+ const prompts: Prompt[] = [
generateFakeSubmittedPrompt(),
generateFakeSubmittedPrompt(),
generateFakeSubmittedPrompt(),
@@ -228,7 +229,7 @@ const Home = () => {
const [tabSelected, setTabSelected] = useState(
HomeTabKeys.Projects
)
- const [items, setItems] = useState(projects)
+ const [items, setItems] = useState(projects)
const [searchParams, setSearchParams] = useSearchParams()
const { searchResults, query, searchAgainst } = useHomeSearch(projects)
const sortBy = searchParams.get('sort_by') ?? 'modified:desc'
@@ -484,6 +485,8 @@ function HomeTab(props: HomeTabProps) {
{el.name}
@@ -565,7 +568,7 @@ function HomeHeader({
: '',
}}
>
- Last Modified
+ Age
@@ -653,18 +656,37 @@ function HomeItemsArea(props: HomeItemsAreaProps) {
)
}
-interface ResultGridProjectsProps {
+interface ResultGridPromptsProps {
searchResults: Prompt[]
query: string
sortBy: string
}
-function ResultGridPrompts(props) {
+function ResultGridPrompts(props: ResultGridPromptsProps) {
+ // Maybe consider lifting this higher but I see no reason at the moment
+ const onAction = (...args: any) => {
+ console.log(args)
+ }
+ const onDelete = (...args: any) => {
+ console.log(args)
+ }
+ const onFeedback = (...args: any) => {
+ console.log(args)
+ }
+
return (
- {props.searchResults.map((prompt) => (
-
- ))}
+ {props.searchResults
+ .sort(getPromptSortFunction(props.sortBy))
+ .map((prompt: Prompt) => (
+
+ ))}
)
}
@@ -686,8 +708,8 @@ function ResultGridProjects(props: ResultGridProjectsProps) {
<>
{props.searchResults.length > 0 ? (
- {(props.searchResults ?? [])
- .sort(getSortFunction(props.sortBy))
+ {props.searchResults
+ .sort(getProjectSortFunction(props.sortBy))
.map((item) => (
No results found
- {items.length === 0
+ {props.searchResults.length === 0
? ', ready to make your first one?'
- : ` with the search term "${query}"`}
+ : ` with the search term "${props.query}"`}
)}
>