mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-02 15:44:57 -05:00
feat(ui): add loading state for builder
This commit is contained in:
@@ -1004,6 +1004,7 @@
|
||||
"unknownOutput": "Unknown output: {{name}}",
|
||||
"updateNode": "Update Node",
|
||||
"updateApp": "Update App",
|
||||
"loadingTemplates": "Loading {{name}}",
|
||||
"updateAllNodes": "Update Nodes",
|
||||
"allNodesUpdated": "All Nodes Updated",
|
||||
"unableToUpdateNodes_one": "Unable to update {{count}} node",
|
||||
|
||||
@@ -2,12 +2,15 @@ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
||||
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
||||
import type { SystemStyleObject } from '@invoke-ai/ui-library';
|
||||
import { Button, Flex, Spacer } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { firefoxDndFix } from 'features/dnd/util';
|
||||
import { FormElementComponent } from 'features/nodes/components/sidePanel/builder/ContainerElementComponent';
|
||||
import { buildFormElementDndData, useBuilderDndMonitor } from 'features/nodes/components/sidePanel/builder/dnd-hooks';
|
||||
import { WorkflowBuilderEditMenu } from 'features/nodes/components/sidePanel/builder/WorkflowBuilderMenu';
|
||||
import { $hasTemplates } from 'features/nodes/store/nodesSlice';
|
||||
import { selectFormRootElementId, selectIsFormEmpty } from 'features/nodes/store/workflowSlice';
|
||||
import type { FormElement } from 'features/nodes/types/workflow';
|
||||
import { buildContainer, buildDivider, buildHeading, buildText } from 'features/nodes/types/workflow';
|
||||
@@ -15,6 +18,7 @@ import { startCase } from 'lodash-es';
|
||||
import type { RefObject } from 'react';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetOpenAPISchemaQuery } from 'services/api/endpoints/appInfo';
|
||||
import { assert } from 'tsafe';
|
||||
|
||||
const sx: SystemStyleObject = {
|
||||
@@ -28,8 +32,7 @@ const sx: SystemStyleObject = {
|
||||
|
||||
export const WorkflowBuilder = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const rootElementId = useAppSelector(selectFormRootElementId);
|
||||
const isFormEmpty = useAppSelector(selectIsFormEmpty);
|
||||
|
||||
useBuilderDndMonitor();
|
||||
|
||||
return (
|
||||
@@ -47,9 +50,7 @@ export const WorkflowBuilder = memo(() => {
|
||||
<WorkflowBuilderEditMenu />
|
||||
</Flex>
|
||||
<ScrollableContent>
|
||||
<Flex sx={sx} data-is-empty={isFormEmpty}>
|
||||
<FormElementComponent id={rootElementId} />
|
||||
</Flex>
|
||||
<WorkflowBuilderContent />
|
||||
</ScrollableContent>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -57,6 +58,25 @@ export const WorkflowBuilder = memo(() => {
|
||||
});
|
||||
WorkflowBuilder.displayName = 'WorkflowBuilder';
|
||||
|
||||
const WorkflowBuilderContent = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const rootElementId = useAppSelector(selectFormRootElementId);
|
||||
const isFormEmpty = useAppSelector(selectIsFormEmpty);
|
||||
const openApiSchemaQuery = useGetOpenAPISchemaQuery();
|
||||
const loadedTemplates = useStore($hasTemplates);
|
||||
|
||||
if (openApiSchemaQuery.isLoading || !loadedTemplates) {
|
||||
return <IAINoContentFallback label={t('nodes.loadingNodes')} icon={null} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex sx={sx} data-is-empty={isFormEmpty}>
|
||||
<FormElementComponent id={rootElementId} />
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
WorkflowBuilderContent.displayName = 'WorkflowBuilderContent';
|
||||
|
||||
const useAddFormElementDnd = (
|
||||
type: Exclude<FormElement['type'], 'node-field'>,
|
||||
draggableRef: RefObject<HTMLElement>
|
||||
|
||||
@@ -10,7 +10,7 @@ export const EmptyState = () => {
|
||||
const isCleanEditor = useAppSelector(selectCleanEditor);
|
||||
|
||||
return (
|
||||
<Flex w="full" userSelect="none" justifyContent="center">
|
||||
<Flex w="full" h="full" userSelect="none" justifyContent="center">
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { FormElementComponent } from 'features/nodes/components/sidePanel/builder/ContainerElementComponent';
|
||||
import { EmptyState } from 'features/nodes/components/sidePanel/viewMode/EmptyState';
|
||||
import { $hasTemplates } from 'features/nodes/store/nodesSlice';
|
||||
import { selectFormRootElementId, selectIsFormEmpty } from 'features/nodes/store/workflowSlice';
|
||||
import { t } from 'i18next';
|
||||
import { memo } from 'react';
|
||||
@@ -13,9 +15,7 @@ export const ViewModeLeftPanelContent = memo(() => {
|
||||
return (
|
||||
<Box position="relative" w="full" h="full">
|
||||
<ScrollableContent>
|
||||
<Flex flexDir="column" w="full" maxW="768px">
|
||||
<ViewModeLeftPanelContentInner />
|
||||
</Flex>
|
||||
<ViewModeLeftPanelContentInner />
|
||||
</ScrollableContent>
|
||||
</Box>
|
||||
);
|
||||
@@ -24,10 +24,11 @@ ViewModeLeftPanelContent.displayName = 'ViewModeLeftPanelContent';
|
||||
|
||||
const ViewModeLeftPanelContentInner = memo(() => {
|
||||
const { isLoading } = useGetOpenAPISchemaQuery();
|
||||
const loadedTemplates = useStore($hasTemplates);
|
||||
const rootElementId = useAppSelector(selectFormRootElementId);
|
||||
const isFormEmpty = useAppSelector(selectIsFormEmpty);
|
||||
|
||||
if (isLoading) {
|
||||
if (isLoading || !loadedTemplates) {
|
||||
return <IAINoContentFallback label={t('nodes.loadingNodes')} icon={null} />;
|
||||
}
|
||||
|
||||
@@ -35,6 +36,10 @@ const ViewModeLeftPanelContentInner = memo(() => {
|
||||
return <EmptyState />;
|
||||
}
|
||||
|
||||
return <FormElementComponent id={rootElementId} />;
|
||||
return (
|
||||
<Flex flexDir="column" w="full" maxW="768px">
|
||||
<FormElementComponent id={rootElementId} />
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
ViewModeLeftPanelContentInner.displayName = ' ViewModeLeftPanelContentInner';
|
||||
|
||||
Reference in New Issue
Block a user