add unique avatar support
This commit is contained in:
parent
367e6ab8be
commit
db4df87be1
5 changed files with 139 additions and 70 deletions
BIN
app/assets/images/avatar-bg.png
Normal file
BIN
app/assets/images/avatar-bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -14,6 +14,24 @@ class Content extends App.ControllerContent
|
||||||
super
|
super
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
|
for avatar in @$('.user.avatar')
|
||||||
|
avatar = $(avatar)
|
||||||
|
size = if avatar.hasClass('big') then 50 else 40
|
||||||
|
@createUniqueAvatar avatar, size, avatar.data('firstname'), avatar.data('lastname'), avatar.data('userid')
|
||||||
|
|
||||||
|
createUniqueAvatar: (holder, size, firstname, lastname, id) ->
|
||||||
|
width = 300
|
||||||
|
height = 226
|
||||||
|
|
||||||
|
holder.addClass 'unique'
|
||||||
|
|
||||||
|
rng = new Math.seedrandom(id);
|
||||||
|
x = rng() * (width - size)
|
||||||
|
y = rng() * (height - size)
|
||||||
|
holder.css('background-position', "-#{ x }px -#{ y }px")
|
||||||
|
|
||||||
|
holder.text(firstname[0] + lastname[0])
|
||||||
|
|
||||||
render: ->
|
render: ->
|
||||||
@html App.view('layout_ref/content')()
|
@html App.view('layout_ref/content')()
|
||||||
|
|
||||||
|
|
1
app/assets/javascripts/app/lib/base/seedrandom.min.js
vendored
Normal file
1
app/assets/javascripts/app/lib/base/seedrandom.min.js
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
!function(a,b,c,d,e,f,g,h,i){function j(a){var b,c=a.length,e=this,f=0,g=e.i=e.j=0,h=e.S=[];for(c||(a=[c++]);d>f;)h[f]=f++;for(f=0;d>f;f++)h[f]=h[g=r&g+a[f%c]+(b=h[f])],h[g]=b;(e.g=function(a){for(var b,c=0,f=e.i,g=e.j,h=e.S;a--;)b=h[f=r&f+1],c=c*d+h[r&(h[f]=h[g=r&g+b])+(h[g]=b)];return e.i=f,e.j=g,c})(d)}function k(a,b){var c,d=[],e=typeof a;if(b&&"object"==e)for(c in a)try{d.push(k(a[c],b-1))}catch(f){}return d.length?d:"string"==e?a:a+"\0"}function l(a,b){for(var c,d=a+"",e=0;e<d.length;)b[r&e]=r&(c^=19*b[r&e])+d.charCodeAt(e++);return n(b)}function m(c){try{return a.crypto.getRandomValues(c=new Uint8Array(d)),n(c)}catch(e){return[+new Date,a,(c=a.navigator)&&c.plugins,a.screen,n(b)]}}function n(a){return String.fromCharCode.apply(0,a)}var o=c.pow(d,e),p=c.pow(2,f),q=2*p,r=d-1,s=c["seed"+i]=function(a,f,g){var h=[];f=1==f?{entropy:!0}:f||{};var r=l(k(f.entropy?[a,n(b)]:null==a?m():a,3),h),s=new j(h);return l(n(s.S),b),(f.pass||g||function(a,b,d){return d?(c[i]=a,b):a})(function(){for(var a=s.g(e),b=o,c=0;p>a;)a=(a+c)*d,b*=d,c=s.g(1);for(;a>=q;)a/=2,b/=2,c>>>=1;return(a+c)/b},r,"global"in f?f.global:this==c)};l(c[i](),b),g&&g.exports?g.exports=s:h&&h.amd&&h(function(){return s})}(this,[],Math,256,6,52,"object"==typeof module&&module,"function"==typeof define&&define,"random");
|
|
@ -14,6 +14,34 @@
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
<h2>Avatars</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Users and customers might not have a profile images because:
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
<li>They didn't upload one
|
||||||
|
<li>They didn't login using a authentication provider like facebook, twitter or google where we get an avatar
|
||||||
|
<li>They have no avatar associated with their email address (gravatar)
|
||||||
|
</ol>
|
||||||
|
<p>
|
||||||
|
They will get a random avatar consisting of a blured version of the Zammad logo and their initials.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The background is generated by using a <i>random numbers generator</i> (RNG) with the user-id as the <b>seed</b>. The RNG is then used to create the <code>x</code> and <code>y</code> position of the background. Since the user-id is unique and does not change it's guaranteed that the avatar background stays the same and this makes it possible to calculate the avatar on the client without having to store the coordinates on the server side.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<span class="user avatar" data-firstname="Hans" data-lastname="Huber" data-userid="5"></span>
|
||||||
|
<span class="user avatar" data-firstname="Rafael" data-lastname="Schweizer" data-userid="6"></span>
|
||||||
|
<span class="user avatar" data-firstname="Stefanie" data-lastname="Lingerl" data-userid="7"></span>
|
||||||
|
<span class="user avatar" data-firstname="Igor" data-lastname="Kaufer" data-userid="8"></span>
|
||||||
|
<span class="user avatar" data-firstname="Ina" data-lastname="Lingerl" data-userid="12"></span>
|
||||||
|
<span class="big user avatar" data-firstname="Andreas" data-lastname="Berger" data-userid="9"></span>
|
||||||
|
<span class="big user avatar" data-firstname="Luisa" data-lastname="Hofner" data-userid="10"></span>
|
||||||
|
<span class="big user avatar" data-firstname="Clara" data-lastname="Altman" data-userid="11"></span>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<h2>Headlines</h2>
|
<h2>Headlines</h2>
|
||||||
<h1>h1. Bootstrap heading</h1>
|
<h1>h1. Bootstrap heading</h1>
|
||||||
<h2>h2. Bootstrap heading</h2>
|
<h2>h2. Bootstrap heading</h2>
|
||||||
|
|
|
@ -7,8 +7,6 @@ body {
|
||||||
|
|
||||||
ol,
|
ol,
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.create {
|
a.create {
|
||||||
|
@ -595,6 +593,7 @@ ol.tabs li {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs {
|
.tabs {
|
||||||
|
padding: 0;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
color: #b8b8b8;
|
color: #b8b8b8;
|
||||||
border: 1px solid rgba(0,8,14,.08);
|
border: 1px solid rgba(0,8,14,.08);
|
||||||
|
@ -1864,6 +1863,23 @@ footer {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unique.avatar {
|
||||||
|
background-image: url(<%= asset_path "avatar-bg.png" %>);
|
||||||
|
background-size: auto;
|
||||||
|
color: white;
|
||||||
|
line-height: 42px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
text-shadow: 0 1px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unique.big.avatar {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 52px;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 32%;
|
width: 32%;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
|
@ -3174,76 +3190,82 @@ footer {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-entry .recipientList-iconSpacer {
|
.recipientList,
|
||||||
|
.recipientList-organisationMembers {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recipientList-entry .recipientList-iconSpacer {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-entry .icon:not(.plus) {
|
.recipientList-entry .icon:not(.plus) {
|
||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-entry:hover .icon {
|
.recipientList-entry:hover .icon {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-name {
|
.recipientList-name {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-detail {
|
.recipientList-detail {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-icon.plus {
|
.recipientList-icon.plus {
|
||||||
margin-left: 13px;
|
margin-left: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-new {
|
.recipientList-new {
|
||||||
background: hsl(145,51%,45%);
|
background: hsl(145,51%,45%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown .recipientList-new:hover {
|
.dropdown .recipientList-new:hover {
|
||||||
background: hsl(147,52%,43%);
|
background: hsl(147,52%,43%);
|
||||||
}
|
}
|
||||||
|
|
||||||
li.recipientList-controls,
|
li.recipientList-controls,
|
||||||
li.recipientList-controls:hover {
|
li.recipientList-controls:hover {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: hsl(206,7%,28%);
|
background: hsl(206,7%,28%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-backClickArea {
|
.recipientList-backClickArea {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-backButton {
|
.recipientList-backButton {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: 1px solid hsl(234,10%,10%);
|
border: 1px solid hsl(234,10%,10%);
|
||||||
box-shadow: 0 1px rgba(255,255,255,.03) inset;
|
box-shadow: 0 1px rgba(255,255,255,.03) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-backClickArea:active .recipientList-backButton {
|
.recipientList-backClickArea:active .recipientList-backButton {
|
||||||
background: hsl(206,7%,25%);
|
background: hsl(206,7%,25%);
|
||||||
box-shadow: 0 1px rgba(0,0,0,.1) inset;
|
box-shadow: 0 1px rgba(0,0,0,.1) inset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-backButton .icon {
|
.recipientList-backButton .icon {
|
||||||
margin-bottom: -2px;
|
margin-bottom: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.recipientList-organisationMembers {
|
.recipientList-organisationMembers {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue