Initial cut at saving/retrieving the main browser layout.

Still needs some work to:

- Minimise AJAX calls by writing multiple settings at once.
- Move the settings storage/retrieval JS code into a global file
- Avoid using synchronous AJAX calls in the main thread
This commit is contained in:
Dave Page 2015-02-11 10:00:57 +00:00
parent 506dd6437f
commit e995104000
8 changed files with 165 additions and 115 deletions

View File

@ -2,12 +2,12 @@
<div id="container" class="browser-pane-container"> <div id="container" class="browser-pane-container">
<div id="browser" class="pane ui-layout-west browser-browser-pane"> <div class="pane ui-layout-west browser-browser-pane">
<p>Browser Pane</p> <p>Browser Pane</p>
</div> </div>
<div class="pane ui-layout-center browser-inner-pane" id="inner"> <div class="pane ui-layout-center browser-inner-pane" id="outer-center">
<div class="pane ui-layout-center browser-center-pane"> <div class="pane ui-layout-center browser-center-pane" id="inner-center">
<ul class="nav nav-tabs browser-tab-bar" role="tablist"> <ul class="nav nav-tabs browser-tab-bar" role="tablist">
<li role="presentation" class="active"><a href="#dashboard" aria-controls="home" role="tab" data-toggle="tab">Dashboard</a></li> <li role="presentation" class="active"><a href="#dashboard" aria-controls="home" role="tab" data-toggle="tab">Dashboard</a></li>
<li role="presentation"><a href="#properties" aria-controls="profile" role="tab" data-toggle="tab">Properties</a></li> <li role="presentation"><a href="#properties" aria-controls="profile" role="tab" data-toggle="tab">Properties</a></li>
@ -31,38 +31,82 @@
</div> </div>
<script> <script>
// create page layout
$('#container').layout({
center: {
maskContents: true function storeLayout(pane, $pane, paneState, paneOptions) {
}, state = layout.readState();
west: { $.post("{{ url_for('settings.store') }}", { setting: "Browser/SQL-Pane/Size", value: state.center.children.layout1.south.size });
size: 250, $.post("{{ url_for('settings.store') }}", { setting: "Browser/SQL-Pane/Hidden", value: state.center.children.layout1.south.initHidden });
spacing_closed: 22, $.post("{{ url_for('settings.store') }}", { setting: "Browser/SQL-Pane/Closed", value: state.center.children.layout1.south.initClosed });
togglerLength_closed: 140, $.post("{{ url_for('settings.store') }}", { setting: "Browser/Browser-Pane/Size", value: state.west.size });
togglerAlign_closed: "top", $.post("{{ url_for('settings.store') }}", { setting: "Browser/Browser-Pane/Hidden", value: state.west.initHidden });
togglerContent_closed: 'B<br />r<br />o<br />w<br />s<br />e<br />r', $.post("{{ url_for('settings.store') }}", { setting: "Browser/Browser-Pane/Closed", value: state.west.initClosed });
togglerTip_closed: "Open & Pin Browser", return true
sliderTip: "Slide Open Browser", }
slideTrigger_open: "mouseover",
} function getSetting(setting, defval) {
}); var value
$('#inner').layout({ $.ajaxSetup({
south: { async: false
size: 250, });
spacing_closed: 22,
togglerLength_closed: 140,
togglerAlign_closed: "right",
togglerContent_closed: 'SQL Pane',
togglerTip_closed: "Open & Pin SQL Pane",
sliderTip: "Slide Open SQL Pane",
slideTrigger_open: "mouseover",
} $.post("{{ url_for('settings.get') }}", { setting: setting, default: defval })
}); .done(function(data) {
value = data
});
$.ajaxSetup({
async: true
});
return value
}
// Get the previous settings
var sqlPaneSize = getSetting("Browser/SQL-Pane/Size", "250")
var sqlPaneHidden = (getSetting("Browser/SQL-Pane/Hidden", "false") == "true" ? true : false)
var sqlPaneClosed = (getSetting("Browser/SQL-Pane/Closed", "false") == "true" ? true : false)
var browserPaneSize = getSetting("Browser/Browser-Pane/Size", "250")
var browserPaneHidden = (getSetting("Browser/Browser-Pane/Hidden", "false") == "true" ? true : false)
var browserPaneClosed = (getSetting("Browser/Browser-Pane/Closed", "false") == "true" ? true : false)
var layout
var layoutDefault = {
center__maskContents: true,
center__paneSelector: "#outer-center",
center__maskContents: true,
center__children: [{
center__paneSelector: "#inner-center",
center__maskContents: true,
center__onresize: "storeLayout",
south__maskContents: true,
south__size: sqlPaneSize,
south__initHidden: sqlPaneHidden,
south__initClosed: sqlPaneClosed,
south__spacing_closed: 22,
south__togglerLength_closed: 140,
south__togglerAlign_closed: "right",
south__togglerContent_closed: 'SQL Pane',
south__togglerTip_closed: "Open & Pin SQL Pane",
south__sliderTip: "Slide Open SQL Pane",
south__slideTrigger_open: "mouseover",
}],
west__maskContents: true,
west__size: browserPaneSize,
west__initHidden: browserPaneHidden,
west__initClosed: browserPaneClosed,
west__spacing_closed: 22,
west__togglerLength_closed: 140,
west__togglerAlign_closed: "top",
west__togglerContent_closed: 'B<br />r<br />o<br />w<br />s<br />e<br />r',
west__togglerTip_closed: "Open & Pin Browser",
west__sliderTip: "Slide Open Browser",
west__slideTrigger_open: "mouseover",
};
layout = $('#container').layout(layoutDefault);
// Make the tabs, umm, tabable
$('#dashboard a').click(function (e) { $('#dashboard a').click(function (e) {
e.preventDefault() e.preventDefault()
$(this).tab('show') $(this).tab('show')

View File

@ -0,0 +1,37 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Utility functions for storing and retrieving user configuration settings."""
from flask import current_app
from flask.ext.login import current_user
from flask.ext.sqlalchemy import SQLAlchemy
from settings_model import db, Setting
def store_setting(setting, value):
"""Set a configuration setting for the current user."""
db.init_app(current_app)
data = Setting(user_id=current_user.id, setting=setting, value=value)
db.session.merge(data)
db.session.commit()
def get_setting(setting, default=None):
"""Retrieve a configuration setting for the current user, or return the
default value specified by the caller."""
db.init_app(current_app)
data = Setting.query.filter_by(user_id=current_user.id, setting=setting).first()
if not data or data.value is None:
return default
else:
return data.value

View File

@ -43,7 +43,5 @@ class Setting(db.Model):
__tablename__ = 'setting' __tablename__ = 'setting'
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
setting = db.Column(db.String(255), primary_key=True) setting = db.Column(db.String(255), primary_key=True)
boolean_value = db.Column(db.Boolean()) value = db.Column(db.String(1024))
integer_value = db.Column(db.Integer())
string_value = db.Column(db.String(1024))

View File

@ -0,0 +1,50 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2015, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Views for setting and storing configuration options."""
MODULE_NAME = 'settings'
import config
from flask import Blueprint, abort, request
from flask.ext.security import login_required
from . import get_setting, store_setting
# Initialise the module
blueprint = Blueprint(MODULE_NAME, __name__, url_prefix='/' + MODULE_NAME)
@blueprint.route("/store", methods=['POST'])
@blueprint.route("/store/<setting>/<value>", methods=['GET'])
@login_required
def store(setting=None, value=None):
"""Store a configuration setting."""
if request.method == 'POST':
setting = request.form['setting']
value = request.form['value']
store_setting(setting, value)
return ''
@blueprint.route("/get", methods=['POST'])
@blueprint.route("/get/<setting>", methods=['GET'])
@blueprint.route("/get/<setting>/<default>", methods=['GET'])
@login_required
def get(setting=None, default=None):
"""Get a configuration setting."""
if request.method == 'POST':
setting = request.form['setting']
default = request.form['default']
try:
value = get_setting(setting, default)
except:
return ''
return value

View File

@ -41,6 +41,7 @@
<script src="{{ url_for('static', filename='js/vendor/alertifyjs/alertify.min.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/alertifyjs/alertify.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/jquery-ui/jquery-ui.min.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/jquery-ui/jquery-ui.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/jquery-layout/jquery.layout.min.js') }}"></script> <script src="{{ url_for('static', filename='js/vendor/jquery-layout/jquery.layout.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/jquery-layout/plugins/jquery.layout.state.js') }}"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script> <script src="{{ url_for('static', filename='js/main.js') }}"></script>
<script> <script>

View File

@ -13,7 +13,6 @@ MODULE_NAME = 'utils'
import config import config
from flask import Blueprint, render_template from flask import Blueprint, render_template
from flask.ext.security import login_required from flask.ext.security import login_required
from time import time, ctime
# Initialise the module # Initialise the module
blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', template_folder='templates', url_prefix='/' + MODULE_NAME) blueprint = Blueprint(MODULE_NAME, __name__, static_folder='static', template_folder='templates', url_prefix='/' + MODULE_NAME)

View File

@ -1,79 +0,0 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2014, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""Utility functions for storing and retrieving user configuration settings."""
from flask import current_app
from flask.ext.login import current_user
from flask.ext.sqlalchemy import SQLAlchemy
from settings_model import db, Setting
def set_boolean(setting, value):
"""Set a boolean configuration setting for the current user."""
db.init_app(current_app)
data = Setting(user_id=current_user.id, setting=setting, boolean_value=value)
db.session.merge(data)
db.session.commit()
def set_integer(setting, value):
"""Set a string configuration setting for the current user."""
db.init_app(current_app)
data = Setting(user_id=current_user.id, setting=setting, integer_value=value)
db.session.merge(data)
db.session.commit()
def set_string(setting, value):
"""Set a string configuration setting for the current user."""
db.init_app(current_app)
data = Setting(user_id=current_user.id, setting=setting, string_value=value)
db.session.merge(data)
db.session.commit()
def get_boolean(setting, default=None):
"""Retrieve a boolean configuration setting for the current user, or return
the default value specified by the caller."""
db.init_app(current_app)
data = Setting.query.filter_by(user_id=current_user.id, setting=setting).first()
if not data or data.boolean_value is None:
return default
else:
return data.boolean_value
def get_integer(setting, default=None):
"""Retrieve an integer configuration setting for the current user, or return
the default value specified by the caller."""
db.init_app(current_app)
data = Setting.query.filter_by(user_id=current_user.id, setting=setting).first()
if not data or data.integer_value is None:
return default
else:
return data.integer_value
def get_string(setting, default=None):
"""Retrieve a string configuration setting for the current user, or return
the default value specified by the caller."""
db.init_app(current_app)
data = Setting.query.filter_by(user_id=current_user.id, setting=setting).first()
if not data or data.string_value is None:
return default
else:
return data.string_value

View File

@ -14,7 +14,7 @@ from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore from flask.ext.security import Security, SQLAlchemyUserDatastore
from flask.ext.security.utils import encrypt_password from flask.ext.security.utils import encrypt_password
from settings.settings_model import db, Role, User from pgadmin.settings.settings_model import db, Role, User
import getpass, os, random, sys, string import getpass, os, random, sys, string