Browse Source

Can upload

pull/1/head
Dashie der otter 2 years ago
parent
commit
19aea0fdb0
Signed by: Dashie <dashie@sigpipe.me> GPG Key ID: C2D57B325840B755
11 changed files with 120 additions and 65 deletions
  1. 1
    0
      .gitignore
  2. 7
    1
      README.md
  3. 5
    3
      app.py
  4. 31
    52
      controllers/sound.py
  5. 4
    4
      controllers/users.py
  6. 10
    2
      forms.py
  7. 26
    0
      migrations/versions/02_6b5a95742bb4_.py
  8. 6
    1
      models.py
  9. 4
    2
      templates/layout.jinja2
  10. 26
    0
      templates/sound/upload.jinja2
  11. 0
    0
      uploads/.gitkeep

+ 1
- 0
.gitignore View File

@@ -4,4 +4,5 @@ TODO.org
.idea
*.db
uploads/pictures/*
uploads/sounds/*
tmp/cty.xml

+ 7
- 1
README.md View File

@@ -33,6 +33,12 @@ Reel2Bits
# Crons explained
- none yet

# TODO
- Albums
- Tags
- Genre
- User picture

# Licensing
- MIT License

+ 5
- 3
app.py View File

@@ -9,11 +9,12 @@ from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_migrate import Migrate
from flask_security import Security
from flask_uploads import configure_uploads, UploadSet, IMAGES
from flask_uploads import configure_uploads, UploadSet, AUDIO

from controllers.admin import bp_admin
from controllers.main import bp_main
from controllers.users import bp_users
from controllers.sound import bp_sound
from forms import ExtendedRegisterForm
from models import db, user_datastore
from utils import dt_utc_to_user_tz, InvalidUsage, show_date_no_offset, is_admin, gcfg
@@ -74,12 +75,13 @@ def create_app(cfg=None):
response.status_code = error.status_code
return response

pictures = UploadSet('pictures', IMAGES)
configure_uploads(app, pictures)
sounds = UploadSet('sounds', AUDIO)
configure_uploads(app, sounds)

app.register_blueprint(bp_main)
app.register_blueprint(bp_users)
app.register_blueprint(bp_admin)
app.register_blueprint(bp_sound)

# Used in development
@app.route('/uploads/<path:stuff>', methods=['GET'])

+ 31
- 52
controllers/sound.py View File

@@ -2,60 +2,39 @@ import pytz
from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_security import login_required, current_user
from sqlalchemy import func
from werkzeug.utils import secure_filename
from forms import SoundUploadForm
from models import db, User, UserLogging, Sound
from flask_uploads import UploadSet, AUDIO

from forms import UserProfileForm
from models import db, User, UserLogging
bp_sound = Blueprint('bp_sound', __name__)

bp_users = Blueprint('bp_users', __name__)
sounds = UploadSet('sounds', AUDIO)


@bp_users.route('/user/logs', methods=['GET'])
@bp_sound.route('/sound/upload', methods=['GET', 'POST'])
@login_required
def logs():
level = request.args.get('level')
pcfg = {"title": "User Logs"}
if level:
_logs = UserLogging.query.filter(UserLogging.level == level.upper(),
UserLogging.user_id == current_user.id
).order_by(UserLogging.timestamp.desc()).limit(100).all()
else:
_logs = UserLogging.query.filter(UserLogging.user_id == current_user.id
).order_by(UserLogging.timestamp.desc()).limit(100).all()
return render_template('users/user_logs.jinja2', pcfg=pcfg, logs=_logs)


@bp_users.route('/user', methods=['GET'])
@login_required
def profile():
pcfg = {"title": "My Profile"}

user = User.query.filter(User.id == current_user.id).first()
if not user:
flash("User not found", 'error')
return redirect(url_for("bp_main.home"))

return render_template('users/profile.jinja2', pcfg=pcfg, user=user)


@bp_users.route('/user/edit', methods=['GET', 'POST'])
@login_required
def edit():
pcfg = {"title": "Edit my profile"}

user = User.query.filter(User.id == current_user.id).first()
if not user:
flash("User not found", 'error')
return redirect(url_for("bp_main.home"))

form = UserProfileForm(request.form, user)
form.timezone.choices = [[str(i), str(i)] for i in pytz.all_timezones]

if form.validate_on_submit():
user.lastname = form.lastname.data
user.firstname = form.firstname.data
user.timezone = form.timezone.data

db.session.commit()
return redirect(url_for('bp_users.profile'))

return render_template('users/edit.jinja2', pcfg=pcfg, form=form, user=user)
def upload():
pcfg = {"title": "New upload"}

form = SoundUploadForm()

if request.method == 'POST' and 'sound' in request.files:
if form.validate_on_submit():
filename = sounds.save(request.files['sound'])
rec = Sound()
rec.filename=filename
rec.user_id=current_user.id
rec.title = form.title.data
rec.public = form.public.data

db.session.add(rec)
db.session.commit()
flash('Uploaded !', 'success')
else:
return render_template('sound/upload.jinja2', pcfg=pcfg, form=form, flash='Error with the file')
return redirect(url_for('bp_main.home', username=current_user.name))
# TODO redirect to song page

# GET
return render_template('sound/upload.jinja2', pcfg=pcfg, form=form)

+ 4
- 4
controllers/users.py View File

@@ -24,12 +24,12 @@ def logs():
return render_template('users/user_logs.jinja2', pcfg=pcfg, logs=_logs)


@bp_users.route('/user', methods=['GET'])
@bp_users.route('/user/<string:name>', methods=['GET'])
@login_required
def profile():
pcfg = {"title": "My Profile"}
def profile(name):
pcfg = {"title": "%s's profile" % name}

user = User.query.filter(User.id == current_user.id).first()
user = User.query.filter(User.name == name).first()
if not user:
flash("User not found", 'error')
return redirect(url_for("bp_main.home"))

+ 10
- 2
forms.py View File

@@ -2,7 +2,7 @@ import datetime
from libqth import is_valid_qth

from flask_security import RegisterForm, current_user
from flask_uploads import UploadSet, IMAGES
from flask_uploads import UploadSet, AUDIO
from flask_wtf import Form
from flask_wtf.file import FileField, FileAllowed, FileRequired
from wtforms import PasswordField, SubmitField, TextAreaField, SelectField, IntegerField, \
@@ -20,7 +20,7 @@ from utils import dt_utc_to_user_tz

BaseModelForm = model_form_factory(Form)

pictures = UploadSet('pictures', IMAGES)
sounds = UploadSet('sounds', AUDIO)


class PasswordFieldNotHidden(StringField):
@@ -69,3 +69,11 @@ class ConfigForm(Form):
app_name = StringField('App Name', [DataRequired()])

submit = SubmitField('Update config')


class SoundUploadForm(Form):
title = StringField('Title')
sound = FileField('File', [FileRequired(), FileAllowed(AUDIO)])
public = BooleanField('Public', default=True)

submit = SubmitField('Upload')

+ 26
- 0
migrations/versions/02_6b5a95742bb4_.py View File

@@ -0,0 +1,26 @@
"""Add Sound filename

Revision ID: 6b5a95742bb4
Revises: da3273ca0f0f
Create Date: 2016-12-31 15:24:39.095388

"""

# revision identifiers, used by Alembic.
revision = '6b5a95742bb4'
down_revision = 'da3273ca0f0f'

from alembic import op
import sqlalchemy as sa


def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('sound', sa.Column('filename', sa.String(length=255), nullable=True))
### end Alembic commands ###


def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_column('sound', 'filename')
### end Alembic commands ###

+ 6
- 1
models.py View File

@@ -127,10 +127,12 @@ class Sound(db.Model):
description = db.Column(db.UnicodeText(), nullable=True)
public = db.Column(db.Boolean(), default=True, nullable=False)
slug = db.Column(db.String(255), unique=True, nullable=True)
filename = db.Column(db.String(255), unique=False, nullable=True)

user_id = db.Column(db.Integer(), db.ForeignKey('user.id'), nullable=False)
sound_infos = db.relationship('SoundInfo', backref='sound_info', lazy='dynamic', cascade="delete")


@event.listens_for(User, 'after_update')
@event.listens_for(User, 'after_insert')
def make_slug(mapper, connection, target):
@@ -145,7 +147,10 @@ def make_slug(mapper, connection, target):
@event.listens_for(Sound, 'after_insert')
def make_slug(mapper, connection, target):
if not target.slug or target.slug == "":
title = "{0} {1}".format(target.id, target.title)
if not target.title or target.title == "":
title = "{0} {1}".format(target.id, target.filename)
else:
title = "{0} {1}".format(target.id, target.title)
slug = slugify(title)
connection.execute(
User.__table__.update().where(User.__table__.c.id == target.id).values(slug=slug)

+ 4
- 2
templates/layout.jinja2 View File

@@ -52,7 +52,9 @@
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">

{% if current_user.is_authenticated %}
<li><a href="{{ url_for('bp_sound.upload') }}">Upload</a></li>
{% endif %}
</ul>
<ul class="nav navbar-nav navbar-right">
{% if request.endpoint %}
@@ -62,7 +64,7 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Logged as {{ current_user.name }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li class="dropdown-header">User</li>
<li><a href="{{ url_for('bp_users.profile') }}">Profile</a></li>
<li><a href="{{ url_for('bp_users.profile', name=current_user.name) }}">Profile</a></li>
<li><a href="{{ url_for('bp_users.logs') }}">Logs</a></li>
{% if is_admin() %}
<li role="separator" class="divider"></li>

+ 26
- 0
templates/sound/upload.jinja2 View File

@@ -0,0 +1,26 @@
{% extends "layout.jinja2" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block content %}
<div class="row">
<div class="col-lg-6">
<h3>New upload</h3>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<form action="{{ url_for('bp_sound.upload') }}" method="POST" class="form-horizontal" enctype="multipart/form-data">
{{ form.hidden_tag() }}
{{ wtf.form_errors(form, hiddens=True) }}
{{ wtf.form_field(form.title, 'horizontal', placeholder="What's the title ?") }}
{{ wtf.form_field(form.sound, 'horizontal', accept='.wav, .mp3, .aac, .ogg, .oga, .flac') }}
{{ wtf.form_field(form.public, 'horizontal') }}
{{ wtf.form_field(form.submit, button_map={'submit': 'success'}) }}
</form>
</div>

<div class="col-lg-6">
</div>

</div>
{% endblock %}

+ 0
- 0
uploads/.gitkeep View File


Loading…
Cancel
Save