diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json
index 329c0ec355..5d82dc3424 100644
--- a/invokeai/frontend/web/package.json
+++ b/invokeai/frontend/web/package.json
@@ -66,6 +66,7 @@
"chakra-react-select": "^4.9.2",
"cmdk": "^1.0.0",
"compare-versions": "^6.1.1",
+ "dateformat": "^5.0.3",
"fracturedjsonjs": "^4.0.2",
"framer-motion": "^11.10.0",
"i18next": "^23.15.1",
@@ -127,6 +128,7 @@
"@storybook/react": "^8.3.4",
"@storybook/react-vite": "^8.3.4",
"@storybook/theming": "^8.3.4",
+ "@types/dateformat": "^5.0.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.16.10",
"@types/react": "^18.3.11",
diff --git a/invokeai/frontend/web/pnpm-lock.yaml b/invokeai/frontend/web/pnpm-lock.yaml
index e5ad9e9d07..4de3d05578 100644
--- a/invokeai/frontend/web/pnpm-lock.yaml
+++ b/invokeai/frontend/web/pnpm-lock.yaml
@@ -47,6 +47,9 @@ dependencies:
compare-versions:
specifier: ^6.1.1
version: 6.1.1
+ dateformat:
+ specifier: ^5.0.3
+ version: 5.0.3
fracturedjsonjs:
specifier: ^4.0.2
version: 4.0.2
@@ -211,6 +214,9 @@ devDependencies:
'@storybook/theming':
specifier: ^8.3.4
version: 8.3.4(storybook@8.3.4)
+ '@types/dateformat':
+ specifier: ^5.0.2
+ version: 5.0.2
'@types/lodash-es':
specifier: ^4.17.12
version: 4.17.12
@@ -3407,6 +3413,10 @@ packages:
'@types/d3-zoom': 3.0.8
dev: false
+ /@types/dateformat@5.0.2:
+ resolution: {integrity: sha512-M95hNBMa/hnwErH+a+VOD/sYgTmo15OTYTM2Hr52/e0OdOuY+Crag+kd3/ioZrhg0WGbl9Sm3hR7UU+MH6rfOw==}
+ dev: true
+
/@types/diff-match-patch@1.0.36:
resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
dev: false
@@ -4832,6 +4842,11 @@ packages:
'@babel/runtime': 7.25.7
dev: true
+ /dateformat@5.0.3:
+ resolution: {integrity: sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==}
+ engines: {node: '>=12.20'}
+ dev: false
+
/de-indent@1.0.2:
resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
dev: true
diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItem.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItem.tsx
index a1744fc0ab..fa03ddf986 100644
--- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItem.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItem.tsx
@@ -10,6 +10,7 @@ import {
} from '@invoke-ai/ui-library';
import { EMPTY_OBJECT } from 'app/store/constants';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import dateFormat, { masks } from 'dateformat';
import { $isWorkflowListMenuIsOpen } from 'features/nodes/store/workflowListMenu';
import { selectWorkflowId, workflowModeChanged } from 'features/nodes/store/workflowSlice';
import { useDeleteLibraryWorkflow } from 'features/workflowLibrary/hooks/useDeleteLibraryWorkflow';
@@ -21,6 +22,8 @@ import { useTranslation } from 'react-i18next';
import { PiDownloadSimpleBold, PiPencilBold, PiTrashBold } from 'react-icons/pi';
import type { WorkflowRecordListItemDTO } from 'services/api/types';
+import { WorkflowListItemTooltip } from './WorkflowListItemTooltip';
+
export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListItemDTO }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const { t } = useTranslation();
@@ -87,14 +90,31 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
onMouseOut={handleMouseOut}
alignItems="center"
>
-
- {workflow.name}
+ }>
+
+
+ {workflow.name}
+
+ {isActive && (
+
+ {t('workflows.opened')}
+
+ )}
+
+ {workflow.category !== 'default' && (
+
+ {t('common.updated')}: {dateFormat(workflow.updated_at, masks.shortDate)}{' '}
+ {dateFormat(workflow.updated_at, masks.shortTime)}
+
+ )}
+
- {isActive && (
-
- {t('workflows.opened')}
-
- )}
diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItemTooltip.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItemTooltip.tsx
new file mode 100644
index 0000000000..5b2fb75240
--- /dev/null
+++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListItemTooltip.tsx
@@ -0,0 +1,26 @@
+import { Flex, Text } from '@invoke-ai/ui-library';
+import dateFormat, { masks } from 'dateformat';
+import { useTranslation } from 'react-i18next';
+import type { WorkflowRecordListItemDTO } from 'services/api/types';
+
+export const WorkflowListItemTooltip = ({ workflow }: { workflow: WorkflowRecordListItemDTO }) => {
+ const { t } = useTranslation();
+ return (
+
+ {workflow.description}
+ {workflow.category !== 'default' && (
+
+
+ {t('workflows.opened')}: {dateFormat(workflow.opened_at, masks.shortDate)}
+
+
+ {t('common.updated')}: {dateFormat(workflow.updated_at, masks.shortDate)}
+
+
+ {t('common.created')}: {dateFormat(workflow.created_at, masks.shortDate)}
+
+
+ )}
+
+ );
+};
diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListMenu.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListMenu.tsx
index 94126b33f4..863750faae 100644
--- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListMenu.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/WorkflowListMenu/WorkflowListMenu.tsx
@@ -1,6 +1,7 @@
import { Flex, Spinner } from '@invoke-ai/ui-library';
import { useStore } from '@nanostores/react';
import { EMPTY_ARRAY } from 'app/store/constants';
+import { $projectId } from 'app/store/nanostores/projectId';
import { $workflowCategories } from 'app/store/nanostores/workflowCategories';
import { useAppSelector } from 'app/store/storeHooks';
import { selectWorkflowSearchTerm } from 'features/nodes/store/workflowSlice';
@@ -14,8 +15,9 @@ import WorkflowSearch from './WorkflowSearch';
export const WorkflowListMenu = () => {
const searchTerm = useAppSelector(selectWorkflowSearchTerm);
+ const projectId = useStore($projectId);
const { data, isLoading } = useListWorkflowsQuery(
- {},
+ { order_by: projectId ? 'created_at' : 'opened_at' },
{
selectFromResult: ({ data, isLoading }) => {
const filteredData =