diff --git a/.gitignore b/.gitignore index e2082e9..532bee7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.un~ *.swp *.sh +thsf.log +thsf_venv diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..dd49821 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,6 @@ +global-exclude *.pyc +global-exclude build +global-exclude __pycache__ + +include src/thsf/templates/*.* +include src/thsf/static/**/*.* diff --git a/Makefile b/Makefile index 9ac38b3..c097280 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,32 @@ -.PHONY: install +.PHONY: clean install run stop install: - echo "We Make P0RN" + set -e ;\ + THSF_DIR=$$(pwd); \ + echo [+] Déploiement dans $$THSF_DIR; \ + python3 -m venv thsf_venv; \ + . thsf_venv/bin/activate; \ + pip install -r requirements.txt ;\ + pip install . ;\ + pip install gunicorn; + +run: + set -e ;\ + THSF_DIR=$$(pwd); \ + echo [+] Démarrage dans $$THSF_DIR; \ + . thsf_venv/bin/activate; \ + thsf_venv/bin/gunicorn -D -p thsf.pid -w 4 -b 127.0.0.1:8042 'thsf:app' + +stop: + -set -e;\ + kill -15 $$(cat thsf.pid); \ + rm thsf.pid + +clean: + -set -e ;\ + rm -Rf ./build ;\ + rm -Rf ./src/thsf.egg-info; \ + . thsf_venv/bin/activate; \ + pip uninstall thsf -y + +all: clean stop install run diff --git a/README.md b/README.md index 1076d37..704aa32 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ Lorsque la demande de fusion sera acceptée (vous pouvez auto-accepter vos deman ### Personnalisation de la publication -Afin de rendre le processus plus souple, il est possible de personnaliser la livraison en plaçant **à la racine du dépôt** un fichier `Makefile` contenant une cible `install` qui sera systématiquement exécutée. +Afin de rendre le processus plus souple, il est possible de personnaliser la livraison en plaçant **à la racine du dépôt** un fichier `Makefile` contenant une cible `all` qui sera systématiquement exécutée. -C'est dans cette cible `install` que vous pourrez mettre toutes vos commandes personnalisées, typiquement l'installation de modules `npm`. +C'est dans cette cible `all` que vous pourrez mettre toutes vos commandes personnalisées, typiquement l'installation de modules `python`, etc. Le processus de publication est le suivant: @@ -26,7 +26,7 @@ Le processus de publication est le suivant: 2. La branche `master` du présent dépôt est cloné sur le serveur hébergeant le site du **THSF** -3. Si un fichier `Makefile` se trouve **à la racine du dépôt**, la cible `install` (i.e: `make install`) est automatiquement exécutée. +3. Si un fichier `Makefile` se trouve **à la racine du dépôt**, la cible `all` (i.e: `make all`) est automatiquement exécutée. ## Contrôle de qualité et tests diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..3410596 --- /dev/null +++ b/config.yml @@ -0,0 +1,30 @@ +--- +log: + version: 1 + formatters: + default: + format: '[%(asctime)-20s][%(levelname)-8s][%(funcName)-20s]: %(message)s' + handlers: + wsgi: + class: logging.FileHandler + filename: thsf.log + formatter: default + loggers: + thsf: + handlers: [wsgi] + propagate: no + root: + level: INFO + handlers: [wsgi] +app: + secret_key: xxx + languages: + - fr + name: THSF + real_url: https://www.thsf.net +pretalx: + url: https://23.thsf.net + apikey: sdfsdfsdf + event: thsf-2023 + schedule: wip + diff --git a/index.html b/index.html deleted file mode 100644 index 372d98e..0000000 --- a/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - THSF 2023: Extractivisme - - - - - - - - -
- - -
- - diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..dc40988 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[build-system] +requires = ["setuptools>=62", + "build", + "wheel"] +build-backend = "setuptools.build_meta" + +[tool.pytest.ini_options] +pythonpath = [ + "src" +] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1e40446 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +build +wheel +flask +gunicorn +pyYAML diff --git a/resources/THSF23_WEBSITE_BANNER.svg b/resources/THSF23_WEBSITE_BANNER.svg new file mode 100644 index 0000000..f680b45 --- /dev/null +++ b/resources/THSF23_WEBSITE_BANNER.svg @@ -0,0 +1,611 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8320658 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,48 @@ +[metadata] +version = 0.0.1 +classifiers = + Programming Language :: Python :: 3 + License :: OSI Approved :: MIT License + Operating System :: OS Independent +url = https://git.tetalab.org/tetalab/thsf.net +description = "THSF website" +name = thsf +long_description = file: README.md +long_description_content_type = text/markdown +author = Doug Le Tough +author_email = doug@redatomik.org + +[options] +package_dir = + = src +packages = find: +include_package_data = True +python_requires = >=3.8 +install_requires = + flask + gunicorn + pyYAML + +[options.packages.find] +where = src + +[options.extras_require] +dev = + twine + build + wheel>=0.37.0 + flake8>=4.0.1 + flake8-breakpoint>=1.1.0 + flake8-builtins>=1.5.3 + flake8-print>=4.0.0 + flake8-return>=1.1.3 + pep8-naming>=0.8.2 + setuptools>=60.9.2 + pylint>=2.12.2 + +[flake8] +ignore = E111 +exclude = .git,__pycache__,build,dist, thot-cli-venv +max-line-length = 160 +use-flake8-tabs = true +tab-width = 2 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..b908cbe --- /dev/null +++ b/setup.py @@ -0,0 +1,3 @@ +import setuptools + +setuptools.setup() diff --git a/src/thsf/__init__.py b/src/thsf/__init__.py new file mode 100644 index 0000000..fcbf56e --- /dev/null +++ b/src/thsf/__init__.py @@ -0,0 +1,98 @@ +import sys +import logging +from logging import config +import yaml +from flask import Flask, render_template, redirect, request, url_for + + +# ------------------------------------------------------------------------------ +# -- Configuration +# ------------------------------------------------------------------------------ +class AppConfig: + """ Flask application config """ + CONFIG_FILENAME = "config.yml" + + +# ------------------------------------------------------------------------------ +# -- Application +# ------------------------------------------------------------------------------ +logger = logging.getLogger('wsgi') +app = Flask(__name__) + + +# ------------------------------------------------------------------------------ +# -- Local configuration +# ------------------------------------------------------------------------------ +app.config.from_object(__name__ + '.AppConfig') +try: + with open(app.config["CONFIG_FILENAME"], "r") as local_config_file: + app.local_config = yaml.load(local_config_file, Loader=yaml.SafeLoader) + app.config["SECRET_KEY"] = app.local_config["app"]["secret_key"] + app.config["LANGUAGES"] = app.local_config["app"]["languages"] + config.dictConfig(app.local_config["log"]) +except Exception as err: + logger.critical("[{}] {}".format(err.__class__, str(err))) + sys.exit(1) + + +# ------------------------------------------------------------------------------ +# -- Tools +# ------------------------------------------------------------------------------ +@app.errorhandler(404) +def page_not_found(err): + return redirect(url_for('index')) + + +# ------------------------------------------------------------------------------ +# -- Routes +# ------------------------------------------------------------------------------ +@app.route('/favicon.ico', methods=['GET']) +def favicon(): + return redirect(url_for('static', filename='images/favicon.png')) + +@app.route('/', methods=['GET']) +def index(): + return render_template("index.html") + +@app.route('/planning', methods=['GET']) +def planning(): + return "planning" + +@app.route('/concerts', methods=['GET']) +def concerts(): + return "concerts" + +@app.route('/djsets', methods=['GET']) +def djsets(): + return "djsets" + +@app.route('/exhibitions', methods=['GET']) +def exhibitions(): + return "exhibitions" + +@app.route('/lighttalks', methods=['GET']) +def lighttalks(): + return "lighttalks" + +@app.route('/paneldiscussions', methods=['GET']) +def paneldiscussions(): + return "paneldiscussions" + +@app.route('/screenings', methods=['GET']) +def screenings(): + return "screenings" + +@app.route('/talks', methods=['GET']) +def talks(): + return "talks" + +@app.route('/workshops', methods=['GET']) +def workshops(): + return "workshops" + + +# ------------------------------------------------------------------------------ +# -- Main +# ------------------------------------------------------------------------------ +if __name__ == '__main__': + app.run(host='127.0.0.1', port=5000, debug=True) diff --git a/src/thsf/static/css/style.css b/src/thsf/static/css/style.css new file mode 100644 index 0000000..b4f8bc4 --- /dev/null +++ b/src/thsf/static/css/style.css @@ -0,0 +1,111 @@ +@font-face { + font-family: pfdintextcomppromedium; + src: url(../fonts/PFDinTextCompPro-Medium.ttf); +} + +@font-face { + font-family: pfdintextcompprothin; + src: url(../fonts/PFDinTextCompPro-Thin.ttf); +} + + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background-color: #e6007e; + background-repeat: no-repeat; + background-size: auto; + background-position-x: center; + font-family: pfdintextcomppromedium; +} + +span.header { + font-size: 9.75em; + font-weight: bold; +} + + +span.subheader { + margin: 0; + font-size: 3.47em; + font-weight: thin; +} + +span.place { + margin: 0; + font-size: 2.145em; +} + +.white { + color: #ffffff; +} + +.black { + color: #1A000D; +} + +.thin { + font-family: pfdintextcompprothin; +} + +.bold { + font-family: pfdintextcomppromedium; +} + +#main_wrapper { + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; +} + +#header { + text-align: center; + margin-bottom: -3em; +} + +#logo_wrapper { + margin-top: 1em; + width: 40em; +} + +img.logo { + width: inherit; +} + +#navbar_wrapper { + margin-top: 1em; + display: flex; + flex-direction: line; + justify-content: flex-start; + align-items: center; + gap: 2em; +} + +.button { + font-size: 4em; + transition-property: color; + transition-duration: 1s; +} + +.button:hover { + color: #ffffff; + cursor: pointer; +} + + +#cursorbar { + margin-top: 1em; +} + +.cursor { + width: 0; + height: 0; + border-left: 0.75em solid transparent; + border-right: 0.75em solid transparent; + border-bottom: 0.75em solid #000000; +} diff --git a/fonts/PFDinTextCompPro-Medium.ttf b/src/thsf/static/fonts/PFDinTextCompPro-Medium.ttf similarity index 100% rename from fonts/PFDinTextCompPro-Medium.ttf rename to src/thsf/static/fonts/PFDinTextCompPro-Medium.ttf diff --git a/fonts/PFDinTextCompPro-Thin.ttf b/src/thsf/static/fonts/PFDinTextCompPro-Thin.ttf similarity index 100% rename from fonts/PFDinTextCompPro-Thin.ttf rename to src/thsf/static/fonts/PFDinTextCompPro-Thin.ttf diff --git a/fonts/Uni Sans Bold.otf b/src/thsf/static/fonts/Uni Sans Bold.otf similarity index 100% rename from fonts/Uni Sans Bold.otf rename to src/thsf/static/fonts/Uni Sans Bold.otf diff --git a/fonts/Uni Sans Book.otf b/src/thsf/static/fonts/Uni Sans Book.otf similarity index 100% rename from fonts/Uni Sans Book.otf rename to src/thsf/static/fonts/Uni Sans Book.otf diff --git a/src/thsf/static/fonts/fontawesome-free-6.4.0-web.zip b/src/thsf/static/fonts/fontawesome-free-6.4.0-web.zip new file mode 100644 index 0000000..c1bd796 Binary files /dev/null and b/src/thsf/static/fonts/fontawesome-free-6.4.0-web.zip differ diff --git a/images/affiche_v1.png b/src/thsf/static/images/affiche_v1.png similarity index 100% rename from images/affiche_v1.png rename to src/thsf/static/images/affiche_v1.png diff --git a/images/bg.png b/src/thsf/static/images/bg.png similarity index 100% rename from images/bg.png rename to src/thsf/static/images/bg.png diff --git a/images/favicon.png b/src/thsf/static/images/favicon.png similarity index 100% rename from images/favicon.png rename to src/thsf/static/images/favicon.png diff --git a/src/thsf/static/images/logo.svg b/src/thsf/static/images/logo.svg new file mode 100644 index 0000000..c2b921e --- /dev/null +++ b/src/thsf/static/images/logo.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/pretalx-header.png b/src/thsf/static/images/pretalx-header.png similarity index 100% rename from images/pretalx-header.png rename to src/thsf/static/images/pretalx-header.png diff --git a/src/thsf/templates/base.html b/src/thsf/templates/base.html new file mode 100644 index 0000000..2d2dd7b --- /dev/null +++ b/src/thsf/templates/base.html @@ -0,0 +1,22 @@ + + + + THSF 2023: S/Extraire + + + + + + {% block headers %} + {% endblock %} + + + +{% block content %} +{% endblock %} + + diff --git a/src/thsf/templates/index.html b/src/thsf/templates/index.html new file mode 100644 index 0000000..e3736ab --- /dev/null +++ b/src/thsf/templates/index.html @@ -0,0 +1,36 @@ +{% extends "base.html" %} +{% block content %} +
+
+ +
+ Toulouse Hacker Space Factory +
+
+ 26 28 mai 2023 - + CINÉMA UTOPIA BORDEROUGE +
+
+
+ +
+ +
+
+
+
+{% endblock %} diff --git a/src/thsf/templates/planning.html b/src/thsf/templates/planning.html new file mode 100644 index 0000000..0630c4f --- /dev/null +++ b/src/thsf/templates/planning.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% block headers %} + +{% endblock %} + +{% block content %} +
+ + +
+{% endblock %} diff --git a/src/thsf_wsgi.py b/src/thsf_wsgi.py new file mode 100644 index 0000000..f204296 --- /dev/null +++ b/src/thsf_wsgi.py @@ -0,0 +1,5 @@ +from thsf import app + +if __name__ == "__main__": + application = app + application.run(host="127.0.0.1", port=8043) diff --git a/styles/main.css b/styles/main.css deleted file mode 100644 index 2c803c8..0000000 --- a/styles/main.css +++ /dev/null @@ -1,151 +0,0 @@ -@font-face { - font-family: pfdintextcomppro; - src: url(../fonts/PFDinTextCompPro-Medium.ttf); -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; - font-family: pfdintextcomppro; -} - -body { - background-color: #e6007e; - background-image: url('../images/bg.png'); - background-repeat: no-repeat; - background-size: auto; - background-position-x: center; - /* overflow: hidden; */ -} - -#thsf-schedule-wrapper { - position: fixed; - top: 220px; - left: 50%; - transform: translateX(-50%); - width: 50%; - height: 90%; - overflow: auto; - margin-bottom: 10px; -} - - -ul { - overflow: hidden; - perspective: 900px; - list-style: none; - height: 100vh; - max-height: 800px; - min-height: 400px; - text-align: center; -} - -@keyframes width-sway { - 0%, 100% { - width: 500px; - } - 50% { - width: 100%; - } -} -li { - position: absolute; - top: 0; - margin: auto; - width: 100%; - transform: translateY(100vh); - font-size: 6rem; - font-family: pfdintextcomppro; - font-weight: bold; - color: #ffffdd; - animation: 5.3333333333s spiral-staircase linear infinite; - white-space: nowrap; -} - -li:nth-child(1) { - animation-delay: 0.3333333333s; -} - -li:nth-child(2) { - animation-delay: 0.6666666667s; -} - -li:nth-child(3) { - animation-delay: 1s; -} - -li:nth-child(4) { - animation-delay: 1.3333333333s; -} - -li:nth-child(5) { - animation-delay: 1.6666666667s; -} - -li:nth-child(6) { - animation-delay: 2s; -} - -li:nth-child(7) { - animation-delay: 2.3333333333s; -} - -li:nth-child(8) { - animation-delay: 2.6666666667s; -} - -li:nth-child(9) { - animation-delay: 3s; -} - -li:nth-child(10) { - animation-delay: 3.3333333333s; -} - -li:nth-child(11) { - animation-delay: 3.6666666667s; -} - -li:nth-child(12) { - animation-delay: 4s; -} - -li:nth-child(13) { - animation-delay: 4.3333333333s; -} - -li:nth-child(14) { - animation-delay: 4.6666666667s; -} - -li:nth-child(15) { - animation-delay: 5s; -} - -li:nth-child(16) { - animation-delay: 5.3333333333s; -} - -@keyframes spiral-staircase { - 0% { - transform: rotateY(90deg) translateY(105vh) rotate(0deg) scale(0); - opacity: 0; - } - 40% { - transform: rotateY(90deg) translateY(61vh) rotate(0deg) scale(0); - opacity: 0; - } - 50% { - transform: rotateY(0deg) translateY(55vh) rotate(0deg) scale(0.50); - opacity: 1; - } - 75% { - transform: rotateY(-60deg) translateY(27.5vh) rotate(0deg) scale(1); - opacity: 1; - } - 100% { - transform: rotateY(-90deg) translateY(-5vh) rotate(0deg) scale(1.2); - opacity: 0; - } -}