Skip to content

Commit

Permalink
Dev opti (#15)
Browse files Browse the repository at this point in the history
Co-authored-by: shanexi <[email protected]>
Co-authored-by: joe <[email protected]>
  • Loading branch information
3 people authored Sep 20, 2024
1 parent 9a58470 commit db820a8
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 34 deletions.
47 changes: 47 additions & 0 deletions .github/workflows/sync-open-source-main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Sync open-source main

on:
push:
branches:
- main
paths:
- "web/apps/web/**"
- "web/packages/**"
- ".github/**"

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Get last commit author email
id: get_email
run: echo "COMMIT_AUTHOR_EMAIL=$(git log -n 1 --pretty=format:%ae)" >> $GITHUB_ENV

- name: Test author email
run: echo "The commit author email is $COMMIT_AUTHOR_EMAIL"

- name: Get last commit author name
id: get_name
run: echo "COMMIT_AUTHOR_NAME=$(git log -n 1 --pretty=format:%an)" >> $GITHUB_ENV

- name: Test author name
run: echo "The commit author name is $COMMIT_AUTHOR_NAME"

- uses: cpina/github-action-push-to-another-repository@main
env:
SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }}
with:
source-directory: web
target-directory: web
destination-github-username: "myshell-ai"
destination-repository-name: "open-source"
target-branch: main
create-target-branch-if-needed: false
user-name: ${{ env.COMMIT_AUTHOR_NAME }}
user-email: ${{ env.COMMIT_AUTHOR_EMAIL }}

- name: Test get variable exported by push-to-another-repository
run: echo $DESTINATION_CLONED_DIRECTORY
19 changes: 19 additions & 0 deletions web/.husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh
# . "$(dirname "$0")/_/husky.sh"


echo "===\n>> Pre-push Hook: Checking branch name..."

cd web

BRANCH=`git rev-parse --abbrev-ref HEAD`
PROTECTED_BRANCHES="^(main|test)"

if [[ "$BRANCH" =~ $PROTECTED_BRANCHES ]]
then
echo "\n🚫 Cannot push to remote $BRANCH branch, please create your own branch and use PR."
fi

echo ">> Finish checking branch name.\n==="

exit 0
23 changes: 4 additions & 19 deletions web/apps/web/src/components/workflow/import-modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ const ImportModal: React.FC<{
onOpenChange: (open: boolean) => void;
}> = ({ open, onOpenChange }) => {
const [openTips, setOpenTips] = useBoolean(false);
const [isExpand, isExpandAction] = useBoolean(false);
const [fileUrl, setFileUrl] = useState<string | undefined>();
const [workflow, setWorkflow] = useState<Workflow | undefined>();
const { existedInfo, importWorkflow, setExistedInfo } = useWorkflowStore(
Expand Down Expand Up @@ -204,31 +203,17 @@ const ImportModal: React.FC<{
</AlertDialogTitle>
</AlertDialogHeader>
<AlertDialogDescription className="flex flex-col gap-1.5">
<Heading size="h2">Warning</Heading>
<Heading size="h2">Missing Items</Heading>
<Text size="sm" color="subtle">
The following items are missing.
<br />
Replace it with installed models/widgets, or contact us to add
it to the standard environment.
If this workflow would run in MyShell, please replace the
missing models/widgets with similar installed ones, or contact
us to add them to the standard environment.
</Text>
<div
className="flex items-center cursor-pointer"
onClick={() => isExpandAction.toggle()}>
<Text size="sm" color="subtler">
{isExpand ? 'Show Less' : 'View Detail'}
</Text>
<ChevronDownIcon
className={cn('w-4 h-4 ml-1.5 text-subtler', {
'rotate-180': isExpand,
})}
/>
</div>
<div
className={cn(
'flex-1 rounded-lg border border-default p-3 w-[340px] max-h-60 overflow-x-hidden',
{
hidden: !isExpand,
},
)}>
{!isEmpty(existedInfo.non_existed_models) ? (
<div>
Expand Down
25 changes: 20 additions & 5 deletions web/apps/web/src/components/workflow/node-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,19 @@ const NodeCard: React.FC<
NodeData & {
children: React.ReactNode;
selected?: boolean;
has_error?: boolean;
mode?: string;
}
> = ({ id, children, runtime_data, selected, name, display_name, mode }) => {
> = ({
id,
children,
runtime_data,
selected,
name,
display_name,
mode,
has_error,
}) => {
const selectRef = useRef(null);
const active = useHover(selectRef);
const isUndefined = mode === 'undefined';
Expand All @@ -35,7 +45,9 @@ const NodeCard: React.FC<
},
{
'!border-critical':
runtime_data?.node_status === NodeStatusEnum.failed || isUndefined,
runtime_data?.node_status === NodeStatusEnum.failed ||
isUndefined ||
has_error,
},
{
'!border-brand': runtime_data?.node_status === NodeStatusEnum.start,
Expand All @@ -48,17 +60,20 @@ const NodeCard: React.FC<
<SchemaProvider
id={id}
name={name}
mode={mode}
display_name={display_name}
output={runtime_data?.output}>
<ContextMenu>
{isUndefined ? (
<div className="pb-2">
<Heading size="h1" color="critical">
Undefined Widget
Missing Widget
</Heading>
{/* <Text color="critical">Missing Model</Text> */}
<br />
<Text color="critical">
Replace it with installed widgets, or contact us to add it to
the standard environment.
Replace it with installed widgets/models, or contact us to add
it to the standard environment.
</Text>
</div>
) : null}
Expand Down
15 changes: 14 additions & 1 deletion web/apps/web/src/components/workflow/node-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,22 @@ interface NodeFormProps {
loading?: boolean;
modeMap?: Record<string, TFieldMode>;
onModeChange?: (name: string, mode: TFieldMode) => void;
onStatusChange?: (status: { [key: string]: string }) => void;
}

const NodeForm = forwardRef<FormRef, NodeFormProps>(
({ values, onChange, schema, loading, onModeChange, modeMap }, ref) => {
(
{
values,
onChange,
schema,
loading,
onModeChange,
onStatusChange,
modeMap,
},
ref,
) => {
const { schema: formSchema, formKey } = useSchemaContext(state => ({
schema: state.schema,
formKey: state.formKey,
Expand Down Expand Up @@ -78,6 +90,7 @@ const NodeForm = forwardRef<FormRef, NodeFormProps>(
schema={currentSchema}
modeMap={modeMap}
onModeChange={onModeChange}
onStatusChange={onStatusChange}
components={{
Input,
Select,
Expand Down
24 changes: 22 additions & 2 deletions web/apps/web/src/components/workflow/nodes/widget-node/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import {
import { TValues, TFieldMode } from '@shellagent/form-engine';
import { FormRef } from '@shellagent/ui';
import { useKeyPress } from 'ahooks';
import React, { useCallback, useRef, useEffect } from 'react';
import React, {
useCallback,
useRef,
useEffect,
useState,
useMemo,
} from 'react';
import { useShallow } from 'zustand/react/shallow';

import { useWorkflowState } from '@/stores/workflow/use-workflow-state';
Expand All @@ -21,6 +27,7 @@ import { useDuplicateState } from './hook/use-duplicate-state';
import { EventType, useEventEmitter } from '../../emitter';
import NodeCard from '../../node-card';
import NodeForm from '../../node-form';
import { some } from 'lodash-es';

const WidgetNode: React.FC<NodeProps<WidgetNodeType>> = ({
id,
Expand All @@ -29,6 +36,7 @@ const WidgetNode: React.FC<NodeProps<WidgetNodeType>> = ({
}) => {
const formRef = useRef<FormRef>(null);
const nodeRef = useRef<HTMLElement | null>(null);
const statusRef = useRef({});
const { duplicateState } = useDuplicateState(id);
const { onDelNode } = useReactFlowStore(state => ({
onDelNode: state.onDelNode,
Expand All @@ -37,6 +45,8 @@ const WidgetNode: React.FC<NodeProps<WidgetNodeType>> = ({
setCurrentCopyId: state.setCurrentCopyId,
}));

const [hasError, setHasError] = useState(false);

const {
setNodeData,
nodeData,
Expand Down Expand Up @@ -144,14 +154,24 @@ const WidgetNode: React.FC<NodeProps<WidgetNodeType>> = ({
}
});

const onStatusChange = (obj: { [key: string]: string }) => {
statusRef.current = { ...statusRef.current, ...obj };
setHasError(some(statusRef.current, value => value === 'missOption'));
};

return (
<NodeCard selected={selected} mode={nodeData[data.id]?.mode} {...data}>
<NodeCard
selected={selected}
mode={nodeData[data.id]?.mode}
has_error={some(statusRef.current, value => value === 'missOption')}
{...data}>
<NodeForm
ref={formRef}
loading={loading.getReactFlow}
values={nodeData[data.id]}
onChange={onChange}
onModeChange={onModeChange}
onStatusChange={onStatusChange}
modeMap={fieldsModeMap?.[data.id] || {}}
/>
</NodeCard>
Expand Down
10 changes: 6 additions & 4 deletions web/apps/web/src/stores/workflow/schema-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ export const useSchemaContext = <T,>(

export interface SchemaProviderProps {
id: string;
name: string | undefined;
display_name: string | undefined;
name?: string;
mode?: string;
display_name?: string;
children: React.ReactNode | React.ReactNode[];
output?: Record<string, any>;
}

export const SchemaProvider: React.FC<SchemaProviderProps> = ({
name = '',
mode,
display_name = '',
id,
children,
Expand Down Expand Up @@ -122,7 +124,7 @@ export const SchemaProvider: React.FC<SchemaProviderProps> = ({
memoized.schema = endSchema;
} else if (!isEmpty(currentWidgetSchema)) {
const schema = getSchemaByWidget({
name: display_name,
name: mode === 'undefined' ? name : display_name,
inputSchema: currentWidgetSchema?.input_schema,
outputSchema: currentWidgetSchema?.output_schema,
fieldsModeMap: currentFieldsModeMap,
Expand All @@ -142,7 +144,7 @@ export const SchemaProvider: React.FC<SchemaProviderProps> = ({
outputs: memoized.outputRefTypes,
});
return memoized;
}, [id, name, display_name, currentWidgetSchema, currentFieldsModeMap]);
}, [id, mode, name, display_name, currentWidgetSchema, currentFieldsModeMap]);

const formKey = useMemo(() => {
return `${JSON.stringify({
Expand Down
20 changes: 19 additions & 1 deletion web/apps/web/src/stores/workflow/workflow-store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ export const createWorkflowStore = () => {
);
}
if (type === EventStatusEnum.workflow_end) {
get().flowInstance?.fitView();
set(
produce(state => {
state.loading.workflowRunning = false;
Expand Down Expand Up @@ -453,11 +452,30 @@ export const createWorkflowStore = () => {
return nodes;
});
if (data?.node_status === NodeStatusEnum.failed) {
get().flowInstance?.fitView({
minZoom: 0.8,
maxZoom: 1.5,
nodes: [{ id: data?.node_id as string }],
padding: 400,
});
// 设置为选中状态,放到最上层
get().flowInstance?.setNodes(nodes =>
nodes.map(node =>
node.id === data?.node_id
? {
...node,
selected: true,
}
: node,
),
);
set(
produce(state => {
state.loading.workflowRunning = false;
}),
);
} else {
get().flowInstance?.fitView();
}
}
},
Expand Down
19 changes: 18 additions & 1 deletion web/packages/form-engine/src/components/control/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
TooltipContent,
IconButton,
Switch,
Text,
} from '@shellagent/ui';
import { isEmpty, omit } from 'lodash-es';
import React, { useMemo, useRef, useState } from 'react';
Expand All @@ -37,7 +38,7 @@ type Mode = 'raw' | 'ui' | 'ref';
*/
const Control: React.FC<IControlProps> = props => {
const { name } = props;
const { fields, components, remove, modeMap, onModeChange } =
const { fields, components, remove, modeMap, onModeChange, onStatusChange } =
useFormEngineContext();
const { setValue, getValues } = useFormContext();
const { schema, state, parent } = fields[name] || {};
Expand Down Expand Up @@ -284,11 +285,27 @@ const Control: React.FC<IControlProps> = props => {
if (xOnChangePropsName) {
newField[xOnChangePropsName] = field.onChange;
}
const missOption =
xComponentProps?.options?.length &&
newField[valuePropsName] &&
!xComponentProps?.options?.find(
(item: { value: string }) =>
item.value === (newField[valuePropsName] as unknown as string),
);
if (missOption !== undefined) {
onStatusChange?.({ [name]: missOption ? 'missOption' : '' });
}
const FormItemWithDesc =
(!checked && xSwithable) || xHiddenControl ? null : (
<div className="grow">
<FormControl>{renderFormItem()}</FormControl>
{fieldState.error ? <FormMessage /> : null}
{missOption ? (
<Text color="critical">
{newField[valuePropsName] as unknown as string} is
undefined.
</Text>
) : null}
</div>
);

Expand Down
Loading

0 comments on commit db820a8

Please sign in to comment.