Merge branch 'release'
This commit is contained in:
commit
95d1717f57
19
.deepsource.toml
Normal file
19
.deepsource.toml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
version = 1
|
||||
|
||||
exclude_patterns = [
|
||||
"static/**",
|
||||
"deploy/**",
|
||||
"contributions/**"
|
||||
]
|
||||
|
||||
[[analyzers]]
|
||||
name = "javascript"
|
||||
enabled = true
|
||||
|
||||
[analyzers.meta]
|
||||
plugins = ["react"]
|
||||
environment = [
|
||||
"nodejs",
|
||||
"browser"
|
||||
]
|
||||
dialect = "typescript"
|
||||
8
.github/workflows/client.yml
vendored
8
.github/workflows/client.yml
vendored
|
|
@ -48,10 +48,10 @@ jobs:
|
|||
- name: Figure out the PR number
|
||||
run: echo ${{ github.event.pull_request.number }}
|
||||
|
||||
- name: Use Node.js 10.16.3
|
||||
- name: Use Node.js 14.15.4
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "10.16.3"
|
||||
node-version: "14.15.4"
|
||||
|
||||
# Retrieve npm dependencies from cache. After a successful run, these dependencies are cached again
|
||||
- name: Cache npm dependencies
|
||||
|
|
@ -151,10 +151,10 @@ jobs:
|
|||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 10.16.3
|
||||
- name: Use Node.js 14.15.4
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "10.16.3"
|
||||
node-version: "14.15.4"
|
||||
|
||||
# Retrieve npm dependencies from cache. After a successful run, these dependencies are cached again
|
||||
- name: Cache npm dependencies
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
lts/dubnium
|
||||
lts/fermium
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": "^10.16.3",
|
||||
"npm": "^6.9.0"
|
||||
"node": "^14.15.4",
|
||||
"npm": "^6.14.10"
|
||||
},
|
||||
"cracoConfig": "craco.dev.config.js",
|
||||
"dependencies": {
|
||||
|
|
@ -35,14 +35,14 @@
|
|||
"@types/react-table": "^7.0.13",
|
||||
"@types/styled-components": "^5.1.3",
|
||||
"@types/tinycolor2": "^1.4.2",
|
||||
"@uppy/core": "^1.8.2",
|
||||
"@uppy/dashboard": "^1.6.2",
|
||||
"@uppy/file-input": "^1.3.1",
|
||||
"@uppy/google-drive": "^1.3.2",
|
||||
"@uppy/onedrive": "^0.1.1",
|
||||
"@uppy/react": "^1.4.5",
|
||||
"@uppy/url": "^1.3.2",
|
||||
"@uppy/webcam": "^1.3.1",
|
||||
"@uppy/core": "^1.16.0",
|
||||
"@uppy/dashboard": "^1.16.0",
|
||||
"@uppy/file-input": "^1.4.22",
|
||||
"@uppy/google-drive": "^1.5.22",
|
||||
"@uppy/onedrive": "^1.1.22",
|
||||
"@uppy/react": "^1.11.2",
|
||||
"@uppy/url": "^1.5.16",
|
||||
"@uppy/webcam": "^1.8.4",
|
||||
"@welldone-software/why-did-you-render": "^4.2.5",
|
||||
"algoliasearch": "^4.2.0",
|
||||
"axios": "^0.21.1",
|
||||
|
|
|
|||
|
|
@ -381,7 +381,7 @@ const TextLoadingState = ({ text }: { text?: string }) => (
|
|||
);
|
||||
|
||||
const IconLoadingState = ({ size, icon }: { size?: Size; icon?: IconName }) => (
|
||||
<Icon name={icon} size={IconSizeProp(size)} invisible={true} />
|
||||
<Icon name={icon} size={IconSizeProp(size)} invisible />
|
||||
);
|
||||
|
||||
const getIconContent = (props: ButtonProps) =>
|
||||
|
|
|
|||
|
|
@ -263,7 +263,7 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
onChange={onInputchange}
|
||||
onConfirm={onConfirm}
|
||||
value={value}
|
||||
selectAllOnFocus={true}
|
||||
selectAllOnFocus
|
||||
placeholder={props.placeholder || defaultValue}
|
||||
className={props.className}
|
||||
onCancel={onConfirm}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const PopoverVideo = (props: VideoComponentProps) => {
|
|||
minimal
|
||||
usePortal
|
||||
enforceFocus={false}
|
||||
lazy={true}
|
||||
lazy
|
||||
modifiers={{
|
||||
flip: {
|
||||
behavior: ["right", "left", "bottom", "top"],
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ const PageNumberInput = (props: {
|
|||
min={1}
|
||||
max={props.pageCount || 1}
|
||||
buttonPosition="none"
|
||||
clampValueOnBlur={true}
|
||||
clampValueOnBlur
|
||||
onBlur={(e: any) => {
|
||||
const oldPageNo = Number(props.pageNo || 0);
|
||||
const value = e.target.value;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ class HelpModal extends React.Component<Props> {
|
|||
<>
|
||||
{isHelpModalOpen && (
|
||||
<ModalComponent
|
||||
canOutsideClickClose={true}
|
||||
canOutsideClickClose
|
||||
canEscapeKeyClose
|
||||
scrollContents
|
||||
height={MODAL_HEIGHT}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ export type ComparisonOperations =
|
|||
| "EQUALS"
|
||||
| "NOT_EQUALS"
|
||||
| "LESSER"
|
||||
| "GREATER";
|
||||
| "GREATER"
|
||||
| "IN"
|
||||
| "NOT_IN";
|
||||
|
||||
export type HiddenType =
|
||||
| boolean
|
||||
|
|
|
|||
|
|
@ -54,6 +54,22 @@ describe("isHidden test", () => {
|
|||
comparison: "NOT_EQUALS",
|
||||
},
|
||||
},
|
||||
{
|
||||
values: { name: "Name", config: { type: "Different BODY" } },
|
||||
hidden: {
|
||||
path: "config.type",
|
||||
value: ["EMAIL", "BODY"],
|
||||
comparison: "IN",
|
||||
},
|
||||
},
|
||||
{
|
||||
values: { name: "Name", config: { type: "BODY" } },
|
||||
hidden: {
|
||||
path: "config.type",
|
||||
value: ["EMAIL", "BODY"],
|
||||
comparison: "NOT_IN",
|
||||
},
|
||||
},
|
||||
{
|
||||
values: undefined,
|
||||
hidden: false,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ export const isHidden = (values: any, hiddenConfig?: HiddenType) => {
|
|||
return valueAtPath > value;
|
||||
case "LESSER":
|
||||
return valueAtPath < value;
|
||||
case "IN":
|
||||
return Array.isArray(value) && value.includes(valueAtPath);
|
||||
case "NOT_IN":
|
||||
return Array.isArray(value) && !value.includes(valueAtPath);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ export const FIELD_REQUIRED_ERROR = "This field is required";
|
|||
export const VALID_FUNCTION_NAME_ERROR =
|
||||
"Must be a valid variable name (camelCase)";
|
||||
export const UNIQUE_NAME_ERROR = "Name must be unique";
|
||||
export const NAME_SPACE_ERROR = "Name must not have spaces";
|
||||
export const NAME_SPACE_ERROR = "Name cannot have spaces";
|
||||
|
||||
export const FORM_VALIDATION_EMPTY_EMAIL = "Please enter an email";
|
||||
export const FORM_VALIDATION_INVALID_EMAIL =
|
||||
"Please provide a valid email address";
|
||||
export const ENTER_VIDEO_URL = "Please provide a valid url";
|
||||
export const ENTER_VIDEO_URL = "Please provide a valid URL";
|
||||
|
||||
export const FORM_VALIDATION_EMPTY_PASSWORD = "Please enter the password";
|
||||
export const FORM_VALIDATION_PASSWORD_RULE =
|
||||
|
|
@ -27,11 +27,11 @@ export const LOGIN_PAGE_PASSWORD_INPUT_LABEL = "Password";
|
|||
export const LOGIN_PAGE_EMAIL_INPUT_PLACEHOLDER = "Email";
|
||||
export const LOGIN_PAGE_PASSWORD_INPUT_PLACEHOLDER = "Password";
|
||||
export const LOGIN_PAGE_INVALID_CREDS_ERROR =
|
||||
"It looks like you may have entered incorrect/invalid credentials. Please try again or reset password using the button below.";
|
||||
"You may have entered incorrect/invalid credentials. Please try again or reset your password.";
|
||||
export const LOGIN_PAGE_INVALID_CREDS_FORGOT_PASSWORD_LINK = "Reset Password";
|
||||
export const NEW_TO_APPSMITH = "New to Appsmith?";
|
||||
|
||||
export const LOGIN_PAGE_LOGIN_BUTTON_TEXT = "sign in";
|
||||
export const LOGIN_PAGE_LOGIN_BUTTON_TEXT = "Sign in";
|
||||
export const LOGIN_PAGE_FORGOT_PASSWORD_TEXT = "Forgot Password";
|
||||
export const LOGIN_PAGE_REMEMBER_ME_LABEL = "Remember";
|
||||
export const LOGIN_PAGE_SIGN_UP_LINK_TEXT = "Sign up";
|
||||
|
|
@ -44,16 +44,16 @@ export const SIGNUP_PAGE_NAME_INPUT_LABEL = "Name";
|
|||
export const SIGNUP_PAGE_PASSWORD_INPUT_LABEL = "Password";
|
||||
export const SIGNUP_PAGE_PASSWORD_INPUT_PLACEHOLDER = "Password";
|
||||
export const SIGNUP_PAGE_LOGIN_LINK_TEXT = "Sign In";
|
||||
export const SIGNUP_PAGE_NAME_INPUT_SUBTEXT = "How should we call you?";
|
||||
export const SIGNUP_PAGE_NAME_INPUT_SUBTEXT = "What should we call you?";
|
||||
export const SIGNUP_PAGE_SUBMIT_BUTTON_TEXT = "Sign Up";
|
||||
export const ALREADY_HAVE_AN_ACCOUNT = "Already have an account?";
|
||||
export const ALREADY_HAVE_AN_ACCOUNT = "You may already have an account.";
|
||||
|
||||
export const SIGNUP_PAGE_SUCCESS = "Awesome! You have successfully registered.";
|
||||
export const SIGNUP_PAGE_SUCCESS_LOGIN_BUTTON_TEXT = "Login";
|
||||
|
||||
export const RESET_PASSWORD_PAGE_PASSWORD_INPUT_LABEL = "New Password";
|
||||
export const RESET_PASSWORD_PAGE_PASSWORD_INPUT_PLACEHOLDER = "New Password";
|
||||
export const RESET_PASSWORD_LOGIN_LINK_TEXT = "Back to Sign In";
|
||||
export const RESET_PASSWORD_LOGIN_LINK_TEXT = "Back to sign in page";
|
||||
export const RESET_PASSWORD_PAGE_TITLE = "Reset Password";
|
||||
export const RESET_PASSWORD_SUBMIT_BUTTON_TEXT = "Reset";
|
||||
export const RESET_PASSWORD_PAGE_SUBTITLE =
|
||||
|
|
@ -63,9 +63,9 @@ export const RESET_PASSWORD_RESET_SUCCESS = "Your password has been reset"; //"Y
|
|||
export const RESET_PASSWORD_RESET_SUCCESS_LOGIN_LINK = "Login";
|
||||
|
||||
export const RESET_PASSWORD_EXPIRED_TOKEN =
|
||||
"The password reset link has expired. Please try generating a new link";
|
||||
"This password reset link has expired. Please try generating a new link";
|
||||
export const RESET_PASSWORD_INVALID_TOKEN =
|
||||
"The password reset link is invalid. Please try generating a new link";
|
||||
"This password reset link is invalid. Please try generating a new link";
|
||||
export const RESET_PASSWORD_FORGOT_PASSWORD_LINK = "Forgot Password";
|
||||
|
||||
export const FORGOT_PASSWORD_PAGE_EMAIL_INPUT_LABEL = "Email";
|
||||
|
|
@ -81,7 +81,7 @@ export const PRIVACY_POLICY_LINK = "Privacy Policy";
|
|||
export const TERMS_AND_CONDITIONS_LINK = "Terms and Conditions";
|
||||
|
||||
export const ERROR_500 =
|
||||
"We apologize, Something went wrong. We're working to fix things.";
|
||||
"Whoops, something went wrong. This is unexpected, and we'll look into this.";
|
||||
export const ERROR_0 =
|
||||
"We could not connect to our servers. Please check your network connection";
|
||||
export const ERROR_401 =
|
||||
|
|
@ -159,7 +159,7 @@ export const LIGHTNING_MENU_API_CREATE_NEW = "Create new API";
|
|||
export const LIGHTNING_MENU_OPTION_TEXT = "Plain Text";
|
||||
export const LIGHTNING_MENU_OPTION_JS = "Write JS";
|
||||
export const LIGHTNING_MENU_OPTION_HTML = "Write HTML";
|
||||
export const CHECK_REQUEST_BODY = "Check Request body to debug?";
|
||||
export const CHECK_REQUEST_BODY = "Please check request body to debug?";
|
||||
export const DONT_SHOW_THIS_AGAIN = "Don't show this again";
|
||||
export const SHOW_REQUEST = "Show Request";
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ export const TABLE_FILTER_COLUMN_TYPE_CALLOUT =
|
|||
|
||||
export const WIDGET_SIDEBAR_TITLE = "Widgets";
|
||||
export const WIDGET_SIDEBAR_CAPTION =
|
||||
"To add a widget, please drag and drop a widget on the canvas to the right";
|
||||
"To add a widget, please click + and add widget to the canvas.";
|
||||
export const GOOGLE_RECAPTCHA_KEY_ERROR =
|
||||
"Google Re-Captcha Token Generation failed! Please check the Re-captcha Site Key.";
|
||||
export const GOOGLE_RECAPTCHA_DOMAIN_ERROR =
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ export const PageTabsContainer = (props: AppViewerHeaderProps) => {
|
|||
onMouseDown={() => startScrolling(true)}
|
||||
onMouseUp={stopScrolling}
|
||||
onMouseLeave={stopScrolling}
|
||||
onTouchStart={() => startScrolling(true)}
|
||||
onTouchEnd={stopScrolling}
|
||||
visible={shouldShowLeftArrow}
|
||||
>
|
||||
<Icon name="chevron-left" />
|
||||
|
|
@ -137,6 +139,8 @@ export const PageTabsContainer = (props: AppViewerHeaderProps) => {
|
|||
onMouseDown={() => startScrolling(false)}
|
||||
onMouseUp={stopScrolling}
|
||||
onMouseLeave={stopScrolling}
|
||||
onTouchStart={() => startScrolling(false)}
|
||||
onTouchEnd={stopScrolling}
|
||||
visible={shouldShowRightArrow}
|
||||
>
|
||||
<Icon name="chevron-right" />
|
||||
|
|
|
|||
|
|
@ -1346,10 +1346,10 @@ function* addTableWidgetFromQuerySaga(action: ReduxAction<string>) {
|
|||
rightColumn: columns,
|
||||
columns,
|
||||
rows,
|
||||
parentId: "0",
|
||||
parentId: MAIN_CONTAINER_WIDGET_ID,
|
||||
widgetName,
|
||||
renderMode: RenderModes.CANVAS,
|
||||
parentRowSpace: 1,
|
||||
parentRowSpace: GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
|
||||
parentColumnSpace: 1,
|
||||
isLoading: false,
|
||||
props: {
|
||||
|
|
@ -1362,7 +1362,11 @@ function* addTableWidgetFromQuerySaga(action: ReduxAction<string>) {
|
|||
topRow,
|
||||
rightColumn,
|
||||
bottomRow,
|
||||
} = yield calculateNewWidgetPosition(newWidget, "0", widgets);
|
||||
} = yield calculateNewWidgetPosition(
|
||||
newWidget,
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
widgets,
|
||||
);
|
||||
|
||||
newWidget = {
|
||||
...newWidget,
|
||||
|
|
|
|||
|
|
@ -27,13 +27,11 @@ class FilePickerWidget extends BaseWidget<
|
|||
FilePickerWidgetProps,
|
||||
FilePickerWidgetState
|
||||
> {
|
||||
uppy: any;
|
||||
|
||||
constructor(props: FilePickerWidgetProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
version: 0,
|
||||
isLoading: false,
|
||||
uppy: this.initializeUppy(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -63,24 +61,70 @@ class FilePickerWidget extends BaseWidget<
|
|||
};
|
||||
}
|
||||
|
||||
refreshUppy = (props: FilePickerWidgetProps) => {
|
||||
this.uppy = Uppy({
|
||||
static getTriggerPropertyMap(): TriggerPropertiesMap {
|
||||
return {
|
||||
onFilesSelected: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* if uppy is not initialized before, initialize it
|
||||
* else setState of uppy instance
|
||||
*/
|
||||
initializeUppy = () => {
|
||||
const uppyState = {
|
||||
id: this.props.widgetId,
|
||||
autoProceed: false,
|
||||
allowMultipleUploads: true,
|
||||
debug: false,
|
||||
restrictions: {
|
||||
maxFileSize: this.props.maxFileSize
|
||||
? this.props.maxFileSize * 1024 * 1024
|
||||
: null,
|
||||
maxNumberOfFiles: this.props.maxNumFiles,
|
||||
minNumberOfFiles: null,
|
||||
allowedFileTypes:
|
||||
this.props.allowedFileTypes &&
|
||||
(this.props.allowedFileTypes.includes("*") ||
|
||||
_.isEmpty(this.props.allowedFileTypes))
|
||||
? null
|
||||
: this.props.allowedFileTypes,
|
||||
},
|
||||
};
|
||||
|
||||
return Uppy(uppyState);
|
||||
};
|
||||
|
||||
/**
|
||||
* set states on the uppy instance with new values
|
||||
*/
|
||||
reinitializeUppy = (props: FilePickerWidgetProps) => {
|
||||
const uppyState = {
|
||||
id: props.widgetId,
|
||||
autoProceed: false,
|
||||
allowMultipleUploads: true,
|
||||
debug: false,
|
||||
restrictions: {
|
||||
maxFileSize: props.maxFileSize ? props.maxFileSize * 1024 * 1024 : null,
|
||||
maxNumberOfFiles: props.maxNumFiles,
|
||||
minNumberOfFiles: null,
|
||||
allowedFileTypes:
|
||||
props.allowedFileTypes &&
|
||||
(props.allowedFileTypes.includes("*") ||
|
||||
(this.props.allowedFileTypes.includes("*") ||
|
||||
_.isEmpty(props.allowedFileTypes))
|
||||
? null
|
||||
: props.allowedFileTypes,
|
||||
},
|
||||
})
|
||||
};
|
||||
|
||||
this.state.uppy.setOptions(uppyState);
|
||||
};
|
||||
|
||||
/**
|
||||
* add all uppy events listeners needed
|
||||
*/
|
||||
initializeUppyEventListeners = () => {
|
||||
this.state.uppy
|
||||
.use(Dashboard, {
|
||||
target: "body",
|
||||
metaFields: [],
|
||||
|
|
@ -101,7 +145,11 @@ class FilePickerWidget extends BaseWidget<
|
|||
disablePageScrollWhenModalOpen: true,
|
||||
proudlyDisplayPoweredByUppy: false,
|
||||
onRequestCloseModal: () => {
|
||||
this.uppy.getPlugin("Dashboard").closeModal();
|
||||
const plugin = this.state.uppy.getPlugin("Dashboard");
|
||||
|
||||
if (plugin) {
|
||||
plugin.closeModal();
|
||||
}
|
||||
},
|
||||
locale: {},
|
||||
})
|
||||
|
|
@ -117,7 +165,8 @@ class FilePickerWidget extends BaseWidget<
|
|||
facingMode: "user",
|
||||
locale: {},
|
||||
});
|
||||
this.uppy.on("file-removed", (file: any) => {
|
||||
|
||||
this.state.uppy.on("file-removed", (file: any) => {
|
||||
const updatedFiles = this.props.files
|
||||
? this.props.files.filter((dslFile) => {
|
||||
return file.id !== dslFile.id;
|
||||
|
|
@ -125,47 +174,50 @@ class FilePickerWidget extends BaseWidget<
|
|||
: [];
|
||||
this.props.updateWidgetMetaProperty("files", updatedFiles);
|
||||
});
|
||||
this.uppy.on("file-added", (file: any) => {
|
||||
const dslFiles = this.props.files ? [...this.props.files] : [];
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.readAsDataURL(file.data);
|
||||
reader.onloadend = () => {
|
||||
const base64data = reader.result;
|
||||
const binaryReader = new FileReader();
|
||||
binaryReader.readAsBinaryString(file.data);
|
||||
binaryReader.onloadend = () => {
|
||||
const rawData = binaryReader.result;
|
||||
const textReader = new FileReader();
|
||||
textReader.readAsText(file.data);
|
||||
textReader.onloadend = () => {
|
||||
const text = textReader.result;
|
||||
const newFile = {
|
||||
id: file.id,
|
||||
base64: base64data,
|
||||
blob: file.data,
|
||||
raw: rawData,
|
||||
text: text,
|
||||
name: file.meta ? file.meta.name : undefined,
|
||||
this.state.uppy.on("files-added", (files: any[]) => {
|
||||
const dslFiles = this.props.files ? [...this.props.files] : [];
|
||||
|
||||
const fileReaderPromises = files.map((file) => {
|
||||
const reader = new FileReader();
|
||||
return new Promise((resolve) => {
|
||||
reader.readAsDataURL(file.data);
|
||||
reader.onloadend = () => {
|
||||
const base64data = reader.result;
|
||||
const binaryReader = new FileReader();
|
||||
binaryReader.readAsBinaryString(file.data);
|
||||
binaryReader.onloadend = () => {
|
||||
const rawData = binaryReader.result;
|
||||
const textReader = new FileReader();
|
||||
textReader.readAsText(file.data);
|
||||
textReader.onloadend = () => {
|
||||
const text = textReader.result;
|
||||
const newFile = {
|
||||
id: file.id,
|
||||
base64: base64data,
|
||||
blob: file.data,
|
||||
raw: rawData,
|
||||
text: text,
|
||||
name: file.meta ? file.meta.name : undefined,
|
||||
};
|
||||
|
||||
resolve(newFile);
|
||||
};
|
||||
};
|
||||
dslFiles.push(newFile);
|
||||
this.props.updateWidgetMetaProperty("files", dslFiles);
|
||||
};
|
||||
};
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
Promise.all(fileReaderPromises).then((files) => {
|
||||
this.props.updateWidgetMetaProperty("files", dslFiles.concat(files));
|
||||
});
|
||||
});
|
||||
this.uppy.on("upload", () => {
|
||||
|
||||
this.state.uppy.on("upload", () => {
|
||||
this.onFilesSelected();
|
||||
});
|
||||
this.setState({ version: this.state.version + 1 });
|
||||
};
|
||||
|
||||
static getTriggerPropertyMap(): TriggerPropertiesMap {
|
||||
return {
|
||||
onFilesSelected: true,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* this function is called when user selects the files and it do two things:
|
||||
* 1. calls the action if any
|
||||
|
|
@ -208,29 +260,30 @@ class FilePickerWidget extends BaseWidget<
|
|||
prevProps.files.length > 0 &&
|
||||
this.props.files === undefined
|
||||
) {
|
||||
this.uppy.reset();
|
||||
this.state.uppy.reset();
|
||||
} else if (
|
||||
!shallowequal(prevProps.allowedFileTypes, this.props.allowedFileTypes) ||
|
||||
prevProps.maxNumFiles !== this.props.maxNumFiles ||
|
||||
prevProps.maxFileSize !== this.props.maxFileSize
|
||||
) {
|
||||
this.refreshUppy(this.props);
|
||||
this.reinitializeUppy(this.props);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.refreshUppy(this.props);
|
||||
|
||||
this.initializeUppyEventListeners();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.uppy.close();
|
||||
this.state.uppy.close();
|
||||
}
|
||||
|
||||
getPageView() {
|
||||
return (
|
||||
<FilePickerComponent
|
||||
uppy={this.uppy}
|
||||
uppy={this.state.uppy}
|
||||
widgetId={this.props.widgetId}
|
||||
key={this.props.widgetId}
|
||||
label={this.props.label}
|
||||
|
|
@ -247,8 +300,8 @@ class FilePickerWidget extends BaseWidget<
|
|||
}
|
||||
|
||||
export interface FilePickerWidgetState extends WidgetState {
|
||||
version: number;
|
||||
isLoading: boolean;
|
||||
uppy: any;
|
||||
}
|
||||
|
||||
export interface FilePickerWidgetProps extends WidgetProps, WithMeta {
|
||||
|
|
|
|||
|
|
@ -154,10 +154,11 @@ class InputWidget extends BaseWidget<InputWidgetProps, WidgetState> {
|
|||
| React.KeyboardEvent<HTMLTextAreaElement>
|
||||
| React.KeyboardEvent<HTMLInputElement>,
|
||||
) => {
|
||||
const { isValid, onSubmit } = this.props;
|
||||
const isEnterKey = e.key === "Enter" || e.keyCode === 13;
|
||||
if (isEnterKey && this.props.onSubmit) {
|
||||
if (isEnterKey && onSubmit && isValid) {
|
||||
super.executeAction({
|
||||
dynamicString: this.props.onSubmit,
|
||||
dynamicString: onSubmit,
|
||||
event: {
|
||||
type: EventType.ON_SUBMIT,
|
||||
callback: this.onSubmitSuccess,
|
||||
|
|
|
|||
|
|
@ -4501,39 +4501,40 @@
|
|||
"@typescript-eslint/types" "4.6.0"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
"@uppy/companion-client@^1.4.1", "@uppy/companion-client@^1.5.4":
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/companion-client/-/companion-client-1.5.4.tgz#11a9d2ee91a13789ca083f88a3ac7378b3fb20ed"
|
||||
integrity sha512-AmrKamjHraqm/eV00ps8brw5ajI9NqjzBotTtPH9QaC+D3wIQ/EoWZNTGx4OlGYRahEoVr1K6hhlyUoHmEQc4w==
|
||||
"@uppy/companion-client@^1.8.1":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/companion-client/-/companion-client-1.8.1.tgz#e8796ac5d2219663da1ef46367efd9cbcf629b17"
|
||||
integrity sha512-me07SraLbf+Q7z5i6IVTrKc6tiIe84ztqrifx8ftL/XKfOf2niYrS04PU4sppOCtkHiSPG/jP1TDFYd9HVL3aA==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
namespace-emitter "^2.0.1"
|
||||
qs-stringify "^1.1.0"
|
||||
|
||||
"@uppy/core@^1.8.2":
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/core/-/core-1.13.2.tgz#78c03019ca78ebaa2920c1fa4888ee76531d2e59"
|
||||
integrity sha512-h0fbwlntm51lJ5i9k16csAsGNuWSzAZe69gLX/5DOISWqziRdF3g2EtSG17p/p/tK/MwX1dzyNU8JI6krDYIwA==
|
||||
"@uppy/core@^1.16.0":
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/core/-/core-1.16.0.tgz#a5058e4adb1c7e3d7b52d260eef48fe7283294d7"
|
||||
integrity sha512-qzd/G23KVTLOVmfmszPj8qaTuKyt6ZfLNpp5UnjrZkdvs9b+tY/uKEjUI3Dw8ScSa7roaizQU064z3eik8G84Q==
|
||||
dependencies:
|
||||
"@transloadit/prettier-bytes" "0.0.7"
|
||||
"@uppy/store-default" "^1.2.4"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/store-default" "^1.2.5"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
cuid "^2.1.1"
|
||||
lodash.throttle "^4.1.1"
|
||||
mime-match "^1.0.2"
|
||||
namespace-emitter "^2.0.1"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/dashboard@^1.12.8", "@uppy/dashboard@^1.6.2":
|
||||
version "1.12.8"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/dashboard/-/dashboard-1.12.8.tgz#1ec26020753fb58ac6182f5adad7d018e6157097"
|
||||
integrity sha512-ryz2x2i/jwVJCDGcdiQqD6Az92WPY6ft/r5iu2TTxOIzUFdou3T1rKF/6Dbh3qVCbzzFviPMLdTVfaSsEoQdNw==
|
||||
"@uppy/dashboard@^1.16.0":
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/dashboard/-/dashboard-1.16.0.tgz#5489dedae26cf4980894de3dd5147a5f62073343"
|
||||
integrity sha512-Kc4OyIvR7b9rVmuJkDG1hWgCYNcE+x2u5a2tB73CAa6BzXFRUTizd3sx3OAVZELWFBJ6GR0gERcjjeXZItXBSw==
|
||||
dependencies:
|
||||
"@transloadit/prettier-bytes" "0.0.7"
|
||||
"@uppy/informer" "^1.5.11"
|
||||
"@uppy/provider-views" "^1.7.7"
|
||||
"@uppy/status-bar" "^1.7.6"
|
||||
"@uppy/thumbnail-generator" "^1.6.7"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/informer" "^1.6.0"
|
||||
"@uppy/provider-views" "^1.11.0"
|
||||
"@uppy/status-bar" "^1.9.0"
|
||||
"@uppy/thumbnail-generator" "^1.7.5"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
classnames "^2.2.6"
|
||||
cuid "^2.1.1"
|
||||
is-shallow-equal "^1.0.1"
|
||||
|
|
@ -4543,134 +4544,128 @@
|
|||
preact "8.2.9"
|
||||
resize-observer-polyfill "^1.5.0"
|
||||
|
||||
"@uppy/drag-drop@^1.4.19":
|
||||
version "1.4.19"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/drag-drop/-/drag-drop-1.4.19.tgz#b8e2748c6384cddaf42b43d55c801288d59f5e60"
|
||||
integrity sha512-gY1zDOcAqw1tNNCIhjjJm63IujZyNpAUA6yMVWuSri9Sisy7D2GjJUuoRhUUBZlg37AJthFSku7NVERMBxqSTw==
|
||||
"@uppy/drag-drop@^1.4.24":
|
||||
version "1.4.24"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/drag-drop/-/drag-drop-1.4.24.tgz#02ee9df001a1074f45ddaeb93fc84f7f7c05d82f"
|
||||
integrity sha512-uiAGu2GlLH/AE3B6H1ooyDGuRmVPcycpVXupzavlXMMTd4NDnove9DK24svvzTYYm83WgRIF3UDqkDn12wYn1w==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/file-input@^1.3.1":
|
||||
version "1.4.17"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/file-input/-/file-input-1.4.17.tgz#60cd804b57be35dcfb4a6edfd1a7b6c15f1095ed"
|
||||
integrity sha512-Z29AYWLwd2pOCEeEFdrhkEvzKOCYRm60H7j5heZ6HIovU0bdz7znpY5s9pVg6R4JDwtUux05+zMexFKKMxuVmA==
|
||||
"@uppy/file-input@^1.4.22":
|
||||
version "1.4.22"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/file-input/-/file-input-1.4.22.tgz#e8642542ceedce71a11494f08d41a5144605f814"
|
||||
integrity sha512-GvH3B3fQqJdeKUxRIK1RMAd3BizlCigXjDXO7ndEfXlc/iK7YQi7P8UUZadfdgOK7bne2JPzKydvkSP1EbVAwQ==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/google-drive@^1.3.2":
|
||||
version "1.5.16"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/google-drive/-/google-drive-1.5.16.tgz#12f37a0c8320980edda901b335d1fd5bb8a84ecb"
|
||||
integrity sha512-es6rKyY3iUnpX6i5LNt/okzz5GIQKdnE8GS/GzbIlywsenRFw9hpRo5oqIDFqkKCQ4t0PKOoB5kb1d18VfJxuw==
|
||||
"@uppy/google-drive@^1.5.22":
|
||||
version "1.5.22"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/google-drive/-/google-drive-1.5.22.tgz#d185e8da86ba2a42d1198544401a60c9092e4025"
|
||||
integrity sha512-yzlT4J3FDh2By1ogjmFWRFxuVybLCVuZYg55vTUKnIrQWCbd8clena2YZuuJofJOAYjd4HlCaaRKZDFKekS89w==
|
||||
dependencies:
|
||||
"@uppy/companion-client" "^1.5.4"
|
||||
"@uppy/provider-views" "^1.7.7"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/companion-client" "^1.8.1"
|
||||
"@uppy/provider-views" "^1.11.0"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/informer@^1.5.11":
|
||||
version "1.5.11"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/informer/-/informer-1.5.11.tgz#ebd5b8960838e47ec2088a2ce0e6b914b664a283"
|
||||
integrity sha512-sZIWKvV3UO5Epk6V2e5girlzgsqukDAKnLkZh6nOqjSGRkMudGUrEZwuSOB496lBVqo38BTavI/zf+eLvrdBlA==
|
||||
"@uppy/informer@^1.6.0":
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/informer/-/informer-1.6.0.tgz#65e90c1f258c8fc54c71dcbf4a8d0c485400fc8e"
|
||||
integrity sha512-599eQol5XlsVk+rIRctMKGbUHldyeDOHxzSHgvzsTOSBLL3vj6bN+OblBX1kF4DlHgEHhanLrjo+UfjvpNvy+A==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/onedrive@^0.1.1":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/onedrive/-/onedrive-0.1.4.tgz#18e4459019070ec7f2430629cdeb16fddeb343c4"
|
||||
integrity sha512-3qOhqjh7kv7I7S7t8qSFYNQf3Jr6g+DrNgsf/jcht/mp7zm1F+UlJR/nmxZC5BEtUbA91GYPXwcowxdeX+oWvQ==
|
||||
"@uppy/onedrive@^1.1.22":
|
||||
version "1.1.22"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/onedrive/-/onedrive-1.1.22.tgz#16e983f299cd1afc12c5c8b7e6551417ebff20f8"
|
||||
integrity sha512-nCqj+l6+YsYASt/bHIzuvSDuFzweESD/gzBi+/1XE6CaQytzqqDbEfxhxkTcaoyj6iu+GGsKHxTJ8h8YSPEr4g==
|
||||
dependencies:
|
||||
"@uppy/companion-client" "^1.4.1"
|
||||
"@uppy/provider-views" "^1.5.2"
|
||||
"@uppy/utils" "^2.1.2"
|
||||
"@uppy/companion-client" "^1.8.1"
|
||||
"@uppy/provider-views" "^1.11.0"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/progress-bar@^1.3.19":
|
||||
version "1.3.19"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/progress-bar/-/progress-bar-1.3.19.tgz#6abf87a2c05f1d91c2d1fb2955ce0d5ca2199408"
|
||||
integrity sha512-o0sCpN7J/CcW17IbOoQ/0kbUGHoVPgwfHgyrO77I0J5aMn+qFqEs094xvVnU7gp92NMBsllvT1Vyr8ZNtPq+Dg==
|
||||
"@uppy/progress-bar@^1.3.24":
|
||||
version "1.3.24"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/progress-bar/-/progress-bar-1.3.24.tgz#a4fa3ca88931b6333a1583ee9a2670f591206dca"
|
||||
integrity sha512-FLfGGaswnr+Glsk+1WIxd5tT0DfxxZJiLhjmBHVZZGHy2qpBpXbPTeFxcPdlOUPokYKeBGqMKyAYz/LBVpjXAQ==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/provider-views@^1.5.2", "@uppy/provider-views@^1.7.7":
|
||||
version "1.7.7"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/provider-views/-/provider-views-1.7.7.tgz#fe85617d86b72ce376f9efa0c369ab7b2eb3af2e"
|
||||
integrity sha512-PLIAeUJKNOU+Yfxr4iX6oFoHS15SZZhnDj+n2JWyg3l6iNOG7gvLq85OMARFOUA0DlP5srRq4NlR/nlMWo+0xw==
|
||||
"@uppy/provider-views@^1.11.0":
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/provider-views/-/provider-views-1.11.0.tgz#efd6db4d77a539ad092f4b178a3480701bbc9f7e"
|
||||
integrity sha512-aFGGzByDAR3w8QgMRiuE2XEkDsr51bN6kPiE2p6zplwKZ5FGPVx+j5/+pUNa0Qsb8w0dYJBqlhCCnFcRBDkgjw==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
classnames "^2.2.6"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/react@^1.4.5":
|
||||
version "1.10.8"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/react/-/react-1.10.8.tgz#260bc37693c8a1aa6f719cada22b67414913466d"
|
||||
integrity sha512-FO6PThrYZaEGZd7G3YooHHKsxhZqF6/Euy+jI8CLhROf78Kg0Gr3dURhwaH902NgPrA5Yfa6xRSC1d4etwMktg==
|
||||
"@uppy/react@^1.11.2":
|
||||
version "1.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/react/-/react-1.11.2.tgz#9d1a1a4c0710e456654cdb4dc17735501036a54a"
|
||||
integrity sha512-Pz4ghEn+9I8XiAkqJGKMLXbVvcnvTAID/o7aqXq7yMQGi61sy3SUgeagX0yaCuKOZ6l4IXItPsZnBMe/Km3MJQ==
|
||||
dependencies:
|
||||
"@uppy/dashboard" "^1.12.8"
|
||||
"@uppy/drag-drop" "^1.4.19"
|
||||
"@uppy/progress-bar" "^1.3.19"
|
||||
"@uppy/status-bar" "^1.7.6"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/dashboard" "^1.16.0"
|
||||
"@uppy/drag-drop" "^1.4.24"
|
||||
"@uppy/file-input" "^1.4.22"
|
||||
"@uppy/progress-bar" "^1.3.24"
|
||||
"@uppy/status-bar" "^1.9.0"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
prop-types "^15.6.1"
|
||||
|
||||
"@uppy/status-bar@^1.7.6":
|
||||
version "1.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/status-bar/-/status-bar-1.7.6.tgz#f25b50466398b1952c8b60b16d2c491ea342992f"
|
||||
integrity sha512-nlZztGjDNEmWZQfWfV/DajeNjtdhqeGO1mRQVpmjWvrCABFaTvWN9jb1t7VEZjuaegSujZot00RP7uU4au/Q+w==
|
||||
"@uppy/status-bar@^1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/status-bar/-/status-bar-1.9.0.tgz#1db2859fd10b1dc7eb6045dbeb56bb3b4cbcb518"
|
||||
integrity sha512-5Hmx3iRRDfP04xmopDXAzEYz7GM4SNAXs2ayRPYSQZ5OC2Bvqqb2IYVLj09PHCRsH695VBGz9+3kIEvn/OFqbQ==
|
||||
dependencies:
|
||||
"@transloadit/prettier-bytes" "0.0.7"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
classnames "^2.2.6"
|
||||
lodash.throttle "^4.1.1"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/store-default@^1.2.4":
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/store-default/-/store-default-1.2.4.tgz#480f50cbf23f36158557a42b7699da0cf629d368"
|
||||
integrity sha512-d4YTq6SeH792+vG9OXGCfmCIoo4RteLJKU2mZCzMYNjCZ1yNfU/FVw1r7heTc7f2wNls56ABor2xSybk/X+wFA==
|
||||
"@uppy/store-default@^1.2.5":
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/store-default/-/store-default-1.2.5.tgz#52936331d6ac4911197d256d13974d5bae93b3a6"
|
||||
integrity sha512-jnf0U8cfb8Bhgt6yh86YRJO9EEnCyG9BgXZ8dPWWLybgC9Expw3Ah/s3T21tcdChgv4zzdhSACd0JKxCQowyYg==
|
||||
|
||||
"@uppy/thumbnail-generator@^1.6.7":
|
||||
version "1.6.7"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/thumbnail-generator/-/thumbnail-generator-1.6.7.tgz#65375106dae2cfd1f4cddb073e9d8ff278ca94e5"
|
||||
integrity sha512-8FRO042ulfK3qRDE1tEETxw/iDIrLzlHxqhrHG45kxZ2QfqbByg5bJAgvlwg7Zyd4202rkq75J8KeFowS/Ntjg==
|
||||
"@uppy/thumbnail-generator@^1.7.5":
|
||||
version "1.7.5"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/thumbnail-generator/-/thumbnail-generator-1.7.5.tgz#ae2fa68c684463b41fa7b4a878c4e29974680c6f"
|
||||
integrity sha512-YUbFLpkfOudbdJMQPqWmVmq/qHh40+0ZHkJHrStpZmTq/OSjHLxyXWSZ1RDgJnAcsh3lUhR4yuembNVmtSrtjg==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
exifr "^5.0.2"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
exifr "^6.0.0"
|
||||
math-log2 "^1.0.1"
|
||||
|
||||
"@uppy/url@^1.3.2":
|
||||
version "1.5.11"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/url/-/url-1.5.11.tgz#a664b6a386c913ce33af51c8f497c3e036a0389b"
|
||||
integrity sha512-EYAK/9m++O1HApKCty3Vd6T5qcdCMC3GL0IfN1kO0cE6J7fmhL7nEnud5eWqq6752ydNmhvR9lFYrPv/8AHljQ==
|
||||
"@uppy/url@^1.5.16":
|
||||
version "1.5.16"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/url/-/url-1.5.16.tgz#636830aa01b13a3726abfe87c2e66006412ba867"
|
||||
integrity sha512-IEsfhVwTUoyvgZcr/uHEwxBMX8SDQQBXFkd3eW0T+jSNVzyP7jQo7bqVyUEjrALOp9xH8X21aXTPvnWc4k1iww==
|
||||
dependencies:
|
||||
"@uppy/companion-client" "^1.5.4"
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/companion-client" "^1.8.1"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@uppy/utils@^2.1.2":
|
||||
version "2.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/utils/-/utils-2.4.4.tgz#29520cdfaf926af58828a9c141cb7b0fa43f8bc4"
|
||||
integrity sha512-7A0uwK5Rf8XcKqlpNUZ5L5LmkHT5c0/UWjDJGwmzeCxp2lECgzsMC+4vgA6kT4sFzPFbLtUtxHi7ecFwow3NQQ==
|
||||
dependencies:
|
||||
lodash.throttle "^4.1.1"
|
||||
|
||||
"@uppy/utils@^3.2.3":
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/utils/-/utils-3.2.3.tgz#91cb4a133bd610b861fe3069be1f0e85036dcc20"
|
||||
integrity sha512-ue14v4yKK6bYBPGjt31wvLnYMThKCVOsy3R7y++eFuPsxfidIGmOGiv+Qmv0895kMJtt7gk0MddXjbCdBX4Ksg==
|
||||
"@uppy/utils@^3.4.0":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/utils/-/utils-3.4.0.tgz#4afcf8c26dec13ee54676bd1f7958fc1063b68df"
|
||||
integrity sha512-XcT4UgUm1NhWAeQjMrr5LCE7Uookg12FTwQw/QwXBuGABoVilfk56i6h8ecf1bVX0D74zdpSnUiB1h+8a7ollw==
|
||||
dependencies:
|
||||
abortcontroller-polyfill "^1.4.0"
|
||||
lodash.throttle "^4.1.1"
|
||||
|
||||
"@uppy/webcam@^1.3.1":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/webcam/-/webcam-1.7.0.tgz#e770733b0679454ed1aa78075d55f49a95b1cc6c"
|
||||
integrity sha512-j5OAAAHWAPDLThdnHS/a6K9O28FQbsi7ZOX7FJzA+u14iOBEmAbuWy99ziETITNdE6vIjiRrak1ixeDSdPFRQQ==
|
||||
"@uppy/webcam@^1.8.4":
|
||||
version "1.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@uppy/webcam/-/webcam-1.8.4.tgz#7a4f7f9dc4def955e701560a59c22fdb08e5efe4"
|
||||
integrity sha512-WhJrOgH0N2V5QhQZc10N1kIunxOF3/SQ/KTssTEudn7tkVNhkTLRldAlmcA4vZ0HB3Zxg9HaJPy4twBvUgFUbw==
|
||||
dependencies:
|
||||
"@uppy/utils" "^3.2.3"
|
||||
"@uppy/utils" "^3.4.0"
|
||||
preact "8.2.9"
|
||||
|
||||
"@vue/compiler-core@3.0.0":
|
||||
|
|
@ -4912,9 +4907,9 @@ abbrev@1:
|
|||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||
|
||||
abortcontroller-polyfill@^1.4.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.5.0.tgz#2c562f530869abbcf88d949a2b60d1d402e87a7c"
|
||||
integrity sha512-O6Xk757Jb4o0LMzMOMdWvxpHWrQzruYBaUruFaIOfAQRnWFxfdXYobw12jrVHGtoXk6WiiyYzc0QWN9aL62HQA==
|
||||
version "1.7.1"
|
||||
resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.1.tgz#27084bac87d78a7224c8ee78135d05df430c2d2f"
|
||||
integrity sha512-yml9NiDEH4M4p0G4AcPkg8AAa4mF3nfYF28VQxaokpO67j9H7gWgmsVWJ/f1Rn+PzsnDYvzJzWIQzCqDKRvWlA==
|
||||
|
||||
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
||||
version "1.3.7"
|
||||
|
|
@ -8905,10 +8900,10 @@ executable@^4.1.1:
|
|||
dependencies:
|
||||
pify "^2.2.0"
|
||||
|
||||
exifr@^5.0.2:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/exifr/-/exifr-5.0.6.tgz#7c8e5aad1083fa4ec172103dca24215203001209"
|
||||
integrity sha512-iDB4IhKoKVF+uDDrHRlyNxWqGaTxYluVWqvBWVG54HkQZe8qkFYl9eQrjEP3d8Q4UMBZ9rWu3Pa+mfC+o4CZuw==
|
||||
exifr@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/exifr/-/exifr-6.0.0.tgz#e82af10e158852a1c7e19aea45bceb4cdd486727"
|
||||
integrity sha512-a8n3SVIyuI5NP5VJCb/rJHsqXnofgYL1ZXcJdKBXOmCNIrj+pSExaBFHcbdEF5xp5GQrK4kpOabLJ+wBfUGYuA==
|
||||
|
||||
exit-hook@^1.0.0:
|
||||
version "1.1.1"
|
||||
|
|
@ -15374,6 +15369,11 @@ q@^1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
||||
|
||||
qs-stringify@^1.1.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/qs-stringify/-/qs-stringify-1.2.1.tgz#9b39ef6b816bd83309628fc9dad435fc0eccc28b"
|
||||
integrity sha512-2N5xGLGZUxpgAYq1fD1LmBSCbxQVsXYt5JU0nU3FuPWO8PlCnKNFQwXkZgyB6mrTdg7IbexX4wxIR403dJw9pw==
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ public enum AppsmithPluginError {
|
|||
AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_JSON_PARSE_ERROR(500, 5006, "Plugin failed to parse JSON \"{0}\" with error: {1}",
|
||||
AppsmithErrorAction.DEFAULT),
|
||||
PLUGIN_DATASOURCE_TEST_GENERIC_ERROR(500, 5007, "Plugin failed to test with the given configuration. Please reach out to Appsmith customer support to report this",
|
||||
AppsmithErrorAction.LOG_EXTERNALLY),
|
||||
;
|
||||
|
||||
private final Integer httpErrorCode;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DatasourceStructure {
|
||||
|
||||
List<Table> tables;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
package com.appsmith.external.models;
|
||||
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
|
|
@ -21,6 +24,15 @@ public class DatasourceTestResult {
|
|||
* @param invalids String messages that explain why the test failed.
|
||||
*/
|
||||
public DatasourceTestResult(String... invalids) {
|
||||
if (invalids == null) {
|
||||
invalids = new String[]{AppsmithPluginError.PLUGIN_DATASOURCE_TEST_GENERIC_ERROR.getMessage()};
|
||||
} else {
|
||||
invalids = Arrays
|
||||
.stream(invalids)
|
||||
.map(x -> x == null ? AppsmithPluginError.PLUGIN_DATASOURCE_TEST_GENERIC_ERROR.getMessage() : x)
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
|
||||
this.invalids = Set.of(invalids);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package com.appsmith.external.models;
|
||||
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DatasourceTestResultTest {
|
||||
|
||||
@Test
|
||||
public void testNewDatasourceTestResult_NullInvalidArray() {
|
||||
DatasourceTestResult nullInvalidsResult = new DatasourceTestResult((String) null);
|
||||
assertNotNull(nullInvalidsResult);
|
||||
assertTrue(nullInvalidsResult.getInvalids().contains(AppsmithPluginError.PLUGIN_DATASOURCE_TEST_GENERIC_ERROR.getMessage()));
|
||||
|
||||
nullInvalidsResult = new DatasourceTestResult(new String[]{null});
|
||||
assertNotNull(nullInvalidsResult);
|
||||
assertTrue(nullInvalidsResult.getInvalids().contains(AppsmithPluginError.PLUGIN_DATASOURCE_TEST_GENERIC_ERROR.getMessage()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
package com.external.plugins;
|
||||
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
||||
import com.appsmith.external.models.ActionConfiguration;
|
||||
import com.appsmith.external.models.ActionExecutionResult;
|
||||
import com.appsmith.external.models.DBAuth;
|
||||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
import com.appsmith.external.models.DatasourceStructure;
|
||||
import com.appsmith.external.models.DatasourceTestResult;
|
||||
import com.appsmith.external.models.Endpoint;
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError;
|
||||
import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException;
|
||||
import com.appsmith.external.plugins.BasePlugin;
|
||||
import com.appsmith.external.plugins.PluginExecutor;
|
||||
import lombok.NonNull;
|
||||
|
|
@ -29,6 +30,7 @@ import software.amazon.awssdk.regions.Region;
|
|||
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
|
||||
import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder;
|
||||
import software.amazon.awssdk.services.dynamodb.model.DynamoDbResponse;
|
||||
import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
|
@ -38,6 +40,7 @@ import java.net.URI;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
|
@ -73,15 +76,15 @@ public class DynamoPlugin extends BasePlugin {
|
|||
DatasourceConfiguration datasourceConfiguration,
|
||||
ActionConfiguration actionConfiguration) {
|
||||
|
||||
return (Mono<ActionExecutionResult>) Mono.fromCallable(() -> {
|
||||
return Mono.fromCallable(() -> {
|
||||
ActionExecutionResult result = new ActionExecutionResult();
|
||||
|
||||
final String action = actionConfiguration.getPath();
|
||||
if (StringUtils.isEmpty(action)) {
|
||||
return Mono.error(new AppsmithPluginException(
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR,
|
||||
"Missing action name (like `ListTables`, `GetItem` etc.)."
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
final String body = actionConfiguration.getBody();
|
||||
|
|
@ -93,17 +96,17 @@ public class DynamoPlugin extends BasePlugin {
|
|||
} catch (IOException e) {
|
||||
final String message = "Error parsing the JSON body: " + e.getMessage();
|
||||
log.warn(message, e);
|
||||
return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, message));
|
||||
throw new AppsmithPluginException(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, message);
|
||||
}
|
||||
|
||||
final Class<?> requestClass;
|
||||
try {
|
||||
requestClass = Class.forName("software.amazon.awssdk.services.dynamodb.model." + action + "Request");
|
||||
} catch (ClassNotFoundException e) {
|
||||
return Mono.error(new AppsmithPluginException(
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_ERROR,
|
||||
"Unknown action: `" + action + "`. Note that action names are case-sensitive."
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -117,21 +120,20 @@ public class DynamoPlugin extends BasePlugin {
|
|||
} catch (AppsmithPluginException | InvocationTargetException | IllegalAccessException | NoSuchMethodException | ClassNotFoundException e) {
|
||||
final String message = "Error executing the DynamoDB Action: " + (e.getCause() == null ? e : e.getCause()).getMessage();
|
||||
log.warn(message, e);
|
||||
return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, message));
|
||||
throw new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, message);
|
||||
}
|
||||
|
||||
result.setIsExecutionSuccess(true);
|
||||
System.out.println(Thread.currentThread().getName() + ": In the DynamoPlugin, got action execution result");
|
||||
return Mono.just(result);
|
||||
return result;
|
||||
})
|
||||
.flatMap(obj -> obj)
|
||||
.subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<DynamoDbClient> datasourceCreate(DatasourceConfiguration datasourceConfiguration) {
|
||||
|
||||
return (Mono<DynamoDbClient>) Mono.fromCallable(() -> {
|
||||
return Mono.fromCallable(() -> {
|
||||
final DynamoDbClientBuilder builder = DynamoDbClient.builder();
|
||||
|
||||
if (!CollectionUtils.isEmpty(datasourceConfiguration.getEndpoints())) {
|
||||
|
|
@ -141,10 +143,10 @@ public class DynamoPlugin extends BasePlugin {
|
|||
|
||||
final DBAuth authentication = (DBAuth) datasourceConfiguration.getAuthentication();
|
||||
if (authentication == null || StringUtils.isEmpty(authentication.getDatabaseName())) {
|
||||
return Mono.error(new AppsmithPluginException(
|
||||
throw new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_DATASOURCE_ARGUMENT_ERROR,
|
||||
"Missing region in datasource."
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
builder.region(Region.of(authentication.getDatabaseName()));
|
||||
|
|
@ -153,9 +155,8 @@ public class DynamoPlugin extends BasePlugin {
|
|||
AwsBasicCredentials.create(authentication.getUsername(), authentication.getPassword())
|
||||
));
|
||||
|
||||
return Mono.justOrEmpty(builder.build());
|
||||
return builder.build();
|
||||
})
|
||||
.flatMap(obj -> obj)
|
||||
.subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +205,28 @@ public class DynamoPlugin extends BasePlugin {
|
|||
)
|
||||
.subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<DatasourceStructure> getStructure(DynamoDbClient ddb, DatasourceConfiguration datasourceConfiguration) {
|
||||
return Mono.fromCallable(() -> {
|
||||
final ListTablesResponse listTablesResponse = ddb.listTables();
|
||||
|
||||
List<DatasourceStructure.Table> tables = new ArrayList<>();
|
||||
for (final String tableName : listTablesResponse.tableNames()) {
|
||||
tables.add(new DatasourceStructure.Table(
|
||||
DatasourceStructure.TableType.TABLE,
|
||||
tableName,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList()
|
||||
));
|
||||
}
|
||||
|
||||
return new DatasourceStructure(tables);
|
||||
|
||||
}).subscribeOn(scheduler);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static String toLowerCamelCase(String action) {
|
||||
|
|
@ -259,7 +282,8 @@ public class DynamoPlugin extends BasePlugin {
|
|||
|| value instanceof Integer
|
||||
|| value instanceof Float
|
||||
|| value instanceof Double) {
|
||||
// These data types have a setter method that takes a the value as is. Nothing fancy here.
|
||||
// This will *never* be successful. DynamoDB takes in numeric values as strings, which means the
|
||||
// control should never flow here for numeric types.
|
||||
builderType.getMethod(setterName, value.getClass()).invoke(builder, value);
|
||||
|
||||
} else if (value instanceof Map) {
|
||||
|
|
@ -337,44 +361,41 @@ public class DynamoPlugin extends BasePlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private static Map<String, Object> sdkToPlain(SdkPojo response) {
|
||||
final Map<String, Object> plain = new HashMap<>();
|
||||
private static Object sdkToPlain(Object valueObj) {
|
||||
if (valueObj instanceof SdkPojo) {
|
||||
final SdkPojo response = (SdkPojo) valueObj;
|
||||
final Map<String, Object> plain = new HashMap<>();
|
||||
|
||||
for (final SdkField<?> field : response.sdkFields()) {
|
||||
Object value = field.getValueOrDefault(response);
|
||||
|
||||
if (value instanceof SdkPojo) {
|
||||
value = sdkToPlain((SdkPojo) value);
|
||||
|
||||
} else if (value instanceof Map) {
|
||||
final Map<String, Object> valueAsMap = (Map) value;
|
||||
final Map<String, Object> plainMap = new HashMap<>();
|
||||
for (final Map.Entry<String, Object> entry : valueAsMap.entrySet()) {
|
||||
final var key = entry.getKey();
|
||||
Object innerValue = entry.getValue();
|
||||
if (innerValue instanceof SdkPojo) {
|
||||
innerValue = sdkToPlain((SdkPojo) innerValue);
|
||||
}
|
||||
plainMap.put(key, innerValue);
|
||||
}
|
||||
value = plainMap;
|
||||
|
||||
} else if (value instanceof List) {
|
||||
final List<Object> valueAsList = (List) value;
|
||||
final List<Object> plainList = new ArrayList<>();
|
||||
for (Object item : valueAsList) {
|
||||
if (item instanceof SdkPojo) {
|
||||
item = sdkToPlain((SdkPojo) item);
|
||||
}
|
||||
plainList.add(item);
|
||||
}
|
||||
value = plainList;
|
||||
for (final SdkField<?> field : response.sdkFields()) {
|
||||
Object value = field.getValueOrDefault(response);
|
||||
plain.put(field.memberName(), sdkToPlain(value));
|
||||
}
|
||||
|
||||
plain.put(field.memberName(), value);
|
||||
return plain;
|
||||
|
||||
} else if (valueObj instanceof Map) {
|
||||
final Map<?, ?> valueAsMap = (Map<?, ?>) valueObj;
|
||||
final Map<Object, Object> plainMap = new HashMap<>();
|
||||
|
||||
for (final Map.Entry<?, ?> entry : valueAsMap.entrySet()) {
|
||||
plainMap.put(entry.getKey(), sdkToPlain(entry.getValue()));
|
||||
}
|
||||
|
||||
return plainMap;
|
||||
|
||||
} else if (valueObj instanceof Collection) {
|
||||
final List<?> valueAsList = (List<?>) valueObj;
|
||||
final List<Object> plainList = new ArrayList<>();
|
||||
|
||||
for (Object item : valueAsList) {
|
||||
plainList.add(sdkToPlain(item));
|
||||
}
|
||||
|
||||
return plainList;
|
||||
|
||||
}
|
||||
|
||||
return plain;
|
||||
return valueObj;
|
||||
}
|
||||
|
||||
private static boolean isUpperCase(String s) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.appsmith.external.models.ActionConfiguration;
|
|||
import com.appsmith.external.models.ActionExecutionResult;
|
||||
import com.appsmith.external.models.DBAuth;
|
||||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
import com.appsmith.external.models.DatasourceStructure;
|
||||
import com.appsmith.external.models.Endpoint;
|
||||
import lombok.extern.log4j.Log4j;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
@ -29,6 +30,7 @@ import java.net.URI;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -91,8 +93,6 @@ public class DynamoPluginTest {
|
|||
))
|
||||
.build());
|
||||
|
||||
System.out.println(ddb.listTables());
|
||||
|
||||
Endpoint endpoint = new Endpoint();
|
||||
endpoint.setHost(host);
|
||||
endpoint.setPort(port.longValue());
|
||||
|
|
@ -221,4 +221,41 @@ public class DynamoPluginTest {
|
|||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScan() {
|
||||
final String body = "{\n" +
|
||||
" \"TableName\": \"cities\"\n" +
|
||||
"}\n";
|
||||
|
||||
StepVerifier.create(execute("Scan", body))
|
||||
.assertNext(result -> {
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getIsExecutionSuccess());
|
||||
assertNotNull(result.getBody());
|
||||
final List<Object> items = (List<Object>) ((Map<String, Object>) result.getBody()).get("Items");
|
||||
assertEquals(2, items.size());
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStructure() {
|
||||
final Mono<DatasourceStructure> structureMono = pluginExecutor
|
||||
.datasourceCreate(dsConfig)
|
||||
.flatMap(conn -> pluginExecutor.getStructure(conn, dsConfig));
|
||||
|
||||
StepVerifier.create(structureMono)
|
||||
.assertNext(structure -> {
|
||||
assertNotNull(structure);
|
||||
assertNotNull(structure.getTables());
|
||||
assertEquals(
|
||||
List.of("cities"),
|
||||
structure.getTables().stream()
|
||||
.map(DatasourceStructure.Table::getName)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,12 @@
|
|||
{
|
||||
"label": "Body",
|
||||
"configProperty": "actionConfiguration.body",
|
||||
"controlType": "QUERY_DYNAMIC_TEXT"
|
||||
"controlType": "QUERY_DYNAMIC_TEXT",
|
||||
"hidden": {
|
||||
"path": "actionConfiguration.pluginSpecifiedTemplates[0].value",
|
||||
"comparison": "IN",
|
||||
"value": ["GET_DOCUMENT", "GET_COLLECTION", "DELETE_DOCUMENT"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -347,13 +347,15 @@ public class MySqlPlugin extends BasePlugin {
|
|||
@Override
|
||||
public Mono<DatasourceTestResult> testDatasource(DatasourceConfiguration datasourceConfiguration) {
|
||||
return datasourceCreate(datasourceConfiguration)
|
||||
.flatMap(connection -> {
|
||||
return Mono.from(connection.close());
|
||||
})
|
||||
.flatMap(connection -> Mono.from(connection.close()))
|
||||
.then(Mono.just(new DatasourceTestResult()))
|
||||
.onErrorResume(error -> {
|
||||
log.error("Error when testing MySQL datasource.", error);
|
||||
return Mono.just(new DatasourceTestResult(error.getMessage()));
|
||||
// We always expect to have an error object, but the error object may not be well formed
|
||||
final String errorMessage = error.getMessage() == null
|
||||
? AppsmithPluginError.PLUGIN_DATASOURCE_TEST_GENERIC_ERROR.getMessage()
|
||||
: error.getMessage();
|
||||
System.out.println("Error when testing MySQL datasource. " + errorMessage);
|
||||
return Mono.just(new DatasourceTestResult(errorMessage));
|
||||
})
|
||||
.subscribeOn(scheduler);
|
||||
|
||||
|
|
@ -541,14 +543,14 @@ public class MySqlPlugin extends BasePlugin {
|
|||
return structure;
|
||||
})
|
||||
.onErrorMap(e -> {
|
||||
if (!(e instanceof AppsmithPluginException) && !(e instanceof StaleConnectionException)) {
|
||||
return new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_ERROR,
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
if (!(e instanceof AppsmithPluginException) && !(e instanceof StaleConnectionException)) {
|
||||
return new AppsmithPluginException(
|
||||
AppsmithPluginError.PLUGIN_ERROR,
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
return e;
|
||||
return e;
|
||||
})
|
||||
.subscribeOn(scheduler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ package com.appsmith.server.controllers;
|
|||
|
||||
import com.appsmith.external.models.ActionExecutionResult;
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ActionMoveDTO;
|
||||
import com.appsmith.server.dtos.ActionViewDTO;
|
||||
import com.appsmith.server.dtos.ExecuteActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.dtos.RefactorNameDTO;
|
||||
import com.appsmith.server.dtos.ResponseDTO;
|
||||
import com.appsmith.server.services.ActionCollectionService;
|
||||
|
|
@ -82,7 +82,7 @@ public class ActionController {
|
|||
}
|
||||
|
||||
@PutMapping("/refactor")
|
||||
public Mono<ResponseDTO<Layout>> refactorActionName(@RequestBody RefactorNameDTO refactorNameDTO) {
|
||||
public Mono<ResponseDTO<LayoutDTO>> refactorActionName(@RequestBody RefactorNameDTO refactorNameDTO) {
|
||||
return layoutActionService.refactorActionName(refactorNameDTO)
|
||||
.map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.appsmith.server.controllers;
|
|||
|
||||
import com.appsmith.server.constants.Url;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.dtos.RefactorNameDTO;
|
||||
import com.appsmith.server.dtos.ResponseDTO;
|
||||
import com.appsmith.server.services.LayoutActionService;
|
||||
|
|
@ -46,7 +47,7 @@ public class LayoutController {
|
|||
}
|
||||
|
||||
@PutMapping("/{layoutId}/pages/{pageId}")
|
||||
public Mono<ResponseDTO<Layout>> updateLayout(@PathVariable String pageId, @PathVariable String layoutId, @RequestBody Layout layout) {
|
||||
public Mono<ResponseDTO<LayoutDTO>> updateLayout(@PathVariable String pageId, @PathVariable String layoutId, @RequestBody Layout layout) {
|
||||
return layoutActionService.updateLayout(pageId, layoutId, layout)
|
||||
.map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null));
|
||||
}
|
||||
|
|
@ -58,7 +59,7 @@ public class LayoutController {
|
|||
}
|
||||
|
||||
@PutMapping("/refactor")
|
||||
public Mono<ResponseDTO<Layout>> refactorWidgetName(@RequestBody RefactorNameDTO refactorNameDTO) {
|
||||
public Mono<ResponseDTO<LayoutDTO>> refactorWidgetName(@RequestBody RefactorNameDTO refactorNameDTO) {
|
||||
return layoutActionService.refactorWidgetName(refactorNameDTO)
|
||||
.map(created -> new ResponseDTO<>(HttpStatus.OK.value(), created, null));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.appsmith.server.dtos;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
/**
|
||||
* This class would be used to send any action updates that have happened as part of update layout. The client should
|
||||
* consume this structure to update the actions in its local storage (instead of fetching all the page actions afresh).
|
||||
*/
|
||||
public class LayoutActionUpdateDTO {
|
||||
String id;
|
||||
String name;
|
||||
Boolean executeOnLoad;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.appsmith.server.dtos;
|
||||
|
||||
import com.appsmith.server.domains.ScreenType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.minidev.json.JSONObject;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class LayoutDTO {
|
||||
|
||||
private String id;
|
||||
|
||||
ScreenType screen;
|
||||
|
||||
JSONObject dsl;
|
||||
|
||||
List<HashSet<DslActionDTO>> layoutOnLoadActions;
|
||||
|
||||
// All the actions which have been updated as part of updateLayout function call
|
||||
List<LayoutActionUpdateDTO> actionUpdates;
|
||||
|
||||
// All the toast messages that the developer user should be displayed to inform about the consequences of update layout.
|
||||
List<String> messages;
|
||||
|
||||
public Set<String> userPermissions = new HashSet<>();
|
||||
}
|
||||
|
|
@ -251,14 +251,14 @@ public class MustacheHelper {
|
|||
|
||||
} else if (value instanceof List) {
|
||||
for (Object childValue : (List) value) {
|
||||
if (isDomainModel(childValue.getClass())) {
|
||||
if (childValue != null && isDomainModel(childValue.getClass())) {
|
||||
renderFieldValues(childValue, context);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (value instanceof Map) {
|
||||
for (Object childValue : ((Map) value).values()) {
|
||||
if (isDomainModel(childValue.getClass())) {
|
||||
if (childValue != null && isDomainModel(childValue.getClass())) {
|
||||
renderFieldValues(childValue, context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1578,4 +1578,43 @@ public class DatabaseChangelog {
|
|||
public void clearUserDataCollection(MongoTemplate mongoTemplate) {
|
||||
mongoTemplate.dropCollection(UserData.class);
|
||||
}
|
||||
|
||||
@ChangeSet(order = "050", id = "update-database-documentation-links-v1-2-1", author = "")
|
||||
public void updateDatabaseDocumentationLinks_v1_2_1(MongoTemplate mongoTemplate) {
|
||||
for (Plugin plugin : mongoTemplate.findAll(Plugin.class)) {
|
||||
switch (plugin.getPackageName()) {
|
||||
case "postgres-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-postgres");
|
||||
break;
|
||||
case "mongo-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-mongodb");
|
||||
break;
|
||||
case "elasticsearch-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-elasticsearch");
|
||||
break;
|
||||
case "dynamo-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-dynamodb");
|
||||
break;
|
||||
case "redis-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-redis");
|
||||
break;
|
||||
case "mssql-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-mssql");
|
||||
break;
|
||||
case "firestore-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-firestore");
|
||||
break;
|
||||
case "redshift-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-redshift");
|
||||
break;
|
||||
case "mysql-plugin":
|
||||
plugin.setDocumentationLink("https://docs.appsmith.com/v/v1.2.1/datasource-reference/querying-mysql");
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
mongoTemplate.save(plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,10 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
public Mono<NewAction> findByUnpublishedNameAndPageId(String name, String pageId, AclPermission aclPermission) {
|
||||
Criteria nameCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.name)).is(name);
|
||||
Criteria pageCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).is(pageId);
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
|
||||
return queryOne(List.of(nameCriteria, pageCriteria), aclPermission);
|
||||
return queryOne(List.of(nameCriteria, pageCriteria, deletedCriteria), aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,17 +79,26 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
|
||||
@Override
|
||||
public Flux<NewAction> findByPageIdAndViewMode(String pageId, Boolean viewMode, AclPermission aclPermission) {
|
||||
Criteria pageCriteria;
|
||||
|
||||
List<Criteria> criteria = new ArrayList<>();
|
||||
|
||||
Criteria pageCriterion;
|
||||
|
||||
// Fetch published actions
|
||||
if (Boolean.TRUE.equals(viewMode)) {
|
||||
pageCriteria = where(fieldName(QNewAction.newAction.publishedAction) + "." + fieldName(QNewAction.newAction.publishedAction.pageId)).is(pageId);
|
||||
pageCriterion = where(fieldName(QNewAction.newAction.publishedAction) + "." + fieldName(QNewAction.newAction.publishedAction.pageId)).is(pageId);
|
||||
criteria.add(pageCriterion);
|
||||
}
|
||||
// Fetch unpublished actions
|
||||
else {
|
||||
pageCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).is(pageId);
|
||||
pageCriterion = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).is(pageId);
|
||||
criteria.add(pageCriterion);
|
||||
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteria.add(deletedCriteria);
|
||||
}
|
||||
return queryAll(List.of(pageCriteria), aclPermission);
|
||||
return queryAll(criteria, aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -163,6 +174,10 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
Criteria pageCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).in(pageIds);
|
||||
criteriaList.add(pageCriteria);
|
||||
}
|
||||
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteriaList.add(deletedCriteria);
|
||||
}
|
||||
|
||||
return queryAll(criteriaList, aclPermission, sort);
|
||||
|
|
@ -183,12 +198,17 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
Criteria executeOnLoadCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.executeOnLoad)).is(Boolean.TRUE);
|
||||
criteriaList.add(executeOnLoadCriteria);
|
||||
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteriaList.add(deletedCriteria);
|
||||
|
||||
return queryAll(criteriaList, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<NewAction> findUnpublishedActionsByNameInAndPageId(Set<String> names, String pageId, AclPermission permission) {
|
||||
List<Criteria> criteriaList = new ArrayList<>();
|
||||
|
||||
if (names != null) {
|
||||
Criteria namesCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.name)).in(names);
|
||||
criteriaList.add(namesCriteria);
|
||||
|
|
@ -196,6 +216,10 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
Criteria pageCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).is(pageId);
|
||||
criteriaList.add(pageCriteria);
|
||||
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteriaList.add(deletedCriteria);
|
||||
|
||||
return queryAll(criteriaList, permission);
|
||||
}
|
||||
|
||||
|
|
@ -212,6 +236,10 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
Criteria pageCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.pageId)).is(pageId);
|
||||
criteriaList.add(pageCriteria);
|
||||
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriteria = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteriaList.add(deletedCriteria);
|
||||
|
||||
return queryAll(criteriaList, permission);
|
||||
}
|
||||
|
||||
|
|
@ -228,9 +256,18 @@ public class CustomNewActionRepositoryImpl extends BaseAppsmithRepositoryImpl<Ne
|
|||
Boolean viewMode,
|
||||
AclPermission aclPermission) {
|
||||
|
||||
Criteria applicationCriteria = where(fieldName(QNewAction.newAction.applicationId)).is(applicationId);
|
||||
List<Criteria> criteria = new ArrayList<>();
|
||||
|
||||
return queryAll(List.of(applicationCriteria), aclPermission);
|
||||
Criteria applicationCriterion = where(fieldName(QNewAction.newAction.applicationId)).is(applicationId);
|
||||
criteria.add(applicationCriterion);
|
||||
|
||||
if (Boolean.FALSE.equals(viewMode)) {
|
||||
// In case an action has been deleted in edit mode, but still exists in deployed mode, NewAction object would exist. To handle this, only fetch non-deleted actions
|
||||
Criteria deletedCriterion = where(fieldName(QNewAction.newAction.unpublishedAction) + "." + fieldName(QNewAction.newAction.unpublishedAction.deletedAt)).is(null);
|
||||
criteria.add(deletedCriterion);
|
||||
}
|
||||
|
||||
return queryAll(criteria, aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
|
|||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
|
|
@ -33,37 +34,65 @@ public class CustomNewPageRepositoryImpl extends BaseAppsmithRepositoryImpl<NewP
|
|||
|
||||
@Override
|
||||
public Mono<NewPage> findByIdAndLayoutsIdAndViewMode(String id, String layoutId, AclPermission aclPermission, Boolean viewMode) {
|
||||
Criteria idCriterion = getIdCriteria(id);
|
||||
String layoutsIdKey;
|
||||
String layoutsKey;
|
||||
|
||||
List<Criteria> criteria = new ArrayList<>();
|
||||
Criteria idCriterion = getIdCriteria(id);
|
||||
criteria.add(idCriterion);
|
||||
|
||||
if (Boolean.TRUE.equals(viewMode)) {
|
||||
layoutsKey = fieldName(QNewPage.newPage.publishedPage) + "." + fieldName(QNewPage.newPage.publishedPage.layouts);
|
||||
} else {
|
||||
layoutsKey = fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.layouts);
|
||||
|
||||
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
|
||||
Criteria deletedCriterion = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
|
||||
criteria.add(deletedCriterion);
|
||||
}
|
||||
layoutsIdKey = layoutsKey + "." + fieldName(QLayout.layout.id);
|
||||
|
||||
Criteria layoutCriterion = where(layoutsIdKey).is(layoutId);
|
||||
criteria.add(layoutCriterion);
|
||||
|
||||
List<Criteria> criteria = List.of(idCriterion, layoutCriterion);
|
||||
return queryOne(criteria, aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<NewPage> findByNameAndViewMode(String name, AclPermission aclPermission, Boolean viewMode) {
|
||||
Criteria nameCriterion = getNameCriterion(name, viewMode);
|
||||
|
||||
return queryOne(List.of(nameCriterion), aclPermission);
|
||||
List<Criteria> criteria = new ArrayList<>();
|
||||
|
||||
Criteria nameCriterion = getNameCriterion(name, viewMode);
|
||||
criteria.add(nameCriterion);
|
||||
|
||||
if (Boolean.FALSE.equals(viewMode)) {
|
||||
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
|
||||
Criteria deletedCriterion = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
|
||||
criteria.add(deletedCriterion);
|
||||
}
|
||||
|
||||
return queryOne(criteria, aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<NewPage> findByNameAndApplicationIdAndViewMode(String name, String applicationId, AclPermission aclPermission, Boolean viewMode) {
|
||||
|
||||
List<Criteria> criteria = new ArrayList<>();
|
||||
|
||||
Criteria nameCriterion = getNameCriterion(name, viewMode);
|
||||
criteria.add(nameCriterion);
|
||||
|
||||
Criteria applicationIdCriterion = where(fieldName(QNewPage.newPage.applicationId)).is(applicationId);
|
||||
criteria.add(applicationIdCriterion);
|
||||
|
||||
return queryOne(List.of(nameCriterion, applicationIdCriterion), aclPermission);
|
||||
if (Boolean.FALSE.equals(viewMode)) {
|
||||
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
|
||||
Criteria deletedCriteria = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
|
||||
criteria.add(deletedCriteria);
|
||||
}
|
||||
|
||||
return queryOne(criteria, aclPermission);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -4,16 +4,17 @@ import com.appsmith.server.domains.Layout;
|
|||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ActionMoveDTO;
|
||||
import com.appsmith.server.dtos.RefactorNameDTO;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface LayoutActionService {
|
||||
Mono<Layout> updateLayout(String pageId, String layoutId, Layout layout);
|
||||
Mono<LayoutDTO> updateLayout(String pageId, String layoutId, Layout layout);
|
||||
|
||||
Mono<ActionDTO> moveAction(ActionMoveDTO actionMoveDTO);
|
||||
|
||||
Mono<Layout> refactorWidgetName(RefactorNameDTO refactorNameDTO);
|
||||
Mono<LayoutDTO> refactorWidgetName(RefactorNameDTO refactorNameDTO);
|
||||
|
||||
Mono<Layout> refactorActionName(RefactorNameDTO refactorNameDTO);
|
||||
Mono<LayoutDTO> refactorActionName(RefactorNameDTO refactorNameDTO);
|
||||
|
||||
Mono<ActionDTO> updateAction(String id, ActionDTO action);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@ import com.appsmith.server.domains.Layout;
|
|||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ActionMoveDTO;
|
||||
import com.appsmith.server.dtos.DslActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutActionUpdateDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.dtos.RefactorNameDTO;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.MustacheHelper;
|
||||
|
|
@ -121,7 +123,7 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Mono<Layout> refactorWidgetName(RefactorNameDTO refactorNameDTO) {
|
||||
public Mono<LayoutDTO> refactorWidgetName(RefactorNameDTO refactorNameDTO) {
|
||||
String pageId = refactorNameDTO.getPageId();
|
||||
String layoutId = refactorNameDTO.getLayoutId();
|
||||
String oldName = refactorNameDTO.getOldName();
|
||||
|
|
@ -136,7 +138,7 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Mono<Layout> refactorActionName(RefactorNameDTO refactorNameDTO) {
|
||||
public Mono<LayoutDTO> refactorActionName(RefactorNameDTO refactorNameDTO) {
|
||||
String pageId = refactorNameDTO.getPageId();
|
||||
String layoutId = refactorNameDTO.getLayoutId();
|
||||
String oldName = refactorNameDTO.getOldName();
|
||||
|
|
@ -167,7 +169,7 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
* @param newName
|
||||
* @return
|
||||
*/
|
||||
private Mono<Layout> refactorName(String pageId, String layoutId, String oldName, String newName) {
|
||||
private Mono<LayoutDTO> refactorName(String pageId, String layoutId, String oldName, String newName) {
|
||||
String regexPattern = preWord + oldName + postWord;
|
||||
Pattern oldNamePattern = Pattern.compile(regexPattern);
|
||||
|
||||
|
|
@ -466,11 +468,11 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Mono<Layout> updateLayout(String pageId, String layoutId, Layout layout) {
|
||||
public Mono<LayoutDTO> updateLayout(String pageId, String layoutId, Layout layout) {
|
||||
JSONObject dsl = layout.getDsl();
|
||||
if (dsl == null) {
|
||||
// There is no DSL here. No need to process anything. Return as is.
|
||||
return Mono.just(layout);
|
||||
return Mono.just(generateResponseDTO(layout));
|
||||
}
|
||||
|
||||
Set<String> widgetNames = new HashSet<>();
|
||||
|
|
@ -496,6 +498,8 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
Set<ActionDependencyEdge> edges = new HashSet<>();
|
||||
Set<String> actionsUsedInDSL = new HashSet<>();
|
||||
List<ActionDTO> flatmapPageLoadActions = new ArrayList<>();
|
||||
List<LayoutActionUpdateDTO> actionUpdates = new ArrayList<>();
|
||||
List<String> messages = new ArrayList<>();
|
||||
|
||||
Mono<List<HashSet<DslActionDTO>>> allOnLoadActionsMono = pageLoadActionsUtil
|
||||
.findAllOnLoadActions(dynamicBindingNames, actionNames, pageId, edges, actionsUsedInDSL, flatmapPageLoadActions);
|
||||
|
|
@ -504,7 +508,9 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
return allOnLoadActionsMono
|
||||
.flatMap(allOnLoadActions -> {
|
||||
// Update these actions to be executed on load, unless the user has touched the executeOnLoad setting for this
|
||||
return newActionService.setOnLoad((flatmapPageLoadActions)).thenReturn(allOnLoadActions);
|
||||
return newActionService
|
||||
.updateActionsExecuteOnLoad(flatmapPageLoadActions, pageId, actionUpdates, messages)
|
||||
.thenReturn(allOnLoadActions);
|
||||
})
|
||||
.zipWith(newPageService.findByIdAndLayoutsId(pageId, layoutId, MANAGE_PAGES, false)
|
||||
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND,
|
||||
|
|
@ -542,7 +548,26 @@ public class LayoutActionServiceImpl implements LayoutActionService {
|
|||
}
|
||||
}
|
||||
return Mono.empty();
|
||||
})
|
||||
.map(savedLayout -> {
|
||||
LayoutDTO layoutDTO = generateResponseDTO(savedLayout);
|
||||
layoutDTO.setActionUpdates(actionUpdates);
|
||||
layoutDTO.setMessages(messages);
|
||||
return layoutDTO;
|
||||
});
|
||||
}
|
||||
|
||||
private LayoutDTO generateResponseDTO(Layout layout) {
|
||||
|
||||
LayoutDTO layoutDTO = new LayoutDTO();
|
||||
|
||||
layoutDTO.setId(layout.getId());
|
||||
layoutDTO.setDsl(layout.getDsl());
|
||||
layoutDTO.setScreen(layout.getScreen());
|
||||
layoutDTO.setLayoutOnLoadActions(layout.getLayoutOnLoadActions());
|
||||
layoutDTO.setUserPermissions(layout.getUserPermissions());
|
||||
|
||||
return layoutDTO;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.appsmith.server.domains.NewAction;
|
|||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ActionViewDTO;
|
||||
import com.appsmith.server.dtos.ExecuteActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutActionUpdateDTO;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
|
@ -57,5 +58,5 @@ public interface NewActionService extends CrudService<NewAction, String> {
|
|||
|
||||
Flux<NewAction> findByPageId(String pageId);
|
||||
|
||||
Mono<Boolean> setOnLoad(List<ActionDTO> actions);
|
||||
Mono<Boolean> updateActionsExecuteOnLoad(List<ActionDTO> actions, String pageId, List<LayoutActionUpdateDTO> actionUpdates, List<String> messages);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import com.appsmith.server.domains.User;
|
|||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.ActionViewDTO;
|
||||
import com.appsmith.server.dtos.ExecuteActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutActionUpdateDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.MustacheHelper;
|
||||
|
|
@ -42,6 +43,7 @@ import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
|||
import org.springframework.data.mongodb.core.convert.MongoConverter;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
|
@ -57,6 +59,7 @@ import java.time.Instant;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
|
@ -916,25 +919,147 @@ public class NewActionServiceImpl extends BaseService<NewActionRepository, NewAc
|
|||
return repository.findByPageId(pageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* !!!WARNING!!! This function edits the parameters actionUpdates and messages which are eventually returned back to
|
||||
* the caller with the updates values.
|
||||
* @param onLoadActions : All the actions which have been found to be on page load
|
||||
* @param pageId
|
||||
* @param actionUpdates : Empty array list which would be set in this function with all the page actions whose
|
||||
* execute on load setting has changed (whether flipped from true to false, or vice versa)
|
||||
* @param messages : Empty array list which would be set in this function with all the messages that should be
|
||||
* displayed to the developer user communicating the action executeOnLoad changes.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Mono<Boolean> setOnLoad(List<ActionDTO> actions) {
|
||||
if (actions == null) {
|
||||
return Mono.just(FALSE);
|
||||
}
|
||||
public Mono<Boolean> updateActionsExecuteOnLoad(List<ActionDTO> onLoadActions,
|
||||
String pageId,
|
||||
List<LayoutActionUpdateDTO> actionUpdates,
|
||||
List<String> messages) {
|
||||
|
||||
List<ActionDTO> toUpdateActions = new ArrayList<>();
|
||||
for (ActionDTO action : actions) {
|
||||
// If a user has ever set execute on load, this field can not be changed automatically. It has to be
|
||||
// explicitly changed by the user again. Add the action to update only if this condition is false.
|
||||
if (FALSE.equals(action.getUserSetOnLoad())) {
|
||||
action.setExecuteOnLoad(TRUE);
|
||||
toUpdateActions.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
return Flux.fromIterable(toUpdateActions)
|
||||
.flatMap(actionDTO -> updateUnpublishedAction(actionDTO.getId(), actionDTO))
|
||||
.then(Mono.just(TRUE));
|
||||
MultiValueMap<String, String> params = CollectionUtils.toMultiValueMap(new LinkedCaseInsensitiveMap<>(8, Locale.ENGLISH));
|
||||
params.add(FieldName.PAGE_ID, pageId);
|
||||
|
||||
// Fetch all the actions which exist in this page.
|
||||
Flux<ActionDTO> pageActionsFlux = this.getUnpublishedActions(params).cache();
|
||||
|
||||
// Before we update the actions, fetch all the actions which are currently set to execute on load.
|
||||
Mono<List<ActionDTO>> existingOnPageLoadActionsMono = pageActionsFlux
|
||||
.flatMap(action -> {
|
||||
if (TRUE.equals(action.getExecuteOnLoad())) {
|
||||
return Mono.just(action);
|
||||
}
|
||||
return Mono.empty();
|
||||
})
|
||||
.collectList();
|
||||
|
||||
return existingOnPageLoadActionsMono
|
||||
.zipWith(pageActionsFlux.collectList())
|
||||
.flatMap( tuple -> {
|
||||
List<ActionDTO> existingOnPageLoadActions = tuple.getT1();
|
||||
List<ActionDTO> pageActions = tuple.getT2();
|
||||
|
||||
// There are no actions in this page. No need to proceed further since no actions would get updated
|
||||
if (pageActions.isEmpty()) {
|
||||
return Mono.just(FALSE);
|
||||
}
|
||||
|
||||
// No actions require an update if no actions have been found as page load actions as well as
|
||||
// existing on load page actions are empty
|
||||
if (existingOnPageLoadActions.isEmpty() && (onLoadActions == null || onLoadActions.isEmpty())) {
|
||||
return Mono.just(FALSE);
|
||||
}
|
||||
|
||||
// Extract names of existing pageload actions and new page load actions for quick lookup.
|
||||
Set<String> existingOnPageLoadActionNames = existingOnPageLoadActions
|
||||
.stream()
|
||||
.map(action -> action.getName())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<String> newOnLoadActionNames = onLoadActions
|
||||
.stream()
|
||||
.map(action -> action.getName())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
|
||||
// Calculate the actions which would need to be updated from execute on load TRUE to FALSE.
|
||||
Set<String> turnedOffActionNames = new HashSet<>();
|
||||
turnedOffActionNames.addAll(existingOnPageLoadActionNames);
|
||||
turnedOffActionNames.removeAll(newOnLoadActionNames);
|
||||
|
||||
// Calculate the actions which would need to be updated from execute on load FALSE to TRUE
|
||||
Set<String> turnedOnActionNames = new HashSet<>();
|
||||
turnedOnActionNames.addAll(newOnLoadActionNames);
|
||||
turnedOnActionNames.removeAll(existingOnPageLoadActionNames);
|
||||
|
||||
for (ActionDTO action : pageActions) {
|
||||
|
||||
String actionName = action.getName();
|
||||
// If a user has ever set execute on load, this field can not be changed automatically. It has to be
|
||||
// explicitly changed by the user again. Add the action to update only if this condition is false.
|
||||
if (FALSE.equals(action.getUserSetOnLoad())) {
|
||||
|
||||
// If this action is no longer an onload action, turn the execute on load to false
|
||||
if (turnedOffActionNames.contains(actionName)) {
|
||||
action.setExecuteOnLoad(FALSE);
|
||||
toUpdateActions.add(action);
|
||||
}
|
||||
|
||||
// If this action is newly found to be on load, turn execute on load to true
|
||||
if (turnedOnActionNames.contains(actionName)) {
|
||||
action.setExecuteOnLoad(TRUE);
|
||||
toUpdateActions.add(action);
|
||||
}
|
||||
} else {
|
||||
// Remove the action name from either of the lists (if present) because this action should
|
||||
// not be updated
|
||||
turnedOnActionNames.remove(actionName);
|
||||
turnedOffActionNames.remove(actionName);
|
||||
}
|
||||
}
|
||||
|
||||
// Add newly turned on page actions to report back to the caller
|
||||
actionUpdates.addAll(
|
||||
addActionUpdatesForActionNames(pageActions, turnedOnActionNames)
|
||||
);
|
||||
|
||||
// Add newly turned off page actions to report back to the caller
|
||||
actionUpdates.addAll(
|
||||
addActionUpdatesForActionNames(pageActions, turnedOffActionNames)
|
||||
);
|
||||
|
||||
// Now add messages that would eventually be displayed to the developer user informing them
|
||||
// about the action setting change.
|
||||
if (!turnedOffActionNames.isEmpty()) {
|
||||
messages.add(turnedOffActionNames.toString() + " will no longer be executed on page load");
|
||||
}
|
||||
|
||||
if (!turnedOnActionNames.isEmpty()) {
|
||||
messages.add(turnedOnActionNames.toString() + " will be executed automatically on page load");
|
||||
}
|
||||
|
||||
// Finally update the actions which require an update
|
||||
return Flux.fromIterable(toUpdateActions)
|
||||
.flatMap(actionDTO -> updateUnpublishedAction(actionDTO.getId(), actionDTO))
|
||||
.then(Mono.just(TRUE));
|
||||
});
|
||||
}
|
||||
|
||||
private List<LayoutActionUpdateDTO> addActionUpdatesForActionNames(List<ActionDTO> pageActions,
|
||||
Set<String> actionNames) {
|
||||
|
||||
return pageActions
|
||||
.stream()
|
||||
.filter(pageAction -> actionNames.contains(pageAction.getName()))
|
||||
.map(pageAction -> {
|
||||
LayoutActionUpdateDTO layoutActionUpdateDTO = new LayoutActionUpdateDTO();
|
||||
layoutActionUpdateDTO.setId(pageAction.getId());
|
||||
layoutActionUpdateDTO.setName(pageAction.getName());
|
||||
layoutActionUpdateDTO.setExecuteOnLoad(pageAction.getExecuteOnLoad());
|
||||
return layoutActionUpdateDTO;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -5,15 +5,11 @@ import com.appsmith.external.models.Connection;
|
|||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
import com.appsmith.external.models.Endpoint;
|
||||
import com.appsmith.external.models.Property;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.assertj.core.api.IterableAssert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
|
@ -29,13 +25,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
// Disabling this so we may use `Arrays.asList` with single argument, which is easier to refactor, just for tests.
|
||||
"ArraysAsListWithZeroOrOneArgument"
|
||||
)
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class MustacheHelperTest {
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private void checkTokens(String template, List<String> expected) {
|
||||
assertThat(tokenize(template)).isEqualTo(expected);
|
||||
}
|
||||
|
|
@ -406,7 +397,14 @@ public class MustacheHelperTest {
|
|||
new Property("param2", "{{ queryParam2 }}")
|
||||
));
|
||||
|
||||
final Map<String, String> context = Map.of(
|
||||
configuration.setPluginSpecifiedTemplates(Arrays.asList(
|
||||
null,
|
||||
new Property("prop1", "{{ pluginSpecifiedProp1 }}"),
|
||||
null,
|
||||
new Property("prop2", "{{ pluginSpecifiedProp2 }}")
|
||||
));
|
||||
|
||||
final Map<String, String> context = new HashMap<>(Map.of(
|
||||
"body", "rendered body",
|
||||
"path", "rendered path",
|
||||
"next", "rendered next",
|
||||
|
|
@ -416,7 +414,12 @@ public class MustacheHelperTest {
|
|||
"bodyParam2", "rendered bodyParam2",
|
||||
"queryParam1", "rendered queryParam1",
|
||||
"queryParam2", "rendered queryParam2"
|
||||
);
|
||||
));
|
||||
|
||||
context.putAll(Map.of(
|
||||
"pluginSpecifiedProp1", "rendered pluginSpecifiedProp1",
|
||||
"pluginSpecifiedProp2", "rendered pluginSpecifiedProp2"
|
||||
));
|
||||
|
||||
assertKeys(configuration).hasSameElementsAs(context.keySet());
|
||||
|
||||
|
|
@ -440,6 +443,13 @@ public class MustacheHelperTest {
|
|||
new Property("param1", "rendered queryParam1"),
|
||||
new Property("param2", "rendered queryParam2")
|
||||
);
|
||||
|
||||
assertThat(configuration.getPluginSpecifiedTemplates()).containsExactly(
|
||||
null,
|
||||
new Property("prop1", "rendered pluginSpecifiedProp1"),
|
||||
null,
|
||||
new Property("prop2", "rendered pluginSpecifiedProp2")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import com.appsmith.server.domains.Plugin;
|
|||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.DslActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutActionUpdateDTO;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.dtos.RefactorNameDTO;
|
||||
import com.appsmith.server.helpers.MockPluginExecutor;
|
||||
|
|
@ -37,6 +39,7 @@ import reactor.test.StepVerifier;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -216,7 +219,7 @@ public class LayoutActionServiceTest {
|
|||
|
||||
ActionDTO createdAction = newActionService.createAction(action).block();
|
||||
|
||||
Layout firstLayout = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).block();
|
||||
LayoutDTO firstLayout = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).block();
|
||||
|
||||
|
||||
RefactorNameDTO refactorNameDTO = new RefactorNameDTO();
|
||||
|
|
@ -225,7 +228,7 @@ public class LayoutActionServiceTest {
|
|||
refactorNameDTO.setOldName("beforeNameChange");
|
||||
refactorNameDTO.setNewName("PostNameChange");
|
||||
|
||||
Layout postNameChangeLayout = layoutActionService.refactorActionName(refactorNameDTO).block();
|
||||
LayoutDTO postNameChangeLayout = layoutActionService.refactorActionName(refactorNameDTO).block();
|
||||
|
||||
Mono<NewAction> postNameChangeActionMono = newActionService.findById(createdAction.getId(), READ_ACTIONS);
|
||||
|
||||
|
|
@ -238,11 +241,152 @@ public class LayoutActionServiceTest {
|
|||
DslActionDTO actionDTO = postNameChangeLayout.getLayoutOnLoadActions().get(0).iterator().next();
|
||||
assertThat(actionDTO.getName()).isEqualTo("PostNameChange");
|
||||
|
||||
// JSONObject newDsl = new JSONObject(Map.of("widgetName", "firstWidget", "mustacheProp", "{{ PostNameChange.data }}"));
|
||||
dsl.put("testField", "{{ PostNameChange.data }}");
|
||||
assertThat(postNameChangeLayout.getDsl()).isEqualTo(dsl);
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void refactorActionNameToDeletedName() {
|
||||
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())).thenReturn(Mono.just(new MockPluginExecutor()));
|
||||
|
||||
ActionDTO action = new ActionDTO();
|
||||
action.setName("Query1");
|
||||
action.setPageId(testPage.getId());
|
||||
ActionConfiguration actionConfiguration = new ActionConfiguration();
|
||||
actionConfiguration.setHttpMethod(HttpMethod.GET);
|
||||
action.setActionConfiguration(actionConfiguration);
|
||||
action.setDatasource(datasource);
|
||||
|
||||
Layout layout = testPage.getLayouts().get(0);
|
||||
|
||||
ActionDTO firstAction = newActionService.createAction(action).block();
|
||||
|
||||
LayoutDTO firstLayout = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).block();
|
||||
|
||||
applicationPageService.publish(testPage.getApplicationId()).block();
|
||||
|
||||
newActionService.deleteUnpublishedAction(firstAction.getId()).block();
|
||||
|
||||
// Create another action with the same name as the erstwhile deleted action
|
||||
action.setId(null);
|
||||
ActionDTO secondAction = newActionService.createAction(action).block();
|
||||
|
||||
RefactorNameDTO refactorNameDTO = new RefactorNameDTO();
|
||||
refactorNameDTO.setPageId(testPage.getId());
|
||||
refactorNameDTO.setLayoutId(firstLayout.getId());
|
||||
refactorNameDTO.setOldName("Query1");
|
||||
refactorNameDTO.setNewName("NewActionName");
|
||||
|
||||
layoutActionService.refactorActionName(refactorNameDTO).block();
|
||||
|
||||
Mono<NewAction> postNameChangeActionMono = newActionService.findById(secondAction.getId(), READ_ACTIONS);
|
||||
|
||||
StepVerifier
|
||||
.create(postNameChangeActionMono)
|
||||
.assertNext(updatedAction -> {
|
||||
|
||||
assertThat(updatedAction.getUnpublishedAction().getName()).isEqualTo("NewActionName");
|
||||
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void actionExecuteOnLoadChangeOnUpdateLayout() {
|
||||
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())).thenReturn(Mono.just(new MockPluginExecutor()));
|
||||
|
||||
ActionDTO action1 = new ActionDTO();
|
||||
action1.setName("firstAction");
|
||||
action1.setPageId(testPage.getId());
|
||||
ActionConfiguration actionConfiguration1 = new ActionConfiguration();
|
||||
actionConfiguration1.setHttpMethod(HttpMethod.GET);
|
||||
action1.setActionConfiguration(actionConfiguration1);
|
||||
action1.setDatasource(datasource);
|
||||
|
||||
ActionDTO action2 = new ActionDTO();
|
||||
action2.setName("secondAction");
|
||||
action2.setPageId(testPage.getId());
|
||||
ActionConfiguration actionConfiguration2 = new ActionConfiguration();
|
||||
actionConfiguration2.setHttpMethod(HttpMethod.GET);
|
||||
action2.setActionConfiguration(actionConfiguration2);
|
||||
action2.setDatasource(datasource);
|
||||
|
||||
JSONObject dsl = new JSONObject();
|
||||
dsl.put("widgetName", "firstWidget");
|
||||
JSONArray temp = new JSONArray();
|
||||
temp.addAll(List.of(new JSONObject(Map.of("key", "testField"))));
|
||||
dsl.put("dynamicBindingPathList", temp);
|
||||
dsl.put("testField", "{{ firstAction.data }}");
|
||||
|
||||
Layout layout = testPage.getLayouts().get(0);
|
||||
layout.setDsl(dsl);
|
||||
|
||||
ActionDTO createdAction1 = newActionService.createAction(action1).block();
|
||||
ActionDTO createdAction2 = newActionService.createAction(action2).block();
|
||||
|
||||
Mono<LayoutDTO> updateLayoutMono = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout);
|
||||
|
||||
StepVerifier.create(updateLayoutMono)
|
||||
.assertNext(updatedLayout -> {
|
||||
log.debug("{}", updatedLayout.getMessages());
|
||||
DslActionDTO actionDTO = updatedLayout.getLayoutOnLoadActions().get(0).iterator().next();
|
||||
assertThat(actionDTO.getName()).isEqualTo("firstAction");
|
||||
|
||||
List<LayoutActionUpdateDTO> actionUpdates = updatedLayout.getActionUpdates();
|
||||
assertThat(actionUpdates.size()).isEqualTo(1);
|
||||
assertThat(actionUpdates.get(0).getName()).isEqualTo("firstAction");
|
||||
assertThat(actionUpdates.get(0).getExecuteOnLoad()).isTrue();
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(newActionService.findById(createdAction1.getId()))
|
||||
.assertNext(newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad()).isTrue());
|
||||
|
||||
StepVerifier.create(newActionService.findById(createdAction2.getId()))
|
||||
.assertNext(newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad()).isFalse());
|
||||
|
||||
dsl = new JSONObject();
|
||||
dsl.put("widgetName", "firstWidget");
|
||||
temp = new JSONArray();
|
||||
temp.addAll(List.of(new JSONObject(Map.of("key", "testField"))));
|
||||
dsl.put("dynamicBindingPathList", temp);
|
||||
dsl.put("testField", "{{ secondAction.data }}");
|
||||
|
||||
layout.setDsl(dsl);
|
||||
|
||||
updateLayoutMono = layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout);
|
||||
|
||||
StepVerifier.create(updateLayoutMono)
|
||||
.assertNext(updatedLayout -> {
|
||||
log.debug("{}", updatedLayout.getMessages());
|
||||
DslActionDTO actionDTO = updatedLayout.getLayoutOnLoadActions().get(0).iterator().next();
|
||||
assertThat(actionDTO.getName()).isEqualTo("secondAction");
|
||||
|
||||
List<LayoutActionUpdateDTO> actionUpdates = updatedLayout.getActionUpdates();
|
||||
assertThat(actionUpdates.size()).isEqualTo(2);
|
||||
|
||||
Optional<LayoutActionUpdateDTO> firstActionUpdateOptional = actionUpdates.stream().filter(actionUpdate -> actionUpdate.getName().equals("firstAction")).findFirst();
|
||||
LayoutActionUpdateDTO firstActionUpdate = firstActionUpdateOptional.get();
|
||||
assertThat(firstActionUpdate).isNotNull();
|
||||
assertThat(firstActionUpdate.getExecuteOnLoad()).isFalse();
|
||||
|
||||
Optional<LayoutActionUpdateDTO> secondActionUpdateOptional = actionUpdates.stream().filter(actionUpdate -> actionUpdate.getName().equals("secondAction")).findFirst();
|
||||
LayoutActionUpdateDTO secondActionUpdate = secondActionUpdateOptional.get();
|
||||
assertThat(secondActionUpdate).isNotNull();
|
||||
assertThat(secondActionUpdate.getExecuteOnLoad()).isTrue();
|
||||
})
|
||||
.verifyComplete();
|
||||
|
||||
StepVerifier.create(newActionService.findById(createdAction1.getId()))
|
||||
.assertNext(newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad()).isFalse());
|
||||
|
||||
StepVerifier.create(newActionService.findById(createdAction2.getId()))
|
||||
.assertNext(newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad()).isTrue());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ import com.appsmith.server.constants.FieldName;
|
|||
import com.appsmith.server.domains.Application;
|
||||
import com.appsmith.server.domains.Datasource;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.domains.NewAction;
|
||||
import com.appsmith.server.domains.NewPage;
|
||||
import com.appsmith.server.domains.Plugin;
|
||||
import com.appsmith.server.domains.PluginType;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.dtos.ActionDTO;
|
||||
import com.appsmith.server.dtos.DslActionDTO;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
|
|
@ -205,7 +204,7 @@ public class LayoutServiceTest {
|
|||
|
||||
Layout startLayout = layoutService.createLayout(page.getId(), testLayout).block();
|
||||
|
||||
Mono<Layout> updatedLayoutMono = layoutActionService.updateLayout("random-impossible-id-page", startLayout.getId(), updateLayout);
|
||||
Mono<LayoutDTO> updatedLayoutMono = layoutActionService.updateLayout("random-impossible-id-page", startLayout.getId(), updateLayout);
|
||||
|
||||
StepVerifier
|
||||
.create(updatedLayoutMono)
|
||||
|
|
@ -238,7 +237,7 @@ public class LayoutServiceTest {
|
|||
|
||||
Mono<Layout> startLayoutMono = pageMono.flatMap(page -> layoutService.createLayout(page.getId(), testLayout));
|
||||
|
||||
Mono<Layout> updatedLayoutMono = Mono.zip(pageMono, startLayoutMono)
|
||||
Mono<LayoutDTO> updatedLayoutMono = Mono.zip(pageMono, startLayoutMono)
|
||||
.flatMap(tuple -> {
|
||||
PageDTO page = tuple.getT1();
|
||||
Layout startLayout = tuple.getT2();
|
||||
|
|
@ -276,7 +275,7 @@ public class LayoutServiceTest {
|
|||
|
||||
Mono<PageDTO> pageMono = createPage(app, testPage).cache();
|
||||
|
||||
Mono<Layout> testMono = pageMono
|
||||
Mono<LayoutDTO> testMono = pageMono
|
||||
.flatMap(page1 -> {
|
||||
List<Mono<ActionDTO>> monos = new ArrayList<>();
|
||||
|
||||
|
|
@ -464,7 +463,7 @@ public class LayoutServiceTest {
|
|||
|
||||
Mono<PageDTO> pageMono = createPage(app, testPage).cache();
|
||||
|
||||
Mono<Layout> testMono = pageMono
|
||||
Mono<LayoutDTO> testMono = pageMono
|
||||
.flatMap(page1 -> {
|
||||
List<Mono<ActionDTO>> monos = new ArrayList<>();
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,46 @@ public class PageServiceTest {
|
|||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void reuseDeletedPageName() {
|
||||
|
||||
PageDTO testPage = new PageDTO();
|
||||
testPage.setName("reuseDeletedPageName");
|
||||
setupTestApplication();
|
||||
testPage.setApplicationId(application.getId());
|
||||
|
||||
// Create Page
|
||||
PageDTO firstPage = applicationPageService.createPage(testPage).block();
|
||||
|
||||
// Publish the application
|
||||
applicationPageService.publish(application.getId());
|
||||
|
||||
//Delete Page in edit mode
|
||||
applicationPageService.deleteUnpublishedPage(firstPage.getId()).block();
|
||||
|
||||
testPage.setId(null);
|
||||
testPage.setName("New Page Name");
|
||||
// Create Second Page
|
||||
PageDTO secondPage = applicationPageService.createPage(testPage).block();
|
||||
|
||||
//Update the name of the new page
|
||||
PageDTO newPage = new PageDTO();
|
||||
newPage.setId(secondPage.getId());
|
||||
newPage.setName("reuseDeletedPageName");
|
||||
Mono<PageDTO> updatePageNameMono = newPageService.updatePage(secondPage.getId(), newPage);
|
||||
|
||||
StepVerifier
|
||||
.create(updatePageNameMono)
|
||||
.assertNext(page -> {
|
||||
assertThat(page).isNotNull();
|
||||
assertThat(page.getId()).isNotNull();
|
||||
assertThat("reuseDeletedPageName".equals(page.getName()));
|
||||
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void purgeAllPages() {
|
||||
|
|
|
|||
|
|
@ -100,5 +100,5 @@ example:
|
|||

|
||||
|
||||
## Need Assistance
|
||||
- If you are unable to resolve any issue while doing the setup, please initiate a Github discussion or send an email to support@appsmith.com. We'll be happy to help you.
|
||||
- If you are unable to resolve any issue while doing the setup, please feel free to ask questions on our [Discord channel](https://discord.com/invite/rBTTVJp) or initiate a [Github discussion](https://github.com/appsmithorg/appsmith/discussions) or send an email to `support@appsmith.com`. We'll be happy to help you.
|
||||
- In case you notice any discrepancy, please raise an issue on Github and/or send an email to support@appsmith.com.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user