Hello, I understand that, but what do we win by using it? As you have noticed by now I am not very fond of using templates for everything, and I believe this is one of the things that we can skip templates. We might even shift this to a frontend concern and if we want there are node libraries to get gravatars.
I was able to create a PoC as a sample of what I was talking about: - Add gravatar library to package.json - Created a Preferences cache. (js/preferences.js) - So this was the concept I was talking about in a previous email we talked about caching. the getConfiguration and the getAllConfiguration are not great names, but they return a Promise that is consumed in the load_gravatar. The idea here is that we are caching the pgAdmin settings and when need need to consume them, we wait for it to be available. - load_gravatar is using the pattern to retrieve the configuration from a possible cache and then apply the gravatar Things that need to be revisited in the PoC: - No tests, just some spiked code - Did not retrieve the username from the backend, we need to create an endpoint that give us this - The url is hardcoded to get the configuration - Maybe the Preferences is not the correct place to get server_mode configuration not sure, what do you think? Thanks Joao On Mon, Mar 5, 2018 at 11:21 AM Murtuza Zabuawala < murtuza.zabuaw...@enterprisedb.com> wrote: > Hi Joao, > > We are using Flask-Gravatar <https://pythonhosted.org/Flask-Gravatar/> > module for this and it is designed to work with template only. > > -- > Regards, > Murtuza Zabuawala > EnterpriseDB: http://www.enterprisedb.com > The Enterprise PostgreSQL Company > > > On Mon, Mar 5, 2018 at 8:57 PM, Joao De Almeida Pereira < > jdealmeidapere...@pivotal.io> wrote: > >> Hi Murtuza, >> >> Why are we doing this using templates? Can this be done with a request to >> the backend to get the image and then retrieve the Gravatar if it is >> defined or return a static image if not? >> >> + >> +{% if config.SERVER_MODE %} >> window.onload = function(e){ >> setTimeout(function() { >> - var gravatarImg = '<img src="{{ username | gravatar }}" width="18" >> height="18" alt="Gravatar image for {{ username }}"> {{ username }} <span >> class="caret"></span>'; >> + var gravatarImg = {{ IMG.PREPARE_HTML()|safe }} >> //$('#navbar-menu .navbar-right > li > a').html(gravatarImg); >> var navbarRight = >> document.getElementById("navbar-menu").getElementsByClassName("navbar-right")[0]; >> if (navbarRight) { >> >> what if we have >> >> var gravatarImg = '<img src="/user/{{username}}/gravatar" width="18" >> height="18" alt="Gravatar image for {{ username }}"> {{ username }} <span >> class="caret"></span>'; >> >> And then the endpoint >> /user/{{username}}/gravatar >> would be responsible for returning a Gravatar or not depending on the >> configuration? >> >> >> Thanks >> Joao >> >> On Mon, Mar 5, 2018 at 3:13 AM Murtuza Zabuawala < >> murtuza.zabuaw...@enterprisedb.com> wrote: >> >>> Hi, >>> >>> PFA patch to disable Gravatar image in Server mode. >>> >>> Requirments & Issues: >>> - For security reasons. >>> - For systems which do not have internet access. >>> - Hangs pgAdmin4 while loading the page if connection has no internet >>> access (as described in the ticket) >>> >>> -- >>> Regards, >>> Murtuza Zabuawala >>> EnterpriseDB: http://www.enterprisedb.com >>> The Enterprise PostgreSQL Company >>> >>> >
diff --git a/web/package.json b/web/package.json index 2707b334..8d62e7b5 100644 --- a/web/package.json +++ b/web/package.json @@ -66,6 +66,7 @@ "exports-loader": "~0.6.4", "flotr2": "^0.1.0", "font-awesome": "^4.7.0", + "gravatar": "^1.6.0", "hard-source-webpack-plugin": "^0.4.9", "immutability-helper": "^2.2.0", "imports-loader": "^0.7.1", diff --git a/web/pgadmin/browser/templates/browser/index.html b/web/pgadmin/browser/templates/browser/index.html index 58ff43f8..0901f44a 100644 --- a/web/pgadmin/browser/templates/browser/index.html +++ b/web/pgadmin/browser/templates/browser/index.html @@ -5,6 +5,7 @@ try { require( ['sources/generated/app.bundle'], function() { + pgAdmin.applyAvatar(pgAdmin); }, function() { /* TODO:: Show proper error dialog */ @@ -66,17 +67,6 @@ require.onResourceLoad = function (context, map, depMaps) { }, 400) } }; -window.onload = function(e){ - setTimeout(function() { - var gravatarImg = '<img src="{{ username | gravatar }}" width="18" height="18" alt="Gravatar image for {{ username }}"> {{ username }} <span class="caret"></span>'; - //$('#navbar-menu .navbar-right > li > a').html(gravatarImg); - var navbarRight = document.getElementById("navbar-menu").getElementsByClassName("navbar-right")[0]; - if (navbarRight) { - var list = navbarRight.getElementsByTagName("LI")[0]; - list.getElementsByTagName("a")[0].innerHTML = gravatarImg; - } - }, 1000); -}; {% endblock %} {% block body %} diff --git a/web/pgadmin/preferences/__init__.py b/web/pgadmin/preferences/__init__.py index f1f571cd..e75aa4cb 100644 --- a/web/pgadmin/preferences/__init__.py +++ b/web/pgadmin/preferences/__init__.py @@ -21,6 +21,7 @@ from pgadmin.utils.ajax import success_return, \ make_response as ajax_response, internal_server_error from pgadmin.utils.menu import MenuItem from pgadmin.utils.preferences import Preferences +import config MODULE_NAME = 'preferences' @@ -163,6 +164,10 @@ def preferences_s(): p['module'] = m['name'] res.append(p) + res.append({'name': 'pgadmin', 'configuration': [ + {'server_mode': config.SERVER_MODE} + ] + }) return ajax_response( response=res, status=200 diff --git a/web/pgadmin/static/bundle/app.js b/web/pgadmin/static/bundle/app.js index a2b86f87..ec78c89b 100644 --- a/web/pgadmin/static/bundle/app.js +++ b/web/pgadmin/static/bundle/app.js @@ -1,6 +1,6 @@ define('app', [ - 'babel-polyfill', 'sources/pgadmin', 'bundled_browser', 'pgadmin.datagrid', -], function(babelPolyFill, pgAdmin) { + 'babel-polyfill', 'sources/pgadmin', 'sources/preferences', 'sources/load_gravatar', 'bundled_browser', 'pgadmin.datagrid', +], function(babelPolyFill, pgAdmin, preferences, gravatar) { var initializeModules = function(Object) { for (var key in Object) { var module = Object[key]; @@ -20,4 +20,7 @@ define('app', [ // create menus after all modules are initialized. pgAdmin.Browser.create_menus(); + + pgAdmin.Settings = new preferences.Preferences(); + pgAdmin.applyAvatar = gravatar.applyAvatar; }); diff --git a/web/pgadmin/static/js/load_gravatar.js b/web/pgadmin/static/js/load_gravatar.js new file mode 100644 index 00000000..1372b9b6 --- /dev/null +++ b/web/pgadmin/static/js/load_gravatar.js @@ -0,0 +1,19 @@ +import gravatar from 'gravatar'; + +export function applyAvatar(pgAdmin) { + pgAdmin.Settings.getConfiguration('server_mode') + .then(function(server_mode) { + const username = 'pivo...@pivotal.io'; + if (server_mode) { + const gravatarImg = '<img src="' + gravatar.url(username) + '" width="18"' + + ' height="18" alt="Gravatar image for ' + username + '"> ' + username + ' <span' + + ' class="caret">' + username + '</span>'; + + const navbarRight = document.getElementById('navbar-menu').getElementsByClassName('navbar-right')[0]; + if (navbarRight) { + const list = navbarRight.getElementsByTagName('LI')[0]; + list.getElementsByTagName('a')[0].innerHTML = gravatarImg; + } + } + }); +} diff --git a/web/pgadmin/static/js/pgadmin.js b/web/pgadmin/static/js/pgadmin.js index f0f93d9a..648157fe 100644 --- a/web/pgadmin/static/js/pgadmin.js +++ b/web/pgadmin/static/js/pgadmin.js @@ -101,5 +101,7 @@ define([], function() { return 0; }; + + return pgAdmin; }); diff --git a/web/pgadmin/static/js/preferences.js b/web/pgadmin/static/js/preferences.js new file mode 100644 index 00000000..c46098bf --- /dev/null +++ b/web/pgadmin/static/js/preferences.js @@ -0,0 +1,33 @@ +import axios from 'axios'; +import _ from 'underscore'; + +export class Preferences { + constructor() { + this.config = {}; + } + + getAllConfiguration() { + let self = this; + return axios.get('http://localhost:5050/preferences/get_all') + .then((response) => { + const node = _.findWhere(response.data, {'name': 'pgadmin'}); + self.config = Object.assign({}, node['configuration'][0]); + }); + } + + + getConfiguration(key) { + let self = this; + if (self.config[key] === undefined) { + return this.getAllConfiguration() + .then(() => { + return self.config[key]; + }); + } + + + return new Promise((resolve) => { + resolve(self.config[key]); + }); + } +} diff --git a/web/yarn.lock b/web/yarn.lock index 666a20e6..3c874496 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1185,6 +1185,10 @@ bluebird@^3.0.0, bluebird@^3.0.5, bluebird@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" +blueimp-md5@^2.3.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.10.0.tgz#02f0843921f90dca14f5b8920a38593201d6964d" + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -2456,6 +2460,10 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +email-validator@^1.0.7: + version "1.1.1" + resolved "https://registry.yarnpkg.com/email-validator/-/email-validator-1.1.1.tgz#b07f3be7bac1dc099bc43e75f6ae399f552d5a80" + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -3410,6 +3418,15 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +gravatar@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.6.0.tgz#8bdc9b786ca725a8e7076416d1731f8d3331c976" + dependencies: + blueimp-md5 "^2.3.0" + email-validator "^1.0.7" + querystring "0.2.0" + yargs "^6.0.0" + gulp-decompress@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gulp-decompress/-/gulp-decompress-1.2.0.tgz#8eeb65a5e015f8ed8532cafe28454960626f0dc7" @@ -7768,6 +7785,12 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + dependencies: + camelcase "^3.0.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -7780,6 +7803,24 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" +yargs@^6.0.0: + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + yargs@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"