Closed #54 - added mass tag
- Moved tag forms to separate files - Tag forms got tag autocompletion
This commit is contained in:
parent
cf1b5837a7
commit
bc43883339
16 changed files with 246 additions and 56 deletions
|
@ -97,3 +97,4 @@ deleteComment.all=moderator
|
|||
listTags=anonymous
|
||||
mergeTags=moderator
|
||||
renameTags=moderator
|
||||
massTag=moderator
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6f606d107513424139b0070d944d4f14dcb12423
|
||||
Subproject commit dae26a24c48a5140175ef7d0843b6b762692b8cd
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
34
public_html/media/js/mass-tag.js
Normal file
34
public_html/media/js/mass-tag.js
Normal 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');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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}
|
||||
|
|
|
@ -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]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,4 +33,5 @@ class Privilege extends Enum
|
|||
const ListTags = 21;
|
||||
const MergeTags = 27;
|
||||
const RenameTags = 27;
|
||||
const MassTag = 29;
|
||||
}
|
||||
|
|
|
@ -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: ?>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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"> </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"> </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 ?>
|
||||
|
|
21
src/Views/tag-mass-tag.phtml
Normal file
21
src/Views/tag-mass-tag.phtml
Normal 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"> </label>
|
||||
<button type="submit">Tag!</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
21
src/Views/tag-merge.phtml
Normal file
21
src/Views/tag-merge.phtml
Normal 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"> </label>
|
||||
<button type="submit">Merge!</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
21
src/Views/tag-rename.phtml
Normal file
21
src/Views/tag-rename.phtml
Normal 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"> </label>
|
||||
<button type="submit">Rename!</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
Loading…
Reference in a new issue