Skip to content

Commit aa46614

Browse files
Ensure the correct title populated for restored query tool tabs.#3319
1 parent 7946ee7 commit aa46614

File tree

10 files changed

+113
-47
lines changed

10 files changed

+113
-47
lines changed

web/pgadmin/browser/static/js/browser.js

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import getApiInstance, {parseApiError} from '../../../static/js/api_instance';
1616
import usePreferences, { setupPreferenceBroadcast } from '../../../preferences/static/js/store';
1717
import checkNodeVisibility from '../../../static/js/check_node_visibility';
1818
import * as showQueryTool from '../../../tools/sqleditor/static/js/show_query_tool';
19-
import {getRandomInt} from 'sources/utils';
2019

2120
define('pgadmin.browser', [
2221
'sources/gettext', 'sources/url_for', 'sources/pgadmin',
@@ -304,30 +303,35 @@ define('pgadmin.browser', [
304303
url_for('settings.get_application_state')
305304
).then((res)=> {
306305
if(res.data.success && res.data.data.result.length > 0){
306+
let deleteToolDataIds = [];
307307
_.each(res.data.data.result, function(toolState){
308308
let toolNme = toolState.tool_name;
309-
let toolDataId = `${toolNme}-${getRandomInt(1, 9999999)}`;
309+
let toolDataId = `${toolNme}-${toolState.id}`;
310310
let connectionInfo = toolState.connection_info;
311-
localStorage.setItem(toolDataId, toolState.tool_data);
312-
311+
313312
if (toolNme == 'sqleditor'){
314313
showQueryTool.relaunchSqlTool(connectionInfo, toolDataId);
315-
}else if(toolNme == 'psql'){
316-
pgAdmin.Tools.Psql.openPsqlTool(null, null, connectionInfo);
317-
}else if(toolNme == 'ERD'){
318-
pgAdmin.Tools.ERD.showErdTool(null, null, false, connectionInfo, toolDataId);
319-
}else if(toolNme == 'schema_diff'){
320-
pgAdmin.Tools.SchemaDiff.launchSchemaDiff(toolDataId);
314+
}else{
315+
localStorage.setItem(toolDataId, toolState.tool_data);
316+
deleteToolDataIds.push(toolState.id);
317+
if(toolNme == 'psql'){
318+
pgAdmin.Tools.Psql.openPsqlTool(null, null, connectionInfo);
319+
}else if(toolNme == 'ERD'){
320+
pgAdmin.Tools.ERD.showErdTool(null, null, false, connectionInfo, toolDataId);
321+
}else if(toolNme == 'schema_diff'){
322+
pgAdmin.Tools.SchemaDiff.launchSchemaDiff(toolDataId);
323+
}
321324
}
322325
});
323326

324327
// call clear application state data.
325-
try {
326-
getApiInstance().delete(url_for('settings.delete_application_state'), {});
327-
} catch (error) {
328-
console.error(error);
329-
pgAdmin.Browser.notifier.error(gettext('Failed to remove query data.') + parseApiError(error));
330-
}
328+
if(deleteToolDataIds.length > 0){
329+
try {
330+
getApiInstance().delete(url_for('settings.delete_application_state'), {data:{'trans_ids': deleteToolDataIds}});
331+
} catch (error) {
332+
console.error(error);
333+
pgAdmin.Browser.notifier.error(gettext('Failed to remove query data.') + parseApiError(error));
334+
}}
331335
}
332336
}).catch(function(error) {
333337
pgAdmin.Browser.notifier.pgRespErrorNotify(error);

web/pgadmin/settings/__init__.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ def get_exposed_url_endpoints(self):
5757
'settings.get_file_format_setting',
5858
'settings.save_application_state',
5959
'settings.get_application_state',
60-
'settings.delete_application_state'
60+
'settings.delete_application_state',
61+
'settings.get_tool_data'
6162
]
6263

6364

@@ -326,8 +327,7 @@ def get_last_saved_file_hash(file_path, trans_id):
326327

327328
@blueprint.route(
328329
'/get_application_state',
329-
methods=["GET"], endpoint='get_application_state'
330-
)
330+
methods=["GET"], endpoint='get_application_state')
331331
@pga_login_required
332332
def get_application_state():
333333
"""
@@ -369,17 +369,42 @@ def get_application_state():
369369
}
370370
)
371371

372+
@blueprint.route(
373+
'/get_tool_data/<int:trans_id>',
374+
methods=["GET"], endpoint='get_tool_data')
375+
@pga_login_required
376+
def get_tool_data(trans_id):
377+
fernet = Fernet(current_app.config['SECRET_KEY'].encode())
378+
result = db.session \
379+
.query(ApplicationState) \
380+
.filter(ApplicationState.uid == current_user.id, ApplicationState.id == trans_id) \
381+
.first()
382+
383+
return make_json_response(
384+
data={
385+
'status': True,
386+
'msg': '',
387+
'result': {
388+
'tool_data': fernet.decrypt(result.tool_data).decode(),
389+
}
390+
}
391+
)
372392

373393
@blueprint.route(
374394
'/delete_application_state/',
375395
methods=["DELETE"], endpoint='delete_application_state')
376396
@pga_login_required
377397
def delete_application_state():
378-
trans_id = None
398+
status = False
399+
msg = gettext('Unable to delete application state data.')
379400
if request.data:
380401
data = json.loads(request.data)
381-
trans_id = int(data['panelId'].split('_')[-1])
382-
status, msg = delete_tool_data(trans_id)
402+
if 'trans_ids' in data:
403+
for trans_id in data['trans_ids']:
404+
status, msg = delete_tool_data(trans_id)
405+
else:
406+
trans_id = int(data['panelId'].split('_')[-1])
407+
status, msg = delete_tool_data(trans_id)
383408
return make_json_response(
384409
data={
385410
'status': status,

web/pgadmin/settings/static/ApplicationStateProvider.jsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function deleteToolData(panelId, closePanelId){
3737
}
3838
};
3939

40-
export function ApplicationStateProvider({children}){
40+
export function ApplicationStateProvider({children, toolDataId}){
4141
const preferencesStore = usePreferences();
4242
const saveAppState = preferencesStore?.getPreferencesForModule('misc')?.save_app_state;
4343
const openNewTab = preferencesStore?.getPreferencesForModule('browser')?.new_browser_tab_open;
@@ -63,9 +63,36 @@ export function ApplicationStateProvider({children}){
6363
return saveAppState;
6464
};
6565

66+
async function getQueryToolContent() {
67+
try {
68+
let transId = toolDataId.split('-')[1];
69+
const res = await getApiInstance({'Content-Encoding': 'gzip'}).get(
70+
url_for('settings.get_tool_data', {
71+
'trans_id': transId,
72+
})
73+
);
74+
return res.data.success? JSON.parse(res.data.data.result.tool_data): null;
75+
} catch (error) {
76+
pgAdmin.Browser.notifier.pgRespErrorNotify(error);
77+
return null;
78+
}
79+
}
80+
81+
const deleteToolData = ()=>{
82+
let transId = toolDataId.split('-')[1];
83+
getApiInstance().delete(
84+
url_for('settings.delete_application_state'), {data:{'panelId': transId}}
85+
).then(()=> { /* Sonar Qube */}).catch(function(error) {
86+
pgAdmin.Browser.notifier.pgRespErrorNotify(error);
87+
});
88+
89+
};
90+
6691
const value = useMemo(()=>({
6792
saveToolData,
6893
isSaveToolDataEnabled,
94+
getQueryToolContent,
95+
deleteToolData
6996
}), []);
7097

7198
return <ApplicationStateContext.Provider value={value}>
@@ -75,5 +102,6 @@ export function ApplicationStateProvider({children}){
75102
}
76103

77104
ApplicationStateProvider.propTypes = {
78-
children: PropTypes.object
105+
children: PropTypes.object,
106+
toolDataId: PropTypes.string
79107
};

web/pgadmin/static/js/helpers/Layout/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function TabTitle({id, closable, defaultInternal}) {
4545
}, []);
4646

4747
useEffect(()=>{
48-
const deregister = layoutDocker.eventBus.registerListener(LAYOUT_EVENTS.REFRESH_TITLE, _.debounce((panelId)=>{
48+
const deregister = layoutDocker.eventBus.registerListener(LAYOUT_EVENTS.REFRESH_TITLE, (panelId)=>{
4949
if(panelId == id) {
5050
const internal = layoutDocker?.find(id)?.internal??{};
5151
setAttrs({
@@ -54,7 +54,7 @@ function TabTitle({id, closable, defaultInternal}) {
5454
tooltip: internal.tooltip ?? internal.title,
5555
});
5656
}
57-
}, 100));
57+
});
5858

5959
return ()=>deregister?.();
6060
}, []);

web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ export default class ERDTool extends React.Component {
360360
this.diagram.deserialize(sqlValue);
361361
this.diagram.clearSelection();
362362
this.registerModelEvents();
363+
this.setState({dirty: true});
364+
this.eventBus.fireEvent(ERD_EVENTS.DIRTY, true, this.serializeFile());
363365
}
364366
}
365367
else if(this.props.params.gen) {

web/pgadmin/tools/sqleditor/static/js/SQLEditorModule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export default class SQLEditor {
248248
root.render(
249249
<Theme>
250250
<PgAdminProvider value={pgAdmin}>
251-
<ApplicationStateProvider>
251+
<ApplicationStateProvider toolDataId={params.toolDataId}>
252252
<ModalProvider>
253253
<NotifierProvider pgAdmin={pgAdmin} pgWindow={pgWindow} />
254254
{ params.error ?

web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
166166
const docker = useRef(null);
167167
const api = useMemo(()=>getApiInstance(), []);
168168
const modal = useModal();
169-
const {isSaveToolDataEnabled} = useApplicationState();
169+
const {isSaveToolDataEnabled, deleteToolData} = useApplicationState();
170170

171171
/* Connection status poller */
172172
let pollTime = qtState.preferences.sqleditor.connection_status_fetch_time > 0
@@ -283,31 +283,32 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
283283
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.HANDLE_API_ERROR, err);
284284
setQtStatePartial({ editor_disabled: true });
285285
});
286-
} else if (qtState.params.sql_id) {
286+
} else if (qtState.params.toolDataId) {
287287
populateEditorData();
288288
} else {
289289
setQtStatePartial({ editor_disabled: false });
290290
}
291291
};
292292

293293
const populateEditorData = () =>{
294-
let sqlId = qtState.params.sql_id,
295-
loadSqlFromLocalStorage = true;
296-
294+
let populateQueryContent = true;
295+
297296
if(qtState.params.open_file_name){
298297
if(qtState.params.file_deleted == 'false' && qtState.params.is_editor_dirty == 'false'){
299-
// call load file from disk as no fil changes
298+
// call load file from disk as no file changes
300299
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, qtState.params.open_file_name, qtState.params?.storage);
300+
populateQueryContent = false;
301+
deleteToolData();
301302
}else if(qtState.params.file_deleted != 'true'){
302303
if(qtState.params.external_file_changes == 'true'){
303-
loadSqlFromLocalStorage = false;
304-
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.WARN_RELOAD_FILE, qtState.params.open_file_name, sqlId);
304+
populateQueryContent = false;
305+
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.WARN_RELOAD_FILE, qtState.params.open_file_name);
305306
}else{
306307
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE_DONE, qtState.params.open_file_name, true);
307308
}
308309
}
309310
}
310-
if(loadSqlFromLocalStorage) eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_SQL_FROM_LOCAL_STORAGE, sqlId);
311+
if(populateQueryContent) eventBus.current.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_GET_QUERY_CONTENT);
311312
setQtStatePartial({ editor_disabled: false });
312313
};
313314

@@ -545,7 +546,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
545546
});
546547
isDirtyRef.current = false;
547548
setPanelTitle(qtPanelDocker, qtPanelId, fileName, {...qtState, current_file: fileName}, isDirtyRef.current);
548-
549+
549550
if(isSaveToolDataEnabled('sqleditor'))eventBus.current.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_SAVE_QUERY_TOOL_DATA);
550551
}
551552
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.EDITOR_LAST_FOCUS);
@@ -584,6 +585,8 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
584585
[QUERY_TOOL_EVENTS.LOAD_FILE_DONE, fileDone],
585586
[QUERY_TOOL_EVENTS.SAVE_FILE_DONE, fileDone],
586587
[QUERY_TOOL_EVENTS.QUERY_CHANGED, (isDirty)=>{
588+
if(isDirtyRef.current === isDirty) return;
589+
587590
isDirtyRef.current = isDirty;
588591
if(qtState.params.is_query_tool) {
589592
setPanelTitle(qtPanelDocker, qtPanelId, null, qtState, isDirty);

web/pgadmin/tools/sqleditor/static/js/components/QueryToolConstants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const QUERY_TOOL_EVENTS = {
2929
TRIGGER_GRAPH_VISUALISER: 'TRIGGER_GRAPH_VISUALISER',
3030
TRIGGER_SELECT_ALL: 'TRIGGER_SELECT_ALL',
3131
TRIGGER_SAVE_QUERY_TOOL_DATA: 'TRIGGER_SAVE_QUERY_TOOL_DATA',
32+
TRIGGER_GET_QUERY_CONTENT: 'TRIGGER_GET_QUERY_CONTENT',
3233

3334
COPY_DATA: 'COPY_DATA',
3435
SET_LIMIT_VALUE: 'SET_LIMIT_VALUE',

web/pgadmin/tools/sqleditor/static/js/components/sections/Query.jsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ import ConfirmExecuteQueryContent from '../dialogs/ConfirmExecuteQueryContent';
2323
import usePreferences from '../../../../../../preferences/static/js/store';
2424
import { getTitle } from '../../sqleditor_title';
2525
import PropTypes from 'prop-types';
26-
import { useApplicationState, getToolData } from '../../../../../../settings/static/ApplicationStateProvider';
26+
import { useApplicationState } from '../../../../../../settings/static/ApplicationStateProvider';
2727
import { useDelayDebounce } from '../../../../../../static/js/custom_hooks';
2828

29-
3029
async function registerAutocomplete(editor, api, transId) {
3130
editor.registerAutocomplete((context, onAvailable)=>{
3231
return new Promise((resolve, reject)=>{
@@ -64,7 +63,7 @@ export default function Query({onTextSelect, setQtStatePartial}) {
6463
const layoutDocker = useContext(LayoutDockerContext);
6564
const lastCursorPos = React.useRef();
6665
const pgAdmin = usePgAdmin();
67-
const {saveToolData, isSaveToolDataEnabled} = useApplicationState();
66+
const {saveToolData, isSaveToolDataEnabled, getQueryToolContent, deleteToolData} = useApplicationState();
6867
const preferencesStore = usePreferences();
6968
const modalId = MODAL_DIALOGS.QT_CONFIRMATIONS;
7069

@@ -160,15 +159,16 @@ export default function Query({onTextSelect, setQtStatePartial}) {
160159
}
161160
};
162161

163-
const warnReloadFile = (fileName, sqlId, storage=null)=>{
162+
const warnReloadFile = (fileName, storage=null)=>{
164163
queryToolCtx.modal.confirm(
165164
gettext('Reload file?'),
166165
gettext('The file has been modified by another program. Do you want to reload it and loose changes made in pgadmin?'),
167166
function() {
168167
eventBus.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, fileName);
168+
deleteToolData();
169169
},
170170
function() {
171-
eventBus.fireEvent(QUERY_TOOL_EVENTS.LOAD_SQL_FROM_LOCAL_STORAGE, sqlId);
171+
eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_GET_QUERY_CONTENT);
172172
eventBus.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE_DONE, fileName, true, storage);
173173
}
174174
);
@@ -244,6 +244,7 @@ export default function Query({onTextSelect, setQtStatePartial}) {
244244
focus && editor.current?.focus();
245245
editor.current?.setValue(value, !queryToolCtx.params.is_query_tool);
246246
});
247+
247248
eventBus.registerListener(QUERY_TOOL_EVENTS.TRIGGER_QUERY_CHANGE, ()=>{
248249
change();
249250
});
@@ -283,10 +284,12 @@ export default function Query({onTextSelect, setQtStatePartial}) {
283284
setSaveQtData(true);
284285
});
285286

286-
eventBus.registerListener(QUERY_TOOL_EVENTS.LOAD_SQL_FROM_LOCAL_STORAGE, (sqlId)=>{
287-
let sqlValue = getToolData(sqlId);
288-
if (sqlValue) {
287+
eventBus.registerListener(QUERY_TOOL_EVENTS.TRIGGER_GET_QUERY_CONTENT, async ()=>{
288+
let sqlValue = await getQueryToolContent();
289+
if(sqlValue){
289290
eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_SET_SQL, sqlValue);
291+
// call delete appplication state api
292+
deleteToolData();
290293
}
291294
});
292295
}, []);

web/pgadmin/tools/sqleditor/static/js/show_query_tool.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ export function showERDSqlTool(parentData, erdSqlId, queryToolTitle, queryToolMo
114114
launchQueryTool(queryToolMod, transId, gridUrl, queryToolTitle, {});
115115
}
116116

117-
export function relaunchSqlTool(connectionInfo, sqlId){
117+
export function relaunchSqlTool(connectionInfo, toolDataId){
118118
let browserPref = usePreferences.getState().getPreferencesForModule('browser');
119119
let parentData = {
120120
server_group: {
@@ -135,7 +135,7 @@ export function relaunchSqlTool(connectionInfo, sqlId){
135135
const qtUrl = generateUrl(transId, parentData, null);
136136
const title = getTitle(pgAdmin, browserPref, parentData, false, connectionInfo.server_name, connectionInfo.database_name, connectionInfo.role || connectionInfo.user);
137137
launchQueryTool(pgWindow.pgAdmin.Tools.SQLEditor, transId, qtUrl, title, {
138-
sql_id: sqlId,
138+
toolDataId: toolDataId,
139139
...connectionInfo,
140140
});
141141

0 commit comments

Comments
 (0)