diff --git a/app/static/css/themes/default_theme.css b/app/static/css/themes/default_theme.css index 1c04ac1..c287756 100644 --- a/app/static/css/themes/default_theme.css +++ b/app/static/css/themes/default_theme.css @@ -125,6 +125,14 @@ div.editor-toolbar, div.CodeMirror { --text-disabled: #c0c0c0; } +.dl-button { + --link: #149641; + --link-text: #ffffff; + --link-active: #0f7331; + --meta: rgba(0, 0, 0, .15); + --meta-text: #000000; +} + /* Extra style on top of the Pygments style */ table.codehilitetable td.linenos { color: #808080; diff --git a/app/static/css/widgets.css b/app/static/css/widgets.css index 42fcd1e..0ad14fb 100644 --- a/app/static/css/widgets.css +++ b/app/static/css/widgets.css @@ -86,6 +86,9 @@ height: 64px; } } +hr.signature { + opacity: 0.2; +} .trophies { display: flex; flex-wrap: wrap; @@ -125,6 +128,34 @@ .trophy span { font-size: 80%; } -hr.signature { - opacity: 0.2; +.dl-button { + display: inline-flex; + flex-direction: row; + align-items: stretch; + border-radius: 5px; + overflow: hidden; + margin: 3px 5px; + vertical-align: middle; +} +.dl-button a { + display: flex; + align-items: center; + padding: 5px 15px; + font-size: 110%; + background: var(--link); + color: var(--link-text); +} +.dl-button a:hover, +.dl-button a:focus, +.dl-button a:active { + background: var(--link-active); + text-decoration: none; +} +.dl-button span { + display: flex; + align-items: center; + padding: 5px 8px; + background: var(--meta); + color: var(--meta-text); + font-size: 90%; } \ No newline at end of file diff --git a/app/static/less/widgets.less b/app/static/less/widgets.less index 185cb79..4af3fb9 100644 --- a/app/static/less/widgets.less +++ b/app/static/less/widgets.less @@ -109,6 +109,11 @@ } } +hr.signature { + opacity: 0.2; +} + + /* Trophies */ .trophies { display: flex; @@ -157,6 +162,31 @@ } } -hr.signature { - opacity: 0.2; + +/* Download button */ +.dl-button { + display: inline-flex; flex-direction: row; align-items: stretch; + + border-radius: 5px; overflow: hidden; + margin: 3px 5px; vertical-align: middle; + + a { + display:flex; align-items:center; + padding: 5px 15px; + + font-size: 110%; + background: var(--link); color: var(--link-text); + + &:hover, &:focus, &:active { + background: var(--link-active); + text-decoration: none; + } + } + + span { + display: flex; align-items:center; + padding: 5px 8px; + background: var(--meta); color: var(--meta-text); + font-size: 90%; + } } diff --git a/app/utils/markdown_extensions/pclinks.py b/app/utils/markdown_extensions/pclinks.py index 9fe982b..58911fd 100644 --- a/app/utils/markdown_extensions/pclinks.py +++ b/app/utils/markdown_extensions/pclinks.py @@ -16,9 +16,11 @@ from markdown.inlinepatterns import InlineProcessor import xml.etree.ElementTree as etree from flask import url_for, render_template from app.utils.unicode_names import normalize +from app.utils.filters.humanize import humanize from app.models.poll import Poll from app.models.topic import Topic from app.models.user import Member +from app.models.attachment import Attachment class PCLinkExtension(Extension): @@ -48,6 +50,7 @@ class PCLinksInlineProcessor(InlineProcessor): 'membre': handleUser, 'user': handleUser, 'u': handleUser, 'sondage': handlePoll, 'poll': handlePoll, 'topic': handleTopic, 't': handleTopic, + 'fichier': handleFile, 'file': handleFile, 'f': handleFile, } def handleMatch(self, m, data): @@ -121,3 +124,32 @@ def handleUser(content_id, context): a.set('class', 'profile-link') return a + +def handleFile(content_id, context): + try: + content_id = int(content_id) + except ValueError: + return "[Fichier invalide]" + + file = Attachment.query.get(content_id) + + if file is None: + return "[Fichier inconnu]" + + # Build element manually to avoid code injection + container = etree.Element('div') + container.set('class', 'dl-button') + + xtitle = etree.SubElement(container, 'a') + xtitle.text = file.name + xtitle.set('href', file.url) + + xsize = etree.SubElement(container, 'span') + xsize.text = humanize(file.size, unit='o') + + # + # TLTitre.g3a + # {{ file.size | humanize(unit='o') }} + # + + return container