Propagate WidgetConfigs to new widget. Use theme spaces everywhere.

This commit is contained in:
Abhinav Jha 2019-10-02 23:43:04 +05:30
parent 59b3eb1d7b
commit 91fd8ff17e
15 changed files with 116 additions and 38 deletions

View File

@ -24,9 +24,9 @@ export type Theme = {
};
export const theme: Theme = {
radii: [0, 4, 8, 10, 20],
radii: [0, 4, 8, 10, 20, 50],
fontSizes: [0, 10, 12, 14, 16, 18, 24, 28, 32, 48, 64],
spaces: [0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
spaces: [0, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
fontWeights: [0, 400, 500, 700],
colors: {
primary: Colors.GREEN,

View File

@ -48,6 +48,7 @@ export const ReduxActionErrorTypes: { [key: string]: string } = {
FETCH_PAGE_ERROR: "FETCH_PAGE_ERROR",
SAVE_PAGE_ERROR: "SAVE_PAGE_ERROR",
FETCH_WIDGET_CARDS_ERROR: "FETCH_WIDGET_CARDS_ERROR",
WIDGET_OPERATION_ERROR: "WIDGET_OPERATION_ERROR",
};
export type ReduxActionErrorType = (typeof ReduxActionErrorTypes)[keyof typeof ReduxActionErrorTypes];

View File

@ -22,6 +22,7 @@ export interface BaseStyle {
export interface ComponentProps {
widgetId: string;
widgetName?: string;
style: BaseStyle;
}

View File

@ -24,6 +24,17 @@ export const Container = styled("div")<ContainerProps>`
left: 0;
top: 0;
width: 100%;
padding: ${props => props.theme.spaces[8]}px ${props =>
props.theme.spaces[1]}px ${props => props.theme.spaces[1]}px;
&:after {
content: "${props => props.widgetName}";
position: absolute;
left: ${props => props.theme.spaces[1]}px;
top: ${props => props.theme.spaces[1]}px;
font-size: ${props => props.theme.fontSizes[2]}px;
text-align: left;
width: 100%;
}
`;
export const FocusContext: Context<{

View File

@ -16,20 +16,20 @@ const ResizableContainer = styled(Resizable)`
&:before {
content: "";
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
width: ${props => props.theme.spaces[2]}px;
height: ${props => props.theme.spaces[2]}px;
border-radius: ${props => props.theme.radii[5]}%;
z-index: 9;
background: ${props => props.theme.colors.containerBorder};
}
&:after {
right: -4px;
top: 50%;
right: -${props => props.theme.spaces[1]}px;
top: calc(50% - ${props => props.theme.spaces[1]}px);
}
&:before {
left: calc(50%);
top: calc(100% - 4px);
left: calc(50% - ${props => props.theme.spaces[1]}px);
bottom: -${props => props.theme.spaces[1]}px;
}
`;
@ -50,6 +50,8 @@ export const ResizableComponent = (props: ResizableComponentProps) => {
width: props.style.componentWidth as number,
height: props.style.componentHeight as number,
}}
minWidth={props.parentColumnSpace}
minHeight={props.parentRowSpace}
style={{ ...props.style }}
onResizeStop={updateSize}
grid={[props.parentColumnSpace, props.parentRowSpace]}

View File

@ -19,7 +19,7 @@ const CardsPaneWrapper = styled.div`
const CardsWrapper = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: ${props => props.theme.spaces[2]}px;
grid-gap: ${props => props.theme.spaces[1]}px;
justify-items: stretch;
align-items: stretch;
`;

View File

@ -105,15 +105,14 @@ const mapStateToProps = (state: AppState): EditorReduxState => {
state.ui.editor.pageWidgetId,
state.entities,
);
const configs = state.entities.widgetConfig.config;
const cards = state.ui.editor.cards;
const groups: string[] = Object.keys(cards);
groups.forEach((group: string) => {
cards[group] = cards[group].map((widget: WidgetCardProps) => ({
...widget,
...configs[widget.type],
}));
cards[group] = cards[group].map((widget: WidgetCardProps) => {
const { rows, columns } = state.entities.widgetConfig.config[widget.type];
return { ...widget, rows, columns };
});
});
return {

View File

@ -24,6 +24,7 @@ export function* validateResponse(response: ApiResponse) {
export function* errorSaga(errorAction: ReduxAction<{ error: any }>) {
// Just a pass through for now.
// Add procedures to customize errors here
console.log(errorAction.payload.error);
yield put({
type: ReduxActionTypes.REPORT_ERROR,
payload: {

View File

@ -1,5 +1,6 @@
import {
ReduxActionTypes,
ReduxActionErrorTypes,
ReduxAction,
} from "../constants/ReduxActionConstants";
import {
@ -9,13 +10,19 @@ import {
WidgetDelete,
} from "../actions/pageActions";
import { FlattenedWidgetProps } from "../reducers/entityReducers/canvasWidgetsReducer";
import { getWidgets, getWidget, getWidgetParent } from "./selectors";
import {
getWidgets,
getWidget,
getWidgetParent,
getDefaultWidgetConfig,
} from "./selectors";
import {
generateWidgetProps,
updateWidgetSize,
updateWidgetPosition,
} from "../utils/WidgetPropsUtils";
import { put, select, takeEvery, takeLatest, all } from "redux-saga/effects";
import { getNextWidgetName } from "../utils/AppsmithUtils";
export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
try {
@ -31,7 +38,7 @@ export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
} = addChildAction.payload;
const widget: FlattenedWidgetProps = yield select(getWidget, widgetId);
const widgets = yield select(getWidgets);
const defaultWidgetConfig = yield select(getDefaultWidgetConfig, type);
const childWidget = generateWidgetProps(
widget,
type,
@ -41,6 +48,8 @@ export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
rows,
parentRowSpace,
parentColumnSpace,
getNextWidgetName(type, widgets),
defaultWidgetConfig,
);
widgets[childWidget.widgetId] = childWidget;
if (widget && widget.children) {
@ -51,11 +60,13 @@ export function* addChildSaga(addChildAction: ReduxAction<WidgetAddChild>) {
type: ReduxActionTypes.UPDATE_LAYOUT,
payload: { widgets },
});
} catch (err) {
} catch (error) {
yield put({
type: ReduxActionTypes.WIDGET_OPERATION_ERROR,
action: ReduxActionTypes.WIDGET_ADD_CHILD,
...err,
type: ReduxActionErrorTypes.WIDGET_OPERATION_ERROR,
payload: {
action: ReduxActionTypes.WIDGET_ADD_CHILD,
error,
},
});
}
}
@ -74,12 +85,13 @@ export function* deleteSaga(deleteAction: ReduxAction<WidgetDelete>) {
type: ReduxActionTypes.UPDATE_LAYOUT,
payload: { widgets },
});
} catch (err) {
console.log(err);
} catch (error) {
yield put({
type: ReduxActionTypes.WIDGET_OPERATION_ERROR,
action: ReduxActionTypes.WIDGET_DELETE,
...err,
type: ReduxActionErrorTypes.WIDGET_OPERATION_ERROR,
payload: {
action: ReduxActionTypes.WIDGET_DELETE,
error,
},
});
}
}
@ -110,11 +122,13 @@ export function* moveSaga(moveAction: ReduxAction<WidgetMove>) {
type: ReduxActionTypes.UPDATE_LAYOUT,
payload: { widgets },
});
} catch (err) {
} catch (error) {
yield put({
type: ReduxActionTypes.WIDGET_OPERATION_ERROR,
action: ReduxActionTypes.WIDGET_MOVE,
...err,
type: ReduxActionErrorTypes.WIDGET_OPERATION_ERROR,
payload: {
action: ReduxActionTypes.WIDGET_MOVE,
error,
},
});
}
}
@ -133,11 +147,13 @@ export function* resizeSaga(resizeAction: ReduxAction<WidgetResize>) {
type: ReduxActionTypes.UPDATE_LAYOUT,
payload: { widgets },
});
} catch (err) {
} catch (error) {
yield put({
type: ReduxActionTypes.WIDGET_OPERATION_ERROR,
action: ReduxActionTypes.WIDGET_RESIZE,
...err,
type: ReduxActionErrorTypes.WIDGET_OPERATION_ERROR,
payload: {
action: ReduxActionTypes.WIDGET_RESIZE,
error,
},
});
}
}

View File

@ -1,7 +1,7 @@
import { AppState } from "../reducers";
import { FlattenedWidgetProps } from "../reducers/entityReducers/canvasWidgetsReducer";
import { WidgetProps } from "../widgets/BaseWidget";
import { WidgetType } from "../constants/WidgetConstants";
export const getWidgets = (
state: AppState,
): { [widgetId: string]: FlattenedWidgetProps } => {
@ -35,3 +35,14 @@ export const getWidgetParent = (
widget.children.indexOf(widgetId) > -1,
);
};
export const getDefaultWidgetConfig = (
state: AppState,
type: WidgetType,
): Partial<WidgetProps> => {
const configs = state.entities.widgetConfig.config;
const widgetConfig = { ...configs[type] };
delete widgetConfig.rows;
delete widgetConfig.columns;
return widgetConfig;
};

View File

@ -12,6 +12,8 @@ import FontFaceObserver from "fontfaceobserver";
import PropertyControlRegistry from "./PropertyControlRegistry";
import WidgetBuilderRegistry from "./WidgetRegistry";
import { Property } from "../api/ActionAPI";
import { WidgetType } from "../constants/WidgetConstants";
import { FlattenedWidgetProps } from "../reducers/entityReducers/canvasWidgetsReducer";
import _ from "lodash";
export const createReducer = (
@ -60,3 +62,29 @@ export const mapToPropList = (map: Record<string, string>): Property[] => {
return { key: key, value: value };
});
};
export const getNextWidgetName = (
type: WidgetType,
widgets: {
[id: string]: FlattenedWidgetProps;
},
) => {
const prefix = type
.split("_")
.filter(token => token !== "WIDGET")
.join("")
.toLowerCase();
const usedIndices: number[] = Object.values(widgets).map(widget => {
if (widget.type === type) {
const ind = widget.widgetName
? parseInt(widget.widgetName.split(prefix)[1], 10)
: 0;
return Number.isNaN(ind) ? 0 : ind;
}
return 0;
}) as number[];
const lastIndex = Math.max(...usedIndices);
return prefix + (lastIndex + 1);
};

View File

@ -211,6 +211,8 @@ export const generateWidgetProps = (
rows: number,
parentRowSpace: number,
parentColumnSpace: number,
widgetName: string,
widgetConfig: Partial<WidgetProps>,
): ContainerWidgetProps<WidgetProps> => {
if (parent && parent.snapColumns && parent.snapRows) {
const sizes = {
@ -229,11 +231,13 @@ export const generateWidgetProps = (
background: Colors.WHITE,
};
}
console.log(widgetConfig);
return {
...widgetConfig,
type,
executeAction: () => {},
widgetId: generateReactKey(),
widgetName: generateReactKey(), //TODO: figure out what this is to populate appropriately
widgetName: widgetName || generateReactKey(), //TODO: figure out what this is to populate appropriately
isVisible: true,
parentColumnSpace,
parentRowSpace,

View File

@ -14,6 +14,7 @@ class ButtonWidget extends BaseWidget<ButtonWidgetProps, WidgetState> {
<ButtonComponent
style={this.getPositionStyle()}
widgetId={this.props.widgetId}
widgetName={this.props.widgetName}
key={this.props.widgetId}
text={this.props.text}
onClick={() => {

View File

@ -35,9 +35,10 @@ class ContainerWidget extends BaseWidget<
super.componentDidUpdate(previousProps);
let snapColumnSpace = this.state.snapColumnSpace;
if (this.state.componentWidth)
snapColumnSpace =
snapColumnSpace = Math.floor(
this.state.componentWidth /
(this.props.snapColumns || DEFAULT_GRID_COLUMNS);
(this.props.snapColumns || DEFAULT_GRID_COLUMNS),
);
if (this.state.snapColumnSpace !== snapColumnSpace) {
this.setState({
snapColumnSpace,
@ -67,6 +68,7 @@ class ContainerWidget extends BaseWidget<
}}
isRoot={!this.props.parentId}
orientation={this.props.orientation || "VERTICAL"}
widgetName={this.props.widgetName}
>
{_.map(this.props.children, this.renderChildWidget)}
</ContainerComponent>

View File

@ -10,6 +10,7 @@ class SpinnerWidget extends BaseWidget<SpinnerWidgetProps, WidgetState> {
<SpinnerComponent
style={this.getPositionStyle()}
widgetId={this.props.widgetId}
widgetName={this.props.widgetName}
key={this.props.widgetId}
size={this.props.size}
value={this.props.value}