diff --git a/cpanfile b/cpanfile
index 265bb40..93b7cf7 100644
--- a/cpanfile
+++ b/cpanfile
@@ -1,4 +1,4 @@
-requires 'Mojolicious';
+requires 'Mojolicious', '>= 7.88';
requires 'Mojolicious::Plugin::Authentication';
requires 'Imager';
requires 'File::Basename';
diff --git a/fotostore.pl b/fotostore.pl
index e2c7abe..96da165 100755
--- a/fotostore.pl
+++ b/fotostore.pl
@@ -4,11 +4,14 @@ use warnings;
use lib 'lib';
use Mojolicious::Lite; # app, get, post is exported.
+use Mojo::Promise;
+use Mojo::IOLoop;
-use File::Basename 'basename';
+use File::Basename qw/basename fileparse/;
use File::Path 'mkpath';
use File::Spec 'catfile';
use Cwd;
+use POSIX;
use Imager;
use DBI;
@@ -43,6 +46,8 @@ my $sha = Digest::SHA->new('sha256');
# Directory to save image files
my $IMAGE_DIR = File::Spec->catfile( getcwd(), 'public', $IMAGE_BASE );
+my $log = Mojo::Log->new();
+
plugin 'authentication', {
autoload_user => 1,
load_user => sub {
@@ -92,10 +97,10 @@ get '/register' => ( authenticated => 0 ) => sub {
post '/register' => ( authenticated => 0 ) => sub {
my $self = shift;
- my $username = $self->req->param('username');
- my $password = $self->req->param('password');
- my $fullname = $self->req->param('fullname');
- my $invite = $self->req->param('invite');
+ my $username = $self->req->param('username') || "";
+ my $password = $self->req->param('password') || "";
+ my $fullname = $self->req->param('fullname') || "";
+ my $invite = $self->req->param('invite') || "";
if ( $invite eq $config->{'invite_code'} ) {
@@ -141,10 +146,21 @@ get '/' => sub {
get '/get_images' => ( authenticated => 1 ) => sub {
my $self = shift;
+ #Getting current user
my $current_user = $self->current_user;
my $user_id = $current_user->{'user_id'};
- my $files_list = $db->get_files( $current_user->{'user_id'}, 20 );
+ #Getting images list with paging
+ my $page = $self->param('page') || 1;
+ my $items = $self->param('per-page') || 20;
+
+ if (($page !~ /^\d+$/) || ($page <= 1)) { $page = 1}
+ if (($items !~ /^\d+$/) || ($items <= 0)) { $items = 20}
+
+ # process images list
+ my $req_result = $db->get_files( $current_user->{'user_id'}, $items , $page);
+ my $files_list = $req_result->{'images_list'};
+ my $pages_count = ceil($req_result->{'total_rows'}/$items);
my $thumbs_dir =
File::Spec->catfile( $IMAGE_DIR, $current_user->{'user_id'},
@@ -157,6 +173,7 @@ get '/get_images' => ( authenticated => 1 ) => sub {
for my $img_item (@$files_list) {
my $file = $img_item->{'file_name'};
my $img_hash = {};
+ $img_hash->{'id'} = $img_item->{'file_id'};
$img_hash->{'filename'} = $img_item->{'original_filename'};
$img_hash->{'original_url'} =
File::Spec->catfile( '/', $IMAGE_BASE, $current_user->{'user_id'},
@@ -185,10 +202,14 @@ get '/get_images' => ( authenticated => 1 ) => sub {
$img_hash->{'scales'} = \@scaled;
push( @$images, $img_hash );
+
+
}
+ my $reply_data = { current_page => $page, items_per_page => $items, pages_count => $pages_count, images_list => $images };
+
# Render
- return $self->render( json => $images );
+ return $self->render( json => $reply_data );
};
# Upload image file
@@ -201,7 +222,6 @@ post '/upload' => ( authenticated => 1 ) => sub {
my $user = $self->current_user();
my $user_id = $user->{'user_id'};
- $self->app->log->debug( "user:" . Dumper($user) );
# Not upload
unless ($image) {
@@ -213,7 +233,11 @@ post '/upload' => ( authenticated => 1 ) => sub {
# Check file type
my $image_type = $image->headers->content_type;
- my %valid_types = map { $_ => 1 } qw(image/gif image/jpeg image/png);
+ my %valid_types = (
+ 'image/gif' => 'gif',
+ 'image/jpeg' => 'jpg',
+ 'image/png' => 'png'
+ );
# Content type is wrong
unless ( $valid_types{$image_type} ) {
@@ -223,13 +247,7 @@ post '/upload' => ( authenticated => 1 ) => sub {
);
}
- # Extention
- my $exts = {
- 'image/gif' => 'gif',
- 'image/jpeg' => 'jpg',
- 'image/png' => 'png'
- };
- my $ext = $exts->{$image_type};
+ my $ext = $valid_types{$image_type};
# Image file
my $filename = sprintf( '%s.%s', create_hash( $image->slurp() ), $ext );
@@ -239,58 +257,24 @@ post '/upload' => ( authenticated => 1 ) => sub {
# Save to file
$image->move_to($image_file);
- my $imager = Imager->new();
- $imager->read( file => $image_file ) or die $imager->errstr;
-
- #http://sylvana.net/jpegcrop/exif_orientation.html
- #http://myjaphoo.de/docs/exifidentifiers.html
- my $rotation_angle = $imager->tags( name => "exif_orientation" ) || 1;
- $self->app->log->info(
- "Rotation angle [" . $rotation_angle . "] [" . $image->filename . "]" );
-
- if ( $rotation_angle == 3 ) {
- $imager = $imager->rotate( degrees => 180 );
- }
- elsif ( $rotation_angle == 6 ) {
- $imager = $imager->rotate( degrees => 90 );
- }
-
- my $original_width = $imager->getwidth();
-
- for my $scale (@scale_width) {
-
- #Skip sizes which more than original image
- if ( $scale >= $original_width ) {
- next;
- }
-
- my $scaled = $imager->scale( xpixels => $scale );
-
- $scaled->write( file =>
- File::Spec->catfile( get_path( $user_id, $scale ), $filename ) )
- or die $scaled->errstr;
- }
-
- if ( !$db->add_file( $user->{'user_id'}, $filename, $image->filename ) ) {
-
- #TODO: Send error msg
- }
-
- $self->render(
- json => {
- files => [
- {
- name => $image->filename,
- size => $image->size,
- url => sprintf( '/images/orig/%s', $filename ),
- thumbnailUrl => sprintf( '/images/200/%s', $filename ),
+
+ my $promise = store_image($image_file, $image->filename, $user_id);
+
+ #TODO: add errors handling
+ Mojo::Promise->all($promise)->then(sub {
+ $self->render(
+ json => {
+ files => [
+ {
+ name => $image->filename,
+ size => $image->size,
+ url => sprintf( '/images/orig/%s', $filename ),
+ thumbnailUrl => sprintf( '/images/200/%s', $filename ),
+ }
+ ]
}
- ]
- }
- );
-
- # Redirect to top page
- # $self->redirect_to('index');
+ );
+ })->wait;
} => 'upload';
@@ -310,4 +294,68 @@ sub get_path {
return $path;
}
+sub store_image {
+ my $image_file = shift;
+ my $original_filename = shift;
+ my $user_id = shift;
+
+ my $promise = Mojo::Promise->new;
+ # Process and store uploaded file in a separate process
+ Mojo::IOLoop->subprocess(
+ sub {
+ my $subprocess = shift;
+
+ my $filename = fileparse($image_file);
+ my $imager = Imager->new();
+ $imager->read( file => $image_file ) or die $imager->errstr;
+
+ #http://sylvana.net/jpegcrop/exif_orientation.html
+ #http://myjaphoo.de/docs/exifidentifiers.html
+ my $rotation_angle = $imager->tags( name => "exif_orientation" ) || 1;
+ $log->debug(
+ "Rotation angle [" . $rotation_angle . "]" );
+
+ if ( $rotation_angle == 3 ) {
+ $imager = $imager->rotate( degrees => 180 );
+ }
+ elsif ( $rotation_angle == 6 ) {
+ $imager = $imager->rotate( degrees => 90 );
+ }
+
+ my $original_width = $imager->getwidth();
+
+ for my $scale (@scale_width) {
+
+ #Skip sizes which more than original image
+ if ( $scale >= $original_width ) {
+ next;
+ }
+
+ my $scaled = $imager->scale( xpixels => $scale );
+
+ $scaled->write( file =>
+ File::Spec->catfile( get_path( $user_id, $scale ), $filename ) )
+ or die $scaled->errstr;
+ }
+
+ if ( !$db->add_file( $user_id, $filename, $original_filename ) ) {
+
+ $log->error(sprintf('Can\'t save file %s', $filename));
+ die sprintf('Can\'t save file %s', $filename);
+ }
+
+ return $filename;
+ },
+ sub {
+ my ($subprocess, $err, @results) = @_;
+ $log->error("Subprocess error: $err") and return if $err;
+ $promise->reject("Subprocess error: $err @results") if $err;
+ $promise->resolve(1, @results);
+ }
+ );
+
+ return $promise;
+}
+
+Mojo::IOLoop->start;
app->start;
diff --git a/lib/FotoStore/DB.pm b/lib/FotoStore/DB.pm
index 49dea87..4951676 100644
--- a/lib/FotoStore/DB.pm
+++ b/lib/FotoStore/DB.pm
@@ -1,5 +1,6 @@
package FotoStore::DB;
+use v5.20;
use strict;
use warnings;
@@ -59,8 +60,17 @@ sub add_file($self, $user_id, $filename, $original_filename) {
return $rows;
}
-sub get_files($self, $user_id, $count=20, $start_at=0) {
- return $self->{'dbh'}->selectall_arrayref(q~select * from images where owner_id=? order by created_time desc~, { Slice => {} }, $user_id );
+sub get_files($self, $user_id, $items_count=20, $page=1) {
+
+ # Calculate offset
+ # Pages in UI starts from 1, but here we need it to start from 0
+ $page = 1 if ($page < 1);
+ my $start_at = --$page * $items_count;
+
+ my ($rows_count) = $self->{'dbh'}->selectrow_array(q~select count(*) from images where owner_id=? ~, undef , $user_id);
+ my $images_list = $self->{'dbh'}->selectall_arrayref(q~select * from images where owner_id=? order by created_time desc LIMIT ? OFFSET ? ~, { Slice => {} }, $user_id, $items_count, $start_at );
+
+ return { total_rows => $rows_count, images_list => $images_list };
}
1;
\ No newline at end of file
diff --git a/public/css/main.css b/public/css/main.css
index aaeba2a..17b16a1 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -15,6 +15,15 @@
padding: 5px;
}
+.copy-img:before {
+ content: url(/img/copy_icon.png);
+ width: 32px;
+ height: 32px;
+ overflow: hidden;
+ cursor: pointer;
+ position: relative;
+}
+
.copy-img {
content: url(/img/copy_icon.png);
width: 32px;
@@ -24,6 +33,15 @@
position: relative;
}
+.copy-bb-more:before {
+ content: url(/img/more_icon.png);
+ width: 32px;
+ height: 32px;
+ overflow: hidden;
+ cursor: pointer;
+ position: relative;
+}
+
.copy-bb-more {
content: url(/img/more_icon.png);
width: 32px;
@@ -37,4 +55,9 @@
float: left;
padding-right: 5px;
position: relative;
+}
+
+.upload-form {
+ height: 100px;
+ padding: 10px;
}
\ No newline at end of file
diff --git a/public/file_uploader/.gitignore b/public/file_uploader/.gitignore
deleted file mode 100755
index 29a41a8..0000000
--- a/public/file_uploader/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-.DS_Store
-*.pyc
-node_modules
diff --git a/public/file_uploader/.jshintrc b/public/file_uploader/.jshintrc
deleted file mode 100755
index 4ad82e6..0000000
--- a/public/file_uploader/.jshintrc
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
- "camelcase" : true, // true: Identifiers must be in camelCase
- "curly" : true, // true: Require {} for every new block or scope
- "eqeqeq" : true, // true: Require triple equals (===) for comparison
- "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
- "immed" : true, // true: Require immediate invocations to be wrapped in parens
- // e.g. `(function () { } ());`
- "indent" : 4, // {int} Number of spaces to use for indentation
- "latedef" : true, // true: Require variables/functions to be defined before being used
- "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
- "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
- "noempty" : true, // true: Prohibit use of empty blocks
- "nonew" : true, // true: Prohibit use of constructors for side-effects (without assignment)
- "plusplus" : false, // true: Prohibit use of `++` & `--`
- "quotmark" : "single", // Quotation mark consistency:
- // false : do nothing (default)
- // true : ensure whatever is used is consistent
- // "single" : require single quotes
- // "double" : require double quotes
- "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
- "unused" : true, // true: Require all defined variables be used
- "strict" : true, // true: Requires all functions run in ES5 Strict Mode
- "trailing" : true, // true: Prohibit trailing whitespaces
- "maxparams" : false, // {int} Max number of formal params allowed per function
- "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
- "maxstatements" : false, // {int} Max number statements per function
- "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
- "maxlen" : false, // {int} Max number of characters per line
-
- // Relaxing
- "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
- "boss" : false, // true: Tolerate assignments where comparisons would be expected
- "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
- "eqnull" : false, // true: Tolerate use of `== null`
- "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
- "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
- "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
- // (ex: `for each`, multiple try/catch, function expression…)
- "evil" : false, // true: Tolerate use of `eval` and `new Function()`
- "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
- "funcscope" : false, // true: Tolerate defining variables inside control statements"
- "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
- "iterator" : false, // true: Tolerate using the `__iterator__` property
- "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
- "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
- "laxcomma" : false, // true: Tolerate comma-first style coding
- "loopfunc" : false, // true: Tolerate functions being defined in loops
- "multistr" : false, // true: Tolerate multi-line strings
- "proto" : false, // true: Tolerate using the `__proto__` property
- "scripturl" : false, // true: Tolerate script-targeted URLs
- "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
- "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
- "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
- "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
- "validthis" : false, // true: Tolerate using this in a non-constructor function
-
- // Environments
- "browser" : false, // Web Browser (window, document, etc)
- "couch" : false, // CouchDB
- "devel" : false, // Development/debugging (alert, confirm, etc)
- "dojo" : false, // Dojo Toolkit
- "jquery" : false, // jQuery
- "mootools" : false, // MooTools
- "node" : false, // Node.js
- "nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
- "prototypejs" : false, // Prototype and Scriptaculous
- "rhino" : false, // Rhino
- "worker" : false, // Web Workers
- "wsh" : false, // Windows Scripting Host
- "yui" : false, // Yahoo User Interface
-
- // Legacy
- "nomen" : true, // true: Prohibit dangling `_` in variables
- "onevar" : true, // true: Allow only one `var` statement per function
- "passfail" : false, // true: Stop on first error
- "white" : true, // true: Check against strict whitespace and indentation rules
-
- // Custom Globals
- "globals" : {} // additional predefined global variables
-}
diff --git a/public/file_uploader/.npmignore b/public/file_uploader/.npmignore
deleted file mode 100755
index 0530f5d..0000000
--- a/public/file_uploader/.npmignore
+++ /dev/null
@@ -1,20 +0,0 @@
-*
-!css/jquery.fileupload-noscript.css
-!css/jquery.fileupload-ui-noscript.css
-!css/jquery.fileupload-ui.css
-!css/jquery.fileupload.css
-!img/loading.gif
-!img/progressbar.gif
-!js/cors/jquery.postmessage-transport.js
-!js/cors/jquery.xdr-transport.js
-!js/vendor/jquery.ui.widget.js
-!js/jquery.fileupload-angular.js
-!js/jquery.fileupload-audio.js
-!js/jquery.fileupload-image.js
-!js/jquery.fileupload-jquery-ui.js
-!js/jquery.fileupload-process.js
-!js/jquery.fileupload-ui.js
-!js/jquery.fileupload-validate.js
-!js/jquery.fileupload-video.js
-!js/jquery.fileupload.js
-!js/jquery.iframe-transport.js
diff --git a/public/file_uploader/CONTRIBUTING.md b/public/file_uploader/CONTRIBUTING.md
deleted file mode 100755
index e182f9b..0000000
--- a/public/file_uploader/CONTRIBUTING.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Please follow these pull request guidelines:
-
-1. Update your fork to the latest upstream version.
-
-2. Follow the coding conventions of the original source files (indentation, spaces, brackets layout).
-
-3. Code changes must pass JSHint validation with the `.jshintrc` settings of this project.
-
-4. Code changes must pass the QUnit tests defined in the `test` folder.
-
-5. New features should be covered by accompanying QUnit tests.
-
-6. Keep your commits as atomic as possible, i.e. create a new commit for every single bug fix or feature added.
-
-7. Always add meaningful commit messages.
diff --git a/public/file_uploader/LICENSE b/public/file_uploader/LICENSE
deleted file mode 100755
index 0ecca3e..0000000
--- a/public/file_uploader/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2017 jQuery-File-Upload Authors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/public/file_uploader/README.md b/public/file_uploader/README.md
deleted file mode 100755
index 56785b8..0000000
--- a/public/file_uploader/README.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# jQuery File Upload Plugin
-
-## Demo
-[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
-
-## Description
-File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
-Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-## Setup
-* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
-* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
-
-## Features
-* **Multiple file upload:**
- Allows to select multiple files at once and upload them simultaneously.
-* **Drag & Drop support:**
- Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
-* **Upload progress bar:**
- Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
-* **Cancelable uploads:**
- Individual file uploads can be canceled to stop the upload progress.
-* **Resumable uploads:**
- Aborted uploads can be resumed with browsers supporting the Blob API.
-* **Chunked uploads:**
- Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
-* **Client-side image resizing:**
- Images can be automatically resized on client-side with browsers supporting the required JS APIs.
-* **Preview images, audio and video:**
- A preview of image, audio and video files can be displayed before uploading with browsers supporting the required APIs.
-* **No browser plugins (e.g. Adobe Flash) required:**
- The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
-* **Graceful fallback for legacy browsers:**
- Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
-* **HTML file upload form fallback:**
- Allows progressive enhancement by using a standard HTML file upload form as widget element.
-* **Cross-site file uploads:**
- Supports uploading files to a different domain with cross-site XMLHttpRequests or iframe redirects.
-* **Multiple plugin instances:**
- Allows to use multiple plugin instances on the same webpage.
-* **Customizable and extensible:**
- Provides an API to set individual options and define callBack methods for various upload events.
-* **Multipart and file contents stream uploads:**
- Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
-* **Compatible with any server-side application platform:**
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-## Requirements
-
-### Mandatory requirements
-* [jQuery](https://jquery.com/) v. 1.6+
-* [jQuery UI widget factory](https://api.jqueryui.com/jQuery.widget/) v. 1.9+ (included): Required for the basic File Upload plugin, but very lightweight without any other dependencies from the jQuery UI suite.
-* [jQuery Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) (included): Required for [browsers without XHR file upload support](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
-
-### Optional requirements
-* [JavaScript Templates engine](https://github.com/blueimp/JavaScript-Templates) v. 2.5.4+: Used to render the selected and uploaded files for the Basic Plus UI and jQuery UI versions.
-* [JavaScript Load Image library](https://github.com/blueimp/JavaScript-Load-Image) v. 1.13.0+: Required for the image previews and resizing functionality.
-* [JavaScript Canvas to Blob polyfill](https://github.com/blueimp/JavaScript-Canvas-to-Blob) v. 2.1.1+:Required for the image previews and resizing functionality.
-* [blueimp Gallery](https://github.com/blueimp/Gallery) v. 2.15.1+: Used to display the uploaded images in a lightbox.
-* [Bootstrap](http://getbootstrap.com/) v. 3.2.0+
-* [Glyphicons](http://glyphicons.com/)
-
-The user interface of all versions except the jQuery UI version is built with [Bootstrap](http://getbootstrap.com/) and icons from [Glyphicons](http://glyphicons.com/).
-
-### Cross-domain requirements
-[Cross-domain File Uploads](https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads) using the [Iframe Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/jquery.iframe-transport.js) require a redirect back to the origin server to retrieve the upload results. The [example implementation](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/main.js) makes use of [result.html](https://github.com/blueimp/jQuery-File-Upload/blob/master/cors/result.html) as a static redirect page for the origin server.
-
-The repository also includes the [jQuery XDomainRequest Transport plugin](https://github.com/blueimp/jQuery-File-Upload/blob/master/js/cors/jquery.xdr-transport.js), which enables limited cross-domain AJAX requests in Microsoft Internet Explorer 8 and 9 (IE 10 supports cross-domain XHR requests).
-The XDomainRequest object allows GET and POST requests only and doesn't support file uploads. It is used on the [Demo](https://blueimp.github.io/jQuery-File-Upload/) to delete uploaded files from the cross-domain demo file upload service.
-
-### Custom Backends
-
-You can add support for various backends by adhering to the specification [outlined here](https://github.com/blueimp/jQuery-File-Upload/wiki/JSON-Response).
-
-## Browsers
-
-### Desktop browsers
-The File Upload plugin is regularly tested with the latest browser versions and supports the following minimal versions:
-
-* Google Chrome
-* Apple Safari 4.0+
-* Mozilla Firefox 3.0+
-* Opera 11.0+
-* Microsoft Internet Explorer 6.0+
-
-### Mobile browsers
-The File Upload plugin has been tested with and supports the following mobile browsers:
-
-* Apple Safari on iOS 6.0+
-* Google Chrome on iOS 6.0+
-* Google Chrome on Android 4.0+
-* Default Browser on Android 2.3+
-* Opera Mobile 12.0+
-
-### Supported features
-For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).
-
-## Contributing
-**Bug fixes** and **new features** can be proposed using [pull requests](https://github.com/blueimp/jQuery-File-Upload/pulls).
-Please read the [contribution guidelines](https://github.com/blueimp/jQuery-File-Upload/blob/master/CONTRIBUTING.md) before submitting a pull request.
-
-## Support
-This project is actively maintained, but there is no official support channel.
-If you have a question that another developer might help you with, please post to [Stack Overflow](http://stackoverflow.com/questions/tagged/blueimp+jquery+file-upload) and tag your question with `blueimp jquery file upload`.
-
-## License
-Released under the [MIT license](https://opensource.org/licenses/MIT).
diff --git a/public/file_uploader/angularjs.html b/public/file_uploader/angularjs.html
deleted file mode 100755
index 4858c86..0000000
--- a/public/file_uploader/angularjs.html
+++ /dev/null
@@ -1,211 +0,0 @@
-
-
-
-
File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for AngularJS.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-
-
-
-
-
-
-
Demo Notes
-
-
-
-
The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
-
Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
-
Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
-
You can drag & drop files from your desktop on this webpage (see Browser support).
File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-
-
-
-
- Add files...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Demo Notes
-
-
-
-
The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
-
Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
-
Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
-
You can drag & drop files from your desktop on this webpage (see Browser support).
File Upload widget with multiple file selection, drag&drop support and progress bar for jQuery.
- Supports cross-domain, chunked and resumable file uploads.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-
-
-
-
- Select files...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Demo Notes
-
-
-
-
The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
-
Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
-
Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
-
You can drag & drop files from your desktop on this webpage (see Browser support).
File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-
-
-
-
-
-
-
Demo Notes
-
-
-
-
The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
-
Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
-
Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
-
You can drag & drop files from your desktop on this webpage (see Browser support).
File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery UI.
- Supports cross-domain, chunked and resumable file uploads and client-side image resizing.
- Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
-
-
-
-
-
Demo Notes
-
-
The maximum file size for uploads in this demo is 999 KB (default file size is unlimited).
-
Only image files (JPG, GIF, PNG) are allowed in this demo (by default there is no file type restriction).
-
Uploaded files will be deleted automatically after 5 minutes or less (demo files are stored in memory).
-
You can drag & drop files from your desktop on this webpage (see Browser support).
+
\ No newline at end of file
diff --git a/templates/layouts/base.html.ep b/templates/layouts/base.html.ep
index 5e99f76..b978e6a 100644
--- a/templates/layouts/base.html.ep
+++ b/templates/layouts/base.html.ep
@@ -14,7 +14,7 @@
-
+