Skip to content

Commit 89eab84

Browse files
author
Olufemi Adeyemi
committed
dcache-view (user-profile): make gravatar optional
Motivation: If a user account have an email associated with it, a request is sent to check if the email is registered with the Gravatar, and if it is, the image from gravatar is used by dcache-view as the user profile. Since this is the current default behaviour of dcache-view, some sites are not happy with this and the preferred behaviour will to make gravatar optional for users. Modification: 1. properly remove all node inside the user profile section. 2. add a checkbox in the login form. This enable users to choose whether to use a gravatar or not. By default, the checkbox is unchecked. This means that users will have to specfically check the checkbox to indicate that dcache-view can make a request to the Gravatar 3. adjust the user-image element 4. update user-profile and user-profile-dropdown element to use the adjusted user-image element. 5. add a section in the user-profile for user to see and sel- ect the preferred user profile image. There are only two options (identicon and gravatar) available at this time. Result: User can now opt-in or out of gravatar. Target: master Request: 1.5 Request: 1.4 Require-notes: no Require-book: no Acked-by: Tigran Mkrtchyan Fixes: #135 Reviewed at https://rb.dcache.org/r/11450/
1 parent d3a65db commit 89eab84

6 files changed

Lines changed: 255 additions & 61 deletions

File tree

src/elements/dv-elements/user-authentication/forms/login-form.html

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@
7070
font-size: 0.71em;
7171
}
7272
}
73+
.checkbox-container {
74+
display: flex;
75+
align-items: center;
76+
}
77+
.flex {
78+
flex: 1 1 auto;
79+
}
80+
.info-class {
81+
display:inline-block;
82+
padding-left: 5px;
83+
}
84+
.info-icon {
85+
width:15px;
86+
height:15px;
87+
fill: #f2f4f4
88+
}
7389
</style>
7490
<div id="container">
7591
<iron-a11y-keys keys="enter" on-keys-pressed="_login"></iron-a11y-keys>
@@ -88,8 +104,17 @@
88104
name="password" id="password"
89105
value="{{password::input}}" placeholder="password" type="password">
90106
</paper-input-container>
91-
<div>
107+
<div class="checkbox-container">
92108
<paper-checkbox checked="{{assertionStatus}}">Assert all roles</paper-checkbox>
109+
<span class="flex"></span>
110+
<paper-checkbox checked="{{useGravatar}}">Use Gravatar </paper-checkbox>
111+
<div class="info-class">
112+
<iron-icon icon="info" class="info-icon"></iron-icon>
113+
<paper-tooltip>
114+
A Gravatar is a Globally Recognized Avatar (See https://en.gravatar.com/).
115+
If this option is checked, a request will be sent to Gravatar.
116+
</paper-tooltip>
117+
</div>
93118
</div>
94119
<div class$="[[_computedClass(errorMessage)]]">
95120
<span class="error-message">[[errorMessage]]</span>
@@ -141,6 +166,14 @@
141166
type: Boolean,
142167
value: false,
143168
notify: true
169+
},
170+
useGravatar: {
171+
type: Boolean,
172+
value: function () {
173+
return sessionStorage.useGravatar === "yes";
174+
},
175+
notify: true,
176+
observer: '_useGravatarChanged'
144177
}
145178
};
146179
}
@@ -244,6 +277,10 @@
244277
this.updateStyles();
245278
return classes;
246279
}
280+
_useGravatarChanged(g)
281+
{
282+
sessionStorage.useGravatar = g === true ? "yes" : "no";
283+
}
247284
}
248285
window.customElements.define(LoginForm.is, LoginForm);
249286
</script>

src/elements/dv-elements/user-profile/gravatar-request.html

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,10 @@
33

44
<dom-module id="gravatar-request">
55
<template>
6-
<iron-jsonp-library
7-
id="jsonp"
8-
library-url="[[libraryUrl]]"
9-
library-loaded="{{loaded}}"
10-
library-error-message="{{errorMessage}}"></iron-jsonp-library>
6+
<div id="jsonp-holder"></div>
117
</template>
128
<script>
13-
class GravatarRequest extends Polymer.Element
9+
class GravatarRequest extends DcacheViewMixins.Namespace(DcacheViewMixins.Commons(Polymer.Element))
1410
{
1511
constructor()
1612
{
@@ -39,13 +35,8 @@
3935
notify: true,
4036
observer: '_generateLibraryUrl'
4137
},
42-
errorMessage: {
43-
type: String,
44-
observer: '_errorOccurred'
45-
},
46-
loaded: {
47-
type: Boolean,
48-
observer: '_generateGravatarSrc'
38+
_runningHash: {
39+
type: String
4940
},
5041
_counter: {
5142
type: Number,
@@ -74,31 +65,40 @@
7465
}
7566
_generateLibraryUrl(hash)
7667
{
77-
if (hash.length > 0 && this._counter < hash.length) {
78-
this.$.jsonp.libraryUrl =
79-
`https://en.gravatar.com/${hash[this._counter]}.json?callback=%%callback%%`;
80-
this._counter++;
81-
} else {
82-
throw new Error("No associated Gravatar available with these emails.");
68+
if (hash) {
69+
if (this._counter > hash.length) {
70+
throw new Error("No associated Gravatar available with these emails.");
71+
}
72+
if (hash.length > 0 && this._counter < hash.length) {
73+
this.removeAllChildren(this.$["jsonp-holder"]);
74+
const jsonp = /** @type {!IronJsonpLibrary} */ (
75+
document.createElement('iron-jsonp-library'));
76+
jsonp.addEventListener('library-loaded-changed', this._generateGravatarSrc.bind(this));
77+
jsonp.addEventListener('library-error-message-changed', this._errorOccurred.bind(this));
78+
this.$['jsonp-holder'].appendChild(jsonp);
79+
this._runningHash = hash[this._counter];
80+
jsonp.libraryUrl = `https://en.gravatar.com/${this._runningHash}.json?callback=%%callback%%`;
81+
this._counter++;
82+
}
8383
}
8484
}
85-
_errorOccurred(err)
85+
_errorOccurred(event)
8686
{
87-
if (err !== null) {
87+
if (event && !!(event.detail) && !!(event.detail.value)) {
8888
try {
8989
this._generateLibraryUrl(this.hash);
9090
} catch (e) {
9191
this.dispatchEvent(new CustomEvent('gravatar-request-error', {detail: {message: err}}));
9292
}
9393
}
9494
}
95-
_generateGravatarSrc(isSuccessful)
95+
_generateGravatarSrc(event)
9696
{
97-
if (isSuccessful) {
97+
if (event.detail.value) {
9898
window.CONFIG.avatarSrc =
99-
`https://secure.gravatar.com/avatar/${this.hash[+this._counter-1]}?s=${this.size}`;
99+
`https://secure.gravatar.com/avatar/${this._runningHash}?s=${this.size}`;
100100
this.dispatchEvent(new CustomEvent('gravatar-request-successful', {detail: {
101-
link: `https://secure.gravatar.com/avatar/${this.hash[+this._counter-1]}?s=${this.size}`}}));
101+
link: `https://secure.gravatar.com/avatar/${this._runningHash}?s=${this.size}`}}));
102102
}
103103
}
104104
}

src/elements/dv-elements/user-profile/user-image.html

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
<style>
88
:host {
99
--user-image-border-radius: 0;
10+
--user-image-width: 60px;
11+
--user-image-height: 60px;
1012
}
1113
.container{
1214
width: 100%;
@@ -25,14 +27,16 @@
2527
}
2628
img {
2729
border-radius: var(--user-image-border-radius);
30+
width: var(--user-image-width);
31+
height: var(--user-image-height);
2832
}
2933
</style>
3034
<div class="container">
3135
<gravatar-request id="gravatar"
3236
size="[[size]]"
3337
on-gravatar-request-error="_gravatarResponseListener"
3438
on-gravatar-request-successful="_gravatarResponseListener"></gravatar-request>
35-
<img id="avatar" width="{{size}}" height="{{size}}">
39+
<img id="avatar">
3640
<paper-spinner id="spinner" active="[[loading]]"></paper-spinner>
3741
</div>
3842
</template>
@@ -57,7 +61,7 @@
5761
},
5862
size: {
5963
type: Number,
60-
Value: 60,
64+
value: 60,
6165
notify: true
6266
},
6367
loading: {
@@ -74,7 +78,11 @@
7478
link: {
7579
type: String,
7680
notify: true,
77-
}
81+
},
82+
gravatarSwitch: {
83+
type: Boolean,
84+
notify: true
85+
},
7886
}
7987
}
8088
static get observers()
@@ -84,35 +92,53 @@
8492
'_visibility(loading)'
8593
];
8694
}
95+
constructor()
96+
{
97+
super();
98+
this._requestNewImageListener = this._requestNewImage.bind(this)
99+
}
87100
ready()
88101
{
89102
super.ready();
90103
Polymer.RenderStatus.afterNextRender(this, ()=> {
91104
if (window.CONFIG.avatarSrc === undefined || window.CONFIG.avatarSrc === "") {
92-
if (this.email===undefined || this.email === null || this.email === "") {
93-
this.src = this._fallbackCall(this.fallbackValue);
94-
return;
95-
}
96-
const gravatar = this.$.gravatar;
97-
gravatar.request(this.email);
98-
99-
/**
100-
* If no response is received from the request after 1.5 seconds,
101-
* use the fallback option.
102-
*/
103-
setTimeout(()=>{
104-
if (!window.CONFIG.avatarSrc) {
105+
if (sessionStorage.getItem('useGravatar') === "yes") {
106+
if (this.email===undefined || this.email === null
107+
|| this.email === "" || this.email === "not available") {
105108
this.src = this._fallbackCall(this.fallbackValue);
109+
return;
106110
}
107-
}, 1500);
111+
this._gravatarRequestWithFallBack();
112+
} else {
113+
this.src = this._fallbackCall(this.fallbackValue);
114+
}
108115
} else {
109116
this.src = window.CONFIG.avatarSrc;
110117
}
111118
});
112119
}
120+
connectedCallback()
121+
{
122+
super.connectedCallback();
123+
window.addEventListener('dv-user-image-request', this._requestNewImageListener);
124+
}
125+
disconnectedCallback()
126+
{
127+
super.disconnectedCallback();
128+
window.removeEventListener('dv-user-image-request', this._requestNewImageListener);
129+
}
113130
_gravatarResponseListener(e)
114131
{
115-
this.src = e.detail.link ? e.detail.link : this._fallbackCall(this.fallbackValue);
132+
if (e.detail.link) {
133+
this.src = e.detail.link;
134+
sessionStorage.setItem('useGravatar', 'yes');
135+
this.gravatarSwitch = true;
136+
} else {
137+
this.src = this._fallbackCall(this.fallbackValue);
138+
this.dispatchEvent(new CustomEvent('dv-namespace-show-message-toast', {
139+
detail: {message: e.message}, bubbles: true, composed: true
140+
}));
141+
}
116142
}
117143
_srcChanged(n)
118144
{
@@ -127,6 +153,8 @@
127153
const uIcon = new IdenticonRequest(value);
128154
uIcon.size = this.size;
129155
window.CONFIG.avatarSrc = uIcon.generateSrc();
156+
sessionStorage.setItem('useGravatar', 'no');
157+
this.gravatarSwitch = false;
130158
return uIcon.generateSrc();
131159
}
132160
_visibility(loading) {
@@ -138,6 +166,37 @@
138166
this.$.spinner.classList.add('hide');
139167
}
140168
}
169+
_gravatarRequestWithFallBack()
170+
{
171+
try {
172+
const gravatar = this.$.gravatar;
173+
gravatar._counter = 0;
174+
gravatar.request(this.email);
175+
} catch (e) {
176+
this.src = this._fallbackCall(this.fallbackValue);
177+
this.dispatchEvent(new CustomEvent('dv-namespace-show-message-toast', {
178+
detail: {message: `${e.message}`}, bubbles: true, composed: true
179+
}));
180+
}
181+
182+
/**
183+
* If no response is received from the request after 1.5 seconds,
184+
* use the fallback option.
185+
*/
186+
setTimeout(()=>{
187+
if (!window.CONFIG.avatarSrc) {
188+
this.src = this._fallbackCall(this.fallbackValue);
189+
}
190+
}, 1500);
191+
}
192+
_requestNewImage(e)
193+
{
194+
if (e.detail.type === "gravatar") {
195+
this._gravatarRequestWithFallBack();
196+
} else if (e.detail.type === "identicon") {
197+
this.src = this._fallbackCall(this.fallbackValue);
198+
}
199+
}
141200
}
142201
window.customElements.define(UserImage.is, UserImage);
143202
</script>

src/elements/dv-elements/user-profile/user-profile-dropdown.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
}
8989
user-image {
9090
--user-image-border-radius: 5px;
91+
--user-image-width: 20px;
92+
--user-image-height: 20px;
9193
}
9294
.dropdown-content .dropdown-divider {
9395
height: 1px;
@@ -105,7 +107,7 @@
105107
</style>
106108
<div class="dropdown">
107109
<div on-tap="_open" class="dropbtn">
108-
<user-image size="20" fallback-value="[[username]]" email="[[email]]"></user-image>
110+
<user-image fallback-value="[[username]]" email="[[email]]"></user-image>
109111
<iron-icon icon="icons:arrow-drop-down"></iron-icon>
110112
</div>
111113
<div id="dropdownPanel" class="dropdown-content">

0 commit comments

Comments
 (0)