Skip to content

Commit 6e16574

Browse files
with confirmation hook
1 parent b454799 commit 6e16574

File tree

5 files changed

+61
-116
lines changed

5 files changed

+61
-116
lines changed

packages/compass-aggregations/src/components/confirm-update-view-model/confirm-update-view-modal.tsx

Lines changed: 0 additions & 47 deletions
This file was deleted.

packages/compass-aggregations/src/components/confirm-update-view-model/index.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

packages/compass-aggregations/src/components/pipeline-toolbar/pipeline-header/pipeline-actions.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
exportAggregationResults,
1515
runAggregation,
1616
} from '../../../modules/aggregation';
17-
import { openConfirmUpdateModal } from '../../../modules/update-view';
17+
import { updateView } from '../../../modules/update-view';
1818
import { explainAggregation } from '../../../modules/explain';
1919
import {
2020
getIsPipelineInvalidFromBuilderState,
@@ -189,7 +189,7 @@ const mapState = (state: RootState) => {
189189
};
190190

191191
const mapDispatch = {
192-
onUpdateView: openConfirmUpdateModal,
192+
onUpdateView: updateView,
193193
onRunAggregation: runAggregation,
194194
onExportAggregationResults: exportAggregationResults,
195195
onExplainAggregation: explainAggregation,

packages/compass-aggregations/src/modules/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import comments from './comments';
1919
import autoPreview from './auto-preview';
2020
import id from './id';
2121
import savedPipeline from './saved-pipeline';
22-
import updateView from './update-view';
2322
import settings from './settings';
2423
import savingPipeline from './saving-pipeline';
2524
import outResultsFn from './out-results-fn';
25+
import updateViewError from './update-view';
2626
import aggregation from './aggregation';
2727
import countDocuments from './count-documents';
2828
import isDataLake from './is-datalake';
@@ -77,6 +77,7 @@ const rootReducer = combineReducers({
7777
editViewName,
7878
sourceName,
7979
outResultsFn,
80+
updateViewError,
8081
aggregation,
8182
workspace,
8283
countDocuments,
@@ -89,7 +90,6 @@ const rootReducer = combineReducers({
8990
insights,
9091
searchIndexes,
9192
collectionStats,
92-
updateView,
9393
});
9494

9595
export type RootState = ReturnType<typeof rootReducer>;

packages/compass-aggregations/src/modules/update-view.ts

Lines changed: 57 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,15 @@ import {
88
import type { PipelineBuilderThunkAction } from '.';
99
import { isAction } from '../utils/is-action';
1010
import type { AnyAction } from 'redux';
11+
import { showConfirmation } from '@mongodb-js/compass-components';
12+
import { fetchIndexes } from './search-indexes';
1113

12-
export type UpdateViewState = {
13-
isOpen: boolean;
14-
updateViewError: null | string;
15-
};
16-
17-
export const INITIAL_STATE: UpdateViewState = {
18-
isOpen: false,
19-
updateViewError: null,
20-
};
21-
22-
// Action for opening model.
23-
export const OPEN_CONFIRM_UPDATE_MODEL =
24-
'aggregations/update-view/OPEN_CONFIRM_UPDATE_MODEL' as const;
25-
interface OpenConfirmUpdateModel {
26-
type: typeof OPEN_CONFIRM_UPDATE_MODEL;
27-
}
14+
export type UpdateViewState = null | string;
2815

29-
// Action for closing model.
30-
export const CLOSE_CONFIRM_UPDATE_MODEL =
31-
'aggregations/update-view/CLOSE_CONFIRM_UPDATE_MODEL' as const;
32-
interface CloseConfirmUpdateModel {
33-
type: typeof CLOSE_CONFIRM_UPDATE_MODEL;
34-
}
16+
/**
17+
* State `null` when there is no error, or string if there's an error.
18+
*/
19+
export const INITIAL_STATE: UpdateViewState = null;
3520

3621
// Action for when an error occurs when updating a view.
3722
export const ERROR_UPDATING_VIEW =
@@ -49,34 +34,15 @@ interface DismissViewUpdateErrorAction {
4934
}
5035

5136
export type UpdateViewAction =
52-
| OpenConfirmUpdateModel
53-
| CloseConfirmUpdateModel
5437
| ErrorUpdatingViewAction
5538
| DismissViewUpdateErrorAction;
5639

5740
export default function reducer(
5841
state: UpdateViewState = INITIAL_STATE,
5942
action: AnyAction
6043
): UpdateViewState {
61-
if (isAction<OpenConfirmUpdateModel>(action, OPEN_CONFIRM_UPDATE_MODEL)) {
62-
return {
63-
...state,
64-
isOpen: true,
65-
};
66-
}
67-
68-
if (isAction<CloseConfirmUpdateModel>(action, CLOSE_CONFIRM_UPDATE_MODEL)) {
69-
return {
70-
...state,
71-
isOpen: false,
72-
};
73-
}
74-
7544
if (isAction<ErrorUpdatingViewAction>(action, ERROR_UPDATING_VIEW)) {
76-
return {
77-
...state,
78-
updateViewError: action.error,
79-
};
45+
return action.error;
8046
}
8147
if (
8248
isAction<DismissViewUpdateErrorAction>(action, DISMISS_VIEW_UPDATE_ERROR) ||
@@ -90,23 +56,6 @@ export default function reducer(
9056
return state;
9157
}
9258

93-
/**
94-
* Action creator for opening the confirmation modal.
95-
*
96-
* @returns {Object} The action to open the modal.
97-
*/
98-
export const openConfirmUpdateModal = (): OpenConfirmUpdateModel => ({
99-
type: OPEN_CONFIRM_UPDATE_MODEL,
100-
});
101-
102-
/**
103-
* Action creator for closing the confirmation modal.
104-
*
105-
* @returns {Object} The action to close the modal.
106-
*/
107-
export const closeConfirmUpdateModal = (): CloseConfirmUpdateModel => ({
108-
type: CLOSE_CONFIRM_UPDATE_MODEL,
109-
});
11059
/**
11160
* Action creator for showing the error that occured with updating the view.
11261
*/
@@ -126,6 +75,37 @@ export const dismissViewError = (): DismissViewUpdateErrorAction => ({
12675
type: DISMISS_VIEW_UPDATE_ERROR,
12776
});
12877

78+
const isPipelineSearchQueryable = (
79+
pipeline: Array<Record<string, any>>
80+
): boolean => {
81+
for (const stage of pipeline) {
82+
const stageKey = Object.keys(stage)[0];
83+
84+
// Check if the stage is $addFields, $set, or $match
85+
if (
86+
!(
87+
stageKey === '$addFields' ||
88+
stageKey === '$set' ||
89+
stageKey === '$match'
90+
)
91+
) {
92+
return false; // Not searchable
93+
}
94+
95+
// If the stage is $match, check if uses $expr
96+
if (stageKey === '$match') {
97+
const matchStage = stage['$match'];
98+
const allKeys = Object.keys(matchStage);
99+
100+
if (!(allKeys.length === 1 && allKeys.includes('$expr'))) {
101+
return false; // Not searchable
102+
}
103+
}
104+
}
105+
106+
return true;
107+
};
108+
129109
/**
130110
* Updates a view.
131111
*
@@ -145,7 +125,6 @@ export const updateView = (): PipelineBuilderThunkAction<Promise<void>> => {
145125
}
146126
) => {
147127
dispatch(dismissViewError());
148-
dispatch(closeConfirmUpdateModal());
149128

150129
const state = getState();
151130
const ds = state.dataService.dataService;
@@ -161,6 +140,24 @@ export const updateView = (): PipelineBuilderThunkAction<Promise<void>> => {
161140
getState(),
162141
pipelineBuilder
163142
);
143+
144+
await dispatch(fetchIndexes());
145+
if (state.searchIndexes.indexes.length > 0) {
146+
const pipelineIsSearchQueryable = isPipelineSearchQueryable(viewPipeline);
147+
const confirmed = await showConfirmation({
148+
title: `Are you sure you want to update the view?`,
149+
description: pipelineIsSearchQueryable
150+
? 'There are search indexes created on this view. Updating the view will result in an index rebuild, which will consume additional resources on your cluster.'
151+
: 'This update will make the view incompatible with search indexes and will cause all search indexes to fail. Only views containing $addFields, $set or $match stages with the $expr operator are compatible with search indexes.',
152+
buttonText: 'Update',
153+
variant: pipelineIsSearchQueryable ? 'primary' : 'danger',
154+
});
155+
156+
if (!confirmed) {
157+
return;
158+
}
159+
}
160+
164161
const options = {
165162
viewOn: toNS(state.namespace).collection,
166163
pipeline: viewPipeline,

0 commit comments

Comments
 (0)