Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
|
d08a19b7cb | ||
|
664b26ddac | ||
|
455484f2b2 | ||
|
c3d690f98a | ||
|
8ff6d351c4 | ||
|
3d3e83d1d8 |
13 changed files with 231 additions and 95 deletions
58
fotostore.pl
58
fotostore.pl
|
@ -166,15 +166,15 @@ get '/get_images' => ( authenticated => 1 ) => sub {
|
||||||
File::Spec->catfile( $IMAGE_DIR, $current_user->{'user_id'},
|
File::Spec->catfile( $IMAGE_DIR, $current_user->{'user_id'},
|
||||||
$thumbs_size );
|
$thumbs_size );
|
||||||
|
|
||||||
my @images = map { $_->{'file_name'} } @$files_list;
|
my @images = map { $_->file_name } @$files_list;
|
||||||
|
|
||||||
my $images = [];
|
my $images = [];
|
||||||
|
|
||||||
for my $img_item (@$files_list) {
|
for my $img_item (@$files_list) {
|
||||||
my $file = $img_item->{'file_name'};
|
my $file = $img_item->file_name;
|
||||||
my $img_hash = {};
|
my $img_hash = {};
|
||||||
$img_hash->{'id'} = $img_item->{'file_id'};
|
$img_hash->{'id'} = $img_item->file_id;
|
||||||
$img_hash->{'filename'} = $img_item->{'original_filename'};
|
$img_hash->{'filename'} = $img_item->original_filename;
|
||||||
$img_hash->{'original_url'} =
|
$img_hash->{'original_url'} =
|
||||||
File::Spec->catfile( '/', $IMAGE_BASE, $current_user->{'user_id'},
|
File::Spec->catfile( '/', $IMAGE_BASE, $current_user->{'user_id'},
|
||||||
$ORIG_DIR, $file );
|
$ORIG_DIR, $file );
|
||||||
|
@ -196,7 +196,6 @@ get '/get_images' => ( authenticated => 1 ) => sub {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$img_hash->{'scales'} = \@scaled;
|
$img_hash->{'scales'} = \@scaled;
|
||||||
|
@ -257,11 +256,16 @@ post '/upload' => ( authenticated => 1 ) => sub {
|
||||||
# Save to file
|
# Save to file
|
||||||
$image->move_to($image_file);
|
$image->move_to($image_file);
|
||||||
|
|
||||||
|
my $imager = Imager->new();
|
||||||
|
$imager->read( file => $image_file ) or die $imager->errstr;
|
||||||
|
|
||||||
my $promise = store_image($image_file, $image->filename, $user_id);
|
my $promise = store_image($imager , $filename, $image->filename, $user_id);
|
||||||
|
|
||||||
#TODO: add errors handling
|
#TODO: add errors handling
|
||||||
Mojo::Promise->all($promise)->then(sub {
|
Mojo::Promise->all($promise)->then(sub {
|
||||||
|
my $res = shift;
|
||||||
|
save_tags($imager, $res->[1]);
|
||||||
|
|
||||||
$self->render(
|
$self->render(
|
||||||
json => {
|
json => {
|
||||||
files => [
|
files => [
|
||||||
|
@ -278,6 +282,21 @@ post '/upload' => ( authenticated => 1 ) => sub {
|
||||||
|
|
||||||
} => 'upload';
|
} => 'upload';
|
||||||
|
|
||||||
|
post '/album' => ( authenticated => 1 ) => sub {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
my $user_id = $self->current_user()->{'user_id'};
|
||||||
|
my $album_name = $self->req->param('album_name');
|
||||||
|
my $album_desc = $self->req->param('album_desc') || '';
|
||||||
|
|
||||||
|
my $album = $db->add_album($user_id, $album_name, $album_desc);
|
||||||
|
$self->render(
|
||||||
|
json => { album_id => $album->album_id,
|
||||||
|
album_name => $album->album_name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
sub create_hash {
|
sub create_hash {
|
||||||
my $data_to_hash = shift;
|
my $data_to_hash = shift;
|
||||||
|
|
||||||
|
@ -295,7 +314,8 @@ sub get_path {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub store_image {
|
sub store_image {
|
||||||
my $image_file = shift;
|
my $imager = shift;
|
||||||
|
my $filename = shift;
|
||||||
my $original_filename = shift;
|
my $original_filename = shift;
|
||||||
my $user_id = shift;
|
my $user_id = shift;
|
||||||
|
|
||||||
|
@ -303,12 +323,6 @@ sub store_image {
|
||||||
# Process and store uploaded file in a separate process
|
# Process and store uploaded file in a separate process
|
||||||
Mojo::IOLoop->subprocess(
|
Mojo::IOLoop->subprocess(
|
||||||
sub {
|
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://sylvana.net/jpegcrop/exif_orientation.html
|
||||||
#http://myjaphoo.de/docs/exifidentifiers.html
|
#http://myjaphoo.de/docs/exifidentifiers.html
|
||||||
my $rotation_angle = $imager->tags( name => "exif_orientation" ) || 1;
|
my $rotation_angle = $imager->tags( name => "exif_orientation" ) || 1;
|
||||||
|
@ -338,13 +352,14 @@ sub store_image {
|
||||||
or die $scaled->errstr;
|
or die $scaled->errstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !$db->add_file( $user_id, $filename, $original_filename ) ) {
|
my $file_info = $db->add_file( $user_id, $filename, $original_filename );
|
||||||
|
if ( !defined $file_info ) {
|
||||||
$log->error(sprintf('Can\'t save file %s', $filename));
|
$log->error(sprintf('Can\'t save file %s', $filename));
|
||||||
die sprintf('Can\'t save file %s', $filename);
|
die sprintf('Can\'t save file %s', $filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $filename;
|
|
||||||
|
return $file_info->file_id;
|
||||||
},
|
},
|
||||||
sub {
|
sub {
|
||||||
my ($subprocess, $err, @results) = @_;
|
my ($subprocess, $err, @results) = @_;
|
||||||
|
@ -357,5 +372,16 @@ sub store_image {
|
||||||
return $promise;
|
return $promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub save_tags {
|
||||||
|
my $image = shift;
|
||||||
|
my $db_file_id = shift;
|
||||||
|
|
||||||
|
my @tags = $image->tags();
|
||||||
|
|
||||||
|
my %tags_data = map { $_->[0] => $_->[1]} @tags;
|
||||||
|
$db->save_tags($db_file_id, \%tags_data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Mojo::IOLoop->start;
|
Mojo::IOLoop->start;
|
||||||
app->start;
|
app->start;
|
||||||
|
|
|
@ -4,24 +4,30 @@ use v5.20;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
use feature qw(signatures);
|
use feature qw(signatures say);
|
||||||
no warnings qw(experimental::signatures);
|
no warnings qw(experimental::signatures);
|
||||||
|
|
||||||
|
use Data::Dumper;
|
||||||
|
use DBIx::Struct qw(connector);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my $db_file = shift;
|
my $db_file = shift;
|
||||||
|
|
||||||
my $dbh = DBI->connect(sprintf('dbi:SQLite:dbname=%s', $db_file),"","");
|
my $dbix = DBIx::Struct::connect(sprintf('dbi:SQLite:dbname=%s', $db_file),"","");
|
||||||
|
|
||||||
my $self = {
|
my $self = {
|
||||||
dbh => $dbh,
|
dbix_connector => $dbix,
|
||||||
};
|
};
|
||||||
bless $self, $class;
|
bless $self, $class;
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_user ($self, $nickname, $password) {
|
sub check_user ($self, $nickname, $password) {
|
||||||
my ($user_id) = $self->{'dbh'}->selectrow_array(q~select user_id from users where nickname=? and password=?~, undef, ($nickname, $password));
|
my $row = one_row('users', { nickname => $nickname, password => $password });
|
||||||
return $user_id;
|
return $row->user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_user ($self, $user_id) {
|
sub get_user ($self, $user_id) {
|
||||||
|
@ -33,31 +39,31 @@ sub get_user ($self, $user_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _get_user_by_user_id ($self, $user_id) {
|
sub _get_user_by_user_id ($self, $user_id) {
|
||||||
my $user_data = $self->{'dbh'}->selectrow_hashref(q~select user_id, nickname, fullname, timestamp from users where user_id=?~, {}, ($user_id));
|
my $row = one_row('users', {user_id => $user_id}) || return {};
|
||||||
return $user_data;
|
return {user_id => $row->user_id, nickname => $row->nickname, fullname => $row->fullname, timestamp => $row->timestamp};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _get_user_by_username($self, $username) {
|
sub _get_user_by_username($self, $username) {
|
||||||
my $user_data = $self->{'dbh'}->selectrow_hashref(q~select user_id, nickname, fullname, timestamp from users where nickname=?~, {}, ($username));
|
my $row = one_row('users', {nickname => $username}) || return {};
|
||||||
return $user_data;
|
return {user_id => $row->user_id, nickname => $row->nickname, fullname => $row->fullname, timestamp => $row->timestamp};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub add_user($self, $username, $password, $fullname) {
|
sub add_user($self, $username, $password, $fullname) {
|
||||||
my $rows = $self->{'dbh'}->do(q~insert into users (nickname, password, fullname) values (?, ?, ?)~, undef, ($username, $password, $fullname));
|
my $row = new_row('users', nickname => $username, password => $password, fullname => $fullname);
|
||||||
if ($self->{'dbh'}->errstr) {
|
return $row;
|
||||||
die $self->{'dbh'}->errstr;
|
|
||||||
}
|
|
||||||
return $rows;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub add_file($self, $user_id, $filename, $original_filename) {
|
sub add_file($self, $user_id, $filename, $original_filename) {
|
||||||
my $rows = $self->{'dbh'}->do(q~insert into images (owner_id, file_name, original_filename) values (?, ?, ?)~, undef, ($user_id, $filename, $original_filename));
|
|
||||||
if ($self->{'dbh'}->errstr) {
|
my $row = new_row('images',
|
||||||
die $self->{'dbh'}->errstr;
|
owner_id => $user_id,
|
||||||
}
|
file_name => $filename,
|
||||||
return $rows;
|
original_filename => $original_filename
|
||||||
|
);
|
||||||
|
|
||||||
|
return $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_files($self, $user_id, $items_count=20, $page=1) {
|
sub get_files($self, $user_id, $items_count=20, $page=1) {
|
||||||
|
@ -67,10 +73,48 @@ sub get_files($self, $user_id, $items_count=20, $page=1) {
|
||||||
$page = 1 if ($page < 1);
|
$page = 1 if ($page < 1);
|
||||||
my $start_at = --$page * $items_count;
|
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 ($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 );
|
my $rows_count = one_row(['images' => -count => 'file_id', -where => { 'owner_id' => $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 );
|
||||||
|
my $images_list = all_rows([
|
||||||
|
'images' =>
|
||||||
|
-where => { 'owner_id' => $user_id },
|
||||||
|
-limit => $items_count,
|
||||||
|
-offset => $start_at
|
||||||
|
]);
|
||||||
|
|
||||||
return { total_rows => $rows_count, images_list => $images_list };
|
return { total_rows => $rows_count, images_list => $images_list };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub add_album($self, $user_id, $album_name, $album_desc) {
|
||||||
|
my $row = new_row('albums', name => $album_name, description => $album_desc, owner_id => $user_id);
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub save_tag($self, $db_file_id, $tag_name, $tag_value) {
|
||||||
|
eval {
|
||||||
|
my $row = new_row('exif_data', 'exif_tag' => $tag_name, 'tag_data' => $tag_value,'image_id' => $db_file_id, deleted => 0) || die "error!";
|
||||||
|
return $row;
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
say STDERR ("Error! $@");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub save_tags($self, $db_file_id, $tag_data) {
|
||||||
|
eval {
|
||||||
|
connector->txn(sub {
|
||||||
|
for my $key (keys %$tag_data) {
|
||||||
|
$self->save_tag($db_file_id, $key, $tag_data->{$key});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
say STDERR ("Error! $@");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1;
|
1;
|
6
public/vendor/js/vue.min.js
vendored
Normal file
6
public/vendor/js/vue.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -2,13 +2,14 @@
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
|
||||||
CREATE TABLE albums (
|
CREATE TABLE `albums` (
|
||||||
album_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
`album_id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
name STRING NOT NULL,
|
`name` STRING NOT NULL,
|
||||||
description TEXT,
|
`description` TEXT,
|
||||||
created DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
`created` DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
||||||
modified DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
`modified` DATETIME DEFAULT (CURRENT_TIMESTAMP),
|
||||||
deleted BOOLEAN
|
`deleted` BOOLEAN,
|
||||||
|
`owner_id` INTEGER NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
13
sql/deploy/exif_data.sql
Normal file
13
sql/deploy/exif_data.sql
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
-- Deploy fotostore:exif_data to sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE `exif_data` (
|
||||||
|
`record_id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
`exif_tag` TEXT NOT NULL,
|
||||||
|
`tag_data` TEXT NOT NULL,
|
||||||
|
`image_id` INTEGER NOT NULL,
|
||||||
|
`deleted` BOOLEAN DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
17
sql/deploy/images@v1.0.0.sql
Normal file
17
sql/deploy/images@v1.0.0.sql
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
-- Deploy fotostore:images to sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
CREATE TABLE images (
|
||||||
|
file_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
owner_id INTEGER NOT NULL,
|
||||||
|
file_name TEXT NOT NULL,
|
||||||
|
created_time DATETIME NOT NULL
|
||||||
|
DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY (
|
||||||
|
owner_id
|
||||||
|
)
|
||||||
|
REFERENCES users (user_id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
COMMIT;
|
7
sql/revert/exif_data.sql
Normal file
7
sql/revert/exif_data.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Revert fotostore:exif_data from sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- XXX Add DDLs here.
|
||||||
|
|
||||||
|
COMMIT;
|
5
sql/revert/images@v1.0.0.sql
Normal file
5
sql/revert/images@v1.0.0.sql
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE images;
|
||||||
|
|
||||||
|
COMMIT;
|
|
@ -11,3 +11,5 @@ user_albums [users albums] 2017-07-22T09:47:48Z Denis Fedoseev <denis.fedoseev@g
|
||||||
@v1.0.0 2017-08-02T03:46:51Z Denis Fedoseev <denis.fedoseev@gmail.com> # Tag v1.0.0.
|
@v1.0.0 2017-08-02T03:46:51Z Denis Fedoseev <denis.fedoseev@gmail.com> # Tag v1.0.0.
|
||||||
images [images@v1.0.0] 2017-08-02T03:55:08Z Denis Fedoseev <denis.fedoseev@gmail.com> # Adds images.original_filename.
|
images [images@v1.0.0] 2017-08-02T03:55:08Z Denis Fedoseev <denis.fedoseev@gmail.com> # Adds images.original_filename.
|
||||||
@v1.1.0 2017-08-02T04:46:42Z Denis Fedoseev <denis.fedoseev@gmail.com> # Tag v1.1.0.
|
@v1.1.0 2017-08-02T04:46:42Z Denis Fedoseev <denis.fedoseev@gmail.com> # Tag v1.1.0.
|
||||||
|
|
||||||
|
exif_data 2018-08-19T08:04:49Z Denis Fedoseev <denis.fedoseev@gmail.com> # exif data table
|
||||||
|
|
7
sql/verify/exif_data.sql
Normal file
7
sql/verify/exif_data.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:exif_data on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- XXX Add verifications here.
|
||||||
|
|
||||||
|
ROLLBACK;
|
7
sql/verify/images@v1.0.0.sql
Normal file
7
sql/verify/images@v1.0.0.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
-- Verify fotostore:images on sqlite
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
select file_id, owner_id, file_name, created_time from images where 0;
|
||||||
|
|
||||||
|
ROLLBACK;
|
|
@ -5,26 +5,7 @@
|
||||||
<script src="/file_uploader/js/vendor/jquery.ui.widget.js"></script>
|
<script src="/file_uploader/js/vendor/jquery.ui.widget.js"></script>
|
||||||
<script src="/file_uploader/js/jquery.iframe-transport.js"></script>
|
<script src="/file_uploader/js/jquery.iframe-transport.js"></script>
|
||||||
<script src="/file_uploader/js/jquery.fileupload.js"></script>
|
<script src="/file_uploader/js/jquery.fileupload.js"></script>
|
||||||
<script>
|
|
||||||
$(function () {
|
|
||||||
$('#fileupload').fileupload({
|
|
||||||
dataType: 'json',
|
|
||||||
done: function (e, data) {
|
|
||||||
$.each(data.result.files, function (index, file) {
|
|
||||||
$('<p/>').text(file.name).appendTo('#lastUploadLog');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
sequentialUploads: true,
|
|
||||||
progressall: function (e, data) {
|
|
||||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
|
||||||
$('#progress .progress-bar').css(
|
|
||||||
'width',
|
|
||||||
progress + '%'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="progress" class="container">
|
<div id="progress" class="container">
|
||||||
<div class="progress-bar" style="width: 0%;"></div>
|
<div class="progress-bar" style="width: 0%;"></div>
|
||||||
|
@ -109,7 +90,6 @@
|
||||||
xhr.onload = function () {
|
xhr.onload = function () {
|
||||||
var result = JSON.parse(xhr.responseText);
|
var result = JSON.parse(xhr.responseText);
|
||||||
self.imagesList = result.images_list;
|
self.imagesList = result.images_list;
|
||||||
console.dir(self.imagesList);
|
|
||||||
self.pagesCount = result.pages_count;
|
self.pagesCount = result.pages_count;
|
||||||
}
|
}
|
||||||
xhr.send()
|
xhr.send()
|
||||||
|
@ -126,3 +106,24 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('#fileupload').fileupload({
|
||||||
|
dataType: 'json',
|
||||||
|
done: function (e, data) {
|
||||||
|
$.each(data.result.files, function (index, file) {
|
||||||
|
$('<p/>').text(file.name).appendTo('#lastUploadLog');
|
||||||
|
$('#progress .progress-bar').css('width','0%');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
sequentialUploads: true,
|
||||||
|
progressall: function (e, data) {
|
||||||
|
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||||
|
$('#progress .progress-bar').css(
|
||||||
|
'width',
|
||||||
|
progress + '%'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" >
|
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" >
|
||||||
<title>Rough, Slow, Stupid, Contrary Photohosting</title>
|
<title>Simple image hosting</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<!-- Bootstrap styles -->
|
<!-- Bootstrap styles -->
|
||||||
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<link rel="stylesheet" href="/file_uploader/css/jquery.fileupload-ui.css">
|
<link rel="stylesheet" href="/file_uploader/css/jquery.fileupload-ui.css">
|
||||||
<link rel="stylesheet" href="/css/main.css">
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
|
||||||
<script src="https://vuejs.org/js/vue.min.js"></script>
|
<script src="/vendor/js/vue.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="/">Rough, Slow, Stupid, Contrary Photohosting</a>
|
<a class="navbar-brand" href="/">Tiny images hosting</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-collapse collapse">
|
<div class="navbar-collapse collapse">
|
||||||
<% if (!is_user_authenticated()) { %>
|
<% if (!is_user_authenticated()) { %>
|
||||||
|
|
Loading…
Reference in a new issue