Worked on user view appearance
This commit is contained in:
parent
3ec1b94ee7
commit
f5606c4169
21 changed files with 279 additions and 51 deletions
|
@ -8,6 +8,11 @@ body {
|
|||
font-size: 17px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-variant: small-caps;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#middle {
|
||||
padding: 0 2em;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
.form-wrapper {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#top-navigation li a {
|
||||
display: inline-block;
|
||||
font-variant: small-caps;
|
||||
padding: 0.5em 1em;
|
||||
color: #000;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#user-list {
|
||||
min-width: 20em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#user-list ul {
|
||||
|
@ -25,3 +26,34 @@
|
|||
display: inline-block;
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
||||
#user-list .users {
|
||||
display: inline-block;
|
||||
margin: 1em auto;
|
||||
}
|
||||
#user-list .users li {
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
||||
#user-list li:after {
|
||||
clear: left;
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
#user-list .user img {
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
margin-right: 1em;
|
||||
}
|
||||
#user-list .user .details {
|
||||
float: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#user-list .user h1 {
|
||||
margin-top: 0;
|
||||
font-weight: normal;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
|
51
public_html/css/user.css
Normal file
51
public_html/css/user.css
Normal file
|
@ -0,0 +1,51 @@
|
|||
#user-view {
|
||||
min-width: 30em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#user-view .side {
|
||||
text-align: center;
|
||||
width: 150px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#user-view .top {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#user-view ul {
|
||||
display: inline-block;
|
||||
list-style-type: none;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#user-view ul a {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
||||
#user-view ul a.active {
|
||||
background: #faffca;
|
||||
}
|
||||
|
||||
#user-view .tab {
|
||||
display: none;
|
||||
margin-top: 1.5em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#user-view .tab.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#user-view .tab.basic-info table {
|
||||
margin: 0 auto;
|
||||
text-align: left;
|
||||
}
|
||||
#user-view .tab.basic-info td {
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
<link rel="stylesheet" type="text/css" href="/css/login-form.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/registration-form.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/user-list.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="/css/user.css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -13,26 +13,20 @@ App.Controls.FileDropper = function(
|
|||
$fileInput.attr('multiple', allowMultiple);
|
||||
$fileInput.hide();
|
||||
|
||||
$fileInput.change(function(e)
|
||||
{
|
||||
$fileInput.change(function(e) {
|
||||
addFiles(this.files);
|
||||
});
|
||||
|
||||
$dropDiv.on('dragenter', function(e)
|
||||
{
|
||||
$dropDiv.on('dragenter', function(e) {
|
||||
$dropDiv.addClass('active');
|
||||
}).on('dragleave', function(e)
|
||||
{
|
||||
}).on('dragleave', function(e) {
|
||||
$dropDiv.removeClass('active');
|
||||
}).on('dragover', function(e)
|
||||
{
|
||||
}).on('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
}).on('drop', function(e)
|
||||
{
|
||||
}).on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
addFiles(e.originalEvent.dataTransfer.files);
|
||||
}).on('click', function(e)
|
||||
{
|
||||
}).on('click', function(e) {
|
||||
$fileInput.show().focus().trigger('click').hide();
|
||||
$dropDiv.addClass('active');
|
||||
});
|
||||
|
|
|
@ -16,7 +16,9 @@ App.Presenters.PagedCollectionPresenter = function(util, promise, api) {
|
|||
var totalRecords;
|
||||
|
||||
function init(args) {
|
||||
parseSearchArgs(args.searchArgs);
|
||||
pageNumber = parseInt(args.page) || 1;
|
||||
searchOrder = args.order;
|
||||
searchQuery = args.query;
|
||||
baseUri = args.baseUri;
|
||||
backendUri = args.backendUri;
|
||||
renderCallback = args.renderCallback;
|
||||
|
@ -99,13 +101,6 @@ App.Presenters.PagedCollectionPresenter = function(util, promise, api) {
|
|||
});
|
||||
}
|
||||
|
||||
function parseSearchArgs(searchArgs) {
|
||||
var args = util.parseComplexRouteArgs(searchArgs);
|
||||
pageNumber = parseInt(args.page) || 1;
|
||||
searchOrder = args.order;
|
||||
searchQuery = args.query;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
|
|
|
@ -33,7 +33,7 @@ App.Presenters.UserAccountRemovalPresenter = function(
|
|||
}
|
||||
|
||||
function render() {
|
||||
$el = jQuery(target);
|
||||
var $el = jQuery(target);
|
||||
$el.html(template({
|
||||
user: user,
|
||||
canDeleteAccount: privileges.canDeleteAccount}));
|
||||
|
@ -47,7 +47,8 @@ App.Presenters.UserAccountRemovalPresenter = function(
|
|||
|
||||
function accountRemovalFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
$messages = jQuery(target).find('.messages');
|
||||
var $el = jQuery(target);
|
||||
$messages = $el.find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (!$el.find('input[name=confirmation]:visible').prop('checked')) {
|
||||
messagePresenter.showError($messages, 'Must confirm to proceed.');
|
||||
|
|
|
@ -28,7 +28,7 @@ App.Presenters.UserBrowsingSettingsPresenter = function(
|
|||
}
|
||||
|
||||
function render() {
|
||||
$el = jQuery(target);
|
||||
var $el = jQuery(target);
|
||||
$el.html(template({user: user}));
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,13 @@ App.Presenters.UserListPresenter = function(
|
|||
}
|
||||
|
||||
function initPaginator(args) {
|
||||
activeSearchOrder = util.parseComplexRouteArgs(args.searchArgs).order;
|
||||
var searchArgs = util.parseComplexRouteArgs(args.searchArgs);
|
||||
searchArgs.order = searchArgs.order || 'name';
|
||||
activeSearchOrder = searchArgs.order;
|
||||
|
||||
pagedCollectionPresenter.init({
|
||||
searchArgs: args.searchArgs,
|
||||
pageNumber: searchArgs.page,
|
||||
order: searchArgs.order,
|
||||
baseUri: '#/users',
|
||||
backendUri: '/users',
|
||||
renderCallback: function updateCollection(data) {
|
||||
|
@ -44,6 +48,7 @@ App.Presenters.UserListPresenter = function(
|
|||
function render() {
|
||||
$el.html(template({
|
||||
userList: userList,
|
||||
formatRelativeTime: util.formatRelativeTime,
|
||||
}));
|
||||
$el.find('.order a').click(orderLinkClicked);
|
||||
$el.find('.order [data-order="' + activeSearchOrder + '"]').parent('li').addClass('active');
|
||||
|
@ -52,8 +57,7 @@ App.Presenters.UserListPresenter = function(
|
|||
pagedCollectionPresenter.render($pager);
|
||||
};
|
||||
|
||||
function orderLinkClicked(e)
|
||||
{
|
||||
function orderLinkClicked(e) {
|
||||
e.preventDefault();
|
||||
var $orderLink = jQuery(this);
|
||||
activeSearchOrder = $orderLink.attr('data-order');
|
||||
|
|
|
@ -18,6 +18,7 @@ App.Presenters.UserPresenter = function(
|
|||
var template;
|
||||
var user;
|
||||
var userName;
|
||||
var activeTab;
|
||||
|
||||
function init(args) {
|
||||
userName = args.userName;
|
||||
|
@ -39,7 +40,9 @@ App.Presenters.UserPresenter = function(
|
|||
userBrowsingSettingsPresenter.init(_.extend(extendedContext, {target: '#browsing-settings-target'})),
|
||||
userAccountSettingsPresenter.init(_.extend(extendedContext, {target: '#account-settings-target'})),
|
||||
userAccountRemovalPresenter.init(_.extend(extendedContext, {target: '#account-removal-target'})))
|
||||
.then(render);
|
||||
.then(function() {
|
||||
initTabs(args);
|
||||
})
|
||||
|
||||
}).fail(function(response) {
|
||||
$el.empty();
|
||||
|
@ -47,6 +50,11 @@ App.Presenters.UserPresenter = function(
|
|||
});
|
||||
}
|
||||
|
||||
function initTabs(args) {
|
||||
activeTab = args.tab || 'basic-info';
|
||||
render();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(template({
|
||||
user: user,
|
||||
|
@ -56,10 +64,23 @@ App.Presenters.UserPresenter = function(
|
|||
userBrowsingSettingsPresenter.render();
|
||||
userAccountSettingsPresenter.render();
|
||||
userAccountRemovalPresenter.render();
|
||||
};
|
||||
changeTab(activeTab);
|
||||
}
|
||||
|
||||
function changeTab(targetTab) {
|
||||
var $link = $el.find('a[data-tab=' + targetTab + ']');
|
||||
var $links = $link.closest('ul').find('a[data-tab]');
|
||||
var tab = $link.attr('data-tab');
|
||||
var $tabs = $link.closest('.tab-wrapper').find('.tab');
|
||||
$links.removeClass('active');
|
||||
$link.addClass('active');
|
||||
$tabs.removeClass('active');
|
||||
$tabs.filter('[data-tab=' + tab + ']').addClass('active');
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: initTabs,
|
||||
render: render
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ App.Router = function(jQuery, util, appState) {
|
|||
inject('#/users', 'userListPresenter');
|
||||
inject('#/users/:searchArgs', 'userListPresenter');
|
||||
inject('#/user/:userName', 'userPresenter');
|
||||
inject('#/user/:userName/:tab', 'userPresenter');
|
||||
setRoot('#/users');
|
||||
};
|
||||
|
||||
|
|
|
@ -90,12 +90,64 @@ App.Util = (function(jQuery, promise) {
|
|||
});
|
||||
}
|
||||
|
||||
function formatRelativeTime(timeString) {
|
||||
if (!timeString)
|
||||
return 'never';
|
||||
|
||||
var time = Date.parse(timeString);
|
||||
var now = Date.now();
|
||||
var difference = Math.abs(now - time);
|
||||
var future = now < time;
|
||||
|
||||
var text = (function(difference) {
|
||||
var mul = 1000;
|
||||
var prevMul;
|
||||
|
||||
mul *= 60;
|
||||
if (difference < mul)
|
||||
return 'a few seconds';
|
||||
if (difference < mul * 2)
|
||||
return 'a minute';
|
||||
|
||||
prevMul = mul; mul *= 60;
|
||||
if (difference < mul)
|
||||
return Math.round(difference / prevMul) + ' minutes';
|
||||
if (difference < mul * 2)
|
||||
return 'an hour';
|
||||
|
||||
prevMul = mul; mul *= 24;
|
||||
if (difference < mul)
|
||||
return Math.round(difference / prevMul) + ' hours';
|
||||
if (difference < mul * 2)
|
||||
return 'a day';
|
||||
|
||||
prevMul = mul; mul *= 30.42;
|
||||
if (difference < mul)
|
||||
return Math.round(difference / prevMul) + ' days';
|
||||
if (difference < mul * 2)
|
||||
return 'a month';
|
||||
|
||||
prevMul = mul; mul *= 12;
|
||||
if (difference < mul)
|
||||
return Math.round(difference / prevMul) + ' months';
|
||||
if (difference < mul * 2)
|
||||
return 'a year';
|
||||
|
||||
return Math.round(difference / mul) + ' years';
|
||||
})(difference);
|
||||
|
||||
if (text == 'a day')
|
||||
return future ? 'tomorrow' : 'yesterday';
|
||||
return future ? 'in ' + text : text + ' ago';
|
||||
}
|
||||
|
||||
return {
|
||||
promiseTemplate: promiseTemplate,
|
||||
initPresenter : initPresenter,
|
||||
initContentPresenter: initContentPresenter,
|
||||
parseComplexRouteArgs: parseComplexRouteArgs,
|
||||
compileComplexRouteArgs: compileComplexRouteArgs,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<form class="account-removal">
|
||||
<div class="messages"></div>
|
||||
<div class="messages"></div>
|
||||
|
||||
<form class="form-wrapper account-removal">
|
||||
<div class="form-row">
|
||||
<label class="form-label" for="account-removal-confirmation">Confirmation:</label>
|
||||
<div class="form-input">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<form class="account-settings">
|
||||
<div class="messages"></div>
|
||||
<div class="messages"></div>
|
||||
|
||||
<form class="form-wrapper account-settings">
|
||||
<% if (canChangeAvatarStyle) { %>
|
||||
<div class="form-row">
|
||||
<label class="form-label">User picture:</label>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<form class="browsing-settings">
|
||||
<div class="messages"></div>
|
||||
<div class="messages"></div>
|
||||
|
||||
<form class="form-wrapper browsing-settings">
|
||||
<div class="form-row">
|
||||
<label class="form-label">Safety:</label>
|
||||
<div class="form-input">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="messages"></div>
|
||||
|
||||
<form method="post" class="form-wrapper">
|
||||
<form class="form-wrapper">
|
||||
<div class="form-row">
|
||||
<label class="form-label" for="login-user">User name:</label>
|
||||
<div class="form-input">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<div class="messages"></div>
|
||||
|
||||
<form method="post" class="form-wrapper">
|
||||
<form class="form-wrapper">
|
||||
<div class="form-row">
|
||||
<label class="form-label" for="registration-user">User name:</label>
|
||||
<div class="form-input">
|
||||
|
|
|
@ -14,11 +14,28 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<% _.each(userList, function(user) { %>
|
||||
<div class="user">
|
||||
User name: <a href="#/user/<%= user.name %>"><%= user.name %></a>
|
||||
</div>
|
||||
<% }); %>
|
||||
<ul class="users">
|
||||
<% _.each(userList, function(user) { %>
|
||||
<li class="user">
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<img src="/api/users/<%= user.name %>/avatar/80" alt="<%= user.name %>"/>
|
||||
</a>
|
||||
<div class="details">
|
||||
<h1>
|
||||
<a href="#/user/<%= user.name %>">
|
||||
<%= user.name %>
|
||||
</a>
|
||||
</h1>
|
||||
<div class="date-joined" title="<%= user.registrationTime %>">
|
||||
Joined: <%= formatRelativeTime(user.registrationTime) %>
|
||||
</div>
|
||||
<div class="date-seen">
|
||||
Last seen: <%= formatRelativeTime(user.lastLoginTime) %>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<% }); %>
|
||||
</ul>
|
||||
|
||||
<div class="pager"></div>
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,73 @@
|
|||
<div id="user-view">
|
||||
<div id="user-view" class="tab-wrapper">
|
||||
<div class="messages"></div>
|
||||
|
||||
<img src="/api/users/<%= user.name %>/avatar/50" alt="Avatar"/>
|
||||
<%= user.name %>
|
||||
<div class="top">
|
||||
<div class="side">
|
||||
<img src="/api/users/<%= user.name %>/avatar/100" alt="Avatar"/>
|
||||
<br/>
|
||||
<%= user.name %>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#/user/<%= user.name %>" data-tab="basic-info">Basic information</a>
|
||||
</li>
|
||||
|
||||
<% if (canChangeBrowsingSettings) { %>
|
||||
<li>
|
||||
<a href="#/user/<%= user.name %>/browsing-settings" data-tab="browsing-settings">Browsing settings</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (canChangeAccountSettings) { %>
|
||||
<li>
|
||||
<a href="#/user/<%= user.name %>/account-settings" data-tab="account-settings">Account settings</a>
|
||||
</li>
|
||||
<% } %>
|
||||
|
||||
<% if (canDeleteAccount) { %>
|
||||
<li>
|
||||
<a href="#/user/<%= user.name %>/account-removal" data-tab="account-removal">Account removal</a>
|
||||
</li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="tab basic-info" data-tab="basic-info">
|
||||
<h2>Basic information</h2>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>Registered:</td>
|
||||
<td><%= user.registrationTime %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Seen:</td>
|
||||
<td><%= user.lastLoginTime %></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% if (canChangeBrowsingSettings) { %>
|
||||
<h2>Browsing settings</h2>
|
||||
<div id="browsing-settings-target"></div>
|
||||
<div class="tab" data-tab="browsing-settings">
|
||||
<h2>Browsing settings</h2>
|
||||
<div id="browsing-settings-target"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (canChangeAccountSettings) { %>
|
||||
<h2>Account settings</h2>
|
||||
<div id="account-settings-target"></div>
|
||||
<div class="tab" data-tab="account-settings">
|
||||
<h2>Account settings</h2>
|
||||
<div id="account-settings-target"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (canDeleteAccount) { %>
|
||||
<h2>Account removal</h2>
|
||||
<div id="account-removal-target"></div>
|
||||
<div class="tab" data-tab="account-removal">
|
||||
<h2>Account removal</h2>
|
||||
<div id="account-removal-target"></div>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue