Restructure
This commit is contained in:
2
python_flask/.gitignore
vendored
2
python_flask/.gitignore
vendored
@@ -1,3 +1,3 @@
|
|||||||
/__pycache__/
|
__pycache__/
|
||||||
/venv/
|
/venv/
|
||||||
*.sqlite
|
*.sqlite
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
document.body.addEventListener('htmx:responseError', function(evt) {
|
|
||||||
console.log(evt.detail);
|
|
||||||
let detail = evt.detail;
|
|
||||||
let responsecode = detail.xhr.status;
|
|
||||||
if (responsecode == 400 && detail.requestConfig.path === "/list/") {
|
|
||||||
alert(detail.xhr.response)
|
|
||||||
console.log(evt.detail.xhr.repsonse);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// document.body.addEventListener('htmx:beforeRequest', function(evt) {
|
|
||||||
// let detail = evt.detail;
|
|
||||||
// console.log(evt.detail);
|
|
||||||
// return false;
|
|
||||||
// });
|
|
||||||
console.log("Added event listener");
|
|
||||||
55
python_flask/packager/__init__.py
Normal file
55
python_flask/packager/__init__.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import uuid
|
||||||
|
import sqlalchemy
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
from .helpers import *
|
||||||
|
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///./db.sqlite"
|
||||||
|
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
|
from packager.models import *
|
||||||
|
import packager.views
|
||||||
|
|
||||||
|
|
||||||
|
db.create_all()
|
||||||
|
try:
|
||||||
|
db.session.add(
|
||||||
|
PackageList(
|
||||||
|
id="ab2f16c2-d5f5-460b-b149-0fc9eec12887",
|
||||||
|
name="EDC",
|
||||||
|
description="What you always carry",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
db.session.add(
|
||||||
|
PackageList(
|
||||||
|
id="9f3a72cd-7e30-4263-bd52-92fb7bed1242",
|
||||||
|
name="Camping",
|
||||||
|
description="For outdoors",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.add(
|
||||||
|
PackageListItem(
|
||||||
|
id="4c08f0d5-583e-4882-8bea-2b2faab61fff",
|
||||||
|
name="Taschenmesser",
|
||||||
|
description="",
|
||||||
|
packagelist_id="ab2f16c2-d5f5-460b-b149-0fc9eec12887",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.add(
|
||||||
|
PackageListItem(
|
||||||
|
id="f7fe1c35-23c8-4e57-bec0-56212cff940a",
|
||||||
|
name="Geldbeutel",
|
||||||
|
description="",
|
||||||
|
packagelist_id="ab2f16c2-d5f5-460b-b149-0fc9eec12887",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
except sqlalchemy.exc.IntegrityError:
|
||||||
|
pass
|
||||||
105
python_flask/packager/components/NewPackageList.py
Normal file
105
python_flask/packager/components/NewPackageList.py
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import dominate
|
||||||
|
import dominate.tags as t
|
||||||
|
from dominate.util import raw
|
||||||
|
|
||||||
|
from ..helpers import *
|
||||||
|
|
||||||
|
|
||||||
|
def NewPackageList(name=None, description=None, error=False, errormsg=None):
|
||||||
|
assert not (error and not errormsg)
|
||||||
|
with t.form(
|
||||||
|
id="new-pkglist",
|
||||||
|
name="new_pkglist",
|
||||||
|
data_hx_post="/list/",
|
||||||
|
data_hx_target="#pkglist-manager",
|
||||||
|
data_hx_swap="outerHTML",
|
||||||
|
_class=cls("mt-8", "p-5", "border-2", "border-gray-200"),
|
||||||
|
**{"x-on:htmx:before-request": "(e) => submit_enabled || e.preventDefault()"},
|
||||||
|
) as doc:
|
||||||
|
with t.div(_class=cls("mb-5", "flex", "flex-row", "items-center")):
|
||||||
|
t.span(_class=cls("mdi", "mdi-playlist-plus", "text-2xl", "mr-4"))
|
||||||
|
t.p("Add new package list", _class=cls("inline", "text-xl"))
|
||||||
|
with t.div(_class=cls("w-11/12", "mx-auto")):
|
||||||
|
with t.div(_class=cls("pb-8")):
|
||||||
|
with t.div(
|
||||||
|
_class=cls("flex", "flex-row", "justify-center", "items-start")
|
||||||
|
):
|
||||||
|
t.label(
|
||||||
|
"Name",
|
||||||
|
_for="listname",
|
||||||
|
_class=cls("font-bold", "w-1/2", "p-2", "text-center"),
|
||||||
|
)
|
||||||
|
with t.div(_class=cls("w-1/2")):
|
||||||
|
t._input(
|
||||||
|
type="text",
|
||||||
|
id="listname",
|
||||||
|
name="name",
|
||||||
|
**{"value": name} if name is not None else {},
|
||||||
|
data_hx_target="#new-pkglist",
|
||||||
|
data_hx_post="/list/name/validate",
|
||||||
|
data_hx_swap="outerHTML",
|
||||||
|
_class=cls(
|
||||||
|
"block",
|
||||||
|
"w-full",
|
||||||
|
"p-2",
|
||||||
|
"bg-gray-50",
|
||||||
|
"appearance-none" if error else None,
|
||||||
|
"border-2",
|
||||||
|
"border-red-400" if error else "border-gray-300",
|
||||||
|
"rounded",
|
||||||
|
"focus:outline-none",
|
||||||
|
"focus:bg-white",
|
||||||
|
"focus:border-purple-500" if not error else None,
|
||||||
|
),
|
||||||
|
**{
|
||||||
|
"x-on:input": "submit_enabled = $event.srcElement.value.trim().length !== 0;"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
t.p(
|
||||||
|
errormsg, _class=cls("mt-1", "text-red-400", "text-sm")
|
||||||
|
) if error else None
|
||||||
|
with t.div(
|
||||||
|
_class=cls("flex", "flex-row", "justify-center", "items-center", "pb-8")
|
||||||
|
):
|
||||||
|
t.label(
|
||||||
|
"Description",
|
||||||
|
_for="listdesc",
|
||||||
|
_class=cls("font-bold", "w-1/2", "text-center"),
|
||||||
|
)
|
||||||
|
t._input(
|
||||||
|
type="text",
|
||||||
|
id="listdesc",
|
||||||
|
name="description",
|
||||||
|
**{"value": description} if description is not None else {},
|
||||||
|
_class=cls(
|
||||||
|
"block",
|
||||||
|
"w-1/2",
|
||||||
|
"p-2",
|
||||||
|
"bg-gray-50",
|
||||||
|
"appearance-none",
|
||||||
|
"border-2",
|
||||||
|
"border-gray-300",
|
||||||
|
"rounded",
|
||||||
|
"focus:outline-none",
|
||||||
|
"focus:bg-white",
|
||||||
|
"focus:border-purple-500",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
t._input(
|
||||||
|
type="submit",
|
||||||
|
value="Add",
|
||||||
|
**{
|
||||||
|
"x-bind:class": 'submit_enabled ? "" : "cursor-not-allowed opacity-50"'
|
||||||
|
},
|
||||||
|
_class=cls(
|
||||||
|
"py-2",
|
||||||
|
"border-2",
|
||||||
|
"rounded",
|
||||||
|
"border-gray-300",
|
||||||
|
"mx-auto",
|
||||||
|
"w-full",
|
||||||
|
"hover:border-purple-500" if not error else None,
|
||||||
|
"hover:bg-purple-200" if not error else None,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return doc
|
||||||
30
python_flask/packager/components/PackageListManager.py
Normal file
30
python_flask/packager/components/PackageListManager.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import dominate
|
||||||
|
import dominate.tags as t
|
||||||
|
from dominate.util import raw
|
||||||
|
|
||||||
|
from . import NewPackageList, PackageListTable
|
||||||
|
|
||||||
|
from ..helpers import *
|
||||||
|
|
||||||
|
|
||||||
|
class PackageListManager:
|
||||||
|
def __init__(
|
||||||
|
self, pkglists, name=None, description=None, error=False, errormsg=None
|
||||||
|
):
|
||||||
|
assert not (error and not errormsg)
|
||||||
|
with t.div(
|
||||||
|
id="pkglist-manager",
|
||||||
|
_class=cls("p-8", "max-w-xl"),
|
||||||
|
**{
|
||||||
|
"x-data": '{ submit_enabled: document.getElementById("listname").value.trim().length !== 0 }'
|
||||||
|
},
|
||||||
|
) as doc:
|
||||||
|
PackageListTable(pkglists),
|
||||||
|
NewPackageList(
|
||||||
|
name=name, description=description, error=error, errormsg=errormsg
|
||||||
|
)
|
||||||
|
|
||||||
|
self.doc = doc
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
return self.doc.render()
|
||||||
80
python_flask/packager/components/PackageListTable.py
Normal file
80
python_flask/packager/components/PackageListTable.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import dominate
|
||||||
|
import dominate.tags as t
|
||||||
|
from dominate.util import raw
|
||||||
|
|
||||||
|
from ..helpers import *
|
||||||
|
|
||||||
|
|
||||||
|
def PackageListTable(pkglists):
|
||||||
|
doc = t.div(id="packagelist-table")
|
||||||
|
with doc:
|
||||||
|
t.h1("Package Lists", _class=cls("text-2xl", "mb-5"))
|
||||||
|
with t.table(
|
||||||
|
id="packagelist-table",
|
||||||
|
_class=cls(
|
||||||
|
"table",
|
||||||
|
"table-auto",
|
||||||
|
# "border-separate",
|
||||||
|
"border-collapse",
|
||||||
|
"border-spacing-0",
|
||||||
|
"border",
|
||||||
|
"w-full",
|
||||||
|
),
|
||||||
|
):
|
||||||
|
with t.thead(_class=cls("bg-gray-200")):
|
||||||
|
t.tr(
|
||||||
|
t.th("Name", _class=cls("border", "p-2")),
|
||||||
|
t.th("Description", _class=cls("border", "p-2")),
|
||||||
|
t.th(_class=cls("border p-2")),
|
||||||
|
t.th(_class=cls("border p-2")),
|
||||||
|
t.th(_class=cls("border p-2")),
|
||||||
|
_class="h-10",
|
||||||
|
)
|
||||||
|
with t.tbody(data_hx_target="closest tr", data_hx_swap="outerHTML"):
|
||||||
|
for pkglist in pkglists:
|
||||||
|
t.tr(
|
||||||
|
t.td(pkglist.name, _class=cls("border", "px-2")),
|
||||||
|
t.td(str(pkglist.description), _class=cls("border", "px-2")),
|
||||||
|
t.td(
|
||||||
|
t.span(_class=cls("mdi", "mdi-delete", "text-xl")),
|
||||||
|
id="delete-packagelist",
|
||||||
|
data_hx_delete=f"/list/{pkglist.id}",
|
||||||
|
_class=cls(
|
||||||
|
"border",
|
||||||
|
"bg-red-200",
|
||||||
|
"hover:bg-red-400",
|
||||||
|
"cursor-pointer",
|
||||||
|
"w-8",
|
||||||
|
"text-center",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
t.td(
|
||||||
|
t.span(_class=cls("mdi", "mdi-pencil", "text-xl")),
|
||||||
|
id="edit-packagelist",
|
||||||
|
data_hx_post=f"/list/{pkglist.id}/edit",
|
||||||
|
_class=cls(
|
||||||
|
"border",
|
||||||
|
"bg-blue-200",
|
||||||
|
"hover:bg-blue-400",
|
||||||
|
"cursor-pointer",
|
||||||
|
"w-8",
|
||||||
|
"text-center",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
t.td(
|
||||||
|
t.span(_class=cls("mdi", "mdi-arrow-right", "text-xl")),
|
||||||
|
id="edit-packagelist",
|
||||||
|
# data_hx_post=f"/list/{pkglist.id}/edit",
|
||||||
|
_class=cls(
|
||||||
|
"border",
|
||||||
|
"bg-green-200",
|
||||||
|
"hover:bg-green-400",
|
||||||
|
"cursor-pointer",
|
||||||
|
"w-8",
|
||||||
|
"text-center",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_class=cls("h-10", "even:bg-gray-100", "hover:bg-purple-200"),
|
||||||
|
)
|
||||||
|
|
||||||
|
return doc
|
||||||
3
python_flask/packager/components/__init__.py
Normal file
3
python_flask/packager/components/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from .NewPackageList import NewPackageList
|
||||||
|
from .PackageListTable import PackageListTable
|
||||||
|
from .PackageListManager import PackageListManager
|
||||||
2
python_flask/packager/helpers.py
Normal file
2
python_flask/packager/helpers.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
def cls(*args):
|
||||||
|
return " ".join([a for a in args if a is not None])
|
||||||
3
python_flask/packager/js/app.js
Normal file
3
python_flask/packager/js/app.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
document.body.addEventListener('htmx:responseError', function(evt) {
|
||||||
|
console.log(evt.detail);
|
||||||
|
});
|
||||||
19
python_flask/packager/models.py
Normal file
19
python_flask/packager/models.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from . import db
|
||||||
|
|
||||||
|
|
||||||
|
class PackageList(db.Model):
|
||||||
|
__tablename__ = "packagelist"
|
||||||
|
id = db.Column(db.String(36), primary_key=True)
|
||||||
|
name = db.Column(db.Text, unique=True, nullable=False)
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
items = db.relationship("PackageListItem", backref="packagelist", lazy=True)
|
||||||
|
|
||||||
|
|
||||||
|
class PackageListItem(db.Model):
|
||||||
|
__tablename__ = "packagelistitem"
|
||||||
|
id = db.Column(db.String(36), primary_key=True)
|
||||||
|
name = db.Column(db.Text, unique=True, nullable=False)
|
||||||
|
description = db.Column(db.Text)
|
||||||
|
packagelist_id = db.Column(
|
||||||
|
db.String(36), db.ForeignKey("packagelist.id"), nullable=False
|
||||||
|
)
|
||||||
@@ -1,46 +1,18 @@
|
|||||||
import uuid
|
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
from flask import Flask, request, make_response
|
from . import app
|
||||||
|
from .models import *
|
||||||
|
from .helpers import *
|
||||||
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
import uuid
|
||||||
|
import os
|
||||||
|
|
||||||
import dominate
|
import dominate
|
||||||
import dominate.tags as t
|
import dominate.tags as t
|
||||||
from dominate.util import raw
|
from dominate.util import raw
|
||||||
|
|
||||||
|
from .components import PackageListManager
|
||||||
|
|
||||||
app = Flask(__name__)
|
from flask import request, make_response
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///./db.sqlite"
|
|
||||||
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|
||||||
db = SQLAlchemy(app)
|
|
||||||
|
|
||||||
|
|
||||||
class PackageList(db.Model):
|
|
||||||
id = db.Column(db.String(36), primary_key=True)
|
|
||||||
name = db.Column(db.Text, unique=True)
|
|
||||||
description = db.Column(db.Text)
|
|
||||||
|
|
||||||
|
|
||||||
db.create_all()
|
|
||||||
try:
|
|
||||||
db.session.add(
|
|
||||||
PackageList(
|
|
||||||
id="ab2f16c2-d5f5-460b-b149-0fc9eec12887",
|
|
||||||
name="EDC",
|
|
||||||
description="What you always carry",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
db.session.add(
|
|
||||||
PackageList(
|
|
||||||
id="9f3a72cd-7e30-4263-bd52-92fb7bed1242",
|
|
||||||
name="Camping",
|
|
||||||
description="For outdoors",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
except sqlalchemy.exc.IntegrityError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def get_packagelists():
|
def get_packagelists():
|
||||||
@@ -71,202 +43,21 @@ def delete_packagelist(id):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def pkglist_table():
|
|
||||||
pkglists = get_packagelists()
|
|
||||||
doc = t.div(id="packagelist-table")
|
|
||||||
with doc:
|
|
||||||
t.h1("Package Lists", _class=cls("text-2xl", "mb-5"))
|
|
||||||
with t.table(
|
|
||||||
id="packagelist-table",
|
|
||||||
_class=cls(
|
|
||||||
"table",
|
|
||||||
"table-auto",
|
|
||||||
# "border-separate",
|
|
||||||
"border-collapse",
|
|
||||||
"border-spacing-0",
|
|
||||||
"border",
|
|
||||||
"w-full",
|
|
||||||
),
|
|
||||||
):
|
|
||||||
with t.thead(_class=cls("bg-gray-200")):
|
|
||||||
t.tr(
|
|
||||||
t.th("Name", _class=cls("border", "p-2")),
|
|
||||||
t.th("Description", _class=cls("border", "p-2")),
|
|
||||||
t.th(_class=cls("border p-2")),
|
|
||||||
t.th(_class=cls("border p-2")),
|
|
||||||
_class="h-10",
|
|
||||||
)
|
|
||||||
with t.tbody(data_hx_target="closest tr", data_hx_swap="outerHTML"):
|
|
||||||
for pkglist in pkglists:
|
|
||||||
t.tr(
|
|
||||||
t.td(pkglist.name, _class=cls("border", "px-2")),
|
|
||||||
t.td(str(pkglist.description), _class=cls("border", "px-2")),
|
|
||||||
t.td(
|
|
||||||
t.span(_class=cls("mdi", "mdi-delete", "text-xl")),
|
|
||||||
id="delete-packagelist",
|
|
||||||
data_hx_delete=f"/list/{pkglist.id}",
|
|
||||||
_class=cls(
|
|
||||||
"border",
|
|
||||||
"bg-red-200",
|
|
||||||
"hover:bg-red-400",
|
|
||||||
"cursor-pointer",
|
|
||||||
"w-8",
|
|
||||||
"text-center",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
t.td(
|
|
||||||
t.span(_class=cls("mdi", "mdi-pencil", "text-xl")),
|
|
||||||
id="edit-packagelist",
|
|
||||||
data_hx_post=f"/list/{pkglist.id}/edit",
|
|
||||||
_class=cls(
|
|
||||||
"border",
|
|
||||||
"bg-blue-200",
|
|
||||||
"hover:bg-blue-400",
|
|
||||||
"cursor-pointer",
|
|
||||||
"w-8",
|
|
||||||
"text-center",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_class=cls("h-10", "even:bg-gray-100", "hover:bg-purple-200"),
|
|
||||||
)
|
|
||||||
|
|
||||||
return doc
|
|
||||||
|
|
||||||
|
|
||||||
def cls(*args):
|
|
||||||
return " ".join([a for a in args if a is not None])
|
|
||||||
|
|
||||||
|
|
||||||
def new_pkglist_form(name=None, description=None, error=False, errormsg=None):
|
|
||||||
assert not (error and not errormsg)
|
|
||||||
with t.form(
|
|
||||||
id="new-pkglist",
|
|
||||||
name="new_pkglist",
|
|
||||||
data_hx_post="/list/",
|
|
||||||
data_hx_target="#pkglist-manager",
|
|
||||||
data_hx_swap="outerHTML",
|
|
||||||
_class=cls("mt-8", "p-5", "border-2", "border-gray-200"),
|
|
||||||
**{"x-on:htmx:before-request": "(e) => submit_enabled || e.preventDefault()"},
|
|
||||||
) as doc:
|
|
||||||
with t.div(_class=cls("mb-5", "flex", "flex-row", "items-center")):
|
|
||||||
t.span(_class=cls("mdi", "mdi-playlist-plus", "text-2xl", "mr-4"))
|
|
||||||
t.p("Add new package list", _class=cls("inline", "text-xl"))
|
|
||||||
with t.div(_class=cls("w-11/12", "mx-auto")):
|
|
||||||
with t.div(_class=cls("pb-8")):
|
|
||||||
with t.div(
|
|
||||||
_class=cls("flex", "flex-row", "justify-center", "items-start")
|
|
||||||
):
|
|
||||||
t.label(
|
|
||||||
"Name",
|
|
||||||
_for="listname",
|
|
||||||
_class=cls("font-bold", "w-1/2", "p-2", "text-center"),
|
|
||||||
)
|
|
||||||
with t.div(_class=cls("w-1/2")):
|
|
||||||
t._input(
|
|
||||||
type="text",
|
|
||||||
id="listname",
|
|
||||||
name="name",
|
|
||||||
**{"value": name} if name is not None else {},
|
|
||||||
data_hx_target="#new-pkglist",
|
|
||||||
data_hx_post="/list/name/validate",
|
|
||||||
data_hx_swap="outerHTML",
|
|
||||||
_class=cls(
|
|
||||||
"block",
|
|
||||||
"w-full",
|
|
||||||
"p-2",
|
|
||||||
"bg-gray-50",
|
|
||||||
"appearance-none" if error else None,
|
|
||||||
"border-2",
|
|
||||||
"border-red-400" if error else "border-gray-300",
|
|
||||||
"rounded",
|
|
||||||
"focus:outline-none",
|
|
||||||
"focus:bg-white",
|
|
||||||
"focus:border-purple-500" if not error else None,
|
|
||||||
),
|
|
||||||
**{
|
|
||||||
"x-on:input": "submit_enabled = $event.srcElement.value.trim().length !== 0;"
|
|
||||||
},
|
|
||||||
)
|
|
||||||
t.p(
|
|
||||||
errormsg, _class=cls("mt-1", "text-red-400", "text-sm")
|
|
||||||
) if error else None
|
|
||||||
with t.div(
|
|
||||||
_class=cls("flex", "flex-row", "justify-center", "items-center", "pb-8")
|
|
||||||
):
|
|
||||||
t.label(
|
|
||||||
"Description",
|
|
||||||
_for="listdesc",
|
|
||||||
_class=cls("font-bold", "w-1/2", "text-center"),
|
|
||||||
)
|
|
||||||
t._input(
|
|
||||||
type="text",
|
|
||||||
id="listdesc",
|
|
||||||
name="description",
|
|
||||||
**{"value": description} if description is not None else {},
|
|
||||||
_class=cls(
|
|
||||||
"block",
|
|
||||||
"w-1/2",
|
|
||||||
"p-2",
|
|
||||||
"bg-gray-50",
|
|
||||||
"appearance-none",
|
|
||||||
"border-2",
|
|
||||||
"border-gray-300",
|
|
||||||
"rounded",
|
|
||||||
"focus:outline-none",
|
|
||||||
"focus:bg-white",
|
|
||||||
"focus:border-purple-500",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
t._input(
|
|
||||||
type="submit",
|
|
||||||
value="Add",
|
|
||||||
**{
|
|
||||||
"x-bind:class": 'submit_enabled ? "" : "cursor-not-allowed opacity-50"'
|
|
||||||
},
|
|
||||||
_class=cls(
|
|
||||||
"py-2",
|
|
||||||
"border-2",
|
|
||||||
"rounded",
|
|
||||||
"border-gray-300",
|
|
||||||
"mx-auto",
|
|
||||||
"w-full",
|
|
||||||
"hover:border-purple-500" if not error else None,
|
|
||||||
"hover:bg-purple-200" if not error else None,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
return doc
|
|
||||||
|
|
||||||
|
|
||||||
def pkglist_manager(name=None, description=None, error=False, errormsg=None):
|
|
||||||
assert not (error and not errormsg)
|
|
||||||
with t.div(
|
|
||||||
id="pkglist-manager",
|
|
||||||
_class=cls("p-8", "max-w-xl"),
|
|
||||||
**{
|
|
||||||
"x-data": '{ submit_enabled: document.getElementById("listname").value.trim().length !== 0 }'
|
|
||||||
},
|
|
||||||
) as doc:
|
|
||||||
pkglist_table()
|
|
||||||
new_pkglist_form(
|
|
||||||
name=name, description=description, error=error, errormsg=errormsg
|
|
||||||
)
|
|
||||||
return doc
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def root():
|
def root():
|
||||||
doc = dominate.document(title="My cool title")
|
doc = dominate.document(title="My cool title")
|
||||||
with doc.head:
|
with doc.head:
|
||||||
t.script(src="https://unpkg.com/htmx.org@1.7.0")
|
t.script(src="https://unpkg.com/htmx.org@1.7.0")
|
||||||
t.script(src="https://cdn.tailwindcss.com")
|
t.script(src="https://cdn.tailwindcss.com")
|
||||||
t.script(src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js", defer=True)
|
t.script(src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.js", defer=True)
|
||||||
t.link(
|
t.link(
|
||||||
rel="stylesheet",
|
rel="stylesheet",
|
||||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css",
|
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css",
|
||||||
)
|
)
|
||||||
with doc:
|
with doc:
|
||||||
t.script(raw(open("app.js").read()))
|
|
||||||
pkglist_manager()
|
t.script(raw(open(os.path.join(app.root_path, "js/app.js")).read()))
|
||||||
|
PackageListManager(get_packagelists())
|
||||||
|
|
||||||
return make_response(doc.render(), 200)
|
return make_response(doc.render(), 200)
|
||||||
|
|
||||||
@@ -284,8 +75,12 @@ def add_new_list():
|
|||||||
errormsg = f'Name "{name}" already exists'
|
errormsg = f'Name "{name}" already exists'
|
||||||
|
|
||||||
return make_response(
|
return make_response(
|
||||||
pkglist_manager(
|
PackageListManager(
|
||||||
name=name, description=description, error=error, errormsg=errormsg
|
get_packagelists(),
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
error=error,
|
||||||
|
errormsg=errormsg,
|
||||||
).render(),
|
).render(),
|
||||||
200,
|
200,
|
||||||
)
|
)
|
||||||
@@ -361,7 +156,7 @@ def edit_list_submit(id):
|
|||||||
description = request.form["description"]
|
description = request.form["description"]
|
||||||
if len(name) == 0:
|
if len(name) == 0:
|
||||||
with t.tr(id="pkglist-edit-row") as doc:
|
with t.tr(id="pkglist-edit-row") as doc:
|
||||||
with t.td(colspan=2, _class=cls("border-none", "bg-purple-100", "h-10")):
|
with t.td(colspan=3, _class=cls("border-none", "bg-purple-100", "h-10")):
|
||||||
t.p("Name cannot be empty", _class=cls("text-red-400", "text-sm"))
|
t.p("Name cannot be empty", _class=cls("text-red-400", "text-sm"))
|
||||||
with t.div(_class=cls("flex", "flex-row", "h-full")):
|
with t.div(_class=cls("flex", "flex-row", "h-full")):
|
||||||
with t.div(
|
with t.div(
|
||||||
@@ -435,7 +230,7 @@ def edit_list_submit(id):
|
|||||||
except sqlalchemy.exc.IntegrityError:
|
except sqlalchemy.exc.IntegrityError:
|
||||||
with t.tr(id="pkglist-edit-row") as doc:
|
with t.tr(id="pkglist-edit-row") as doc:
|
||||||
with t.td(
|
with t.td(
|
||||||
colspan=2, _class=cls("border-none", "bg-purple-100", "h-10")
|
colspan=3, _class=cls("border-none", "bg-purple-100", "h-10")
|
||||||
):
|
):
|
||||||
t.p(
|
t.p(
|
||||||
f"Name {name} already exists",
|
f"Name {name} already exists",
|
||||||
@@ -546,10 +341,10 @@ def get_edit_list(pkglist):
|
|||||||
_class="h-10",
|
_class="h-10",
|
||||||
id="pkglist-edit-row",
|
id="pkglist-edit-row",
|
||||||
**{
|
**{
|
||||||
"x-data": '{ edit_submit_enabled: document.getElementById("listedit-name").value.trim().length() !== 0 }'
|
"x-data": '{ edit_submit_enabled: document.getElementById("listedit-name").value.trim().length !== 0 }'
|
||||||
},
|
},
|
||||||
) as doc:
|
) as doc:
|
||||||
with t.td(colspan=2, _class=cls("border-none", "bg-purple-100", "h-full")):
|
with t.td(colspan=3, _class=cls("border-none", "bg-purple-100", "h-full")):
|
||||||
with t.div(_class=cls("flex", "flex-row", "h-full")):
|
with t.div(_class=cls("flex", "flex-row", "h-full")):
|
||||||
with t.div(
|
with t.div(
|
||||||
_class=cls(
|
_class=cls(
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
source ./venv/bin/activate
|
source ./venv/bin/activate
|
||||||
|
|
||||||
|
export FLASK_APP=packager
|
||||||
|
export FLASK_ENV=development
|
||||||
|
|
||||||
python3 -m flask run --reload
|
python3 -m flask run --reload
|
||||||
|
|||||||
Reference in New Issue
Block a user