summaryrefslogtreecommitdiffstats
path: root/client/components/users
diff options
context:
space:
mode:
authorMaxime Quandalle <maxime@quandalle.com>2015-05-12 19:20:58 +0200
committerMaxime Quandalle <maxime@quandalle.com>2015-05-12 19:33:50 +0200
commit2dbea30842ec63a68055245fe26633bb7913daf3 (patch)
treee9143893a3d3bf4ad34dd3a97d6f3466561c8756 /client/components/users
downloadwekan-2dbea30842ec63a68055245fe26633bb7913daf3.tar.gz
wekan-2dbea30842ec63a68055245fe26633bb7913daf3.tar.bz2
wekan-2dbea30842ec63a68055245fe26633bb7913daf3.zip
Renaissance
_,,ad8888888888bba,_ ,ad88888I888888888888888ba, ,88888888I88888888888888888888a, ,d888888888I8888888888888888888888b, d88888PP"""" ""YY88888888888888888888b, ,d88"'__,,--------,,,,.;ZZZY8888888888888, ,8IIl'" ;;l"ZZZIII8888888888, ,I88l;' ;lZZZZZ888III8888888, ,II88Zl;. ;llZZZZZ888888I888888, ,II888Zl;. .;;;;;lllZZZ888888I8888b ,II8888Z;; `;;;;;''llZZ8888888I8888, II88888Z;' .;lZZZ8888888I888b II88888Z; _,aaa, .,aaaaa,__.l;llZZZ88888888I888 II88888IZZZZZZZZZ, .ZZZZZZZZZZZZZZ;llZZ88888888I888, II88888IZZ<'(@@>Z| |ZZZ<'(@@>ZZZZ;;llZZ888888888I88I ,II88888; `""" ;| |ZZ; `""" ;;llZ8888888888I888 II888888l `;; .;llZZ8888888888I888, ,II888888Z; ;;; .;;llZZZ8888888888I888I III888888Zl; .., `;; ,;;lllZZZ88888888888I888 II88888888Z;;...;(_ _) ,;;;llZZZZ88888888888I888, II88888888Zl;;;;;' `--'Z;. .,;;;;llZZZZ88888888888I888b ]I888888888Z;;;;' ";llllll;..;;;lllZZZZ88888888888I8888, II888888888Zl.;;"Y88bd888P";;,..;lllZZZZZ88888888888I8888I II8888888888Zl;.; `"PPP";;;,..;lllZZZZZZZ88888888888I88888 II888888888888Zl;;. `;;;l;;;;lllZZZZZZZZW88888888888I88888 `II8888888888888Zl;. ,;;lllZZZZZZZZWMZ88888888888I88888 II8888888888888888ZbaalllZZZZZZZZZWWMZZZ8888888888I888888, `II88888888888888888b"WWZZZZZWWWMMZZZZZZI888888888I888888b `II88888888888888888;ZZMMMMMMZZZZZZZZllI888888888I8888888 `II8888888888888888 `;lZZZZZZZZZZZlllll888888888I8888888, II8888888888888888, `;lllZZZZllllll;;.Y88888888I8888888b, ,II8888888888888888b .;;lllllll;;;.;..88888888I88888888b, II888888888888888PZI;. .`;;;.;;;..; ...88888888I8888888888, II888888888888PZ;;';;. ;. .;. .;. .. Y8888888I88888888888b, ,II888888888PZ;;' `8888888I8888888888888b, II888888888' 888888I8888888888888888 ,II888888888 ,888888I8888888888888888 ,d88888888888 d888888I8888888888ZZZZZZ ,ad888888888888I 8888888I8888ZZZZZZZZZZZZ 888888888888888' 888888IZZZZZZZZZZZZZZZZZ 8888888888P'8P' Y888ZZZZZZZZZZZZZZZZZZZZ 888888888, " ,ZZZZZZZZZZZZZZZZZZZZZZZ 8888888888, ,ZZZZZZZZZZZZZZZZZZZZZZZZZZ 888888888888a, _ ,ZZZZZZZZZZZZZZZZZZZZ88888888 888888888888888ba,_d' ,ZZZZZZZZZZZZZZZZZ8888888888888 8888888888888888888888bbbaaa,,,______,ZZZZZZZZZZZZZZZ88888888888888888 88888888888888888888888888888888888ZZZZZZZZZZZZZZZ88888888888888888888 8888888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888 888888888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888888888 8888888888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888 88888888888888888888888888888ZZZZZZZZZZZZZZ888888888888888888888888888 8888888888888888888888888888ZZZZZZZZZZZZZZ88888888888888888 Normand 8 88888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888 Veilleux 8 8888888888888888888888888ZZZZZZZZZZZZZZ8888888888888888888888888888888
Diffstat (limited to 'client/components/users')
-rw-r--r--client/components/users/avatar.jade7
-rw-r--r--client/components/users/events.js59
-rw-r--r--client/components/users/form.styl50
-rw-r--r--client/components/users/headerButtons.jade27
-rw-r--r--client/components/users/headerButtons.js5
-rw-r--r--client/components/users/helpers.js27
-rw-r--r--client/components/users/member.styl107
-rw-r--r--client/components/users/router.js29
-rw-r--r--client/components/users/templates.html118
9 files changed, 429 insertions, 0 deletions
diff --git a/client/components/users/avatar.jade b/client/components/users/avatar.jade
new file mode 100644
index 00000000..70ef69e0
--- /dev/null
+++ b/client/components/users/avatar.jade
@@ -0,0 +1,7 @@
+template(name="userAvatar")
+ .member(class="{{class}} {{# if draggable }}js-member{{else}}js-member-on-card-menu{{/if}}"
+ title="{{userData.profile.name}} ({{userData.username}})")
+ +avatar(user=userData size=size)
+ if showBadges
+ span.member-status(class="{{# if userData.profile.status}}active{{/if}}")
+ span.member-type(class=memberType)
diff --git a/client/components/users/events.js b/client/components/users/events.js
new file mode 100644
index 00000000..14df9717
--- /dev/null
+++ b/client/components/users/events.js
@@ -0,0 +1,59 @@
+// XXX This should be handled by default (and in a better way) by useraccounts.
+// See https://github.com/meteor-useraccounts/core/issues/384
+Template.atForm.onRendered(function() {
+ this.find('input').focus();
+});
+
+Template.memberMenuPopup.events({
+ 'click .js-language': Popup.open('setLanguage'),
+ 'click .js-logout': function(evt) {
+ evt.preventDefault();
+
+ Meteor.logout(function() {
+ Router.go('Home');
+ });
+ }
+});
+
+Template.setLanguagePopup.events({
+ 'click .js-set-language': function(evt) {
+ Users.update(Meteor.userId(), {
+ $set: {
+ 'profile.language': this.tag
+ }
+ });
+ evt.preventDefault();
+ }
+});
+
+Template.profileEditForm.events({
+ 'click .js-edit-profile': function() {
+ Session.set('ProfileEditForm', true);
+ },
+ 'click .js-cancel-edit-profile': function() {
+ Session.set('ProfileEditForm', false);
+ },
+ 'submit #ProfileEditForm': function(evt, t) {
+ var name = t.find('#name').value;
+ var bio = t.find('#bio').value;
+
+ // trim and update
+ if ($.trim(name)) {
+ Users.update(this.profile()._id, {
+ $set: {
+ 'profile.name': name,
+ 'profile.bio': bio
+ }
+ }, function() {
+
+ // update complete close profileEditForm
+ Session.set('ProfileEditForm', false);
+ });
+ }
+ evt.preventDefault();
+ }
+});
+
+Template.memberName.events({
+ 'click .js-show-mem-menu': Popup.open('user')
+});
diff --git a/client/components/users/form.styl b/client/components/users/form.styl
new file mode 100644
index 00000000..845c810d
--- /dev/null
+++ b/client/components/users/form.styl
@@ -0,0 +1,50 @@
+.at-form-landing-logo
+ width: 275px
+ margin: auto
+ margin-top: 50px
+ margin-top: 17vh
+
+ img
+ width: 275px
+
+
+.at-form
+ margin: auto
+ width: 275px
+ padding: 25px
+ margin-top: 20px
+ padding-bottom: 10px
+ background: #fff
+ border-radius: 3px
+ border: 1px solid #dbdbdb
+ border-bottom-color: #c2c2c2
+ box-shadow: 0 1px 6px rgba(0, 0, 0, .3)
+
+ .at-link
+ color: darken(#27AE60, 40%)
+
+ label
+ margin-bottom: 3px
+
+ input
+ width: 100%
+
+ .at-title
+ background: #F7F7F7
+ margin: -25px
+ padding: 15px 25px 5px
+ margin-bottom: 20px
+ border-bottom: 1px solid #dcdcdc
+ color: darken(white, 70%)
+ font-weight: bold
+
+ .at-signup-link,
+ .at-signin-link,
+ .at-forgotPwd
+ font-size: 0.9em
+ margin-top: 15px
+ color: darken(white, 70%)
+
+ .at-signUp,
+ .at-signIn
+ font-weight: bold
diff --git a/client/components/users/headerButtons.jade b/client/components/users/headerButtons.jade
new file mode 100644
index 00000000..74c24ad5
--- /dev/null
+++ b/client/components/users/headerButtons.jade
@@ -0,0 +1,27 @@
+template(name="headerUserBar")
+ #header-user-bar
+ if currentUser
+ a.js-open-header-member-menu
+ if currentUser.profile.name
+ = currentUser.profile.name
+ else
+ = currentUser.username
+ i.fa.fa-chevron-down
+ else
+ a(href="{{pathFor route='signUp'}}") Sign in
+ span.separator -
+ a(href="{{pathFor route='signIn'}}") Log in
+
+template(name="memberHeader")
+ a.header-member.js-open-header-member-menu
+ span= currentUser.profile.name
+ +userAvatar(user=currentUser size="small")
+
+template(name="memberMenuPopup")
+ ul.pop-over-list
+ li: a(href="{{pathFor route='Profile' username=currentUser.username}}") {{_ 'profile'}}
+ li: a.js-language {{_ 'language'}}
+ li: a(href = "{{pathFor route='Settings'}}") {{_ 'settings'}}
+ hr
+ ul.pop-over-list
+ li: a.js-logout {{_ 'log-out'}}
diff --git a/client/components/users/headerButtons.js b/client/components/users/headerButtons.js
new file mode 100644
index 00000000..70594fb5
--- /dev/null
+++ b/client/components/users/headerButtons.js
@@ -0,0 +1,5 @@
+Template.headerUserBar.events({
+ 'click .js-sign-in': Popup.open('signup'),
+ 'click .js-log-in': Popup.open('login'),
+ 'click .js-open-header-member-menu': Popup.open('memberMenu')
+});
diff --git a/client/components/users/helpers.js b/client/components/users/helpers.js
new file mode 100644
index 00000000..33867298
--- /dev/null
+++ b/client/components/users/helpers.js
@@ -0,0 +1,27 @@
+Template.userAvatar.helpers({
+ userData: function() {
+ if (! this.user) {
+ this.user = Users.findOne(this.userId);
+ }
+ return this.user;
+ },
+ memberType: function() {
+ var userId = this.userId || this.user._id;
+ var user = Users.findOne(userId);
+ return user && user.isBoardAdmin() ? 'admin' : 'normal';
+ }
+});
+
+Template.setLanguagePopup.helpers({
+ languages: function() {
+ return _.map(TAPi18n.getLanguages(), function(lang, tag) {
+ return {
+ tag: tag,
+ name: lang.name
+ };
+ });
+ },
+ isCurrentLanguage: function() {
+ return this.tag === TAPi18n.getLanguage();
+ }
+});
diff --git a/client/components/users/member.styl b/client/components/users/member.styl
new file mode 100644
index 00000000..3dfdaa37
--- /dev/null
+++ b/client/components/users/member.styl
@@ -0,0 +1,107 @@
+@import 'nib'
+
+avatar-radius = 50%
+
+.member
+ border-radius: 3px
+ display: block
+ float: left
+ height: 30px
+ width: @height
+ margin: 0 4px 4px 0
+ position: relative
+ cursor: pointer
+ user-select: none
+ z-index: 1
+ text-decoration: none
+ border-radius: avatar-radius
+
+ .avatar
+ height: 100%
+ width: @height
+ display: flex
+ align-items: center
+ justify-content: center
+ overflow: hidden
+ border-radius: avatar-radius
+
+ .avatar-initials
+ font-weight: bold
+ max-width: 100%
+ max-height: 100%
+ font-size: 14px
+ line-height: 200%
+ background-color: #dbdbdb
+ color: #444444
+
+ .avatar-image
+ max-width: 100%
+ max-height: 100%
+
+ .member-status
+ background-color: #b3b3b3
+ border: 1px solid #fff
+ border-radius: 50%
+ height: 8px
+ width: @height
+ position: absolute
+ right: 0px
+ bottom: 0px
+ border: 1px solid white
+
+ &.active
+ background: #64c464
+ border-color: #daf1da
+
+ &.idle
+ background: #e4e467
+ border-color: #f7f7d4
+
+ &.disconnected
+ background: #bdbdbd
+ border-color: #ededed
+
+ &.extra-small
+ .avatar-initials
+ font-size: 9px
+ width: 18px
+ height: 18px
+ line-height: 18px
+
+ .avatar-image
+ width: 18px
+ height: 18px
+
+ &.small
+ width: 30px
+ height: 30px
+
+ .avatar-initials
+ font-size: 12px
+ line-height: 30px
+
+ &.large
+ height: 85px
+ line-height: 85px
+ width: 85px
+
+ .avatar
+ width: 85px
+ height: 85px
+
+ .avatar-initials
+ font-size: 16px
+ font-weight: 700
+ line-height: 85px
+ width: 85px
+
+.atMention
+ background: #dbdbdb
+ border-radius: 3px
+ padding: 1px 4px
+ margin: -1px 0
+ display: inline-block
+
+ &.me
+ background: #cfdfe8
+
diff --git a/client/components/users/router.js b/client/components/users/router.js
new file mode 100644
index 00000000..d59e174d
--- /dev/null
+++ b/client/components/users/router.js
@@ -0,0 +1,29 @@
+
+_.each(['signIn', 'signUp', 'resetPwd',
+ 'forgotPwd', 'enrollAccount', 'changePwd'], function(routeName) {
+ AccountsTemplates.configureRoute(routeName, {
+ layoutTemplate: 'userFormsLayout'
+ });
+});
+
+Router.route('/profile/:username', {
+ name: 'Profile',
+ template: 'profile',
+ waitOn: function() {
+ return Meteor.subscribe('profile', this.params.username);
+ },
+ data: function() {
+ var params = this.params;
+ return {
+ profile: function() {
+ return Users.findOne({ username: params.username });
+ }
+ };
+ }
+});
+
+Router.route('/settings', {
+ name: 'Settings',
+ template: 'settings',
+ layoutTemplate: 'AuthLayout'
+});
diff --git a/client/components/users/templates.html b/client/components/users/templates.html
new file mode 100644
index 00000000..5783eebf
--- /dev/null
+++ b/client/components/users/templates.html
@@ -0,0 +1,118 @@
+<template name="setLanguagePopup">
+<ul class="pop-over-list">
+ {{#each languages}}
+ <li class="{{# if isCurrentLanguage}}active{{/if}}">
+ <a class="js-set-language">
+ {{name}}
+ {{# if isCurrentLanguage}}
+ <span class="icon-sm fa fa-check"></span>
+ {{/if}}
+ </a>
+ </li>
+ {{/each}}
+</ul>
+</template>
+
+<template name='profile'>
+ {{ # if profile }}
+ <div class="tabbed-pane-header">
+ <div class="tabbed-pane-header-wrapper clearfix">
+ <a class="tabbed-pane-header-image profile-image ed js-change-avatar-profile" href="#">
+ {{> userAvatar user=profile size="large"}}
+ </a>
+ <div class="tabbed-pane-header-details">
+ <div class="js-current-details">
+ <div class="tabbed-pane-header-details-name">
+ <h1 class="inline"> {{ profile.profile.name }} </h1>
+ <p class="window-title-extra quiet"> @{{ profile.username }} </p>
+ </div>
+ <div class="tabbed-pane-header-details-content">
+ <p>{{ profile.profile.bio }}</p>
+ </div>
+ <div class="tabbed-pane-header-details-content"></div>
+ </div>
+ {{ > profileEditForm }}
+ </div>
+ </div>
+ </div>
+ {{ else }}
+ {{ > message label='user-profile-not-found' }}
+ {{ /if }}
+</template>
+
+<template name="settings">
+ {{ > profile profile=currentUser }}
+ <div class="tabbed-pane-main-col clearfix">
+ <div class="tabbed-pane-main-col-loading hide js-loading-page">
+ <span class="tabbed-pane-main-col-loading-spinner spinner"></span>
+ </div>
+ <div class="tabbed-pane-main-col-wrapper js-content">
+ <div class="window-module clearfix">
+ <div class="window-module-title">
+ <h3>{{_ "account-details"}}</h3>
+ </div>
+ <a class="big-link js-change-name-and-bio" href="#">
+ <span class="text">{{_ 'change-name-initials-bio'}}</span>
+ </a>
+ <a class="big-link js-change-avatar" href="#">
+ <span class="text">{{_ 'change-avatar'}}</span>
+ </a>
+ <a class="big-link js-change-password" href="#">
+ <span class="text">{{_ 'change-password'}}</span>
+ </a>
+ <a class="big-link js-change-email" href="#">
+ <span class="text">{{_ 'change-email'}}</span>
+ </a>
+ </div>
+ </div>
+ </div>
+</template>
+
+<template name="profileEditForm">
+ {{#if $eq currentUser.username profile.username }}
+ {{# if session 'ProfileEditForm' }}
+ <form id="ProfileEditForm" class="js-profile-form">
+ <p class="error js-profile-form-error hide"></p>
+ <label>{{_ "username"}}</label>
+ <input type="text" id="username" value="{{ profile.username }}" disabled>
+ <label>{{_ "fullname"}}</label>
+ <input type="text" id="name" value="{{ profile.profile.name }}">
+ <label>
+ {{_ "bio"}} <span class="quiet">({{_ 'optional'}})</span>
+ </label>
+ <textarea id="bio">{{ profile.profile.bio }}</textarea>
+ <input type="submit" class="primary wide js-submit-profile" value="{{_ 'save'}}">
+ <input type="button" class="js-cancel-edit-profile" value="{{_ 'cancel'}}">
+ </form>
+ {{ else }}
+ <a class="button-link tabbed-pane-header-details-edit js-edit-profile" href="#">
+ <span class="icon-sm fa fa-pencil"></span>
+ {{_ "edit-profile"}}
+ </a>
+ {{ /if }}
+ {{ /if }}
+</template>
+
+<template name="userPopup">
+ <div class="board-member-menu">
+ <div class="mini-profile-info">
+ {{> userAvatar user=user}}
+ <div class="info">
+ <h3 class="bottom" style="margin-right: 40px;">
+ <a class="js-profile" href="{{ pathFor route='Profile' username=user.username }}">{{ user.profile.name }}</a>
+ </h3>
+ <p class="quiet bottom">@{{ user.username }}</p>
+ </div>
+ </div>
+ </div>
+</template>
+
+
+<template name="memberName">
+ <a class="inline-object js-show-mem-menu" href="{{ pathFor route='Profile' username=user.username }}">
+ {{ user.profile.name }}
+ {{# if username }}
+ ({{ user.username }})
+ {{ /if }}
+ </a>
+</template>