Load, and save the files in the Query Editor.

Also, the changes done by Ashesh to resolved few issue with the file
manager in 'Select' mode.
This commit is contained in:
Surinder Kumar 2016-05-14 15:29:03 +05:30 committed by Ashesh Vashi
parent 4dc7f84761
commit 1aeab98a2b
5 changed files with 1023 additions and 657 deletions

View File

@ -1156,3 +1156,12 @@ form[name="change_password_form"] .help-block {
height: 32px;
padding-left: 5px;
}
/* Overriding the css for the dropzone */
.dropzone .dz-preview .dz-progress {
height: initial;
}
.dropzone .dz-preview .dz-progress .dz-upload {
bottom: initial;
}

View File

@ -17,6 +17,9 @@ body {
<div class="sql-editor" data-trans-id="{{ uniqueId }}">
<div id="btn-toolbar" class="pg-prop-btn-group" role="toolbar" aria-label="">
<div class="btn-group" role="group" aria-label="">
<button id="btn-load-file" type="button" class="btn btn-default btn-load-file" title="{{ _('Open File') }}">
<i class="fa fa-folder-open-o" aria-hidden="true"></i>
</button>
<button id="btn-save" type="button" class="btn btn-default" title="{{ _('Save') }}" disabled>
<i class="fa fa-floppy-o" aria-hidden="true"></i>
</button>

View File

@ -13,6 +13,7 @@ MODULE_NAME = 'sqleditor'
import json
import pickle
import random
import os
from flask import Response, url_for, render_template, session, request
from flask.ext.babel import gettext
from flask.ext.security import login_required
@ -21,7 +22,13 @@ from pgadmin.utils.ajax import make_json_response, bad_request, success_return,
from pgadmin.utils.driver import get_driver
from config import PG_DEFAULT_DRIVER
from pgadmin.tools.sqleditor.command import QueryToolCommand
from pgadmin.utils import get_storage_directory
# import unquote from urlib for python2.x and python3.x
try:
from urllib import unquote
except Exception as e:
from urllib.parse import unquote
# Async Constants
ASYNC_OK = 1
@ -44,7 +51,7 @@ class SqlEditorModule(PgAdminModule):
A module class for SQL Grid derived from PgAdminModule.
"""
LABEL = "SQL Editor"
LABEL = gettext("SQL Editor")
def get_own_menuitems(self):
return {}
@ -949,3 +956,87 @@ def is_begin_required(query):
return True
return True
@blueprint.route('/load_file/', methods=["PUT", "POST"])
@login_required
def load_file():
"""
This function gets name of file from request data
reads the data and sends back in reponse
"""
if request.data:
file_data = json.loads(request.data.decode())
# retrieve storage directory path
storage_manager_path = get_storage_directory()
# generate full path of file
file_path = os.path.join(
storage_manager_path,
unquote(file_data['file_name'])
)
file_data = None
# read file
try:
with open(file_path, 'r') as myfile:
file_data = myfile.read()
except IOError as e:
# we don't want to expose real path of file
# so only show error message.
if e.strerror == 'Permission denied':
err_msg = "Error: {0}".format(e.strerror)
else:
err_msg = "Error: {0}".format(e.strerror)
return internal_server_error(errormsg=err_msg)
except Exception as e:
err_msg = "Error: {0}".format(e.strerror)
return internal_server_error(errormsg=err_msg)
return make_json_response(
data={
'status': True, 'result': file_data,
}
)
@blueprint.route('/save_file/', methods=["PUT", "POST"])
@login_required
def save_file():
"""
This function retrieves file_name and data from request.
and then save the data to the file
"""
if request.data:
file_data = json.loads(request.data.decode())
# retrieve storage directory path
storage_manager_path = get_storage_directory()
# generate full path of file
file_path = os.path.join(
storage_manager_path,
unquote(file_data['file_name'])
)
file_content = file_data['file_content']
file_data = None
# write to file
try:
with open(file_path, 'w') as output_file:
output_file.write(file_content)
except IOError as e:
if e.strerror == 'Permission denied':
err_msg = "Error: {0}".format(e.strerror)
else:
err_msg = "Error: {0}".format(e.strerror)
return internal_server_error(errormsg=err_msg)
except Exception as e:
err_msg = "Error: {0}".format(e.strerror)
return internal_server_error(errormsg=err_msg)
return make_json_response(
data={
'status': True,
}
)

View File

@ -3,7 +3,7 @@ define(
'codemirror/mode/sql/sql', 'codemirror/addon/selection/mark-selection', 'codemirror/addon/selection/active-line',
'codemirror/addon/fold/foldgutter', 'codemirror/addon/fold/foldcode', 'codemirror/addon/fold/pgadmin-sqlfoldcode',
'backgrid.select.all', 'backbone.paginator', 'backgrid.paginator', 'backgrid.filter',
'bootstrap', 'pgadmin.browser', 'wcdocker'],
'bootstrap', 'pgadmin.browser', 'wcdocker', 'pgadmin.file_manager'],
function($, _, alertify, pgAdmin, Backbone, Backgrid, CodeMirror) {
// Some scripts do export their object in the window only.
@ -143,6 +143,7 @@ define(
// Bind all the events
events: {
"click .btn-load-file": "on_file_load",
"click #btn-save": "on_save",
"click #btn-add-row": "on_add",
"click #btn-filter": "on_show_filter",
@ -641,7 +642,20 @@ define(
},
do_not_close_menu: function(ev) {
ev.stopPropagation();
}
},
// callback function for load file button click.
on_file_load: function() {
var self = this;
// Trigger the save signal to the SqlEditorController class
self.handler.trigger(
'pgadmin-sqleditor:button:load_file',
self,
self.handler
);
},
});
/* Defining controller class for data grid, which actually
@ -683,11 +697,22 @@ define(
self.transId = self.container.data('transId');
self.gridView.editor_title = editor_title;
self.gridView.current_file = undefined;
// Render the header
self.gridView.render();
// Listen to the file manager button events
pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:select_file', self._select_file_handler, self);
pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:create_file', self._save_file_handler, self);
// Listen to the codemirror on text change event
// only in query editor tool
if (self.is_query_tool)
self.gridView.query_tool_obj.on('change', self._on_query_change, self);
// Listen on events come from SQLEditorView for the button clicked.
self.on('pgadmin-sqleditor:button:load_file', self._load_file, self);
self.on('pgadmin-sqleditor:button:save', self._save, self);
self.on('pgadmin-sqleditor:button:addrow', self._add, self);
self.on('pgadmin-sqleditor:button:show_filter', self._show_filter, self);
@ -1297,12 +1322,34 @@ define(
/* This function will fetch the list of changed models and make
* the ajax call to save the data into the database server.
* and will open save file dialog conditionally.
*/
_save: function() {
var self = this,
data = [],
save_data = true;
// Open save file dialog if query tool
if (self.is_query_tool) {
var current_file = self.gridView.current_file;
if (!_.isUndefined(current_file)) {
self._save_file_handler(current_file);
}
else {
// provide custom option to save file dialog
var params = {
'supported_types': ["*", "sql"],
'dialog_type': 'create_file',
'dialog_title': 'Save File',
'btn_primary': 'Save'
}
pgAdmin.FileManager.init();
pgAdmin.FileManager.show_dialog(params);
}
return;
}
$("#btn-save").prop('disabled', true);
if (self.changedModels.length == 0)
return;
@ -1395,6 +1442,87 @@ define(
}
},
// load select file dialog
_load_file: function() {
var params = {
'supported_types': ["sql"], // file types allowed
'dialog_type': 'select_file' // open select file dialog
}
pgAdmin.FileManager.init();
pgAdmin.FileManager.show_dialog(params);
},
// read file data and return as response
_select_file_handler: function(e) {
var self = this;
data = {
'file_name': e
}
// Make ajax call to load the data from file
$.ajax({
url: "{{ url_for('sqleditor.index') }}" + "load_file/",
method: 'POST',
async: false,
contentType: "application/json",
data: JSON.stringify(data),
success: function(res) {
if (res.data.status) {
self.gridView.query_tool_obj.setValue(res.data.result);
self.gridView.current_file = e;
}
},
error: function(e) {
var errmsg = $.parseJSON(e.responseText).errormsg;
alertify.error(errmsg);
}
});
},
// read data from codemirror and write to file
_save_file_handler: function(e) {
var self = this;
data = {
'file_name': e,
'file_content': self.gridView.query_tool_obj.getValue()
}
// Make ajax call to save the data to file
$.ajax({
url: "{{ url_for('sqleditor.index') }}" + "save_file/",
method: 'POST',
async: false,
contentType: "application/json",
data: JSON.stringify(data),
success: function(res) {
if (res.data.status) {
alertify.success('{{ _('File saved successfully.') }}');
self.gridView.current_file = e;
// disable save button on file save
$("#btn-save").prop('disabled', true);
}
},
error: function(e) {
var errmsg = $.parseJSON(e.responseText).errormsg;
alertify.error(errmsg);
}
});
},
// codemirror text change event
_on_query_change: function(query_tool_obj) {
if(query_tool_obj.getValue().length == 0) {
$("#btn-save").prop('disabled', true);
}
else {
$("#btn-save").prop('disabled', false);
}
},
// This function will run the SQL query and refresh the data in the backgrid.
_refresh: function() {
var self = this;
@ -1696,6 +1824,7 @@ define(
$("#btn-query-dropdown").prop('disabled', disabled);
$("#btn-edit-dropdown").prop('disabled', disabled);
$("#btn-edit").prop('disabled', disabled);
$('#btn-load-file').prop('disabled', disabled);
},
// This function will fetch the sql query from the text box