From 80b0827308acc189b6e2ffece65c5b84665ea5f1 Mon Sep 17 00:00:00 2001 From: citrons Date: Wed, 23 Jun 2021 19:02:02 +0000 Subject: colors for markdown --- apioforum/mdrender.py | 7 ++++++- apioforum/templates/base.html | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 8c59c42..715617e 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -1,4 +1,5 @@ import bleach +from .csscolors import csscolors allowed_tags = [ 'p', @@ -12,9 +13,13 @@ allowed_tags = [ 'del', 'mark', 'img', - 'marquee' + 'marquee', + 'pulsate' ] +allowed_tags += csscolors +allowed_tags += ("mark" + c for c in csscolors) + allowed_attributes = bleach.sanitizer.ALLOWED_ATTRIBUTES.copy() allowed_attributes.update( img='src', diff --git a/apioforum/templates/base.html b/apioforum/templates/base.html index 637cc09..33e49f6 100644 --- a/apioforum/templates/base.html +++ b/apioforum/templates/base.html @@ -6,6 +6,7 @@ {%block title %}{% endblock %} + -- cgit v1.2.3 From 807ea10167786db8ba7442f77405c55d70d1fd11 Mon Sep 17 00:00:00 2001 From: citrons Date: Wed, 23 Jun 2021 19:26:15 +0000 Subject: color element --- apioforum/mdrender.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 715617e..2a0c9f5 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -14,7 +14,8 @@ allowed_tags = [ 'mark', 'img', 'marquee', - 'pulsate' + 'pulsate', + 'color' ] allowed_tags += csscolors @@ -23,6 +24,7 @@ allowed_tags += ("mark" + c for c in csscolors) allowed_attributes = bleach.sanitizer.ALLOWED_ATTRIBUTES.copy() allowed_attributes.update( img='src', + color='color' ) allowed_tags.extend(bleach.sanitizer.ALLOWED_TAGS) -- cgit v1.2.3 From abe17e8567f9e34f87fe24fd504d9affcf6b8aab Mon Sep 17 00:00:00 2001 From: citrons Date: Wed, 23 Jun 2021 19:46:10 +0000 Subject: add the files that I did not add --- apioforum/csscolors.py | 150 ++++++++++++++++++++ apioforum/static/md-colors.css | 306 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 456 insertions(+) create mode 100644 apioforum/csscolors.py create mode 100644 apioforum/static/md-colors.css diff --git a/apioforum/csscolors.py b/apioforum/csscolors.py new file mode 100644 index 0000000..25bdfdd --- /dev/null +++ b/apioforum/csscolors.py @@ -0,0 +1,150 @@ +csscolors = [ + "black", + "silver", + "gray", + "white", + "maroon", + "red", + "purple", + "fuchsia", + "green", + "lime", + "olive", + "yellow", + "navy", + "blue", + "teal", + "aqua", + "orange", + "aliceblue", + "antiquewhite", + "aquamarine", + "azure", + "beige", + "bisque", + "blanchedalmond", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflowerblue", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkgrey", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategray", + "darkslategrey", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dimgrey", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "greenyellow", + "grey", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrodyellow", + "lightgray", + "lightgreen", + "lightgrey", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategray", + "lightslategrey", + "lightsteelblue", + "lightyellow", + "limegreen", + "linen", + "magenta", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "oldlace", + "olivedrab", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "skyblue", + "slateblue", + "slategray", + "slategrey", + "snow", + "springgreen", + "steelblue", + "tan", + "thistle", + "tomato", + "turquoise", + "violet", + "wheat", + "whitesmoke", + "yellowgreen", + "rebeccapurple" +] diff --git a/apioforum/static/md-colors.css b/apioforum/static/md-colors.css new file mode 100644 index 0000000..e29da0c --- /dev/null +++ b/apioforum/static/md-colors.css @@ -0,0 +1,306 @@ + +pulsate { animation: 2s infinite alternate pulsate; } + +@keyframes pulsate { + from { letter-spacing: normal; } + to { letter-spacing: 1px; } +} + +black { color: black; } +silver { color: silver; } +gray { color: gray; } +white { color: white; } +maroon { color: maroon; } +red { color: red; } +purple { color: purple; } +fuchsia { color: fuchsia; } +green { color: green; } +lime { color: lime; } +olive { color: olive; } +yellow { color: yellow; } +navy { color: navy; } +blue { color: blue; } +teal { color: teal; } +aqua { color: aqua; } +orange { color: orange; } +aliceblue { color: aliceblue; } +antiquewhite { color: antiquewhite; } +aquamarine { color: aquamarine; } +azure { color: azure; } +beige { color: beige; } +bisque { color: bisque; } +blanchedalmond { color: blanchedalmond; } +blueviolet { color: blueviolet; } +brown { color: brown; } +burlywood { color: burlywood; } +cadetblue { color: cadetblue; } +chartreuse { color: chartreuse; } +chocolate { color: chocolate; } +coral { color: coral; } +cornflowerblue { color: cornflowerblue; } +cornsilk { color: cornsilk; } +crimson { color: crimson; } +cyan { color: cyan; } +darkblue { color: darkblue; } +darkcyan { color: darkcyan; } +darkgoldenrod { color: darkgoldenrod; } +darkgray { color: darkgray; } +darkgreen { color: darkgreen; } +darkgrey { color: darkgrey; } +darkkhaki { color: darkkhaki; } +darkmagenta { color: darkmagenta; } +darkolivegreen { color: darkolivegreen; } +darkorange { color: darkorange; } +darkorchid { color: darkorchid; } +darkred { color: darkred; } +darksalmon { color: darksalmon; } +darkseagreen { color: darkseagreen; } +darkslateblue { color: darkslateblue; } +darkslategray { color: darkslategray; } +darkslategrey { color: darkslategrey; } +darkturquoise { color: darkturquoise; } +darkviolet { color: darkviolet; } +deeppink { color: deeppink; } +deepskyblue { color: deepskyblue; } +dimgray { color: dimgray; } +dimgrey { color: dimgrey; } +dodgerblue { color: dodgerblue; } +firebrick { color: firebrick; } +floralwhite { color: floralwhite; } +forestgreen { color: forestgreen; } +gainsboro { color: gainsboro; } +ghostwhite { color: ghostwhite; } +gold { color: gold; } +goldenrod { color: goldenrod; } +greenyellow { color: greenyellow; } +grey { color: grey; } +honeydew { color: honeydew; } +hotpink { color: hotpink; } +indianred { color: indianred; } +indigo { color: indigo; } +ivory { color: ivory; } +khaki { color: khaki; } +lavender { color: lavender; } +lavenderblush { color: lavenderblush; } +lawngreen { color: lawngreen; } +lemonchiffon { color: lemonchiffon; } +lightblue { color: lightblue; } +lightcoral { color: lightcoral; } +lightcyan { color: lightcyan; } +lightgoldenrodyellow { color: lightgoldenrodyellow; } +lightgray { color: lightgray; } +lightgreen { color: lightgreen; } +lightgrey { color: lightgrey; } +lightpink { color: lightpink; } +lightsalmon { color: lightsalmon; } +lightseagreen { color: lightseagreen; } +lightskyblue { color: lightskyblue; } +lightslategray { color: lightslategray; } +lightslategrey { color: lightslategrey; } +lightsteelblue { color: lightsteelblue; } +lightyellow { color: lightyellow; } +limegreen { color: limegreen; } +linen { color: linen; } +magenta { color: magenta; } +mediumaquamarine { color: mediumaquamarine; } +mediumblue { color: mediumblue; } +mediumorchid { color: mediumorchid; } +mediumpurple { color: mediumpurple; } +mediumseagreen { color: mediumseagreen; } +mediumslateblue { color: mediumslateblue; } +mediumspringgreen { color: mediumspringgreen; } +mediumturquoise { color: mediumturquoise; } +mediumvioletred { color: mediumvioletred; } +midnightblue { color: midnightblue; } +mintcream { color: mintcream; } +mistyrose { color: mistyrose; } +moccasin { color: moccasin; } +navajowhite { color: navajowhite; } +oldlace { color: oldlace; } +olivedrab { color: olivedrab; } +orangered { color: orangered; } +orchid { color: orchid; } +palegoldenrod { color: palegoldenrod; } +palegreen { color: palegreen; } +paleturquoise { color: paleturquoise; } +palevioletred { color: palevioletred; } +papayawhip { color: papayawhip; } +peachpuff { color: peachpuff; } +peru { color: peru; } +pink { color: pink; } +plum { color: plum; } +powderblue { color: powderblue; } +rosybrown { color: rosybrown; } +royalblue { color: royalblue; } +saddlebrown { color: saddlebrown; } +salmon { color: salmon; } +sandybrown { color: sandybrown; } +seagreen { color: seagreen; } +seashell { color: seashell; } +sienna { color: sienna; } +skyblue { color: skyblue; } +slateblue { color: slateblue; } +slategray { color: slategray; } +slategrey { color: slategrey; } +snow { color: snow; } +springgreen { color: springgreen; } +steelblue { color: steelblue; } +tan { color: tan; } +thistle { color: thistle; } +tomato { color: tomato; } +turquoise { color: turquoise; } +violet { color: violet; } +wheat { color: wheat; } +whitesmoke { color: whitesmoke; } +yellowgreen { color: yellowgreen; } +rebeccapurple { color: rebeccapurple; } + + +markblack { background-color: black; } +marksilver { background-color: silver; } +markgray { background-color: gray; } +markwhite { background-color: white; } +markmaroon { background-color: maroon; } +markred { background-color: red; } +markpurple { background-color: purple; } +markfuchsia { background-color: fuchsia; } +markgreen { background-color: green; } +marklime { background-color: lime; } +markolive { background-color: olive; } +markyellow { background-color: yellow; } +marknavy { background-color: navy; } +markblue { background-color: blue; } +markteal { background-color: teal; } +markaqua { background-color: aqua; } +markorange { background-color: orange; } +markaliceblue { background-color: aliceblue; } +markantiquewhite { background-color: antiquewhite; } +markaquamarine { background-color: aquamarine; } +markazure { background-color: azure; } +markbeige { background-color: beige; } +markbisque { background-color: bisque; } +markblanchedalmond { background-color: blanchedalmond; } +markblueviolet { background-color: blueviolet; } +markbrown { background-color: brown; } +markburlywood { background-color: burlywood; } +markcadetblue { background-color: cadetblue; } +markchartreuse { background-color: chartreuse; } +markchocolate { background-color: chocolate; } +markcoral { background-color: coral; } +markcornflowerblue { background-color: cornflowerblue; } +markcornsilk { background-color: cornsilk; } +markcrimson { background-color: crimson; } +markcyan { background-color: cyan; } +markdarkblue { background-color: darkblue; } +markdarkcyan { background-color: darkcyan; } +markdarkgoldenrod { background-color: darkgoldenrod; } +markdarkgray { background-color: darkgray; } +markdarkgreen { background-color: darkgreen; } +markdarkgrey { background-color: darkgrey; } +markdarkkhaki { background-color: darkkhaki; } +markdarkmagenta { background-color: darkmagenta; } +markdarkolivegreen { background-color: darkolivegreen; } +markdarkorange { background-color: darkorange; } +markdarkorchid { background-color: darkorchid; } +markdarkred { background-color: darkred; } +markdarksalmon { background-color: darksalmon; } +markdarkseagreen { background-color: darkseagreen; } +markdarkslateblue { background-color: darkslateblue; } +markdarkslategray { background-color: darkslategray; } +markdarkslategrey { background-color: darkslategrey; } +markdarkturquoise { background-color: darkturquoise; } +markdarkviolet { background-color: darkviolet; } +markdeeppink { background-color: deeppink; } +markdeepskyblue { background-color: deepskyblue; } +markdimgray { background-color: dimgray; } +markdimgrey { background-color: dimgrey; } +markdodgerblue { background-color: dodgerblue; } +markfirebrick { background-color: firebrick; } +markfloralwhite { background-color: floralwhite; } +markforestgreen { background-color: forestgreen; } +markgainsboro { background-color: gainsboro; } +markghostwhite { background-color: ghostwhite; } +markgold { background-color: gold; } +markgoldenrod { background-color: goldenrod; } +markgreenyellow { background-color: greenyellow; } +markgrey { background-color: grey; } +markhoneydew { background-color: honeydew; } +markhotpink { background-color: hotpink; } +markindianred { background-color: indianred; } +markindigo { background-color: indigo; } +markivory { background-color: ivory; } +markkhaki { background-color: khaki; } +marklavender { background-color: lavender; } +marklavenderblush { background-color: lavenderblush; } +marklawngreen { background-color: lawngreen; } +marklemonchiffon { background-color: lemonchiffon; } +marklightblue { background-color: lightblue; } +marklightcoral { background-color: lightcoral; } +marklightcyan { background-color: lightcyan; } +marklightgoldenrodyellow { background-color: lightgoldenrodyellow; } +marklightgray { background-color: lightgray; } +marklightgreen { background-color: lightgreen; } +marklightgrey { background-color: lightgrey; } +marklightpink { background-color: lightpink; } +marklightsalmon { background-color: lightsalmon; } +marklightseagreen { background-color: lightseagreen; } +marklightskyblue { background-color: lightskyblue; } +marklightslategray { background-color: lightslategray; } +marklightslategrey { background-color: lightslategrey; } +marklightsteelblue { background-color: lightsteelblue; } +marklightyellow { background-color: lightyellow; } +marklimegreen { background-color: limegreen; } +marklinen { background-color: linen; } +markmagenta { background-color: magenta; } +markmediumaquamarine { background-color: mediumaquamarine; } +markmediumblue { background-color: mediumblue; } +markmediumorchid { background-color: mediumorchid; } +markmediumpurple { background-color: mediumpurple; } +markmediumseagreen { background-color: mediumseagreen; } +markmediumslateblue { background-color: mediumslateblue; } +markmediumspringgreen { background-color: mediumspringgreen; } +markmediumturquoise { background-color: mediumturquoise; } +markmediumvioletred { background-color: mediumvioletred; } +markmidnightblue { background-color: midnightblue; } +markmintcream { background-color: mintcream; } +markmistyrose { background-color: mistyrose; } +markmoccasin { background-color: moccasin; } +marknavajowhite { background-color: navajowhite; } +markoldlace { background-color: oldlace; } +markolivedrab { background-color: olivedrab; } +markorangered { background-color: orangered; } +markorchid { background-color: orchid; } +markpalegoldenrod { background-color: palegoldenrod; } +markpalegreen { background-color: palegreen; } +markpaleturquoise { background-color: paleturquoise; } +markpalevioletred { background-color: palevioletred; } +markpapayawhip { background-color: papayawhip; } +markpeachpuff { background-color: peachpuff; } +markperu { background-color: peru; } +markpink { background-color: pink; } +markplum { background-color: plum; } +markpowderblue { background-color: powderblue; } +markrosybrown { background-color: rosybrown; } +markroyalblue { background-color: royalblue; } +marksaddlebrown { background-color: saddlebrown; } +marksalmon { background-color: salmon; } +marksandybrown { background-color: sandybrown; } +markseagreen { background-color: seagreen; } +markseashell { background-color: seashell; } +marksienna { background-color: sienna; } +markskyblue { background-color: skyblue; } +markslateblue { background-color: slateblue; } +markslategray { background-color: slategray; } +markslategrey { background-color: slategrey; } +marksnow { background-color: snow; } +markspringgreen { background-color: springgreen; } +marksteelblue { background-color: steelblue; } +marktan { background-color: tan; } +markthistle { background-color: thistle; } +marktomato { background-color: tomato; } +markturquoise { background-color: turquoise; } +markviolet { background-color: violet; } +markwheat { background-color: wheat; } +markwhitesmoke { background-color: whitesmoke; } +markyellowgreen { background-color: yellowgreen; } +markrebeccapurple { background-color: rebeccapurple; } -- cgit v1.2.3 From ebe4f5ed73c1bf3641907420c061dfe047e6a9a8 Mon Sep 17 00:00:00 2001 From: citrons Date: Wed, 23 Jun 2021 19:51:08 +0000 Subject: remove the --- apioforum/mdrender.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 2a0c9f5..5f1192b 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -14,8 +14,7 @@ allowed_tags = [ 'mark', 'img', 'marquee', - 'pulsate', - 'color' + 'pulsate' ] allowed_tags += csscolors @@ -23,8 +22,7 @@ allowed_tags += ("mark" + c for c in csscolors) allowed_attributes = bleach.sanitizer.ALLOWED_ATTRIBUTES.copy() allowed_attributes.update( - img='src', - color='color' + img='src' ) allowed_tags.extend(bleach.sanitizer.ALLOWED_TAGS) -- cgit v1.2.3 From d1bb2fa1b24ecaa54e1a9fc0cfd95aaa9a4907c9 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 24 Jun 2021 01:04:11 +0000 Subject: unwideify the trunk as well --- apioforum/static/style.css | 3 --- apioforum/templates/view_forum.html | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index da580bf..bb57513 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -189,9 +189,6 @@ main { max-width: 60ch; margin: auto; } -main.widemain { - max-width: 120ch; -} blockquote { margin-left: 10px; diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index d1489c8..b27088d 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -1,8 +1,7 @@ {% extends 'base.html' %} {% from 'common.html' import ts, tag, disp_user, post_url %} {% block header %}

{% block title %}apioforum{%endblock%}

{%endblock%} -{%block nmcontent%} -
+{%block content%}

welcome to the apioforum

forum rules: do not be a bad person. do not do bad things.

{% if g.user %} @@ -47,5 +46,4 @@ {%endfor%} -
{%endblock%} -- cgit v1.2.3 From 0133b7b7ee1bcde5cd63c48fdb0af25dfb1ffd00 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 19:37:09 +0000 Subject: allowify even more html tags --- apioforum/mdrender.py | 17 ++++++++++++++--- apioforum/static/style.css | 9 +++++++++ apioforum/templates/common.html | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 5f1192b..7dbbf6b 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -14,7 +14,11 @@ allowed_tags = [ 'mark', 'img', 'marquee', - 'pulsate' + 'pulsate', + 'sup','sub', + 'table','thead','tbody','tr','th','td', + 'details','summary', + ] allowed_tags += csscolors @@ -22,7 +26,9 @@ allowed_tags += ("mark" + c for c in csscolors) allowed_attributes = bleach.sanitizer.ALLOWED_ATTRIBUTES.copy() allowed_attributes.update( - img='src' + img=['src','alt','title'], + ol=['start'], + details=['open'], ) allowed_tags.extend(bleach.sanitizer.ALLOWED_TAGS) @@ -30,7 +36,12 @@ allowed_tags.extend(bleach.sanitizer.ALLOWED_TAGS) cleaner = bleach.sanitizer.Cleaner(tags=allowed_tags,attributes=allowed_attributes) import markdown -md = markdown.Markdown(extensions=['pymdownx.tilde','fenced_code']) +md = markdown.Markdown(extensions=[ + 'pymdownx.tilde', + 'fenced_code', + 'tables', + 'pymdownx.details', +]) def render(text): text = md.reset().convert(text) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index bb57513..3815860 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -205,3 +205,12 @@ blockquote { padding: 1px 3px; border: 1px solid black; } + +.md table { + border: 1px solid grey; + border-collapse: collapse; +} +.md table td,.md table th { + border: 1px solid grey; + padding: 4px; +} diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 9301a49..ff20644 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -26,7 +26,7 @@ #{{post.id}} -
+
{{ post.content|md|safe }}
-- cgit v1.2.3 From 871340cd4e071d415b763cff4396be1e57fec28d Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 19:45:15 +0000 Subject: allow md for sup and sub --- apioforum/mdrender.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 7dbbf6b..4e3a891 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -11,6 +11,7 @@ allowed_tags = [ 'h6', 'pre', 'del', + 'ins', 'mark', 'img', 'marquee', @@ -38,6 +39,7 @@ cleaner = bleach.sanitizer.Cleaner(tags=allowed_tags,attributes=allowed_attribut import markdown md = markdown.Markdown(extensions=[ 'pymdownx.tilde', + 'pymdownx.caret', 'fenced_code', 'tables', 'pymdownx.details', -- cgit v1.2.3 From 604f533989840b929549e9c76a7ba707345d4341 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 19:48:05 +0000 Subject: hr --- apioforum/mdrender.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apioforum/mdrender.py b/apioforum/mdrender.py index 4e3a891..52a6e6c 100644 --- a/apioforum/mdrender.py +++ b/apioforum/mdrender.py @@ -19,6 +19,9 @@ allowed_tags = [ 'sup','sub', 'table','thead','tbody','tr','th','td', 'details','summary', + 'hr' + + ] -- cgit v1.2.3 From 3c2a773095e23a75d2fcb1ca92699228313f6715 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 20:02:50 +0000 Subject: view post source button --- apioforum/templates/common.html | 15 ++++++++++----- apioforum/thread.py | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index ff20644..8fcf5fe 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -17,13 +17,18 @@ {% endif %} - {% if buttons and post.author == g.user %} - edit + {% if buttons %} + {% if post.author == g.user %} + edit + delete + {% endif %} delete + href="{{url_for('thread.view_post',post_id=post.id)}}">src {% endif %} - #{{post.id}} + + #{{post.id}}
diff --git a/apioforum/thread.py b/apioforum/thread.py index 4bb3c86..e6d3690 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -84,8 +84,7 @@ def edit_post(post_id): post = db.execute("SELECT * FROM posts WHERE id = ?",(post_id,)).fetchone() if post is None: flash("that post doesn't exist") - # todo: index route - return redirect("/") + return redirect(url_for('index')) if post['author'] != g.user: flash("you can only edit posts that you created") @@ -107,6 +106,19 @@ def edit_post(post_id): else: flash(err) return render_template("edit_post.html",post=post) + +@bp.route("/view_post/") +def view_post(post_id): + db = get_db() + post = db.execute("SELECT * FROM posts WHERE id = ?",(post_id,)).fetchone() + if post is None: + flash("that post doesn't exist") + return redirect(url_for('index')) + + # when we have permissions, insert permissions check here + return render_template("view_post.html",post=post) + + @bp.route("//config",methods=["GET","POST"]) def config_thread(thread_id): -- cgit v1.2.3 From fb3c1f07d6488cfe91f3a5232224ff82e53ec339 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 23:24:21 +0000 Subject: db things, display poll on thread page, start of voting interface --- apioforum/db.py | 26 ++++++++++++++++++++++++++ apioforum/templates/view_thread.html | 22 ++++++++++++++++++++++ apioforum/thread.py | 10 +++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/apioforum/db.py b/apioforum/db.py index e5159db..271ab75 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -84,6 +84,32 @@ CREATE TABLE thread_tags ( ALTER TABLE users ADD COLUMN bio TEXT; ALTER TABLE users ADD COLUMN joined TIMESTAMP; """, +""" +CREATE TABLE polls ( + id INTEGER PRIMARY KEY, + title TEXT NOT NULL +); +ALTER TABLE threads ADD COLUMN poll INTEGER REFERENCES polls(id); + +CREATE TABLE poll_options ( + poll INTEGER NOT NULL REFERENCES polls(id), + text TEXT NOT NULL, + option_idx INTEGER NOT NULL, + PRIMARY KEY ( poll, option_idx ) +); + +CREATE TABLE votes ( + id INTEGER PRIMARY KEY, + user TEXT NOT NULL REFERENCES users(username), + poll INTEGER NOT NULL, + option_idx INTEGER NOT NULL, + time TIMESTAMP NOT NULL, + FOREIGN KEY ( poll, option_idx ) REFERENCES poll_options(poll, option_idx) +); +ALTER TABLE posts ADD COLUMN vote INTEGER REFERENCES votes(id); +""", + + ] def init_db(): diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index fb62880..855f792 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -5,6 +5,14 @@ {% endblock %} {%block content%} +{% if poll %} +

{{poll.title}}

+
    + {%for opt in poll.options%} +
  • #{{opt.option_idx}} - {{opt.text}}
  • + {%endfor%} +
+{% endif %}
{% if g.user == thread.creator %} @@ -27,6 +35,20 @@ {% if g.user %}
+ {% if poll %} +
+ poll: {{poll.title}} +

if you want, you can submit a vote along with this post. if you have previously voted + on this poll, your previous vote will be changed

+ + + {% for opt in poll.options %} +
+ + + {% endfor %} +
+ {% endif %}
{% else %} diff --git a/apioforum/thread.py b/apioforum/thread.py index e6d3690..3dbc32d 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -27,7 +27,15 @@ def view_thread(thread_id): INNER JOIN thread_tags ON thread_tags.tag = tags.id WHERE thread_tags.thread = ? ORDER BY tags.id""",(thread_id,)).fetchall() - return render_template("view_thread.html",posts=posts,thread=thread,tags=tags) + poll = None + if thread['poll'] is not None: + poll_row = db.execute("SELECT * FROM polls where id = ?",(thread['poll'],)).fetchone() + options = db.execute("SELECT * FROM poll_options WHERE poll = ?",(poll_row['id'],)).fetchall() + poll = {} + poll.update(poll_row) + poll['options'] = options + + return render_template("view_thread.html",posts=posts,thread=thread,tags=tags,poll=poll) @bp.route("//create_post", methods=("POST",)) def create_post(thread_id): -- cgit v1.2.3 From 2327776fa7d720f4cf46baa71da78223a185cedc Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 23:27:55 +0000 Subject: fix crash when posting an empty message --- apioforum/thread.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apioforum/thread.py b/apioforum/thread.py index e6d3690..5f4b0af 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -55,7 +55,8 @@ def create_post(thread_id): ) db.commit() flash("post posted postfully") - return redirect(post_jump(thread_id, post_id)) + return redirect(post_jump(thread_id, post_id)) + return redirect(url_for('thread.view_thread',thread_id=thread_id)) @bp.route("/delete_post/", methods=["GET","POST"]) def delete_post(post_id): -- cgit v1.2.3 From 3b31c84972d566bc6de569e1df9e96cf7e239f23 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 25 Jun 2021 23:44:06 +0000 Subject: i will have this here too --- apioforum/templates/view_thread.html | 2 +- apioforum/thread.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index 855f792..d45b36b 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -45,7 +45,7 @@ {% for opt in poll.options %}
- + {% endfor %} {% endif %} diff --git a/apioforum/thread.py b/apioforum/thread.py index 3dbc32d..3e03a67 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -46,6 +46,7 @@ def create_post(thread_id): db = get_db() content = request.form['content'] thread = db.execute("SELECT * FROM threads WHERE id = ?;",(thread_id,)).fetchone() + print(request.form.get('poll')) if len(content.strip()) == 0: flash("you cannot post an empty message") elif not thread: @@ -63,7 +64,8 @@ def create_post(thread_id): ) db.commit() flash("post posted postfully") - return redirect(post_jump(thread_id, post_id)) + return redirect(post_jump(thread_id, post_id)) + return redirect(url_for('thread.view_thread',thread_id=thread_id)) @bp.route("/delete_post/", methods=["GET","POST"]) def delete_post(post_id): -- cgit v1.2.3 From ccb0394a52050f21701c856239f999ede529f71b Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 26 Jun 2021 00:07:10 +0000 Subject: voting now works --- apioforum/db.py | 1 + apioforum/thread.py | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/apioforum/db.py b/apioforum/db.py index 271ab75..1faa167 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -104,6 +104,7 @@ CREATE TABLE votes ( poll INTEGER NOT NULL, option_idx INTEGER NOT NULL, time TIMESTAMP NOT NULL, + current INTEGER NOT NULL, FOREIGN KEY ( poll, option_idx ) REFERENCES poll_options(poll, option_idx) ); ALTER TABLE posts ADD COLUMN vote INTEGER REFERENCES votes(id); diff --git a/apioforum/thread.py b/apioforum/thread.py index 3e03a67..559f9b2 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -37,6 +37,29 @@ def view_thread(thread_id): return render_template("view_thread.html",posts=posts,thread=thread,tags=tags,poll=poll) + + + +def register_vote(thread,pollval): + if pollval is None or pollval == 'dontvote': + return + option_idx = int(pollval) + db = get_db() + cur = db.cursor() + cur.execute(""" + UPDATE votes + SET current = 0 + WHERE poll = ? AND user = ?; + """,(thread['poll'],g.user)) + cur.execute(""" + INSERT INTO votes (user,poll,option_idx,time,current) + VALUES (?,?,?,current_timestamp,1); + """,(g.user,thread['poll'],option_idx)) + vote_id = cur.lastrowid + return vote_id + + + @bp.route("//create_post", methods=("POST",)) def create_post(thread_id): if g.user is None: @@ -46,17 +69,25 @@ def create_post(thread_id): db = get_db() content = request.form['content'] thread = db.execute("SELECT * FROM threads WHERE id = ?;",(thread_id,)).fetchone() - print(request.form.get('poll')) if len(content.strip()) == 0: flash("you cannot post an empty message") elif not thread: flash("that thread does not exist") else: + vote_id = None + if thread['poll'] is not None: + pollval = request.form.get('poll') + try: + vote_id = register_vote(thread,pollval) + except ValueError: + flash("invalid poll form value") + return redirect(url_for('thread.view_thread',thread_id=thread_id)) + cur = db.cursor() - cur.execute( - "INSERT INTO posts (thread,author,content,created) VALUES (?,?,?,current_timestamp);", - (thread_id,g.user,content) - ) + cur.execute(""" + INSERT INTO posts (thread,author,content,created,vote) + VALUES (?,?,?,current_timestamp,?); + """,(thread_id,g.user,content,vote_id)) post_id = cur.lastrowid cur.execute( "UPDATE threads SET updated = current_timestamp WHERE id = ?;", -- cgit v1.2.3 From a1660cad33f03828e2c74d8f083ad6490ea0da7f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 26 Jun 2021 01:05:28 +0000 Subject: displaying of votes on posts --- apioforum/static/style.css | 6 ++++-- apioforum/templates/common.html | 7 ++++++- apioforum/templates/view_thread.html | 20 +++++++++++++++++++- apioforum/thread.py | 26 ++++++++++++++++++-------- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 3815860..6178dd9 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -16,8 +16,8 @@ body { font-family: sans-serif; word-wrap: break-word; } } .post:last-of-type { border-bottom: 1px solid black; } -.post-heading { font-size: smaller; } -.post-heading,a.username { +.post-heading,.post-footer { font-size: smaller; } +.post-heading,.post-footer,a.username { color: hsl(0,0%,25%); } a.username { @@ -32,6 +32,8 @@ a.username { .post-heading-a { margin-left: 0.2em } .post-heading-b { float: right; margin-right: 0.5em } +.post-footer { margin-left: 0.2em; font-style: italic; } + .post-anchor-link { color: hsl(0,0%,25%); } .thread-top-bar, .user-top-bar { diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 8fcf5fe..3321085 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -6,7 +6,7 @@ {{url_for('thread.view_thread', thread_id=post.thread)}}#post_{{post.id}} {%- endmacro %} -{% macro disp_post(post, buttons=False) %} +{% macro disp_post(post, buttons=False, footer=None) %}
@@ -34,6 +34,11 @@
{{ post.content|md|safe }}
+ {% if footer %} + + {% endif %}
{% endmacro %} diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index d45b36b..513ee59 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -29,7 +29,25 @@
{% for post in posts %} - {{ disp_post(post, True) }} + {% if votes[post.id] %} + + {% set vote = votes[post.id] %} + {% set option_idx = vote.option_idx %} + {% set option = poll.options[option_idx-1] %} + + {% set footer %} + {% if vote.current %} + {{post.author}} votes for {{option_idx}}: {{option.text}} + {% else %} + {{post.author}} voted for {{option_idx}}: {{option.text}}, but later changed their vote + {% endif %} + {% endset %} + + {{ disp_post(post, buttons=True, footer=footer) }} + + {% else %} + {{ disp_post(post, buttons=True) }} + {% endif %} {% endfor %}
{% if g.user %} diff --git a/apioforum/thread.py b/apioforum/thread.py index 559f9b2..7d068c4 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -18,10 +18,11 @@ def view_thread(thread_id): if thread is None: abort(404) else: - posts = db.execute( - "SELECT * FROM posts WHERE thread = ? ORDER BY created ASC;", - (thread_id,) - ).fetchall() + posts = db.execute(""" + SELECT * FROM posts + WHERE posts.thread = ? + ORDER BY created ASC; + """,(thread_id,)).fetchall() tags = db.execute( """SELECT tags.* FROM tags INNER JOIN thread_tags ON thread_tags.tag = tags.id @@ -34,11 +35,20 @@ def view_thread(thread_id): poll = {} poll.update(poll_row) poll['options'] = options + votes = {} + # todo: optimise this somehow + for post in posts: + if post['vote'] is not None: + votes[post['id']] = db.execute("SELECT * FROM votes WHERE id = ?",(post['vote'],)).fetchone() - return render_template("view_thread.html",posts=posts,thread=thread,tags=tags,poll=poll) - - - + return render_template( + "view_thread.html", + posts=posts, + thread=thread, + tags=tags, + poll=poll, + votes=votes + ) def register_vote(thread,pollval): if pollval is None or pollval == 'dontvote': -- cgit v1.2.3 From cd8b3aa2c5abd414068c8f9f5edbebab807153eb Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 26 Jun 2021 01:23:58 +0000 Subject: display vote counts (badly) --- apioforum/db.py | 5 ++++- apioforum/templates/view_thread.html | 2 +- apioforum/thread.py | 9 ++++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apioforum/db.py b/apioforum/db.py index 1faa167..67989df 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -109,7 +109,10 @@ CREATE TABLE votes ( ); ALTER TABLE posts ADD COLUMN vote INTEGER REFERENCES votes(id); """, - +""" +CREATE VIEW vote_counts AS + SELECT poll, option_idx, count(*) AS num FROM votes WHERE current GROUP BY option_idx,poll; +""", ] diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index 513ee59..622cf06 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -9,7 +9,7 @@

{{poll.title}}

    {%for opt in poll.options%} -
  • #{{opt.option_idx}} - {{opt.text}}
  • +
  • #{{opt.option_idx}} - {{opt.text}} - {{opt.num or 0}}
  • {%endfor%}
{% endif %} diff --git a/apioforum/thread.py b/apioforum/thread.py index 7d068c4..ec50b3b 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -29,9 +29,16 @@ def view_thread(thread_id): WHERE thread_tags.thread = ? ORDER BY tags.id""",(thread_id,)).fetchall() poll = None + votes = None if thread['poll'] is not None: poll_row = db.execute("SELECT * FROM polls where id = ?",(thread['poll'],)).fetchone() - options = db.execute("SELECT * FROM poll_options WHERE poll = ?",(poll_row['id'],)).fetchall() + options = db.execute(""" + SELECT poll_options.*, vote_counts.num + FROM poll_options + LEFT OUTER JOIN vote_counts ON poll_options.poll = vote_counts.poll + AND poll_options.option_idx = vote_counts.option_idx + WHERE poll_options.poll = ?; + """,(poll_row['id'],)).fetchall() poll = {} poll.update(poll_row) poll['options'] = options -- cgit v1.2.3 From edbd48340de9add59bcf34f312ae036adae8dcfd Mon Sep 17 00:00:00 2001 From: ubq323 Date: Mon, 28 Jun 2021 23:48:33 +0000 Subject: displayation of vote retractions --- apioforum/db.py | 4 +++- apioforum/templates/view_thread.html | 30 ++++++++++++++++++------------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apioforum/db.py b/apioforum/db.py index 67989df..25bda94 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -102,9 +102,11 @@ CREATE TABLE votes ( id INTEGER PRIMARY KEY, user TEXT NOT NULL REFERENCES users(username), poll INTEGER NOT NULL, - option_idx INTEGER NOT NULL, + option_idx INTEGER, time TIMESTAMP NOT NULL, current INTEGER NOT NULL, + is_retraction INTEGER, + CHECK (is_retraction OR (option_idx NOT NULL)), FOREIGN KEY ( poll, option_idx ) REFERENCES poll_options(poll, option_idx) ); ALTER TABLE posts ADD COLUMN vote INTEGER REFERENCES votes(id); diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index 622cf06..b999658 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -33,21 +33,27 @@ {% set vote = votes[post.id] %} {% set option_idx = vote.option_idx %} - {% set option = poll.options[option_idx-1] %} - {% set footer %} - {% if vote.current %} - {{post.author}} votes for {{option_idx}}: {{option.text}} - {% else %} - {{post.author}} voted for {{option_idx}}: {{option.text}}, but later changed their vote - {% endif %} - {% endset %} + {# this is bad but it's going to get refactored anyway #} + {% set footer %} + {% if vote.is_retraction %} + {{post.author}} retracted their vote + {% else %} + {% set option = poll.options[option_idx-1] %} + {% if vote.current %} + {{post.author}} votes for {{option_idx}}: {{option.text}} + {% else %} + {{post.author}} voted for {{option_idx}}: {{option.text}}, but later changed their vote + {% endif %} + {% endif %} - {{ disp_post(post, buttons=True, footer=footer) }} - + {% endset %} + + {{ disp_post(post, buttons=True, footer=footer) }} + {% else %} - {{ disp_post(post, buttons=True) }} - {% endif %} + {{ disp_post(post, buttons=True) }} + {% endif %} {% endfor %}
{% if g.user %} -- cgit v1.2.3 From fecd96342a07589f71cac6fc1d28e2f6d3240cbf Mon Sep 17 00:00:00 2001 From: ubq323 Date: Tue, 29 Jun 2021 00:30:02 +0000 Subject: retraction of votes --- apioforum/templates/view_thread.html | 8 ++++++++ apioforum/thread.py | 25 ++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index b999658..7bf253d 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -64,8 +64,16 @@ poll: {{poll.title}}

if you want, you can submit a vote along with this post. if you have previously voted on this poll, your previous vote will be changed

+ + + {% if has_voted %} +
+ + + {% endif %} + {% for opt in poll.options %}
diff --git a/apioforum/thread.py b/apioforum/thread.py index ec50b3b..ce451ab 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -47,6 +47,12 @@ def view_thread(thread_id): for post in posts: if post['vote'] is not None: votes[post['id']] = db.execute("SELECT * FROM votes WHERE id = ?",(post['vote'],)).fetchone() + + if g.user is None: + has_voted = None + else: + v = db.execute("SELECT * FROM votes WHERE poll = ? AND user = ? AND current AND NOT is_retraction;",(poll['id'],g.user)).fetchone() + has_voted = v is not None return render_template( "view_thread.html", @@ -54,13 +60,21 @@ def view_thread(thread_id): thread=thread, tags=tags, poll=poll, - votes=votes + votes=votes, + has_voted=has_voted, ) def register_vote(thread,pollval): if pollval is None or pollval == 'dontvote': return - option_idx = int(pollval) + + is_retraction = pollval == 'retractvote' + + if is_retraction: + option_idx = None + else: + option_idx = int(pollval) + db = get_db() cur = db.cursor() cur.execute(""" @@ -68,10 +82,11 @@ def register_vote(thread,pollval): SET current = 0 WHERE poll = ? AND user = ?; """,(thread['poll'],g.user)) + cur.execute(""" - INSERT INTO votes (user,poll,option_idx,time,current) - VALUES (?,?,?,current_timestamp,1); - """,(g.user,thread['poll'],option_idx)) + INSERT INTO votes (user,poll,option_idx,time,current,is_retraction) + VALUES (?,?,?,current_timestamp,1,?); + """,(g.user,thread['poll'],option_idx,is_retraction)) vote_id = cur.lastrowid return vote_id -- cgit v1.2.3 From 3aa8279af5247ce34cfab8842afeb404f3864845 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 11 Jul 2021 02:22:52 +0000 Subject: poll creation and deletion ui; polls work now, for some value of 'work' --- apioforum/templates/config_thread.html | 25 +++++++++++ apioforum/thread.py | 80 ++++++++++++++++++++++++++++++++-- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/apioforum/templates/config_thread.html b/apioforum/templates/config_thread.html index b26a73d..2c9804e 100644 --- a/apioforum/templates/config_thread.html +++ b/apioforum/templates/config_thread.html @@ -2,6 +2,7 @@ {% from 'common.html' import tag %} {% block header %}

{% block title %}configure thread '{{thread.title}}'{% endblock %}

{% endblock %} {% block content %} +

thread options

title @@ -27,4 +28,28 @@ cancel + +{% if thread.poll is none %} +

create poll

+
+
+ create poll + + +
+ + +
+

important: once a poll is created, you will not be able to modify it except to delete it entirely

+ +
+{% else %} +

delete poll

+

there is already a poll attached to this thread. you can delete it, which will allow you to create a new one, but this will erase all existing votes and data for the current poll.

+
+ +
+ +{% endif %} + {% endblock %} diff --git a/apioforum/thread.py b/apioforum/thread.py index ce451ab..ec98d89 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -1,8 +1,10 @@ # view posts in thread +import itertools + from flask import ( Blueprint, render_template, abort, request, g, redirect, - url_for, flash + url_for, flash, jsonify ) from .db import get_db @@ -48,7 +50,7 @@ def view_thread(thread_id): if post['vote'] is not None: votes[post['id']] = db.execute("SELECT * FROM votes WHERE id = ?",(post['vote'],)).fetchone() - if g.user is None: + if g.user is None or poll is None: has_voted = None else: v = db.execute("SELECT * FROM votes WHERE poll = ? AND user = ? AND current AND NOT is_retraction;",(poll['id'],g.user)).fetchone() @@ -89,8 +91,78 @@ def register_vote(thread,pollval): """,(g.user,thread['poll'],option_idx,is_retraction)) vote_id = cur.lastrowid return vote_id - - + +@bp.route("//create_poll",methods=["POST"]) +def create_poll(thread_id): + fail = redirect(url_for('thread.config_thread',thread_id=thread_id)) + success = redirect(url_for('thread.view_thread',thread_id=thread_id)) + err = None + db = get_db() + thread = db.execute('select * from threads where id = ?',(thread_id,)).fetchone() + + polltitle = request.form.get('polltitle','').strip() + polloptions = [q.strip() for q in request.form.get('polloptions','').split("\n") if len(q.strip()) > 0] + + if thread is None: + err = "that thread does not exist" + elif g.user is None: + err = "you need to be logged in to do that" + elif g.user != thread['creator']: + err = "you can only create polls on threads that you own" + elif thread['poll'] is not None: + err = "a poll already exists for that thread" + elif not len(polltitle) > 0: + err = "poll title can't be empty" + elif len(polloptions) < 2: + err = "you must provide at least 2 options" + + if err is not None: + flash(err) + return fail + else: + cur = db.cursor() + cur.execute("INSERT INTO polls (title) VALUES (?)",(polltitle,)) + pollid = cur.lastrowid + cur.execute("UPDATE threads SET poll = ? WHERE threads.id = ?",(pollid,thread_id)) + cur.executemany( + "INSERT INTO poll_options (poll,option_idx,text) VALUES (?,?,?)", + zip(itertools.repeat(pollid),range(len(polloptions)),polloptions) + ) + db.commit() + flash("poll created successfully") + return success + +@bp.route("//delete_poll",methods=["POST"]) +def delete_poll(thread_id): + fail = redirect(url_for('thread.config_thread',thread_id=thread_id)) + success = redirect(url_for('thread.view_thread',thread_id=thread_id)) + err = None + db = get_db() + thread = db.execute('select * from threads where id = ?',(thread_id,)).fetchone() + + if thread is None: + err = "that thread does not exist" + elif g.user is None: + err = "you need to be logged in to do that" + elif g.user != thread['creator']: + err = "you can only delete polls on threads that you own" + elif thread['poll'] is None: + err = "there is no poll to delete on this thread" + + if err is not None: + flash(err) + return fail + else: + pollid = thread['poll'] + + db.execute("UPDATE posts SET vote = NULL WHERE thread = ?",(thread_id,)) # this assumes only max one poll per thread + db.execute("DELETE FROM votes WHERE poll = ?",(pollid,)) + db.execute("DELETE FROM poll_options WHERE poll = ?",(pollid,)) + db.execute("UPDATE THREADS set poll = NULL WHERE id = ?",(thread_id,)) + db.execute("DELETE FROM polls WHERE id = ?",(pollid,)) + db.commit() + flash("poll deleted successfully") + return success @bp.route("//create_post", methods=("POST",)) def create_post(thread_id): -- cgit v1.2.3 From 9c375cff4dc60ef1ff0c512f6da028129430e377 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 11 Jul 2021 02:23:20 +0000 Subject: somehow view_post.html never actually ended up in the repo???? --- apioforum/templates/view_post.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 apioforum/templates/view_post.html diff --git a/apioforum/templates/view_post.html b/apioforum/templates/view_post.html new file mode 100644 index 0000000..993c005 --- /dev/null +++ b/apioforum/templates/view_post.html @@ -0,0 +1,12 @@ +{% from 'common.html' import disp_post %} +{% extends 'base.html' %} +{% block header %} +

{%block title%}viewing post{%endblock%}

+{% endblock %} + +{% block content %} +{{disp_post(post,False)}} +

post source:

+ +i am satisfied +{% endblock %} -- cgit v1.2.3 From 94e93dffbc2f23823cfb6949828861063a3f3e23 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 11 Jul 2021 02:42:34 +0000 Subject: fix indexing issue with displaying of votes --- apioforum/thread.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apioforum/thread.py b/apioforum/thread.py index ec98d89..20b02ca 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -39,7 +39,8 @@ def view_thread(thread_id): FROM poll_options LEFT OUTER JOIN vote_counts ON poll_options.poll = vote_counts.poll AND poll_options.option_idx = vote_counts.option_idx - WHERE poll_options.poll = ?; + WHERE poll_options.poll = ? + ORDER BY option_idx asc; """,(poll_row['id'],)).fetchall() poll = {} poll.update(poll_row) @@ -126,7 +127,7 @@ def create_poll(thread_id): cur.execute("UPDATE threads SET poll = ? WHERE threads.id = ?",(pollid,thread_id)) cur.executemany( "INSERT INTO poll_options (poll,option_idx,text) VALUES (?,?,?)", - zip(itertools.repeat(pollid),range(len(polloptions)),polloptions) + zip(itertools.repeat(pollid),range(1,len(polloptions)+1),polloptions) ) db.commit() flash("poll created successfully") -- cgit v1.2.3 From 2eae97d6a08da4b832ccc69ce66bd15009001737 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 11 Jul 2021 02:45:06 +0000 Subject: actually that could be slightly neater --- apioforum/thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apioforum/thread.py b/apioforum/thread.py index 20b02ca..daf0b85 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -127,7 +127,7 @@ def create_poll(thread_id): cur.execute("UPDATE threads SET poll = ? WHERE threads.id = ?",(pollid,thread_id)) cur.executemany( "INSERT INTO poll_options (poll,option_idx,text) VALUES (?,?,?)", - zip(itertools.repeat(pollid),range(1,len(polloptions)+1),polloptions) + zip(itertools.repeat(pollid),itertools.count(1),polloptions) ) db.commit() flash("poll created successfully") -- cgit v1.2.3 From a2c82ca4f96420234460ea5fdea5df37078117d7 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 17 Jul 2021 23:27:37 +0000 Subject: vote meters idk --- apioforum/__init__.py | 3 +++ apioforum/db.py | 4 ++++ apioforum/forum.py | 32 +++++++++++++++++++++++++++-- apioforum/templates/view_forum.html | 40 +++++++++++++++++++++++++++++++++++++ setup.py | 1 + 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/apioforum/__init__.py b/apioforum/__init__.py index 9d49f36..6c9eaa8 100644 --- a/apioforum/__init__.py +++ b/apioforum/__init__.py @@ -40,6 +40,9 @@ def create_app(): from .fuzzy import fuzzy app.jinja_env.filters['fuzzy']=fuzzy + from .util import gen_colour + app.jinja_env.filters['gen_colour']=gen_colour + @app.context_processor def path_for_next(): p = request.path diff --git a/apioforum/db.py b/apioforum/db.py index 25bda94..ba1f6a3 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -115,6 +115,10 @@ ALTER TABLE posts ADD COLUMN vote INTEGER REFERENCES votes(id); CREATE VIEW vote_counts AS SELECT poll, option_idx, count(*) AS num FROM votes WHERE current GROUP BY option_idx,poll; """, +""" +CREATE VIEW total_vote_counts AS + SELECT poll, count(*) AS total_votes FROM votes WHERE current GROUP BY poll; +""", ] diff --git a/apioforum/forum.py b/apioforum/forum.py index fa6fcc8..56811e0 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -19,7 +19,7 @@ def view_forum(): db = get_db() threads = db.execute( """SELECT threads.id, threads.title, threads.creator, threads.created, - threads.updated, count(posts.id) as num_replies, max(posts.id), posts.author as last_user + threads.updated, threads.poll, count(posts.id) as num_replies, max(posts.id), posts.author as last_user FROM threads INNER JOIN posts ON posts.thread = threads.id GROUP BY threads.id @@ -27,6 +27,7 @@ def view_forum(): """).fetchall() thread_tags = {} preview_post = {} + thread_polls = {} #todo: somehow optimise this for thread in threads: thread_tags[thread['id']] = db.execute( @@ -39,10 +40,37 @@ def view_forum(): """SELECT * FROM posts WHERE thread = ? ORDER BY created DESC; """,(thread['id'],)).fetchone() + + if thread['poll'] is not None: + # todo: make this not be duplicated from thread.py + poll_row= db.execute(""" + SELECT polls.*,total_vote_counts.total_votes FROM polls + LEFT OUTER JOIN total_vote_counts ON polls.id = total_vote_counts.poll + WHERE polls.id = ?; + """,(thread['poll'],)).fetchone() + options = db.execute(""" + SELECT poll_options.*, vote_counts.num + FROM poll_options + LEFT OUTER JOIN vote_counts ON poll_options.poll = vote_counts.poll + AND poll_options.option_idx = vote_counts.option_idx + WHERE poll_options.poll = ? + ORDER BY option_idx asc; + """,(poll_row['id'],)).fetchall() + + poll = {} + poll.update(poll_row) + poll['options'] = options + poll['total_votes']=poll['total_votes'] or 0 + thread_polls[thread['id']]=poll + + + + return render_template("view_forum.html", threads=threads, thread_tags=thread_tags, - preview_post=preview_post + preview_post=preview_post, + thread_polls=thread_polls ) @bp.route("/create_thread",methods=("GET","POST")) diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index b27088d..017d9f0 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -43,6 +43,46 @@
{% endif %} + {% if thread_polls[thread.id] %} + {% set poll = thread_polls[thread.id] %} + {% set total_votes = poll.total_votes %} + {% set n = namespace() %} + {% set n.runningtotal = 0 %} + +
+ + {% if total_votes == 0 %} + no votes + {% else %} + {% for opt in poll.options %} + {% set opt_count = opt.num or 0 %} + {% set colour = (loop.count|string + opt.text)|gen_colour %} + {% if opt_count != 0 %} + {% set percentage = 100*(opt_count/total_votes) %} + {# todo: do this in css somehow #} + {% if opt.text|length > 10 %} + {% set opt_text = opt.text[:7] + "..." %} + {% else %} + {% set opt_text = opt.text %} + {% endif %} + + + {{opt_text}}: {{opt_count}} + + {% set n.runningtotal = n.runningtotal + percentage %} + {% endif %} + {% endfor %} + {% endif %} + + poll: {{poll.title}} + {% for opt in poll.options %} + option "{{opt.text}}": {{opt.num}} votes + {% endfor %} + total votes: {{total_votes}} + + +
+ {% endif %}
{%endfor%} diff --git a/setup.py b/setup.py index 089f3a4..15992ed 100644 --- a/setup.py +++ b/setup.py @@ -10,5 +10,6 @@ setup( 'markdown', 'bleach', 'pymdown-extensions', + 'hsluv', ], ) -- cgit v1.2.3 From 589dae7625f7f98ee3d546887792db3dfc90b464 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 13:59:06 +0000 Subject: fix spacing on vote meter --- apioforum/static/style.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 6178dd9..5263568 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -137,6 +137,11 @@ nav .links { display: flex; } .thread-preview-post { font-style: italic; } .thread-preview-ts { font-weight: bold; } +.thread-vote-summary { + margin-top: 4px; + margin-bottom: -8px; +} + /* wide screens */ @media all and (min-width: 600px) { .thread-listing-title { font-size: larger; } -- cgit v1.2.3 From 8d2e7d0f6562f42730b8bc62576f10e7d06e5117 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 14:15:18 +0000 Subject: minor change things --- apioforum/__init__.py | 3 +++ apioforum/templates/view_forum.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apioforum/__init__.py b/apioforum/__init__.py index 6c9eaa8..364bad3 100644 --- a/apioforum/__init__.py +++ b/apioforum/__init__.py @@ -17,6 +17,9 @@ def create_app(): except OSError: pass + app.jinja_env.trim_blocks = True + app.jinja_env.lstrip_blocks = True + from . import db db.init_app(app) from . import permissions diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index 017d9f0..2e49a41 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -76,7 +76,7 @@ poll: {{poll.title}} {% for opt in poll.options %} - option "{{opt.text}}": {{opt.num}} votes + option "{{opt.text}}": {{opt.num or 0}} votes {% endfor %} total votes: {{total_votes}} -- cgit v1.2.3 From 153ac274490c08375d58fa83042406c6ec52f968 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 14:38:07 +0000 Subject: vote meter on view thread page --- apioforum/forum.py | 2 +- apioforum/templates/common.html | 37 ++++++++++++++++++++++++++++++++++ apioforum/templates/view_forum.html | 39 ++---------------------------------- apioforum/templates/view_thread.html | 3 ++- apioforum/thread.py | 6 +++++- 5 files changed, 47 insertions(+), 40 deletions(-) diff --git a/apioforum/forum.py b/apioforum/forum.py index 56811e0..1da6d27 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -45,7 +45,7 @@ def view_forum(): # todo: make this not be duplicated from thread.py poll_row= db.execute(""" SELECT polls.*,total_vote_counts.total_votes FROM polls - LEFT OUTER JOIN total_vote_counts ON polls.id = total_vote_counts.poll + LEFT OUTER JOIN total_vote_counts ON polls.id = total_vote_counts.poll WHERE polls.id = ?; """,(thread['poll'],)).fetchone() options = db.execute(""" diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 3321085..c8afd9e 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -49,3 +49,40 @@ {% macro tag(the_tag) -%} {{the_tag.name}} {%- endmacro %} + +{% macro vote_meter(poll) %} + {% set total_votes = poll.total_votes %} + {% set n = namespace() %} + {% set n.runningtotal = 0 %} + + {% if total_votes == 0 %} + no votes + {% else %} + {% for opt in poll.options %} + {% set opt_count = opt.num or 0 %} + {% set colour = (loop.count|string + opt.text)|gen_colour %} + {% if opt_count != 0 %} + {% set percentage = 100*(opt_count/total_votes) %} + {# todo: do this in css somehow #} + {% if opt.text|length > 10 %} + {% set opt_text = opt.text[:7] + "..." %} + {% else %} + {% set opt_text = opt.text %} + {% endif %} + + + {{opt_text}}: {{opt_count}} + + {% set n.runningtotal = n.runningtotal + percentage %} + {% endif %} + {% endfor %} + {% endif %} + + poll: {{poll.title}} + {% for opt in poll.options %} + option "{{opt.text}}": {{opt.num or 0}} votes + {% endfor %} + total votes: {{total_votes}} + + +{% endmacro %} diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index 2e49a41..e8d4f8a 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% from 'common.html' import ts, tag, disp_user, post_url %} +{% from 'common.html' import ts, tag, disp_user, post_url, vote_meter %} {% block header %}

{% block title %}apioforum{%endblock%}

{%endblock%} {%block content%}

welcome to the apioforum

@@ -44,43 +44,8 @@ {% endif %} {% if thread_polls[thread.id] %} - {% set poll = thread_polls[thread.id] %} - {% set total_votes = poll.total_votes %} - {% set n = namespace() %} - {% set n.runningtotal = 0 %} -
- - {% if total_votes == 0 %} - no votes - {% else %} - {% for opt in poll.options %} - {% set opt_count = opt.num or 0 %} - {% set colour = (loop.count|string + opt.text)|gen_colour %} - {% if opt_count != 0 %} - {% set percentage = 100*(opt_count/total_votes) %} - {# todo: do this in css somehow #} - {% if opt.text|length > 10 %} - {% set opt_text = opt.text[:7] + "..." %} - {% else %} - {% set opt_text = opt.text %} - {% endif %} - - - {{opt_text}}: {{opt_count}} - - {% set n.runningtotal = n.runningtotal + percentage %} - {% endif %} - {% endfor %} - {% endif %} - - poll: {{poll.title}} - {% for opt in poll.options %} - option "{{opt.text}}": {{opt.num or 0}} votes - {% endfor %} - total votes: {{total_votes}} - - + {{ vote_meter(thread_polls[thread.id]) }}
{% endif %} diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index 7bf253d..aec9103 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -1,4 +1,4 @@ -{% from 'common.html' import disp_post,tag %} +{% from 'common.html' import disp_post,tag,vote_meter %} {% extends 'base.html' %} {% block header %}

{%block title %}{{thread.title}}{% endblock %}

@@ -12,6 +12,7 @@
  • #{{opt.option_idx}} - {{opt.text}} - {{opt.num or 0}}
  • {%endfor%} +{{ vote_meter(poll) }} {% endif %}
    diff --git a/apioforum/thread.py b/apioforum/thread.py index daf0b85..f8e8036 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -33,7 +33,11 @@ def view_thread(thread_id): poll = None votes = None if thread['poll'] is not None: - poll_row = db.execute("SELECT * FROM polls where id = ?",(thread['poll'],)).fetchone() + poll_row= db.execute(""" + SELECT polls.*,total_vote_counts.total_votes FROM polls + LEFT OUTER JOIN total_vote_counts ON polls.id = total_vote_counts.poll + WHERE polls.id = ?; + """,(thread['poll'],)).fetchone() options = db.execute(""" SELECT poll_options.*, vote_counts.num FROM poll_options -- cgit v1.2.3 From 2a0a21ae101ce54080bdedd323a6ca6ddf36d35f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 14:43:00 +0000 Subject: fix displaying of poll options --- apioforum/templates/view_thread.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apioforum/templates/view_thread.html b/apioforum/templates/view_thread.html index aec9103..429621a 100644 --- a/apioforum/templates/view_thread.html +++ b/apioforum/templates/view_thread.html @@ -7,11 +7,11 @@ {%block content%} {% if poll %}

    {{poll.title}}

    -
      +
        {%for opt in poll.options%} -
      1. #{{opt.option_idx}} - {{opt.text}} - {{opt.num or 0}}
      2. +
      3. {{opt.text}}: {{opt.num or 0}} votes
      4. {%endfor%} -
    + {{ vote_meter(poll) }} {% endif %}
    -- cgit v1.2.3 From 2d92be0e223a8b54749d0b2d304a78b16b92000d Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 14:51:55 +0000 Subject: shouldn't count retractions as part of the total vote count --- apioforum/db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apioforum/db.py b/apioforum/db.py index ba1f6a3..f3693a9 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -117,7 +117,7 @@ CREATE VIEW vote_counts AS """, """ CREATE VIEW total_vote_counts AS - SELECT poll, count(*) AS total_votes FROM votes WHERE current GROUP BY poll; + SELECT poll, count(*) AS total_votes FROM votes WHERE current AND NOT is_retraction GROUP BY poll; """, ] -- cgit v1.2.3 From f86ec8076e53ec3608fbcf64e0b4df18eba0e9e5 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 15:12:19 +0000 Subject: don't need that print statement any more --- apioforum/forum.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apioforum/forum.py b/apioforum/forum.py index a736af9..d3402f0 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -97,11 +97,6 @@ def view_forum(forum_id): a['updated'] = datetime.datetime.fromisoformat(a['updated']) subforums.append(a) - - - - - print(thread_polls) return render_template("view_forum.html", forum=forum, subforums=subforums, -- cgit v1.2.3 From 8b022f838f507c1a6fcc67edc97fecdd17423f06 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 15:16:26 +0000 Subject: wrong name for loop counter thing --- apioforum/templates/common.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apioforum/templates/common.html b/apioforum/templates/common.html index 286bec8..dfbd934 100644 --- a/apioforum/templates/common.html +++ b/apioforum/templates/common.html @@ -87,7 +87,7 @@ {% else %} {% for opt in poll.options %} {% set opt_count = opt.num or 0 %} - {% set colour = (loop.count|string + opt.text)|gen_colour %} + {% set colour = (loop.index|string + opt.text)|gen_colour %} {% if opt_count != 0 %} {% set percentage = 100*(opt_count/total_votes) %} {# todo: do this in css somehow #} -- cgit v1.2.3 From ca9059374bae63dcf47b0ffcaa57b43ae608c309 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sun, 18 Jul 2021 15:16:46 +0000 Subject: and i forgot to add util.py as well --- apioforum/util.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 apioforum/util.py diff --git a/apioforum/util.py b/apioforum/util.py new file mode 100644 index 0000000..64bdf20 --- /dev/null +++ b/apioforum/util.py @@ -0,0 +1,16 @@ +# various utility things + +import hsluv +import hashlib + +# same algorithm as xep-0392 +def gen_colour(s): + b=s.encode("utf-8") + h=hashlib.sha1(b) + two_bytes=h.digest()[:2] + val = int.from_bytes(two_bytes, 'little') + angle = 360*(val/65536) + col = hsluv.hsluv_to_hex([angle, 80, 70]) + return col + + -- cgit v1.2.3 From dc65b43ddce195c2ed35f6b7a0c1a96d284e0d55 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 22 Jul 2021 16:59:50 +0000 Subject: make tags be per-forum and have the thread config interface work with this --- apioforum/db.py | 16 ++++++++++++++++ apioforum/forum.py | 17 +++++++++++++++++ apioforum/templates/view_forum.html | 3 +++ apioforum/thread.py | 7 ++++--- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/apioforum/db.py b/apioforum/db.py index abcd774..50b142e 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -155,6 +155,22 @@ CREATE VIEW number_of_posts AS CREATE VIEW total_vote_counts AS SELECT poll, count(*) AS total_votes FROM votes WHERE current AND NOT is_retraction GROUP BY poll; """, +""" +PRAGMA foreign_keys = off; +BEGIN TRANSACTION; +CREATE TABLE tags_new ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + text_colour TEXT NOT NULL, + bg_colour TEXT NOT NULL, + forum INTEGER NOT NULL REFERENCES forums(id) +); +INSERT INTO tags_new (id,name,text_colour,bg_colour,forum) + SELECT id,name,text_colour,bg_colour,1 FROM tags; +DROP TABLE tags; +ALTER TABLE tags_new RENAME TO tags; +PRAGMA foreign_keys = on; +""", ] def init_db(): diff --git a/apioforum/forum.py b/apioforum/forum.py index d3402f0..e03ca01 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -18,6 +18,19 @@ bp = Blueprint("forum", __name__, url_prefix="/") def not_actual_index(): return redirect("/1") +def get_avail_tags(forum_id): + db = get_db() + tags = db.execute(""" + WITH RECURSIVE fs AS + (SELECT * FROM forums WHERE id = ? + UNION ALL + SELECT forums.* FROM forums, fs WHERE fs.parent=forums.id) + SELECT * FROM tags + WHERE tags.forum in (SELECT id FROM fs) + ORDER BY id; + """,(forum_id,)).fetchall() + return tags + def forum_path(forum_id): db = get_db() ancestors = db.execute(""" @@ -50,6 +63,9 @@ def view_forum(forum_id): """,(forum_id,)).fetchall() thread_tags = {} thread_polls = {} + + avail_tags = get_avail_tags(forum_id) + #todo: somehow optimise this for thread in threads: thread_tags[thread['id']] = db.execute( @@ -103,6 +119,7 @@ def view_forum(forum_id): threads=threads, thread_tags=thread_tags, thread_polls=thread_polls, + avail_tags=avail_tags, ) @bp.route("//create_thread",methods=("GET","POST")) diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index 88be22f..67693d8 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -11,6 +11,9 @@ {% if forum.description %} {{forum.description|md|safe}} {% endif %} +{% for the_tag in avail_tags %} +{{tag(the_tag)}} +{% endfor %} {% if subforums %}

    subforae

    diff --git a/apioforum/thread.py b/apioforum/thread.py index f8e8036..991dc0b 100644 --- a/apioforum/thread.py +++ b/apioforum/thread.py @@ -7,6 +7,7 @@ from flask import ( url_for, flash, jsonify ) from .db import get_db +from .forum import get_avail_tags bp = Blueprint("thread", __name__, url_prefix="/thread") @@ -275,7 +276,7 @@ def config_thread(thread_id): db = get_db() thread = db.execute("select * from threads where id = ?",(thread_id,)).fetchone() thread_tags = [r['tag'] for r in db.execute("select tag from thread_tags where thread = ?",(thread_id,)).fetchall()] - avail_tags = db.execute("select * from tags order by id").fetchall() + avail_tags = get_avail_tags(thread['forum']) err = None if g.user is None: err = "you need to be logged in to do that" @@ -297,8 +298,8 @@ def config_thread(thread_id): flash("title updated successfully") db.commit() changed = False - wanted_tags = [] - for tagid in range(1,len(avail_tags)+1): + for avail_tag in avail_tags: + tagid = avail_tag['id'] current = tagid in thread_tags wanted = f'tag_{tagid}' in request.form if wanted and not current: -- cgit v1.2.3 From d22cd7736b46e4cae507cbb5e1d83f6794c2f921 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 22 Jul 2021 17:26:08 +0000 Subject: improve ui slightly --- apioforum/static/style.css | 1 + apioforum/templates/view_forum.html | 3 +++ 2 files changed, 4 insertions(+) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 237cad6..1ee3b14 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -80,6 +80,7 @@ dt { font-weight: bold } img { max-width: 100% } +.avail_tags { margin-top: 30px } nav#navbar { float: right; padding: 5px; margin: 2px; border: 1px solid black; display:flex; align-items: center; flex-wrap: wrap } nav#navbar p { margin-left: 15px; margin-top: 0; margin-bottom: 0; margin-right: 10px; padding: 0 } diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index 67693d8..25d83e5 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -11,8 +11,11 @@ {% if forum.description %} {{forum.description|md|safe}} {% endif %} +

    available tags: {% for the_tag in avail_tags %} {{tag(the_tag)}} +{% else %} +(none available) {% endfor %} {% if subforums %} -- cgit v1.2.3 From 054e159a1183bbd328d24924e4478e7677fade42 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Thu, 22 Jul 2021 17:35:37 +0000 Subject: minor html restructure --- apioforum/static/style.css | 2 +- apioforum/templates/base.html | 2 +- apioforum/templates/view_forum.html | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 1ee3b14..1f089a0 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -189,7 +189,7 @@ blockquote { border-left: 3px solid grey; } -.search-form { +.inline-form { display: inline-block; } diff --git a/apioforum/templates/base.html b/apioforum/templates/base.html index 9cfd7f3..ca1dd87 100644 --- a/apioforum/templates/base.html +++ b/apioforum/templates/base.html @@ -12,7 +12,7 @@