Skip to content

Commit 0f2067a

Browse files
committed
retain current query when new query is applied from autocomplete
1 parent 8fd9393 commit 0f2067a

File tree

2 files changed

+85
-32
lines changed

2 files changed

+85
-32
lines changed

packages/compass-query-bar/src/components/option-editor.tsx

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,19 @@ import type { RootState } from '../stores/query-bar-store';
2727
import { useAutocompleteFields } from '@mongodb-js/compass-field-store';
2828
import { applyFromHistory } from '../stores/query-bar-reducer';
2929
import { getQueryAttributes } from '../utils';
30-
import type { BaseQuery, QueryFormFields } from '../constants/query-properties';
30+
import type {
31+
BaseQuery,
32+
QueryFormFields,
33+
QueryProperty,
34+
} from '../constants/query-properties';
35+
import { QUERY_PROPERTIES } from '../constants/query-properties';
3136
import { mapQueryToFormFields } from '../utils/query';
3237
import { DEFAULT_FIELD_VALUES } from '../constants/query-bar-store';
38+
import type {
39+
FavoriteQuery,
40+
RecentQuery,
41+
} from '@mongodb-js/my-queries-storage';
42+
import _ from 'lodash';
3343

3444
const editorContainerStyles = css({
3545
position: 'relative',
@@ -87,8 +97,9 @@ const insightsBadgeStyles = css({
8797
flex: 'none',
8898
});
8999

100+
type OptionEditorName = Exclude<QueryProperty, 'maxTimeMS' | 'limit' | 'skip'>;
90101
type OptionEditorProps = {
91-
optionName: string;
102+
optionName: OptionEditorName;
92103
namespace: string;
93104
id?: string;
94105
hasError?: boolean;
@@ -107,7 +118,7 @@ type OptionEditorProps = {
107118
insights?: Signal | Signal[];
108119
disabled?: boolean;
109120
savedQueries: SavedQuery[];
110-
onApplyQuery: (query: BaseQuery) => void;
121+
onApplyQuery: (query: BaseQuery, fieldsToPreserve: QueryProperty[]) => void;
111122
};
112123

113124
export const OptionEditor: React.FunctionComponent<OptionEditorProps> = ({
@@ -166,27 +177,19 @@ export const OptionEditor: React.FunctionComponent<OptionEditorProps> = ({
166177
return isQueryHistoryAutocompleteEnabled
167178
? createQueryWithHistoryAutocompleter({
168179
queryProperty: optionName,
169-
savedQueries: savedQueries
170-
.filter((query) => {
171-
const isOptionNameInQuery =
172-
optionName === 'filter' || optionName in query.queryProperties;
173-
const isUpdateNotInQuery = !('update' in query.queryProperties);
174-
return isOptionNameInQuery && isUpdateNotInQuery;
175-
})
176-
.map((query) => ({
177-
type: query.type,
178-
lastExecuted: query.lastExecuted,
179-
queryProperties: query.queryProperties,
180-
}))
181-
.sort(
182-
(a, b) => a.lastExecuted.getTime() - b.lastExecuted.getTime()
183-
),
180+
savedQueries,
184181
options: {
185182
fields: schemaFields,
186183
serverVersion,
187184
},
188185
onApply: (query: SavedQuery['queryProperties']) => {
189-
onApplyQuery(query);
186+
// When we are applying a query from `filter` field, we want to apply the whole query,
187+
// otherwise we want to preserve the other fields that are already in the current query.
188+
const fieldsToPreserve =
189+
optionName === 'filter'
190+
? []
191+
: QUERY_PROPERTIES.filter((x) => x !== optionName);
192+
onApplyQuery(query, fieldsToPreserve);
190193
if (!query[optionName]) {
191194
return;
192195
}
@@ -295,25 +298,66 @@ export const OptionEditor: React.FunctionComponent<OptionEditorProps> = ({
295298
);
296299
};
297300

298-
const ConnectedOptionEditor = (state: RootState) => ({
301+
export function getOptionBasedQueries(
302+
optionName: OptionEditorName,
303+
type: 'recent' | 'favorite',
304+
queries: (RecentQuery | FavoriteQuery)[]
305+
) {
306+
return (
307+
queries
308+
.map((query) => ({
309+
type,
310+
lastExecuted: query._lastExecuted,
311+
// For query that's being autocompeted from the main `filter`, we want to
312+
// show whole query to the user, so that when its applied, it will replace
313+
// the whole query (filter, project, sort etc).
314+
// For other options, we only want to show the query for that specific option.
315+
queryProperties: getQueryAttributes(
316+
optionName !== 'filter' ? { [optionName]: query[optionName] } : query
317+
),
318+
}))
319+
// Filter the query if:
320+
// - its empty
321+
// - its an `update` query
322+
// - its a duplicate
323+
.filter((query, i, arr) => {
324+
const queryIsUpdate = _.has(query.queryProperties, 'update');
325+
const queryIsEmpty = _.isEmpty(query.queryProperties);
326+
if (queryIsEmpty || queryIsUpdate) {
327+
return false;
328+
}
329+
return (
330+
i ===
331+
arr.findIndex(
332+
(t) =>
333+
JSON.stringify(t.queryProperties) ===
334+
JSON.stringify(query.queryProperties)
335+
)
336+
);
337+
})
338+
.sort((a, b) => a.lastExecuted.getTime() - b.lastExecuted.getTime())
339+
);
340+
}
341+
342+
const mapStateToProps = (state: RootState, ownProps: OptionEditorProps) => ({
299343
namespace: state.queryBar.namespace,
300344
serverVersion: state.queryBar.serverVersion,
301345
savedQueries: [
302-
...state.queryBar.recentQueries.map((query) => ({
303-
type: 'recent',
304-
lastExecuted: query._lastExecuted,
305-
queryProperties: getQueryAttributes(query),
306-
})),
307-
...state.queryBar.favoriteQueries.map((query) => ({
308-
type: 'favorite',
309-
lastExecuted: query._lastExecuted,
310-
queryProperties: getQueryAttributes(query),
311-
})),
346+
...getOptionBasedQueries(
347+
ownProps.optionName,
348+
'recent',
349+
state.queryBar.recentQueries
350+
),
351+
...getOptionBasedQueries(
352+
ownProps.optionName,
353+
'favorite',
354+
state.queryBar.favoriteQueries
355+
),
312356
],
313357
});
314358

315359
const mapDispatchToProps = {
316360
onApplyQuery: applyFromHistory,
317361
};
318362

319-
export default connect(ConnectedOptionEditor, mapDispatchToProps)(OptionEditor);
363+
export default connect(mapStateToProps, mapDispatchToProps)(OptionEditor);

packages/compass-query-bar/src/stores/query-bar-reducer.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,23 @@ type ApplyFromHistoryAction = {
224224
};
225225

226226
export const applyFromHistory = (
227-
query: BaseQuery & { update?: Document }
227+
query: BaseQuery & { update?: Document },
228+
currentQueryFieldsToRetain: QueryProperty[] = []
228229
): QueryBarThunkAction<void, ApplyFromHistoryAction> => {
229230
return (dispatch, getState, { localAppRegistry, preferences }) => {
231+
const currentFields = getState().queryBar.fields;
232+
const currentQuery = currentQueryFieldsToRetain.reduce((acc, key) => {
233+
if (currentFields[key]?.value) {
234+
acc[key] = currentFields[key].value;
235+
}
236+
return acc;
237+
}, {} as Record<string, number | Document>);
230238
const fields = mapQueryToFormFields(
231239
{ maxTimeMS: preferences.getPreferences().maxTimeMS },
232240
{
233241
...DEFAULT_FIELD_VALUES,
234242
...query,
243+
...currentQuery,
235244
}
236245
);
237246
dispatch({

0 commit comments

Comments
 (0)