Closed #54 - added mass tag

- Moved tag forms to separate files
- Tag forms got tag autocompletion
This commit is contained in:
Marcin Kurczewski 2013-10-29 09:04:42 +01:00
parent cf1b5837a7
commit bc43883339
16 changed files with 246 additions and 56 deletions

View file

@ -97,3 +97,4 @@ deleteComment.all=moderator
listTags=anonymous
mergeTags=moderator
renameTags=moderator
massTag=moderator

@ -1 +1 @@
Subproject commit 6f606d107513424139b0070d944d4f14dcb12423
Subproject commit dae26a24c48a5140175ef7d0843b6b762692b8cd

View file

@ -7,3 +7,21 @@
.posts {
margin: 0 auto;
}
.form-wrapper {
text-align: center;
}
.small-screen .form-wrapper {
width: 100%;
}
form.aligned {
width: 24em;
text-align: left;
margin: 0 auto;
}
form.aligned label.left {
width: 7em;
}
form h1 {
text-align: center;
}

View file

@ -5,6 +5,10 @@
position: relative;
display: inline-block;
}
.post .link {
color: black;
}
.post-type-youtube:after,
.post-type-flash:after {
position: absolute;
@ -29,6 +33,33 @@
}
.post .toggle-tag {
position: absolute;
z-index: 2;
width: 100px;
height: 30px;
background: whitesmoke;
opacity: .5;
border: 1px solid black;
margin: 60px 25px;
line-height: 30px;
}
.post .toggle-tag:hover {
opacity: 1;
}
.post.taggable.tagged .toggle-tag {
background-color: #0f0;
color: black;
}
.post.taggable:not(.tagged) .toggle-tag {
background-color: #f00;
color: white;
}
.post .link {
z-index: 1;
}
.post:focus,
.post:hover {
border: 1px solid firebrick;

View file

@ -21,6 +21,7 @@
.form-wrapper {
width: 50%;
max-width: 24em;
display: inline-block;
text-align: center;
}
@ -34,9 +35,6 @@ form.aligned {
form.aligned label.left {
width: 7em;
}
form.aligned input {
width: 24em;
}
form h1 {
text-align: center;
}

View file

@ -144,7 +144,9 @@ function extractLast(term)
$(function()
{
var searchInput = $('#top-nav .search input');
$('[data-autocomplete-url]').each(function()
{
var searchInput = $(this);
searchInput
// don't navigate away from the field on tab when selecting an item
.bind("keydown", function(event)
@ -179,6 +181,7 @@ $(function()
return false;
}
});
});
});
function getTagItOptions()

View file

@ -0,0 +1,34 @@
$(function()
{
$('.post a.toggle-tag').click(function(e)
{
if(e.isPropagationStopped())
return;
e.preventDefault();
e.stopPropagation();
var aDom = $(this);
if (aDom.hasClass('inactive'))
return;
aDom.addClass('inactive');
var url = $(this).attr('href') + '?json';
$.get(url, {submit: 1}, function(data)
{
if (data['success'])
{
aDom.removeClass('inactive');
aDom.parents('.post').toggleClass('tagged');
aDom.text(aDom.parents('.post').hasClass('tagged')
? aDom.attr('data-text-tagged')
: aDom.attr('data-text-untagged'));
}
else
{
alert(data['errorMessage']);
aDom.removeClass('inactive');
}
});
});
});

View file

@ -48,20 +48,28 @@ class PostController
/**
* @route /posts
* @route /posts/{page}
* @route /posts/{query}/
* @route /posts/{query}/{page}
* @route /{source}
* @route /{source}/{page}
* @route /{source}/{query}/
* @route /{source}/{query}/{page}
* @route /{source}/{additionalInfo}/{query}/
* @route /{source}/{additionalInfo}/{query}/{page}
* @validate source posts|mass-tag
* @validate page \d*
* @validate query [^\/]*
* @validate additionalInfo [^\/]*
*/
public function listAction($query = null, $page = 1)
public function listAction($query = null, $page = 1, $source = 'posts', $additionalInfo = null)
{
$this->context->stylesheets []= 'post-small.css';
$this->context->stylesheets []= 'post-list.css';
$this->context->stylesheets []= 'paginator.css';
if ($this->context->user->hasEnabledEndlessScrolling())
$this->context->scripts []= 'paginator-endless.js';
if ($source == 'mass-tag')
$this->context->scripts []= 'mass-tag.js';
$this->context->source = $source;
$this->context->additionalInfo = $additionalInfo;
//redirect requests in form of /posts/?query=... to canonical address
$formQuery = InputHelper::get('query');
@ -70,7 +78,7 @@ class PostController
$this->context->transport->searchQuery = $formQuery;
if (strpos($formQuery, '/') !== false)
throw new SimpleException('Search query contains invalid characters');
$url = \Chibi\UrlHelper::route('post', 'list', ['query' => urlencode($formQuery)]);
$url = \Chibi\UrlHelper::route('post', 'list', ['source' => $source, 'additionalInfo' => $additionalInfo, 'query' => urlencode($formQuery)]);
\Chibi\UrlHelper::forward($url);
return;
}
@ -81,6 +89,12 @@ class PostController
$this->context->subTitle = 'posts';
$this->context->transport->searchQuery = $query;
PrivilegesHelper::confirmWithException(Privilege::ListPosts);
if ($source == 'mass-tag')
{
PrivilegesHelper::confirmWithException(Privilege::MassTag);
$this->context->massTagTag = $additionalInfo;
$this->context->massTagQuery = $query;
}
$postCount = Model_Post::getEntityCount($query);
$pageCount = ceil($postCount / $postsPerPage);
@ -97,6 +111,37 @@ class PostController
/**
* @route /post/{id}/toggle-tag/{tag}
* @validate tag [^\/]*
*/
public function toggleTagAction($id, $tag)
{
$post = Model_Post::locate($id);
R::preload($post, ['uploader' => 'user']);
$this->context->transport->post = $post;
$tag = Model_Tag::validateTag($tag);
if (InputHelper::get('submit'))
{
PrivilegesHelper::confirmWithException(Privilege::MassTag);
$tags = array_map(function($x) { return $x->name; }, $post->sharedTag);
if (in_array($tag, $tags))
$tags = array_diff($tags, [$tag]);
else
$tags += [$tag];
$dbTags = Model_Tag::insertOrUpdate($tags);
$post->sharedTag = $dbTags;
R::store($post);
$this->context->transport->success = true;
}
}
/**
* @route /favorites
* @route /favorites/{page}

View file

@ -70,4 +70,19 @@ class TagController
$this->context->transport->success = true;
}
}
/**
* @route /mass-tag-redirect
*/
public function massTagRedirectAction()
{
PrivilegesHelper::confirmWithException(Privilege::MassTag);
if (InputHelper::get('submit'))
{
$suppliedQuery = InputHelper::get('query');
$suppliedTag = InputHelper::get('tag');
$suppliedTag = Model_Tag::validateTag($suppliedTag);
\Chibi\UrlHelper::forward(\Chibi\UrlHelper::route('post', 'list', ['source' => 'mass-tag', 'query' => urlencode($suppliedQuery), 'additionalInfo' => $suppliedTag]));
}
}
}

View file

@ -33,4 +33,5 @@ class Privilege extends Enum
const ListTags = 21;
const MergeTags = 27;
const RenameTags = 27;
const MassTag = 29;
}

View file

@ -1,3 +1,7 @@
<?php if (isset($this->context->source) and $this->context->source == 'mass-tag' and PrivilegesHelper::confirm(Privilege::MassTag)): ?>
<?php $this->renderFile('tag-mass-tag') ?>
<?php endif ?>
<?php if (empty($this->context->transport->posts)): ?>
<p class="alert alert-warning">No posts to show.</p>
<?php else: ?>

View file

@ -1,5 +1,18 @@
<div class="post post-type-<?php echo TextHelper::camelCaseToHumanCase(PostType::toString($this->context->post->type)) ?>">
<a href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->post->id]) ?>">
<?php $classNames = ['post', 'post-type-' . TextHelper::camelCaseToHumanCase(PostType::toString($this->context->post->type))] ?>
<?php if (isset($this->context->source) and $this->context->source == 'mass-tag'): ?>
<?php $classNames []= 'taggable' ?>
<?php if (in_array($this->context->additionalInfo, array_map(function($x) { return $x->name; }, $this->context->post->sharedTag))): ?>
<?php $classNames []= 'tagged' ?>
<?php endif ?>
<?php endif ?>
<div class="<?php echo implode(' ', $classNames) ?>">
<?php if (isset($this->context->source) and $this->context->source == 'mass-tag'): ?>
<a class="toggle-tag" href="<?php echo \Chibi\UrlHelper::route('post', 'toggle-tag', ['id' => $this->context->post->id, 'tag' => $this->context->additionalInfo]) ?>" data-text-tagged="Tagged" data-text-untagged="Untagged">
<?php echo in_array('tagged', $classNames) ? 'Tagged' : 'Untagged' ?>
</a>
<?php endif ?>
<a class="link" href="<?php echo \Chibi\UrlHelper::route('post', 'view', ['id' => $this->context->post->id]) ?>">
<img class="thumb" src="<?php echo \Chibi\UrlHelper::route('post', 'thumb', ['name' => $this->context->post->name]) ?>" alt="@<?php echo $this->context->post->id ?>"/>
</a>
<div class="info-bar">

View file

@ -12,49 +12,13 @@
</div>
<?php if (PrivilegesHelper::confirm(Privilege::MergeTags)): ?>
<div class="form-wrapper">
<form class="aligned" method="post" action="<?php echo \Chibi\UrlHelper::route('tag', 'merge') ?>">
<h1>merge tags</h1>
<div>
<label class="left" for="merge-source-tag">Source tag:</label>
<div class="input-wrapper"><input type="text" name="source-tag" id="merge-source-tag"></div>
</div>
<div>
<label class="left" for="merge-target-tag">Target tag:</label>
<div class="input-wrapper"><input type="text" name="target-tag" id="merge-target-tag"></div>
</div>
<input type="hidden" name="submit" value="1"/>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Merge!</button>
</div>
</form>
</div>
<?php $this->renderFile('tag-merge') ?>
<?php endif ?>
<?php if (PrivilegesHelper::confirm(Privilege::RenameTags)): ?>
<div class="form-wrapper">
<form class="aligned simple-action" method="post" action="<?php echo \Chibi\UrlHelper::route('tag', 'rename') ?>">
<h1>rename tags</h1>
<div>
<label class="left" for="rename-source-tag">Source tag:</label>
<div class="input-wrapper"><input type="text" name="source-tag" id="rename-source-tag"></div>
</div>
<div>
<label class="left" for="rename-target-tag">Target tag:</label>
<div class="input-wrapper"><input type="text" name="target-tag" id="rename-target-tag"></div>
</div>
<input type="hidden" name="submit" value="1"/>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Rename!</button>
</div>
</form>
</div>
<?php $this->renderFile('tag-rename') ?>
<?php endif ?>
<?php if (PrivilegesHelper::confirm(Privilege::MassTag)): ?>
<?php $this->renderFile('tag-mass-tag') ?>
<?php endif ?>

View file

@ -0,0 +1,21 @@
<div class="form-wrapper">
<form class="aligned" method="post" action="<?php echo \Chibi\UrlHelper::route('tag', 'mass-tag-redirect') ?>">
<h1>mass tag</h1>
<div>
<label class="left" for="mass-tag-query">Search query:</label>
<div class="input-wrapper"><input type="text" name="query" id="mass-tag-query" value="<?php echo isset($this->context->massTagQuery) ? $this->context->massTagQuery : '' ?>" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/></div>
</div>
<div>
<label class="left" for="mass-tag-tag">Tag:</label>
<div class="input-wrapper"><input type="text" name="tag" id="mass-tag-tag" value="<?php echo isset($this->context->massTagTag) ? $this->context->massTagTag : '' ?>" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/></div>
</div>
<input type="hidden" name="submit" value="1"/>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Tag!</button>
</div>
</form>
</div>

21
src/Views/tag-merge.phtml Normal file
View file

@ -0,0 +1,21 @@
<div class="form-wrapper">
<form class="aligned" method="post" action="<?php echo \Chibi\UrlHelper::route('tag', 'merge') ?>">
<h1>merge tags</h1>
<div>
<label class="left" for="merge-source-tag">Source tag:</label>
<div class="input-wrapper"><input type="text" name="source-tag" id="merge-source-tag" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/></div>
</div>
<div>
<label class="left" for="merge-target-tag">Target tag:</label>
<div class="input-wrapper"><input type="text" name="target-tag" id="merge-target-tag" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/></div>
</div>
<input type="hidden" name="submit" value="1"/>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Merge!</button>
</div>
</form>
</div>

View file

@ -0,0 +1,21 @@
<div class="form-wrapper">
<form class="aligned simple-action" method="post" action="<?php echo \Chibi\UrlHelper::route('tag', 'rename') ?>">
<h1>rename tags</h1>
<div>
<label class="left" for="rename-source-tag">Source tag:</label>
<div class="input-wrapper"><input type="text" name="source-tag" id="rename-source-tag" data-autocomplete-url="<?php echo \Chibi\UrlHelper::route('tag', 'list') ?>"/></div>
</div>
<div>
<label class="left" for="rename-target-tag">Target tag:</label>
<div class="input-wrapper"><input type="text" name="target-tag" id="rename-target-tag"/></div>
</div>
<input type="hidden" name="submit" value="1"/>
<div>
<label class="left">&nbsp;</label>
<button type="submit">Rename!</button>
</div>
</form>
</div>