Skip to content

Commit c7fe3a9

Browse files
authored
Merge pull request #967 from lyp000119/dev
add migrationViewDetailConfig test and migration view config
2 parents 6229f8f + 58bf1ba commit c7fe3a9

File tree

13 files changed

+166
-60
lines changed

13 files changed

+166
-60
lines changed

frontend/src/app/components/ChartEditor.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import {
4242
SaveFormContext,
4343
useSaveFormContext,
4444
} from 'app/pages/MainPage/pages/VizPage/SaveFormContext';
45-
import { useMainSlice } from 'app/pages/MainPage/slice';
4645
import { IChart } from 'app/types/Chart';
4746
import { ChartDTO } from 'app/types/ChartDTO';
4847
import { makeDownloadDataTask } from 'app/utils/fetch';
@@ -103,7 +102,6 @@ export const ChartEditor: React.FC<ChartEditorProps> = ({
103102
}) => {
104103
const saveFormContextValue = useSaveFormContext();
105104
const { actions } = useWorkbenchSlice();
106-
const { actions: mainActions } = useMainSlice();
107105
const dispatch = useDispatch();
108106
const dataset = useSelector(datasetsSelector);
109107
const dataview = useSelector(currentDataViewSelector);
@@ -477,7 +475,7 @@ export const ChartEditor: React.FC<ChartEditorProps> = ({
477475
],
478476
fileName: backendChart?.name || 'chart',
479477
resolve: () => {
480-
dispatch(mainActions.setDownloadPolling(true));
478+
dispatch(actions.setChartEditorDownloadPolling(true));
481479
},
482480
}),
483481
);
@@ -489,7 +487,7 @@ export const ChartEditor: React.FC<ChartEditorProps> = ({
489487
dataChartId,
490488
dataview,
491489
dispatch,
492-
mainActions,
490+
actions,
493491
widgetId,
494492
]);
495493

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
1-
import { View } from 'app/types/View';
2-
import isUndefined from 'lodash/isUndefined';
1+
import { APP_VERSION_BETA_2 } from '../constants';
2+
import MigrationEvent from '../MigrationEvent';
3+
import MigrationEventDispatcher from '../MigrationEventDispatcher';
34

4-
export const beta2 = viewDetailData => {
5-
if (!viewDetailData) {
6-
return viewDetailData;
5+
export const beta2 = viewConfig => {
6+
if (!viewConfig) {
7+
return viewConfig;
78
}
89

910
try {
10-
let viewConfig = JSON.parse(viewDetailData.config);
11-
12-
if (isUndefined(viewConfig.expensiveQuery)) {
11+
if (viewConfig) {
1312
viewConfig.expensiveQuery = false;
1413
}
15-
viewDetailData.config = JSON.stringify(viewConfig);
1614

17-
return viewDetailData;
15+
return viewConfig;
1816
} catch (error) {
1917
console.error('Migration ViewConfig Errors | beta.2 | ', error);
20-
return viewDetailData;
18+
return viewConfig;
2119
}
2220
};
2321

24-
export const migrateViewConfig = (viewDetailData: View) => {
25-
let config = beta2(viewDetailData);
26-
return beta2(config);
22+
export const migrateViewConfig = (viewConfig: string) => {
23+
if (!viewConfig?.trim().length) {
24+
return viewConfig;
25+
}
26+
27+
const config = JSON.parse(viewConfig);
28+
const event2 = new MigrationEvent(APP_VERSION_BETA_2, beta2);
29+
const dispatcher = new MigrationEventDispatcher(event2);
30+
const result = dispatcher.process(config);
31+
32+
return JSON.stringify(result);
2733
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Datart
3+
*
4+
* Copyright 2021
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
import { APP_VERSION_BETA_2 } from '../constants';
20+
import { migrateViewConfig } from '../ViewConfig/migrationViewDetailConfig';
21+
22+
describe('migrateViewConfig Test', () => {
23+
test('Test when config is null', () => {
24+
const config = JSON.stringify(null);
25+
expect(migrateViewConfig(config)).toEqual('null');
26+
});
27+
28+
test('Test when config is empty', () => {
29+
const config = '';
30+
expect(migrateViewConfig(config)).toEqual('');
31+
});
32+
33+
test('Test config without expensiveQuery variable', () => {
34+
const config =
35+
'{"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0}';
36+
expect(migrateViewConfig(config)).toEqual(
37+
`{"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0,"expensiveQuery":false,"version":"${APP_VERSION_BETA_2}"}`,
38+
);
39+
expect(migrateViewConfig(config)).toMatch(/"version":/);
40+
});
41+
42+
test('Test when there is a version number and expensiveQuery = false', () => {
43+
const config = `{"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0,"expensiveQuery":false,"version":"${APP_VERSION_BETA_2}"}`;
44+
expect(migrateViewConfig(config)).toEqual(config);
45+
expect(migrateViewConfig(config)).toMatch(/"version":/);
46+
});
47+
48+
test('Test when there is a version number and expensiveQuery = true', () => {
49+
const config = `{"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0,"expensiveQuery":true,"version":"${APP_VERSION_BETA_2}"}`;
50+
expect(migrateViewConfig(config)).toEqual(config);
51+
expect(migrateViewConfig(config)).toMatch(/"version":/);
52+
});
53+
54+
/**
55+
* The case of dirty data
56+
*/
57+
test('Test when config is null', () => {
58+
const config =
59+
'{"expensiveQuery":false,"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0}';
60+
expect(migrateViewConfig(config)).toEqual(
61+
`{"expensiveQuery":false,"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0,"version":"${APP_VERSION_BETA_2}"}`,
62+
);
63+
expect(migrateViewConfig(config)).toMatch(/"version":/);
64+
});
65+
66+
/**
67+
* The case of dirty data
68+
*/
69+
test('Test for dirty data', () => {
70+
const config =
71+
'{"expensiveQuery":true,"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0}';
72+
expect(migrateViewConfig(config)).toEqual(
73+
`{"expensiveQuery":false,"concurrencyControl":true,"concurrencyControlMode":"DIRTYREAD","cache":false,"cacheExpires":0,"version":"${APP_VERSION_BETA_2}"}`,
74+
);
75+
expect(migrateViewConfig(config)).toMatch(/"version":/);
76+
});
77+
});

frontend/src/app/pages/ChartWorkbenchPage/components/ChartHeaderPanel/ChartHeaderPanel.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ import { Button, Space } from 'antd';
2020
import SaveToDashboard from 'app/components/SaveToDashboard';
2121
import useI18NPrefix from 'app/hooks/useI18NPrefix';
2222
import useMount from 'app/hooks/useMount';
23-
import { backendChartSelector } from 'app/pages/ChartWorkbenchPage/slice/workbenchSlice';
23+
import {
24+
backendChartSelector,
25+
selectChartEditorDownloadPolling,
26+
useWorkbenchSlice,
27+
} from 'app/pages/ChartWorkbenchPage/slice/workbenchSlice';
2428
import { DownloadListPopup } from 'app/pages/MainPage/Navbar/DownloadListPopup';
2529
import { loadTasks } from 'app/pages/MainPage/Navbar/service';
2630
import { selectHasVizFetched } from 'app/pages/MainPage/pages/VizPage/slice/selectors';
2731
import { getFolders } from 'app/pages/MainPage/pages/VizPage/slice/thunks';
28-
import { useMainSlice } from 'app/pages/MainPage/slice';
29-
import { selectDownloadPolling } from 'app/pages/MainPage/slice/selectors';
3032
import { downloadFile } from 'app/utils/fetch';
3133
import { FC, memo, useCallback, useState } from 'react';
3234
import { useDispatch, useSelector } from 'react-redux';
@@ -61,9 +63,9 @@ const ChartHeaderPanel: FC<{
6163
const hasVizFetched = useSelector(selectHasVizFetched);
6264
const [isModalVisible, setIsModalVisible] = useState<boolean>(false);
6365
const backendChart = useSelector(backendChartSelector);
64-
const downloadPolling = useSelector(selectDownloadPolling);
66+
const downloadPolling = useSelector(selectChartEditorDownloadPolling);
6567
const dispatch = useDispatch();
66-
const { actions } = useMainSlice();
68+
const { actions } = useWorkbenchSlice();
6769

6870
const handleModalOk = useCallback(
6971
(dashboardId: string, dashboardType: string) => {
@@ -79,7 +81,7 @@ const ChartHeaderPanel: FC<{
7981

8082
const onSetPolling = useCallback(
8183
(polling: boolean) => {
82-
dispatch(actions.setDownloadPolling(polling));
84+
dispatch(actions.setChartEditorDownloadPolling(polling));
8385
},
8486
[dispatch, actions],
8587
);
@@ -90,6 +92,7 @@ const ChartHeaderPanel: FC<{
9092
dispatch(getFolders(orgId as string));
9193
}
9294
});
95+
9396
return (
9497
<Wrapper>
9598
<h1>{chartName}</h1>
@@ -101,7 +104,7 @@ const ChartHeaderPanel: FC<{
101104
onDownloadFile={item => {
102105
if (item.id) {
103106
downloadFile(item.id).then(() => {
104-
dispatch(actions.setDownloadPolling(true));
107+
dispatch(actions.setChartEditorDownloadPolling(true));
105108
});
106109
}
107110
}}

frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/components/Chart404Graph.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ export default Chart404Graph;
6161
const StyledChart404Graph = styled.div`
6262
display: flex;
6363
flex-flow: column;
64-
justify-content: center;
6564
align-items: center;
65+
justify-content: center;
6666
height: 100%;
6767
opacity: 0.3;
6868
`;

frontend/src/app/pages/ChartWorkbenchPage/slice/workbenchSlice.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export type WorkbenchState = {
7878
backendChartId?: string;
7979
aggregation?: boolean;
8080
datasetLoading: boolean;
81+
chartEditorDownloadPolling: boolean;
8182
};
8283

8384
const initState: WorkbenchState = {
@@ -87,6 +88,7 @@ const initState: WorkbenchState = {
8788
dataset: {},
8889
aggregation: true,
8990
datasetLoading: false,
91+
chartEditorDownloadPolling: false,
9092
};
9193

9294
// Selectors
@@ -142,6 +144,11 @@ export const datasetLoadingSelector = createSelector(
142144
workbenchSelector,
143145
wb => wb.datasetLoading,
144146
);
147+
148+
export const selectChartEditorDownloadPolling = createSelector(
149+
workbenchSelector,
150+
wb => wb.chartEditorDownloadPolling,
151+
);
145152
// Effects
146153
export const initWorkbenchAction = createAsyncThunk(
147154
'workbench/initWorkbenchAction',
@@ -208,7 +215,7 @@ export const fetchViewDetailAction = createAsyncThunk(
208215
method: 'GET',
209216
url: `views/${arg}`,
210217
});
211-
return migrateViewConfig(response.data);
218+
return response.data;
212219
},
213220
);
214221

@@ -442,6 +449,9 @@ const workbenchSlice = createSlice({
442449
resetWorkbenchState: (state, action) => {
443450
return initState;
444451
},
452+
setChartEditorDownloadPolling(state, { payload }: PayloadAction<boolean>) {
453+
state.chartEditorDownloadPolling = payload;
454+
},
445455
},
446456
extraReducers: builder => {
447457
builder
@@ -460,6 +470,7 @@ const workbenchSlice = createSlice({
460470
if (index !== undefined) {
461471
state.currentDataView = {
462472
...payload,
473+
config: migrateViewConfig(payload.config),
463474
meta: transformMeta(payload.model),
464475
computedFields,
465476
};

frontend/src/app/pages/MainPage/pages/ViewPage/Main/Editor/SQLEditor.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ export const SQLEditor = memo(() => {
104104
type: CommonFormTypes.Edit,
105105
visible: true,
106106
parentIdLabel: t('folder'),
107+
initialValues: {
108+
name: '',
109+
parentId: '',
110+
config: {},
111+
},
107112
onSave: (values, onClose) => {
108113
let index = getInsertedNodeIndex(values, viewsData);
109114

frontend/src/app/pages/MainPage/pages/ViewPage/SaveForm.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
} from 'antd';
3131
import { ModalForm, ModalFormProps } from 'app/components';
3232
import useI18NPrefix from 'app/hooks/useI18NPrefix';
33+
import { APP_CURRENT_VERSION } from 'app/migration/constants';
3334
import debounce from 'debounce-promise';
3435
import { DEFAULT_DEBOUNCE_WAIT } from 'globalConstants';
3536
import {
@@ -115,7 +116,13 @@ export function SaveForm({ formProps, ...modalProps }: SaveFormProps) {
115116

116117
const save = useCallback(
117118
values => {
118-
onSave(values, onCancel);
119+
onSave(
120+
{
121+
...values,
122+
config: { version: APP_CURRENT_VERSION, ...values.config },
123+
},
124+
onCancel,
125+
);
119126
},
120127
[onSave, onCancel],
121128
);
@@ -184,15 +191,7 @@ export function SaveForm({ formProps, ...modalProps }: SaveFormProps) {
184191
}}
185192
/>
186193
</Form.Item>
187-
<Form.Item
188-
wrapperCol={{ span: 13, offset: 9 }}
189-
name={['config', 'expensiveQuery']}
190-
initialValue={expensiveQuery}
191-
valuePropName="checked"
192-
>
193-
<Checkbox>{t('expensiveQuery')}</Checkbox>
194-
</Form.Item>
195-
{!simple && (
194+
{!simple && initialValues?.config && (
196195
<>
197196
<AdvancedToggle
198197
type="link"
@@ -238,6 +237,14 @@ export function SaveForm({ formProps, ...modalProps }: SaveFormProps) {
238237
>
239238
<InputNumber disabled={!cache} />
240239
</Form.Item>
240+
<Form.Item
241+
wrapperCol={{ span: 13, offset: 9 }}
242+
name={['config', 'expensiveQuery']}
243+
initialValue={expensiveQuery}
244+
valuePropName="checked"
245+
>
246+
<Checkbox>{t('expensiveQuery')}</Checkbox>
247+
</Form.Item>
241248
</AdvancedWrapper>
242249
</>
243250
)}

frontend/src/app/pages/MainPage/pages/ViewPage/Sidebar/index.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,20 +228,23 @@ const Wrapper = styled.div<{
228228
isDragging: boolean;
229229
width: number;
230230
}>`
231-
transition: ${p => (!p.isDragging ? 'width 0.3s ease' : 'none')};
232231
height: 100%;
232+
transition: ${p => (!p.isDragging ? 'width 0.3s ease' : 'none')};
233233
&.close {
234-
width: ${SPACE_TIMES(7.5)} !important;
235-
border-right: 1px solid #e9ecef;
236234
position: absolute;
235+
width: ${SPACE_TIMES(7.5)} !important;
237236
height: 100%;
238237
background: #fff;
238+
border-right: 1px solid #e9ecef;
239239
.menuUnfoldOutlined {
240240
position: absolute;
241241
top: 50%;
242242
left: 50%;
243243
transform: translate(-50%, -50%);
244244
}
245+
> div {
246+
display: ${p => (p.sliderVisible ? 'none' : 'flex')};
247+
}
245248
&:hover {
246249
width: ${p => p.width + '%'} !important;
247250
.menuUnfoldOutlined {
@@ -255,18 +258,15 @@ const Wrapper = styled.div<{
255258
}
256259
}
257260
}
258-
> div {
259-
display: ${p => (p.sliderVisible ? 'none' : 'flex')};
260-
}
261261
`;
262262
const ListNavWrapper = styled(ListNav)`
263+
position: relative;
264+
z-index: ${NAV_LEVEL};
263265
display: flex;
264266
flex-direction: column;
265267
flex-shrink: 0;
268+
height: 100%;
266269
padding: ${SPACE_XS} 0;
267270
background-color: ${p => p.theme.componentBackground};
268271
border-right: 1px solid ${p => p.theme.borderColorSplit};
269-
height: 100%;
270-
position: relative;
271-
z-index: ${NAV_LEVEL};
272272
`;

0 commit comments

Comments
 (0)