cleanup and setup.py

master
km0 2 years ago
parent 330cf88089
commit 2f7d25bbb7

@ -2,7 +2,22 @@
![frog](cover.jpg)
A way to archive and retrieve all our pads. Now with a fast way to insert new pads without too much effort uiii.
A way to create, archive and retrieve our pads. Now with a fast way to insert new pads without too much effort uiii.
# Features
- Custom categories
- Filter by categories
- Table sorting
- Create new pad if URL is not provided
# TODO
- Setup script
- Search
- Server side rendering?
![lifecycle](lifecycle.jpg)

@ -1,245 +0,0 @@
:root {
--bg: dodgerblue;
--color: white;
}
* {
box-sizing: border-box;
}
html,
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.6;
color: var(--color);
background-color: var(--bg);
}
a {
color: currentColor;
}
.version {
font-size: 18px;
font-weight: normal;
}
input {
color: currentColor;
border: 1px solid currentColor;
outline: none;
padding: 0.4em;
margin: 0;
background: none;
}
input.overview {
width: 60ch;
}
button {
display: inline-block;
background: none;
border: 1px solid currentColor;
border-radius: 50%;
color: currentColor;
line-height: 1rem;
text-align: center;
padding: 0.4em;
cursor: pointer;
}
button.add {
display: inline-block;
width: 2em;
height: 2em;
font-size: 1em;
margin-left: 8px;
}
button.submit {
margin-left: 12px;
padding: 0.6em;
font-size: 1em;
}
button:hover {
background-color: var(--color);
color: var(--bg);
}
*:not(h2) + input {
margin-left: 12px;
}
.app-form {
display: inline-block;
padding-left: 12px;
border-left: 1px solid currentColor;
margin-top: 12px;
margin-bottom: 12px;
}
.app-form h2 {
margin: 0;
font-weight: normal;
}
table {
width: 100%;
}
table a {
text-decoration: none;
}
tr.header {
position: sticky;
top: 0;
background-color: var(--bg);
z-index: 100;
}
th {
text-align: left;
padding: 24px 0;
border-bottom: 1px solid currentColor;
text-transform: capitalize;
font-size: 21px;
user-select: none;
cursor: pointer;
}
td {
padding: 12px;
border-bottom: 1px solid currentColor;
}
td.title {
font-weight: bold;
}
td.overview,
th.overview {
flex-grow: 3;
}
td.overview p {
margin: 0;
}
tr {
position: relative;
transition: transform 0.1s ease-in;
}
tr:hover:not(:first-of-type) {
transition: transform 0.2s ease-out;
transform: translateX(10px);
}
.stretched:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.loading {
font-size: 28px;
}
.grow {
animation: grow 5s;
}
.filter {
padding-left: 12px;
border-left: 1px solid currentColor;
margin-top: 32px;
margin-bottom: 48px;
}
.filter h2 {
font-weight: normal;
margin: 0;
margin-bottom: 8px;
}
.filter ul {
display: flex;
flex-wrap: wrap;
list-style: none;
gap: 8px;
margin: 0;
padding: 0;
}
.filter ul li,
.category {
display: inline-block;
border: 1px solid currentColor;
padding: 0 4px;
user-select: none;
cursor: pointer;
}
.filter .active {
background-color: var(--color);
color: var(--bg);
}
tr {
display: flex;
justify-content: space-between;
}
th,
td {
padding: 12px 12px;
}
th:first-of-type,
td:first-child {
padding-left: 0;
}
th:last-of-type,
td:last-child {
padding-right: 0;
}
th.date,
td.date {
flex-grow: 0.4;
margin-left: auto;
}
tr > * {
flex: 1;
}
td.categories {
align-content: flex-start;
display: flex;
flex-wrap: wrap;
gap: 8px;
height: auto;
}
.categories .category {
border: none;
}
@keyframes grow {
from {
transform: scale(100%);
}
to {
transform: scale(0, 1000%) rotate(1turn);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 KiB

After

Width:  |  Height:  |  Size: 713 KiB

@ -1,5 +1,5 @@
# Flask application to serve the web pages
from flask import Flask, request, redirect, url_for, jsonify
from flask import Flask, request, redirect, url_for, jsonify, render_template
from flask_cors import CORS
# Mediawiki client to interact with the Wiki
@ -14,10 +14,6 @@ import os
from dotenv import load_dotenv
from pathlib import Path
# datetime to work with dates
from datetime import datetime
# load the mediawiki credentials from the shared folder
dotenv_path = Path("/var/www/.mw-credentials")
load_dotenv(dotenv_path=dotenv_path)
@ -47,11 +43,14 @@ app = Flask(__name__)
CORS(app)
# Url prefix for the soupboat
# Url prefix for the soupboat and port
base_url = os.environ.get('BASE_URL', '')
port = os.environ.get('FLASK_RUN_PORT', '')
# Page of the wiki with the pads
padliography = 'Padliography2'
padliography = os.environ.get('PAGE', '')
# register the middleware to prefix all the requests with our base_url
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=base_url)
@ -98,8 +97,13 @@ def get_pads():
return pads
@app.route('/', methods=['GET', 'POST'])
@app.route('/')
def home():
return render_template('home.html')
@app.route('/api/', methods=['GET', 'POST'])
def api():
if request.method == 'POST':
link = request.json.get('link', None)
@ -108,8 +112,8 @@ def home():
categories = request.json.get('categories', '')
date = request.json.get('date', None)
date = datetime.strftime(datetime.strptime(
date, 'yyyy-mm-dd'), 'dd-mm-yyyy')
# date = datetime.strftime(datetime.strptime(
# date, '%Y-%m-%d'), '%d-%m-%Y')
add_pad(link, title, overview, categories, date)
redirect(url_for('home'))
@ -121,4 +125,4 @@ def home():
return jsonify(response)
app.run(port=3147)
app.run(port=port)

@ -0,0 +1,16 @@
from setuptools import find_packages, setup
setup(
name='Padliography',
version='2.0.0',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=[
'flask',
'flask_cors',
'bs4',
'mwclient',
'python-dotenv',
],
)

@ -1,124 +1,245 @@
body {
font-size: 1.5rem;
margin: 0;
background: rgb(255, 244, 235);
:root {
--bg: dodgerblue;
--color: white;
}
.contents {
margin: 32px;
* {
box-sizing: border-box;
}
h1 {
color: #ecab72;
margin: 32px;
text-align: center;
html,
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.6;
color: var(--color);
background-color: var(--bg);
}
a {
color: currentColor;
}
a.stretched-link::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
.version {
font-size: 18px;
font-weight: normal;
}
/* FILTERS */
.tag {
input {
color: currentColor;
border: 1px solid currentColor;
outline: none;
padding: 0.4em;
margin: 0;
background: none;
font-size: 20px;
}
input.overview {
width: 60ch;
}
button {
display: inline-block;
background: none;
border: 1px solid currentColor;
padding: 0 0.5em;
border-radius: 1em;
margin: 4px;
text-transform: capitalize;
user-select: none;
border-radius: 50%;
color: currentColor;
line-height: 1rem;
text-align: center;
padding: 0.4em;
cursor: pointer;
}
transform: translateY(0);
transition: transform 0.4s ease-in;
button.add {
display: inline-block;
width: 2em;
height: 2em;
font-size: 1em;
margin-left: 8px;
}
.tag.active {
background-color: white;
button.submit {
margin-left: 12px;
padding: 0.6em;
font-size: 1em;
}
.tag.active.all {
background: none;
button:hover {
background-color: var(--color);
color: var(--bg);
}
.filters .tag:focus,
.filters .tag:hover {
transform: translateY(-4px);
transition: transform 0.2s ease-out;
*:not(h2) + input {
margin-left: 12px;
}
ul {
padding: 0;
.app-form {
display: inline-block;
padding-left: 12px;
border-left: 1px solid currentColor;
margin-top: 12px;
margin-bottom: 12px;
}
/* TABLE */
.app-form h2 {
margin: 0;
font-weight: normal;
}
table {
border-collapse: collapse;
width: 100%;
}
table a {
text-decoration: none;
}
tr.header {
position: sticky;
top: 0;
background-color: var(--bg);
z-index: 100;
}
th {
text-align: left;
padding: 24px 0;
border-bottom: 1px solid currentColor;
text-transform: capitalize;
font-size: 21px;
user-select: none;
cursor: pointer;
}
td {
padding: 12px;
border-bottom: 1px solid currentColor;
}
td.title {
font-weight: bold;
}
td.overview,
th.overview {
flex-grow: 3;
}
td.overview p {
margin: 0;
}
tr {
/* display: none; */
position: relative;
transition: transform 0.1s ease-in;
}
tr:nth-child(even) {
background-color: rgb(251, 237, 225);
tr:hover:not(:first-of-type) {
transition: transform 0.2s ease-out;
transform: translateX(10px);
}
tr.active {
display: table-row;
.stretched:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
tr:hover {
background-color: rgb(250, 232, 217);
.loading {
font-size: 28px;
}
tr .tag {
cursor: default;
.grow {
animation: grow 5s;
}
tr.header {
display: table-row;
text-align: left;
.filter {
padding-left: 12px;
border-left: 1px solid currentColor;
margin-top: 32px;
margin-bottom: 48px;
}
.categories {
width: 20%;
.filter h2 {
font-weight: normal;
margin: 0;
margin-bottom: 8px;
}
.overview {
font-style: italic;
width: 40%;
.filter ul {
display: flex;
flex-wrap: wrap;
list-style: none;
gap: 8px;
margin: 0;
padding: 0;
}
.date {
width: 14ch;
.filter ul li,
.category {
display: inline-block;
border: 1px solid currentColor;
padding: 0 4px;
user-select: none;
cursor: pointer;
}
form {
margin: 32px;
display: inline-block;
padding: 2rem;
background-color: rgb(250, 232, 217);
border-radius: 50%;
.filter .active {
background-color: var(--color);
color: var(--bg);
}
form h2 {
margin: 0;
margin-bottom: 16px;
font-size: 28px;
tr {
display: flex;
justify-content: space-between;
}
th,
td {
padding: 12px 12px;
}
th:first-of-type,
td:first-child {
padding-left: 0;
}
th:last-of-type,
td:last-child {
padding-right: 0;
}
th.date,
td.date {
flex-grow: 0.4;
margin-left: auto;
}
tr > * {
flex: 1;
}
td.categories {
align-content: flex-start;
display: flex;
flex-wrap: wrap;
gap: 8px;
height: auto;
}
.categories .category {
border: none;
}
@keyframes grow {
from {
transform: scale(100%);
}
to {
transform: scale(0, 1000%) rotate(1turn);
}
}

@ -25,14 +25,14 @@ export default {
link.value = newPad();
}
fetch("https://hub.xpub.nl/soupboat/padliography/", {
fetch("api", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
title: title.value.trim(),
link: link.value,
overview: overview.value,
categories: categories.value,
categories: categories.value.join(", "),
date: date.value,
}),
});

@ -16,11 +16,11 @@ export default {
selected.value.has(tag) ? selected.value.delete(tag) : selected.value.add(tag);
};
// fetch("https://hub.xpub.nl/soupboat/padliography/")
fetch("http://127.0.0.1:3147/")
fetch("api")
.then((res) => res.json())
.then((data) => {
pads.value = data.pads;
pads.value.map(
(pad) =>
(pad.categories = pad.categories

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}" />
<script src="https://unpkg.com/vue@3"></script>
<title>Padliography</title>
</head>
@ -16,8 +16,8 @@
</div>
<script type="module">
import PadForm from "./components/PadForm.js";
import PadTable from "./components/PadTable.js";
import PadForm from "{{url_for('static', filename='js/components/PadForm.js')}}";
import PadTable from "{{url_for('static', filename='js/components/PadTable.js')}}";
const { createApp } = Vue;
Loading…
Cancel
Save