added javascript bits, flask flashing, better routing, ux improvements

main
lza_menace 3 years ago
parent 8e3a6338c7
commit f2701abd82

@ -0,0 +1,2 @@
DATA_FOLDER=/home/yourname/git/github.com/lalanza808/suchwowx/data
SECRET_KEY=mycrazyrandomstring

@ -2,9 +2,10 @@ import ipfsApi
from os import path from os import path
from secrets import token_urlsafe from secrets import token_urlsafe
from json import loads, dumps from json import loads, dumps
from requests.exceptions import HTTPError
from flask import Blueprint, render_template, request, current_app from flask import Blueprint, render_template, request, current_app
from flask import send_from_directory, redirect from flask import send_from_directory, redirect, flash, url_for
from suchwowx.models import Meme from suchwowx.models import Meme
from suchwowx.factory import db from suchwowx.factory import db
@ -21,7 +22,20 @@ def index():
@bp.route('/new', methods=['GET', 'POST']) @bp.route('/new', methods=['GET', 'POST'])
def new(): def new():
meme = None meme = None
form_err = False
try:
client = ipfsApi.Client('127.0.0.1', 5001)
client.add_json({})
except Exception as e:
msg = f'[!] IPFS Error: {e}'
print(msg)
flash(msg, 'error')
if "file" in request.files:
return '<script>window.history.back()</script>'
return redirect(url_for('meta.index'))
if "file" in request.files: if "file" in request.files:
if form_err:
return '<script>window.history.back()</script>'
title = request.form.get('title') title = request.form.get('title')
description = request.form.get('description') description = request.form.get('description')
creator = request.form.get('creator') creator = request.form.get('creator')
@ -65,7 +79,7 @@ def new():
db.session.commit() db.session.commit()
return redirect('/') return redirect('/')
except ConnectionError: except ConnectionError:
print('[!] Unable to connect to local ipfs') flash('[!] Unable to connect to local ipfs', 'error')
except Exception as e: except Exception as e:
print(e) print(e)
return render_template( return render_template(

@ -0,0 +1,46 @@
.noty_theme__relax.noty_bar {
margin: 4px 0;
overflow: hidden;
border-radius: 2px;
position: relative; }
.noty_theme__relax.noty_bar .noty_body {
padding: 10px; }
.noty_theme__relax.noty_bar .noty_buttons {
border-top: 1px solid #e7e7e7;
padding: 5px 10px; }
.noty_theme__relax.noty_type__alert,
.noty_theme__relax.noty_type__notification {
background-color: #fff;
border: 1px solid #dedede;
color: #444; }
.noty_theme__relax.noty_type__warning {
background-color: #FFEAA8;
border: 1px solid #FFC237;
color: #826200; }
.noty_theme__relax.noty_type__warning .noty_buttons {
border-color: #dfaa30; }
.noty_theme__relax.noty_type__error {
background-color: #FF8181;
border: 1px solid #e25353;
color: #FFF; }
.noty_theme__relax.noty_type__error .noty_buttons {
border-color: darkred; }
.noty_theme__relax.noty_type__info,
.noty_theme__relax.noty_type__information {
background-color: #78C5E7;
border: 1px solid #3badd6;
color: #FFF; }
.noty_theme__relax.noty_type__info .noty_buttons,
.noty_theme__relax.noty_type__information .noty_buttons {
border-color: #0B90C4; }
.noty_theme__relax.noty_type__success {
background-color: #BCF5BC;
border: 1px solid #7cdd77;
color: darkgreen; }
.noty_theme__relax.noty_type__success .noty_buttons {
border-color: #50C24E; }

@ -0,0 +1,222 @@
.noty_layout_mixin, #noty_layout__top, #noty_layout__topLeft, #noty_layout__topCenter, #noty_layout__topRight, #noty_layout__bottom, #noty_layout__bottomLeft, #noty_layout__bottomCenter, #noty_layout__bottomRight, #noty_layout__center, #noty_layout__centerLeft, #noty_layout__centerRight {
position: fixed;
margin: 0;
padding: 0;
z-index: 9999999;
-webkit-transform: translateZ(0) scale(1, 1);
transform: translateZ(0) scale(1, 1);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-font-smoothing: subpixel-antialiased;
filter: blur(0);
-webkit-filter: blur(0);
max-width: 90%; }
#noty_layout__top {
top: 0;
left: 5%;
width: 90%; }
#noty_layout__topLeft {
top: 20px;
left: 20px;
width: 325px; }
#noty_layout__topCenter {
top: 5%;
left: 50%;
width: 325px;
-webkit-transform: translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
transform: translate(calc(-50% - .5px)) translateZ(0) scale(1, 1); }
#noty_layout__topRight {
top: 20px;
right: 20px;
width: 325px; }
#noty_layout__bottom {
bottom: 0;
left: 5%;
width: 90%; }
#noty_layout__bottomLeft {
bottom: 20px;
left: 20px;
width: 325px; }
#noty_layout__bottomCenter {
bottom: 5%;
left: 50%;
width: 325px;
-webkit-transform: translate(-webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
transform: translate(calc(-50% - .5px)) translateZ(0) scale(1, 1); }
#noty_layout__bottomRight {
bottom: 20px;
right: 20px;
width: 325px; }
#noty_layout__center {
top: 50%;
left: 50%;
width: 325px;
-webkit-transform: translate(-webkit-calc(-50% - .5px), -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
transform: translate(calc(-50% - .5px), calc(-50% - .5px)) translateZ(0) scale(1, 1); }
#noty_layout__centerLeft {
top: 50%;
left: 20px;
width: 325px;
-webkit-transform: translate(0, -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
transform: translate(0, calc(-50% - .5px)) translateZ(0) scale(1, 1); }
#noty_layout__centerRight {
top: 50%;
right: 20px;
width: 325px;
-webkit-transform: translate(0, -webkit-calc(-50% - .5px)) translateZ(0) scale(1, 1);
transform: translate(0, calc(-50% - .5px)) translateZ(0) scale(1, 1); }
.noty_progressbar {
display: none; }
.noty_has_timeout.noty_has_progressbar .noty_progressbar {
display: block;
position: absolute;
left: 0;
bottom: 0;
height: 3px;
width: 100%;
background-color: #646464;
opacity: 0.2;
filter: alpha(opacity=10); }
.noty_bar {
-webkit-backface-visibility: hidden;
-webkit-transform: translate(0, 0) translateZ(0) scale(1, 1);
-ms-transform: translate(0, 0) scale(1, 1);
transform: translate(0, 0) scale(1, 1);
-webkit-font-smoothing: subpixel-antialiased;
overflow: hidden; }
.noty_effects_open {
opacity: 0;
-webkit-transform: translate(50%);
-ms-transform: translate(50%);
transform: translate(50%);
-webkit-animation: noty_anim_in 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
animation: noty_anim_in 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards; }
.noty_effects_close {
-webkit-animation: noty_anim_out 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
animation: noty_anim_out 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards; }
.noty_fix_effects_height {
-webkit-animation: noty_anim_height 75ms ease-out;
animation: noty_anim_height 75ms ease-out; }
.noty_close_with_click {
cursor: pointer; }
.noty_close_button {
position: absolute;
top: 2px;
right: 2px;
font-weight: bold;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
background-color: rgba(0, 0, 0, 0.05);
border-radius: 2px;
cursor: pointer;
-webkit-transition: all .2s ease-out;
transition: all .2s ease-out; }
.noty_close_button:hover {
background-color: rgba(0, 0, 0, 0.1); }
.noty_modal {
position: fixed;
width: 100%;
height: 100%;
background-color: #000;
z-index: 10000;
opacity: .3;
left: 0;
top: 0; }
.noty_modal.noty_modal_open {
opacity: 0;
-webkit-animation: noty_modal_in .3s ease-out;
animation: noty_modal_in .3s ease-out; }
.noty_modal.noty_modal_close {
-webkit-animation: noty_modal_out .3s ease-out;
animation: noty_modal_out .3s ease-out;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards; }
@-webkit-keyframes noty_modal_in {
100% {
opacity: .3; } }
@keyframes noty_modal_in {
100% {
opacity: .3; } }
@-webkit-keyframes noty_modal_out {
100% {
opacity: 0; } }
@keyframes noty_modal_out {
100% {
opacity: 0; } }
@keyframes noty_modal_out {
100% {
opacity: 0; } }
@-webkit-keyframes noty_anim_in {
100% {
-webkit-transform: translate(0);
transform: translate(0);
opacity: 1; } }
@keyframes noty_anim_in {
100% {
-webkit-transform: translate(0);
transform: translate(0);
opacity: 1; } }
@-webkit-keyframes noty_anim_out {
100% {
-webkit-transform: translate(50%);
transform: translate(50%);
opacity: 0; } }
@keyframes noty_anim_out {
100% {
-webkit-transform: translate(50%);
transform: translate(50%);
opacity: 0; } }
@-webkit-keyframes noty_anim_height {
100% {
height: 0; } }
@keyframes noty_anim_height {
100% {
height: 0; } }
/*# sourceMappingURL=noty.css.map*/
/* Custom */
.noty_body {
text-align: center;
}

@ -0,0 +1,10 @@
up-wrapper{display:inline-block}
up-bounds{position:absolute}.up-focusable-content:focus,.up-focusable-content:focus-visible{outline:0}
.up-request-loader{display:none}up-progress-bar{position:fixed;top:0;left:0;z-index:999999999;height:3px;background-color:#007bff}
up-focus-trap{position:fixed;top:0;left:0;width:0;height:0}up-modal,up-drawer,up-cover,up-modal-backdrop,up-drawer-backdrop,up-modal-viewport,up-drawer-viewport,up-cover-viewport{top:0;left:0;bottom:0;right:0}up-modal-box,up-drawer-box{box-shadow:0 0 10px 1px rgba(0,0,0,0.3)}up-popup{box-shadow:0 0 4px rgba(0,0,0,0.3)}up-modal:focus,up-drawer:focus,up-cover:focus,up-modal-box:focus,up-drawer-box:focus,up-cover-box:focus,up-popup:focus,up-modal:focus-visible,up-drawer:focus-visible,up-cover:focus-visible,up-modal-box:focus-visible,up-drawer-box:focus-visible,up-cover-box:focus-visible,up-popup:focus-visible{outline:none}up-modal,up-drawer,up-cover{z-index:2000;position:fixed}up-modal-backdrop,up-drawer-backdrop{position:absolute;background:rgba(0,0,0,0.4)}up-modal-viewport,up-drawer-viewport,up-cover-viewport{position:absolute;overflow-y:scroll;overflow-x:hidden;overscroll-behavior:contain;text-align:center}up-modal-box,up-drawer-box,up-cover-box,up-popup{display:inline-block;text-align:left;position:relative;box-sizing:border-box;max-width:100%;background-color:#fff;padding:20px;overflow-x:hidden}up-modal-content,up-drawer-content,up-cover-content,up-popup-content{display:block}up-popup{z-index:1000}up-modal-dismiss,up-drawer-dismiss,up-cover-dismiss,up-popup-dismiss{color:#888;position:absolute;top:10px;right:10px;font-size:1.7rem;line-height:0.5}up-modal-viewport{justify-content:center}up-modal[nesting="0"] up-modal-viewport{padding:25px 15px}up-modal[nesting="1"] up-modal-viewport{padding:50px 30px}up-modal[nesting="2"] up-modal-viewport{padding:75px 45px}up-modal[nesting="3"] up-modal-viewport{padding:100px 60px}up-modal[nesting="4"] up-modal-viewport{padding:125px 75px}up-modal[size=small] up-modal-box{width:350px}up-modal[size=medium] up-modal-box{width:650px}up-modal[size=large] up-modal-box{width:1000px}up-modal[size=grow] up-modal-box{width:auto}up-modal[size=full] up-modal-box{width:100%}up-drawer-viewport{text-align:left}up-drawer[position=right] up-drawer-viewport{text-align:right}up-drawer-box{min-height:100vh}up-drawer[size=small] up-drawer-box{width:150px}up-drawer[size=medium] up-drawer-box{width:340px}up-drawer[size=large] up-drawer-box{width:600px}up-drawer[size=grow] up-drawer-box{width:auto}up-drawer[size=full] up-drawer-box{width:100%}up-cover-box{width:100%;min-height:100vh;padding:0}up-popup{padding:15px}up-popup[size=small]{width:180px}up-popup[size=medium]{width:300px}up-popup[size=large]{width:550px}up-popup[size=grow] up-popup{width:auto}up-popup[size=full] up-popup{width:100%}
[up-href],[up-clickable]{cursor:pointer}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,6 @@
<footer style="margin: 0 auto; width: 100%; text-align: center;">
<p>Made by @lza_menace</p>
</footer>
{% include 'includes/scripts.html' %}

@ -2,8 +2,11 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>SuchWowX!</title> <title>SuchWowX!</title>
<script src="https://unpkg.com/unpoly@2.5.0/unpoly.min.js"></script> <script src="/static/js/vendor/unpoly-2.5.0.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/unpoly@2.5.0/unpoly.min.css"> <link rel="stylesheet" href="/static/css/vendor/unpoly-2.5.0.min.css">
<link rel="stylesheet" href="/static/css/bulma.min.css"> <link rel="stylesheet" href="/static/css/bulma.min.css">
<link rel="stylesheet" href="/static/css/bulma.css.map"> <!-- <link rel="stylesheet" href="/static/css/bulma.css.map"> -->
<link rel="stylesheet" href="/static/css/vendor/noty-relax.css" />
<link rel="stylesheet" href="/static/css/vendor/noty.css" />
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
</head> </head>

@ -0,0 +1,20 @@
<script src="/static/js/vendor/noty-3.2.0.js"></script>
<!-- <script src="/static/js/vendor/web3-1.3.6.min.js"></script> -->
<!-- <script src="/static/js/main.js"></script> -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<script type="text/javascript">
{% for category, message in messages %}
{% if category == None %}{% set category = 'info' %}{% endif %}
new Noty({
type: '{{ category }}',
theme: 'relax',
layout: 'topCenter',
text: '{{ message }}',
timeout: 4500
}).show();
{% endfor %}
</script>
{% endif %}
{% endwith %}

@ -10,19 +10,37 @@
<p class="subtitle"> <p class="subtitle">
Memes. <strong>Interplanetary</strong>! Memes. <strong>Interplanetary</strong>!
</p> </p>
<a class="button is-primary" href="{{ url_for('meta.new') }}" up-target=".container">New Meme</a> <a class="button is-primary" href="{{ url_for('meta.new') }}">New Meme</a>
{% if get_flashed_messages(with_categories=true) %}
<p>
</br>
You can run your own local IPFS instance and maintain metadata and artwork,
</br>
try installing the software and running the following:
</p>
<code>$ ipfs daemon</code>
{% endif %}
{% if memes %} {% if memes %}
<div id="memes"> <div id="memes">
{% for meme in memes %} {% for meme in memes %}
<div class="meme" style="padding-top:1em;"> <div class="meme" style="padding-top:1em;">
<p>Meme: <a href="{{ url_for('meta.meme', meme_id=meme.id) }}" up-target=".container">{{ meme }}</a></p> <p>Meme: <a href="{{ url_for('meta.meme', meme_id=meme.id) }}" up-preload up-follow=".container">{{ meme }}</a></p>
<p>Upload path: {{ meme.upload_path }}</p> <p>Upload path: {{ meme.upload_path }}</p>
<p>Meta IPFS: {{ meme.meta_ipfs_hash }}</p> <p>Meta IPFS: {{ meme.meta_ipfs_hash }}</p>
<p>Meme IPFS: {{ meme.meme_ipfs_hash }}</p> <p>Meme IPFS: {{ meme.meme_ipfs_hash }}</p>
<p>Title: {{ meme.title }}</p> <p>Title: {{ meme.title }}</p>
<p>Description: {{ meme.description }}</p> <p>Description: {{ meme.description }}</p>
<p>Creator handle: {{ meme.creator_handle }}</p> <p>Creator handle: {{ meme.creator_handle }}</p>
{% if meme.upload_path.endswith('mp4') %}
<video style="max-height: 60vh!important;max-width:80px;" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop>
<source src="{{ url_for('meta.uploaded_file', filename=meme.upload_path) }}" type="video/mp4">
Your browser does not support the video tag.
</video>
{% else %}
<img src="{{ url_for('meta.uploaded_file', filename=meme.upload_path) }}" width="200px" class="img-fluid" style="" />
{% endif %}
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
@ -30,5 +48,6 @@
</div> </div>
</section> </section>
{% include 'includes/footer.html' %}
</body> </body>
</html> </html>

@ -10,7 +10,7 @@
<p class="subtitle"> <p class="subtitle">
Memes. <strong>Interplanetary</strong>! Memes. <strong>Interplanetary</strong>!
</p> </p>
<a class="button" href="{{ url_for('meta.index') }}" up-target=".container">Go Home</a> <a class="button" href="{{ url_for('meta.index') }}" up-preload up-follow=".container">Go Home</a>
{% if meme %} {% if meme %}
<div id="meme"> <div id="meme">
@ -22,7 +22,14 @@
<p>Title: {{ meme.title }}</p> <p>Title: {{ meme.title }}</p>
<p>Description: {{ meme.description }}</p> <p>Description: {{ meme.description }}</p>
<p>Creator handle: {{ meme.creator_handle }}</p> <p>Creator handle: {{ meme.creator_handle }}</p>
<img src="{{ url_for('meta.uploaded_file', filename=meme.upload_path) }}"> {% if meme.upload_path.endswith('mp4') %}
<video style="max-height: 60vh!important;max-width:100%;" {% if not request.MOBILE %}autoplay{% else %}controls{% endif %} muted loop>
<source src="{{ url_for('meta.uploaded_file', filename=meme.upload_path) }}" type="video/mp4">
Your browser does not support the video tag.
</video>
{% else %}
<img src="{{ url_for('meta.uploaded_file', filename=meme.upload_path) }}"class="img-fluid" style="" />
{% endif %}
</div> </div>
</div> </div>
{% endif %} {% endif %}

@ -10,7 +10,7 @@
<p class="subtitle"> <p class="subtitle">
Memes. <strong>Interplanetary</strong>! Memes. <strong>Interplanetary</strong>!
</p> </p>
<a class="button" href="{{ url_for('meta.index') }}" up-target=".container">Go Back</a> <a class="button" href="{{ url_for('meta.index') }}" up-preload up-follow=".container">Go Back</a>
<form method="POST" enctype="multipart/form-data" class="site-form" id="memeUpload" action="{{ url_for('meta.new') }}" style="padding-top:1.5em;"> <form method="POST" enctype="multipart/form-data" class="site-form" id="memeUpload" action="{{ url_for('meta.new') }}" style="padding-top:1.5em;">
<div class="field"> <div class="field">
@ -52,7 +52,7 @@
<div class="field is-grouped"> <div class="field is-grouped">
<div class="control"> <div class="control">
<button class="button is-primary" up-target=".container">Submit</button> <button class="button is-primary" up-follow=".container">Submit</button>
</div> </div>
</div> </div>
</form> </form>

Loading…
Cancel
Save