Merge branch 'release' of gitlab.com:theappsmith/internal-tools-client into release

This commit is contained in:
Nikhil Nandagopal 2019-11-12 12:06:46 +05:30
commit 2cc0e13006
4 changed files with 268 additions and 54 deletions

View File

@ -14,34 +14,91 @@ import { connect } from "react-redux";
import { AppState } from "../../reducers"; import { AppState } from "../../reducers";
import { ActionDataState } from "../../reducers/entityReducers/actionsReducer"; import { ActionDataState } from "../../reducers/entityReducers/actionsReducer";
const DEFAULT_ACTION_TYPE = "Select Action Type"; const DEFAULT_ACTION_TYPE = "Select Action Type" as ActionType;
const DEFAULT_ACTION_LABEL = "Select Action";
enum ACTION_RESOLUTION_TYPE {
SUCCESS,
ERROR,
}
function getActions(
actionPayloads: ActionPayload[] | undefined,
): {
action: ActionPayload | undefined;
onSuccessAction: ActionPayload | undefined;
onErrorAction: ActionPayload | undefined;
} {
let action: ActionPayload | undefined = actionPayloads && actionPayloads[0];
let onSuccessAction: ActionPayload | undefined =
action && action.onSuccess && action.onSuccess[0];
let onErrorAction: ActionPayload | undefined =
action && action.onError && action.onError[0];
return {
action,
onSuccessAction,
onErrorAction,
};
}
class ActionSelectorControl extends BaseControl< class ActionSelectorControl extends BaseControl<
ControlProps & ActionDataState ControlProps & ActionDataState
> { > {
getSelectionActionType(): string { getSelectionActionType(type: ACTION_RESOLUTION_TYPE | string): ActionType {
const selectedActionTypeValue = let selectedActionTypeValue: ActionType | undefined;
this.props.propertyValue && const { action, onSuccessAction, onErrorAction } = getActions(
this.props.propertyValue[0] && this.props.propertyValue,
this.props.propertyValue[0].actionType; );
switch (type) {
case this.props.propertyName:
selectedActionTypeValue = action && action.actionType;
break;
case ACTION_RESOLUTION_TYPE.SUCCESS:
selectedActionTypeValue = onSuccessAction && onSuccessAction.actionType;
break;
case ACTION_RESOLUTION_TYPE.ERROR:
selectedActionTypeValue = onErrorAction && onErrorAction.actionType;
break;
default:
break;
}
const foundActionType = PropertyPaneActionDropdownOptions.find( const foundActionType = PropertyPaneActionDropdownOptions.find(
actionType => actionType.value === selectedActionTypeValue, actionType => actionType.value === selectedActionTypeValue,
); );
return foundActionType ? foundActionType.label : DEFAULT_ACTION_TYPE; return foundActionType
? (foundActionType.label as ActionType)
: DEFAULT_ACTION_TYPE;
} }
getSelectionActionLabel(allActions: DropdownOption[]): string { getSelectionActionLabel(
const selectedActionId = type: ACTION_RESOLUTION_TYPE | string,
this.props.propertyValue && allActions: DropdownOption[],
this.props.propertyValue[0] && ): string {
this.props.propertyValue[0].actionId; let selectedActionId: string | undefined = "";
const { action, onSuccessAction, onErrorAction } = getActions(
this.props.propertyValue,
);
switch (type) {
case this.props.propertyName:
selectedActionId = action && action.actionId;
break;
case ACTION_RESOLUTION_TYPE.SUCCESS:
selectedActionId = onSuccessAction && onSuccessAction.actionId;
break;
case ACTION_RESOLUTION_TYPE.ERROR:
selectedActionId = onErrorAction && onErrorAction.actionId;
break;
default:
break;
}
const foundAction = allActions.find( const foundAction = allActions.find(
action => action.value === selectedActionId, action => action.value === selectedActionId,
); );
return foundAction ? foundAction.label : "Select Action"; return foundAction ? foundAction.label : DEFAULT_ACTION_LABEL;
} }
render() { render() {
const actionTypeOptions: DropdownOption[] = PropertyPaneActionDropdownOptions; const actionTypeOptions: DropdownOption[] = PropertyPaneActionDropdownOptions;
@ -51,16 +108,98 @@ class ActionSelectorControl extends BaseControl<
value: action.id, value: action.id,
}; };
}); });
const selectedActionType = this.getSelectionActionType(); const selectedActionType = this.getSelectionActionType(
const selectedActionLabel = this.getSelectionActionLabel(allActions); this.props.propertyName,
);
const selectedActionLabel = this.getSelectionActionLabel(
this.props.propertyName,
allActions,
);
const selectedSuccessActionType = this.getSelectionActionType(
ACTION_RESOLUTION_TYPE.SUCCESS,
);
const selectedSuccessActionLabel = this.getSelectionActionLabel(
ACTION_RESOLUTION_TYPE.SUCCESS,
allActions,
);
const selectedErrorActionType = this.getSelectionActionType(
ACTION_RESOLUTION_TYPE.ERROR,
);
const selectedErrorActionLabel = this.getSelectionActionLabel(
ACTION_RESOLUTION_TYPE.ERROR,
allActions,
);
return ( return (
<ControlWrapper> <ControlWrapper>
<label>{this.props.label}</label> {this.renderActionSelector(
allActions,
actionTypeOptions,
selectedActionType,
selectedActionLabel,
this.props.propertyName,
this.props.propertyName,
)}
{selectedActionLabel !== DEFAULT_ACTION_LABEL &&
this.renderActionSelector(
allActions,
actionTypeOptions,
selectedSuccessActionType,
selectedSuccessActionLabel,
"On Success",
ACTION_RESOLUTION_TYPE.SUCCESS,
)}
{selectedActionLabel !== DEFAULT_ACTION_LABEL &&
this.renderActionSelector(
allActions,
actionTypeOptions,
selectedErrorActionType,
selectedErrorActionLabel,
"On Error",
ACTION_RESOLUTION_TYPE.ERROR,
)}
</ControlWrapper>
);
}
renderActionSelector(
allActions: DropdownOption[],
actionTypeOptions: DropdownOption[],
selectedActionType: ActionType,
selectedActionLabel: string,
label: string,
actionResolutionType: ACTION_RESOLUTION_TYPE | string,
) {
let onTypeSelect = this.onActionTypeSelect;
switch (actionResolutionType) {
case ACTION_RESOLUTION_TYPE.SUCCESS:
onTypeSelect = this.onSuccessActionTypeSelect;
break;
case ACTION_RESOLUTION_TYPE.ERROR:
onTypeSelect = this.onErrorActionTypeSelect;
break;
}
let onActionSelect = this.onActionSelect;
switch (actionResolutionType) {
case ACTION_RESOLUTION_TYPE.SUCCESS:
onTypeSelect = this.onSuccessActionSelect;
break;
case ACTION_RESOLUTION_TYPE.ERROR:
onTypeSelect = this.onErrorActionSelect;
break;
}
return (
<div>
<div>
<label>{label}</label>
</div>
<StyledDropDown <StyledDropDown
items={actionTypeOptions} items={actionTypeOptions}
filterable={false} filterable={false}
itemRenderer={this.renderItem} itemRenderer={this.renderItem}
onItemSelect={this.onTypeSelect} onItemSelect={onTypeSelect}
noResults={<MenuItem disabled={true} text="No results." />} noResults={<MenuItem disabled={true} text="No results." />}
> >
<Button text={selectedActionType} rightIcon="chevron-down" /> <Button text={selectedActionType} rightIcon="chevron-down" />
@ -71,23 +210,25 @@ class ActionSelectorControl extends BaseControl<
items={allActions} items={allActions}
filterable={false} filterable={false}
itemRenderer={this.renderItem} itemRenderer={this.renderItem}
onItemSelect={this.onActionSelect} onItemSelect={onActionSelect}
noResults={<MenuItem disabled={true} text="No results." />} noResults={<MenuItem disabled={true} text="No results." />}
> >
<Button text={selectedActionLabel} rightIcon="chevron-down" /> <Button text={selectedActionLabel} rightIcon="chevron-down" />
</StyledDropDown> </StyledDropDown>
)} )}
</ControlWrapper> </div>
); );
} }
onActionTypeSelect = (item: DropdownOption) => {
onTypeSelect = (item: DropdownOption): void => {
const actionPayloads: ActionPayload[] = this.props.propertyValue const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice() ? this.props.propertyValue.slice()
: []; : [];
const actionPayload = actionPayloads[0]; let actionPayload = actionPayloads[0];
if (actionPayload) {
if (actionPayload && actionPayload.actionType !== item.value) {
actionPayload.actionId = ""; actionPayload.actionId = "";
actionPayload.onError = undefined;
actionPayload.onSuccess = undefined;
actionPayload.actionType = item.value as ActionType; actionPayload.actionType = item.value as ActionType;
} else { } else {
const actionPayload = { actionType: item.value } as ActionPayload; const actionPayload = { actionType: item.value } as ActionPayload;
@ -95,16 +236,83 @@ class ActionSelectorControl extends BaseControl<
} }
this.updateProperty(this.props.propertyName, actionPayloads); this.updateProperty(this.props.propertyName, actionPayloads);
}; };
onSuccessActionTypeSelect = (item: DropdownOption) => {
const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice()
: [];
let actionPayload = actionPayloads[0];
if (actionPayload) {
const successActionPayloads: ActionPayload[] =
actionPayload.onSuccess || [];
let successActionPayload = successActionPayloads[0];
if (successActionPayload) {
successActionPayload.actionId = "";
successActionPayload.actionType = item.value as ActionType;
} else {
const successActionPayload = {
actionType: item.value,
} as ActionPayload;
successActionPayloads.push(successActionPayload);
}
actionPayload.onSuccess = successActionPayloads;
}
this.updateProperty(this.props.propertyName, actionPayloads);
};
onErrorActionTypeSelect = (item: DropdownOption) => {
const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice()
: [];
let actionPayload = actionPayloads[0];
if (actionPayload) {
const errorActionPayloads: ActionPayload[] = actionPayload.onError || [];
let errorActionPayload = errorActionPayloads[0];
if (errorActionPayload) {
errorActionPayload.actionId = "";
errorActionPayload.actionType = item.value as ActionType;
} else {
const errorActionPayload = {
actionType: item.value,
} as ActionPayload;
errorActionPayloads.push(errorActionPayload);
}
actionPayload.onError = errorActionPayloads;
}
this.updateProperty(this.props.propertyName, actionPayloads);
};
onActionSelect = (item: DropdownOption): void => { onActionSelect = (item: DropdownOption): void => {
const actionPayloads: ActionPayload[] = this.props.propertyValue const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice() ? this.props.propertyValue.slice()
: []; : [];
const actionPayload = actionPayloads[0]; const actionPayload = actionPayloads[0];
actionPayload.actionId = item.value as ActionType; actionPayload.actionId = item.value;
this.updateProperty(this.props.propertyName, actionPayloads); this.updateProperty(this.props.propertyName, actionPayloads);
}; };
onSuccessActionSelect = (item: DropdownOption): void => {
const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice()
: [];
const actionPayload = actionPayloads[0];
const successActionPayloads: ActionPayload[] = actionPayload.onSuccess as ActionPayload[];
const successActionPayload = successActionPayloads[0];
successActionPayload.actionId = item.value;
actionPayload.onSuccess = successActionPayloads;
this.updateProperty(this.props.propertyName, actionPayloads);
};
onErrorActionSelect = (item: DropdownOption): void => {
const actionPayloads: ActionPayload[] = this.props.propertyValue
? this.props.propertyValue.slice()
: [];
const actionPayload = actionPayloads[0];
const errorActionPayloads: ActionPayload[] = actionPayload.onError as ActionPayload[];
const errorActionPayload = errorActionPayloads[0];
errorActionPayload.actionId = item.value;
actionPayload.onError = errorActionPayloads;
this.updateProperty(this.props.propertyName, actionPayloads);
};
renderItem = (option: DropdownOption, itemProps: IItemRendererProps) => { renderItem = (option: DropdownOption, itemProps: IItemRendererProps) => {
if (!itemProps.modifiers.matchesPredicate) { if (!itemProps.modifiers.matchesPredicate) {

View File

@ -22,16 +22,6 @@ export type ActionType =
| "SET_VALUE" | "SET_VALUE"
| "DOWNLOAD"; | "DOWNLOAD";
export enum ActionType1 {
"API",
"QUERY",
"NAVIGATION",
"ALERT",
"JS_FUNCTION",
"SET_VALUE",
"DOWNLOAD",
}
export const PropertyPaneActionDropdownOptions: DropdownOption[] = [ export const PropertyPaneActionDropdownOptions: DropdownOption[] = [
{ label: "Call API", value: "API" }, { label: "Call API", value: "API" },
// { label: "Run Query", value: "QUERY" }, // { label: "Run Query", value: "QUERY" },
@ -41,6 +31,8 @@ export interface ActionPayload {
actionId: string; actionId: string;
actionType: ActionType; actionType: ActionType;
contextParams: Record<string, string>; contextParams: Record<string, string>;
onSuccess?: ActionPayload[];
onError?: ActionPayload[];
} }
export type NavigationType = "NEW_TAB" | "INLINE"; export type NavigationType = "NEW_TAB" | "INLINE";

View File

@ -80,6 +80,13 @@ export function* executeAPIQueryActionSaga(apiAction: { actionId: string }) {
statusCode: response.responseMeta.error.code, statusCode: response.responseMeta.error.code,
...response, ...response,
}; };
if (apiAction.onError) {
yield call(executeActionSaga, apiAction.onError);
}
} else {
if (apiAction.onSuccess) {
yield call(executeActionSaga, apiAction.onSuccess);
}
} }
yield put({ yield put({
type: ReduxActionTypes.EXECUTE_ACTION_SUCCESS, type: ReduxActionTypes.EXECUTE_ACTION_SUCCESS,
@ -88,19 +95,25 @@ export function* executeAPIQueryActionSaga(apiAction: { actionId: string }) {
return response; return response;
} }
export function* executeActionSaga(action: ReduxAction<ActionPayload[]>) { // TODO(satbir): Refact this to not make this recursive.
export function* executeActionSaga(actionPayloads: ActionPayload[]): any {
yield all(
_.map(actionPayloads, (actionPayload: ActionPayload) => {
switch (actionPayload.actionType) {
case "API":
return call(executeAPIQueryActionSaga, actionPayload);
case "QUERY":
return call(executeAPIQueryActionSaga, actionPayload);
default:
return undefined;
}
}),
);
}
export function* executeReduxActionSaga(action: ReduxAction<ActionPayload[]>) {
if (!_.isNil(action.payload)) { if (!_.isNil(action.payload)) {
yield all( yield call(executeActionSaga, action.payload);
_.map(action.payload, (actionPayload: ActionPayload) => {
switch (actionPayload.actionType) {
case "API":
return call(executeAPIQueryActionSaga, actionPayload);
case "QUERY":
return call(executeAPIQueryActionSaga, actionPayload);
}
return undefined;
}),
);
} }
} }
@ -181,7 +194,7 @@ export function* deleteActionSaga(actionPayload: ReduxAction<{ id: string }>) {
export function* watchActionSagas() { export function* watchActionSagas() {
yield all([ yield all([
takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga), takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga),
takeLatest(ReduxActionTypes.EXECUTE_ACTION, executeActionSaga), takeLatest(ReduxActionTypes.EXECUTE_ACTION, executeReduxActionSaga),
takeLatest(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga), takeLatest(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga),
takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga), takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga),
takeLatest(ReduxActionTypes.DELETE_ACTION_INIT, deleteActionSaga), takeLatest(ReduxActionTypes.DELETE_ACTION_INIT, deleteActionSaga),

View File

@ -57,13 +57,13 @@ class TableWidget extends BaseWidget<TableWidgetProps, WidgetState> {
data={tableData} data={tableData}
maxHeight={height} maxHeight={height}
selectedRowIndex={ selectedRowIndex={
this.props.selectedRow && this.props.selectedRow.index this.props.selectedRow && this.props.selectedRow.rowIndex
} }
onRowClick={(rowData: object, index: number) => { onRowClick={(rowData: object, index: number) => {
const { widgetId, onRowSelected } = this.props; const { widgetId, onRowSelected } = this.props;
super.updateWidgetProperty(widgetId, "selectedRow", { super.updateWidgetProperty(widgetId, "selectedRow", {
data: rowData, ...rowData,
index: index, rowIndex: index,
}); });
super.executeAction(onRowSelected); super.executeAction(onRowSelected);
}} }}
@ -84,6 +84,10 @@ export interface TableAction extends ActionPayload {
actionName: string; actionName: string;
} }
interface RowData {
rowIndex: number;
}
export interface TableWidgetProps extends WidgetProps { export interface TableWidgetProps extends WidgetProps {
nextPageKey?: string; nextPageKey?: string;
prevPageKey?: string; prevPageKey?: string;
@ -92,10 +96,7 @@ export interface TableWidgetProps extends WidgetProps {
recordActions?: TableAction[]; recordActions?: TableAction[];
onPageChange?: ActionPayload[]; onPageChange?: ActionPayload[];
onRowSelected?: ActionPayload[]; onRowSelected?: ActionPayload[];
selectedRow?: { selectedRow?: object & RowData;
data: object;
index: number;
};
} }
export default TableWidget; export default TableWidget;