Skip to content

Commit

Permalink
Mango query UX improvements (#1402)
Browse files Browse the repository at this point in the history
- Set editor max height so buttons and stats are not hidden when the
query code is longer than the page height.
- Add cheatsheet modal that shows query operators.
- Display exec stats and warning directly below the editor instead of
in a popover to give easier access to that information, particularly
when trying to optimize queries.
  • Loading branch information
Antonio-Maranhao committed Jul 17, 2023
1 parent 8dd89b0 commit 613a056
Show file tree
Hide file tree
Showing 22 changed files with 525 additions and 184 deletions.
23 changes: 22 additions & 1 deletion app/addons/components/__tests__/codeEditorPanel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import ReactComponents from "../react-components";
import React from "react";
import {mount} from 'enzyme';
import sinon from "sinon";

var codeNoNewlines = 'function (doc) {emit(doc._id, 1);}';
var code = 'function (doc) {\n emit(doc._id, 1);\n}';
Expand All @@ -26,7 +27,7 @@ describe('CodeEditorPanel', () => {
);
expect(codeEditorEl.find('.fonticon-help-circled').length).toBe(0);
});
it('hidden by default', () => {
it('is displayed when docLink is provided', () => {

const codeEditorEl = mount(
<ReactComponents.CodeEditorPanel defaultCode={code} docLink="https://link.com" />
Expand Down Expand Up @@ -72,4 +73,24 @@ describe('CodeEditorPanel', () => {
});
});

describe('Cheatsheet icon', () => {
it('hidden by default', () => {

const codeEditorEl = mount(
<ReactComponents.CodeEditorPanel defaultCode={code}/>
);
expect(codeEditorEl.find('.fonticon-help-circled').length).toBe(0);
});
it('is displayed and onClick handle is called', () => {
const onClickMock = sinon.mock();

const codeEditorEl = mount(
<ReactComponents.CodeEditorPanel defaultCode={code} showCheatSheetIcon onCheatsheatIconClick={onClickMock}/>
);
expect(codeEditorEl.find('.cheatsheet-icon').length).toBe(1);
codeEditorEl.find('.cheatsheet-icon').simulate('click');
sinon.assert.calledOnce(onClickMock);
});
});

});
10 changes: 10 additions & 0 deletions app/addons/components/assets/scss/code-editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
}
}

.cheatsheet-icon {
float: right;
padding-right: 0.5rem;
font-size: 13px;
margin-top: 3px;
&:hover {
color: $cf-brand-highlight;
}
}

.full-page-editor-modal-wrapper {
position: fixed;
padding: 110px;
Expand Down
27 changes: 23 additions & 4 deletions app/addons/components/components/codeeditorpanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ export class CodeEditorPanel extends React.Component {
title: '',
docLink: '',
allowZenMode: true,
syntaxMode: 'javascript',
onCheatsheatIconClick: () => {},
showCheatSheetIcon: false,
setHeightToLineCount: true,
blur () {}
};

getStoreState = () => {
return {
zenModeEnabled: false,
code: this.props.defaultCode
code: this.props.defaultCode,
};
};

Expand All @@ -56,6 +60,13 @@ export class CodeEditorPanel extends React.Component {
}
};

getCheatsheetIcon = () => {
if (!this.props.showCheatSheetIcon) {
return null;
}
return <span className="fonticon fonticon-bookmark cheatsheet-icon" title="Show cheatsheet" onClick={this.props.onCheatsheatIconClick}></span>;
};

getDocIcon = () => {
if (this.props.docLink) {
return (
Expand Down Expand Up @@ -119,23 +130,31 @@ export class CodeEditorPanel extends React.Component {
if (this.props.className) {
classes = this.props.className;
}
const heightSettings = {};
if (this.props.setHeightToLineCount) {
heightSettings.setHeightToLineCount = true;
heightSettings.maxLines = 1000;
} else {
heightSettings.setHeightToLineCount = false;
heightSettings.minLines = 30;
}
return (
<div className={classes}>
<label>
<span>{this.props.title}</span>
{this.getDocIcon()}
{this.getZenModeIcon()}
{this.getCheatsheetIcon()}
</label>
<CodeEditor
id={this.props.id}
ref={node => this.codeEditor = node}
mode="javascript"
mode={this.props.syntaxMode}
defaultCode={this.state.code}
showGutter={true}
ignorableErrors={ignorableErrors}
setHeightToLineCount={true}
maxLines={10000}
blur={this.props.blur}
{...heightSettings}
/>
<Beautify code={this.state.code} beautifiedCode={this.beautify} />
{this.getZenModeOverlay()}
Expand Down
4 changes: 0 additions & 4 deletions app/addons/documents/__tests__/json-view.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,7 @@ describe('Docs JSON View', () => {
testDocs[1].type = 'special';

const idx0 = { ...testDocs[0] };
delete idx0.ddoc;
delete idx0.name;
const idx1 = { ...testDocs[1] };
delete idx1.ddoc;
delete idx1.name;

expect(getJsonViewData(testDocs, {databaseName, docType})).toEqual({
displayedFields: null,
Expand Down
1 change: 1 addition & 0 deletions app/addons/documents/assets/scss/documents.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
@import "index-results";
@import "doc-editor";
@import "header";
@import "mango-query";
@import "revision-browser";
@import "header-docs-left";
@import "partition-key";
Expand Down
28 changes: 0 additions & 28 deletions app/addons/documents/assets/scss/index-results.scss
Original file line number Diff line number Diff line change
Expand Up @@ -195,31 +195,3 @@
width: 300px;
}
}

.execution-stats-popup {
font-size: 14px;
.execution-stats-popup-component {
margin: 0.5rem;
[data-status="false"] {
color: $cf-text01-muted;
}
[data-status="true"] {
.value {
font-weight: bold;
}
}
}
.warning {
color: $cf-alert-error-color;
margin: 0.5rem;
}
}

.execution-stats {
font-size: 13px;
padding: 8px 8px 8px 0;

.fonticon-attention-circled {
margin-right: 4px;
}
}
63 changes: 63 additions & 0 deletions app/addons/documents/assets/scss/mango-query.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

@import "../../../../../assets/scss/variables";

.mango-cheatsheet-modal {
max-width: none!important;
width: 50%!important;

.table-wrapper {
max-height: 300px;
overflow-y: scroll;
}
}

.execution-stats {
font-size: 13px;
padding: 8px 8px 8px 0;

.execution-stats-header {
font-size: 16px;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}

.execution-stats-empty-body {
font-style: italic;
}

.execution-stats-body {
[data-status="false"] {
color: $cf-text01-muted;
}
[data-status="true"] {
.value {
font-weight: bold;
}
}
}
.warning {
padding: 0.5rem;
margin-top: 0.5rem;
font-weight: 600;
background-color: $cf-alert-bg;
color: $cf-alert-color;
border-left: 4px solid $cf-warning;
.fonticon-attention-circled {
margin-right: 4px;
}
i::before {
color: $cf-warning;
}
}
}
7 changes: 7 additions & 0 deletions app/addons/documents/assets/scss/view-editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@
.help-link {
margin-left: 4px;
}

.mango-code-editor {
height: 300px;
& > div {
height: 90%;
}
}
}

.mango-select {
Expand Down
7 changes: 6 additions & 1 deletion app/addons/documents/index-results/actions/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,13 @@ export const fetchDocs = (queryDocs, fetchParams, queryOptionsParams) => {
if (layout) {
dispatch(changeLayout(layout));
}
const augmentedStats = executionStats ? {
...executionStats,
// inject when stats were fetched
ts: new Date().getTime(),
} : null;
// dispatch that we're all done
dispatch(newResultsAvailable(finalDocList, params, canShowNext, docType, executionStats, warning));
dispatch(newResultsAvailable(finalDocList, params, canShowNext, docType, augmentedStats, warning));
}).catch((error) => {
if (error && error.message.includes('`partition` parameter is not supported')) {
dispatch(partitionParamNotSupported());
Expand Down
6 changes: 5 additions & 1 deletion app/addons/documents/index-results/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ const initialState = {
showReduce: false,
stable: false,
update: 'true'
}
},
executionStats: null,
warning: null,
};

function loadStyle() {
Expand Down Expand Up @@ -95,6 +97,8 @@ export default function resultsState(state = initialState, action) {
case ActionTypes.INDEX_RESULTS_REDUX_RESET_STATE:
return {
...initialState,
executionStats: state.executionStats,
warning: state.warning,
noResultsWarning: state.noResultsWarning,
selectedLayout: state.selectedLayout,
selectedDocs: [],
Expand Down
Loading

0 comments on commit 613a056

Please sign in to comment.