This commit is contained in:
Marcin Kurczewski 2013-10-07 00:44:17 +02:00
parent 885b2cf31f
commit 3fd34db37c
15 changed files with 454 additions and 5 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
local.ini
db.sqlite
db.sqlite-journal
public_html/media/js/jquery.tagit.js
public_html/media/css/jquery.tagit.css

View file

@ -4,6 +4,7 @@ prettyPrint=1
[main]
dbPath=./db.sqlite
filesPath=./files/
title=szurubooru
[registration]

2
files/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*
!.gitignore

11
init.php Normal file
View file

@ -0,0 +1,11 @@
<?php
function download($source, $destination)
{
$content = file_get_contents($source);
if (substr($destination, -1, 1) == '/')
$destination .= basename($source);
file_put_contents($destination, $content);
}
download('http://raw.github.com/aehlke/tag-it/master/css/jquery.tagit.css', './public_html/media/css/jquery.tagit.css');
download('http://raw.github.com/aehlke/tag-it/master/js/tag-it.min.js', './public_html/media/js/jquery.tagit.js');

View file

@ -3,7 +3,7 @@ body {
color: black;
margin: 0;
padding: 0;
font-family: sans-serif;
font-family: 'Droid Sans', sans-serif;
font-size: 12pt;
}
@ -77,3 +77,19 @@ nav li.search input {
.clear {
clear: both;
}
#sidebar {
float: left;
width: 25%;
margin-right: 1em;
}
#sidebar h1 {
margin-top: 0;
text-align: center;
font-weight: normal;
}
#inner-content {
overflow: hidden;
}

View file

@ -0,0 +1,110 @@
.items .item {
width: 30%;
float: left;
}
.items .sep {
width: 3%;
float: left;
}
#file-handler-wrapper {
display: table;
width: 100%;
}
#file-handler {
cursor: pointer;
font-size: 150%;
text-align: center;
vertical-align: middle;
height: 200px;
width: 100%;
display: table-cell;
border: 3px dashed #eee;
}
#file-handler.active {
background: #eee;
border-color: firebrick;
}
.post .thumbnail {
width: 100px;
height: 100px;
line-height: 100px;
background-image: url('../img/thumb-unavailable.png');
border: 1px solid black;
vertical-align: middle;
text-align: center;
display: block;
float: left;
margin-right: 1em;
}
#post-template {
display: none;
}
.post {
margin-bottom: 4em;
}
.post .remove-trigger {
cursor: pointer;
float: right;
color: rgba(128, 0, 0, 0.25);
vertical-align: middle;
}
.post .remove-trigger span {
margin-left: 0.25em;
vertical-align: middle;
color: rgba(128, 0, 0, 1);
font-size: 130%;
}
.post label {
line-height: 33px;
}
.post label.left {
display: inline-block;
width: 4em;
}
.post .safety label:not(.left) {
margin-right: 0.75em;
}
.post .file-name strong {
overflow: hidden;
text-overflow: ellipsis;
max-width: 50%;
display: inline-block;
vertical-align: middle;
}
.safety-sfw {
color: #63ca63;
}
.safety-sketchy {
color: #f4c657;
}
.safety-nsfw {
color: #df4b0d;
}
ul.tagit {
display: inline-block;
vertical-align: middle;
margin: 0;
font-size: 1em;
}
.submit-wrapper {
text-align: center;
}
input.submit {
margin: 0 auto;
font-size: 115%;
padding: 0.2em 0.7em;
color: white;
background: cornflowerblue;
border: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

View file

@ -0,0 +1,138 @@
$(function()
{
var handler = $('#file-handler');
var tags = []; //todo: retrieve tags
$('#upload-step2').hide();
handler.on('dragenter', function(e)
{
$(this).addClass('active');
});
handler.on('dragleave', function(e)
{
$(this).removeClass('active');
});
handler.on('dragover', function(e)
{
e.preventDefault();
});
handler.on('drop', function(e)
{
e.preventDefault();
handleFiles(e.originalEvent.dataTransfer.files);
$(this).trigger('dragleave');
});
handler.on('click', function(e)
{
$(':file').show().focus().trigger('click').hide();
});
$(':file').change(function(e)
{
handleFiles(this.files);
});
$('.post .remove-trigger').on('click', function()
{
$(this).parents('.post').slideUp(function()
{
$(this).remove();
});
});
$('#upload-step2 form').submit(function(e)
{
var url = $(this).attr('action') + '?json';
e.preventDefault();
var posts = $('.post', $(this));
if (posts.length == 0)
{
alert('No posts to upload!');
return;
}
posts.each(function()
{
var postDom = $(this);
var file = postDom.data('file');
var tags = postDom.find('[name=tags]').val();
var safety = postDom.find('[name=safety]').val();
var fd = new FormData();
fd.append('file', file);
fd.append('tags', tags);
fd.append('safety', safety);
var ajax =
{
url: url,
data: fd,
processData: false,
contentType: false,
type: 'POST',
success: function(data)
{
//todo: do this nice
if (data['success'])
{
postDom.slideUp();
//alert(file.name + ': success!');
}
else
{
alert(data['errorMessage']);
}
}
};
$.ajax(ajax);
});
});
function handleFiles(files)
{
$('#upload-step1').fadeOut(function()
{
for (var i = 0; i < files.length; i ++)
{
var file = files[i];
var postDom = $('#post-template').clone(true);
postDom.removeAttr('id');
postDom.data('file', file);
$('.file-name strong', postDom).text(file.name);
$('.tags input', postDom).tagit({caseSensitive: true, availableTags: tags, placeholderText: $('.tags input').attr('placeholder')});
$('.posts').append(postDom);
if (!file.type.match('image.*'))
{
continue;
}
var reader = new FileReader();
reader.onload = (function(theFile)
{
return function(e)
{
var img = postDom.find('img')
/*img.css('max-width', img.css('width'));
img.css('max-height', img.css('height'));
img.css('width', 'auto');
img.css('height', 'auto');*/
img.css('background-image', 'none');
img.attr('src', e.target.result);
};
})(file);
reader.readAsDataURL(file);
}
$('#upload-step2').fadeIn(function()
{
});
});
}
});

View file

@ -29,6 +29,7 @@ class Bootstrap
$this->context->title = $this->config->main->title;
$this->context->stylesheets = ['core.css'];
$this->context->scripts = [];
$this->context->layoutName = isset($_GET['json'])
? 'layout-json'

View file

@ -1,6 +1,13 @@
<?php
class PostController
{
public function workWrapper($callback)
{
$this->context->stylesheets []= 'jquery.tagit.css';
$this->context->scripts []= 'jquery.tagit.js';
$callback();
}
/**
* @route /posts
* @route /posts/{query}
@ -27,8 +34,78 @@ class PostController
*/
public function uploadAction()
{
$this->context->stylesheets []= 'upload.css';
$this->context->scripts []= 'upload.js';
$this->context->subTitle = 'upload';
throw new Exception('Not implemented');
PrivilegesHelper::confirmWithException($this->context->user, Privilege::UploadPost);
if (isset($_FILES['file']))
{
$suppliedSafety = intval(InputHelper::get('safety'));
if (!in_array($suppliedSafety, PostSafety::getAll()))
throw new SimpleException('Invalid safety type "' . $suppliedSafety . '"');
$suppliedTags = InputHelper::get('tags');
$suppliedTags = preg_split('/[,;\s+]/', $suppliedTags);
$suppliedTags = array_filter($suppliedTags);
$suppliedTags = array_unique($suppliedTags);
foreach ($suppliedTags as $tag)
if (!preg_match('/^\w+$/i', $tag))
throw new SimpleException('Invalid tag "' . $tag . '"');
$suppliedFile = $_FILES['file'];
switch ($suppliedFile['type'])
{
case 'image/gif':
case 'image/png':
case 'image/jpeg':
$postType = PostType::Image;
break;
case 'application/x-shockwave-flash':
$postType = PostType::Flash;
break;
default:
throw new SimpleException('Invalid file type "' . $suppliedFile['type'] . '"');
}
//todo: find out duplicate files
do
{
$name = md5(mt_rand() . uniqid());
$path = $this->config->main->filesPath . DIRECTORY_SEPARATOR . $name;
}
while (file_exists($path));
$dbTags = [];
foreach ($suppliedTags as $tag)
{
$dbTag = R::findOne('tag', 'name = ?', [$tag]);
if (!$dbTag)
{
$dbTag = R::dispense('tag');
$dbTag->name = $tag;
R::store($dbTag);
}
$dbTags []= $dbTag;
}
$dbPost = R::dispense('post');
$dbPost->type = $postType;
$dbPost->name = $name;
$dbPost->mimeType = $suppliedFile['type'];
$dbPost->safety = $suppliedSafety;
$dbPost->sharedTag = $dbTags;
move_uploaded_file($suppliedFile['tmp_name'], $path);
R::store($dbPost);
//todo: generate thumbnail
$this->context->transport->success = true;
}
}
/**

12
src/Models/PostSafety.php Normal file
View file

@ -0,0 +1,12 @@
<?php
class PostSafety
{
const Safe = 1;
const Sketchy = 2;
const Unsafe = 3;
public static function getAll()
{
return [self::Safe, self::Sketchy, self::Unsafe];
}
}

6
src/Models/PostType.php Normal file
View file

@ -0,0 +1,6 @@
<?php
class PostType
{
const Image = 1;
const Flash = 2;
}

View file

@ -10,7 +10,13 @@
<?php foreach ($this->context->stylesheets as $name): ?>
<link rel="stylesheet" type="text/css" href="<?php echo \Chibi\UrlHelper::absoluteUrl('/media/css/' . $name) ?>"/>
<?php endforeach ?>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans:400,700">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/flick/jquery-ui.css">
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/jquery-ui.min.js"></script>
<?php foreach ($this->context->scripts as $name): ?>
<script type="text/javascript" src="<?php echo \Chibi\UrlHelper::absoluteUrl('/media/js/' . $name) ?>"></script>
<?php endforeach ?>
</head>
<body>

View file

@ -0,0 +1,67 @@
<?php if ($this->context->transport->success === true): ?>
<p>Post created!</p>
<?php elseif (isset($this->context->transport->errorMessage)): ?>
<p class="alert alert-error"><?php echo $this->context->transport->errorMessage ?></p>
<?php else: ?>
<div id="sidebar">
<h1>file upload</h1>
<p>Use tags to describe uploaded images. Try to specify characters, their look and shows they are from.</p>
<p>Set proper visibility setting if the image isn&rsquo;t safe for work or you&rsquo;re not sure it&rsquo;s 100% <span class="safety-sfw">safe</span>.</p>
<p>Only registered users can view <span class="safety-sketchy">sketchy</span> or <span class="safety-nsfw">NSFW</span> content.</p>
<p>Click submit when you&rsquo;re done.</p>
</div>
<div id="inner-content">
<div id="upload-step1">
<input type=file multiple style="display: none"/>
<div id="file-handler-wrapper">
<div id="file-handler">
Drop files here!<br>
Or just click on this box.
</div>
</div>
<div class="clear"></div>
</div>
<div id="upload-step2">
<form action="<?php echo \Chibi\UrlHelper::route('post', 'upload') ?>" method="post">
<div class="posts">
</div>
<div class="submit-wrapper">
<input type="submit" value="Submit" class="submit btn"/>
</div>
</form>
</div>
<div id="post-template" class="post">
<a class="remove-trigger">
remove <span>&times;</span>
</a>
<img class="thumbnail" src="<?php echo \Chibi\UrlHelper::absoluteUrl('/media/img/pixel.gif') ?>" alt="Thumbnail"/>
<div>
<div class="file-name">
<label class="left">File:</label>
<strong>filename.jpg</strong>
</div>
<div class="safety">
<label class="left">Safety:</label>
<label><input type="radio" name="safety" value="<?php echo PostSafety::Safe ?>" checked="checked"/> Safe for work</label>
<label><input type="radio" name="safety" value="<?php echo PostSafety::Sketchy ?>"/> Sketchy</label>
<label><input type="radio" name="safety" value="<?php echo PostSafety::Unsafe ?>"/> Not safe for work</label>
</div>
<div class="tags">
<label class="left">Tags:</label>
<input type="text" name="tags" placeholder="enter some tags&hellip;"/>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<?php endif ?>