Merge branch 'release'

This commit is contained in:
Arpit Mohan 2020-11-03 14:28:18 +05:30
commit bd11fdef91
14 changed files with 125 additions and 17 deletions

View File

@ -205,7 +205,16 @@
"avatar_url": "https://avatars0.githubusercontent.com/u/25309929?v=4",
"profile": "https://github.com/A-Scratchy",
"contributions": [
"code"
"code"
]
},
{
"login": "sumanthyedoti",
"name": "Sumanth Yedoti",
"avatar_url": "https://avatars3.githubusercontent.com/u/30371888?v=4",
"profile": "https://github.com/sumanthyedoti",
"contributions": [
"code"
]
}
],

View File

@ -121,6 +121,9 @@ The Appsmith platform is available under the [Apache License 2.0](https://www.ap
<td align="center"><a href="http://prashantchaubey.com"><img src="https://avatars3.githubusercontent.com/u/14848874?v=4" width="100px;" alt=""/><br /><sub><b>Prashant Chaubey</b></sub></a><br /><a href="https://github.com/appsmithorg/appsmith/commits?author=pc9795" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/A-Scratchy"><img src="https://avatars0.githubusercontent.com/u/25309929?v=4" width="100px;" alt=""/><br /><sub><b>Adam</b></sub></a><br /><a href="https://github.com/appsmithorg/appsmith/commits?author=A-Scratchy" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/sumanthyedoti"><img src="https://avatars3.githubusercontent.com/u/30371888?v=4" width="100px;" alt=""/><br /><sub><b>Sumanth Yedoti</b></sub></a><br /><a href="#tool-sumanthyedoti" title="Tools">🔧</a> <a href="https://github.com/appsmithorg/appsmith/commits?author=sumanthyedoti" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-enable -->

View File

@ -0,0 +1,18 @@
const dsl = require("../../../fixtures/inputdsl.json");
const widgetsPage = require("../../../locators/Widgets.json");
const dynamicInput = require("../../../locators/DynamicInput.json");
describe("Binding prompt", function() {
before(() => {
cy.addDsl(dsl);
});
it("Show binding prompt when there are no bindings in the editor", () => {
cy.openPropertyPane("inputwidget");
cy.get(widgetsPage.defaultInput).type(" ");
cy.get(dynamicInput.bindingPrompt).should("be.visible");
cy.get(widgetsPage.defaultInput).type("{{");
cy.get(dynamicInput.bindingPrompt).should("not.be.visible");
});
});

View File

@ -48,6 +48,9 @@ describe("Video Widget Functionality", function() {
it("Update video url and check play and pause functionality validation", function() {
cy.testCodeMirror(testdata.videoUrl);
cy.get(".CodeMirror textarea")
.first()
.blur();
cy.get(widgetsPage.autoPlay).click();
cy.wait("@updateLayout").should(
"have.nested.property",

View File

@ -1,5 +1,6 @@
{
"input": ".CodeMirror textarea",
"hints": "ul.CodeMirror-hints",
"evaluatedValue": ".t--CodeEditor-evaluatedValue"
"evaluatedValue": ".t--CodeEditor-evaluatedValue",
"bindingPrompt": ".t--no-binding-prompt"
}

View File

@ -0,0 +1,48 @@
import React, { useRef } from "react";
import styled from "styled-components";
import { Colors } from "constants/Colors";
const Wrapper = styled.span<{ visible: boolean; bottomOffset: number }>`
padding: 8px;
font-size: 12px;
color: ${Colors.GRAY_CHATEAU};
border-radius: 2px;
background-color: ${Colors.BLUE_CHARCOAL};
position: absolute;
bottom: ${props => -props.bottomOffset}px;
width: 100%;
line-height: 13px;
visibility: ${props => (props.visible ? "visible" : "hidden")};
z-index: 1;
`;
const CurlyBraces = styled.span`
color: white;
background-color: #f3672a;
border-radius: 2px;
padding: 2px;
margin: 0px 2px;
`;
const BindingPrompt = (props: { isOpen: boolean }): JSX.Element => {
const promptRef = useRef<HTMLDivElement>(null);
let bottomOffset = 30;
if (promptRef.current) {
const boundingRect = promptRef.current.getBoundingClientRect();
bottomOffset = boundingRect.height;
}
return (
<Wrapper
className="t--no-binding-prompt"
ref={promptRef}
visible={props.isOpen}
bottomOffset={bottomOffset}
>
Type <CurlyBraces>{"{{"}</CurlyBraces> to see a list of variables
</Wrapper>
);
};
export default BindingPrompt;

View File

@ -36,6 +36,7 @@ import {
import { bindingMarker } from "components/editorComponents/CodeEditor/markHelpers";
import { bindingHint } from "components/editorComponents/CodeEditor/hintHelpers";
import { retryPromise } from "utils/AppsmithUtils";
import BindingPrompt from "./BindingPrompt";
const LightningMenu = lazy(() =>
retryPromise(() => import("components/editorComponents/LightningMenu")),
@ -91,9 +92,7 @@ class CodeEditor extends Component<Props, State> {
};
textArea = React.createRef<HTMLTextAreaElement>();
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
editor: CodeMirror.Editor;
editor!: CodeMirror.Editor;
hinters: Hinter[] = [];
constructor(props: Props) {
@ -272,6 +271,7 @@ class CodeEditor extends Component<Props, State> {
theme,
disabled,
className,
placeholder,
showLightningMenu,
dataTreePath,
dynamicData,
@ -291,6 +291,10 @@ class CodeEditor extends Component<Props, State> {
("evaluatedValue" in this.props ||
("dataTreePath" in this.props && !!this.props.dataTreePath));
const showBindingPrompt =
(!this.props.input.value?.includes("{{") || !this.props.input.value) &&
showEvaluatedValue;
return (
<DynamicAutocompleteInputWrapper
theme={this.props.theme}
@ -346,12 +350,11 @@ class CodeEditor extends Component<Props, State> {
className="leftImageStyles"
/>
)}
<textarea
ref={this.textArea}
{..._.omit(this.props.input, ["onChange", "value"])}
defaultValue={input.value}
placeholder={this.props.placeholder}
placeholder={placeholder}
/>
{this.props.link && (
<React.Fragment>
@ -368,6 +371,7 @@ class CodeEditor extends Component<Props, State> {
{this.props.rightIcon && (
<IconContainer>{this.props.rightIcon}</IconContainer>
)}
<BindingPrompt isOpen={showBindingPrompt} />
</EditorWrapper>
</EvaluatedValuePopup>
</DynamicAutocompleteInputWrapper>

View File

@ -124,7 +124,7 @@ export const EditorWrapper = styled.div<{
left: 0;
top: 0;
`
: `z-index: 0; position: relative;`}
: `position: relative;`}
min-height: 32px;
height: ${props => props.height || "auto"};
background-color: ${props =>

View File

@ -6,4 +6,5 @@ export default styled.div`
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
min-height: 50px;
`;

View File

@ -237,7 +237,7 @@ const mapStateToProps = (
};
};
const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({
updateDatasource: datasource =>
dispatch(change(API_EDITOR_FORM_NAME, "datasource", datasource)),
});

View File

@ -24,7 +24,6 @@ class DropdownWidget extends BaseWidget<DropdownWidgetProps, WidgetState> {
selectionType: VALIDATION_TYPES.TEXT,
isRequired: VALIDATION_TYPES.BOOLEAN,
// onOptionChange: VALIDATION_TYPES.ACTION_SELECTOR,
selectedOptionValueArr: VALIDATION_TYPES.ARRAY,
selectedOptionValues: VALIDATION_TYPES.ARRAY,
defaultOptionValue: VALIDATION_TYPES.DEFAULT_OPTION_VALUE,
};

View File

@ -51,8 +51,8 @@ const withMeta = (WrappedWidget: typeof BaseWidget) => {
Object.keys(metaProperties).forEach(metaProperty => {
const defaultProperty = defaultProperties[metaProperty];
if (
prevProps[metaProperty] !== this.props[metaProperty] &&
this.props[defaultProperty] === this.props[metaProperty]
!_.isEqual(prevProps[metaProperty], this.props[metaProperty]) &&
_.isEqual(this.props[defaultProperty], this.props[metaProperty])
) {
this.setState({ [metaProperty]: this.props[metaProperty] });
}

View File

@ -88,6 +88,9 @@ public class DatabaseChangelog {
* from an index with the fields `"organizationId", "name"`. If an index exists with the first ordering and we try
* to **ensure** an index with the same name but the second ordering of fields, errors will show up and bad things
* WILL happen.
*
* Also, please check out the following blog on how to best create indexes :
* https://emptysqua.re/blog/optimizing-mongodb-compound-indexes/
*/
private static Index makeIndex(String... fields) {
if (fields.length == 1) {
@ -1193,4 +1196,23 @@ public class DatabaseChangelog {
}
@ChangeSet(order = "040", id = "new-page-new-action-add-indexes", author = "")
public void addNewPageAndNewActionNewIndexes(MongoTemplate mongoTemplate) {
dropIndexIfExists(mongoTemplate, NewAction.class, "createdAt");
ensureIndexes(mongoTemplate, NewAction.class,
makeIndex("applicationId", "deleted", "createdAt")
.named("applicationId_deleted_createdAt_compound_index")
);
dropIndexIfExists(mongoTemplate, NewPage.class, "createdAt");
ensureIndexes(mongoTemplate, NewPage.class,
makeIndex("applicationId", "deleted")
.named("applicationId_deleted_compound_index")
);
}
}

View File

@ -24,7 +24,6 @@ import com.appsmith.server.domains.NewPage;
import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.PluginType;
import com.appsmith.server.domains.QNewAction;
import com.appsmith.server.dtos.ActionDTO;
import com.appsmith.server.dtos.ActionViewDTO;
import com.appsmith.server.dtos.ExecuteActionDTO;
@ -66,7 +65,6 @@ import static com.appsmith.server.acl.AclPermission.MANAGE_DATASOURCES;
import static com.appsmith.server.acl.AclPermission.READ_ACTIONS;
import static com.appsmith.server.acl.AclPermission.READ_PAGES;
import static com.appsmith.server.helpers.BeanCopyUtils.copyNewFieldValuesIntoOldObject;
import static com.appsmith.server.repositories.BaseAppsmithRepositoryImpl.fieldName;
import static java.lang.Boolean.TRUE;
@Service
@ -727,14 +725,14 @@ public class NewActionServiceImpl extends BaseService<NewActionRepository, NewAc
@Override
public Flux<ActionViewDTO> getActionsForViewMode(String applicationId) {
Sort sort = Sort.by(fieldName(QNewAction.newAction.publishedAction) + "." + fieldName(QNewAction.newAction.publishedAction.name));
if (applicationId == null || applicationId.isEmpty()) {
return Flux.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.APPLICATION_ID));
}
// fetch the published actions by applicationId
return findAllByApplicationIdAndViewMode(applicationId, true, EXECUTE_ACTIONS, sort)
// No need to sort the results
return findAllByApplicationIdAndViewMode(applicationId, true, EXECUTE_ACTIONS, null)
.map(action -> {
ActionViewDTO actionViewDTO = new ActionViewDTO();
actionViewDTO.setId(action.getId());
@ -783,7 +781,9 @@ public class NewActionServiceImpl extends BaseService<NewActionRepository, NewAc
public Flux<ActionDTO> getUnpublishedActions(MultiValueMap<String, String> params) {
String name = null;
List<String> pageIds = new ArrayList<>();
Sort sort = Sort.by(FieldName.NAME);
// In the edit mode, the actions should be displayed in the order they were created.
Sort sort = Sort.by(FieldName.CREATED_AT);
if (params.getFirst(FieldName.NAME) != null) {
name = params.getFirst(FieldName.NAME);