mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat: add 'project' workflow category
This commit is contained in:
@ -32,6 +32,7 @@ class WorkflowRecordOrderBy(str, Enum, metaclass=MetaEnum):
|
|||||||
class WorkflowCategory(str, Enum, metaclass=MetaEnum):
|
class WorkflowCategory(str, Enum, metaclass=MetaEnum):
|
||||||
User = "user"
|
User = "user"
|
||||||
Default = "default"
|
Default = "default"
|
||||||
|
Project = "project"
|
||||||
|
|
||||||
|
|
||||||
class WorkflowMeta(BaseModel):
|
class WorkflowMeta(BaseModel):
|
||||||
|
@ -1626,7 +1626,8 @@
|
|||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
"workflowLibrary": "Workflow Library",
|
"workflowLibrary": "Workflow Library",
|
||||||
"userWorkflows": "My Workflows",
|
"userWorkflows": "My Workflows",
|
||||||
"defaultWorkflows": "Default Workflows",
|
"defaultWorkflows": "Defaults",
|
||||||
|
"projectWorkflows": "Project",
|
||||||
"openWorkflow": "Open Workflow",
|
"openWorkflow": "Open Workflow",
|
||||||
"uploadWorkflow": "Upload Workflow",
|
"uploadWorkflow": "Upload Workflow",
|
||||||
"deleteWorkflow": "Delete Workflow",
|
"deleteWorkflow": "Delete Workflow",
|
||||||
@ -1636,9 +1637,7 @@
|
|||||||
"saveWorkflowAs": "Save Workflow As",
|
"saveWorkflowAs": "Save Workflow As",
|
||||||
"problemSavingWorkflow": "Problem Saving Workflow",
|
"problemSavingWorkflow": "Problem Saving Workflow",
|
||||||
"workflowSaved": "Workflow Saved",
|
"workflowSaved": "Workflow Saved",
|
||||||
"noRecentWorkflows": "No Recent Workflows",
|
"noWorkflows": "No Workflows",
|
||||||
"noUserWorkflows": "No User Workflows",
|
|
||||||
"noSystemWorkflows": "No System Workflows",
|
|
||||||
"problemLoading": "Problem Loading Workflows",
|
"problemLoading": "Problem Loading Workflows",
|
||||||
"loading": "Loading Workflows",
|
"loading": "Loading Workflows",
|
||||||
"noDescription": "No description",
|
"noDescription": "No description",
|
||||||
|
@ -14,7 +14,7 @@ export type XYPosition = z.infer<typeof zXYPosition>;
|
|||||||
export const zDimension = z.number().gt(0).nullish();
|
export const zDimension = z.number().gt(0).nullish();
|
||||||
export type Dimension = z.infer<typeof zDimension>;
|
export type Dimension = z.infer<typeof zDimension>;
|
||||||
|
|
||||||
export const zWorkflowCategory = z.enum(['user', 'default']);
|
export const zWorkflowCategory = z.enum(['user', 'default', 'project']);
|
||||||
export type WorkflowCategory = z.infer<typeof zWorkflowCategory>;
|
export type WorkflowCategory = z.infer<typeof zWorkflowCategory>;
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ import {
|
|||||||
Spacer,
|
Spacer,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { SelectItem } from '@mantine/core';
|
import { SelectItem } from '@mantine/core';
|
||||||
|
import { useStore } from '@nanostores/react';
|
||||||
|
import { $projectId } from 'app/store/nanostores/projectId';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import {
|
import {
|
||||||
IAINoContentFallback,
|
IAINoContentFallback,
|
||||||
@ -35,13 +37,16 @@ import { useDebounce } from 'use-debounce';
|
|||||||
|
|
||||||
const PER_PAGE = 10;
|
const PER_PAGE = 10;
|
||||||
|
|
||||||
const ORDER_BY_DATA: SelectItem[] = [
|
const BASE_ORDER_BY_DATA: SelectItem[] = [
|
||||||
{ value: 'opened_at', label: 'Opened' },
|
|
||||||
{ value: 'created_at', label: 'Created' },
|
{ value: 'created_at', label: 'Created' },
|
||||||
{ value: 'updated_at', label: 'Updated' },
|
{ value: 'updated_at', label: 'Updated' },
|
||||||
{ value: 'name', label: 'Name' },
|
{ value: 'name', label: 'Name' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const OPENED_AT_ORDER_BY_EXTRAS: SelectItem[] = [
|
||||||
|
{ value: 'opened_at', label: 'Opened' },
|
||||||
|
];
|
||||||
|
|
||||||
const DIRECTION_DATA: SelectItem[] = [
|
const DIRECTION_DATA: SelectItem[] = [
|
||||||
{ value: 'ASC', label: 'Ascending' },
|
{ value: 'ASC', label: 'Ascending' },
|
||||||
{ value: 'DESC', label: 'Descending' },
|
{ value: 'DESC', label: 'Descending' },
|
||||||
@ -55,14 +60,21 @@ const WorkflowLibraryList = () => {
|
|||||||
const [order_by, setOrderBy] = useState<WorkflowRecordOrderBy>('opened_at');
|
const [order_by, setOrderBy] = useState<WorkflowRecordOrderBy>('opened_at');
|
||||||
const [direction, setDirection] = useState<SQLiteDirection>('ASC');
|
const [direction, setDirection] = useState<SQLiteDirection>('ASC');
|
||||||
const [debouncedQuery] = useDebounce(query, 500);
|
const [debouncedQuery] = useDebounce(query, 500);
|
||||||
|
const projectId = useStore($projectId);
|
||||||
|
const orderByData = useMemo<SelectItem[]>(() => {
|
||||||
|
if (category === 'project') {
|
||||||
|
return BASE_ORDER_BY_DATA;
|
||||||
|
}
|
||||||
|
return [...BASE_ORDER_BY_DATA, ...OPENED_AT_ORDER_BY_EXTRAS];
|
||||||
|
}, [category]);
|
||||||
|
|
||||||
const queryArg = useMemo<Parameters<typeof useListWorkflowsQuery>[0]>(() => {
|
const queryArg = useMemo<Parameters<typeof useListWorkflowsQuery>[0]>(() => {
|
||||||
if (category === 'user') {
|
if (category === 'default') {
|
||||||
return {
|
return {
|
||||||
page,
|
page,
|
||||||
per_page: PER_PAGE,
|
per_page: PER_PAGE,
|
||||||
order_by,
|
order_by: 'name' as const,
|
||||||
direction,
|
direction: 'ASC' as const,
|
||||||
category,
|
category,
|
||||||
query: debouncedQuery,
|
query: debouncedQuery,
|
||||||
};
|
};
|
||||||
@ -70,8 +82,8 @@ const WorkflowLibraryList = () => {
|
|||||||
return {
|
return {
|
||||||
page,
|
page,
|
||||||
per_page: PER_PAGE,
|
per_page: PER_PAGE,
|
||||||
order_by: 'name' as const,
|
order_by,
|
||||||
direction: 'ASC' as const,
|
direction,
|
||||||
category,
|
category,
|
||||||
query: debouncedQuery,
|
query: debouncedQuery,
|
||||||
};
|
};
|
||||||
@ -137,6 +149,15 @@ const WorkflowLibraryList = () => {
|
|||||||
setPage(0);
|
setPage(0);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleSetProjectCategory = useCallback(() => {
|
||||||
|
setCategory('project');
|
||||||
|
setPage(0);
|
||||||
|
// Projects can't be sorted by opened_at
|
||||||
|
if (order_by === 'opened_at') {
|
||||||
|
setOrderBy('name');
|
||||||
|
}
|
||||||
|
}, [order_by]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex gap={4} alignItems="center" h={10} flexShrink={0} flexGrow={0}>
|
<Flex gap={4} alignItems="center" h={10} flexShrink={0} flexGrow={0}>
|
||||||
@ -148,6 +169,15 @@ const WorkflowLibraryList = () => {
|
|||||||
>
|
>
|
||||||
{t('workflows.userWorkflows')}
|
{t('workflows.userWorkflows')}
|
||||||
</IAIButton>
|
</IAIButton>
|
||||||
|
{projectId && (
|
||||||
|
<IAIButton
|
||||||
|
variant={category === 'project' ? undefined : 'ghost'}
|
||||||
|
onClick={handleSetProjectCategory}
|
||||||
|
isChecked={category === 'project'}
|
||||||
|
>
|
||||||
|
{t('workflows.projectWorkflows')}
|
||||||
|
</IAIButton>
|
||||||
|
)}
|
||||||
<IAIButton
|
<IAIButton
|
||||||
variant={category === 'default' ? undefined : 'ghost'}
|
variant={category === 'default' ? undefined : 'ghost'}
|
||||||
onClick={handleSetDefaultCategory}
|
onClick={handleSetDefaultCategory}
|
||||||
@ -157,12 +187,12 @@ const WorkflowLibraryList = () => {
|
|||||||
</IAIButton>
|
</IAIButton>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Spacer />
|
<Spacer />
|
||||||
{category === 'user' && (
|
{category !== 'default' && (
|
||||||
<>
|
<>
|
||||||
<IAIMantineSelect
|
<IAIMantineSelect
|
||||||
label={t('common.orderBy')}
|
label={t('common.orderBy')}
|
||||||
value={order_by}
|
value={order_by}
|
||||||
data={ORDER_BY_DATA}
|
data={orderByData}
|
||||||
onChange={handleChangeOrderBy}
|
onChange={handleChangeOrderBy}
|
||||||
formControlProps={{
|
formControlProps={{
|
||||||
w: 48,
|
w: 48,
|
||||||
@ -223,7 +253,7 @@ const WorkflowLibraryList = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</ScrollableContent>
|
</ScrollableContent>
|
||||||
) : (
|
) : (
|
||||||
<IAINoContentFallback label={t('workflows.noUserWorkflows')} />
|
<IAINoContentFallback label={t('workflows.noWorkflows')} />
|
||||||
)}
|
)}
|
||||||
<Divider />
|
<Divider />
|
||||||
{data && (
|
{data && (
|
||||||
|
@ -3,5 +3,5 @@ import ReactDOM from 'react-dom/client';
|
|||||||
import InvokeAIUI from './app/components/InvokeAIUI';
|
import InvokeAIUI from './app/components/InvokeAIUI';
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||||
<InvokeAIUI />
|
<InvokeAIUI projectId="test" />
|
||||||
);
|
);
|
||||||
|
126
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
126
invokeai/frontend/web/src/services/api/schema.d.ts
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user