public inbox for [email protected]  
help / color / mirror / Atom feed
From: Surinder Kumar <[email protected]>
To: pgadmin-hackers <[email protected]>
Subject: Re: [pgAdmin4][Patch]: File Manager & Backform FileControl
Date: Thu, 12 May 2016 00:18:27 +0530
Message-ID: <CAM5-9D9jr0E9bsE-_exx-XGrmRq9LZSeA+emm8Sbc-jJR_Ny3Q@mail.gmail.com> (raw)
In-Reply-To: <CAM5-9D_ZZ5MFX1xiiUa0k_oo12+U7KXBQ4fhZjz_u0_CDNH2dQ@mail.gmail.com>
References: <CAM5-9D8GX9gNZp95K11rfnpnn4msEH=F6hhZNpBE_WLX46vicg@mail.gmail.com>
	<CACCA4P22BrRBfxTvSRYaPb_VaOA+8HbNLkZDM=w-H8VXeo6HNQ@mail.gmail.com>
	<CACCA4P3s_TAbNP+piWawJA7dg1eS194MC0RGoHh461e1=cUAWw@mail.gmail.com>
	<CAM5-9D-KihU=fqFQ9jV9tDw83cyQnVYZ71UYQoUbLi4C1vVUuA@mail.gmail.com>
	<CAM5-9D8n54WPdpP-H_hN9-X0rxT-vhu4Y6rqJCf7FaCxuBDWAg@mail.gmail.com>
	<CAM5-9D_ZZ5MFX1xiiUa0k_oo12+U7KXBQ4fhZjz_u0_CDNH2dQ@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi,

PFA updated patch with following issues fixed:
1. not listing files based on default file type selected.
2. load css file using 'get_own_stylesheets' method instead of loading from
'base.html'.
3. setting custom dialog title and button not working.

On Wed, May 11, 2016 at 3:03 PM, Surinder Kumar <
[email protected]> wrote:

>
> ---------- Forwarded message ----------
> From: Surinder Kumar <[email protected]>
> Date: Tue, May 10, 2016 at 11:43 PM
> Subject: Re: [pgadmin-hackers][pgAdmin4][Patch]: File Manager & Backform
> FileControl
> To: Neel Patel <[email protected]>
> Cc: pgadmin-hackers <[email protected]>
>
>
> Hi,
>
> Please find updated path with couple of review comments given by Ashesh
> Vashi.
> 1. Add variable *STORAGE_DIR* in configuration settings which decides the
> directory to list when *File manager* is opens, previously
> we have provided this option in preferences which is removed due to
> security issues.
> 2. List all available Volumes by default when *STORAGE_DIR *is set to
> empty for *Windows* platform.
> 3. Also, added support to allow user to provide
> *Dialog title and custom name for primary(OK) button,*
>
> Usage:
>
> 1. Set variable *STORAGE_DIR *to some value in config.py.
> 2. Import it in your module as following:
> *   import config*
> *   config.**STORAGE_DIR*
>
> *Usage*: Backform FilleControl
>
> schema:[{
>   id: 'select_file', label: '{{ _('Select File')}}',
>   type: 'text', *control*: *Backform.FileControl*,
>   *dialog_type: '*select_file*'*, *supp_types: [*'*', 'pdf', 'text',
> 'patch', 'py'*],*
> *  dialog_title: '*Title to appear on dialog*", *
> *  btn_primary: '*Save File*'*
> }]
>
> Please review the patch.
>
> On Wed, May 4, 2016 at 6:35 PM, Surinder Kumar <
> [email protected]> wrote:
>
>> Hi
>>
>> PFA updated patch with resolved review comments.
>>
>> On Thu, Apr 28, 2016 at 6:39 PM, Neel Patel <[email protected]>
>> wrote:
>>
>>> Hi Surinder,
>>>
>>> Please find additional comments as below.
>>>
>>> 1.  In Windows OS, when we try to open the dialog with default
>>> preference value then it gives error as below.
>>>
>>> 2016-04-28 13:07:44,716: ERROR  pgadmin:        Exception on
>>> /file_manager/filemanager/2530270/ [POST]
>>> Traceback (most recent call last):
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask\app.py",
>>> line 1817, in wsgi_app
>>>     response = self.full_dispatch_request()
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask\app.py",
>>> line 1477, in full_dispatch_request
>>>     rv = self.handle_user_exception(e)
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask\app.py",
>>> line 1381, in handle_user_exception
>>>     reraise(exc_type, exc_value, tb)
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask\app.py",
>>> line 1475, in full_dispatch_request
>>>     rv = self.dispatch_request()
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask\app.py",
>>> line 1461, in dispatch_request
>>>     return self.view_functions[rule.endpoint](**req.view_args)
>>>   File "C:\Projects\venv_python_2_7\Lib\site-packages\flask_login.py",
>>> line 758, in decorated_view
>>>     return func(*args, **kwargs)
>>>   File "C:\Projects\pgadmin4\web\pgadmin\misc\file_manager\__init__.py",
>>> line 629, in file_manager
>>>     return getattr(myFilemanager, mode)(**kwargs)
>>>   File "C:\Projects\pgadmin4\web\pgadmin\misc\file_manager\__init__.py",
>>> line 421, in getfolder
>>>     filelist = self.list_filesystem(dir, path, trans_data, file_type)
>>>   File "C:\Projects\pgadmin4\web\pgadmin\misc\file_manager\__init__.py",
>>> line 331, in list_filesystem
>>>     for f in sorted(os.listdir(orig_path)):
>>> WindowsError: [Error 161] The specified path is invalid: '//*.*'
>>>
>>> Now the default path will always be the users directory. I have used *os.path.expanduser('~')
>> *which prints user directory. It works for all operating systems.
>>
>>>
>>> 2. Folder having write only permission should not allow to read the
>>> directory. Same way read only permission folder should not allow to create
>>> the folder.     Currently it gives below error.
>>>
>>>    PermissionError: [Errno 13] Permission denied:
>>> '/home/neel/Projects/pgadmin4_file_manager/write_only_premission/'
>>>
>> Fixed.
>>
>>>
>>> 3. In Windows OS, when we open the file manager dialog, no directories
>>> listed though we have directories in the folder. Due to that we are not
>>> able to
>>>     test all the functionality in windows. Once we fix this issue then
>>> we test all the functionality in windows OS.
>>>
>>>    We debug the issue and found that issue is with the json response
>>> which includes the HTML tags.
>>>
>> Fixed. It still have issues in very older browsers. I will fix it.
>>
>>>
>>> 4. In Windows OS, file manager dialog have issue with layout. We are
>>> getting some margin at top before buttons.
>>>
>> Fixed.
>>
>>>
>>> 5. When we give any special characters to folder name that it gives
>>> error saying "Folder does not exist".
>>>     Same is applicable when we give dialog_type to create_file
>>>
>> Fixed.
>>
>>>
>>> 6. In create_file mode, after giving the filename it should display the
>>> name of the file to text control.
>>>
>> Fixed.
>>
>>>
>>> 7. In create_file mode, when user gives the filename and click on the
>>> any blank area of dialog then name is getting cleared.
>>>
>> Fixed.
>>
>>>
>>> 8. When we upload the new file through file manager then it is not
>>> showing in the list though we have selected "All files" options.
>>>
>> Fixed.
>>
>>>
>>> 9. When we rename the folder in "Table mode" then font-family gets
>>> changed. It is not happened in "Grid" mode.
>>>
>> Fixed.
>>
>>>
>>> 10. When we try to download the file then it goes into loop and opens up
>>> 20-30 dialogs at the same time.
>>>
>> Fixed.
>>
>>>
>>> 11. "Rename" button is enabled even though we have not selected the
>>> files/folder to rename and when we click on the "Rename" button it gives
>>> below
>>>      error.
>>>
>>>     TypeError: orig_value is undefined
>>>
>> Fixed.
>>
>>> 12. "Delete" button is enabled even though we have not selected the
>>> files/folder to delete and when we click on the "Delete" button it gives
>>> below error.
>>>      TypeError: path is undefined
>>>
>> Fixed.
>>
>>>
>>> Do let us know if you have queries.
>>>
>>> Thanks,
>>> Neel Patel
>>>
>>> On Wed, Apr 27, 2016 at 9:15 PM, Neel Patel <[email protected]
>>> > wrote:
>>>
>>>> Hi Surinder,
>>>>
>>>> I have applied the patch file and below are some observations.
>>>>
>>>>    - When we create the new folder and hit the enter then we are
>>>>    getting the below error.
>>>>
>>>>                   TypeError: argument of type 'NoneType' is not iterable
>>>>
>>>>    - I have just added the new control in "Import" dialog and observed
>>>>    that new control is getting added in new tab called "General". I think it
>>>>    should not create the new "General" tab.
>>>>    - "Select" and "Cancel" buttons font is different then other
>>>>    dialogs.
>>>>
>>>>
>>>> Thanks,
>>>> Neel Patel
>>>>
>>>> On Wed, Apr 27, 2016 at 6:18 PM, Surinder Kumar <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> The patch is for *File Manager and Backform FileControl*.
>>>>>
>>>>> *File Manager:* It allows user to store their files at one place. The
>>>>> user can set path to this directory in preferences which file manger will
>>>>> use.
>>>>>
>>>>> It will be used by various modules of pgAdmin4 such as
>>>>> *import data from file, query tool, backup & recovery tool* so on..
>>>>> It allows user to perform various operations such as:
>>>>>
>>>>>    - File deletion
>>>>>    - File upload
>>>>>    - Create new directory
>>>>>    - File rename
>>>>>    - File download and
>>>>>    - List files & folders in list and grid view.
>>>>>
>>>>> *FileControl: *This control is used with *File Manager. *It can be
>>>>> used for:
>>>>>
>>>>>    - File Selection
>>>>>    - Folder Selection
>>>>>    - File Creation
>>>>>    - Storage Manager Dialog.( it supports all operations listed
>>>>>    above).
>>>>>
>>>>>
>>>>> Usage*:*
>>>>>
>>>>> schema:[{
>>>>>   id: 'select_file', label: '{{ _('Select File')}}',
>>>>>   type: 'text', *control*: *Backform.FileControl*,
>>>>>   *dialog_type: 'select_file'*, *supp_types: ['*', 'pdf', 'text',
>>>>> 'patch', 'py']*
>>>>> }
>>>>>
>>>>> Where:
>>>>>
>>>>>    - *control* - It should be *Backform.FileControl*
>>>>>    - *dialog_type *- the type of dialog to use.
>>>>>    - options can be:  *select_file, select_folder, create_file &
>>>>>    storage_dialog*.
>>>>>    - *supp_types(*not mandatory) - the types of files allowed to show
>>>>>    and upload.
>>>>>
>>>>> Please review the patch and let me know for the review comments.
>>>>>
>>>>>
>>>>> Thanks
>>>>> Surinder Kumar
>>>>>
>>>>>
>>>>> --
>>>>> Sent via pgadmin-hackers mailing list ([email protected])
>>>>> To make changes to your subscription:
>>>>> http://www.postgresql.org/mailpref/pgadmin-hackers
>>>>>
>>>>>
>>>>
>>>
>>
>
>


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] FileManager_v3.patch (204.8K, 3-FileManager_v3.patch)
  download | inline diff:
diff --git a/web/config.py b/web/config.py
index bc67ead..bef213b 100644
--- a/web/config.py
+++ b/web/config.py
@@ -13,6 +13,17 @@
 
 from logging import *
 import os
+import string
+from sys import platform as _platform
+# Checks if platform is Windows
+if _platform == "win32":
+    from ctypes import windll
+
+# uppercase supported in py2, ascii_uppercase supported in py3
+try:
+    letters = string.uppercase
+except Exception:
+    letters = string.ascii_uppercase
 
 ##########################################################################
 # Application settings
@@ -227,6 +238,48 @@ UPGRADE_CHECK_ENABLED = True
 UPGRADE_CHECK_URL = 'http://www.pgadmin.org/versions.json'
 
 ##########################################################################
+# Storage Manager storage url config settings
+# If user sets STORAGE_DIR to empty it will show all volumes if platform
+# is Windows, '/' if it is Linux, Mac or any other unix type system.
+
+# For example:
+# 1. STORAGE_DIR = get_drive("C") or get_drive() # return C:/ by default
+# where C can be any drive character such as "D", "E", "G" etc
+# 2. Set path manually like
+# STORAGE_DIR = "/path/to/directory/"
+##########################################################################
+
+
+def get_drives(drive_name=None):
+    """
+    This is a generic function which returns the default path for storage
+    manager dialog irrespective of any Platform type to list all
+    files and directories.
+    Platform windows:
+    if no path is given, it will list volumes, else list directory
+    Platform unix:
+    it returns path to root directory if no path is specified.
+    """
+    if _platform == "win32":
+        try:
+            drives = []
+            bitmask = windll.kernel32.GetLogicalDrives()
+            for letter in letters:
+                if bitmask & 1:
+                    drives.append(letter)
+                bitmask >>= 1
+            if (drive_name != '' and drive_name is not None and
+               drive_name in drives):
+                return "{0}{1}".format(drive_name, ':/')
+            else:
+                return drives  # return drives if no argument is passed
+        except Exception:
+            return 'C:/'
+    else:
+        return '/'
+STORAGE_DIR = "/Users/surinder/Documents/Projects/pgadmin4_test/"
+
+##########################################################################
 # Local config settings
 ##########################################################################
 
diff --git a/web/pgadmin/misc/file_manager/__init__.py b/web/pgadmin/misc/file_manager/__init__.py
new file mode 100644
index 0000000..80d30b4
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/__init__.py
@@ -0,0 +1,819 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+"""Implements File Manager"""
+
+from pgadmin.utils import PgAdminModule
+from flask.ext.babel import gettext
+from flask.ext.security import login_required
+from flask import render_template, Response, session, request as req, url_for
+from pgadmin.utils.ajax import make_json_response
+import random
+import os
+import os.path
+import time
+import simplejson as json
+import string
+import config
+from sys import platform as _platform
+
+# Checks if platform is Windows
+if _platform == "win32":
+    import ctypes
+    file_root = ""
+
+# uppercase supported in py2, ascii_uppercase supported in py3
+try:
+    letters = string.uppercase
+except Exception:
+    letters = string.ascii_uppercase
+
+# import unquote from urlib for python2.x and python3.x
+try:
+    from urllib import unquote
+except Exception as e:
+    from urllib.parse import unquote
+
+
+MODULE_NAME = 'file_manager'
+global transid
+
+path_exists = os.path.exists
+split_path = os.path.split
+encode_json = json.JSONEncoder().encode
+
+
+# utility functions
+# convert bytes type to human readable format
+def sizeof_fmt(num, suffix='B'):
+    for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
+        if abs(num) < 1024.0:
+            return "%3.1f %s%s" % (num, unit, suffix)
+        num /= 1024.0
+    return "%.1f %s%s" % (num, 'Y', suffix)
+
+
+# return size of file
+def getSize(path):
+    st = os.stat(path)
+    return st.st_size
+
+
+def getDriveSize(path):
+    if _platform == "win32":
+        free_bytes = ctypes.c_ulonglong(0)
+        ctypes.windll.kernel32.GetDiskFreeSpaceExW(
+            ctypes.c_wchar_p(path), None, None, ctypes.pointer(free_bytes))
+        return free_bytes.value
+
+
+# split extension for files
+def splitext(path):
+    for ext in ['.tar.gz', '.tar.bz2']:
+        if path.endswith(ext):
+            path, ext = path[:-len(ext)], path[-len(ext):]
+            break
+    else:
+        path, ext = os.path.splitext(path)
+    return ext[1:]
+
+
+# check if file is hidden in windows platform
+def is_folder_hidden(filepath):
+    if _platform == "win32":
+        try:
+            attrs = ctypes.windll.kernel32.GetFileAttributesW(
+                unicode(filepath))
+            assert attrs != -1
+            result = bool(attrs & 2)
+        except (AttributeError, AssertionError):
+            result = False
+        return result
+    return False
+
+
+class FileManagerModule(PgAdminModule):
+    """
+    FileManager lists files and folders and does
+    following operations:
+    - File selection
+    - Folder selection
+    - Open file
+    - Create File
+    and also supports:
+    - Rename file
+    - Delete file
+    - Upload file
+    - Create folder
+    """
+
+    LABEL = gettext("Storage")
+
+    def get_own_javascripts(self):
+        return [
+          {
+            'name': 'pgadmin.file_manager',
+            'path': url_for('file_manager.index') + 'file_manager',
+            'when': None
+          },
+          ]
+
+    def get_own_stylesheets(self):
+        return [
+              url_for('static', filename='css/jquery.dropzone/dropzone.css'),
+              url_for('file_manager.static', filename='css/file_manager.css')
+            ]
+
+    def get_own_menuitems(self):
+        return {
+            'file_items': []
+        }
+
+    def get_file_size_preference(self):
+        return self.file_upload_size
+
+    def register_preferences(self):
+        # Register 'file upload size' preference
+        self.file_upload_size = self.preference.register(
+            'options', 'file_upload_size',
+            gettext("Maximum file upload size(MB)"), 'integer', 50,
+            category_label=gettext('Options')
+            )
+
+# Initialise the module
+blueprint = FileManagerModule(
+    MODULE_NAME,
+    __name__,
+    )
+
+
[email protected]("/")
+@login_required
+def index():
+    """Render the preferences dialog."""
+    return render_template(
+            MODULE_NAME + "/index.html", _=gettext)
+
+
[email protected]("/utility.js")
+@login_required
+def utility():
+    """render the required javascript"""
+    return Response(response=render_template(
+        "file_manager/js/utility.js", _=gettext),
+        status=200,
+        mimetype="application/javascript")
+
+
[email protected]("/file_manager.js")
+@login_required
+def file_manager_js():
+    """render the required javascript"""
+    return Response(response=render_template(
+        "file_manager/js/file_manager.js", _=gettext),
+        status=200,
+        mimetype="application/javascript")
+
+
[email protected]("/en.js")
+@login_required
+def language():
+    """render the required javascript"""
+    return Response(response=render_template(
+        "file_manager/js/languages/en.js", _=gettext),
+        status=200,
+        mimetype="application/javascript")
+
+
[email protected]("/file_manager_config.js")
+@login_required
+def file_manager_config_js():
+    """render the required javascript"""
+    return Response(response=render_template(
+        "file_manager/js/file_manager_config.js", _=gettext),
+        status=200,
+        mimetype="application/javascript")
+
+
[email protected]("/<int:trans_id>/file_manager_config.json")
+@login_required
+def file_manager_config(trans_id):
+    """render the required json"""
+    # trans_id = Filemanager.create_new_transaction()
+    data = Filemanager.get_trasaction_selection(trans_id)
+    return Response(response=render_template(
+        "file_manager/js/file_manager_config.json", _=gettext,
+        data=data),
+        status=200,
+        mimetype="application/json")
+
+
[email protected]("/get_trans_id", methods=["GET", "POST"])
+@login_required
+def get_trans_id():
+    if len(req.data) != 0:
+        configs = json.loads(req.data)
+        trans_id = Filemanager.create_new_transaction(configs)
+        global transid
+        transid = trans_id
+    return make_json_response(
+        data={'fileTransId': transid, 'status': True}
+    )
+
+
[email protected]("/del_trans_id/<int:trans_id>", methods=["GET", "POST"])
+@login_required
+def delete_trans_id(trans_id):
+    Filemanager.release_transaction(trans_id)
+    return make_json_response(
+        data={'status': True}
+    )
+
+
+class Filemanager(object):
+    """FileManager Class."""
+    def __init__(self, trans_id):
+        self.trans_id = trans_id
+        self.patherror = encode_json(
+                {
+                    'Error': gettext('No permission to operate on specified path.'),
+                    'Code': -1
+                }
+            )
+        self.dir = config.STORAGE_DIR
+
+        if isinstance(self.dir, list):
+            self.dir = ""
+
+    @staticmethod
+    def create_new_transaction(params):
+        """
+        It will also create a unique transaction id and
+        store the information into session variable.
+        Args:
+            capabilities: Allow/Disallow user to perform
+            selection, rename, delete etc.
+        """
+
+        # Define configs for dialog types
+        # select file, select folder, create mode
+        fm_type = params['dialog_type']
+        storage_dir = config.STORAGE_DIR
+
+        # It is used in utitlity js to decide to
+        # show or hide select file type options
+        show_volumes = True if (isinstance(storage_dir, list) or
+                                not storage_dir) else False
+        supp_types = allow_upload_files = params['supported_types'] \
+            if 'supported_types' in params else []
+        if fm_type == 'select_file':
+            capabilities = ['select_file', 'rename', 'upload', 'create']
+            supp_types = supp_types
+            files_only = True
+            folders_only = False
+            title = "Select File"
+        elif fm_type == 'select_folder':
+            capabilities = ['select_folder', 'rename', 'create']
+            files_only = False
+            folders_only = True
+            title = "Select Folder"
+        elif fm_type == 'create_file':
+            capabilities = ['select_file', 'rename', 'create']
+            supp_types = supp_types
+            files_only = True
+            folders_only = False
+            title = "Create File"
+        elif fm_type == 'storage_dialog':
+            capabilities = ['select_folder', 'select_file', 'download',
+                            'rename', 'delete', 'upload', 'create']
+            supp_types = supp_types
+            files_only = True
+            folders_only = False
+            title = "Storage Manager"
+
+        # create configs using above configs
+        configs = {
+          "fileroot": "/",
+          "dialog_type": fm_type,
+          "title": title,
+          "upload": {
+              "multiple": True
+          },
+          "capabilities": capabilities,
+          "security": {
+              "uploadPolicy": "",
+              "uploadRestrictions": allow_upload_files
+          },
+          "files_only": files_only,
+          "folders_only": folders_only,
+          "supported_types": supp_types,
+          "platform_type": _platform,
+          "show_volumes": show_volumes
+        }
+
+        # Create a unique id for the transaction
+        trans_id = str(random.randint(1, 9999999))
+
+        if 'fileManagerData' not in session:
+            file_manager_data = dict()
+        else:
+            file_manager_data = session['fileManagerData']
+
+        file_upload_size = blueprint.get_file_size_preference().get()
+        configs['upload']['fileSizeLimit'] = file_upload_size
+        file_manager_data[trans_id] = configs
+        session['fileManagerData'] = file_manager_data
+
+        return trans_id
+
+    @staticmethod
+    def get_trasaction_selection(trans_id):
+        """
+        This method returns the information of unique transaction
+        id from the session variable.
+
+        Args:
+            trans_id: unique transaction id
+        """
+        file_manager_data = session['fileManagerData']
+
+        # Return from the function if transaction id not found
+        if str(trans_id) in file_manager_data:
+            return file_manager_data[str(trans_id)]
+
+    @staticmethod
+    def release_transaction(trans_id):
+        """
+        This method is to remove the information of unique transaction
+        id from the session variable.
+
+        Args:
+            trans_id: unique transaction id
+        """
+        file_manager_data = session['fileManagerData']
+        # Return from the function if transaction id not found
+        if str(trans_id) not in file_manager_data:
+            return make_json_response(data={'status': True})
+
+        # Remove the information of unique transaction id
+        # from the session variable.
+        file_manager_data.pop(str(trans_id), None)
+        session['fileManagerData'] = file_manager_data
+
+        return make_json_response(data={'status': True})
+
+    @staticmethod
+    def list_filesystem(dir, path, trans_data, file_type):
+        """
+        It lists all file and folders within the given
+        directory.
+        """
+        files = {}
+        if (_platform == "win32" and path == '/') and (not dir):
+            import config
+            drives = config.get_drives()
+            for drive in drives:
+                protected = 0
+                path = file_name = "{0}:/".format(drive)
+                try:
+                    drive_size = getDriveSize(path)
+                    drive_size_in_units = sizeof_fmt(drive_size)
+                except:
+                    drive_size = 0
+                protected = 1 if drive_size == 0 else 0
+                files[drive] = {
+                    "Filename": file_name,
+                    "Path": path,
+                    "file_type": 'drive',
+                    "Protected": protected,
+                    "Properties": {
+                        "Date Created": "",
+                        "Date Modified": "",
+                        "Size": drive_size_in_units
+                      }
+                }
+            return files
+
+        orig_path = "{0}{1}".format(dir, path)
+        user_dir = path
+        folders_only = trans_data['folders_only'] if 'folders_only' in \
+            trans_data else ''
+        files_only = trans_data['files_only'] if 'files_only' in \
+            trans_data else ''
+        supported_types = trans_data['supported_types'] \
+            if 'supported_types' in trans_data else []
+
+        orig_path = unquote(orig_path)
+        try:
+            for f in sorted(os.listdir(orig_path)):
+                protected = 0
+                system_path = os.path.join(os.path.join(orig_path, f))
+
+                # continue if file/folder is hidden
+                if (is_folder_hidden(system_path) or f.startswith('.')):
+                    continue
+
+                user_path = os.path.join(os.path.join(user_dir, f))
+                created = time.ctime(os.path.getctime(system_path))
+                modified = time.ctime(os.path.getmtime(system_path))
+                file_extension = str(splitext(system_path))
+
+                # set protected to 1 if no write or read permission
+                if(not os.access(system_path, os.R_OK) or
+                   not os.access(system_path, os.W_OK)):
+                    protected = 1
+
+                # list files only or folders only
+                if os.path.isdir(system_path):
+                    if files_only == 'true':
+                        continue
+                    file_extension = str('dir')
+                    user_path = "{0}/".format(user_path)
+                else:
+                    # filter files based on file_type
+                    if file_type is not None and file_type != "*":
+                        if folders_only or len(supported_types) > 0 and \
+                          file_extension not in supported_types or \
+                          file_type != file_extension:
+                            continue
+
+                # create a list of files and folders
+                files[user_path] = {
+                  "Filename": f,
+                  "Path": user_path,
+                  "file_type": file_extension,
+                  "Protected": protected,
+                  "Properties": {
+                    "Date Created": created,
+                    "Date Modified": modified,
+                    "Size": sizeof_fmt(getSize(system_path))
+                  }
+                }
+        except Exception as e:
+            if e.strerror == gettext('Permission denied'):
+                err_msg = "Error: {0}".format(e.strerror)
+            else:
+                err_msg = "Error: {0}".format(e.strerror)
+            files = {
+              'Code': 0,
+              'err_msg': err_msg
+            }
+        return files
+
+    def validate_request(self, capability):
+        """
+        It validates the capability with the capabilities
+        stored in the session
+        """
+        trans_data = Filemanager.get_trasaction_selection(self.trans_id)
+        return False if capability not in trans_data['capabilities'] else True
+
+    def getinfo(self, path=None, getsize=True, name=None, req=None):
+        """
+        Returns a JSON object containing information
+        about the given file.
+        """
+
+        path = unquote(path)
+        orig_path = "{0}{1}".format(self.dir, path)
+        user_dir = path
+        thefile = {
+            'Filename': split_path(orig_path)[-1],
+            'File Type': '',
+            'Path': user_dir,
+            'Error': '',
+            'Code': 0,
+            'Properties': {
+                    'Date Created': '',
+                    'Date Modified': '',
+                    'Width': '',
+                    'Height': '',
+                    'Size': ''
+                }
+            }
+
+        if not path_exists(orig_path):
+            thefile['Error'] = gettext('File does not exist.')
+            return (encode_json(thefile), None, 'application/json')
+
+        if split_path(user_dir)[-1] == '/':
+            thefile['File Type'] = 'Directory'
+        else:
+            thefile['File Type'] = splitext(user_dir)
+
+        created = time.ctime(os.path.getctime(orig_path))
+        modified = time.ctime(os.path.getmtime(orig_path))
+
+        thefile['Properties']['Date Created'] = created
+        thefile['Properties']['Date Modified'] = modified
+        thefile['Properties']['Size'] = sizeof_fmt(getSize(orig_path))
+
+        return thefile
+
+    def getfolder(self, path=None, file_type="", name=None, req=None):
+        """
+        Returns files and folders in give path
+        """
+        trans_data = Filemanager.get_trasaction_selection(self.trans_id)
+        dir = self.dir
+        filelist = self.list_filesystem(dir, path, trans_data, file_type)
+        return filelist
+
+    def rename(self, old=None, new=None, req=None):
+        """
+        Rename file or folder
+        """
+        if not self.validate_request('rename'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        # check if it's dir
+        if old[-1] == '/':
+            old = old[:-1]
+
+        # extract filename
+        oldname = split_path(old)[-1]
+        path = str(old)
+        path = split_path(path)[0]  # extract path
+
+        if not path[-1] == '/':
+            path += '/'
+
+        # newname = encode_urlpath(new)
+        newname = new
+        newpath = path + newname
+
+        # make system old path
+        oldpath_sys = "{0}{1}".format(dir, old)
+        newpath_sys = "{0}{1}".format(dir, newpath)
+
+        error_msg = gettext('Renamed Successfully.')
+        code = 1
+        try:
+            os.rename(oldpath_sys, newpath_sys)
+            code = 0
+        except Exception as e:
+            error_msg = "{0} - {1}".format(
+                gettext('There was an error renaming the file.'),
+                str(e))
+
+        result = {
+            'Old Path': old,
+            'Old Name': oldname,
+            'New Path': newpath,
+            'New Name': newname,
+            'Error': error_msg,
+            'Code': code
+        }
+
+        return result
+
+    def delete(self, path=None, req=None):
+        """
+        Delete file or folder
+        """
+        if not self.validate_request('delete'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        orig_path = "{0}{1}".format(dir, path)
+
+        err_msg = ''
+        code = 1
+        try:
+            if os.path.isdir(orig_path):
+                os.rmdir(orig_path)
+                code = 0
+            else:
+                os.remove(orig_path)
+                code = 0
+        except Exception as e:
+            err_msg = "Error: {0}".format(e.strerror)
+
+        result = {
+            'Path': path,
+            'Error': err_msg,
+            'Code': code
+        }
+
+        return result
+
+    def add(self, req=None):
+        """
+        File upload functionality
+        """
+        if not self.validate_request('upload'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        err_msg = ''
+        code = 1
+        try:
+            path = req.form.get('currentpath')
+            orig_path = "{0}{1}".format(dir, path)
+            thefile = req.files['newfile']
+            newName = '{0}{1}'.format(orig_path, thefile.filename)
+
+            with open(newName, 'wb') as f:
+                f.write(thefile.read())
+            code = 0
+        except Exception as e:
+            err_msg = "Error: {0}".format(e.strerror)
+
+        result = {
+            'Path': path,
+            'Name': newName,
+            'Error': err_msg,
+            'Code': code
+        }
+
+        return result
+
+    def is_file_exist(self, path, name, req=None):
+        """
+        Checks whether given file exists or not
+        """
+        dir = self.dir
+        err_msg = ''
+        code = 1
+        try:
+            orig_path = "{0}{1}".format(dir, path)
+            newName = '{0}{1}'.format(orig_path, name)
+            if os.path.exists(newName):
+                code = 0
+            else:
+                code = 1
+        except Exception as e:
+            err_msg = "Error: {0}".format(e.strerror)
+
+        result = {
+            'Path': path,
+            'Name': newName,
+            'Error': err_msg,
+            'Code': code
+        }
+
+        return result
+
+    def create_file(self, path, name, req=None):
+        """
+        Create new file functionality
+        """
+        if not self.validate_request('create'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        err_msg = ''
+        code = 1
+        try:
+            orig_path = "{0}{1}".format(dir, path)
+            newName = '{0}{1}'.format(orig_path, name)
+            if not os.path.exists(newName):
+                open(newName, 'w')
+                code = 0
+            else:
+                err_msg = gettext("Error: File already exists")
+        except Exception as e:
+            err_msg = "Error: {0}".format(e.strerror)
+
+        result = {
+            'Path': path,
+            'Name': newName,
+            'Error': err_msg,
+            'Code': code
+        }
+
+        return result
+
+    @staticmethod
+    def getNewName(dir, path, newName, count=1):
+        """
+        Utility to provide new name for folder if file
+        with same name already exists
+        """
+        last_char = newName[-1]
+        tnewPath = dir + '/' + path + newName + '_'+str(count)
+        if last_char == 'r' and not path_exists(tnewPath):
+            return tnewPath, newName
+        else:
+            last_char = int(tnewPath[-1]) + 1
+            newPath = dir + '/' + path + newName + '_'+str(last_char)
+            if path_exists(newPath):
+                count += 1
+                return Filemanager.getNewName(dir, path, newName, count)
+            else:
+                return newPath, newName
+
+    def addfolder(self, path, name):
+        """
+        Functionality to create new folder
+        """
+        if not self.validate_request('create'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        newName = name
+        if dir != "":
+            newPath = dir + '/' + path + newName + '/'
+        else:
+            newPath = path + newName + '/'
+
+        err_msg = ''
+        code = 1
+        if not path_exists(newPath):
+            try:
+                os.mkdir(newPath)
+                code = 0
+            except Exception as e:
+                err_msg = "Error: {0}".format(e.strerror)
+        else:
+            newPath, newName = self.getNewName(dir, path, newName)
+            try:
+                os.mkdir(newPath)
+                code = 0
+            except Exception as e:
+                err_msg = "Error: {0}".format(e.strerror)
+
+        result = {
+            'Parent': path,
+            'Name': newName,
+            'Error': err_msg,
+            'Code': code
+        }
+
+        return result
+
+    def download(self, path=None, name=None, req=None):
+        """
+        Functionality to download file
+        """
+        if not self.validate_request('download'):
+            return {
+             'Error': gettext('Not allowed'),
+             'Code': 1
+            }
+
+        dir = self.dir
+        orig_path = "{0}{1}".format(dir, path)
+        name = path.split('/')[-1]
+        content = open(orig_path, 'r')
+        resp = Response(content)
+        resp.headers['Content-Disposition'] = 'attachment; filename='+name
+        return resp
+
+
[email protected]("/filemanager/<int:trans_id>/", methods=["GET", "POST"])
+@login_required
+def file_manager(trans_id):
+    """
+    It is the common function for every call which is made
+    and takes function name from post request and calls it.
+    It gets unique transaction id from post request and
+    rotate it into Filemanager class.
+    """
+    myFilemanager = Filemanager(trans_id)
+    mode = ''
+    kwargs = {}
+    if req.method == 'POST':
+        if req.files:
+            mode = 'add'
+            kwargs = {'req': req}
+        else:
+            kwargs = json.loads(req.data)
+            kwargs['req'] = req
+            mode = kwargs['mode']
+            del kwargs['mode']
+    elif req.method == 'GET':
+        kwargs = {
+          'path': req.args['path'],
+          'name': req.args['name'] if 'name' in req.args else ''
+        }
+        mode = req.args['mode']
+
+    try:
+        func = getattr(myFilemanager, mode)
+        res = func(**kwargs)
+        return make_json_response(data={'result': res, 'status': True})
+    except Exception:
+        return getattr(myFilemanager, mode)(**kwargs)
diff --git a/web/pgadmin/misc/file_manager/static/css/file_manager.css b/web/pgadmin/misc/file_manager/static/css/file_manager.css
new file mode 100755
index 0000000..cebed17
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/static/css/file_manager.css
@@ -0,0 +1,660 @@
+/*
+ * CSS for Storage Manager Dialog
+ */
+
+.file_manager #uploader {
+  padding: 2px 4px;
+  border-width: 1px;
+  display: block;
+  text-align: right;
+  height: auto;
+  min-height:30px;
+  max-height: 80px;
+  overflow: hidden;
+  border-bottom: 1px;
+  top: 35px;
+}
+
+#uploader h1 {
+  font-size: 14px;
+  margin: 0;
+  margin-left: 5px;
+  padding: 0;
+  display: block;
+  float: left;
+  text-align: left;
+  line-height:1.9em;
+  text-shadow:1px 1px 0px #ffffff;
+}
+
+#uploader h1 b {
+  font-weight: normal;
+}
+
+.uploadresponse {
+  display: none;
+}
+
+.fileinfo {
+  min-width: 100px;
+  overflow: auto;
+  /* no margin or border allowed */
+}
+
+.fileinfo #contents li.selected, .fileinfo #contents tbody tr.selected {
+  background: #D9EDF7;
+}
+
+.fileinfo #contents li .fm_file_rename,
+.fileinfo table#contents tr td:first-child input.fm_file_rename {
+  display: none;
+  width: 80px;
+  margin: 0 auto;
+  text-align: center;
+  height: 17px;
+}
+
+.fileinfo table#contents tr td p {
+  display: inline-block;
+  margin-bottom: 0;
+}
+
+.fileinfo table#contents tr td p {
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+.fileinfo > h1 {
+  font-size: 16px;
+  margin: 100px auto;
+}
+
+#toolbar {
+  display: block;
+  clear: left;
+  margin: 50px auto;
+}
+
+.fm_folder {
+  font-size: xx-large !important;
+  color: rgb(255, 204, 0);
+}
+
+.fm_drive {
+  font-size: xx-large !important;
+  color: darkgray;
+}
+
+.fm_file {
+  font-size: xx-large !important;
+}
+
+.file_manager button {
+  background-color: #C0C0C0;
+}
+
+.file_manager h1 {
+  font-size: medium;
+}
+
+/** Input file Replacement */
+.file-input-container {
+  margin:0;
+  position:relative;
+  top:0px;
+  width:215px;
+  height:32px;
+  overflow: hidden;
+}
+
+/** Firefox hack */
+@-moz-document url-prefix() {
+  .file-input-container  {
+    top:11px;
+    width:255px;
+  }
+}
+
+/** Opera hack */
+x:-o-prefocus, .file-input-container {top:16px;width:198px;}
+
+.newfile {
+  position: absolute;
+  top:0;
+  left: 3px;
+  right:0;
+  width: 152px;
+  height:23px;
+  opacity:0;  filter: alpha(opacity=0);
+  cursor: pointer;
+  border:1px solid blue;
+}
+
+.alt-fileinput {
+  display: inline;
+  wrap: no-wrap;
+}
+
+.filepath {
+  background-color: #F4F1ED;
+  border: 1px solid #dcdcdc;
+  margin: 0;
+  padding: 0.1em 0.3em;
+  line-height: 1.7em;
+  -webkit-border-top-left-radius: 6px;
+  -webkit-border-bottom-left-radius: 6px;
+  -moz-border-radius-topleft: 6px;
+  -moz-border-radius-bottomleft: 6px;
+  border-top-left-radius: 6px;
+  border-bottom-left-radius: 6px;
+}
+
+@-moz-document url-prefix() {
+  .filepath {
+    padding:0.2em 0.3em;
+  }
+}
+
+/** Input file Replacement - end */
+.file_listing #contents.grid {
+  padding: 25px;
+  text-align: left;
+}
+
+.file_listing #contents.grid li {
+  display: block;
+  float: left;
+  width: 100px;
+  min-height: 80px;
+  text-align: center;
+  overflow: hidden;
+  margin-bottom: 10px;
+  -webkit-border-radius: 2px;
+  -moz-border-radius: 2px;
+  border-radius: 2px;
+}
+
+div.clip {
+  width: 30px;
+  height: 30px;
+  margin: 10px auto;
+  overflow: hidden;
+}
+
+.file_listing #contents.grid p {
+  display: block;
+  text-align: center;
+  margin-bottom: 10px;
+}
+
+.file_listing #contents.list {
+  width: 100%;
+}
+
+.file_listing #contents.list th,
+.file_listing #contents.list td {
+  text-align: left;
+  padding: 6px;
+  white-space: nowrap;
+}
+
+.file_listing #contents.list thead {
+  background: rgb(244,241,237); /* Old browsers */
+  background: -moz-linear-gradient(top, rgba(244,241,237,1) 0%, rgba(214,212,209,1) 100%); /* FF3.6+ */
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(244,241,237,1)), color-stop(100%,rgba(214,212,209,1))); /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, rgba(244,241,237,1) 0%,rgba(214,212,209,1) 100%); /* Chrome10+,Safari5.1+ */
+  background: -o-linear-gradient(top, rgba(244,241,237,1) 0%,rgba(214,212,209,1) 100%); /* Opera 11.10+ */
+  background: -ms-linear-gradient(top, rgba(244,241,237,1) 0%,rgba(214,212,209,1) 100%); /* IE10+ */
+  background: linear-gradient(to bottom, rgba(244,241,237,1) 0%,rgba(214,212,209,1) 100%); /* W3C */
+  border-bottom: 1px solid #ccc;
+  display: inline-block;
+  width: 100%;
+}
+
+.file_listing #contents.list th {
+  font-weight: bold;
+  cursor: pointer;
+}
+
+.file_listing #contents.list th.tablesorter-headerAsc,
+.file_listing #contents.list th.tablesorter-headerDesc {
+  background: rgb(214,212,209); /* Old browsers */
+  background: -moz-linear-gradient(top, rgba(214,212,209,1) 0%, rgba(244,241,237,1) 100%); /* FF3.6+ */
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(214,212,209,1)), color-stop(100%,rgba(244,241,237,1))); /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, rgba(214,212,209,1) 0%,rgba(244,241,237,1) 100%); /* Chrome10+,Safari5.1+ */
+  background: -o-linear-gradient(top, rgba(214,212,209,1) 0%,rgba(244,241,237,1) 100%); /* Opera 11.10+ */
+  background: -ms-linear-gradient(top, rgba(214,212,209,1) 0%,rgba(244,241,237,1) 100%); /* IE10+ */
+  background: linear-gradient(to bottom, rgba(214,212,209,1) 0%,rgba(244,241,237,1) 100%); /* W3C */
+}
+
+.file_listing #contents.list td {
+  border-bottom: 1px dotted #ccc;
+}
+
+.file_listing #contents.list td:first-child {
+  display: table-cell;
+  padding-left: 0;
+  width: 100%;
+  padding-left: 22px;
+  background-repeat: no-repeat;
+  background-position: 3px center;
+}
+
+.file_listing #contents.list td.tbl_folder:first-child:before {
+  margin-right: 5px;
+  color: rgb(255, 204, 0);
+}
+
+.file_listing #contents.list td.tbl_file:first-child:before {
+  margin-right: 5px;
+}
+
+.file_listing #contents.list td.tbl_drive:first-child:before {
+  color: darkgray;
+  margin-right: 5px;
+}
+
+.file_listing #contents.list tbody tr:hover {
+  background-color: #eee;
+  cursor: pointer;
+}
+
+.file_listing #contents.grid li:hover {
+  border: 1px solid #E5E5E5;
+  background-color: #F7F7F7;
+  cursor: pointer;
+  max-height: 78px;
+}
+
+.meta {
+  display: none;
+}
+
+#activity {
+  margin: 100px auto;
+}
+
+button.grid span,
+button.list span {
+  width: 20px;
+  background-repeat: no-repeat;
+  background-position: center center;
+}
+
+.file_listing #contents li {
+  position: relative;
+}
+
+#dropzone-container h2 {
+  font-size: 20px;
+  margin-top: 0;
+}
+
+.pgadmin-storage-body {
+  min-width: 750px !important;
+  min-height: 380px !important;
+}
+
+.pgadmin-storage-body .ajs-content {
+  top: 0px !important;
+  left: 0 !important;
+  right: 0 !important;
+  height: 100% !important;
+  width: 100% !important;
+}
+
+.storage_dialog {
+  height: 100%;
+  width: 100%;
+}
+
+.storage_content {
+  height: 100%;
+  width: 100%;
+}
+
+.file_manager {
+  bottom: 0;
+  left: 0;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.btn-group.filemanager-btn-group .btn:not(:first-child):not(:last-child) {
+  border-left: 1px solid #A9A9A9;
+}
+
+.file_manager #uploader .filemanager-path-group {
+  padding: 0;
+  display: block;
+  border: 1px solid darkgrey;
+  height: 30px;
+  border-radius: 5px;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  float: left;
+  margin-right: 10px;
+}
+
+.file_manager #uploader .btn-group .btn[disabled] {
+  color: #888;
+  background-color: #ccc;
+}
+
+.file_manager #uploader .filemanager-btn-group {
+  border: 1px solid darkgrey;
+  border-radius: 5px;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  width: auto;
+  float: left;
+  overflow: hidden;
+}
+
+.file_manager .btn-group {
+  margin: 2px 3px;
+}
+
+.file_manager .fileinfo {
+  height: calc(100% - 109px);
+  overflow: hidden;
+  position: relative;
+  top: 35px;
+  font-size: 12px;
+}
+
+.file_manager .fileinfo #contents{
+  padding: 5px;
+  text-align: left;
+  display: inline-block;
+  height: 100%;
+  width: 100%;
+  overflow: auto;
+}
+
+.file_manager .fileinfo #contents thead tr{
+  position: relative;
+  display: block;
+  width: 100%;
+}
+
+.file_manager .fileinfo #contents thead tr th:nth-child(1),
+.file_manager .fileinfo #contents tbody tr td:nth-child(1) {
+  position: relative;
+  width: 100%;
+  min-width: 100%;
+  max-width: 100%;
+}
+
+.file_manager .fileinfo #contents thead tr th:nth-child(2) {
+  width: 152px;
+  min-width: 152px;
+  max-width: 152px;
+}
+
+.file_manager .fileinfo #contents tbody tr td:nth-child(2) {
+  width: 150px;
+  min-width: 150px;
+  max-width: 150px;
+}
+
+.file_manager .fileinfo #contents thead tr th:nth-child(3) {
+  width: 197px;
+  min-width: 197px;
+  max-width: 197px;
+}
+
+.file_manager .fileinfo #contents tbody tr td:nth-child(3) {
+  width: 180px;
+  min-width: 180px;
+  max-width: 180px;
+}
+
+.file_manager .fileinfo #contents tbody {
+  display: block;
+  overflow: auto;
+  width: 100%;
+  height: calc(100% - 30px);
+}
+.file_manager .fileinfo #contents tbody tr{
+  display: table;
+  max-width: 100%;
+  width: 100%;
+}
+
+.file_manager .upload_file {
+  display: none;
+  z-index: 1;
+  margin-bottom: auto;
+  top: 0;
+  margin-top: 0;
+  height: calc(100% - 5px);
+  width: 100%;
+  border: none;
+  position: absolute;
+  bottom: 0;
+  background-color: black;
+  padding: 0px;
+  padding-top: 22px;
+  padding-left: 10px;
+}
+
+.file_manager .upload_file #dropzone-container {
+  height: 100%;
+}
+
+.file_manager .upload_file #multiple-uploads {
+  background: black;
+  color: white;
+  padding: 0px !important;
+  height: calc(100% - 20px);
+  overflow: auto;
+  width: 100%;
+}
+
+.fileinfo .prompt-info {
+  text-align: center;
+  color: #fff;
+}
+
+.file_manager #uploader .btn-group .show_selected_file {
+  float: left;
+  text-align: left;
+  vertical-align: middle;
+  padding: 4px 0 0 5px;
+  height: 100%;
+}
+
+.fileinfo .file_listing {
+  display: block;
+  height: calc(100% - 35px);
+  border: 1px solid #ccc;
+  border-bottom: none;
+  font-size: 12px;
+}
+
+.fileinfo .allowed_file_types {
+  display: block;
+  height: 25px;
+  position: absolute;
+  right: 0;
+  border-top: 1px solid #ccc;
+  padding-top: 4px;
+  bottom: 4px;
+  width: 100%;
+  background: #fff;
+}
+
+.allowed_file_types .create_input {
+  position: absolute;
+  left: 5px;
+  width: 230px;
+}
+
+.allowed_file_types .create_input span {
+  padding-right: 5px;
+}
+
+.allowed_file_types .create_input input[type="text"] {
+  border-radius: 3px;
+  -webkit-border-radius: 3px;
+  -moz-border-radius: 3px;
+  height: 22px;
+  width: 140px;
+  font-size: 13px;
+  display: inline;
+}
+
+.allowed_file_types .change_file_types {
+  position: absolute;
+  top: 4px;
+  right: 0;
+}
+
+.allowed_file_types .change_file_types select {
+  width: 75px;
+  margin-left: 10px;
+  float: right;
+  height: 22px;
+}
+
+.allowed_file_types .change_file_types label {
+  float: right;
+  padding-top: 3px;
+}
+
+.upload_file .file_upload_main {
+  position: relative;
+  height: 127px;;
+  width: 120px;
+  display: inline-block;
+  margin: 0 15px 15px 0 !important;
+  border: 1px solid white;
+  position: relative;
+  border-radius: 5px;
+  -webkit-border-radius: 5px;
+  -moz-border-radius: 5px;
+  background: #fff;
+  margin: 2px;
+  opacity: 1;
+}
+
+.upload_file .file_upload_main .show_error {
+  padding: 10px 0 0 10px;
+  color: #000;
+}
+
+.upload_file .file_upload_main .show_error p.size {
+  text-align: center;
+}
+
+.upload_file .file_upload_main .show_error p.name {
+  font-size: 13px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  text-align: center;
+}
+
+.file_upload_main .dz-preview {
+  margin: 0;
+}
+
+.file_upload_main .dz-progress {
+  top: 83px !important;
+  border: 1px solid #8a6d3b;
+  border-radius: 0 !important;
+  -moz-border-radius: 0 !important;
+  -webkit-border-radius: 0 !important;
+}
+
+.file_upload_main .dz-progress .dz-upload {
+  background: #d9edf7 !important;
+  text-align: center;
+}
+
+.file_upload_main .dz-progress .dz-upload.success {
+  background: green !important;
+}
+
+a.dz-remove {
+  display: none !important;
+}
+
+.upload_file .file_upload_main a.dz_file_remove {
+  position: absolute;
+  top: 0;
+  right: 0;
+  color: #FF0000;
+  cursor: pointer;
+  border-radius: 5px;
+  -moz-border-radius: 5px;
+  -webkit-border-radius: 5px;
+  font-size: large;
+}
+
+.upload_file .file_upload_main a.dz_file_remove:hover {
+  border: 1px solid black;
+}
+
+.fileinfo .delete_item, .fileinfo .replace_file {
+  display: none;
+  padding: 7px 5px;
+  opacity: 0.8;
+  color: #fff;
+  border: 1px solid darkgrey;
+  background: #000;
+  box-shadow: 1px 0px 3px 1px red;
+}
+
+.fileinfo .delete_item span.pull-right .btn,
+.fileinfo .replace_file span.pull-right .btn {
+  padding: 0px 5px;
+  color: #000;
+  background: #fff;
+  font-size: 12px;
+}
+
+.fileinfo .delete_item span,
+.fileinfo .replace_file span {
+  margin-right: 10px;
+}
+
+.upload_file .dz_cross_btn {
+  color: #fff;
+  font-size: x-large;
+  right: -4px;
+  position: absolute;
+  top: -1px;
+  background: transparent;
+  border: none;
+}
+
+.file_manager .fileinfo #contents .fm_lock_icon {
+  color: red;
+  position: absolute;
+  top: 6px;
+  right: 0;
+  left: 19px;
+  font-size: 16px;
+}
+
+.file_manager .fileinfo #contents .fa-lock.tbl_lock_icon {
+  color: red;
+  position: absolute;
+  left: 29px;
+  top: 5px;
+  font-size: 10px;
+}
+
+.fileinfo .activity {
+  position: absolute;
+  left: 50%;
+  font-size: xx-large;
+  top: 30%;
+  z-index: 1;
+}
+
+.file_manager button.ON {
+  background: #F9F8F7;
+  border: 1px inset #ccc;
+}
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/index.html b/web/pgadmin/misc/file_manager/templates/file_manager/index.html
new file mode 100755
index 0000000..51044da
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/index.html
@@ -0,0 +1,55 @@
+<html>
+<head>
+  <script type="text/javascript" src="{{ url_for('static', filename='js/jquery.dropzone/dropzone.js') }}"></script>
+  <script type="text/javascript" src="{{ url_for('file_manager.index') }}utility.js"></script>
+</head>
+<body>
+<div class="file_manager">
+  <form id="uploader" method="post" class='col-xs-12'>
+    <div class="btn-group filemanager-path-group col-sm-7 col-xs-12" role="group">
+      <button name="home" type="button" value="Home" title="Home" class="fa fa-home btn home"><span></span></button>
+      <button name="level-up" type="button" title="Back" value="LevelUp" class="btn fa fa-level-up level-up" disabled><span></span></button>
+      <h1 title=''></h1>
+    </div>
+    <div class="btn-group filemanager-btn-group" role="group">
+      <div class="uploadresponse"></div>
+      <input class="mode" name="mode" type="hidden" value="add" />
+      <input class="currentpath" name="currentpath" type="hidden" />
+      <button type="button" title="Refresh" class="btn fa fa-refresh refresh"></button>
+      <button type="submit" title="Upload File" value="Upload" class="btn fa fa-upload upload"><span></span></button>
+      <button type="button" title="Download File" class="btn fa fa-download download" disabled><span></span></button>
+      <button name="delete" type="button" title="Delete File/Folder" class="btn fa fa-trash delete" disabled><span></span></button>
+      <button name="rename" type="button" title="Rename File/Folder" class="btn fa fa-pencil-square-o rename"><span></span></button>
+      <button name="newfolder" type="button" title="Create new folder" value="New Folder" class="btn fa fa-folder-open create"><span></span></button>
+      <button class="ON fa fa-th btn grid" type="button" title="View as grid"><span></span></button>
+      <button type="button" class="btn fa fa-list list" title="View as Table"><span></span></button>
+    </div>
+  </form>
+  <div class="fileinfo">
+    <span class="activity">
+      <img src="{{ url_for('browser.static', filename='css/aciTree/image/load-root.gif') }}">
+    </span>
+    <div class='delete_item'>
+      <span>Are you sure you want to delete this item ?</span>
+        <span class="pull-right">
+          <button type='button' class='btn btn_yes'>YES</button>
+          <button type='button' class='btn btn_no'>NO</button>
+        </span>
+    </div>
+    <div class='replace_file'>
+      <span>Are you sure you want to replace this file ?</span>
+        <span class="pull-right">
+          <button type='button' class='btn btn_yes'>YES</button>
+          <button type='button' class='btn btn_no'>NO</button>
+        </span>
+    </div>
+    <div class="file_listing">
+    </div>
+    <div class="upload_file dropzone">
+    </div>
+    <div class="allowed_file_types">
+    </div>
+  </div>
+</div>
+</body>
+</html>
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js
new file mode 100644
index 0000000..535a890
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager.js
@@ -0,0 +1,591 @@
+define([
+      'jquery', 'underscore', 'alertify'],
+
+  // This defines File Manager dialog
+  function($, _, alertify) {
+    pgAdmin = pgAdmin || window.pgAdmin || {};
+
+    /*
+     * Hmm... this module is already been initialized, we can refer to the old
+     * object from here.
+     */
+    if (pgAdmin.FileManager)
+        return pgAdmin.FileManager;
+
+    pgAdmin.FileManager = {
+      init: function() {
+        if (this.initialized)
+          return;
+
+        this.initialized = true;
+
+        var module_url = "{{ url_for('file_manager.index') }}",
+            fileConnector = module_url + "filemanager/";
+
+          // send a request to get transaction id
+          var getTransId = function(configs) {
+            return $.ajax({
+              data: configs,
+              type: "POST",
+              async: false,
+              url: module_url + "get_trans_id",
+              dataType: "json",
+              contentType: "application/json; charset=utf-8",
+            });
+          };
+
+          // Function to remove trans id from session
+          var removeTransId = function() {
+            return $.ajax({
+              type: "GET",
+              async: false,
+              url: module_url + "del_trans_id/" + trans_id,
+              dataType: "json",
+              contentType: "application/json; charset=utf-8",
+            });
+          };
+        // Declare the Storage dialog
+        alertify.dialog('storageManagerDlg', function() {
+          var controls = [], // Keep tracking of all the backform controls
+              // Dialog containter
+              $container = $("<div class='storage_dialog'></div>");
+
+          /*
+           * Function: renderStoragePanel
+           *
+           * Renders the FileManager in the content div based on the given
+           * configuration parameters.
+           */
+          var renderStoragePanel = function(params) {
+            /*
+             * Clear the existing html in the storage content
+             */
+            var content = $container.find('.storage_content');
+            content.empty();
+
+            $.get("{{ url_for('file_manager.index') }}", function(data) {
+              content.append(data);
+            });
+
+            transId = getTransId(params);
+            if (transId.readyState == 4)
+              t_res = JSON.parse(transId.responseText);
+            trans_id = t_res.data.fileTransId;
+
+          };
+
+          // Dialog property
+          return {
+            main: function(params) {
+              // Set title and button name
+              if (_.isUndefined(params['dialog_title']))
+                params['dialog_title'] = 'Storage manager';
+              this.set('title', params['dialog_title']);
+              if (_.isUndefined(params['btn_primary']))
+                params['btn_primary'] = 'Select';
+              this.set('label', params['btn_primary']);
+
+              var trans_id;
+              this.title = params.dialog_title;
+
+              params = JSON.stringify(params);
+              $container.find('.storage_content').remove();
+              $container.append("<div class='storage_content'></div>");
+              renderStoragePanel(params);
+              this.show();
+            },
+            settings: {
+              label: undefined
+            },
+            settingUpdated: function (key, oldValue, newValue) {
+              switch (key) {
+              case 'message':
+                  this.setMessage(newValue);
+                  break;
+              case 'label':
+                  if (this.__internal.buttons[0].element) {
+                      this.__internal.buttons[0].element.innerHTML = newValue;
+                  }
+                  break;
+              }
+            },
+            setup:function() {
+              return {
+                buttons:[
+                  {
+                    text: "{{ _('Select') }}", key: 13, className: "btn btn-primary fa fa-file file_manager_ok pg-alertify-button disabled"
+                  },
+                  {
+                    text: "{{ _('Cancel') }}", className: "btn btn-danger fa fa-times pg-alertify-button"
+                  }
+                ],
+                focus: { element: 0 },
+                options: {
+                  closableByDimmer: false,
+
+                }
+              };
+            },
+            callback: function(closeEvent) {
+              if (closeEvent.button.key == 13) {
+                //closeEvent.cancel = true;
+              }
+              if (closeEvent.button.text == "{{ _('Select') }}") {
+                if($('.fileinfo').data('view') == 'grid'){
+                  sel_file = $('.fileinfo').find('#contents li.selected p span').attr('title');
+                } else {
+                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
+                }
+                var newFile = $('.currentpath').val() + sel_file;
+                newFile = newFile.substr(1);
+                pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:storage_dialog', newFile);
+              }
+              removeTransId(trans_id);
+            },
+            build: function() {
+              this.elements.content.appendChild($container.get(0));
+            },
+            hooks: {
+              onshow: function() {
+                $(this.elements.body).addClass('pgadmin-storage-body');
+              }
+            }
+          };
+        });
+
+        // Declare the Selection dialog
+        alertify.dialog('fileSelectionDlg', function() {
+          var controls = [], // Keep tracking of all the backform controls
+              // Dialog containter
+              $container = $("<div class='storage_dialog file_selection_dlg'></div>");
+
+          // send a request to get transaction id
+          /*
+           * Function: renderStoragePanel
+           *
+           * Renders the FileManager in the content div based on the given
+           * configuration parameters.
+           */
+          var renderStoragePanel = function(configs) {
+            /*
+             * Clear the existing html in the storage content
+             */
+            var content = $container.find('.storage_content');
+            content.empty();
+
+            $.get("{{ url_for('file_manager.index') }}", function(data) {
+              content.append(data);
+            });
+
+            transId = getTransId(configs);
+            if (transId.readyState == 4)
+              t_res = JSON.parse(transId.responseText);
+            trans_id = t_res.data.fileTransId;
+          };
+
+          // Dialog property
+          return {
+            main: function(params) {
+              // Set title and button name
+              if (_.isUndefined(params['dialog_title']))
+                params['dialog_title'] = 'Select file';
+              this.set('title', params['dialog_title']);
+              if (_.isUndefined(params['btn_primary']))
+                params['btn_primary'] = 'Select';
+              this.set('label', params['btn_primary']);
+
+              var trans_id;
+              this.title = params.dialog_title;
+
+              params = JSON.stringify(params);
+              $container.find('.storage_content').remove();
+              $container.append("<div class='storage_content'></div>");
+              renderStoragePanel(params);
+              this.show();
+            },
+            settings: {
+              label: undefined
+            },
+            settingUpdated: function (key, oldValue, newValue) {
+              switch (key) {
+              case 'message':
+                  this.setMessage(newValue);
+                  break;
+              case 'label':
+                  if (this.__internal.buttons[0].element) {
+                      this.__internal.buttons[0].element.innerHTML = newValue;
+                  }
+                  break;
+              }
+            },
+            setup:function() {
+              return {
+                buttons:[
+                  {
+                    text: "{{ _('Select') }}", key: 13, className: "btn btn-primary fa fa-file file_manager_ok pg-alertify-button disabled"
+                  },
+                  {
+                    text: "{{ _('Cancel') }}", key: 27, className: "btn btn-danger fa fa-times pg-alertify-button"
+                  }
+                ],
+                focus: { element: 0 },
+                options: {
+                  closableByDimmer: false,
+                  maximizable: false,
+                  closable: false,
+                  movable: true
+                }
+              };
+            },
+            callback: function(closeEvent) {
+              if (closeEvent.button.text == "{{ _('Select') }}") {
+                if($('.fileinfo').data('view') == 'grid'){
+                  sel_file = $('.fileinfo').find('#contents li.selected  p span').attr('title');
+                } else {
+                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
+                }
+                var newFile = $('.currentpath').val() + sel_file;
+                newFile = newFile.substr(1);
+                pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:select_file', newFile);
+              }
+              removeTransId(trans_id);
+            },
+            build: function() {
+              this.elements.content.appendChild($container.get(0));
+            },
+            hooks: {
+              onshow: function() {
+                $(this.elements.body).addClass('pgadmin-storage-body');
+              }
+            }
+          };
+        });
+
+        // Declare the Folder Selection dialog
+        alertify.dialog('folderSelectionDlg', function() {
+          var controls = [], // Keep tracking of all the backform controls
+              // Dialog containter
+              $container = $("<div class='storage_dialog folder_selection_dlg'></div>");
+
+          // send a request to get transaction id
+          /*
+           * Function: renderStoragePanel
+           *
+           * Renders the FileManager in the content div based on the given
+           * configuration parameters.
+           */
+          var renderStoragePanel = function(params) {
+            /*
+             * Clear the existing html in the storage content
+             */
+            var content = $container.find('.storage_content');
+            content.empty();
+
+            $.get("{{ url_for('file_manager.index') }}", function(data) {
+              content.append(data);
+            });
+
+            transId = getTransId(params);
+            if (transId.readyState == 4)
+              t_res = JSON.parse(transId.responseText);
+            trans_id = t_res.data.fileTransId;
+
+          };
+
+          // Dialog property
+          return {
+            main: function(params) {
+              // Set title and button name
+              if (_.isUndefined(params['dialog_title']))
+                params['dialog_title'] = 'Select folder';
+              this.set('title', params['dialog_title']);
+              if (_.isUndefined(params['btn_primary']))
+                params['btn_primary'] = 'Select';
+              this.set('label', params['btn_primary']);
+
+              var trans_id;
+              params = JSON.stringify(params);
+              $container.find('.storage_content').remove();
+              $container.append("<div class='storage_content'></div>");
+              renderStoragePanel(params);
+              this.show();
+            },
+            settings: {
+              label: undefined
+            },
+            settingUpdated: function (key, oldValue, newValue) {
+              switch (key) {
+              case 'message':
+                  this.setMessage(newValue);
+                  break;
+              case 'label':
+                  if (this.__internal.buttons[0].element) {
+                      this.__internal.buttons[0].element.innerHTML = newValue;
+                  }
+                  break;
+              }
+            },
+            setup:function() {
+              return {
+                buttons:[
+                  {
+                    text: "{{ _('Select') }}", key: 13, className: "btn btn-primary fa fa-file file_manager_ok pg-alertify-button disabled"
+                  },
+                  {
+                    text: "{{ _('Cancel') }}", key: 27, className: "btn btn-danger fa fa-times pg-alertify-button"
+                  }
+                ],
+                focus: { element: 0 },
+                options: {
+                  closableByDimmer: false,
+                  maximizable: false,
+                  closable: false,
+                  movable: true
+                }
+              };
+            },
+            callback: function(closeEvent) {
+              if (closeEvent.button.text == "{{ _('Select') }}") {
+                if($('.fileinfo').data('view') == 'grid'){
+                  sel_file = $('.fileinfo').find('#contents li.selected p span').attr('title');
+                } else {
+                  sel_file = $('.fileinfo tbody tr.selected td p span').attr('title');
+                }
+                var newFile = $('.currentpath').val() + sel_file;
+                newFile = newFile.substr(1);
+                pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:select_folder', newFile);
+              }
+              removeTransId(trans_id);
+            },
+            build: function() {
+              this.elements.content.appendChild($container.get(0));
+            },
+            hooks: {
+              onshow: function() {
+                $(this.elements.body).addClass('pgadmin-storage-body');
+              }
+            }
+          };
+        });
+
+        // Declare the Create mode dialog
+        alertify.dialog('createModeDlg', function() {
+          var controls = [], // Keep tracking of all the backform controls
+              // Dialog containter
+              $container = $("<div class='storage_dialog create_mode_dlg'></div>");
+
+          /*
+           * Function: renderStoragePanel
+           *
+           * Renders the FileManager in the content div based on the given
+           * configuration parameters.
+           */
+          var renderStoragePanel = function(params) {
+            /*
+             * Clear the existing html in the storage content
+             */
+            var content = $container.find('.storage_content');
+            content.empty();
+
+            $.get("{{ url_for('file_manager.index') }}", function(data) {
+              content.append(data);
+            });
+
+            transId = getTransId(params);
+            if (transId.readyState == 4)
+              t_res = JSON.parse(transId.responseText);
+            trans_id = t_res.data.fileTransId;
+
+          };
+
+          // Dialog property
+          return {
+            main: function(params) {
+              var trans_id;
+              // Set title and button name
+              if (_.isUndefined(params['dialog_title']))
+                params['dialog_title'] = 'Create file';
+              this.set('title', params['dialog_title']);
+              if (_.isUndefined(params['btn_primary']))
+                params['btn_primary'] = 'Create';
+              this.set('label', params['btn_primary']);
+
+              params = JSON.stringify(params);
+              $container.find('.storage_content').remove();
+              $container.append("<div class='storage_content'></div>");
+              renderStoragePanel(params);
+              this.show();
+            },
+            settings: {
+              label: undefined
+            },
+            settingUpdated: function (key, oldValue, newValue) {
+              switch (key) {
+              case 'message':
+                  this.setMessage(newValue);
+                  break;
+              case 'label':
+                  if (this.__internal.buttons[0].element) {
+                      this.__internal.buttons[0].element.innerHTML = newValue;
+                  }
+                  break;
+              }
+            },
+            setup:function() {
+              return {
+                buttons:[
+                  {
+                    text: "{{ _('Create') }}", key: 13, className: "btn btn-primary fa fa-file file_manager_create file_manager_ok pg-alertify-button disabled"
+                  },
+                  {
+                    text: "{{ _('Cancel') }}", key: 27, className: "btn btn-danger fa fa-times file_manager_create_cancel pg-alertify-button"
+                  }
+                ],
+                focus: { element: 0 },
+                options: {
+                  closableByDimmer: false,
+                  maximizable: false,
+                  closable: false,
+                  movable: true
+                }
+              };
+            },
+            replace_file: function() {
+                $('.replace_file').show();
+                $('.replace_file .btn_yes').click(function(self) {
+                  $('.replace_file').hide();
+                  var selected_item = $('.allowed_file_types .create_input input[type="text"]').val(),
+                      newFile = $('.currentpath').val() + selected_item,
+                      newFile = newFile.substr(1);
+                  pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:create_file', newFile);
+                  $('.file_manager_create_cancel').trigger('click');
+                });
+                $('.replace_file .btn_no').click(function() {
+                  $('.replace_file').hide();
+                });
+            },
+            is_file_exist: function() {
+              var selected_item = $('.allowed_file_types .create_input input[type="text"]').val(),
+                  is_exist = false;
+
+              var file_data = {
+                'path': $('.currentpath').val(),
+                'name': selected_item,
+                'mode': 'is_file_exist'
+              };
+
+              $.ajax({
+                type: 'POST',
+                data: JSON.stringify(file_data),
+                url: fileConnector + trans_id+'/',
+                dataType: 'json',
+                contentType: "application/x-download; charset=utf-8",
+                async: false,
+                success: function(resp){
+                  data = resp.data.result;
+                  if(data['Code'] === 0){
+                    is_exist = true;
+                  } else {
+                    is_exist = false;
+                  }
+                }
+              });
+              return is_exist;
+            },
+            create_file: function() {
+              var selected_item = $('.allowed_file_types .create_input input[type="text"]').val(),
+                  is_exist = false,
+                  is_created = false;
+
+              var post_data = {
+                'path': $('.currentpath').val(),
+                'name': selected_item,
+                'mode': 'create_file'
+              };
+
+              $.ajax({
+                type: 'POST',
+                data: JSON.stringify(post_data),
+                url: fileConnector + trans_id+'/',
+                dataType: 'json',
+                contentType: "application/x-download; charset=utf-8",
+                async: false,
+                success: function(resp){
+                  data = resp.data.result;
+                  if(data['Code'] === 0){
+                    alertify.success("New File created successfully.");
+                    is_created = true;
+                  } else {
+                    alertify.error(data['Error']);
+                    return false;
+                  }
+                }
+              });
+              return is_created;
+            },
+            callback: function(closeEvent) {
+              if (closeEvent.button.text == "{{ _('Create') }}"){
+                var selected_item = $('.allowed_file_types .create_input input[type="text"]').val();
+                var newFile = $('.currentpath').val() + selected_item;
+                newFile = newFile.substr(1);
+                if(!_.isUndefined(selected_item) && selected_item !== '' && this.is_file_exist()) {
+                  this.replace_file();
+                  closeEvent.cancel = true;
+                }
+                else {
+                  var is_created = this.create_file();
+                  if (is_created) {
+                    pgAdmin.Browser.Events.trigger('pgadmin-storage:finish_btn:create_file', newFile);
+                    removeTransId(trans_id);
+                  }
+                  else {
+                    closeEvent.cancel = true;
+                  }
+                }
+              }
+              if (closeEvent.button.text == "{{ _('Cancel') }}"){
+                removeTransId(trans_id);
+              }
+            },
+            build: function() {
+              this.elements.content.appendChild($container.get(0));
+            },
+            hooks: {
+              onshow: function() {
+                $(this.elements.body).addClass('pgadmin-storage-body');
+              }
+            }
+          };
+        });
+      },
+      show_storage_dlg: function(params) {
+        alertify.storageManagerDlg(params).resizeTo('60%', '80%');
+      },
+      show_file_selection: function(params) {
+        alertify.fileSelectionDlg(params).resizeTo('60%', '80%');
+      },
+      show_folder_selection: function(params) {
+        alertify.folderSelectionDlg(params).resizeTo('60%', '80%');
+      },
+      show_create_dlg: function(params) {
+        alertify.createModeDlg(params).resizeTo('60%', '80%');
+      },
+      // call dialogs subject to dialog_type param
+      show_dialog: function(params) {
+        if(params.dialog_type == 'select_file') {
+          this.show_file_selection(params);
+        }
+        else if (params.dialog_type == 'select_folder') {
+          this.show_folder_selection(params);
+        }
+        else if (params.dialog_type == 'create_file') {
+          this.show_create_dlg(params);
+        }
+        else {
+          this.show_storage_dlg(params);
+        }
+      }
+    };
+
+    return pgAdmin.FileManager;
+  });
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager_config.json b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager_config.json
new file mode 100644
index 0000000..efb7fcb
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/file_manager_config.json
@@ -0,0 +1,25 @@
+{
+    "options": {
+        "culture": "en",
+        "lang": "py",
+        "defaultViewMode": "grid",
+        "autoload": true,
+        "showFullPath": false,
+        "dialog_type": "{{data.dialog_type}}",
+        "fileRoot": "{{data.fileroot}}",
+        "capabilities": [{% for i in data.capabilities %}{% if loop.index != 1 %}, {% endif %}"{{i}}"{% endfor %}],
+        "allowed_file_types": [{% for i in data.supported_types %}{% if loop.index != 1 %}, {% endif %}"{{i}}"{% endfor %}],
+        "platform_type": "{{ data.platform_type }}",
+        "show_volumes":"{{data.show_volumes}}"
+    },
+    "security": {
+        "uploadPolicy": "{{ data.security.uploadPolicy }}",
+        "uploadRestrictions": [{% for i in data.security.uploadRestrictions %}{% if loop.index != 1 %}, {% endif %}"{{i}}"{% endfor %}]
+    },
+    "upload": {
+        "multiple": "{{ data.upload.multiple }}",
+        "number": 20,
+        "fileSizeLimit": "{{ data.upload.fileSizeLimit }}",
+        "imagesOnly": false
+    }
+}
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/languages/en.js b/web/pgadmin/misc/file_manager/templates/file_manager/js/languages/en.js
new file mode 100644
index 0000000..dba85e8
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/languages/en.js
@@ -0,0 +1,41 @@
+{
+    "LANGUAGE_FILE_NOT_FOUND": "Language file not found.",
+    "upload_success": "File uploaded successfully.",
+    "upload_error": "Error uploading file",
+    "browse": "Browse...",
+    "bytes": " bytes",
+    "cancel": "Cancel",
+    "close": "Close",
+    "confirmation_delete": "Are you sure you wish to delete this file?",
+    "current_folder": "",
+    "del": "Delete",
+    "download": "Download",
+    "dz_dictDefaultMessage": "Drop files here to upload",
+    "dz_dictFallbackMessage": "Your browser does not support drag'n'drop file uploads.",
+    "dz_dictMaxFilesExceeded": "Only %s simultaneous uploads are allowed.",
+    "dz_dictInvalidFileType": "You can't upload files of this type.",
+    "edit": "Edit file",
+    "file_size_limit": "The file size limit (per file) is ",
+    "file_too_big": "The file is too big.",
+    "gb": "gb",
+    "grid_view": "Switch to grid view.",
+    "items": "items",
+    "kb": "kb",
+    "list_view": "Switch to list view.",
+    "mb": "mb",
+    "modified": "Modified",
+    "move": "Move to ...",
+    "name": "Name",
+    "new_folder": "New Folder",
+    "no": "No",
+    "no_foldername": "No folder name was provided.",
+    "rename": "Rename",
+    "save": "Save",
+    "select": "Select",
+    "size": "Size",
+    "successful_added_folder": "New folder added successfully.",
+    "successful_delete": "Delete successful.",
+    "successful_rename": "Rename successful.",
+    "upload": "Upload",
+    "yes": "Yes"
+}
diff --git a/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js b/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js
new file mode 100755
index 0000000..61ab9a7
--- /dev/null
+++ b/web/pgadmin/misc/file_manager/templates/file_manager/js/utility.js
@@ -0,0 +1,1529 @@
+/**
+ * Filemanager JS core
+ *
+ * filemanager.js
+ *
+ *  @license  MIT License
+ *  @author Jason Huck - Core Five Labs
+ *  @author Simon Georget <simon (at) linea21 (dot) com>
+ *  @copyright  Authors
+ */
+
+(function($) {
+
+// User alertify object
+var alertify = require("alertify");
+
+
+/*---------------------------------------------------------
+  Define functions used for various operations
+---------------------------------------------------------*/
+
+// function to retrieve GET params
+$.urlParam = function(name) {
+  var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
+  if (results)
+    return results[1];
+  else
+    return 0;
+};
+
+var getFileExtension = function(name) {
+    var found = name.lastIndexOf('.') + 1;
+    return (found > 0 ? name.substr(found) : "");
+};
+
+var getFileName = function(name) {
+  var fm_filename = name;
+  if (fm_filename.length > 15 ) {
+      fm_filename = name.substr(0, 10) +'...';
+  }
+  return fm_filename;
+};
+
+// send a request to get transaction id
+var getTransId = function() {
+  return $.ajax({
+    async: false,
+    url: "{{ url_for('file_manager.index') }}get_trans_id",
+    dataType: "jsonp"
+  });
+};
+
+// Load language file
+var loadLangFile = function(enjs) {
+  if($.urlParam('langCode') !== 0 && file_exists (enjs)) culture = $.urlParam('langCode');
+  return $.ajax({
+    async: false,
+    url: enjs,
+    dataType: 'jsonp',
+    contentType: "application/json; charset=utf-8"
+  });
+};
+
+// We retrieve config settings from filemanager.config.js
+var loadConfigFile = function (type) {
+  type = (typeof type === "undefined") ? "user" : type;
+  if (type == 'user') {
+    url = file_manager_config_json;
+    userconfig = file_manager_config_json;
+  }
+  return $.ajax({
+    async: false,
+    url: url,
+    dataType: "jsonp",
+    contentType: "application/json; charset=utf-8"
+  });
+};
+
+/*
+ * Forces columns to fill the layout vertically.
+ * Called on initial page load and on resize.
+ */
+var setDimensions = function() {
+  var main_container_height = ( $(window).height() ) / 2 + 35,
+      newH = main_container_height - $('#uploader').height() - 30;
+};
+
+// Display Min Path
+var displayPath = function(path) {
+  if(config.options.showFullPath === false) {
+    // if a "displayPathDecorator" function is defined, use it to decorate path
+    return 'function' === (typeof displayPathDecorator)
+         ? displayPathDecorator(path)
+         : path.replace(fileRoot, "/");
+  } else {
+    return path;
+  }
+};
+
+// Set the view buttons state
+var setViewButtonsFor = function(viewMode) {
+    if (viewMode == 'grid') {
+        $('.grid').addClass('ON');
+        $('.list').removeClass('ON');
+    }
+    else {
+        $('.list').addClass('ON');
+        $('.grid').removeClass('ON');
+    }
+};
+
+/*
+ * preg_replace
+ */
+var preg_replace = function(array_pattern, array_pattern_replace, str)  {
+  var new_str = String (str);
+    for (i=0; i<array_pattern.length; i++) {
+      var reg_exp= RegExp(array_pattern[i], "g");
+      var val_to_replace = array_pattern_replace[i];
+      new_str = new_str.replace (reg_exp, val_to_replace);
+    }
+    return new_str;
+  };
+
+/*
+ * cleanString (), on the same model as server side (connector)
+ * cleanString
+ */
+var cleanString = function(str) {
+  var cleaned = "";
+  var p_search  =   new Array("Š", "š", "Đ", "đ", "Ž", "ž", "Č", "č", "Ć", "ć", "À",
+            "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï",
+            "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "Ő", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "Þ", "ß",
+            "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì",  "í",
+            "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "ő", "ø", "ù", "ú", "û", "ý",
+            "ý", "þ", "ÿ", "Ŕ", "ŕ", " ", "'", "/"
+            );
+  var p_replace =   new Array("S", "s", "Dj", "dj", "Z", "z", "C", "c", "C", "c", "A",
+            "A", "A", "A", "A", "A", "A", "C", "E", "E", "E", "E", "I", "I", "I", "I",
+            "N", "O", "O", "O", "O", "O", "O", "O", "U", "U", "U", "U", "Y", "B", "Ss",
+            "a", "a", "a", "a", "a", "a", "a", "c", "e", "e", "e", "e", "i", "i",
+            "i", "i", "o", "n", "o", "o", "o", "o", "o", "o", "o", "u", "u", "u", "y",
+            "y", "b", "y", "R", "r", "_", "_", ""
+          );
+
+  cleaned = preg_replace(p_search, p_replace, str);
+  cleaned = cleaned.replace(/[^_a-zA-Z0-9]/g, "");
+  cleaned = cleaned.replace(/[_]+/g, "_");
+
+  return cleaned;
+};
+
+/*
+ * nameFormat (), separate filename from extension before calling cleanString()
+ * nameFormat
+ */
+var nameFormat = function(input) {
+  filename = '';
+  if(input.lastIndexOf('.') != -1) {
+    filename  = cleanString(input.substr(0, input.lastIndexOf('.')));
+    filename += '.' + input.split('.').pop();
+  } else {
+    filename = cleanString(input);
+  }
+  return filename;
+};
+
+//Converts bytes to kb, mb, or gb as needed for display.
+var formatBytes = function(bytes){
+  var n = parseFloat(bytes);
+  var d = parseFloat(1024);
+  var c = 0;
+  var u = [lg.bytes,lg.kb,lg.mb,lg.gb];
+
+  while(true){
+    if(n < d){
+      n = Math.round(n * 100) / 100;
+      return n + u[c];
+    } else {
+      n /= d;
+      c += 1;
+    }
+  }
+};
+
+/*
+ * Handle Error. Freeze interactive buttons and display
+ * error message. Also called when auth() function return false (Code == "-1")
+ */
+var handleError = function(errMsg) {
+  $('.storage_dialog .newfile').attr("disabled", "disabled");
+  $('.storage_dialog .upload').attr("disabled", "disabled");
+  $('.storage_dialog .create').attr("disabled", "disabled");
+};
+
+/*
+ * Test if Data structure has the 'cap' capability
+ * 'cap' is one of 'select', 'rename', 'delete', 'download'
+ */
+function has_capability(data, cap) {
+  if (typeof(data['Capabilities']) == "undefined") return true;
+  else return $.inArray(cap, data['Capabilities']) > -1;
+}
+
+// Test if file is authorized
+var isAuthorizedFile = function(filename) {
+  if(config.security.uploadPolicy == 'DISALLOW_ALL') {
+    if($.inArray(getExtension(filename), config.security.uploadRestrictions) != -1) return true;
+  }
+  if(config.security.uploadPolicy == 'ALLOW_ALL') {
+    if($.inArray(getExtension(filename), config.security.uploadRestrictions) == -1) return true;
+  }
+  return false;
+};
+
+// return filename extension
+var getExtension = function(filename) {
+  if(filename.split('.').length == 1)
+    return "";
+  return filename.split('.').pop();
+};
+
+// return filename without extension {
+var getFilename = function(filename) {
+  if(filename.lastIndexOf('.') != -1)
+    return filename.substring(0, filename.lastIndexOf('.'));
+  else
+    return filename;
+};
+
+// helpful in show/hide toolbar button for Windows
+var hideButtons = function() {
+    var current_path = $('.currentpath').val();
+    if(config.options.platform_type == 'win32' && current_path == "/")
+        return true;
+    return false;
+};
+
+/*
+ * Sets the folder status, upload, and new folder functions
+ * to the path specified. Called on initial page load and
+ * whenever a new directory is selected.
+ */
+var setUploader = function(path){
+  $('.storage_dialog #uploader').find('a').remove();
+  $('.storage_dialog #uploader').find('b').remove();
+
+  path = decodeURI(path);
+  var display_string = displayPath(path);
+  var mypath = '';
+
+  // split path
+  split_path = display_string.split('/');
+  split_path = split_path.filter(function(e){return e;});
+
+  // set empty path if it is windows
+  if (config.options.platform_type === "win32" && config.options.show_volumes) {
+      mypath = "";
+  }
+  else if (split_path.length === 0)
+    mypath = $('<b>/</b>');
+  else
+    mypath = $('<a class="breadcrumbs" href="#" data-path="/">/</a>');
+  $(mypath).appendTo($('.storage_dialog #uploader h1'));
+
+  for(var i in split_path) {
+    if (i < split_path.length-1) {
+      mypath = $('<a class="breadcrumbs" href="#" data-path="'+display_string.replace(split_path[i+1], '')+'">'+split_path[i]+'/</a>');
+      $(mypath).appendTo($('.storage_dialog #uploader h1'));
+   }
+   else {
+     mypath = $('<b>'+split_path[i]+'</b>');
+     $(mypath).appendTo($('.storage_dialog #uploader h1'));
+   }
+  }
+
+  $('.currentpath').val(path);
+  if($('.storage_dialog #uploader h1 span').length === 0) {
+    $('<span>'+lg.current_folder+'</span>').appendTo($('.storage_dialog #uploader h1'));
+  }
+
+  $('.storage_dialog #uploader h1').attr('title', display_string);
+  $('.storage_dialog #uploader h1').attr('data-path', display_string);
+
+  // create new folder
+  $('.create').unbind().click(function(){
+    var foldername =  lg.default_foldername;
+    var $file_element,
+        $file_element_list;
+
+    $('.file_manager button.create').attr('disabled', 'disabled');
+    if($('.fileinfo').data('view') == 'grid'){
+
+      // template for creating new folder
+      var folder_div = "<li class='cap_downloadcap_deletecap_select_filecap_select_foldercap_renamecap_createcap_upload'>"+
+          "<div class='clip'><span data-alt='' class='fa fa-folder-open fm_folder'></span></div>"+
+          "<p><input type='text' class='fm_file_rename'><span title=''>New_Folder</span></p>"+
+          "<span class='meta size'></span><span class='meta created'></span><span class='meta modified'></span></li>";
+
+      var path = $('.currentpath').val(),
+          $file_element =  $(folder_div);
+      $('.fileinfo #contents.grid').append($file_element);
+      $file_element.find('p span').toggle();
+      $file_element.find('p input').toggle().val(lg.new_folder).select();
+
+      // rename folder/file on pressing enter key
+      $('.file_manager').bind().on('keyup', function(e) {
+        if (e.keyCode == 13) {
+          e.stopPropagation();
+          $file_element.find('p input').trigger('blur');
+        }
+      });
+
+      // rename folder/file on blur 
+      $file_element.find('p input').on('blur', function(e) {
+        $('.file_manager button.create').removeAttr('disabled');
+        var text_value = $file_element.find('p input').val(),
+            path = $('.currentpath').val();
+        $file_element.find('p input').toggle();
+        $file_element.find('p span').toggle().html(text_value);
+        if(text_value === undefined) text_value = lg.new_folder;
+        getFolderName(text_value);
+        getFolderInfo(path);
+      });
+
+    }
+    else if($('.fileinfo').data('view') == 'list'){
+
+      // template to create new folder in table view
+      var folder_div = $("<tr class='cap_download cap_delete cap_select_file cap_select_folder cap_rename cap_create cap_upload'>"+
+        "<td title='' class='fa fa-folder-open tbl_folder'>"+
+          "<p><input type='text' class='fm_file_rename'><span>"+lg.new_folder+"</span></p>"+
+          "</td><td>"+
+          "<abbr title=''></abbr></td>"+
+          "<td></td>"+
+        "</tr>");
+
+      $file_element_list =  $(folder_div);
+      $('.fileinfo #contents.list').prepend($file_element_list);
+      $file_element_list.find('p span').toggle();
+      $file_element_list.find('p input').toggle().val(lg.new_folder).select();
+
+      // rename folder/file on pressing enter key
+      $('.file_manager').bind().on('keyup', function(e) {
+        if (e.keyCode == 13) {
+          e.stopPropagation();
+          $file_element_list.find('p input').trigger('blur');
+        }
+      });
+
+      // rename folder/file on blur 
+      $file_element_list.find('p input').on('blur', function(e) {
+        $('.file_manager button.create').removeAttr('disabled');
+        var text_value = $file_element_list.find('p input').val(),
+            path = $('.currentpath').val();
+        $file_element_list.find('p input').toggle();
+        $file_element_list.find('p span').toggle().html(text_value);
+        if(text_value === undefined) text_value = lg.new_folder;
+        getFolderName(text_value);
+        getFolderInfo(path);
+      });
+    }
+
+    // create a new folder
+    var getFolderName = function(value){
+      var fname = value;
+
+      if(fname != ''){
+        foldername = cleanString(fname);
+        var d = new Date(); // to prevent IE cache issues
+        $.getJSON(fileConnector + '?mode=addfolder&path=' + $('.currentpath').val() + '&name=' + foldername + '&time=' + d.getMilliseconds(), function(resp){
+          result = resp.data.result;
+          if(result['Code'] === 0){
+            alertify.success(lg.successful_added_folder);
+            getFolderInfo(result['Parent']);
+          } else {
+            alertify.error(result['Error']);
+          }
+        });
+      } else {
+        alertify.error(lg.no_foldername);
+      }
+    };
+
+  });
+};
+
+/*
+ * Binds specific actions to the toolbar based on capability.
+ * and show/hide buttons
+ */
+var bindToolbar = function(data){
+  if (!has_capability(data, 'upload') || hideButtons()) {
+    $('.file_manager').find('button.upload').hide();
+  }
+  else {
+    $('.file_manager').find('button.upload').show();
+  }
+
+  if (!has_capability(data, 'create') || hideButtons()) {
+    $('.file_manager').find('button.create').hide();
+  }
+  else {
+      $('.file_manager').find('button.create').show();
+  }
+
+  if (!has_capability(data, 'delete') || hideButtons()) {
+    $('.file_manager').find('button.delete').hide();
+  } else {
+    $('.file_manager').find('button.delete').click(function(){
+      $('.fileinfo .delete_item').show();
+    });
+
+    // take action based on pressed button yes or no
+    $('.fileinfo .delete_item button.btn_yes').unbind().on('click', function() {
+      if($('.fileinfo').data('view') == 'grid'){
+        var path = $('.fileinfo').find('#contents li.selected .clip span').attr('data-alt');
+        if(path.lastIndexOf('/') == path.length - 1){
+          data['Path'] = path;
+          deleteItem(data);
+        }
+        else {
+          deleteItem(data);
+        }
+      }
+      else {
+        var path = $('.fileinfo').find('table#contents tbody tr.selected td:first-child').attr('title');
+        if(path.lastIndexOf('/') == path.length - 1){
+          data['Path'] = path;
+          deleteItem(data);
+        }
+        else {
+          deleteItem(data);
+        }
+      }
+    });
+
+  }
+
+  // Download file on download button click
+  if (!has_capability(data, 'download') || hideButtons()) {
+    $('.file_manager').find('button.download').hide();
+  } else {
+    $('.file_manager').find('button.download').unbind().click(function(){
+      if($('.fileinfo').data('view') == 'grid'){
+        var path = $('.fileinfo li.selected').find('.clip span').attr('data-alt');
+        window.open(fileConnector + '?mode=download&path=' + encodeURIComponent(path), '_blank');
+      }
+      else {
+        var path = $('.fileinfo').find('table#contents tbody tr.selected td:first-child').attr('title');
+        window.open(fileConnector + '?mode=download&path=' + encodeURIComponent(path), '_blank');
+      }
+    });
+  }
+
+  if (!has_capability(data, 'rename') || hideButtons()) {
+    $('.file_manager').find('button.rename').hide();
+  }
+  else {
+      $('.file_manager').find('button.rename').show();
+  }
+};
+
+// enable/disable button when files/folder are loaded
+var enable_disable_btn = function() {
+  if($('.fileinfo').data('view') == 'grid'){
+    var $grid_file = $('.file_manager').find('#contents li.selected');
+    $grid_file.removeClass('selected');
+    $('.file_manager').find('button.delete').prop('disabled', true);
+    $('.file_manager').find('button.download').prop('disabled', true);
+    $('.file_manager').find('button.rename').prop('disabled', true);
+    if ($grid_file.length > 0) {
+      $('.create_input input[type="text"]').val('');
+      $('.file_manager_ok').addClass('disabled');
+    }
+  } else {
+    var $list_file = $('.fileinfo').find('table#contents tbody tr.selected');
+    $list_file.removeClass('selected');
+    $('.file_manager').find('button.delete').prop('disabled', true);
+    $('.file_manager').find('button.download').prop('disabled', true);
+    $('.file_manager').find('button.rename').prop('disabled', true);
+    if ($list_file.length > 0) {
+      $('.create_input input[type="text"]').val('');
+      $('.file_manager_ok').addClass('disabled');
+    }
+  }
+
+  $('.delete_item').hide();
+  // clear address bar
+  $('.file_manager #uploader h1').show();
+  $('.file_manager #uploader .show_selected_file').remove();
+};
+
+// switch to folder view
+$('.file_manager .fileinfo').on('click', function(e) {
+  enable_disable_btn();
+});
+
+
+// refresh current directory
+$('.file_manager .refresh').on('click', function(e) {
+  enable_disable_btn();
+  var curr_path = $('.currentpath').val();
+  path = curr_path.substring(0, curr_path.lastIndexOf("/")) + "/";
+  getFolderInfo(path);
+});
+
+/*---------------------------------------------------------
+  Item Actions
+---------------------------------------------------------*/
+
+/*
+ * Rename the current item and returns the new name.
+ * by double clicking or by clicking the "Rename" button in
+ * table(list) views.
+ */
+var renameItem = function(data){
+  var orig_name = getFilename(data['Filename']),
+      finalName = '';
+
+  var getNewName = function(rname){
+    if(rname !== ''){
+      var givenName = nameFormat(rname),
+          suffix = getExtension(data['Filename']);
+      if(suffix.length > 0) {
+        givenName = givenName + '.' + suffix;
+      }
+
+      var oldPath = data['Path'],
+          post_data = {
+        "mode": "rename",
+        "old": data['Path'],
+        "new": givenName,
+      };
+
+      $.ajax({
+        type: 'POST',
+        data: JSON.stringify(post_data),
+        url: fileConnector,
+        dataType: 'json',
+        contentType: "application/json; charset=utf-8",
+        async: false,
+        success: function(resp){
+          result = resp.data.result;
+          if(result['Code'] === 0){
+            var newPath = result['New Path'],
+                newName = result['New Name'],
+                title = $("#preview h1").attr("title");
+
+            if (typeof title !="undefined" && title == oldPath)
+              $('#preview h1').text(newName);
+
+            if($('.fileinfo').data('view') == 'grid'){
+              $('.fileinfo span[data-alt="' + oldPath + '"]').parent().next('p span').text(newName);
+              $('.fileinfo span[data-alt="' + oldPath + '"]').attr('data-alt', newPath);
+            } else {
+              $('.fileinfo td[title="' + oldPath + '"]').text(newName);
+              $('.fileinfo td[title="' + oldPath + '"]').attr('title', newPath);
+            }
+            $("#preview h1").html(newName);
+
+            // actualized data for binding
+            data['Path']=newPath;
+            data['Filename']=newName;
+
+            // UnBind toolbar functions.
+            $('.fileinfo').find('button.rename, button.delete, button.download').unbind();
+
+            alertify.success(lg.successful_rename);
+          } else {
+              alertify.error(result['Error']);
+          }
+
+          finalName = result['New Name'];
+        }
+      });
+    }
+  };
+
+  getNewName(data['NewFilename']);
+  return finalName;
+};
+
+/*
+ * delete the folder or files by clicking the "Delete" button
+ * in table(list) view
+ */
+var deleteItem = function(data){
+  var isDeleted = false,
+      msg = lg.confirmation_delete;
+
+  var doDelete = function(data){
+    var parent = data['Path'].split('/').reverse().slice(1).reverse().join('/') + '/';
+    var post_data = {
+      "mode": "delete",
+      "path": data['Path']
+    };
+
+    $.ajax({
+      type: 'POST',
+      data: JSON.stringify(post_data),
+      url: fileConnector,
+      dataType: 'json',
+      contentType: "application/json; charset=utf-8",
+      async: false,
+      success: function(resp){
+        result = resp.data.result;
+        if(result['Code'] === 0){
+          isDeleted = true;
+          if(isDeleted) {
+            alertify.success(lg.successful_delete);
+            var rootpath = result['Path'].substring(0, result['Path'].length-1); // removing the last slash
+                rootpath = rootpath.substr(0, rootpath.lastIndexOf('/') + 1);
+            getFolderInfo(rootpath);
+          }
+        } else {
+          isDeleted = false;
+          alertify.error(result['Error']);
+        }
+      }
+    });
+    return isDeleted;
+  };
+
+  doDelete(data);
+  return isDeleted;
+};
+
+
+// hide message prompt if clicked no
+$('.delete_item button.btn_no').on('click', function() {
+  $('.delete_item').hide();
+});
+
+/*---------------------------------------------------------
+  Functions to Retrieve File and Folder Details
+---------------------------------------------------------*/
+
+/* Decides whether to retrieve file or folder info based on
+ * the path provided.
+ */
+var getDetailView = function(path){
+  if(path.lastIndexOf('/') == path.length - 1){
+    var allowed_types = config.options.allowed_file_types;
+    getFolderInfo(path, allowed_types[0]);
+  }
+};
+
+/*
+ * Retrieves information about the specified file as a JSON
+ * object and uses that data to populate a template for
+ * list views. Binds the toolbar for that file/folder to
+ * enable specific actions. Called whenever an item is
+ * clicked in list views.
+ */
+var getFileInfo = function(file){
+  // Update location for status, upload, & new folder functions.
+  var currentpath = file.substr(0, file.lastIndexOf('/') + 1);
+  setUploader(currentpath);
+
+  // Retrieve the data & populate the template.
+  var d = new Date(); // to prevent IE cache issues
+  var post_data = {
+    'path': file,
+    'mode': 'getinfo'
+  };
+
+  $.ajax({
+    type: 'POST',
+    data: JSON.stringify(post_data),
+    url: fileConnector,
+    dataType: 'json',
+    contentType: "application/json; charset=utf-8",
+    async: false,
+    success: function(resp){
+      data = resp.data.result;
+      if(data['Code'] === 0){
+        var properties = '';
+        if(data['Properties']['Size'] || parseInt(data['Properties']['Size'])==0) properties += '<dt>' + lg.size + '</dt><dd>' + formatBytes(data['Properties']['Size']) + '</dd>';
+        data['Capabilities'] = capabilities;
+        bindToolbar(data);
+      } else {
+        alertify.error(data['Error']);
+      }
+    }
+  });
+};
+
+/*
+ * Retrieves data for all items within the given folder and
+ * creates a list view.
+ */
+var getFolderInfo = function(path, file_type=''){
+  // Update location for status, upload, & new folder functions.
+  setUploader(path);
+
+  // set default selected file type
+  if (file_type === '')
+    var file_type = $('.change_file_types select').val();
+
+  // navigate to directory or path when clicked on breadcrumbs 
+  $('.file_manager a.breadcrumbs').unbind().on('click', function() {
+    var path = $(this).attr('data-path'),
+        current_dir = $(this).html(),
+        move_to = path.substring(0, path.lastIndexOf(current_dir))+current_dir;
+    getFolderInfo(move_to);
+    enab_dis_level_up();
+  });
+
+   // hide select file if we are listing drives in windows.
+   if (hideButtons()) {
+     $(".allowed_file_types .change_file_types").hide();
+   }
+   else {
+     $(".allowed_file_types .change_file_types").show();
+   }
+
+  // Display an activity indicator.
+  $('.fileinfo').find('span.activity').html("<img src='{{ url_for('browser.static', filename='css/aciTree/image/load-root.gif') }}'>");
+
+  // Retrieve the data and generate the markup.
+  var d = new Date(); // to prevent IE cache issues
+  if ($.urlParam('type')) url += '&type=' + $.urlParam('type');
+
+  var post_data = {
+    'path': path,
+    'mode': 'getfolder',
+    'file_type': file_type || "*"
+  };
+
+  $.ajax({
+    type: 'POST',
+    data: JSON.stringify(post_data),
+    url: fileConnector,
+    dataType: 'json',
+    contentType: "application/json; charset=utf-8",
+    async: false,
+    success: function(resp){
+    var result = '';
+    data = resp.data.result;
+
+    // hide activity indicator
+    $('.fileinfo').find('span.activity').hide();
+    if(data.Code === 0) {
+      alertify.error(data.err_msg);
+      return;
+    }
+
+    // generate HTML for files/folder and render into container
+    if(data){
+      if($('.fileinfo').data('view') == 'grid') {
+        result += '<ul id="contents" class="grid">';
+        for(key in data) {
+          var props = data[key]['Properties'],
+              cap_classes = "";
+          for (cap in capabilities) {
+            if (has_capability(data[key], capabilities[cap])) {
+              cap_classes += "cap_" + capabilities[cap];
+            }
+          }
+
+          data[key]['Capabilities'] = capabilities;
+          bindToolbar(data[key]);
+
+          var class_type;
+          if(data[key]['file_type'] == 'dir') {
+            class_type = 'fa fa-folder-open fm_folder';
+          }
+          else if(data[key]['file_type'] == 'drive') {
+            class_type = 'fa fa-hdd-o fm_drive';
+          }
+          else {
+            class_type = 'fa fa-file-text fm_file';
+          }
+
+          var fm_filename = data[key]['Filename'];
+          if (fm_filename.length > 15 ) {
+              fm_filename = data[key]['Filename'].substr(0, 10) +'...';
+          }
+
+          var file_name_original = encodeURI(data[key]['Filename']);
+          var file_path_orig = encodeURI(data[key]['Path']);
+          result += '<li class="' + cap_classes + '"><div class="clip"><span data-alt="' + file_path_orig + '" class="' + class_type + '"></span>';
+          if (data[key]['Protected'] == 1) {
+            result += '<span class="fa fa-lock fm_lock_icon" data-protected="protected"></span>';
+          }
+          result += '</div>';
+          if(!has_capability(data[key], 'rename'))
+            result += '<span>' + fm_filename + '</span>';
+          else
+            result += '<p><input type="text" class="fm_file_rename" /><span title="'+file_name_original+'">' + fm_filename + '</span></p>';
+          if(props['Width'] && props['Width'] != '') result += '<span class="meta dimensions">' + props['Width'] + 'x' + props['Height'] + '</span>';
+          if(props['Size'] && props['Size'] != '') result += '<span class="meta size">' + props['Size'] + '</span>';
+          if(props['Date Created'] && props['Date Created'] != '') result += '<span class="meta created">' + props['Date Created'] + '</span>';
+          if(props['Date Modified'] && props['Date Modified'] != '') result += '<span class="meta modified">' + props['Date Modified'] + '</span>';
+          result += '</li>';
+        }
+
+        result += '</ul>';
+      } else {
+        result += '<table id="contents" class="list">';
+        result += '<thead><tr><th class="headerSortDown"><span>' + lg.name + '</span></th><th><span>' + lg.size + '</span></th><th><span>' + lg.modified + '</span></th></tr></thead>';
+        result += '<tbody>';
+
+        for(key in data){
+          var path = encodeURI(data[key]['Path']),
+              props = data[key]['Properties'],
+              cap_classes = "";
+          for (cap in capabilities) {
+            if (has_capability(data[key], capabilities[cap])) {
+              cap_classes += " cap_" + capabilities[cap];
+            }
+          }
+
+          data[key]['Capabilities'] = capabilities;
+          bindToolbar(data[key]);
+
+          var class_type;
+          if(data[key]['file_type'] == 'dir') {
+            class_type = 'fa fa-folder-open tbl_folder';
+          }
+          else if(data[key]['file_type'] == 'drive') {
+            class_type = 'fa fa-hdd-o tbl_drive';
+          }
+          else {
+            class_type = 'fa fa-file-text tbl_file'
+          }
+
+          var file_name_original = encodeURI(data[key]['Filename']);
+          result += '<tr class="' + cap_classes + '">';
+
+          var fm_filename = data[key]['Filename'];
+          if (fm_filename.length > 15 ) {
+              fm_filename = data[key]['Filename'].substr(0, 10) +'...';
+          }
+
+          result += '<td title="' + path + '" class="'+class_type+'">';
+          if(data[key]['Protected'] == 1) {
+            result += '<i class="fa fa-lock tbl_lock_icon" data-protected="protected"></i>';
+          }
+          if(!has_capability(data[key], 'rename'))
+            result += '<span title="' + data[key]['Filename'] + '">' + fm_filename + '</span></td>';
+          else
+            result += '<p><input type="text" class="fm_file_rename" /><span title="' + file_name_original + '">' + fm_filename + '</span></p></td>';
+
+          if(props['Size'] && props['Size'] != ''){
+            result += '<td><abbr title="' + props['Size'] + '">' + props['Size'] + '</abbr></td>';
+          } else {
+            result += '<td></td>';
+          }
+
+          if(props['Date Modified'] && props['Date Modified'] != ''){
+            result += '<td>' + props['Date Modified'] + '</td>';
+          } else {
+            result += '<td></td>';
+          }
+
+          result += '</tr>';
+        }
+
+        result += '</tbody>';
+        result += '</table>';
+      }
+    } else {
+      result += '<h1>' + lg.could_not_retrieve_folder + '</h1>';
+    }
+
+    // Add the new markup to the DOM.
+    $('.fileinfo .file_listing').html(result);
+
+    // rename file/folder
+    $('.file_manager button.rename').unbind().on('click',function(e){
+      if($('.fileinfo').data('view') == 'grid'){
+        e.stopPropagation();
+        var $this = $('.file_manager').find('#contents li.selected p'),
+            orig_value = decodeURI($this.find('span').attr('title')),
+            newvalue = orig_value.substring(0, orig_value.indexOf('.'));
+
+        if (newvalue === '')
+          newvalue = decodeURI(orig_value);
+
+        $this.find('input').toggle().val(newvalue).focus();
+        $this.find('span').toggle();
+
+        // Rename folder/file on pressing enter key
+        $('.file_manager').unbind().on('keyup', function(e) {
+          if (e.keyCode == 13) {
+            e.stopPropagation();
+            $('.fileinfo #contents li.selected p').find('input').trigger('blur');
+          }
+        });
+
+      }
+      else if($('.fileinfo').data('view') == 'list'){
+        e.stopPropagation();
+        var $this = $('.fileinfo').find('table#contents tbody tr.selected td:first-child p'),
+            orig_value = decodeURI($this.find('span').html()),
+            newvalue = orig_value.substring(0, orig_value.indexOf('.'));
+        if (newvalue === '')
+          newvalue = orig_value;
+
+        $this.find('input').toggle().val(newvalue).focus();
+        $this.find('span').toggle();
+
+        // Rename folder/file on pressing enter key
+        $('.file_manager').unbind().on('keyup', function(e) {
+          if (e.keyCode == 13) {
+            e.stopPropagation();
+            $('.fileinfo table#contents tr.selected td p').find('input').trigger('blur');
+          }
+        });
+      }
+    });
+
+    $('.fileinfo #contents li p').on('dblclick',function(e){
+      e.stopPropagation();
+      $this = $(this);
+      var orig_value = decodeURI($this.find('span').attr('title')),
+          newvalue = orig_value.substring(0, orig_value.indexOf('.'));
+
+      if (newvalue === '')
+        newvalue = orig_value;
+
+      $this.find('input').toggle().val(newvalue).focus();
+      $this.find('span').toggle();
+
+      // Rename folder/file on pressing enter key
+      $('.file_manager').unbind().on('keyup', function(e) {
+        if (e.keyCode == 13) {
+          e.stopPropagation();
+          $this.find('input').trigger('blur');
+        }
+      });
+    });
+
+    // Rename UI handling
+    $('.fileinfo #contents li p').on('blur dblclick','input', function(e){
+      e.stopPropagation();
+      var old_name = decodeURI($(this).siblings('span').attr('title')),
+          newvalue = old_name.substring(0, old_name.indexOf('.'));
+          last = getFileExtension(old_name);
+      if(old_name.indexOf('.') == 0)
+        last = ''
+
+      if (newvalue == '')
+        newvalue = decodeURI(old_name);
+
+      if(e.type=="keydown")
+      {
+        if(e.which==13)
+        {
+          var full_name = decodeURI($(this).val()) + (last !== '' ? '.' + last: '');
+          $(this).toggle();
+          $(this).siblings('span').toggle().html(full_name);
+
+          var new_name = decodeURI($(this).val()),
+              path = decodeURI($(this).parent().parent().find('span').attr('data-alt'));
+
+          var data = {
+            'Filename': old_name,
+            'Path': path,
+            'NewFilename': new_name
+          };
+
+          if (newvalue !== new_name) {
+            renameItem(data);
+            var parent = $('.currentpath').val();
+            getFolderInfo(parent);
+          }
+          e.stopPropagation();
+        }
+        if(e.which==38 || e.which==40 || e.which==37 || e.which==39 || e.keyCode == 32)
+        {
+          e.stopPropagation();
+        }
+      }
+      else if(e.type=="focusout")
+      {
+        if($(this).css('display')=="inline-block")
+        {
+          var full_name = decodeURI($(this).val()) + (last !== ''? '.' + last: '');
+          $(this).toggle();
+          $(this).siblings('span').toggle().html(full_name);
+
+          var new_name = decodeURI($(this).val()),
+              path = decodeURI($(this).parent().parent().find('span').attr('data-alt'));
+
+          var data = {
+            'Filename': old_name,
+            'Path': path,
+            'NewFilename': new_name
+          };
+
+          if (newvalue !== new_name) {
+            renameItem(data);
+            var parent = $('.currentpath').val();
+            getFolderInfo(parent);
+          }
+        }
+      }
+      else
+      {
+        e.stopPropagation();
+      }
+    });
+
+    $('.fileinfo table#contents tr td p').on('dblclick',function(e){
+      e.stopPropagation();
+      // Prompt to rename file/folder
+      $this = $(this);
+      var orig_value = decodeURI($this.find('span').attr('title')),
+          newvalue = orig_value.substring(0, orig_value.indexOf('.'));
+
+      if (newvalue === '')
+        newvalue = orig_value;
+
+      $this.find('input').toggle().val(newvalue).focus();
+      $this.find('span').toggle();
+
+      // Rename folder/file on pressing enter key
+      $('.file_manager').unbind().on('keyup', function(e) {
+        if (e.keyCode == 13) {
+          e.stopPropagation();
+          $this.find('input').trigger('blur');
+        }
+      });
+    });
+
+    $('.fileinfo table#contents tr td p').on('blur dblclick','input',function(e){
+      var old_name = decodeURI($(this).siblings('span').attr('title')),
+          newvalue = old_name.substring(0, old_name.indexOf('.'));
+          last = getFileExtension(old_name);
+      if(old_name.indexOf('.') == 0)
+        last = ''
+
+      if (newvalue == '')
+        newvalue = old_name;
+
+      if(e.type=="focusout")
+      {
+        if($(this).css('display')=="inline-block")
+        {
+          var full_name = decodeURI($(this).val()) + (last !== ''? '.' + last: '');
+          $(this).toggle();
+          $(this).siblings('span').toggle().html(full_name);
+
+          var new_name = decodeURI($(this).val()),
+              path = decodeURI($(this).parent().parent().attr('title'));
+
+          var data = {
+            'Filename': old_name,
+            'Path': path,
+            'NewFilename': new_name
+          };
+
+          if (newvalue !== new_name) {
+            renameItem(data);
+            var parent = path.split('/').reverse().slice(2).reverse().join('/') + '/';
+            getFolderInfo(parent);
+          }
+        }
+      }
+      else
+      {
+        e.stopPropagation();
+      }
+    });
+
+    /*
+     * Bind click events
+     * Select items - afolder dblclick
+     */
+    if($('.fileinfo').data('view') == 'grid'){
+      // Get into folder on dblclick
+      $('.fileinfo').find('#contents li').dblclick(function(e){
+        e.stopPropagation();
+
+        // Enable/Disable level up button
+        enab_dis_level_up();
+        var path = decodeURI($(this).find('span').attr('data-alt'));
+        if(path.lastIndexOf("/") == path.length - 1){
+          $('.file_manager_ok').addClass('disabled');
+          var $create_input = $('.create_input input[type="text"]');
+          $('.file_manager button.delete, .file_manager button.rename').attr('disabled', 'disabled');
+          $('.file_manager button.download').attr('disabled', 'disabled');
+          getFolderInfo(path);
+          if ($create_input.length != 0 && $create_input.val() != '') {
+            $('.file_manager_ok').removeClass('disabled');
+          }
+        } else {
+          getFileInfo(path);
+        }
+      });
+
+      data_cap = {}
+      data_cap['Capabilities'] = capabilities;
+      $('.fileinfo').find('#contents li').click(function(e){
+        e.stopPropagation();
+        var path = decodeURI($(this).find('.clip span').attr('data-alt')),
+            file_name = $(this).find('p span').attr('title'),
+            is_protected = $(this).find('.clip span.fm_lock_icon').attr('data-protected');
+        if(path.lastIndexOf('/') == path.length - 1){
+          if(has_capability(data_cap, 'select_folder') && is_protected == undefined) {
+            $(this).parent().find('li.selected').removeClass('selected');
+            $(this).addClass('selected');
+            $('.file_manager_ok').removeClass('disabled');
+            $('.file_manager button.delete, .file_manager button.rename').removeAttr('disabled', 'disabled');
+            $('.file_manager button.download').attr('disabled', 'disabled');
+            // set selected folder name in breadcrums
+            $('.file_manager #uploader h1').hide();
+            $('.file_manager #uploader .show_selected_file').remove();
+            $('<span class="show_selected_file">'+path+'</span>').appendTo('.file_manager #uploader .filemanager-path-group');
+          }
+          //getFolderInfo(path);
+        } else {
+          if(has_capability(data_cap, 'select_file') && is_protected == undefined) {
+            $(this).parent().find('li.selected').removeClass('selected');
+            $(this).addClass('selected');
+            $('.file_manager_ok').removeClass('disabled');
+            $('.file_manager button.delete, .file_manager button.download, .file_manager button.rename').removeAttr('disabled');
+            // set selected folder name in breadcrums
+            $('.file_manager #uploader h1').hide();
+            $('.file_manager #uploader .show_selected_file').remove();
+            $('<span class="show_selected_file">'+path+'</span>').appendTo('.file_manager #uploader .filemanager-path-group');
+          }
+          if(config.options.dialog_type == 'create_file' && is_protected == undefined) {
+            $('.create_input input[type="text"]').val(file_name);
+            $('.file_manager_ok, .file_manager_create').removeClass('disabled');
+          }
+          getFileInfo(path);
+        }
+
+      });
+    } else {
+      $('.fileinfo table#contents tbody tr').on('click', function(e){
+        e.stopPropagation();
+        var path = decodeURI($('td:first-child', this).attr('title')),
+            file_name = decodeURI($('td:first-child p span', this).attr('title')),
+            is_protected = $('td:first-child', this).find('i.tbl_lock_icon').attr('data-protected');
+        if(path.lastIndexOf('/') == path.length - 1){
+          if(has_capability(data_cap, 'select_folder') && is_protected == undefined) {
+            $(this).parent().find('tr.selected').removeClass('selected');
+            $('td:first-child', this).parent().addClass('selected');
+            $('.file_manager_ok').removeClass('disabled');
+            $('.file_manager button.download').attr('disabled', 'disabled');
+            $('.file_manager button.delete, .file_manager button.rename').removeAttr('disabled');
+            // set selected folder name in breadcrums
+            $('.file_manager #uploader h1').hide();
+            $('.file_manager #uploader .show_selected_file').remove();
+            $('<span class="show_selected_file">'+path+'</span>').appendTo('.file_manager #uploader .filemanager-path-group');
+          }
+          //getFolderInfo(path);
+        } else {
+          if(has_capability(data_cap, 'select_file') && is_protected == undefined) {
+            $(this).parent().find('tr.selected').removeClass('selected');
+            $('td:first-child', this).parent().addClass('selected');
+            $('.file_manager_ok').removeClass('disabled');
+            $('.file_manager button.delete, .file_manager button.download, .file_manager button.rename').removeAttr('disabled');
+            // set selected folder name in breadcrums
+            $('.file_manager #uploader h1').hide();
+            $('.file_manager #uploader .show_selected_file').remove();
+            $('<span class="show_selected_file">'+path+'</span>').appendTo('.file_manager #uploader .filemanager-path-group');
+          }
+          if(config.options.dialog_type == 'create_file' && is_protected == undefined) {
+            $('.create_input input[type="text"]').val(file_name);
+            $('.file_manager_ok, .file_manager_create').removeClass('disabled');
+          }
+          getFileInfo(path);
+        }
+
+
+      });
+
+      $('.fileinfo table#contents tbody tr').on('dblclick', function(e){
+        e.stopPropagation();
+
+        // Enable/Disable level up button
+        enab_dis_level_up();
+        var path = $('td:first-child', this).attr('title');
+        if(path.lastIndexOf('/') == path.length - 1){
+          $('.file_manager_ok').removeClass('disabled');
+          $('.file_manager button.download').attr('disabled', 'disabled');
+          $('.file_manager button.delete, .file_manager button.rename').attr('disabled', 'disabled');
+          getFolderInfo(path);
+        } else {
+          getFileInfo(path);
+        }
+      });
+
+    }
+   }
+  });
+};
+
+// Enable/Disable level up button
+var enab_dis_level_up = function() {
+
+  $('.file_manager #uploader h1').show();
+  $('.show_selected_file').remove();
+  setTimeout(function() {
+    var b = $('.currentpath').val(),
+        $level_up = $('.file_manager').find('button.level-up');
+        $home_btn = $('.file_manager').find('button.home');
+    if (b === fileRoot) {
+      $level_up.attr('disabled', 'disabled');
+      $home_btn.attr('disabled', 'disabled');
+    }
+    else {
+      $home_btn.removeAttr('disabled');
+      $level_up.removeAttr('disabled');
+    }
+  }, 100);
+}
+
+// Get transaction id to generate request url and
+// to generate config files on runtime
+var transId = getTransId(),
+    t_id = '';
+
+if (transId.readyState == 4)
+  t_res = JSON.parse(transId.responseText);
+t_id = t_res.data.fileTransId;
+
+var root_url = '{{ url_for("file_manager.index") }}',
+    file_manager_config_json = root_url+t_id+'/file_manager_config.json',
+    file_manager_config_js = root_url+'file_manager_config.js',
+    fileConnector = root_url+'filemanager/'+t_id+'/',
+    confg = loadConfigFile();
+
+
+// load user configuration file
+if (confg.readyState == 4)
+  config = JSON.parse(confg.responseText);
+
+var fileRoot = config.options.fileRoot,
+    capabilities = config.options.capabilities;
+
+/*
+ * Get localized messages from file
+ * through culture var or from URL
+ */
+var lg = [],
+    enjs = '{{ url_for("file_manager.index") }}'+"en.js",
+    lgf = loadLangFile(enjs);
+
+if (lgf.readyState == 4)
+  lg = JSON.parse(lgf.responseText);
+
+// Disable home button on load
+$('.file_manager').find('button.home').attr('disabled', 'disabled');
+$('.file_manager').find('button.rename').attr('disabled', 'disabled');
+
+if (config.options.dialog_type == 'select_file' ||
+	config.options.dialog_type == 'create_file' ||
+	config.options.dialog_type == 'storage_dialog') {
+
+  // Create file selection dropdown
+  var allowed_types = config.options.allowed_file_types,
+      types_len = allowed_types.length;
+  if(types_len > 0) {
+    var i = 0,
+        select_box = "<div class='change_file_types'><select name='type'>";
+    while(i < types_len) {
+      select_box += "<option value="+allowed_types[i]+">"+(allowed_types[i] == '*' ? 'All Files': allowed_types[i])+"</option>";
+      i++;
+    }
+    select_box += "</select>";
+    select_box += "<label>Format: </label></div>";
+  }
+
+  $(".allowed_file_types").html(select_box);
+
+  $(".allowed_file_types select").on('change', function() {
+    var selected_val = $(this).val(),
+        curr_path = $('.currentpath').val();
+    getFolderInfo(curr_path, selected_val);
+  });
+}
+
+if (config.options.dialog_type == 'create_file') {
+  var create_file_html = '<div class="create_input">'+
+      '<span>Filename:</span>'+
+      '<input type="text" name="new_filename" class="fm_create_input form-control" />'+
+    '</div>';
+
+  $('.create_mode_dlg').find('.allowed_file_types').prepend(create_file_html);
+
+  $('.create_input input[type="text"]').on('keypress, keydown', function() {
+    var input_text_len = $(this).val().length;
+    if(input_text_len > 0 ) {
+      $('.file_manager_ok').removeClass('disabled');
+    }
+    else {
+      $('.file_manager_ok').addClass('disabled');
+    }
+  });
+}
+/*---------------------------------------------------------
+  Initialization
+---------------------------------------------------------*/
+
+$(function(){
+  if(config.extra_js) {
+    for(var i=0; i< config.extra_js.length; i++) {
+      $.ajax({
+        url: config.extra_js[i],
+        dataType: "script",
+        async: extra_js_async
+      });
+    }
+  }
+
+  if($.urlParam('expandedFolder') != 0) {
+    expandedFolder = $.urlParam('expandedFolder');
+    fullexpandedFolder = fileRoot + expandedFolder;
+  } else {
+    expandedFolder = '';
+    fullexpandedFolder = null;
+  }
+
+  // Adjust layout.
+  setDimensions();
+
+  // we finalize the FileManager UI initialization
+  // with localized text if necessary
+  if(config.autoload == true) {
+    $('.upload').append(lg.upload);
+    $('.create').append(lg.new_folder);
+    $('.grid').attr('title', lg.grid_view);
+    $('.list').attr('title', lg.list_view);
+    $('.fileinfo h1').append(lg.select_from_left);
+    $('#itemOptions a[href$="#select"]').append(lg.select);
+    $('#itemOptions a[href$=".download"]').append(lg.download);
+    $('#itemOptions a[href$=".rename"]').append(lg.rename);
+    $('#itemOptions a[href$=".delete"]').append(lg.del);
+    /** Input file Replacement */
+    $('.browse').append('+');
+
+    $('.browse').attr('title', lg.browse);
+
+    $(".newfile").change(function() {
+      $(".filepath").val($(this).val());
+    });
+
+    /** Input file Replacement - end */
+  }
+
+  // Set initial view state.
+  $('.fileinfo').data('view', config.options.defaultViewMode);
+  setViewButtonsFor(config.options.defaultViewMode);
+
+  // Upload click event
+  $('.file_manager .uploader').on('click', 'a', function(e) {
+    e.preventDefault();
+    var b = $('.currentpath').val();
+    var node_val = $(this).next().text();
+    parent = b.substring(0, b.slice(0, -1).lastIndexOf(node_val));
+    getFolderInfo(parent);
+  });
+
+  // re-render the home view
+  $('.file_manager .home').click(function(){
+    var currentViewMode = $('.fileinfo').data('view');
+    $('.fileinfo').data('view', currentViewMode);
+    getFolderInfo(fileRoot);
+    enab_dis_level_up();
+  });
+
+  // Go one directory back
+  $(".file_manager .level-up").click(function() {
+    var b = $('.currentpath').val();
+
+    // Enable/Disable level up button
+    enab_dis_level_up();
+
+    if (b != fileRoot) {
+        parent = b.substring(0, b.slice(0, -1).lastIndexOf("/")) + "/";
+        var d = $(".fileinfo").data("view");
+        $(".fileinfo").data("view", d);
+        getFolderInfo(parent);
+    }
+  });
+
+  // set buttons to switch between grid and list views.
+  $('.file_manager .grid').click(function(){
+    setViewButtonsFor('grid');
+    $('.fileinfo').data('view', 'grid');
+    enable_disable_btn();
+    getFolderInfo($('.currentpath').val());
+  });
+
+  // Show list mode
+  $('.file_manager .list').click(function(){
+    setViewButtonsFor('list');
+    $('.fileinfo').data('view', 'list');
+    enable_disable_btn();
+    getFolderInfo($('.currentpath').val());
+  });
+
+  // Provide initial values for upload form, status, etc.
+  setUploader(fileRoot);
+
+  $('#uploader').attr('action', fileConnector);
+
+  data = {
+    'Capabilities': capabilities
+  };
+  if (has_capability(data, 'upload')) {
+    Dropzone.autoDiscover = false;
+    // we remove simple file upload element
+    $('.file-input-container').remove();
+    $('.upload').remove();
+    $( ".create" ).before( '<button value="Upload" type="button" title="Upload File" name="upload" id="upload" class="btn fa fa-upload upload"><span></span></button> ' );
+
+    $('.upload').unbind().click(function() {
+      // we create prompt
+      var msg  = '<div id="dropzone-container">';
+        msg += '<button class="fa fa-times dz_cross_btn"></button>';
+        msg += '<div id="multiple-uploads" class="dropzone"></div>';
+        msg += '<div class="prompt-info">'+lg.file_size_limit + config.upload.fileSizeLimit + ' ' + lg.mb + '.</div>';
+
+      error_flag = false;
+      var path = $('.currentpath').val(),
+          fileSize = (config.upload.fileSizeLimit != 'auto') ? config.upload.fileSizeLimit : 256; // default dropzone value
+
+      if(config.security.uploadPolicy == 'DISALLOW_ALL') {
+        var allowedFiles = '.' + config.security.uploadRestrictions.join(',.');
+      } else {
+        // we allow any extension since we have no easy way to handle the the built-in `acceptedFiles` params
+        // Would be handled later by the connector
+        var allowedFiles = null;
+      }
+
+      if ($.urlParam('type').toString().toLowerCase() == 'images' || config.upload.imagesOnly) {
+        var allowedFiles = '.' + config.images.imagesExt.join(',.');
+      }
+
+      $('.file_manager .upload_file').toggle();
+      $('.file_manager .upload_file').html(msg);
+
+      //var previewTemplate = '<div id="dropzone-container">';
+      var previewTemplate = '<div class="file_upload_main dz-preview dz-file-preview">'+
+            '<div class="show_error">'+
+              '<p class="size dz-size" data-dz-size></p>'+
+              '<p class="name dz-filename" data-dz-name></p>'+
+            '</div>'+
+            '<div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>'+
+            '<div class="dz-success-mark"><span></span></div>'+
+            '<div class="dz-error-mark"><span></span></div>'+
+            '<div class="dz-error-message"><span data-dz-errormessage></span></div>'+
+            '<a href="javascript:void(0);" class="fa fa-trash dz_file_remove" data-dz-remove></a>'+
+          '</div>';
+
+      $("div#multiple-uploads").dropzone({
+        paramName: "newfile",
+        url: fileConnector + '?config=' + userconfig,
+        maxFilesize: fileSize,
+        maxFiles: config.upload.number,
+        addRemoveLinks: true,
+        previewTemplate: previewTemplate,
+        parallelUploads: config.upload.number,
+        dictMaxFilesExceeded: lg.dz_dictMaxFilesExceeded.replace("%s", config.upload.number),
+        dictDefaultMessage: lg.dz_dictDefaultMessage,
+        dictInvalidFileType: lg.dz_dictInvalidFileType,
+        dictFileTooBig: lg.file_too_big + ' ' + lg.file_size_limit + config.upload.fileSizeLimit + ' ' + lg.mb,
+        acceptedFiles: allowedFiles,
+        autoProcessQueue: true,
+        init: function() {
+          var dropzone = this;
+          $('.dz_cross_btn').unbind().on('click', function() {
+            $('.file_manager .upload_file').toggle();
+          });
+
+        },
+        sending: function(file, xhr, formData) {
+          formData.append("mode", "add");
+          formData.append("currentpath", path);
+          $('.upload_file .dz_cross_btn').attr('disabled', 'disabled');
+          setTimeout(function() {}, 10000);
+        },
+        success: function(file, response) {
+          var response = jQuery.parseJSON(response),
+              data = response.data.result,
+              $this = $(file.previewTemplate);
+
+          if (data['Code'] == 0) {
+            setTimeout(function(){
+              $this.find(".dz-upload").addClass("success");
+            }, 1000);
+            $this.find(".dz-upload").css('width', "100%").html("100%");
+            alertify.success(lg.upload_success);
+          } else {
+            $this.find(".dz-upload").addClass("error");
+            $this.find(".dz-upload").css('width', "0%").html("0%");
+            alertify.error(data['Error']);
+          }
+          getFolderInfo(path);
+        },
+        totaluploadprogress: function(progress) {
+        },
+        complete: function(file) {
+          if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
+          }
+          if (file.status == "error") {
+            alertify.error(lg.ERROR_UPLOADING_FILE);
+          }
+          $('.upload_file .dz_cross_btn').removeAttr('disabled');
+          getFolderInfo(path);
+        }
+      });
+
+    });
+  }
+
+  // Disable select function if no window.opener
+  if(! (window.opener || window.tinyMCEPopup) ) $('#itemOptions a[href$="#select"]').remove();
+  // Keep only browseOnly features if needed
+  if(config.options.browseOnly == true) {
+    $('.newfile').remove();
+    $('.upload').remove();
+    $('.create').remove();
+    $('#toolbar').remove('.rename');
+    $('.contextMenu .rename').remove();
+    $('.contextMenu .delete').remove();
+  }
+  getDetailView(fileRoot + expandedFolder);
+});
+
+})(jQuery);
diff --git a/web/pgadmin/static/css/jquery.dropzone/dropzone.css b/web/pgadmin/static/css/jquery.dropzone/dropzone.css
new file mode 100644
index 0000000..0494d1c
--- /dev/null
+++ b/web/pgadmin/static/css/jquery.dropzone/dropzone.css
@@ -0,0 +1,388 @@
+/*
+ * The MIT License
+ * Copyright (c) 2012 Matias Meno <[email protected]>
+ */
+@-webkit-keyframes passing-through {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30%, 70% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); }
+  100% {
+    opacity: 0;
+    -webkit-transform: translateY(-40px);
+    -moz-transform: translateY(-40px);
+    -ms-transform: translateY(-40px);
+    -o-transform: translateY(-40px);
+    transform: translateY(-40px); } }
+@-moz-keyframes passing-through {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30%, 70% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); }
+  100% {
+    opacity: 0;
+    -webkit-transform: translateY(-40px);
+    -moz-transform: translateY(-40px);
+    -ms-transform: translateY(-40px);
+    -o-transform: translateY(-40px);
+    transform: translateY(-40px); } }
+@keyframes passing-through {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30%, 70% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); }
+  100% {
+    opacity: 0;
+    -webkit-transform: translateY(-40px);
+    -moz-transform: translateY(-40px);
+    -ms-transform: translateY(-40px);
+    -o-transform: translateY(-40px);
+    transform: translateY(-40px); } }
+@-webkit-keyframes slide-in {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); } }
+@-moz-keyframes slide-in {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); } }
+@keyframes slide-in {
+  0% {
+    opacity: 0;
+    -webkit-transform: translateY(40px);
+    -moz-transform: translateY(40px);
+    -ms-transform: translateY(40px);
+    -o-transform: translateY(40px);
+    transform: translateY(40px); }
+  30% {
+    opacity: 1;
+    -webkit-transform: translateY(0px);
+    -moz-transform: translateY(0px);
+    -ms-transform: translateY(0px);
+    -o-transform: translateY(0px);
+    transform: translateY(0px); } }
+@-webkit-keyframes pulse {
+  0% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); }
+  10% {
+    -webkit-transform: scale(1.1);
+    -moz-transform: scale(1.1);
+    -ms-transform: scale(1.1);
+    -o-transform: scale(1.1);
+    transform: scale(1.1); }
+  20% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); } }
+@-moz-keyframes pulse {
+  0% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); }
+  10% {
+    -webkit-transform: scale(1.1);
+    -moz-transform: scale(1.1);
+    -ms-transform: scale(1.1);
+    -o-transform: scale(1.1);
+    transform: scale(1.1); }
+  20% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); } }
+@keyframes pulse {
+  0% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); }
+  10% {
+    -webkit-transform: scale(1.1);
+    -moz-transform: scale(1.1);
+    -ms-transform: scale(1.1);
+    -o-transform: scale(1.1);
+    transform: scale(1.1); }
+  20% {
+    -webkit-transform: scale(1);
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -o-transform: scale(1);
+    transform: scale(1); } }
+.dropzone, .dropzone * {
+  box-sizing: border-box; }
+
+.dropzone {
+  min-height: 150px;
+  border: 2px solid rgba(0, 0, 0, 0.3);
+  background: white;
+  padding: 20px 20px; }
+  .dropzone.dz-clickable {
+    cursor: pointer; }
+    .dropzone.dz-clickable * {
+      cursor: default; }
+    .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {
+      cursor: pointer; }
+  .dropzone.dz-started .dz-message {
+    display: none; }
+  .dropzone.dz-drag-hover {
+    border-style: solid; }
+    .dropzone.dz-drag-hover .dz-message {
+      opacity: 0.5; }
+  .dropzone .dz-message {
+    text-align: center;
+    margin: 2em 0; }
+  .dropzone .dz-preview {
+    position: relative;
+    display: inline-block;
+    vertical-align: top;
+    margin: 16px;
+    min-height: 100px; }
+    .dropzone .dz-preview:hover {
+      z-index: 1000; }
+      .dropzone .dz-preview:hover .dz-details {
+        opacity: 1; }
+    .dropzone .dz-preview.dz-file-preview .dz-image {
+      border-radius: 20px;
+      background: #999;
+      background: linear-gradient(to bottom, #eee, #ddd); }
+    .dropzone .dz-preview.dz-file-preview .dz-details {
+      opacity: 1; }
+    .dropzone .dz-preview.dz-image-preview {
+      background: white; }
+      .dropzone .dz-preview.dz-image-preview .dz-details {
+        -webkit-transition: opacity 0.2s linear;
+        -moz-transition: opacity 0.2s linear;
+        -ms-transition: opacity 0.2s linear;
+        -o-transition: opacity 0.2s linear;
+        transition: opacity 0.2s linear; }
+    .dropzone .dz-preview .dz-remove {
+      font-size: 14px;
+      text-align: center;
+      display: block;
+      cursor: pointer;
+      border: none; }
+      .dropzone .dz-preview .dz-remove:hover {
+        text-decoration: underline; }
+    .dropzone .dz-preview:hover .dz-details {
+      opacity: 1; }
+    .dropzone .dz-preview .dz-details {
+      z-index: 20;
+      position: absolute;
+      top: 0;
+      left: 0;
+      opacity: 0;
+      font-size: 13px;
+      min-width: 100%;
+      max-width: 100%;
+      padding: 2em 1em;
+      text-align: center;
+      color: rgba(0, 0, 0, 0.9);
+      line-height: 150%; }
+      .dropzone .dz-preview .dz-details .dz-size {
+        margin-bottom: 1em;
+        font-size: 16px; }
+      .dropzone .dz-preview .dz-details .dz-filename {
+        white-space: nowrap; }
+        .dropzone .dz-preview .dz-details .dz-filename:hover span {
+          border: 1px solid rgba(200, 200, 200, 0.8);
+          background-color: rgba(255, 255, 255, 0.8); }
+        .dropzone .dz-preview .dz-details .dz-filename:not(:hover) {
+          overflow: hidden;
+          text-overflow: ellipsis; }
+          .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
+            border: 1px solid transparent; }
+      .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
+        background-color: rgba(255, 255, 255, 0.4);
+        padding: 0 0.4em;
+        border-radius: 3px; }
+    .dropzone .dz-preview:hover .dz-image img {
+      -webkit-transform: scale(1.05, 1.05);
+      -moz-transform: scale(1.05, 1.05);
+      -ms-transform: scale(1.05, 1.05);
+      -o-transform: scale(1.05, 1.05);
+      transform: scale(1.05, 1.05);
+      -webkit-filter: blur(8px);
+      filter: blur(8px); }
+    .dropzone .dz-preview .dz-image {
+      border-radius: 20px;
+      overflow: hidden;
+      width: 120px;
+      height: 120px;
+      position: relative;
+      display: block;
+      z-index: 10; }
+      .dropzone .dz-preview .dz-image img {
+        display: block; }
+    .dropzone .dz-preview.dz-success .dz-success-mark {
+      -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);
+      animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }
+    .dropzone .dz-preview.dz-error .dz-error-mark {
+      opacity: 1;
+      -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+      -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);
+      animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }
+    .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
+      pointer-events: none;
+      opacity: 0;
+      z-index: 500;
+      position: absolute;
+      display: block;
+      top: 50%;
+      left: 50%;
+      margin-left: -27px;
+      margin-top: -27px; }
+      .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {
+        display: block;
+        width: 54px;
+        height: 54px; }
+    .dropzone .dz-preview.dz-processing .dz-progress {
+      opacity: 1;
+      -webkit-transition: all 0.2s linear;
+      -moz-transition: all 0.2s linear;
+      -ms-transition: all 0.2s linear;
+      -o-transition: all 0.2s linear;
+      transition: all 0.2s linear; }
+    .dropzone .dz-preview.dz-complete .dz-progress {
+      opacity: 0;
+      -webkit-transition: opacity 0.4s ease-in;
+      -moz-transition: opacity 0.4s ease-in;
+      -ms-transition: opacity 0.4s ease-in;
+      -o-transition: opacity 0.4s ease-in;
+      transition: opacity 0.4s ease-in; }
+    .dropzone .dz-preview:not(.dz-processing) .dz-progress {
+      -webkit-animation: pulse 6s ease infinite;
+      -moz-animation: pulse 6s ease infinite;
+      -ms-animation: pulse 6s ease infinite;
+      -o-animation: pulse 6s ease infinite;
+      animation: pulse 6s ease infinite; }
+    .dropzone .dz-preview .dz-progress {
+      opacity: 1;
+      z-index: 1000;
+      pointer-events: none;
+      position: absolute;
+      height: 16px;
+      left: 50%;
+      top: 50%;
+      margin-top: -8px;
+      width: 80px;
+      margin-left: -40px;
+      background: rgba(255, 255, 255, 0.9);
+      -webkit-transform: scale(1);
+      border-radius: 8px;
+      overflow: hidden; }
+      .dropzone .dz-preview .dz-progress .dz-upload {
+        background: #333;
+        background: linear-gradient(to bottom, #666, #444);
+        position: absolute;
+        top: 0;
+        left: 0;
+        bottom: 0;
+        width: 0;
+        -webkit-transition: width 300ms ease-in-out;
+        -moz-transition: width 300ms ease-in-out;
+        -ms-transition: width 300ms ease-in-out;
+        -o-transition: width 300ms ease-in-out;
+        transition: width 300ms ease-in-out; }
+    .dropzone .dz-preview.dz-error .dz-error-message {
+      display: block; }
+    .dropzone .dz-preview.dz-error:hover .dz-error-message {
+      opacity: 1;
+      pointer-events: auto; }
+    .dropzone .dz-preview .dz-error-message {
+      pointer-events: none;
+      z-index: 1000;
+      position: absolute;
+      display: block;
+      display: none;
+      opacity: 0;
+      -webkit-transition: opacity 0.3s ease;
+      -moz-transition: opacity 0.3s ease;
+      -ms-transition: opacity 0.3s ease;
+      -o-transition: opacity 0.3s ease;
+      transition: opacity 0.3s ease;
+      border-radius: 8px;
+      font-size: 13px;
+      top: 130px;
+      left: -10px;
+      width: 140px;
+      background: #be2626;
+      background: linear-gradient(to bottom, #be2626, #a92222);
+      padding: 0.5em 1.2em;
+      color: white; }
+      .dropzone .dz-preview .dz-error-message:after {
+        content: '';
+        position: absolute;
+        top: -6px;
+        left: 64px;
+        width: 0;
+        height: 0;
+        border-left: 6px solid transparent;
+        border-right: 6px solid transparent;
+        border-bottom: 6px solid #be2626; }
diff --git a/web/pgadmin/static/css/overrides.css b/web/pgadmin/static/css/overrides.css
index 00a9829..d37db64 100755
--- a/web/pgadmin/static/css/overrides.css
+++ b/web/pgadmin/static/css/overrides.css
@@ -1104,4 +1104,55 @@ div.backform_control_notes label.control-label {
 
 form[name="change_password_form"] .help-block {
     color: #A94442 !important;
-}
\ No newline at end of file
+}
+
+
+.file_selection_ctrl .create_input span {
+  padding-right: 10px;
+  font-weight: bold;
+}
+
+.file_selection_ctrl .create_input input[type="text"] {
+  height: 23px;
+  padding: 2px;
+  width: 194px;
+  border-radius: 2px;
+}
+
+.file_selection_ctrl .browse_file_input {
+  display: inline-block;
+  width: 220px;
+  margin-right: 0;
+}
+
+.file_selection_ctrl button.select_item {
+  display: inline;
+  background: #777;
+  background: -webkit-linear-gradient(#777, #999999);
+  background: -o-linear-gradient(#777, #999);
+  background: -moz-linear-gradient(#777, #999);
+  background: linear-gradient(#777, #999);
+  color: #fff;
+  padding: 9px 0px 9px 0px;
+  margin-left: 0px;
+  margin-right: -7px;
+  margin-top: -4px;
+  min-width: 30px;
+  border-top-left-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.file_selection_ctrl button.select_item:focus,
+.file_selection_ctrl button.select_item:active {
+  outline: none;
+  box-shadow: none;
+}
+
+.file_selection_ctrl input[type="text"] {
+  width: calc(100% - 17px);
+  border: none;
+  margin-left: -6px;
+  margin-top: -3px;
+  height: 32px;
+  padding-left: 5px;
+}
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 201ecc1..125e133 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -2038,5 +2038,71 @@
     ].join("\n"))
   });
 
+  /*
+  * Input File Control: This control is used with Storage Manager Dialog,
+  * It allows user to perform following operations:
+  * - Select File
+  * - Select Folder
+  * - Create File
+  * - Opening Storage Manager Dialog itself.
+  */
+  var FileControl = Backform.FileControl = Backform.InputControl.extend({
+    defaults: {
+      type: "text",
+      label: "",
+      min: undefined,
+      max: undefined,
+      maxlength: 255,
+      extraClasses: [],
+      dialog_title: '',
+      btn_primary: '',
+      helpMessage: null,
+      dialog_type: 'select_file'
+    },
+    initialize: function(){
+      Backform.InputControl.prototype.initialize.apply(this, arguments);
+
+      // Listen click events of Storage Manager dialog buttons
+      pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:'+this.field.get('dialog_type'), this.storage_dlg_hander, this);
+    },
+    template: _.template([
+      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
+      '<div class="<%=Backform.controlsClassName%>">',
+        '<div class="file_selection_ctrl form-control">',
+          '<input type="<%=type%>" class="browse_file_input form-control <%=extraClasses.join(\' \')%>" name="<%=name%>" min="<%=min%>" max="<%=max%>"maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
+          '<button class="btn fa fa-ellipsis-h select_item pull-right" <%=disabled ? "disabled" : ""%> ></button>',
+          '<% if (helpMessage && helpMessage.length) { %>',
+          '<span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
+          '<% } %>',
+        '</div>',
+      '</div>'
+    ].join("\n")),
+    events: {
+      "click .select_item": "onSelect",
+    },
+    onSelect: function(e) {
+      var dialog_type = this.field.get('dialog_type');
+          supp_types = this.field.get('supp_types'),
+          btn_primary = this.field.get('btn_primary'),
+          dialog_title = this.field.get('dialog_title');
+      var params = {
+        supported_types: supp_types,
+        dialog_type: dialog_type,
+        dialog_title: dialog_title,
+        btn_primary: btn_primary
+      };
+      pgAdmin.FileManager.init();
+      pgAdmin.FileManager.show_dialog(params);
+    },
+    storage_dlg_hander: function(value) {
+      var field = _.defaults(this.field.toJSON(), this.defaults),
+          attrArr = this.field.get("name").split('.'),
+          name = attrArr.shift();
+
+      // Set selected value into the model
+      this.model.set(name, decodeURI(value));
+    }
+  });
+
   return Backform;
 }));
diff --git a/web/pgadmin/static/js/jquery.dropzone/dropzone.js b/web/pgadmin/static/js/jquery.dropzone/dropzone.js
new file mode 100644
index 0000000..dd5f39e
--- /dev/null
+++ b/web/pgadmin/static/js/jquery.dropzone/dropzone.js
@@ -0,0 +1,1767 @@
+
+/*
+ *
+ * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
+ *
+ * Copyright (c) 2012, Matias Meno
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+(function() {
+  var Dropzone, Emitter, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without,
+    __slice = [].slice,
+    __hasProp = {}.hasOwnProperty,
+    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+  noop = function() {};
+
+  Emitter = (function() {
+    function Emitter() {}
+
+    Emitter.prototype.addEventListener = Emitter.prototype.on;
+
+    Emitter.prototype.on = function(event, fn) {
+      this._callbacks = this._callbacks || {};
+      if (!this._callbacks[event]) {
+        this._callbacks[event] = [];
+      }
+      this._callbacks[event].push(fn);
+      return this;
+    };
+
+    Emitter.prototype.emit = function() {
+      var args, callback, callbacks, event, _i, _len;
+      event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+      this._callbacks = this._callbacks || {};
+      callbacks = this._callbacks[event];
+      if (callbacks) {
+        for (_i = 0, _len = callbacks.length; _i < _len; _i++) {
+          callback = callbacks[_i];
+          callback.apply(this, args);
+        }
+      }
+      return this;
+    };
+
+    Emitter.prototype.removeListener = Emitter.prototype.off;
+
+    Emitter.prototype.removeAllListeners = Emitter.prototype.off;
+
+    Emitter.prototype.removeEventListener = Emitter.prototype.off;
+
+    Emitter.prototype.off = function(event, fn) {
+      var callback, callbacks, i, _i, _len;
+      if (!this._callbacks || arguments.length === 0) {
+        this._callbacks = {};
+        return this;
+      }
+      callbacks = this._callbacks[event];
+      if (!callbacks) {
+        return this;
+      }
+      if (arguments.length === 1) {
+        delete this._callbacks[event];
+        return this;
+      }
+      for (i = _i = 0, _len = callbacks.length; _i < _len; i = ++_i) {
+        callback = callbacks[i];
+        if (callback === fn) {
+          callbacks.splice(i, 1);
+          break;
+        }
+      }
+      return this;
+    };
+
+    return Emitter;
+
+  })();
+
+  Dropzone = (function(_super) {
+    var extend, resolveOption;
+
+    __extends(Dropzone, _super);
+
+    Dropzone.prototype.Emitter = Emitter;
+
+
+    /*
+    This is a list of all available events you can register on a dropzone object.
+
+    You can register an event handler like this:
+
+        dropzone.on("dragEnter", function() { });
+     */
+
+    Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
+
+    Dropzone.prototype.defaultOptions = {
+      url: null,
+      method: "post",
+      withCredentials: false,
+      parallelUploads: 2,
+      uploadMultiple: false,
+      maxFilesize: 256,
+      paramName: "file",
+      createImageThumbnails: true,
+      maxThumbnailFilesize: 10,
+      thumbnailWidth: 120,
+      thumbnailHeight: 120,
+      filesizeBase: 1000,
+      maxFiles: null,
+      params: {},
+      clickable: true,
+      ignoreHiddenFiles: true,
+      acceptedFiles: null,
+      acceptedMimeTypes: null,
+      autoProcessQueue: true,
+      autoQueue: true,
+      addRemoveLinks: false,
+      previewsContainer: null,
+      hiddenInputContainer: "body",
+      capture: null,
+      renameFilename: null,
+      dictDefaultMessage: "Drop files here to upload",
+      dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
+      dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",
+      dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
+      dictInvalidFileType: "You can't upload files of this type.",
+      dictResponseError: "Server responded with {{statusCode}} code.",
+      dictCancelUpload: "Cancel upload",
+      dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
+      dictRemoveFile: "Remove file",
+      dictRemoveFileConfirmation: null,
+      dictMaxFilesExceeded: "You can not upload any more files.",
+      accept: function(file, done) {
+        return done();
+      },
+      init: function() {
+        return noop;
+      },
+      forceFallback: false,
+      fallback: function() {
+        var child, messageElement, span, _i, _len, _ref;
+        this.element.className = "" + this.element.className + " dz-browser-not-supported";
+        _ref = this.element.getElementsByTagName("div");
+        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+          child = _ref[_i];
+          if (/(^| )dz-message($| )/.test(child.className)) {
+            messageElement = child;
+            child.className = "dz-message";
+            continue;
+          }
+        }
+        if (!messageElement) {
+          messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
+          this.element.appendChild(messageElement);
+        }
+        span = messageElement.getElementsByTagName("span")[0];
+        if (span) {
+          if (span.textContent != null) {
+            span.textContent = this.options.dictFallbackMessage;
+          } else if (span.innerText != null) {
+            span.innerText = this.options.dictFallbackMessage;
+          }
+        }
+        return this.element.appendChild(this.getFallbackForm());
+      },
+      resize: function(file) {
+        var info, srcRatio, trgRatio;
+        info = {
+          srcX: 0,
+          srcY: 0,
+          srcWidth: file.width,
+          srcHeight: file.height
+        };
+        srcRatio = file.width / file.height;
+        info.optWidth = this.options.thumbnailWidth;
+        info.optHeight = this.options.thumbnailHeight;
+        if ((info.optWidth == null) && (info.optHeight == null)) {
+          info.optWidth = info.srcWidth;
+          info.optHeight = info.srcHeight;
+        } else if (info.optWidth == null) {
+          info.optWidth = srcRatio * info.optHeight;
+        } else if (info.optHeight == null) {
+          info.optHeight = (1 / srcRatio) * info.optWidth;
+        }
+        trgRatio = info.optWidth / info.optHeight;
+        if (file.height < info.optHeight || file.width < info.optWidth) {
+          info.trgHeight = info.srcHeight;
+          info.trgWidth = info.srcWidth;
+        } else {
+          if (srcRatio > trgRatio) {
+            info.srcHeight = file.height;
+            info.srcWidth = info.srcHeight * trgRatio;
+          } else {
+            info.srcWidth = file.width;
+            info.srcHeight = info.srcWidth / trgRatio;
+          }
+        }
+        info.srcX = (file.width - info.srcWidth) / 2;
+        info.srcY = (file.height - info.srcHeight) / 2;
+        return info;
+      },
+
+      /*
+      Those functions register themselves to the events on init and handle all
+      the user interface specific stuff. Overwriting them won't break the upload
+      but can break the way it's displayed.
+      You can overwrite them if you don't like the default behavior. If you just
+      want to add an additional event handler, register it on the dropzone object
+      and don't overwrite those options.
+       */
+      drop: function(e) {
+        return this.element.classList.remove("dz-drag-hover");
+      },
+      dragstart: noop,
+      dragend: function(e) {
+        return this.element.classList.remove("dz-drag-hover");
+      },
+      dragenter: function(e) {
+        return this.element.classList.add("dz-drag-hover");
+      },
+      dragover: function(e) {
+        return this.element.classList.add("dz-drag-hover");
+      },
+      dragleave: function(e) {
+        return this.element.classList.remove("dz-drag-hover");
+      },
+      paste: noop,
+      reset: function() {
+        return this.element.classList.remove("dz-started");
+      },
+      addedfile: function(file) {
+        var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
+        if (this.element === this.previewsContainer) {
+          this.element.classList.add("dz-started");
+        }
+        if (this.previewsContainer) {
+          file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
+          file.previewTemplate = file.previewElement;
+          this.previewsContainer.appendChild(file.previewElement);
+          _ref = file.previewElement.querySelectorAll("[data-dz-name]");
+          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+            node = _ref[_i];
+            node.textContent = this._renameFilename(file.name);
+          }
+          _ref1 = file.previewElement.querySelectorAll("[data-dz-size]");
+          for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
+            node = _ref1[_j];
+            node.innerHTML = this.filesize(file.size);
+          }
+          if (this.options.addRemoveLinks) {
+            file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
+            file.previewElement.appendChild(file._removeLink);
+          }
+          removeFileEvent = (function(_this) {
+            return function(e) {
+              e.preventDefault();
+              e.stopPropagation();
+              if (file.status === Dropzone.UPLOADING) {
+                return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {
+                  return _this.removeFile(file);
+                });
+              } else {
+                if (_this.options.dictRemoveFileConfirmation) {
+                  return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {
+                    return _this.removeFile(file);
+                  });
+                } else {
+                  return _this.removeFile(file);
+                }
+              }
+            };
+          })(this);
+          _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]");
+          _results = [];
+          for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+            removeLink = _ref2[_k];
+            _results.push(removeLink.addEventListener("click", removeFileEvent));
+          }
+          return _results;
+        }
+      },
+      removedfile: function(file) {
+        var _ref;
+        if (file.previewElement) {
+          if ((_ref = file.previewElement) != null) {
+            _ref.parentNode.removeChild(file.previewElement);
+          }
+        }
+        return this._updateMaxFilesReachedClass();
+      },
+      thumbnail: function(file, dataUrl) {
+        var thumbnailElement, _i, _len, _ref;
+        if (file.previewElement) {
+          file.previewElement.classList.remove("dz-file-preview");
+          _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]");
+          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+            thumbnailElement = _ref[_i];
+            thumbnailElement.alt = file.name;
+            thumbnailElement.src = dataUrl;
+          }
+          return setTimeout(((function(_this) {
+            return function() {
+              return file.previewElement.classList.add("dz-image-preview");
+            };
+          })(this)), 1);
+        }
+      },
+      error: function(file, message) {
+        var node, _i, _len, _ref, _results;
+        if (file.previewElement) {
+          file.previewElement.classList.add("dz-error");
+          if (typeof message !== "String" && message.error) {
+            message = message.error;
+          }
+          _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]");
+          _results = [];
+          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+            node = _ref[_i];
+            _results.push(node.textContent = message);
+          }
+          return _results;
+        }
+      },
+      errormultiple: noop,
+      processing: function(file) {
+        if (file.previewElement) {
+          file.previewElement.classList.add("dz-processing");
+          if (file._removeLink) {
+            return file._removeLink.textContent = this.options.dictCancelUpload;
+          }
+        }
+      },
+      processingmultiple: noop,
+      uploadprogress: function(file, progress, bytesSent) {
+        var node, _i, _len, _ref, _results;
+        if (file.previewElement) {
+          _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]");
+          _results = [];
+          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+            node = _ref[_i];
+            if (node.nodeName === 'PROGRESS') {
+              _results.push(node.value = progress);
+            } else {
+              _results.push(node.style.width = "" + progress + "%");
+            }
+          }
+          return _results;
+        }
+      },
+      totaluploadprogress: noop,
+      sending: noop,
+      sendingmultiple: noop,
+      success: function(file) {
+        if (file.previewElement) {
+          return file.previewElement.classList.add("dz-success");
+        }
+      },
+      successmultiple: noop,
+      canceled: function(file) {
+        return this.emit("error", file, "Upload canceled.");
+      },
+      canceledmultiple: noop,
+      complete: function(file) {
+        if (file._removeLink) {
+          file._removeLink.textContent = this.options.dictRemoveFile;
+        }
+        if (file.previewElement) {
+          return file.previewElement.classList.add("dz-complete");
+        }
+      },
+      completemultiple: noop,
+      maxfilesexceeded: noop,
+      maxfilesreached: noop,
+      queuecomplete: noop,
+      addedfiles: noop,
+      previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Check</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\" sketch:type=\"MSShapeGroup\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:sketch=\"http://www.bohemiancoding.com/sketch/ns\">\n      <title>Error</title>\n      <defs></defs>\n      <g id=\"Page-1\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\" sketch:type=\"MSPage\">\n        <g id=\"Check-+-Oval-2\" sketch:type=\"MSLayerGroup\" stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" id=\"Oval-2\" sketch:type=\"MSShapeGroup\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>"
+    };
+
+    extend = function() {
+      var key, object, objects, target, val, _i, _len;
+      target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+      for (_i = 0, _len = objects.length; _i < _len; _i++) {
+        object = objects[_i];
+        for (key in object) {
+          val = object[key];
+          target[key] = val;
+        }
+      }
+      return target;
+    };
+
+    function Dropzone(element, options) {
+      var elementOptions, fallback, _ref;
+      this.element = element;
+      this.version = Dropzone.version;
+      this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, "");
+      this.clickableElements = [];
+      this.listeners = [];
+      this.files = [];
+      if (typeof this.element === "string") {
+        this.element = document.querySelector(this.element);
+      }
+      if (!(this.element && (this.element.nodeType != null))) {
+        throw new Error("Invalid dropzone element.");
+      }
+      if (this.element.dropzone) {
+        throw new Error("Dropzone already attached.");
+      }
+      Dropzone.instances.push(this);
+      this.element.dropzone = this;
+      elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};
+      this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});
+      if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {
+        return this.options.fallback.call(this);
+      }
+      if (this.options.url == null) {
+        this.options.url = this.element.getAttribute("action");
+      }
+      if (!this.options.url) {
+        throw new Error("No URL provided.");
+      }
+      if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {
+        throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
+      }
+      if (this.options.acceptedMimeTypes) {
+        this.options.acceptedFiles = this.options.acceptedMimeTypes;
+        delete this.options.acceptedMimeTypes;
+      }
+      this.options.method = this.options.method.toUpperCase();
+      if ((fallback = this.getExistingFallback()) && fallback.parentNode) {
+        fallback.parentNode.removeChild(fallback);
+      }
+      if (this.options.previewsContainer !== false) {
+        if (this.options.previewsContainer) {
+          this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer");
+        } else {
+          this.previewsContainer = this.element;
+        }
+      }
+      if (this.options.clickable) {
+        if (this.options.clickable === true) {
+          this.clickableElements = [this.element];
+        } else {
+          this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable");
+        }
+      }
+      this.init();
+    }
+
+    Dropzone.prototype.getAcceptedFiles = function() {
+      var file, _i, _len, _ref, _results;
+      _ref = this.files;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        if (file.accepted) {
+          _results.push(file);
+        }
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.getRejectedFiles = function() {
+      var file, _i, _len, _ref, _results;
+      _ref = this.files;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        if (!file.accepted) {
+          _results.push(file);
+        }
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.getFilesWithStatus = function(status) {
+      var file, _i, _len, _ref, _results;
+      _ref = this.files;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        if (file.status === status) {
+          _results.push(file);
+        }
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.getQueuedFiles = function() {
+      return this.getFilesWithStatus(Dropzone.QUEUED);
+    };
+
+    Dropzone.prototype.getUploadingFiles = function() {
+      return this.getFilesWithStatus(Dropzone.UPLOADING);
+    };
+
+    Dropzone.prototype.getAddedFiles = function() {
+      return this.getFilesWithStatus(Dropzone.ADDED);
+    };
+
+    Dropzone.prototype.getActiveFiles = function() {
+      var file, _i, _len, _ref, _results;
+      _ref = this.files;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {
+          _results.push(file);
+        }
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.init = function() {
+      var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1;
+      if (this.element.tagName === "form") {
+        this.element.setAttribute("enctype", "multipart/form-data");
+      }
+      if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
+        this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
+      }
+      if (this.clickableElements.length) {
+        setupHiddenFileInput = (function(_this) {
+          return function() {
+            if (_this.hiddenFileInput) {
+              _this.hiddenFileInput.parentNode.removeChild(_this.hiddenFileInput);
+            }
+            _this.hiddenFileInput = document.createElement("input");
+            _this.hiddenFileInput.setAttribute("type", "file");
+            if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {
+              _this.hiddenFileInput.setAttribute("multiple", "multiple");
+            }
+            _this.hiddenFileInput.className = "dz-hidden-input";
+            if (_this.options.acceptedFiles != null) {
+              _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles);
+            }
+            if (_this.options.capture != null) {
+              _this.hiddenFileInput.setAttribute("capture", _this.options.capture);
+            }
+            _this.hiddenFileInput.style.visibility = "hidden";
+            _this.hiddenFileInput.style.position = "absolute";
+            _this.hiddenFileInput.style.top = "0";
+            _this.hiddenFileInput.style.left = "0";
+            _this.hiddenFileInput.style.height = "0";
+            _this.hiddenFileInput.style.width = "0";
+            document.querySelector(_this.options.hiddenInputContainer).appendChild(_this.hiddenFileInput);
+            return _this.hiddenFileInput.addEventListener("change", function() {
+              var file, files, _i, _len;
+              files = _this.hiddenFileInput.files;
+              if (files.length) {
+                for (_i = 0, _len = files.length; _i < _len; _i++) {
+                  file = files[_i];
+                  _this.addFile(file);
+                }
+              }
+              _this.emit("addedfiles", files);
+              return setupHiddenFileInput();
+            });
+          };
+        })(this);
+        setupHiddenFileInput();
+      }
+      this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL;
+      _ref1 = this.events;
+      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+        eventName = _ref1[_i];
+        this.on(eventName, this.options[eventName]);
+      }
+      this.on("uploadprogress", (function(_this) {
+        return function() {
+          return _this.updateTotalUploadProgress();
+        };
+      })(this));
+      this.on("removedfile", (function(_this) {
+        return function() {
+          return _this.updateTotalUploadProgress();
+        };
+      })(this));
+      this.on("canceled", (function(_this) {
+        return function(file) {
+          return _this.emit("complete", file);
+        };
+      })(this));
+      this.on("complete", (function(_this) {
+        return function(file) {
+          if (_this.getAddedFiles().length === 0 && _this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {
+            return setTimeout((function() {
+              return _this.emit("queuecomplete");
+            }), 0);
+          }
+        };
+      })(this));
+      noPropagation = function(e) {
+        e.stopPropagation();
+        if (e.preventDefault) {
+          return e.preventDefault();
+        } else {
+          return e.returnValue = false;
+        }
+      };
+      this.listeners = [
+        {
+          element: this.element,
+          events: {
+            "dragstart": (function(_this) {
+              return function(e) {
+                return _this.emit("dragstart", e);
+              };
+            })(this),
+            "dragenter": (function(_this) {
+              return function(e) {
+                noPropagation(e);
+                return _this.emit("dragenter", e);
+              };
+            })(this),
+            "dragover": (function(_this) {
+              return function(e) {
+                var efct;
+                try {
+                  efct = e.dataTransfer.effectAllowed;
+                } catch (_error) {}
+                e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
+                noPropagation(e);
+                return _this.emit("dragover", e);
+              };
+            })(this),
+            "dragleave": (function(_this) {
+              return function(e) {
+                return _this.emit("dragleave", e);
+              };
+            })(this),
+            "drop": (function(_this) {
+              return function(e) {
+                noPropagation(e);
+                return _this.drop(e);
+              };
+            })(this),
+            "dragend": (function(_this) {
+              return function(e) {
+                return _this.emit("dragend", e);
+              };
+            })(this)
+          }
+        }
+      ];
+      this.clickableElements.forEach((function(_this) {
+        return function(clickableElement) {
+          return _this.listeners.push({
+            element: clickableElement,
+            events: {
+              "click": function(evt) {
+                if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) {
+                  _this.hiddenFileInput.click();
+                }
+                return true;
+              }
+            }
+          });
+        };
+      })(this));
+      this.enable();
+      return this.options.init.call(this);
+    };
+
+    Dropzone.prototype.destroy = function() {
+      var _ref;
+      this.disable();
+      this.removeAllFiles(true);
+      if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) {
+        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
+        this.hiddenFileInput = null;
+      }
+      delete this.element.dropzone;
+      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
+    };
+
+    Dropzone.prototype.updateTotalUploadProgress = function() {
+      var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref;
+      totalBytesSent = 0;
+      totalBytes = 0;
+      activeFiles = this.getActiveFiles();
+      if (activeFiles.length) {
+        _ref = this.getActiveFiles();
+        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+          file = _ref[_i];
+          totalBytesSent += file.upload.bytesSent;
+          totalBytes += file.upload.total;
+        }
+        totalUploadProgress = 100 * totalBytesSent / totalBytes;
+      } else {
+        totalUploadProgress = 100;
+      }
+      return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
+    };
+
+    Dropzone.prototype._getParamName = function(n) {
+      if (typeof this.options.paramName === "function") {
+        return this.options.paramName(n);
+      } else {
+        return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
+      }
+    };
+
+    Dropzone.prototype._renameFilename = function(name) {
+      if (typeof this.options.renameFilename !== "function") {
+        return name;
+      }
+      return this.options.renameFilename(name);
+    };
+
+    Dropzone.prototype.getFallbackForm = function() {
+      var existingFallback, fields, fieldsString, form;
+      if (existingFallback = this.getExistingFallback()) {
+        return existingFallback;
+      }
+      fieldsString = "<div class=\"dz-fallback\">";
+      if (this.options.dictFallbackText) {
+        fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
+      }
+      fieldsString += "<input type=\"file\" name=\"" + (this._getParamName(0)) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : void 0) + " /><input type=\"submit\" value=\"Upload!\"></div>";
+      fields = Dropzone.createElement(fieldsString);
+      if (this.element.tagName !== "FORM") {
+        form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
+        form.appendChild(fields);
+      } else {
+        this.element.setAttribute("enctype", "multipart/form-data");
+        this.element.setAttribute("method", this.options.method);
+      }
+      return form != null ? form : fields;
+    };
+
+    Dropzone.prototype.getExistingFallback = function() {
+      var fallback, getFallback, tagName, _i, _len, _ref;
+      getFallback = function(elements) {
+        var el, _i, _len;
+        for (_i = 0, _len = elements.length; _i < _len; _i++) {
+          el = elements[_i];
+          if (/(^| )fallback($| )/.test(el.className)) {
+            return el;
+          }
+        }
+      };
+      _ref = ["div", "form"];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        tagName = _ref[_i];
+        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
+          return fallback;
+        }
+      }
+    };
+
+    Dropzone.prototype.setupEventListeners = function() {
+      var elementListeners, event, listener, _i, _len, _ref, _results;
+      _ref = this.listeners;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        elementListeners = _ref[_i];
+        _results.push((function() {
+          var _ref1, _results1;
+          _ref1 = elementListeners.events;
+          _results1 = [];
+          for (event in _ref1) {
+            listener = _ref1[event];
+            _results1.push(elementListeners.element.addEventListener(event, listener, false));
+          }
+          return _results1;
+        })());
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.removeEventListeners = function() {
+      var elementListeners, event, listener, _i, _len, _ref, _results;
+      _ref = this.listeners;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        elementListeners = _ref[_i];
+        _results.push((function() {
+          var _ref1, _results1;
+          _ref1 = elementListeners.events;
+          _results1 = [];
+          for (event in _ref1) {
+            listener = _ref1[event];
+            _results1.push(elementListeners.element.removeEventListener(event, listener, false));
+          }
+          return _results1;
+        })());
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.disable = function() {
+      var file, _i, _len, _ref, _results;
+      this.clickableElements.forEach(function(element) {
+        return element.classList.remove("dz-clickable");
+      });
+      this.removeEventListeners();
+      _ref = this.files;
+      _results = [];
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        _results.push(this.cancelUpload(file));
+      }
+      return _results;
+    };
+
+    Dropzone.prototype.enable = function() {
+      this.clickableElements.forEach(function(element) {
+        return element.classList.add("dz-clickable");
+      });
+      return this.setupEventListeners();
+    };
+
+    Dropzone.prototype.filesize = function(size) {
+      var cutoff, i, selectedSize, selectedUnit, unit, units, _i, _len;
+      selectedSize = 0;
+      selectedUnit = "b";
+      if (size > 0) {
+        units = ['TB', 'GB', 'MB', 'KB', 'b'];
+        for (i = _i = 0, _len = units.length; _i < _len; i = ++_i) {
+          unit = units[i];
+          cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;
+          if (size >= cutoff) {
+            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
+            selectedUnit = unit;
+            break;
+          }
+        }
+        selectedSize = Math.round(10 * selectedSize) / 10;
+      }
+      return "<strong>" + selectedSize + "</strong> " + selectedUnit;
+    };
+
+    Dropzone.prototype._updateMaxFilesReachedClass = function() {
+      if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
+        if (this.getAcceptedFiles().length === this.options.maxFiles) {
+          this.emit('maxfilesreached', this.files);
+        }
+        return this.element.classList.add("dz-max-files-reached");
+      } else {
+        return this.element.classList.remove("dz-max-files-reached");
+      }
+    };
+
+    Dropzone.prototype.drop = function(e) {
+      var files, items;
+      if (!e.dataTransfer) {
+        return;
+      }
+      this.emit("drop", e);
+      files = e.dataTransfer.files;
+      this.emit("addedfiles", files);
+      if (files.length) {
+        items = e.dataTransfer.items;
+        if (items && items.length && (items[0].webkitGetAsEntry != null)) {
+          this._addFilesFromItems(items);
+        } else {
+          this.handleFiles(files);
+        }
+      }
+    };
+
+    Dropzone.prototype.paste = function(e) {
+      var items, _ref;
+      if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {
+        return;
+      }
+      this.emit("paste", e);
+      items = e.clipboardData.items;
+      if (items.length) {
+        return this._addFilesFromItems(items);
+      }
+    };
+
+    Dropzone.prototype.handleFiles = function(files) {
+      var file, _i, _len, _results;
+      _results = [];
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        _results.push(this.addFile(file));
+      }
+      return _results;
+    };
+
+    Dropzone.prototype._addFilesFromItems = function(items) {
+      var entry, item, _i, _len, _results;
+      _results = [];
+      for (_i = 0, _len = items.length; _i < _len; _i++) {
+        item = items[_i];
+        if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {
+          if (entry.isFile) {
+            _results.push(this.addFile(item.getAsFile()));
+          } else if (entry.isDirectory) {
+            _results.push(this._addFilesFromDirectory(entry, entry.name));
+          } else {
+            _results.push(void 0);
+          }
+        } else if (item.getAsFile != null) {
+          if ((item.kind == null) || item.kind === "file") {
+            _results.push(this.addFile(item.getAsFile()));
+          } else {
+            _results.push(void 0);
+          }
+        } else {
+          _results.push(void 0);
+        }
+      }
+      return _results;
+    };
+
+    Dropzone.prototype._addFilesFromDirectory = function(directory, path) {
+      var dirReader, errorHandler, readEntries;
+      dirReader = directory.createReader();
+      errorHandler = function(error) {
+        return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0;
+      };
+      readEntries = (function(_this) {
+        return function() {
+          return dirReader.readEntries(function(entries) {
+            var entry, _i, _len;
+            if (entries.length > 0) {
+              for (_i = 0, _len = entries.length; _i < _len; _i++) {
+                entry = entries[_i];
+                if (entry.isFile) {
+                  entry.file(function(file) {
+                    if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
+                      return;
+                    }
+                    file.fullPath = "" + path + "/" + file.name;
+                    return _this.addFile(file);
+                  });
+                } else if (entry.isDirectory) {
+                  _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name);
+                }
+              }
+              readEntries();
+            }
+            return null;
+          }, errorHandler);
+        };
+      })(this);
+      return readEntries();
+    };
+
+    Dropzone.prototype.accept = function(file, done) {
+      if (file.size > this.options.maxFilesize * 1024 * 1024) {
+        return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
+      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
+        return done(this.options.dictInvalidFileType);
+      } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
+        done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
+        return this.emit("maxfilesexceeded", file);
+      } else {
+        return this.options.accept.call(this, file, done);
+      }
+    };
+
+    Dropzone.prototype.addFile = function(file) {
+      file.upload = {
+        progress: 0,
+        total: file.size,
+        bytesSent: 0
+      };
+      this.files.push(file);
+      file.status = Dropzone.ADDED;
+      this.emit("addedfile", file);
+      this._enqueueThumbnail(file);
+      return this.accept(file, (function(_this) {
+        return function(error) {
+          if (error) {
+            file.accepted = false;
+            _this._errorProcessing([file], error);
+          } else {
+            file.accepted = true;
+            if (_this.options.autoQueue) {
+              _this.enqueueFile(file);
+            }
+          }
+          return _this._updateMaxFilesReachedClass();
+        };
+      })(this));
+    };
+
+    Dropzone.prototype.enqueueFiles = function(files) {
+      var file, _i, _len;
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        this.enqueueFile(file);
+      }
+      return null;
+    };
+
+    Dropzone.prototype.enqueueFile = function(file) {
+      if (file.status === Dropzone.ADDED && file.accepted === true) {
+        file.status = Dropzone.QUEUED;
+        if (this.options.autoProcessQueue) {
+          return setTimeout(((function(_this) {
+            return function() {
+              return _this.processQueue();
+            };
+          })(this)), 0);
+        }
+      } else {
+        throw new Error("This file can't be queued because it has already been processed or was rejected.");
+      }
+    };
+
+    Dropzone.prototype._thumbnailQueue = [];
+
+    Dropzone.prototype._processingThumbnail = false;
+
+    Dropzone.prototype._enqueueThumbnail = function(file) {
+      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
+        this._thumbnailQueue.push(file);
+        return setTimeout(((function(_this) {
+          return function() {
+            return _this._processThumbnailQueue();
+          };
+        })(this)), 0);
+      }
+    };
+
+    Dropzone.prototype._processThumbnailQueue = function() {
+      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
+        return;
+      }
+      this._processingThumbnail = true;
+      return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {
+        return function() {
+          _this._processingThumbnail = false;
+          return _this._processThumbnailQueue();
+        };
+      })(this));
+    };
+
+    Dropzone.prototype.removeFile = function(file) {
+      if (file.status === Dropzone.UPLOADING) {
+        this.cancelUpload(file);
+      }
+      this.files = without(this.files, file);
+      this.emit("removedfile", file);
+      if (this.files.length === 0) {
+        return this.emit("reset");
+      }
+    };
+
+    Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {
+      var file, _i, _len, _ref;
+      if (cancelIfNecessary == null) {
+        cancelIfNecessary = false;
+      }
+      _ref = this.files.slice();
+      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+        file = _ref[_i];
+        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
+          this.removeFile(file);
+        }
+      }
+      return null;
+    };
+
+    Dropzone.prototype.createThumbnail = function(file, callback) {
+      var fileReader;
+      fileReader = new FileReader;
+      fileReader.onload = (function(_this) {
+        return function() {
+          if (file.type === "image/svg+xml") {
+            _this.emit("thumbnail", file, fileReader.result);
+            if (callback != null) {
+              callback();
+            }
+            return;
+          }
+          return _this.createThumbnailFromUrl(file, fileReader.result, callback);
+        };
+      })(this);
+      return fileReader.readAsDataURL(file);
+    };
+
+    Dropzone.prototype.createThumbnailFromUrl = function(file, imageUrl, callback, crossOrigin) {
+      var img;
+      img = document.createElement("img");
+      if (crossOrigin) {
+        img.crossOrigin = crossOrigin;
+      }
+      img.onload = (function(_this) {
+        return function() {
+          var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;
+          file.width = img.width;
+          file.height = img.height;
+          resizeInfo = _this.options.resize.call(_this, file);
+          if (resizeInfo.trgWidth == null) {
+            resizeInfo.trgWidth = resizeInfo.optWidth;
+          }
+          if (resizeInfo.trgHeight == null) {
+            resizeInfo.trgHeight = resizeInfo.optHeight;
+          }
+          canvas = document.createElement("canvas");
+          ctx = canvas.getContext("2d");
+          canvas.width = resizeInfo.trgWidth;
+          canvas.height = resizeInfo.trgHeight;
+          drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
+          thumbnail = canvas.toDataURL("image/png");
+          _this.emit("thumbnail", file, thumbnail);
+          if (callback != null) {
+            return callback();
+          }
+        };
+      })(this);
+      if (callback != null) {
+        img.onerror = callback;
+      }
+      return img.src = imageUrl;
+    };
+
+    Dropzone.prototype.processQueue = function() {
+      var i, parallelUploads, processingLength, queuedFiles;
+      parallelUploads = this.options.parallelUploads;
+      processingLength = this.getUploadingFiles().length;
+      i = processingLength;
+      if (processingLength >= parallelUploads) {
+        return;
+      }
+      queuedFiles = this.getQueuedFiles();
+      if (!(queuedFiles.length > 0)) {
+        return;
+      }
+      if (this.options.uploadMultiple) {
+        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
+      } else {
+        while (i < parallelUploads) {
+          if (!queuedFiles.length) {
+            return;
+          }
+          this.processFile(queuedFiles.shift());
+          i++;
+        }
+      }
+    };
+
+    Dropzone.prototype.processFile = function(file) {
+      return this.processFiles([file]);
+    };
+
+    Dropzone.prototype.processFiles = function(files) {
+      var file, _i, _len;
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        file.processing = true;
+        file.status = Dropzone.UPLOADING;
+        this.emit("processing", file);
+      }
+      if (this.options.uploadMultiple) {
+        this.emit("processingmultiple", files);
+      }
+      return this.uploadFiles(files);
+    };
+
+    Dropzone.prototype._getFilesWithXhr = function(xhr) {
+      var file, files;
+      return files = (function() {
+        var _i, _len, _ref, _results;
+        _ref = this.files;
+        _results = [];
+        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+          file = _ref[_i];
+          if (file.xhr === xhr) {
+            _results.push(file);
+          }
+        }
+        return _results;
+      }).call(this);
+    };
+
+    Dropzone.prototype.cancelUpload = function(file) {
+      var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref;
+      if (file.status === Dropzone.UPLOADING) {
+        groupedFiles = this._getFilesWithXhr(file.xhr);
+        for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) {
+          groupedFile = groupedFiles[_i];
+          groupedFile.status = Dropzone.CANCELED;
+        }
+        file.xhr.abort();
+        for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) {
+          groupedFile = groupedFiles[_j];
+          this.emit("canceled", groupedFile);
+        }
+        if (this.options.uploadMultiple) {
+          this.emit("canceledmultiple", groupedFiles);
+        }
+      } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) {
+        file.status = Dropzone.CANCELED;
+        this.emit("canceled", file);
+        if (this.options.uploadMultiple) {
+          this.emit("canceledmultiple", [file]);
+        }
+      }
+      if (this.options.autoProcessQueue) {
+        return this.processQueue();
+      }
+    };
+
+    resolveOption = function() {
+      var args, option;
+      option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
+      if (typeof option === 'function') {
+        return option.apply(this, args);
+      }
+      return option;
+    };
+
+    Dropzone.prototype.uploadFile = function(file) {
+      return this.uploadFiles([file]);
+    };
+
+    Dropzone.prototype.uploadFiles = function(files) {
+      var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, method, option, progressObj, response, updateProgress, url, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
+      xhr = new XMLHttpRequest();
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        file.xhr = xhr;
+      }
+      method = resolveOption(this.options.method, files);
+      url = resolveOption(this.options.url, files);
+      xhr.open(method, url, true);
+      xhr.withCredentials = !!this.options.withCredentials;
+      response = null;
+      handleError = (function(_this) {
+        return function() {
+          var _j, _len1, _results;
+          _results = [];
+          for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
+            file = files[_j];
+            _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr));
+          }
+          return _results;
+        };
+      })(this);
+      updateProgress = (function(_this) {
+        return function(e) {
+          var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results;
+          if (e != null) {
+            progress = 100 * e.loaded / e.total;
+            for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
+              file = files[_j];
+              file.upload = {
+                progress: progress,
+                total: e.total,
+                bytesSent: e.loaded
+              };
+            }
+          } else {
+            allFilesFinished = true;
+            progress = 100;
+            for (_k = 0, _len2 = files.length; _k < _len2; _k++) {
+              file = files[_k];
+              if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) {
+                allFilesFinished = false;
+              }
+              file.upload.progress = progress;
+              file.upload.bytesSent = file.upload.total;
+            }
+            if (allFilesFinished) {
+              return;
+            }
+          }
+          _results = [];
+          for (_l = 0, _len3 = files.length; _l < _len3; _l++) {
+            file = files[_l];
+            _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent));
+          }
+          return _results;
+        };
+      })(this);
+      xhr.onload = (function(_this) {
+        return function(e) {
+          var _ref;
+          if (files[0].status === Dropzone.CANCELED) {
+            return;
+          }
+          if (xhr.readyState !== 4) {
+            return;
+          }
+          response = xhr.responseText;
+          if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
+            try {
+              response = JSON.parse(response);
+            } catch (_error) {
+              e = _error;
+              response = "Invalid JSON response from server.";
+            }
+          }
+          updateProgress();
+          if (!((200 <= (_ref = xhr.status) && _ref < 300))) {
+            return handleError();
+          } else {
+            return _this._finished(files, response, e);
+          }
+        };
+      })(this);
+      xhr.onerror = (function(_this) {
+        return function() {
+          if (files[0].status === Dropzone.CANCELED) {
+            return;
+          }
+          return handleError();
+        };
+      })(this);
+      progressObj = (_ref = xhr.upload) != null ? _ref : xhr;
+      progressObj.onprogress = updateProgress;
+      headers = {
+        "Accept": "application/json",
+        "Cache-Control": "no-cache",
+        "X-Requested-With": "XMLHttpRequest"
+      };
+      if (this.options.headers) {
+        extend(headers, this.options.headers);
+      }
+      for (headerName in headers) {
+        headerValue = headers[headerName];
+        if (headerValue) {
+          xhr.setRequestHeader(headerName, headerValue);
+        }
+      }
+      formData = new FormData();
+      if (this.options.params) {
+        _ref1 = this.options.params;
+        for (key in _ref1) {
+          value = _ref1[key];
+          formData.append(key, value);
+        }
+      }
+      for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
+        file = files[_j];
+        this.emit("sending", file, xhr, formData);
+      }
+      if (this.options.uploadMultiple) {
+        this.emit("sendingmultiple", files, xhr, formData);
+      }
+      if (this.element.tagName === "FORM") {
+        _ref2 = this.element.querySelectorAll("input, textarea, select, button");
+        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
+          input = _ref2[_k];
+          inputName = input.getAttribute("name");
+          inputType = input.getAttribute("type");
+          if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
+            _ref3 = input.options;
+            for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
+              option = _ref3[_l];
+              if (option.selected) {
+                formData.append(inputName, option.value);
+              }
+            }
+          } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) {
+            formData.append(inputName, input.value);
+          }
+        }
+      }
+      for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {
+        formData.append(this._getParamName(i), files[i], this._renameFilename(files[i].name));
+      }
+      return this.submitRequest(xhr, formData, files);
+    };
+
+    Dropzone.prototype.submitRequest = function(xhr, formData, files) {
+      return xhr.send(formData);
+    };
+
+    Dropzone.prototype._finished = function(files, responseText, e) {
+      var file, _i, _len;
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        file.status = Dropzone.SUCCESS;
+        this.emit("success", file, responseText, e);
+        this.emit("complete", file);
+      }
+      if (this.options.uploadMultiple) {
+        this.emit("successmultiple", files, responseText, e);
+        this.emit("completemultiple", files);
+      }
+      if (this.options.autoProcessQueue) {
+        return this.processQueue();
+      }
+    };
+
+    Dropzone.prototype._errorProcessing = function(files, message, xhr) {
+      var file, _i, _len;
+      for (_i = 0, _len = files.length; _i < _len; _i++) {
+        file = files[_i];
+        file.status = Dropzone.ERROR;
+        this.emit("error", file, message, xhr);
+        this.emit("complete", file);
+      }
+      if (this.options.uploadMultiple) {
+        this.emit("errormultiple", files, message, xhr);
+        this.emit("completemultiple", files);
+      }
+      if (this.options.autoProcessQueue) {
+        return this.processQueue();
+      }
+    };
+
+    return Dropzone;
+
+  })(Emitter);
+
+  Dropzone.version = "4.3.0";
+
+  Dropzone.options = {};
+
+  Dropzone.optionsForElement = function(element) {
+    if (element.getAttribute("id")) {
+      return Dropzone.options[camelize(element.getAttribute("id"))];
+    } else {
+      return void 0;
+    }
+  };
+
+  Dropzone.instances = [];
+
+  Dropzone.forElement = function(element) {
+    if (typeof element === "string") {
+      element = document.querySelector(element);
+    }
+    if ((element != null ? element.dropzone : void 0) == null) {
+      throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
+    }
+    return element.dropzone;
+  };
+
+  Dropzone.autoDiscover = true;
+
+  Dropzone.discover = function() {
+    var checkElements, dropzone, dropzones, _i, _len, _results;
+    if (document.querySelectorAll) {
+      dropzones = document.querySelectorAll(".dropzone");
+    } else {
+      dropzones = [];
+      checkElements = function(elements) {
+        var el, _i, _len, _results;
+        _results = [];
+        for (_i = 0, _len = elements.length; _i < _len; _i++) {
+          el = elements[_i];
+          if (/(^| )dropzone($| )/.test(el.className)) {
+            _results.push(dropzones.push(el));
+          } else {
+            _results.push(void 0);
+          }
+        }
+        return _results;
+      };
+      checkElements(document.getElementsByTagName("div"));
+      checkElements(document.getElementsByTagName("form"));
+    }
+    _results = [];
+    for (_i = 0, _len = dropzones.length; _i < _len; _i++) {
+      dropzone = dropzones[_i];
+      if (Dropzone.optionsForElement(dropzone) !== false) {
+        _results.push(new Dropzone(dropzone));
+      } else {
+        _results.push(void 0);
+      }
+    }
+    return _results;
+  };
+
+  Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i];
+
+  Dropzone.isBrowserSupported = function() {
+    var capableBrowser, regex, _i, _len, _ref;
+    capableBrowser = true;
+    if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
+      if (!("classList" in document.createElement("a"))) {
+        capableBrowser = false;
+      } else {
+        _ref = Dropzone.blacklistedBrowsers;
+        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+          regex = _ref[_i];
+          if (regex.test(navigator.userAgent)) {
+            capableBrowser = false;
+            continue;
+          }
+        }
+      }
+    } else {
+      capableBrowser = false;
+    }
+    return capableBrowser;
+  };
+
+  without = function(list, rejectedItem) {
+    var item, _i, _len, _results;
+    _results = [];
+    for (_i = 0, _len = list.length; _i < _len; _i++) {
+      item = list[_i];
+      if (item !== rejectedItem) {
+        _results.push(item);
+      }
+    }
+    return _results;
+  };
+
+  camelize = function(str) {
+    return str.replace(/[\-_](\w)/g, function(match) {
+      return match.charAt(1).toUpperCase();
+    });
+  };
+
+  Dropzone.createElement = function(string) {
+    var div;
+    div = document.createElement("div");
+    div.innerHTML = string;
+    return div.childNodes[0];
+  };
+
+  Dropzone.elementInside = function(element, container) {
+    if (element === container) {
+      return true;
+    }
+    while (element = element.parentNode) {
+      if (element === container) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  Dropzone.getElement = function(el, name) {
+    var element;
+    if (typeof el === "string") {
+      element = document.querySelector(el);
+    } else if (el.nodeType != null) {
+      element = el;
+    }
+    if (element == null) {
+      throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
+    }
+    return element;
+  };
+
+  Dropzone.getElements = function(els, name) {
+    var e, el, elements, _i, _j, _len, _len1, _ref;
+    if (els instanceof Array) {
+      elements = [];
+      try {
+        for (_i = 0, _len = els.length; _i < _len; _i++) {
+          el = els[_i];
+          elements.push(this.getElement(el, name));
+        }
+      } catch (_error) {
+        e = _error;
+        elements = null;
+      }
+    } else if (typeof els === "string") {
+      elements = [];
+      _ref = document.querySelectorAll(els);
+      for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
+        el = _ref[_j];
+        elements.push(el);
+      }
+    } else if (els.nodeType != null) {
+      elements = [els];
+    }
+    if (!((elements != null) && elements.length)) {
+      throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
+    }
+    return elements;
+  };
+
+  Dropzone.confirm = function(question, accepted, rejected) {
+    if (window.confirm(question)) {
+      return accepted();
+    } else if (rejected != null) {
+      return rejected();
+    }
+  };
+
+  Dropzone.isValidFile = function(file, acceptedFiles) {
+    var baseMimeType, mimeType, validType, _i, _len;
+    if (!acceptedFiles) {
+      return true;
+    }
+    acceptedFiles = acceptedFiles.split(",");
+    mimeType = file.type;
+    baseMimeType = mimeType.replace(/\/.*$/, "");
+    for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) {
+      validType = acceptedFiles[_i];
+      validType = validType.trim();
+      if (validType.charAt(0) === ".") {
+        if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
+          return true;
+        }
+      } else if (/\/\*$/.test(validType)) {
+        if (baseMimeType === validType.replace(/\/.*$/, "")) {
+          return true;
+        }
+      } else {
+        if (mimeType === validType) {
+          return true;
+        }
+      }
+    }
+    return false;
+  };
+
+  if (typeof jQuery !== "undefined" && jQuery !== null) {
+    jQuery.fn.dropzone = function(options) {
+      return this.each(function() {
+        return new Dropzone(this, options);
+      });
+    };
+  }
+
+  if (typeof module !== "undefined" && module !== null) {
+    module.exports = Dropzone;
+  } else {
+    window.Dropzone = Dropzone;
+  }
+
+  Dropzone.ADDED = "added";
+
+  Dropzone.QUEUED = "queued";
+
+  Dropzone.ACCEPTED = Dropzone.QUEUED;
+
+  Dropzone.UPLOADING = "uploading";
+
+  Dropzone.PROCESSING = Dropzone.UPLOADING;
+
+  Dropzone.CANCELED = "canceled";
+
+  Dropzone.ERROR = "error";
+
+  Dropzone.SUCCESS = "success";
+
+
+  /*
+
+  Bugfix for iOS 6 and 7
+  Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
+  based on the work of https://github.com/stomita/ios-imagefile-megapixel
+   */
+
+  detectVerticalSquash = function(img) {
+    var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;
+    iw = img.naturalWidth;
+    ih = img.naturalHeight;
+    canvas = document.createElement("canvas");
+    canvas.width = 1;
+    canvas.height = ih;
+    ctx = canvas.getContext("2d");
+    ctx.drawImage(img, 0, 0);
+    data = ctx.getImageData(0, 0, 1, ih).data;
+    sy = 0;
+    ey = ih;
+    py = ih;
+    while (py > sy) {
+      alpha = data[(py - 1) * 4 + 3];
+      if (alpha === 0) {
+        ey = py;
+      } else {
+        sy = py;
+      }
+      py = (ey + sy) >> 1;
+    }
+    ratio = py / ih;
+    if (ratio === 0) {
+      return 1;
+    } else {
+      return ratio;
+    }
+  };
+
+  drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
+    var vertSquashRatio;
+    vertSquashRatio = detectVerticalSquash(img);
+    return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
+  };
+
+
+  /*
+   * contentloaded.js
+   *
+   * Author: Diego Perini (diego.perini at gmail.com)
+   * Summary: cross-browser wrapper for DOMContentLoaded
+   * Updated: 20101020
+   * License: MIT
+   * Version: 1.2
+   *
+   * URL:
+   * http://javascript.nwbox.com/ContentLoaded/
+   * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
+   */
+
+  contentLoaded = function(win, fn) {
+    var add, doc, done, init, poll, pre, rem, root, top;
+    done = false;
+    top = true;
+    doc = win.document;
+    root = doc.documentElement;
+    add = (doc.addEventListener ? "addEventListener" : "attachEvent");
+    rem = (doc.addEventListener ? "removeEventListener" : "detachEvent");
+    pre = (doc.addEventListener ? "" : "on");
+    init = function(e) {
+      if (e.type === "readystatechange" && doc.readyState !== "complete") {
+        return;
+      }
+      (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
+      if (!done && (done = true)) {
+        return fn.call(win, e.type || e);
+      }
+    };
+    poll = function() {
+      var e;
+      try {
+        root.doScroll("left");
+      } catch (_error) {
+        e = _error;
+        setTimeout(poll, 50);
+        return;
+      }
+      return init("poll");
+    };
+    if (doc.readyState !== "complete") {
+      if (doc.createEventObject && root.doScroll) {
+        try {
+          top = !win.frameElement;
+        } catch (_error) {}
+        if (top) {
+          poll();
+        }
+      }
+      doc[add](pre + "DOMContentLoaded", init, false);
+      doc[add](pre + "readystatechange", init, false);
+      return win[add](pre + "load", init, false);
+    }
+  };
+
+  Dropzone._autoDiscoverFunction = function() {
+    if (Dropzone.autoDiscover) {
+      return Dropzone.discover();
+    }
+  };
+
+  contentLoaded(window, Dropzone._autoDiscoverFunction);
+
+}).call(this);


view thread (11+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected]
  Subject: Re: [pgAdmin4][Patch]: File Manager & Backform FileControl
  In-Reply-To: <CAM5-9D9jr0E9bsE-_exx-XGrmRq9LZSeA+emm8Sbc-jJR_Ny3Q@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox