Worked on #4, #1 and #2

Also:
- enhanced form stylesheets
- W3C validation
This commit is contained in:
Marcin Kurczewski 2013-10-15 00:41:04 +02:00
parent 79b51d31e5
commit 8fdc90bab7
16 changed files with 282 additions and 92 deletions

View file

@ -58,7 +58,17 @@ hidePost.own=moderator
hidePost.all=moderator
deletePost.own=moderator
deletePost.all=moderator
listUsers=registered
viewUser=registered
changeUserPassword.own=registered
changeUserPassword.all=admin
changeUserEmail.own=registered
changeUserEmail.all=admin
changeUserAccessRank=admin
changeUserName=moderator
acceptUserRegistration=moderator
banUser=admin
listComments=anonymous
listTags=anonymous

View file

@ -10,12 +10,10 @@ form.auth div {
display: table-row;
}
form.auth label {
form.auth label.left {
display: table-cell;
text-align: right;
float: left;
width: 144px;
margin: 5px 16px 0 0;
}
form.auth input {
@ -30,7 +28,6 @@ form.auth input {
form.auth button {
display: block;
margin: 0 auto;
}
form.auth p {

View file

@ -96,7 +96,6 @@ body {
float: right;
background: white;
margin: 0 0.25em;
padding: 0.2em 0.5em;
}
#top-nav li.search input {
border: 0;
@ -161,12 +160,57 @@ a:hover i[class*='icon-'] {
background-color: red;
}
input,
button {
font-family: inherit;
form.aligned input,
form.aligned button {
vertical-align: text-top;
}
form.aligned label {
text-align: right;
vertical-align: middle;
}
form.aligned label.left {
display: inline-block;
padding-right: 1em;
width: 5em;
min-height: 1em;
float: left;
}
form.aligned>div {
margin-bottom: 0.5em;
clear: left;
}
form.aligned label,
form.aligned input,
form.aligned select,
form.aligned button {
vertical-align: middle;
line-height: 20px;
}
form.aligned label,
form.aligned input,
form.aligned select {
padding: 5px;
}
form.aligned input[type=file] {
padding: 5px 0;
}
form.aligned input[type=radio],
form.aligned input[type=checkbox] {
vertical-align: text-top;
}
input:not([type=radio]):not([type=checkbox]) {
label {
display: inline-block;
}
label,
input,
select,
button {
font-family: inherit;
font-size: 11pt;
}
input:not([type=radio], [type=checkbox], [type=file]) {
border: 1px solid #ccc;
}
button {
@ -209,3 +253,13 @@ footer {
font-size: small;
color: silver;
}
.inactive {
opacity: .5;
}
hr {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAIElEQVQYlWNgQAPv3r37j4wHXBJdATY5BnyScAX4TAUAdfp5IbOdz/YAAAAASUVORK5CYII=');
border: 0;
height: 4px;
}

View file

@ -28,6 +28,6 @@
border-color: red;
}
.paginator li.inactive a {
.paginator li.disabled a {
color: gray;
}

View file

@ -9,12 +9,12 @@ embed {
max-width: 100%;
}
.tags ul {
#sidebar .tags ul {
list-style-type: none;
margin: 0 0 0 1em;
padding: 0;
}
.tags li .count {
#sidebar .tags li .count {
padding-left: 0.5em;
color: silver;
}
@ -28,10 +28,10 @@ nav .left {
nav .right {
float: right;
}
nav a.inactive {
nav a.disabled {
color: silver;
}
nav a.inactive i[class*='icon-'] {
nav a.disabled i[class*='icon-'] {
background-color: silver;
}
@ -94,10 +94,6 @@ i.icon-dl {
margin: 2px;
}
.inactive {
opacity: .5;
}
form.edit {
display: none;
padding: 0.5em 1em;
@ -106,26 +102,9 @@ form.edit {
padding-bottom: 0;
margin: 1em 0;
}
form.edit>div {
margin-bottom: 0.5em;
}
form.edit input[type=checkbox],
form.edit label {
vertical-align: middle;
line-height: 33px;
}
form.edit label.left {
display: inline-block;
width: 5em;
float: left;
}
form.edit .safety label:not(.left) {
margin-right: 0.75em;
}
form.edit>div {
clear: left;
}
ul.tagit {
display: block;
vertical-align: middle;

View file

@ -46,10 +46,6 @@
display: none;
}
.inactive {
opacity: .5;
}
.post {
margin-bottom: 4em;
}

View file

@ -22,12 +22,27 @@
margin-bottom: -1px;
}
.tabs li.active a {
border: 1px solid #eee;
border-bottom: 1px solid white;
}
.tabs li.inactive a {
.tabs li a {
border: 1px solid white;
border-bottom: 1px solid #eee;
color: silver;
}
.tabs li.selected a {
border: 1px solid #eee;
border-bottom: 1px solid white;
color: inherit;
}
.avatar-wrapper {
text-align: center;
}
.options ul {
list-style-type: none;
margin: 0;
padding: 0;
}
form.aligned label.left {
width: 10em;
}

View file

@ -7,7 +7,7 @@ function scrolled()
var pageDone = $(document).data('page-done');
if (pageNext == null)
{
pageNext = $('.paginator .next:not(.inactive) a').attr('href');
pageNext = $('.paginator .next:not(.disabled) a').attr('href');
}
if (pageNext != null && pageNext != pageDone)
{
@ -15,7 +15,7 @@ function scrolled()
$.get(pageNext, [], function(response)
{
var dom = $(response);
var nextPage = dom.find('.paginator .next:not(.inactive) a').attr('href');
var nextPage = dom.find('.paginator .next:not(.disabled) a').attr('href');
$(document).data('page-next', nextPage);
$('.paginator-content').append($(response).find('.paginator-content').children().fadeIn('slow'));
scrolled();

View file

@ -22,6 +22,24 @@ class UserController
/**
* @route /user/{name}/edit
* @validate name [^\/]+
*/
public function editAction($name)
{
$this->context->viewName = 'user-view';
$this->context->stylesheets []= 'user-view.css';
$this->context->subTitle = $name;
PrivilegesHelper::confirmWithException($this->context->user, Privilege::ViewUser);
$user = self::locateUser($name);
$this->context->transport->user = $user;
$this->context->transport->tab = 'edit';
}
/**
* @route /user/{name}
* @route /user/{name}/{tab}/{page}

View file

@ -5,7 +5,7 @@ class Model_User extends RedBean_SimpleModel
{
$subject = !empty($this->email)
? $this->email
: $this->name;
: $this->pass_salt . $this->name;
$hash = md5(strtolower(trim($subject)));
$url = 'http://www.gravatar.com/avatar/' . $hash . '?s=' . $size . '&d=retro';
return $url;

View file

@ -14,7 +14,13 @@ class Privilege extends Enum
const ListUsers = 11;
const ViewUser = 12;
const BanUser = 13;
const AcceptUserRegistration = 14;
const ChangeUserPassword = 15;
const ChangeUserAccessRank = 16;
const ChangeUserEmail = 17;
const ChangeUserName = 18;
const ListComments = 13;
const ListTags = 14;
const ListComments = 19;
const ListTags = 20;
}

View file

@ -1,16 +1,16 @@
<form action="<?php echo \Chibi\UrlHelper::route('auth', 'login') ?>" class="auth" method="post">
<form action="<?php echo \Chibi\UrlHelper::route('auth', 'login') ?>" class="auth aligned" method="post">
<div>
<p>If you don't have an account yet,<br/><a href="<?php echo \Chibi\UrlHelper::route('auth', 'register'); ?>">click here</a> to create a new one.</p>
</div>
<div>
<label for="user">User name:</label>
<label class="left" for="user">User name:</label>
<input id="user" name="user"/>
</div>
<div>
<label for="pass">Password:</label>
<label class="left" for="pass">Password:</label>
<input type="password" id="pass" name="pass"/>
</div>
@ -19,6 +19,7 @@
<?php endif ?>
<div>
<label class="left"></label>
<button type="submit">Log in</button>
</div>
</form>

View file

@ -9,33 +9,33 @@
<p>Your registration must be confirmed by staff.</p>
<?php endif ?>
<?php else: ?>
<form action="<?php echo \Chibi\UrlHelper::route('auth', 'register') ?>" class="auth" method="post">
<form action="<?php echo \Chibi\UrlHelper::route('auth', 'register') ?>" class="auth aligned" method="post">
<div>
<p>Registered users can view more content,<br/>upload files and add posts to favorites.</p>
</div>
<div>
<label for="user">User name:</label>
<input id="user" name="user" value="<?php echo $this->context->suppliedUser ?>"/ placeholder="e.g. darth_vader" autocomplete="off">
<label class="left" for="user">User name:</label>
<input id="user" name="user" value="<?php echo $this->context->suppliedUser ?>" placeholder="e.g. darth_vader" autocomplete="off"/>
</div>
<div>
<label for="pass">Password:</label>
<input type="password" id="pass" name="pass1" value="<?php echo $this->context->suppliedPass1 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>"/ autocomplete="off">
<label class="left" for="pass1">Password:</label>
<input type="password" id="pass1" name="pass1" value="<?php echo $this->context->suppliedPass1 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
</div>
<div>
<label for="pass">Password (repeat):</label>
<input type="password" id="pass" name="pass2" value="<?php echo $this->context->suppliedPass2 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>"/ autocomplete="off">
<label class="left" for="pass2">Password (repeat):</label>
<input type="password" id="pass2" name="pass2" value="<?php echo $this->context->suppliedPass2 ?>" placeholder="e.g. <?php echo str_repeat('&#x25cf;', 8) ?>" autocomplete="off"/>
</div>
<div>
<label for="email">E-mail address<?php if ($this->context->transport->emailActivation) echo ' (required)' ?>:</label>
<input id="email" name="email" value="<?php echo $this->context->suppliedEmail ?>" placeholder="e.g. vader@empire.gov"/ autocomplete="off">
<label class="left" for="email">E-mail address<?php if ($this->context->transport->emailActivation) echo ' (required)' ?>:</label>
<input id="email" name="email" value="<?php echo $this->context->suppliedEmail ?>" placeholder="e.g. vader@empire.gov" autocomplete="off"/>
</div>
<div>
<p id="email-info" name="email-info">Your e-mail will be used to show your <a href="http://gravatar.com/">Gravatar</a>.<br/>Leave blank for random Gravatar.</p>
<p id="email-info">Your e-mail will be used to show your <a href="http://gravatar.com/">Gravatar</a>.<br/>Leave blank for random Gravatar.</p>
</div>
<?php if (isset($this->context->transport->errorMessage)): ?>
@ -45,6 +45,7 @@
<?php endif ?>
<div>
<label class="left"></label>
<button type="submit">Register</button>
</div>
</form>

View file

@ -48,7 +48,7 @@ if (!function_exists('pageUrl'))
<?php if ($this->context->transport->page > 1): ?>
<li class="prev">
<?php else: ?>
<li class="prev inactive">
<li class="prev disabled">
<?php endif ?>
<a href="<?php echo pageUrl($this->context->transport->page - 1) ?>">
&laquo;
@ -70,7 +70,7 @@ if (!function_exists('pageUrl'))
<?php if ($this->context->transport->page < $this->context->transport->pageCount): ?>
<li class="next">
<?php else: ?>
<li class="next inactive">
<li class="next disabled">
<?php endif ?>
<a href="<?php echo pageUrl($this->context->transport->page + 1) ?>">
&raquo;

View file

@ -4,7 +4,7 @@
<?php if ($this->context->transport->nextPostId): ?>
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->transport->nextPostId]) ?>">
<?php else: ?>
<a class="inactive">
<a class="disabled">
<?php endif ?>
<i class="icon-next"></i>
<span>next post</span>
@ -15,7 +15,7 @@
<?php if ($this->context->transport->prevPostId): ?>
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->transport->prevPostId]) ?>">
<?php else: ?>
<a class="inactive">
<a class="disabled">
<?php endif ?>
<span>prev post</span>
<i class="icon-prev"></i>
@ -73,7 +73,7 @@
<?php endif ?>
<div class="permalink">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" alt="<?php echo $this->context->transport->post->name ?>">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" title="Download">
<i class="icon-dl"></i>
<span class="ext">
<?php echo strtoupper(substr($this->context->transport->post->orig_name, strrpos($this->context->transport->post->orig_name, '.') + 1)) ?>
@ -94,8 +94,8 @@
<ul>
<?php foreach ($this->context->transport->post->via('favoritee')->sharedUser as $user): ?>
<li>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $user->name]) ?>">
<img src="<?php echo $user->getAvatarUrl() ?>" alt="<?php echo $user->name ?>">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $user->name]) ?>" title="<?php echo $user->name ?>">
<img src="<?php echo htmlspecialchars($user->getAvatarUrl()) ?>" alt="<?php echo $user->name ?>">
</a>
</li>
<?php endforeach ?>
@ -189,7 +189,7 @@
</div>
<?php if ($canEditAnything): ?>
<form action="<?php echo \Chibi\UrlHelper::route('post', 'edit', ['id' => $this->context->transport->post->id]) ?>" method="post" enctype="multiplart/form-data" class="edit">
<form action="<?php echo \Chibi\UrlHelper::route('post', 'edit', ['id' => $this->context->transport->post->id]) ?>" method="post" enctype="multipart/form-data" class="edit aligned">
<h1>edit post</h1>
<?php if ($editPostPrivileges[Privilege::EditPostSafety]): ?>
<div class="safety">

View file

@ -1,12 +1,14 @@
<div id="sidebar">
<div class="avatar-wrapper">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->user->name]) ?>">
<img src="<?php echo $this->context->transport->user->getAvatarUrl(140) ?>" alt="<?php echo $this->context->transport->user->name ?>">
<img src="<?php echo htmlspecialchars($this->context->transport->user->getAvatarUrl(140)) ?>" alt="<?php echo $this->context->transport->user->name ?>">
</a>
<h1><?php echo $this->context->transport->user->name ?></h1>
</div>
<div class="sidebar-unit details">
<h1>details</h1>
<div class="join-date">
<span class="key">Joined:</span>
<span class="value"><?php echo date('Y-m-d', $this->context->transport->user->join_date) ?></span>
@ -17,6 +19,44 @@
<span class="value"><?php echo strtolower(AccessRank::toString($this->context->transport->user->access_rank)) ?></span>
</div>
</div>
<div class="sidebar-unit options">
<h1>options</h1>
<ul>
<?php
$secondary = $this->context->transport->user->id == $this->context->user->id ? 'own' : 'all';
$userModificationPrivileges = [
Privilege::ChangeUserName,
Privilege::ChangeUserEmail,
Privilege::ChangeUserPassword,
Privilege::ChangeUserAccessRank,
];
$userModificationPrivileges = array_fill_keys($userModificationPrivileges, false);
foreach (array_keys($userModificationPrivileges) as $privilege)
{
if (PrivilegesHelper::confirm($this->context->user, $privilege, $secondary))
$userModificationPrivileges[$privilege] = true;
}
$canModifyAnything = count(array_filter($userModificationPrivileges)) > 0;
?>
<?php if ($canModifyAnything): ?>
<li class="edit">
<a href="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name, 'tab' => 'edit']) ?>">
Edit account settings
</a>
</li>
<?php endif ?>
</ul>
<script type="text/javascript">
if (!$('.options ul li').length)
$('.options').hide();
</script>
</div>
</div>
<div id="inner-content">
@ -24,9 +64,9 @@
<nav>
<ul>
<?php if ($this->context->transport->tab == 'favs'): ?>
<li class="active">
<li class="selected favs">
<?php else: ?>
<li class="inactive">
<li class="favs">
<?php endif ?>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->user->name, 'tab' => 'favs', 'page' => 1]) ?>">
Favs
@ -34,34 +74,107 @@
</li>
<?php if ($this->context->transport->tab == 'uploads'): ?>
<li class="active">
<li class="selected uploads">
<?php else: ?>
<li class="inactive">
<li class="uploads">
<?php endif ?>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'view', ['name' => $this->context->transport->user->name, 'tab' => 'uploads', 'page' => 1]) ?>">
Uploads
</a>
</li>
<?php if ($canModifyAnything): ?>
<?php if ($this->context->transport->tab == 'edit'): ?>
<li class="selected edit">
<?php else: ?>
<li class="edit">
<?php endif ?>
<a href="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['name' => $this->context->transport->user->name, 'tab' => 'edit']) ?>">
Account settings
</a>
</li>
<?php endif ?>
</ul>
</nav>
</div>
<?php
/* heh, what a stupid hack */
function pageUrl($page)
{
$context = \Chibi\Registry::getContext();
$controller = $context->route->simpleControllerName;
$action = $context->route->simpleActionName;
$page = max(1, $page);
$page = min($context->transport->pageCount, $page);
$params = [];
$params['page'] = $page;
$params['tab'] = $context->transport->tab;
$params['name'] = $context->transport->user->name;
return \Chibi\UrlHelper::route($controller, $action, $params);
}
?>
<?php if (isset($this->context->transport->posts)): ?>
<?php
/* heh, what a stupid hack */
function pageUrl($page)
{
$context = \Chibi\Registry::getContext();
$controller = $context->route->simpleControllerName;
$action = $context->route->simpleActionName;
$page = max(1, $page);
$page = min($context->transport->pageCount, $page);
$params = [];
$params['page'] = $page;
$params['tab'] = $context->transport->tab;
$params['name'] = $context->transport->user->name;
return \Chibi\UrlHelper::route($controller, $action, $params);
}
$this->renderFile('post-list')
?>
<?php endif ?>
<?php if ($this->context->transport->tab == 'edit'): ?>
<form action="<?php echo \Chibi\UrlHelper::route('user', 'edit', ['id' => $this->context->transport->user->id]) ?>" method="post" class="edit aligned" autocomplete="off">
<?php if ($this->context->user->id == $this->context->transport->user->id): ?>
<div class="old-password">
<label class="left" for="old-password">Old password:</label>
<input type="password" name="old-password" id="old-password" placeholder="Old password"/>
</div>
<hr>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserName, $secondary)): ?>
<div class="nickname">
<label class="left" for="name">Name:</label>
<input type="text" name="name" id="name" placeholder="New name&hellip;"/>
</div>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserEmail, $secondary)): ?>
<div class="email">
<label class="left" for="name">E-mail:</label>
<input type="text" name="email" id="email" placeholder="New e-mail&hellip;"/>
</div>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserPassword, $secondary)): ?>
<div class="password1">
<label class="left" for="password1">New password:</label>
<input type="password" name="password1" id="password1" placeholder="New password&hellip;"/>
</div>
<div class="password2">
<label class="left" for="password2"></label>
<input type="password" name="password2" id="password2" placeholder="New password&hellip; (repeat)"/>
</div>
<?php endif ?>
<?php if (PrivilegesHelper::confirm($this->context->user, Privilege::ChangeUserAccessRank, $secondary)): ?>
<div class="access-rank">
<label class="left" for="access-rank">Access rank:</label>
<select name="access-rank" id="access-rank">
<?php foreach (AccessRank::getAll() as $rank): ?>
<?php if ($rank == $this->context->transport->user->access_rank): ?>
<option value="<?php echo $rank ?>" selected="selected">
<?php else: ?>
<option value="<?php echo $rank ?>">
<?php endif ?>
<?php echo AccessRank::toString($rank) ?>
</option>
<?php endforeach ?>
</select>
</div>
<?php endif ?>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Submit</button>
</div>
</form>
<?php endif ?>
<?php $this->renderFile('post-list') ?>
</div>