first go about
This commit is contained in:
commit
c8d4d9a660
|
@ -0,0 +1,136 @@
|
|||
from flask import Flask, \
|
||||
render_template as Render,\
|
||||
redirect as Redirect, \
|
||||
url_for as MethodUri, \
|
||||
abort as Abort
|
||||
|
||||
from flask_sqlalchemy import SQLAlchemy as DBM
|
||||
from enum import Enum
|
||||
from time import sleep
|
||||
|
||||
# Init
|
||||
app=Flask(__name__)
|
||||
app.config['SQLALCHEMY_DATABASE_URI']="sqlite:///app.db"
|
||||
DB=DBM(app)
|
||||
|
||||
#Enums
|
||||
class WorkState(Enum):
|
||||
OTHER = 0
|
||||
IDEA = 1
|
||||
CONFIRMED = 2
|
||||
PAID = 3
|
||||
INPROGRESS = 4
|
||||
FINISHED = 5
|
||||
class TxProcessor(Enum):
|
||||
OTHER = 0
|
||||
PAYPAL = 1
|
||||
class TxType(Enum):
|
||||
OTHER = 0
|
||||
NORMAL = 1
|
||||
YCH = 2
|
||||
YCHAUCTION = 3
|
||||
class Currency(Enum):
|
||||
OTHER = 0
|
||||
GBP = 1
|
||||
USD = 2
|
||||
EUR = 3
|
||||
CAD = 4
|
||||
class LinkType(Enum):
|
||||
OTHER = 0
|
||||
WIPSKETCH = 1
|
||||
WIPLINES = 2
|
||||
WIPCOLOUR = 3
|
||||
WIPSHADING = 4
|
||||
WIPOTHER = 5
|
||||
DELIVERABLE = 6
|
||||
FINAL = 7
|
||||
|
||||
#Database stuff
|
||||
class Artist(DB.Model):
|
||||
artist_id = DB.Column(DB.Integer, primary_key=True, nullable=False, unique=True)
|
||||
name = DB.Column(DB.String, nullable=False)
|
||||
social_twitter = DB.Column(DB.String)
|
||||
social_telegram = DB.Column(DB.String)
|
||||
social_mastodon = DB.Column(DB.String)
|
||||
social_furaffinity = DB.Column(DB.String)
|
||||
social_weasyl = DB.Column(DB.String)
|
||||
social_inkbunny = DB.Column(DB.String)
|
||||
social_sofurry = DB.Column(DB.String)
|
||||
social_furrynetwork = DB.Column(DB.String)
|
||||
class Work(DB.Model):
|
||||
work_id = DB.Column(DB.Integer, primary_key=True, nullable=False, unique=True)
|
||||
artist_id = DB.Column(DB.Integer, DB.ForeignKey('artist.artist_id'), nullable=False)
|
||||
state = DB.Column(DB.Enum(WorkState), nullable=False)
|
||||
purchase_type = DB.Column(DB.Enum(TxType),nullable=False)
|
||||
work_desc = DB.Column(DB.String)
|
||||
date_proposed = DB.Column(DB.DateTime)
|
||||
date_accepted = DB.Column(DB.DateTime)
|
||||
date_paid = DB.Column(DB.DateTime)
|
||||
date_inprogress = DB.Column(DB.DateTime)
|
||||
date_completed = DB.Column(DB.DateTime)
|
||||
class WorkLink(DB.Model):
|
||||
link_id = DB.Column(DB.Integer, primary_key=True, nullable=False, unique=True)
|
||||
work_id = DB.Column(DB.Integer, DB.ForeignKey('work.work_id'), nullable=False)
|
||||
linktype = DB.Column(DB.Enum(LinkType), nullable=False)
|
||||
descr = DB.Column(DB.String, nullable=False)
|
||||
uri = DB.Column(DB.String, nullable=False)
|
||||
datetime = DB.Column(DB.DateTime, nullable=False)
|
||||
class Transaction(DB.Model):
|
||||
transaction_id = DB.Column(DB.Integer, primary_key=True, nullable=False, unique=True)
|
||||
artist_id = DB.Column(DB.Integer, DB.ForeignKey('artist.artist_id'), nullable=False)
|
||||
work_id = DB.Column(DB.Integer, DB.ForeignKey('work.work_id'), nullable=False)
|
||||
processor = DB.Column(DB.Enum(TxProcessor), nullable=False)
|
||||
processor_txid = DB.Column(DB.String, unique=True, nullable=False)
|
||||
currency = DB.Column(DB.Enum(Currency), nullable=False)
|
||||
amount = DB.Column(DB.Float, nullable=False)
|
||||
datetime = DB.Column(DB.DateTime, nullable=False)
|
||||
|
||||
|
||||
#Debugging stuff
|
||||
def RecreateDB():
|
||||
DB.drop_all()
|
||||
DB.create_all()
|
||||
def PopulateTestData():
|
||||
RecreateDB()
|
||||
tArtist=Artist(name="test artist 1")
|
||||
DB.session.add(tArtist)
|
||||
DB.session.commit()
|
||||
tWork=Work(artist_id=tArtist.artist_id,
|
||||
state=WorkState.FINISHED, purchase_type=TxType.NORMAL)
|
||||
tWorkTwo=Work(artist_id=tArtist.artist_id,
|
||||
state=WorkState.INPROGRESS, purchase_type=TxType.YCHAUCTION)
|
||||
DB.session.add_all((tWork, tWorkTwo))
|
||||
DB.session.commit()
|
||||
|
||||
#Routes
|
||||
@app.route('/')
|
||||
def index():
|
||||
_idea=Work.query.filter_by(state=WorkState.IDEA).join(Artist)
|
||||
_conf=Work.query.filter(
|
||||
(Work.state==WorkState.CONFIRMED) |
|
||||
(Work.state==WorkState.PAID)).join(Artist)
|
||||
_inp=Work.query.filter_by(state=WorkState.INPROGRESS).join(Artist)
|
||||
_cmp=Work.query.filter_by(state=WorkState.FINISHED).join(Artist)
|
||||
|
||||
return Render("index.html.j2", ideas=_idea, cnfpaid=_conf, inprog=_inp, done=_cmp)
|
||||
|
||||
@app.route('/list/<listname>')
|
||||
def list(listname=None):
|
||||
_p=Work.query.filter_by(state=WorkState.FINISHED)
|
||||
return Render("list.html.j2", workslist=listname, works=_p.all())
|
||||
|
||||
@app.route('/add')
|
||||
def add(): return Render("add.html.j2")
|
||||
|
||||
@app.route('/update', methods=['POST'])
|
||||
def update(): return Redirect(MethodUri('index'))
|
||||
|
||||
@app.route('/work/<id>')
|
||||
def view_work(id=None): return True
|
||||
|
||||
@app.route('/artist/<id>')
|
||||
def view_artist(id=None):
|
||||
_a=Artist.query.filter_by(artist_id=id).first()
|
||||
_w=Work.query.filter_by(artist_id=id).all()
|
||||
_t=Transaction.query.filter_by(artist_id=id).all()
|
||||
return Render("artist.html.j2", ainfo=_a, works=_w, txes=_t)
|
|
@ -0,0 +1,4 @@
|
|||
pup.cloud Commissions
|
||||
components
|
||||
- web frontend (Flask)
|
||||
- storage (SQLite, PG, Maria)
|
|
@ -0,0 +1,3 @@
|
|||
Flask~=1.1.2
|
||||
Flask-SQLAlchemy~=2.4.4
|
||||
Jinja2~=2.11.2
|
|
@ -0,0 +1,87 @@
|
|||
<!doctype html>
|
||||
<html lang="en-GB">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="handheldfriendly" content="true" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="description" content="Furry art commission tracker, written in Flask" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="https://assets.pup.cloud/css/chota.min.css" />
|
||||
<style>
|
||||
:root {
|
||||
--colour-lightpurple: #b58dc5;
|
||||
--colour-lightblue: #94b9e6;
|
||||
--colour-green: #6dca81;
|
||||
--grid-maxWidth: 98%;
|
||||
}
|
||||
hr {
|
||||
height: 0;
|
||||
background-color: unset;
|
||||
}
|
||||
.container {
|
||||
width: inherit;
|
||||
padding: 0;
|
||||
}
|
||||
div.lanes:nth-child(1 of div.lane) {
|
||||
margin-left: inherit;
|
||||
}
|
||||
div.lanes:nth-child(-1 of div.lane) {
|
||||
margin-right: inherit;
|
||||
}
|
||||
.lane {
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--color-darkGrey);
|
||||
}
|
||||
.lane > header {
|
||||
background-color: var(--color-darkGrey);
|
||||
color: white;
|
||||
margin: 0;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.4rem 1rem;
|
||||
}
|
||||
.status-confirming {
|
||||
--card-outline-colour: var(--color-darkGrey);
|
||||
--card-header-colour: var(--card-outline-colour);
|
||||
--card-header-text-colour: white;
|
||||
}
|
||||
.status-confirmed {
|
||||
--card-outline-colour: var(--colour-lightpurple);
|
||||
--card-header-colour: var(--card-outline-colour);
|
||||
--card-header-text-colour: white;
|
||||
}
|
||||
.status-inprogress {
|
||||
--card-outline-colour: var(--colour-lightblue);
|
||||
--card-header-colour: var(--card-outline-colour);
|
||||
--card-header-text-colour: white;
|
||||
}
|
||||
.status-completed {
|
||||
--card-outline-colour: var(--colour-green);
|
||||
--card-header-colour: var(--card-outline-colour);
|
||||
--card-header-text-colour: white;
|
||||
}
|
||||
.lane > .card {
|
||||
margin: 1rem;
|
||||
box-shadow: 0 1px 0 2px var(--card-outline-colour);
|
||||
padding: 0;
|
||||
}
|
||||
.lane > .card > header {
|
||||
background-color: var(--card-header-colour);
|
||||
color: var(--card-header-text-colour);
|
||||
margin: 0;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.4rem 1rem;
|
||||
}
|
||||
.lane > .card > section {
|
||||
padding: 1rem 2rem;
|
||||
}
|
||||
</style>
|
||||
<title>p.c Commissions :: {% block title %}{% endblock %}</title>
|
||||
|
||||
{% block head_more %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{% include "navigation-bar.html.j2" %}
|
||||
{% block page_body %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,48 @@
|
|||
{% extends 'base.html.j2' %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
{% block head_more %}
|
||||
{% endblock %}
|
||||
{% block page_body %}
|
||||
<hr/>
|
||||
<div class="container">
|
||||
<div class="row lanes">
|
||||
<div class="col-3 lane status-confirming">
|
||||
<header>Ideas</header>
|
||||
{% for work in ideas %}
|
||||
<div class="card">
|
||||
<header>{{ work.work_desc }}</header>
|
||||
<section>status {{ work.state.name|title }} and artist {{ work.artist.name }}</section>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-3 lane status-confirmed">
|
||||
<header>Confirmed/Paid</header>
|
||||
{% for work in cnfpaid %}
|
||||
<div class="card">
|
||||
<header>{{ work.work_desc }}</header>
|
||||
<section>status {{ work.state.name|title }} and artist {{ work.artist.name }}</section>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-3 lane status-inprogress">
|
||||
<header>In-Progress</header>
|
||||
{% for work in inprog %}
|
||||
<div class="card">
|
||||
<header>{{ work.work_desc }}</header>
|
||||
<section>status {{ work.state.name|title }} and artist {{ work.artist.name }}</section>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-3 lane status-completed">
|
||||
<header>Completed</header>
|
||||
{% for work in done %}
|
||||
<div class="card">
|
||||
<header>{{ work.work_desc }}</header>
|
||||
<section>status {{ work.state.name|title }} and artist {{ work.artist.name }}</section>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,15 @@
|
|||
{% block nav %}
|
||||
<nav class="nav">
|
||||
<div class="nav-left">
|
||||
<a class="brand" href="/">
|
||||
<img src="https://assets.pup.cloud/img/maffsie_awoo.svg" height=150 alt="" />
|
||||
p.c Commissions
|
||||
</a>
|
||||
<div class="tabs">
|
||||
<a href="/">Home</a>
|
||||
<a href="/add">➕ Add</a>
|
||||
<a href="/completed">Completed</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue