Skip to content

Commit

Permalink
fix: 🐛 解决切换属性面板,表单数据不同步的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
limaofeng committed Aug 28, 2021
1 parent ed5f440 commit 3727497
Show file tree
Hide file tree
Showing 20 changed files with 278 additions and 89 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
stories/**
7 changes: 6 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: ['14.x']
node: ["14.x"]
os: [ubuntu-latest]

steps:
Expand All @@ -28,5 +28,10 @@ jobs:
- name: Test
run: yarn test --ci --coverage --maxWorkers=2

- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Build
run: yarn build
15 changes: 14 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,10 @@
"conventional-changelog-cli": "^2.1.1",
"cssnano": "^4.1.11",
"eslint-plugin-prettier": "^3.4.0",
"fake-indexeddb": "^3.1.3",
"graphql": "^15.5.1",
"husky": "^7.0.0",
"identity-obj-proxy": "^3.0.0",
"less": "^4.1.1",
"less-loader": "^7.3.0",
"lodash-es": "^4.17.21",
Expand All @@ -109,7 +111,7 @@
"react-router-dom": "^5.2.0",
"rollup-plugin-postcss": "^4.0.0",
"size-limit": "^5.0.1",
"sunmao": "^0.2.4",
"sunmao": "^0.2.5",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"tsdx": "^0.14.1",
"tslib": "^2.3.0",
Expand All @@ -118,5 +120,16 @@
"resolutions": {
"**/@typescript-eslint/eslint-plugin": "^4.1.1",
"**/@typescript-eslint/parser": "^4.1.1"
},
"jest": {
"moduleNameMapper": {
"^lodash-es$": "lodash",
"^lodash-es/.*": "lodash",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "identity-obj-proxy"
},
"setupFiles": [
"<rootDir>/test/globals-test.ts"
]
}
}
2 changes: 2 additions & 0 deletions src/AsanyEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { ComponentType, useCallback, useEffect, useReducer } from 'react'

import { isElement, isValidElementType } from 'react-is';
import classnames from 'classnames';
import 'overlayscrollbars/css/OverlayScrollbars.css';

import { AsanyProvider } from './AsanyContext';
import Aside from './components/aside';
Expand Down Expand Up @@ -65,6 +66,7 @@ function Editor({
return;
}
dispatch({ type: ActionType.BindSave, payload: onSave });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [onSave]);

const handleResize = useCallback((x) => {
Expand Down
17 changes: 16 additions & 1 deletion src/api/AsideHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import React from 'react';

import { TabPane } from '../components/aside/PropertiesPanel';
import { ActionType } from '../reducers/actions';
import type { AsideHelper, AsideTabPane, IAsanyEditor, IUIAsideState, PanelOptions, UndoFunc } from '../typings';
import type {
AsideHelper,
AsideTabPane,
IAsanyEditor,
IUIAsideState,
PanelOptions,
SunmaoCustomizer,
UndoFunc,
} from '../typings';

export default class AsideHelperImpl implements AsideHelper {
private editor: IAsanyEditor;
Expand All @@ -20,9 +28,16 @@ export default class AsideHelperImpl implements AsideHelper {
}
aside.control.current.next(title, React.createElement(body));
}
open(data: SunmaoCustomizer, options?: PanelOptions): void;
open(tabs: AsideTabPane[], options?: PanelOptions): void | UndoFunc;
open(title: string, body: ComponentType<any>, options?: PanelOptions): void | UndoFunc;
open(title: any, body?: any) {
if (typeof title !== 'string' && !title.hasOwnProperty('length')) {
return this.editor.store.dispatch({
type: ActionType.OpenAside,
payload: { block: title, options: arguments[1] },
});
}
let options;
const tabs: TabPane[] = [];
if (typeof title === 'string') {
Expand Down
51 changes: 34 additions & 17 deletions src/components/aside/Aside.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';

import { isEqual } from 'lodash-es';

import { useDispatch, useSelector } from '../../hooks';
import { UIActionType } from '../../reducers/actions';
import { visibleFilter } from '../../utils';
import { DynaActionFormContext } from '../../utils/BlockAside';
import { DynaActionFormContext, buildAside } from '../../utils/BlockAside';

import ConfigurationToolbar from './ConfigurationToolbar';
import PropertiesPanel, { IPropertiesPanel } from './PropertiesPanel';
Expand All @@ -22,26 +22,31 @@ function Aside(_: AsideProps) {
const dispatch = useDispatch();

const [top, setTop] = useState(60);

const externalTabs = useSelector((state) => state.ui.aside.tabs);
const width = useSelector((state) => state.ui.aside.options?.width || 240);
const initialValue = useSelector((state) => state.ui.aside.options?.value);
const handleChange = useSelector((state) => state.ui.aside.options?.update);
const watchValue = useSelector((state) => state.ui.aside.options?.watchValue, isEqual);
const scenaToolbarVisible = useSelector((state) => state.ui.scena.toolbar.visible);

const [value, setValue] = useState(initialValue);
const customizer = useSelector((state) => state.ui.aside.block?.customizer);
const initialValue = useSelector((state) => state.ui.aside.block?.value);
const handleChange = useSelector((state) => state.ui.aside.block?.update);
const watchValue = useSelector((state) => state.ui.aside.block?.watchValue, isEqual);

useEffect(() => {
setValue(initialValue);
}, [initialValue]);
const cache = useRef({ value: initialValue });

const [, forceRender] = useReducer((s) => s + 1, 0);

useEffect(() => {
if (!watchValue) {
return;
}
return watchValue(setValue);
return watchValue((value) => {
cache.current = value;
forceRender();
});
}, [watchValue]);

// eslint-disable-next-line react-hooks/exhaustive-deps
const handleClose = useCallback(() => dispatch({ type: UIActionType.CloseAside }), []);

const configuration = useRef<IPropertiesPanel>(null);
Expand All @@ -51,14 +56,26 @@ function Aside(_: AsideProps) {
type: UIActionType.AsideRef,
payload: configuration,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const tabs = useMemo(() => {
return externalTabs.map((item) => ({
...item,
content: <item.content onChange={handleChange} />,
}));
}, [externalTabs]);
cache.current.value = initialValue;
if (customizer) {
return buildAside(customizer).map((item) => ({
...item,
content: <item.content value={cache.current.value} onChange={handleChange} />,
}));
}
if (externalTabs) {
return externalTabs.map((item) => ({
...item,
content: <item.content value={cache.current.value} onChange={handleChange} />,
}));
}
return [];
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [externalTabs, customizer]);

useEffect(() => {
const { container } = configuration.current!;
Expand All @@ -68,7 +85,7 @@ function Aside(_: AsideProps) {
}, [scenaToolbarVisible]);

return (
<DynaActionFormContext.Provider value={value}>
<DynaActionFormContext.Provider value={cache.current.value}>
<PropertiesPanel
className="sketch-configuration"
ref={configuration}
Expand All @@ -77,7 +94,7 @@ function Aside(_: AsideProps) {
width,
...(visible ? {} : { transform: `translate3d(${width}px, 0, 0)` }),
}}
tabs={tabs.filter(visibleFilter(value))}
tabs={tabs.filter(visibleFilter(cache.current.value))}
footer={<ConfigurationToolbar />}
onClose={handleClose}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/aside/PropertiesPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function PropertiesPanel(props: PropertiesPanelProps, ref: React.ForwardedRef<IP
);

const { nextIndex, panels } = state.current;
const hasNextPanel = nextIndex != -1;
const hasNextPanel = nextIndex !== -1;
return (
<div ref={container} className={classnames('settings-menu-container', className)} style={style}>
<div id="entry-controls">
Expand Down
1 change: 1 addition & 0 deletions src/components/scena/viewport/MoveableManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function MoveableManager(props: MoveableManagerProps) {
return () => {
window.removeEventListener('resize', handeWindowResize);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const elementGuidelines = Array.from(moveableData.getTargets()).filter((el) => {
Expand Down
33 changes: 20 additions & 13 deletions src/properties/DynaActionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';

import { ComponentPropertyRendererSetting, ICustomizer, IField, IGroup, useSunmao } from 'sunmao';
import { ComponentPropertyRendererSetting, ICustomizer, IField, IGroup, useDebugger, useSunmao } from 'sunmao';
import isEqual from 'lodash/isEqual';
import classnames from 'classnames';

Expand Down Expand Up @@ -109,16 +109,18 @@ PanelBody.defaultProps = {
const DynaActionForm = ({ library = 'cn.asany.editor.form', ...props }: DynaActionFormProps): JSX.Element => {
const { value = {}, onChange, customizer } = props;

const console = useDebugger();
const sunmao = useSunmao();

const [groups, setGroups] = useState<IGroup[]>([]);
const defaultValue = useRef<any>({});
const [form, Form] = useFormState();

useEffect(() => {
if (!customizer) {
return;
}
const defaultValue: { [key: string]: string } = {};
defaultValue.current = {};
groups.length = 0;
setGroups(
customizer.fields
Expand All @@ -142,7 +144,7 @@ const DynaActionForm = ({ library = 'cn.asany.editor.form', ...props }: DynaActi
renderer: getRenderer(sunmao, library, definition),
});
}
defaultValue[definition.name] = definition.defaultValue;
defaultValue.current[definition.name] = definition.defaultValue;
return groups;
}, [])
.map((group) => {
Expand All @@ -152,23 +154,28 @@ const DynaActionForm = ({ library = 'cn.asany.editor.form', ...props }: DynaActi
return group;
})
);
form.setFieldsValue({ ...defaultValue, ...value });
const fieldsValue = { ...defaultValue.current, ...value };
form.setFieldsValue(fieldsValue);
console.log('表单配置:', customizer);
console.log('表单初始数据:', 'DefaultValue = ', defaultValue.current, 'FieldsValue = ', fieldsValue);
return () => {
form.resetFields();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [customizer]);

const handleValuesChange = (_: any, allValues: any) => {
// console.log('blockProps????????表单回显', allValues);
const handleValuesChange = useCallback((_: any, allValues: any) => {
console.log('表单更新', allValues);
onChange && onChange(allValues);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

// useEffect(() => {
// if (value && !isEqual(form.getFieldsValue(), value)) {
// form.setFieldsValue({ ...defaultValue, ...value });
// }
// }, [value]);
useEffect(() => {
if (value && !isEqual(form.getFieldsValue(), value)) {
form.setFieldsValue({ ...defaultValue.current, ...value });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value]);

return (
<Form form={form} component={false} name="control-hooks" onValuesChange={handleValuesChange}>
Expand Down
1 change: 0 additions & 1 deletion src/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export const defaultValue = (mode: AsanyProviderMode, plugins: EditorPlugin[]):
};

export default (state: IAsanyState, action: AsanyAction<any>) => {
console.log('debug', action);
if (action.type === ProjectActionType.ChangeCase) {
const project = action.payload;
let newState = reducers(state, action);
Expand Down
1 change: 0 additions & 1 deletion src/reducers/plugin.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export default function reducer(
action: AsanyAction<IPluginActionType | GlobalAsanyAction>
): IPluginState {
if (GlobalAsanyAction.Init === action.type) {
console.log('GlobalAsanyAction', '--->', action);
return { ...state, ...defaultState };
}
return state;
Expand Down
1 change: 0 additions & 1 deletion src/reducers/ui.reducer/aside.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { AsanyAction, IUIAsideState } from '../../typings';

const defaultState: IUIAsideState = {
visible: false,
tabs: [],
};

export default function reducer(
Expand Down
6 changes: 0 additions & 6 deletions src/style/asany-editor.less
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@ ul, h1, p {
opacity: 0;
}
}

.handle {
z-index: 10;
width: 3px;
height: 100%;
}
}
.sidebar-panel {
display: flex;
Expand Down
19 changes: 14 additions & 5 deletions src/typings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { CSSProperties, ComponentType, ReactElement } from 'react';

import { ICustomizer } from 'sunmao';

import { DispatchWithoutAction, IAsanyStoreContext } from './AsanyContext';
import { Selector } from './hooks/useSelector';
import MoveableData from './utils/MoveableData';
Expand Down Expand Up @@ -370,13 +372,19 @@ export interface SidebarHelper {
export interface PanelOptions {
top?: number | 'auto';
width?: number;
value?: void;
watchValue?: (callback: (value: any) => void) => () => void;
update?: (value: any) => void;
}

export type SunmaoCustomizer = {
id?: string;
customizer: ICustomizer;
value?: any;
watchValue?: (callback: (value: any) => void) => () => void;
update: (value: any) => void;
};

export interface AsideHelper {
state: IUIAsideState;
open(data: SunmaoCustomizer, options?: PanelOptions): void;
open(tabs: AsideTabPane[], options?: PanelOptions): void;
open(title: string, body: ComponentType<any>, options?: PanelOptions): void;
next(title: string, body: ComponentType<any>): void;
Expand Down Expand Up @@ -426,7 +434,7 @@ export interface IAsanyEditor {
dispatch: DispatchWithoutAction<any>;
}

type AsanyProjectType = 'component';
type AsanyProjectType = string;

interface AsanyProject<D = any, T = AsanyProjectType> {
id: string;
Expand Down Expand Up @@ -594,7 +602,8 @@ export interface IUIState {

export interface IUIAsideState {
control?: React.RefObject<any>;
tabs: AsideTabPane[];
tabs?: AsideTabPane[];
block?: SunmaoCustomizer;
options?: PanelOptions;
visible: boolean;
}
Expand Down
Loading

0 comments on commit 3727497

Please sign in to comment.