Compare commits
No commits in common. "c549e1c9423dc56100b276a02631e55dc0e1abcf" and "4d7a81c0c9c785ed422eecf8410433f5c925ea94" have entirely different histories.
c549e1c942
...
4d7a81c0c9
|
@ -1,4 +1,3 @@
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.db
|
*.db
|
||||||
config.json
|
config.json
|
||||||
static/components/
|
|
||||||
|
|
21
bower.json
21
bower.json
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"name": "skehsucks-share",
|
|
||||||
"authors": [
|
|
||||||
"Derek Schmidt <skehmatics@gmail.com>"
|
|
||||||
],
|
|
||||||
"description": "ftp but worse",
|
|
||||||
"main": "notpiracyiswear.py",
|
|
||||||
"license": "GPL",
|
|
||||||
"homepage": "",
|
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
|
||||||
"webcomponentsjs": "^2.0.1",
|
|
||||||
"vaadin-upload": "^4.1.0",
|
|
||||||
"clipboard-copy": "advanced-rest-client/clipboard-copy#^2.0.1",
|
|
||||||
"paper-tooltip": "PolymerElements/paper-tooltip#^2.1.1",
|
|
||||||
"paper-toggle-button": "PolymerElements/paper-toggle-button#^2.1.1"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"webcomponentsjs": "^v1.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,11 @@
|
||||||
from flask import Flask, render_template, flash, send_from_directory, redirect, request, session, url_for, abort
|
from flask import Flask, render_template, flash, send_from_directory, redirect, request, session, url_for
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
from flask_login import LoginManager, current_user, login_user, logout_user, login_required, fresh_login_required
|
from flask_login import LoginManager, current_user, login_user, logout_user, login_required, fresh_login_required
|
||||||
from flask_limiter import Limiter
|
from flask_limiter import Limiter
|
||||||
import flask_limiter.util
|
import flask_limiter.util
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from werkzeug.utils import secure_filename
|
|
||||||
import os
|
import os
|
||||||
import json
|
|
||||||
|
|
||||||
from models import db, User, Referal
|
from models import db, User, Referal
|
||||||
|
|
||||||
|
@ -32,16 +30,6 @@ def load_user(id):
|
||||||
|
|
||||||
limiter = Limiter(app, key_func=flask_limiter.util.get_ipaddr, headers_enabled=True)
|
limiter = Limiter(app, key_func=flask_limiter.util.get_ipaddr, headers_enabled=True)
|
||||||
|
|
||||||
def is_secure_path(path, servepath=None):
|
|
||||||
realpath = os.path.realpath(path) + os.path.sep
|
|
||||||
if servepath is None:
|
|
||||||
servepath = os.path.realpath(app.config['SERVE_DIR'])
|
|
||||||
else:
|
|
||||||
servepath = os.path.realpath(servepath)
|
|
||||||
|
|
||||||
return realpath.startswith(servepath)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
|
@ -118,38 +106,12 @@ def logout():
|
||||||
flash("bye binch", 'info')
|
flash("bye binch", 'info')
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
@app.route('/upload', methods=['GET', 'POST'])
|
|
||||||
@app.route('/upload/<path:path>', methods=['GET', 'POST'])
|
|
||||||
@login_required
|
|
||||||
def upload(path=None):
|
|
||||||
if not current_user.can_upload:
|
|
||||||
abort(403)
|
|
||||||
|
|
||||||
path = path if path is not None else ''
|
|
||||||
if not is_secure_path(os.path.join(app.config['SERVE_DIR'], path)):
|
|
||||||
abort(400)
|
|
||||||
|
|
||||||
if request.method == 'GET':
|
|
||||||
return render_template('upload.html')
|
|
||||||
else:
|
|
||||||
if 'file' in request.files and secure_filename(request.files['file'].filename) != '':
|
|
||||||
file = request.files['file']
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
fullpath = os.path.join(app.config['SERVE_DIR'], path, filename)
|
|
||||||
if os.path.exists(fullpath):
|
|
||||||
return json.dumps({'status': 'error', 'message': "Filename already exists"}), 409
|
|
||||||
file.save(fullpath)
|
|
||||||
relpath = os.path.join(path, filename)
|
|
||||||
return json.dumps({'status': 'success', 'link': url_for('files', path = relpath)}), 201
|
|
||||||
else:
|
|
||||||
return json.dumps({'status': 'error', 'message': "No valid file attached to this request"}), 400
|
|
||||||
|
|
||||||
@app.route('/refer', methods=['GET', 'POST'])
|
@app.route('/refer', methods=['GET', 'POST'])
|
||||||
@fresh_login_required
|
@fresh_login_required
|
||||||
@limiter.limit("50/hour;2/second", key_func=lambda : current_user, exempt_when=lambda : request.method == 'GET')
|
@limiter.limit("50/hour;2/second", key_func=lambda : current_user, exempt_when=lambda : request.method == 'GET')
|
||||||
def refer():
|
def refer():
|
||||||
if not current_user.can_refer:
|
if not current_user.can_refer:
|
||||||
abort(403)
|
return render_template('403.html'), 403
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return render_template('new_referal.html')
|
return render_template('new_referal.html')
|
||||||
|
@ -173,22 +135,20 @@ def refer():
|
||||||
@login_required
|
@login_required
|
||||||
def show_referal():
|
def show_referal():
|
||||||
if not current_user.can_refer:
|
if not current_user.can_refer:
|
||||||
abort(403)
|
return render_template('403.html'), 403
|
||||||
|
|
||||||
return render_template('show_referal.html', key=request.args.get('key'))
|
return render_template('show_referal.html', key=request.args.get('key'))
|
||||||
|
|
||||||
@app.route('/browse/')
|
@app.route('/browse/')
|
||||||
@app.route('/browse/<path:path>')
|
@app.route('/browse/<path:path>')
|
||||||
@login_required
|
@login_required
|
||||||
def browse(path=None):
|
def browse(path = None):
|
||||||
|
# Search for files in path
|
||||||
searchpath = os.path.join(app.config['SERVE_DIR'], path) if path is not None else app.config['SERVE_DIR']
|
searchpath = os.path.join(app.config['SERVE_DIR'], path) if path is not None else app.config['SERVE_DIR']
|
||||||
|
|
||||||
if not is_secure_path(searchpath):
|
|
||||||
abort(400)
|
|
||||||
|
|
||||||
# 404 if no such path exists
|
# 404 if no such path exists
|
||||||
if not os.path.exists(searchpath):
|
if not os.path.exists(searchpath):
|
||||||
abort(404)
|
return render_template('404.html'), 404
|
||||||
|
|
||||||
if not os.path.isdir(searchpath):
|
if not os.path.isdir(searchpath):
|
||||||
return redirect(url_for('files', path=path), code=301)
|
return redirect(url_for('files', path=path), code=301)
|
||||||
|
@ -207,36 +167,11 @@ def browse(path=None):
|
||||||
# Render out the item browser
|
# Render out the item browser
|
||||||
return render_template('items.html', files = file_size_isdir_tuple_list, path = os.path.normpath(path) + '/' if path is not None else '')
|
return render_template('items.html', files = file_size_isdir_tuple_list, path = os.path.normpath(path) + '/' if path is not None else '')
|
||||||
|
|
||||||
# Expecting lots of traffic? Do these via nginx before you kill your server
|
|
||||||
@app.route('/files/<path:path>')
|
@app.route('/files/<path:path>')
|
||||||
@login_required
|
@login_required
|
||||||
def files(path):
|
def files(path):
|
||||||
if not is_secure_path(os.path.join(app.config['SERVE_DIR'], path)):
|
|
||||||
abort(400)
|
|
||||||
return send_from_directory(app.config['SERVE_DIR'], path)
|
return send_from_directory(app.config['SERVE_DIR'], path)
|
||||||
|
|
||||||
@app.route('/components/<path:path>')
|
|
||||||
def components(path):
|
|
||||||
if not is_secure_path(os.path.join('static', 'components', path), servepath=os.path.join('static', 'components')):
|
|
||||||
abort(400)
|
|
||||||
return send_from_directory(os.path.join('static', 'components'), path)
|
|
||||||
|
|
||||||
@app.route('/custom-components/<path:path>')
|
|
||||||
def custom_components(path):
|
|
||||||
if not is_secure_path(os.path.join('static', 'custom-components', path), servepath=os.path.join('static', 'custom-components')):
|
|
||||||
abort(400)
|
|
||||||
return send_from_directory(os.path.join('static', 'custom-components'), path)
|
|
||||||
|
|
||||||
|
|
||||||
# Boring stuff
|
|
||||||
@app.errorhandler(400)
|
|
||||||
def bad_request(e):
|
|
||||||
return render_template('genericerror.html', message="The request you sent didn't check out."), 400
|
|
||||||
|
|
||||||
@app.errorhandler(403)
|
|
||||||
def forbidden(e):
|
|
||||||
return render_template('403.html'), 403
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def page_not_found(e):
|
def page_not_found(e):
|
||||||
return render_template('404.html'), 404
|
return render_template('404.html'), 404
|
||||||
|
|
|
@ -1,350 +0,0 @@
|
||||||
<!--
|
|
||||||
@license
|
|
||||||
Copyright (c) 2017 Vaadin Ltd.
|
|
||||||
This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<link rel="import" href="../components/polymer/polymer-element.html">
|
|
||||||
<link rel="import" href="../components/vaadin-themable-mixin/vaadin-themable-mixin.html">
|
|
||||||
<link rel="import" href="../components/vaadin-progress-bar/src/vaadin-progress-bar.html">
|
|
||||||
<link rel="import" href="../components/vaadin-upload/src/vaadin-upload-icons.html">
|
|
||||||
<link rel="import" href="../components/clipboard-copy/clipboard-copy.html">
|
|
||||||
<link rel="import" href="../components/paper-tooltip/paper-tooltip.html">
|
|
||||||
|
|
||||||
<dom-module id="vaadin-permalinked-upload-file">
|
|
||||||
<template>
|
|
||||||
<style>
|
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style include="lumo-field-button">
|
|
||||||
:host {
|
|
||||||
padding: var(--lumo-space-s) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(:not(:first-child)) {
|
|
||||||
border-top: 1px solid var(--lumo-contrast-10pct);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="row"] {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="status"],
|
|
||||||
[part="error"] {
|
|
||||||
color: var(--lumo-secondary-text-color);
|
|
||||||
font-size: var(--lumo-font-size-s);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="info"] {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
flex: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="meta"] {
|
|
||||||
width: 0.001px;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="name"] {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="commands"] {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="done-icon"],
|
|
||||||
[part="warning-icon"] {
|
|
||||||
margin-right: var(--lumo-space-xs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When both icons are hidden, let us keep space for one */
|
|
||||||
[part="done-icon"][hidden] + [part="warning-icon"][hidden] {
|
|
||||||
display: block !important;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="done-icon"],
|
|
||||||
[part="warning-icon"] {
|
|
||||||
font-size: var(--lumo-icon-size-m);
|
|
||||||
font-family: 'lumo-icons';
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="start-button"],
|
|
||||||
[part="retry-button"],
|
|
||||||
[part="clear-button"],
|
|
||||||
[part="copy-button"] {
|
|
||||||
flex: none;
|
|
||||||
margin-left: var(--lumo-space-xs);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="done-icon"]::before,
|
|
||||||
[part="warning-icon"]::before,
|
|
||||||
[part="start-button"]::before,
|
|
||||||
[part="retry-button"]::before,
|
|
||||||
[part="clear-button"]::before,
|
|
||||||
[part="copy-button"] i {
|
|
||||||
vertical-align: -.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="done-icon"]::before {
|
|
||||||
content: var(--lumo-icons-checkmark);
|
|
||||||
color: var(--lumo-primary-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="warning-icon"]::before {
|
|
||||||
content: var(--lumo-icons-error);
|
|
||||||
color: var(--lumo-error-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="start-button"]::before {
|
|
||||||
content: var(--lumo-icons-play);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="retry-button"]::before {
|
|
||||||
content: var(--lumo-icons-reload);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="clear-button"]::before {
|
|
||||||
content: var(--lumo-icons-cross);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="error"] {
|
|
||||||
color: var(--lumo-error-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="progress"] {
|
|
||||||
width: auto;
|
|
||||||
margin-left: calc(var(--lumo-icon-size-m) + var(--lumo-space-xs));
|
|
||||||
margin-right: calc(var(--lumo-icon-size-m) + var(--lumo-space-xs));
|
|
||||||
}
|
|
||||||
|
|
||||||
[part="progress"][complete],
|
|
||||||
[part="progress"][error] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div part="row">
|
|
||||||
<div part="info">
|
|
||||||
<div part="done-icon" hidden$="[[!file.complete]]"></div>
|
|
||||||
<div part="warning-icon" hidden$="[[!file.error]]"></div>
|
|
||||||
<slot name="custom-icon"></slot>
|
|
||||||
|
|
||||||
<div part="meta">
|
|
||||||
<div part="name" id="name">[[file.name]]</div>
|
|
||||||
<div part="status" hidden$="[[!file.url]]" id="status">Avalible at <a href="[[file.url]]">[[file.url]]</a></div>
|
|
||||||
<div part="error" id="error" hidden$="[[!file.error]]">[[_errorOrMessage(file.error, file.message)]]</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div part="commands">
|
|
||||||
<div part="start-button" file-event="file-start" on-click="_fireFileEvent" hidden$="[[!file.held]]"></div>
|
|
||||||
<div part="retry-button" file-event="file-retry" on-click="_fireFileEvent" hidden$="[[!file.error]]"></div>
|
|
||||||
<div part="clear-button" file-event="file-abort" on-click="_fireFileEvent" hidden$="[[file.complete]]"></div>
|
|
||||||
<div part="copy-button" on-click="_copyUrl" hidden$="[[!file.complete]]">
|
|
||||||
<clipboard-copy id="clipboardomatic" content="[[file.url]]"></clipboard-copy>
|
|
||||||
<i class="material-icons">file_copy</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<paper-tooltip id="copied_notif" for="copy-button" position="right">Copied to clipboard</paper-tooltip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<vaadin-progress-bar
|
|
||||||
part="progress"
|
|
||||||
id="progress"
|
|
||||||
value$="[[_formatProgressValue(file.progress)]]"
|
|
||||||
error$="[[file.error]]"
|
|
||||||
indeterminate$="[[file.indeterminate]]"
|
|
||||||
uploading$="[[file.uploading]]"
|
|
||||||
complete$="[[file.complete]]"
|
|
||||||
hidden$="[[file.complete]]">
|
|
||||||
</vaadin-progress-bar>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* `<vaadin-permalinked-upload-file>` element represents a file in the file list of `<vaadin-upload>`.
|
|
||||||
*
|
|
||||||
* ### Styling
|
|
||||||
*
|
|
||||||
* The following shadow DOM parts are available for styling:
|
|
||||||
*
|
|
||||||
* Part name | Description
|
|
||||||
* ---|---
|
|
||||||
* `row` | File container
|
|
||||||
* `info` | Container for file status icon, file name, status and error messages
|
|
||||||
* `done-icon` | File done status icon
|
|
||||||
* `warning-icon` | File warning status icon
|
|
||||||
* `meta` | Container for file name, status and error messages
|
|
||||||
* `name` | File name
|
|
||||||
* `error` | Error message, shown when error happens
|
|
||||||
* `status` | Status message
|
|
||||||
* `commands` | Container for file command icons
|
|
||||||
* `start-button` | Start file upload button
|
|
||||||
* `retry-button` | Retry file upload button
|
|
||||||
* `clear-button` | Clear file button
|
|
||||||
* `progress`| Progress bar
|
|
||||||
*
|
|
||||||
* The following state attributes are available for styling:
|
|
||||||
*
|
|
||||||
* Attribute | Description | Part name
|
|
||||||
* ---|---|---
|
|
||||||
* `error` | An error has happened during uploading | `:host`
|
|
||||||
* `indeterminate` | Uploading is in progress, but the progress value is unknown | `:host`
|
|
||||||
* `uploading` | Uploading is in progress | `:host`
|
|
||||||
* `complete` | Uploading has finished successfully | `:host`
|
|
||||||
*
|
|
||||||
* See [ThemableMixin – how to apply styles for shadow parts](https://github.com/vaadin/vaadin-themable-mixin/wiki)
|
|
||||||
*
|
|
||||||
* @memberof Vaadin
|
|
||||||
* @mixes Vaadin.ThemableMixin
|
|
||||||
* @demo demo/index.html
|
|
||||||
*/
|
|
||||||
class PermalinkedUploadFileElement extends Vaadin.ThemableMixin(Polymer.Element) {
|
|
||||||
static get is() {
|
|
||||||
return 'vaadin-permalinked-upload-file';
|
|
||||||
}
|
|
||||||
|
|
||||||
static get properties() {
|
|
||||||
return {
|
|
||||||
file: Object
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static get observers() {
|
|
||||||
return [
|
|
||||||
'_fileAborted(file.abort)',
|
|
||||||
'_toggleHostAttribute(file.error, "error")',
|
|
||||||
'_toggleHostAttribute(file.indeterminate, "indeterminate")',
|
|
||||||
'_toggleHostAttribute(file.uploading, "uploading")',
|
|
||||||
'_toggleHostAttribute(file.complete, "complete")',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
_copyUrl(event) {
|
|
||||||
var success = this.$.clipboardomatic.copy();
|
|
||||||
if (success) {
|
|
||||||
var notif = this.$.copied_notif;
|
|
||||||
notif.show();
|
|
||||||
window.setTimeout(function() {
|
|
||||||
notif.hide();
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_errorOrMessage(error, message) {
|
|
||||||
if (message) {
|
|
||||||
return message;
|
|
||||||
} else {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_fileAborted(abort) {
|
|
||||||
if (abort) {
|
|
||||||
this._remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_remove() {
|
|
||||||
this.dispatchEvent(
|
|
||||||
new CustomEvent('file-remove', {
|
|
||||||
detail: {file: this.file},
|
|
||||||
bubbles: true,
|
|
||||||
composed: true
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_formatProgressValue(progress) {
|
|
||||||
return progress / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
_fireFileEvent(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
return this.dispatchEvent(
|
|
||||||
new CustomEvent(e.target.getAttribute('file-event'), {
|
|
||||||
detail: {file: this.file},
|
|
||||||
bubbles: true,
|
|
||||||
composed: true
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_toggleHostAttribute(value, attributeName) {
|
|
||||||
const shouldHave = Boolean(value);
|
|
||||||
const has = this.hasAttribute(attributeName);
|
|
||||||
if (has !== shouldHave) {
|
|
||||||
if (shouldHave) {
|
|
||||||
this.setAttribute(attributeName, '');
|
|
||||||
} else {
|
|
||||||
this.removeAttribute(attributeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the retry button is pressed. It is listened by `vaadin-upload`
|
|
||||||
* which will start a new upload process of this file.
|
|
||||||
*
|
|
||||||
* @event file-retry
|
|
||||||
* @param {Object} detail
|
|
||||||
* @param {Object} detail.file file to retry upload of
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when the start button is pressed. It is listened by `vaadin-upload`
|
|
||||||
* which will start a new upload process of this file.
|
|
||||||
*
|
|
||||||
* @event file-start
|
|
||||||
* @param {Object} detail
|
|
||||||
* @param {Object} detail.file file to start upload of
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired when abort button is pressed. It is listened by `vaadin-upload` which
|
|
||||||
* will abort the upload in progress, but will not remove the file from the list
|
|
||||||
* to allow the animation to hide the element to be run.
|
|
||||||
*
|
|
||||||
* @event file-abort
|
|
||||||
* @param {Object} detail
|
|
||||||
* @param {Object} detail.file file to abort upload of
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fired after the animation to hide the element has finished. It is listened
|
|
||||||
* by `vaadin-upload` which will actually remove the file from the upload
|
|
||||||
* file list.
|
|
||||||
*
|
|
||||||
* @event file-remove
|
|
||||||
* @param {Object} detail
|
|
||||||
* @param {Object} detail.file file to remove from the upload of
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define(PermalinkedUploadFileElement.is, PermalinkedUploadFileElement);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @namespace Vaadin
|
|
||||||
*/
|
|
||||||
window.Vaadin = window.Vaadin || {};
|
|
||||||
Vaadin.PermalinkedUploadFileElement = PermalinkedUploadFileElement;
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</dom-module>
|
|
|
@ -60,7 +60,7 @@ body {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type=file]) {
|
input {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
background-color: var(--secondary-background-color);
|
background-color: var(--secondary-background-color);
|
||||||
border-style: none;
|
border-style: none;
|
||||||
|
@ -68,16 +68,6 @@ input:not([type=file]) {
|
||||||
padding: 4px 16px;
|
padding: 4px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=file] {
|
|
||||||
height: 40px;
|
|
||||||
/* background-color: var(--secondary-background-color); */
|
|
||||||
border-style: dashed;
|
|
||||||
border-color: var(--trinary-background-color);
|
|
||||||
border-width: 2px;
|
|
||||||
padding: 4px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
transition: background cubic-bezier(0.4, 0, 0.2, 1) 0.28s;
|
transition: background cubic-bezier(0.4, 0, 0.2, 1) 0.28s;
|
||||||
background-color: var(--secondary-background-color);
|
background-color: var(--secondary-background-color);
|
||||||
|
@ -98,13 +88,12 @@ button:active {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
#referal_form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-top: 32px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form > div {
|
#referal_form > div {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -114,10 +103,9 @@ form > div {
|
||||||
margin: 12px 0px;
|
margin: 12px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form > button {
|
#referal_form > button {
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[disabled] + .checkboxtext {
|
input[disabled] + .checkboxtext {
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||||
<link href="{{ url_for('static', filename='style.css') }}" type="text/css" rel="stylesheet" />
|
<link href="{{ url_for('static', filename='style.css') }}" type="text/css" rel="stylesheet" />
|
||||||
{% block imports %}
|
|
||||||
{% endblock %}
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -25,11 +23,6 @@
|
||||||
<i class="material-icons">person_add</i>
|
<i class="material-icons">person_add</i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if current_user.can_upload and path is not none %}
|
|
||||||
<a class="nostyle iconbutton" href="{{ url_for('upload', path=path) }}" title="Upload to current directory">
|
|
||||||
<i class="material-icons">cloud_upload</i>
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
<p id="headerbar-text">it's not piracy</p>
|
<p id="headerbar-text">it's not piracy</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
{% extends 'skel.html' %}
|
|
||||||
{% block imports %}
|
|
||||||
<script src="{{ url_for('components', path='webcomponentsjs/webcomponents-loader.js') }}"></script>
|
|
||||||
<link rel="import" href="{{ url_for('components', path='polymer/lib/elements/dom-bind.html') }}">
|
|
||||||
<link rel="import" href="{{ url_for('components', path='polymer/lib/elements/dom-repeat.html') }}">
|
|
||||||
<link rel="import" href="{{ url_for('components', path='polymer/lib/elements/dom-if.html') }}">
|
|
||||||
<link rel="import" href="{{ url_for('components', path='vaadin-upload/vaadin-upload.html') }}">
|
|
||||||
<link rel="import" href="{{ url_for('custom_components', path='vaadin-permalinked-upload-file.html') }}">
|
|
||||||
<link rel="import" href="{{ url_for('components', path='paper-toggle-button/paper-toggle-button.html') }}">
|
|
||||||
{% endblock %}
|
|
||||||
{% block body %}
|
|
||||||
<div id="mainwrapper">
|
|
||||||
<div id="contentarea">
|
|
||||||
<p id="infohead">
|
|
||||||
Files for the file gods
|
|
||||||
</p>
|
|
||||||
<p id="infodisc">
|
|
||||||
Get your upload on my dude.
|
|
||||||
</p>
|
|
||||||
<form class="noscript" action="" method="POST" enctype="multipart/form-data">
|
|
||||||
<input id="upload_input" name="files" type="file" accept="image/*"></input>
|
|
||||||
<button id="upload_button" type="submit">Upload</button>
|
|
||||||
</form>
|
|
||||||
<dom-bind>
|
|
||||||
<template>
|
|
||||||
<vaadin-upload id="file_upload" files="{%raw%}{{files}}{%endraw%}" target="" method="POST" form-data-name="file" nodrop="[[nodrop]]">
|
|
||||||
<style is="custom-style">
|
|
||||||
[nodrop] [part="upload-button"] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
[nodrop] #addFiles {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div slot="drop-label-icon"></div>
|
|
||||||
<span slot="drop-label" class="font-headline">or drag a file here</span>
|
|
||||||
<div slot="file-list">
|
|
||||||
<template is="dom-repeat" items="[[files]]" as="file">
|
|
||||||
<vaadin-permalinked-upload-file file="[[file]]"></vaadin-permalinked-upload-file>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</vaadin-upload>
|
|
||||||
</template>
|
|
||||||
</dom-bind>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function isES6()
|
|
||||||
{
|
|
||||||
try { Function("() => {};"); return true; }
|
|
||||||
catch(exception) { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('WebComponentsReady', function() {
|
|
||||||
// Remove noscript / dinosaur componenets if both webcomponents and es6 avalible
|
|
||||||
if (isES6()){
|
|
||||||
var noscripts = document.querySelectorAll('.noscript');
|
|
||||||
for (var i = noscripts.length-1; i >= 0; i--){
|
|
||||||
noscripts[i].parentNode.removeChild(noscripts[i]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO: Abort polymer loading to fix IE become ing responsive for a bit
|
|
||||||
}
|
|
||||||
|
|
||||||
var upload = document.querySelector('vaadin-upload#file_upload');
|
|
||||||
var binder = document.querySelector('dom-bind');
|
|
||||||
|
|
||||||
upload.addEventListener('upload-response', function(event) {
|
|
||||||
response = JSON.parse(event.detail.xhr.response);
|
|
||||||
console.log(response);
|
|
||||||
if (response.status == 'success'){
|
|
||||||
event.detail.file.url = response.link;
|
|
||||||
} else {
|
|
||||||
event.detail.file.message = response.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
binder.files = [];
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
Reference in New Issue