From d7ef42dddbc1c235b4ded22469b0dbf3c2a5da70 Mon Sep 17 00:00:00 2001 From: crunk Date: Tue, 30 Apr 2024 22:16:14 +0200 Subject: [PATCH 01/49] distribusi file model --- verse/deploydb.py | 1 + verse/file_crawler.py | 1 + verse/migrations/env.py | 23 +++++++------- verse/migrations/versions/8ede45e978d9_.py | 36 ++++++++++++++++++++++ verse/models/distribusi_file_model.py | 2 +- 5 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 verse/file_crawler.py create mode 100644 verse/migrations/versions/8ede45e978d9_.py diff --git a/verse/deploydb.py b/verse/deploydb.py index 9a33cdc..30a8364 100644 --- a/verse/deploydb.py +++ b/verse/deploydb.py @@ -4,6 +4,7 @@ def deploy(): from app import create_app, db from models.distribusi_model import Distribusis # noqa: F401 + from models.distribusi_file_model import DistribusiFiles # noqa: F401 # This model is required for flask_migrate to make the table from models.user_model import User # noqa: F401 diff --git a/verse/file_crawler.py b/verse/file_crawler.py new file mode 100644 index 0000000..8ba8024 --- /dev/null +++ b/verse/file_crawler.py @@ -0,0 +1 @@ +from models.distribusi_file_model import DistribusiFiles diff --git a/verse/migrations/env.py b/verse/migrations/env.py index 847c719..68feded 100644 --- a/verse/migrations/env.py +++ b/verse/migrations/env.py @@ -3,9 +3,10 @@ from __future__ import with_statement import logging from logging.config import fileConfig -from alembic import context from flask import current_app +from alembic import context + # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config @@ -13,19 +14,17 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger("alembic.env") +logger = logging.getLogger('alembic.env') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - "sqlalchemy.url", - str(current_app.extensions["migrate"].db.get_engine().url).replace( - "%", "%%" - ), -) -target_metadata = current_app.extensions["migrate"].db.metadata + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.get_engine().url).replace( + '%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -66,20 +65,20 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, "autogenerate", False): + if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info("No changes in schema detected.") + logger.info('No changes in schema detected.') - connectable = current_app.extensions["migrate"].db.get_engine() + connectable = current_app.extensions['migrate'].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions["migrate"].configure_args, + **current_app.extensions['migrate'].configure_args ) with context.begin_transaction(): diff --git a/verse/migrations/versions/8ede45e978d9_.py b/verse/migrations/versions/8ede45e978d9_.py new file mode 100644 index 0000000..2bdb676 --- /dev/null +++ b/verse/migrations/versions/8ede45e978d9_.py @@ -0,0 +1,36 @@ +"""empty message + +Revision ID: 8ede45e978d9 +Revises: +Create Date: 2024-04-30 22:15:48.023060 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '8ede45e978d9' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('distribusi_files', schema=None) as batch_op: + batch_op.alter_column('type', + existing_type=sa.VARCHAR(length=300), + nullable=True) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('distribusi_files', schema=None) as batch_op: + batch_op.alter_column('type', + existing_type=sa.VARCHAR(length=300), + nullable=False) + + # ### end Alembic commands ### diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 503f7bb..1066fdb 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -7,7 +7,7 @@ class DistribusiFiles(db.Model): __tablename__ = "distribusi_files" id = db.Column(db.Integer, primary_key=True) - type = db.Column(db.String(300), nullable=False, unique=True) + type = db.Column(db.String(300), nullable=True, unique=False) distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) path = db.Column(db.String(4096), nullable=True, unique=False) description = db.Column(db.String(9), nullable=True, unique=False) -- 2.39.2 From bb1bd62250822cacc694236a686e66b228c438d2 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 13 May 2024 21:02:23 +0200 Subject: [PATCH 02/49] file crawler for annotations,descriptions,tags --- verse/file_crawler.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 8ba8024..9e5456b 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -1 +1,22 @@ +import os + +import magic +from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES + from models.distribusi_file_model import DistribusiFiles + +MIME_TYPE = magic.Magic(mime=True) + + +def distribusi_file_with_type(full_path): + mime = MIME_TYPE.from_file(full_path) + type_, subtype = mime.split("/") + if type_ in FILE_TYPES: + print(f"distribusi file:{full_path} type:{type_}") + + +for root, dirs, files in os.walk("stash", topdown=True): + files = list(filter(lambda f: not f.startswith("."), files)) + for file in files: + full_path = os.path.join(root, file) + distribusi_file_with_type(full_path) -- 2.39.2 From 37c1a7a1def582bdf39ebd466a6a98dfdc9b74d0 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 18 May 2024 11:42:12 +0200 Subject: [PATCH 03/49] changed settings to different defaults --- verse/settings.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verse/settings.toml b/verse/settings.toml index 287c705..1206e1d 100644 --- a/verse/settings.toml +++ b/verse/settings.toml @@ -1,4 +1,4 @@ title = "Varia Archive X Distribusi-Verse" -categories = ["event","gathering","work session","workgroup","performance","music event"] +categories = ["event","gathering","workgroup","talk","music event"] start_time = 2017-11-03 end_time = 2025-12-31 -- 2.39.2 From 8f960a1a3b281b661681db011adfa6a02fd08143 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 18 May 2024 11:55:41 +0200 Subject: [PATCH 04/49] reformatted adminpage.py --- verse/adminpage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/verse/adminpage.py b/verse/adminpage.py index 4d78d26..0bb1c39 100644 --- a/verse/adminpage.py +++ b/verse/adminpage.py @@ -46,7 +46,6 @@ def DeleteUsers(adminuserform): userform.errors.append(f"User {useremail} deleted!") - def DeleteUserFromDb(user): try: db.session.delete(user) -- 2.39.2 From 8567af2ed44c978ec7fad4df3cfb0ddf823a276f Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 18 May 2024 11:56:36 +0200 Subject: [PATCH 05/49] describe files start --- verse/describer/forms/describe_file_form.py | 31 +++++++++++++++++++++ verse/describer/templates/describe.html | 2 ++ verse/file_crawler.py | 1 + verse/forms/uploadform.py | 4 +-- verse/models/distribusi_file_model.py | 5 ++-- 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 verse/describer/forms/describe_file_form.py create mode 100644 verse/describer/templates/describe.html diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py new file mode 100644 index 0000000..a61ab4c --- /dev/null +++ b/verse/describer/forms/describe_file_form.py @@ -0,0 +1,31 @@ +"""Describe File Form to describe files in the distribusi archive""" + +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField + + +class DescribeFileForm(FlaskForm): + """DescribeFileForm selection form.""" + + alttext = StringField( + "Alt-text for this file:", + validators=[ + validators.InputRequired(), + Length(3, 255), + ], + ) + searchtags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[ + validators.InputRequired(), + Length(3, 500), + ], + ) + description = StringField( + "Description of this file:", + validators=[ + validators.InputRequired(), + Length(3, 4096), + ], + ) + save = SubmitField("Save") diff --git a/verse/describer/templates/describe.html b/verse/describer/templates/describe.html new file mode 100644 index 0000000..fc36ba4 --- /dev/null +++ b/verse/describer/templates/describe.html @@ -0,0 +1,2 @@ +{% extends "base/base.html" %} +{% block main %} diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 9e5456b..5d1d0f9 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -17,6 +17,7 @@ def distribusi_file_with_type(full_path): for root, dirs, files in os.walk("stash", topdown=True): files = list(filter(lambda f: not f.startswith("."), files)) + files = list(filter(lambda f: not f.endswith(".html"), files)) for file in files: full_path = os.path.join(root, file) distribusi_file_with_type(full_path) diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py index 5d1f21f..261d1cd 100644 --- a/verse/forms/uploadform.py +++ b/verse/forms/uploadform.py @@ -68,8 +68,8 @@ class UploadForm(FlaskForm): ) tags = StringField( - "Add tags, seperated by commas. No need for the '#' sign:", - validators=[validators.InputRequired(), Length(2, 500)], + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[validators.InputRequired(), Length(3, 500)], ) zipfile = FileField( diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 1066fdb..417b861 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -7,11 +7,12 @@ class DistribusiFiles(db.Model): __tablename__ = "distribusi_files" id = db.Column(db.Integer, primary_key=True) - type = db.Column(db.String(300), nullable=True, unique=False) + type = db.Column(db.String(100), nullable=True, unique=False) distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) path = db.Column(db.String(4096), nullable=True, unique=False) - description = db.Column(db.String(9), nullable=True, unique=False) + alttext = db.Column(db.String(255), nullable=True, unique=False) tags = db.Column(db.String(500), nullable=True, unique=False) + description = db.Column(db.String(9), nullable=True, unique=False) def __repr__(self): return "" % self.distribusiname -- 2.39.2 From 8cf699214c0ec00fcbca203d7abc93a136ed3442 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 18 May 2024 16:10:18 +0200 Subject: [PATCH 06/49] database config together --- verse/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verse/app.py b/verse/app.py index 56dd762..eb49b8e 100644 --- a/verse/app.py +++ b/verse/app.py @@ -19,8 +19,8 @@ def create_app(): APP.secret_key = os.urandom(24) APP.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///distribusiverse.db" APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True - APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 + APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 APP.config["MAIL_SERVER"] = "mail.autonomic.zone" APP.config["MAIL_PORT"] = 587 APP.config["MAIL_USE_SSL"] = False -- 2.39.2 From 0fb8929a80a62433ed7def093939115f6f424dd9 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 18 May 2024 16:11:05 +0200 Subject: [PATCH 07/49] file_crawler update --- verse/file_crawler.py | 70 +++++++++++++++++++++++---- verse/models/distribusi_file_model.py | 2 +- verse/statuspengguna/loginuser.py | 1 - 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 5d1d0f9..4ff054b 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -2,22 +2,74 @@ import os import magic from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES - +from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles +from app import create_app, get_app, db +from sqlalchemy.exc import ( + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, +) MIME_TYPE = magic.Magic(mime=True) -def distribusi_file_with_type(full_path): +def _distribusi_file_with_type(distribusi, full_path): mime = MIME_TYPE.from_file(full_path) type_, subtype = mime.split("/") if type_ in FILE_TYPES: - print(f"distribusi file:{full_path} type:{type_}") + _add_distribusi_file_to_db(distribusi, full_path, type_) + +def _get_distribusi_from_path(path): + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + return distribusi + +def _add_distribusi_file_to_db(distribusi, full_path, type): + app = get_app() + print(f"adding file to database: {full_path} type: {type}") + try: + new_distribusi_file = DistribusiFiles( + path=full_path, + type=type, + distribusi=distribusi.id, + ) + db.session.add(new_distribusi_file) + db.session.commit() + return + except InvalidRequestError: + db.session.rollback() + app.logger.error("Something went wrong!") + except IntegrityError: + db.session.rollback() + app.logger.error("file %s already exists!", full_path) + except DataError: + db.session.rollback() + app.logger.error("%s Invalid Entry", full_path) + except InterfaceError: + db.session.rollback() + app.logger.error( + "Error connecting to the database" + ) + except DatabaseError: + db.session.rollback() + app.logger.error( + "Error connecting to the database" + ) + + +def add_distribusi_files(path): + app = create_app() + with app.app_context(): + distribusi = _get_distribusi_from_path(path) + path = os.path.join("stash", path) + for root, dirs, files in os.walk(path, topdown=True): + files = list(filter(lambda f: not f.startswith("."), files)) + files = list(filter(lambda f: not f.endswith(".html"), files)) + for file in files: + full_path = os.path.join(root, file) + _distribusi_file_with_type(distribusi, full_path) -for root, dirs, files in os.walk("stash", topdown=True): - files = list(filter(lambda f: not f.startswith("."), files)) - files = list(filter(lambda f: not f.endswith(".html"), files)) - for file in files: - full_path = os.path.join(root, file) - distribusi_file_with_type(full_path) +add_distribusi_files("2018-12-WttF-Mastodon-and-the-Fediverse") diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 417b861..5e3f5ac 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -12,7 +12,7 @@ class DistribusiFiles(db.Model): path = db.Column(db.String(4096), nullable=True, unique=False) alttext = db.Column(db.String(255), nullable=True, unique=False) tags = db.Column(db.String(500), nullable=True, unique=False) - description = db.Column(db.String(9), nullable=True, unique=False) + description = db.Column(db.String(4096), nullable=True, unique=False) def __repr__(self): return "" % self.distribusiname diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py index db08cac..5d72063 100644 --- a/verse/statuspengguna/loginuser.py +++ b/verse/statuspengguna/loginuser.py @@ -37,7 +37,6 @@ def LoginUser(): loginform.password.errors.append("Invalid email or password!") return render_template("login.html", loginform=loginform) if check_password_hash(user.password, loginform.password.data): - print(type(user)) login_user(user) flash("Logged in successfully.", "success") next = request.args.get("next") -- 2.39.2 From ff8215a7deaf0a5e41da761c2013d3551fa303ec Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 19 May 2024 11:13:21 +0200 Subject: [PATCH 08/49] selector redirects to wip file describer page --- verse/describer/describe_files.py | 22 ++++++++++++ verse/describer/templates/describe.html | 2 -- .../templates/describe_files/describe.html | 34 ++++++++++++++++++ verse/distribusikan/distribusiselector.py | 17 +++++++-- .../distribusiworkflow/selector.html | 7 ++++ verse/file_crawler.py | 2 +- verse/forms/selectorform.py | 2 ++ verse/migrations/versions/8ede45e978d9_.py | 36 ------------------- verse/models/distribusi_file_model.py | 2 +- verse/start.py | 19 ++++------ 10 files changed, 89 insertions(+), 54 deletions(-) create mode 100644 verse/describer/describe_files.py delete mode 100644 verse/describer/templates/describe.html create mode 100644 verse/describer/templates/describe_files/describe.html delete mode 100644 verse/migrations/versions/8ede45e978d9_.py diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py new file mode 100644 index 0000000..ac41c4d --- /dev/null +++ b/verse/describer/describe_files.py @@ -0,0 +1,22 @@ +from flask import Blueprint, render_template +from models.distribusi_model import Distribusis +from models.distribusi_file_model import DistribusiFiles + +describer = Blueprint( + "describer", + __name__, + template_folder="templates/describe_files", + static_folder="static", +) + + +@describer.route("/") +def describe_distribusi_files(distribusiname): + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + distribusi_files = DistribusiFiles.query.filter_by( + distribusi=distribusi.id + ).all() + print(distribusi_files) + return render_template("describe.html", distribusi_files=distribusi_files) diff --git a/verse/describer/templates/describe.html b/verse/describer/templates/describe.html deleted file mode 100644 index fc36ba4..0000000 --- a/verse/describer/templates/describe.html +++ /dev/null @@ -1,2 +0,0 @@ -{% extends "base/base.html" %} -{% block main %} diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html new file mode 100644 index 0000000..700d154 --- /dev/null +++ b/verse/describer/templates/describe_files/describe.html @@ -0,0 +1,34 @@ +{% extends "base/base.html" %} +{% block main %} +
+ {% if current_user.is_authenticated %} +
+ + + +
+ {% if adminuser %} +
+ + + +
+ {% endif %} +
+ + + +
+ {% endif %} +
+ + + +
+
+
+ {% for file in distribusi_files %} +

{{file}}

+ {% endfor%} +
+{% endblock %} diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index ccc5770..2ceb8fc 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -1,7 +1,7 @@ import os import shutil -from flask import flash, render_template +from flask import flash, render_template, redirect, url_for from flask_login import current_user from sqlalchemy.exc import ( DatabaseError, @@ -10,8 +10,9 @@ from sqlalchemy.exc import ( InvalidRequestError, ) -from app import db +from app import db, get_app from distribusikan.distribusisinfo import DistribusisInfo +from describer.describe_files import describe_distribusi_files from forms.distribusiform import DistribusiForm from forms.publicthemeform import PublicThemeForm from forms.selectorform import SelectorForm @@ -32,6 +33,8 @@ def DistribusiSelector(): if selectorform.validate_on_submit(): if selectorform.new.data: SelectNewDistribusi() + if selectorform.describe.data: + return SelectDescribeDistribusi(selectorform.distribusis.data) if selectorform.delete.data: selectorform = DeleteDistribusi(selectorform.distribusis.data) selectorform.distribusis.choices = ( @@ -64,6 +67,16 @@ def SelectNewDistribusi(): SelectCurrentDistribusi("new") +def SelectDescribeDistribusi(distribusiname): + app = get_app + return redirect( + url_for( + "describer.describe_distribusi_files", + distribusiname=distribusiname, + ) + ) + + def SelectUpdateDistribusi(distribusiname): print(f"Update this distribusi {distribusiname}") SelectCurrentDistribusi(distribusiname) diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html index 88dac97..6c95a0b 100644 --- a/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html +++ b/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html @@ -18,6 +18,13 @@ {{ selectorform.update }}
+

+ Describe your distribusi files. Add description texts, tags for search + or add alt-text for images

+
+ {{ selectorform.describe }} +
+

This will delete your distribusi site. This action cannot be undone! diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 4ff054b..0a38280 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -43,7 +43,7 @@ def _add_distribusi_file_to_db(distribusi, full_path, type): app.logger.error("Something went wrong!") except IntegrityError: db.session.rollback() - app.logger.error("file %s already exists!", full_path) + app.logger.error("File %s already exists!", full_path) except DataError: db.session.rollback() app.logger.error("%s Invalid Entry", full_path) diff --git a/verse/forms/selectorform.py b/verse/forms/selectorform.py index d726971..f2f9530 100644 --- a/verse/forms/selectorform.py +++ b/verse/forms/selectorform.py @@ -9,4 +9,6 @@ class SelectorForm(FlaskForm): update = SubmitField("update") + describe = SubmitField("describe") + delete = SubmitField("delete") diff --git a/verse/migrations/versions/8ede45e978d9_.py b/verse/migrations/versions/8ede45e978d9_.py deleted file mode 100644 index 2bdb676..0000000 --- a/verse/migrations/versions/8ede45e978d9_.py +++ /dev/null @@ -1,36 +0,0 @@ -"""empty message - -Revision ID: 8ede45e978d9 -Revises: -Create Date: 2024-04-30 22:15:48.023060 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '8ede45e978d9' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('distribusi_files', schema=None) as batch_op: - batch_op.alter_column('type', - existing_type=sa.VARCHAR(length=300), - nullable=True) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('distribusi_files', schema=None) as batch_op: - batch_op.alter_column('type', - existing_type=sa.VARCHAR(length=300), - nullable=False) - - # ### end Alembic commands ### diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 5e3f5ac..23003b1 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -15,4 +15,4 @@ class DistribusiFiles(db.Model): description = db.Column(db.String(4096), nullable=True, unique=False) def __repr__(self): - return "" % self.distribusiname + return "" % self.path diff --git a/verse/start.py b/verse/start.py index 5cbe8c5..33be140 100644 --- a/verse/start.py +++ b/verse/start.py @@ -2,25 +2,17 @@ from datetime import timedelta -from flask import ( - Blueprint, - redirect, - render_template, - send_from_directory, - session, - url_for, -) +from flask import (Blueprint, redirect, render_template, send_from_directory, + session, url_for) from flask_login import current_user, login_required, logout_user from flask_mail import Mail from flask_wtf.csrf import CSRFError -# Interface! these are seperate files in main folder from adminpage import AdminPage from app import create_app, login_manager +from describer.describe_files import describer from distribusikan.distribusikan import distribusikan from distribusikan.distribusisinfo import DistribusisInfo - -# Use upload form to populate filters from forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User @@ -31,11 +23,14 @@ from statuspengguna.registeruser import register_user APP = create_app() stash_page = Blueprint("stash_page", __name__, static_folder="stash") +APP.register_blueprint(stash_page) + +APP.register_blueprint(describer, url_prefix="/describe") APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(distribusikan) -APP.register_blueprint(stash_page) + @APP.before_request -- 2.39.2 From bbf2fcf047c074c019022be44695f7c9f2f0b4e9 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 19 May 2024 11:29:40 +0200 Subject: [PATCH 09/49] ruff refactoring --- verse/app.py | 1 - verse/describer/describe_files.py | 6 ++++-- verse/describer/forms/describe_file_form.py | 4 ++-- verse/describer/templates/describe_files/describe.html | 2 +- verse/distribusikan/distribusikan.py | 1 - verse/distribusikan/distribusiselector.py | 4 +--- verse/file_crawler.py | 2 +- verse/forms/registerform.py | 2 +- verse/forms/uploadform.py | 2 -- verse/start.py | 1 - verse/statuspengguna/loginuser.py | 2 -- verse/statuspengguna/resetpassword.py | 3 +-- 12 files changed, 11 insertions(+), 19 deletions(-) diff --git a/verse/app.py b/verse/app.py index eb49b8e..529db20 100644 --- a/verse/app.py +++ b/verse/app.py @@ -64,7 +64,6 @@ def get_app(): def settings_from_file(): - settings = {} if os.path.isfile("settings_development.toml"): with open("settings_development.toml", "rb") as settings_file: return tomllib.load(settings_file) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index ac41c4d..28154f1 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -1,4 +1,5 @@ -from flask import Blueprint, render_template +from flask import Blueprint, render_template, redirect, url_for +from flask_login import current_user from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles @@ -12,11 +13,12 @@ describer = Blueprint( @describer.route("/") def describe_distribusi_files(distribusiname): + if not current_user.is_authenticated: + return redirect(url_for("index")) distribusi = Distribusis.query.filter_by( distribusiname=distribusiname ).first() distribusi_files = DistribusiFiles.query.filter_by( distribusi=distribusi.id ).all() - print(distribusi_files) return render_template("describe.html", distribusi_files=distribusi_files) diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py index a61ab4c..286c448 100644 --- a/verse/describer/forms/describe_file_form.py +++ b/verse/describer/forms/describe_file_form.py @@ -1,8 +1,8 @@ """Describe File Form to describe files in the distribusi archive""" from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField - +from wtforms import StringField, SubmitField, validators +from wtforms.validators import Length class DescribeFileForm(FlaskForm): """DescribeFileForm selection form.""" diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 700d154..22b486d 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -28,7 +28,7 @@

{% for file in distribusi_files %} -

{{file}}

+

{{file.path}}

{% endfor%}
{% endblock %} diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py index 4ba50ae..444cb96 100644 --- a/verse/distribusikan/distribusikan.py +++ b/verse/distribusikan/distribusikan.py @@ -4,7 +4,6 @@ from flask_login import login_required from distribusikan.distribusiselector import DistribusiSelector # Distribusi Information -from distribusikan.distribusisinfo import DistribusisInfo from distribusikan.distribusiworkflow import DistribusiWorkflow from distribusikan.editor import Editor from distribusikan.themeselector import ThemeSelector diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index 2ceb8fc..ea55d43 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -10,9 +10,8 @@ from sqlalchemy.exc import ( InvalidRequestError, ) -from app import db, get_app +from app import db from distribusikan.distribusisinfo import DistribusisInfo -from describer.describe_files import describe_distribusi_files from forms.distribusiform import DistribusiForm from forms.publicthemeform import PublicThemeForm from forms.selectorform import SelectorForm @@ -68,7 +67,6 @@ def SelectNewDistribusi(): def SelectDescribeDistribusi(distribusiname): - app = get_app return redirect( url_for( "describer.describe_distribusi_files", diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 0a38280..b395138 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -1,7 +1,7 @@ import os import magic -from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES +from distribusi.mappings import FILE_TYPES from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from app import create_app, get_app, db diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py index cca23ab..89c42d6 100644 --- a/verse/forms/registerform.py +++ b/verse/forms/registerform.py @@ -2,7 +2,7 @@ from flask_wtf import FlaskForm from wtforms import PasswordField, StringField, SubmitField, validators -from wtforms.validators import Email, EqualTo, Length, ValidationError +from wtforms.validators import Email, EqualTo, Length class RegisterForm(FlaskForm): diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py index 261d1cd..90dcd70 100644 --- a/verse/forms/uploadform.py +++ b/verse/forms/uploadform.py @@ -1,7 +1,6 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField, FileRequired, FileSize from wtforms import ( - IntegerField, SelectField, StringField, SubmitField, @@ -10,7 +9,6 @@ from wtforms import ( from wtforms.validators import ( DataRequired, Length, - NumberRange, ValidationError, ) diff --git a/verse/start.py b/verse/start.py index 33be140..91a7c8e 100644 --- a/verse/start.py +++ b/verse/start.py @@ -5,7 +5,6 @@ from datetime import timedelta from flask import (Blueprint, redirect, render_template, send_from_directory, session, url_for) from flask_login import current_user, login_required, logout_user -from flask_mail import Mail from flask_wtf.csrf import CSRFError from adminpage import AdminPage diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py index 5d72063..6f18cde 100644 --- a/verse/statuspengguna/loginuser.py +++ b/verse/statuspengguna/loginuser.py @@ -5,8 +5,6 @@ from flask import ( redirect, render_template, request, - send_from_directory, - session, url_for, ) from flask_bcrypt import check_password_hash diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py index a75f86e..c0288ae 100644 --- a/verse/statuspengguna/resetpassword.py +++ b/verse/statuspengguna/resetpassword.py @@ -1,6 +1,6 @@ from datetime import datetime -from flask import flash, redirect, render_template, url_for +from flask import Blueprint, flash, redirect, render_template, url_for from flask_bcrypt import generate_password_hash from flask_login import login_user from sqlalchemy.exc import ( @@ -15,7 +15,6 @@ from werkzeug.routing import BuildError from app import db from forms.resetpasswordform import ResetPasswordForm from models.user_model import User -from statuspengguna import statuspengguna reset_password = Blueprint( "reset_password", -- 2.39.2 From 2620890ddbe11a4f8042fcd6e73713e2a907ad0a Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 20 May 2024 22:52:58 +0200 Subject: [PATCH 10/49] remove unused git folder --- LICENSE | 0 README.md | 0 __init.py__ | 0 makefile | 0 pyproject.toml | 0 requirements.txt | 0 setup.py | 0 verse/= | 0 verse/__init.py__ | 0 verse/adminpage.py | 0 verse/admintool.py | 0 verse/app.py | 0 verse/deploydb.py | 0 verse/describer/describe_files.py | 0 verse/describer/forms/describe_file_form.py | 0 .../templates/describe_files/describe.html | 0 verse/distribusikan/distribusikan.py | 0 verse/distribusikan/distribusiselector.py | 0 verse/distribusikan/distribusisinfo.py | 0 verse/distribusikan/distribusiworkflow.py | 0 verse/distribusikan/editor.py | 0 .../templates/distribusikan/distribusi.html | 0 .../distribusikan/distribusiworkflow/editcss.html | 0 .../distribusikan/distribusiworkflow/launch.html | 0 .../distribusikan/distribusiworkflow/selector.html | 0 .../distribusikan/distribusiworkflow/theme.html | 0 .../distribusikan/distribusiworkflow/upload.html | 0 .../templates/distribusikan/editor.html | 0 verse/distribusikan/themeselector.py | 0 verse/distribusikan/upload.py | 0 verse/distribusikan/uploadpage.py | 0 verse/file_crawler.py | 0 verse/forms/admindistribusiform.py | 0 verse/forms/adminuserform.py | 0 verse/forms/distribusiform.py | 0 verse/forms/editorform.py | 0 verse/forms/forgotpasswordform.py | 0 verse/forms/loginform.py | 0 verse/forms/publicthemeform.py | 0 verse/forms/registerform.py | 0 verse/forms/resetpasswordform.py | 0 verse/forms/selectorform.py | 0 verse/forms/themeform.py | 0 verse/forms/uploadform.py | 0 verse/instance/.gitignore | 0 verse/migrations/README | 0 verse/migrations/alembic.ini | 0 verse/migrations/env.py | 0 verse/migrations/script.py.mako | 0 verse/models/distribusi_file_model.py | 0 verse/models/distribusi_model.py | 0 verse/models/user_model.py | 0 verse/settings.toml | 0 verse/start.py | 11 ++++++++--- verse/stash/.gitignore | 0 verse/static/css/dropdown.css | 0 verse/static/css/editor.css | 0 verse/static/css/selector.css | 0 verse/static/css/style.css | 0 verse/static/icons/about.txt | 0 verse/static/icons/android-chrome-192x192.png | Bin verse/static/icons/android-chrome-512x512.png | Bin verse/static/icons/apple-touch-icon.png | Bin verse/static/icons/favicon-16x16.png | Bin verse/static/icons/favicon-32x32.png | Bin verse/static/icons/favicon.ico | Bin verse/static/icons/site.webmanifest | 0 verse/static/js/dropdown.js | 0 verse/static/js/editorupdate.js | 0 verse/static/js/script.js | 0 verse/static/svg/arrow_1.svg | 0 verse/static/svg/arrow_2.svg | 0 verse/static/svg/arrow_3.svg | 0 verse/statuspengguna/__init__.py | 0 verse/statuspengguna/forgotpassword.py | 0 verse/statuspengguna/helper.py | 0 verse/statuspengguna/loginuser.py | 0 verse/statuspengguna/registeruser.py | 0 verse/statuspengguna/resetpassword.py | 0 verse/statuspengguna/static/css/dropdown.css | 0 verse/statuspengguna/static/css/editor.css | 0 verse/statuspengguna/static/css/selector.css | 0 verse/statuspengguna/static/css/style.css | 0 verse/statuspengguna/static/icons/about.txt | 0 .../static/icons/android-chrome-192x192.png | Bin .../static/icons/android-chrome-512x512.png | Bin .../static/icons/apple-touch-icon.png | Bin verse/statuspengguna/static/icons/favicon-16x16.png | Bin verse/statuspengguna/static/icons/favicon-32x32.png | Bin verse/statuspengguna/static/icons/favicon.ico | Bin verse/statuspengguna/static/icons/site.webmanifest | 0 verse/statuspengguna/static/js/dropdown.js | 0 verse/statuspengguna/static/js/editorupdate.js | 0 verse/statuspengguna/static/js/script.js | 0 verse/statuspengguna/static/svg/arrow_1.svg | 0 verse/statuspengguna/static/svg/arrow_2.svg | 0 verse/statuspengguna/static/svg/arrow_3.svg | 0 .../templates/statuspengguna/forgotpassword.html | 0 .../templates/statuspengguna/login.html | 0 .../templates/statuspengguna/register.html | 0 .../templates/statuspengguna/resetpassword.html | 0 verse/templates/base/admin.html | 0 verse/templates/base/base.html | 0 verse/templates/base/filtermenu.html | 0 verse/templates/base/help.html | 0 verse/templates/base/index.html | 0 verse/themes/editor/placeholder.css | 0 verse/themes/editor/placeholder.html | 0 verse/themes/hacking.css | 0 verse/themes/masonry.css | 0 verse/themes/peachsunset.css | 0 verse/themes/publicthemes/.gitignore | 0 verse/themes/userthemes/.gitignore | 0 verse/tmpupload/.gitignore | 0 114 files changed, 8 insertions(+), 3 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 __init.py__ mode change 100644 => 100755 makefile mode change 100644 => 100755 pyproject.toml mode change 100644 => 100755 requirements.txt mode change 100644 => 100755 setup.py create mode 100755 verse/= mode change 100644 => 100755 verse/__init.py__ mode change 100644 => 100755 verse/adminpage.py mode change 100644 => 100755 verse/admintool.py mode change 100644 => 100755 verse/app.py mode change 100644 => 100755 verse/deploydb.py mode change 100644 => 100755 verse/describer/describe_files.py mode change 100644 => 100755 verse/describer/forms/describe_file_form.py mode change 100644 => 100755 verse/describer/templates/describe_files/describe.html mode change 100644 => 100755 verse/distribusikan/distribusikan.py mode change 100644 => 100755 verse/distribusikan/distribusiselector.py mode change 100644 => 100755 verse/distribusikan/distribusisinfo.py mode change 100644 => 100755 verse/distribusikan/distribusiworkflow.py mode change 100644 => 100755 verse/distribusikan/editor.py mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusi.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html mode change 100644 => 100755 verse/distribusikan/templates/distribusikan/editor.html mode change 100644 => 100755 verse/distribusikan/themeselector.py mode change 100644 => 100755 verse/distribusikan/upload.py mode change 100644 => 100755 verse/distribusikan/uploadpage.py mode change 100644 => 100755 verse/file_crawler.py mode change 100644 => 100755 verse/forms/admindistribusiform.py mode change 100644 => 100755 verse/forms/adminuserform.py mode change 100644 => 100755 verse/forms/distribusiform.py mode change 100644 => 100755 verse/forms/editorform.py mode change 100644 => 100755 verse/forms/forgotpasswordform.py mode change 100644 => 100755 verse/forms/loginform.py mode change 100644 => 100755 verse/forms/publicthemeform.py mode change 100644 => 100755 verse/forms/registerform.py mode change 100644 => 100755 verse/forms/resetpasswordform.py mode change 100644 => 100755 verse/forms/selectorform.py mode change 100644 => 100755 verse/forms/themeform.py mode change 100644 => 100755 verse/forms/uploadform.py mode change 100644 => 100755 verse/instance/.gitignore mode change 100644 => 100755 verse/migrations/README mode change 100644 => 100755 verse/migrations/alembic.ini mode change 100644 => 100755 verse/migrations/env.py mode change 100644 => 100755 verse/migrations/script.py.mako mode change 100644 => 100755 verse/models/distribusi_file_model.py mode change 100644 => 100755 verse/models/distribusi_model.py mode change 100644 => 100755 verse/models/user_model.py mode change 100644 => 100755 verse/settings.toml mode change 100644 => 100755 verse/start.py mode change 100644 => 100755 verse/stash/.gitignore mode change 100644 => 100755 verse/static/css/dropdown.css mode change 100644 => 100755 verse/static/css/editor.css mode change 100644 => 100755 verse/static/css/selector.css mode change 100644 => 100755 verse/static/css/style.css mode change 100644 => 100755 verse/static/icons/about.txt mode change 100644 => 100755 verse/static/icons/android-chrome-192x192.png mode change 100644 => 100755 verse/static/icons/android-chrome-512x512.png mode change 100644 => 100755 verse/static/icons/apple-touch-icon.png mode change 100644 => 100755 verse/static/icons/favicon-16x16.png mode change 100644 => 100755 verse/static/icons/favicon-32x32.png mode change 100644 => 100755 verse/static/icons/favicon.ico mode change 100644 => 100755 verse/static/icons/site.webmanifest mode change 100644 => 100755 verse/static/js/dropdown.js mode change 100644 => 100755 verse/static/js/editorupdate.js mode change 100644 => 100755 verse/static/js/script.js mode change 100644 => 100755 verse/static/svg/arrow_1.svg mode change 100644 => 100755 verse/static/svg/arrow_2.svg mode change 100644 => 100755 verse/static/svg/arrow_3.svg mode change 100644 => 100755 verse/statuspengguna/__init__.py mode change 100644 => 100755 verse/statuspengguna/forgotpassword.py mode change 100644 => 100755 verse/statuspengguna/helper.py mode change 100644 => 100755 verse/statuspengguna/loginuser.py mode change 100644 => 100755 verse/statuspengguna/registeruser.py mode change 100644 => 100755 verse/statuspengguna/resetpassword.py mode change 100644 => 100755 verse/statuspengguna/static/css/dropdown.css mode change 100644 => 100755 verse/statuspengguna/static/css/editor.css mode change 100644 => 100755 verse/statuspengguna/static/css/selector.css mode change 100644 => 100755 verse/statuspengguna/static/css/style.css mode change 100644 => 100755 verse/statuspengguna/static/icons/about.txt mode change 100644 => 100755 verse/statuspengguna/static/icons/android-chrome-192x192.png mode change 100644 => 100755 verse/statuspengguna/static/icons/android-chrome-512x512.png mode change 100644 => 100755 verse/statuspengguna/static/icons/apple-touch-icon.png mode change 100644 => 100755 verse/statuspengguna/static/icons/favicon-16x16.png mode change 100644 => 100755 verse/statuspengguna/static/icons/favicon-32x32.png mode change 100644 => 100755 verse/statuspengguna/static/icons/favicon.ico mode change 100644 => 100755 verse/statuspengguna/static/icons/site.webmanifest mode change 100644 => 100755 verse/statuspengguna/static/js/dropdown.js mode change 100644 => 100755 verse/statuspengguna/static/js/editorupdate.js mode change 100644 => 100755 verse/statuspengguna/static/js/script.js mode change 100644 => 100755 verse/statuspengguna/static/svg/arrow_1.svg mode change 100644 => 100755 verse/statuspengguna/static/svg/arrow_2.svg mode change 100644 => 100755 verse/statuspengguna/static/svg/arrow_3.svg mode change 100644 => 100755 verse/statuspengguna/templates/statuspengguna/forgotpassword.html mode change 100644 => 100755 verse/statuspengguna/templates/statuspengguna/login.html mode change 100644 => 100755 verse/statuspengguna/templates/statuspengguna/register.html mode change 100644 => 100755 verse/statuspengguna/templates/statuspengguna/resetpassword.html mode change 100644 => 100755 verse/templates/base/admin.html mode change 100644 => 100755 verse/templates/base/base.html mode change 100644 => 100755 verse/templates/base/filtermenu.html mode change 100644 => 100755 verse/templates/base/help.html mode change 100644 => 100755 verse/templates/base/index.html mode change 100644 => 100755 verse/themes/editor/placeholder.css mode change 100644 => 100755 verse/themes/editor/placeholder.html mode change 100644 => 100755 verse/themes/hacking.css mode change 100644 => 100755 verse/themes/masonry.css mode change 100644 => 100755 verse/themes/peachsunset.css mode change 100644 => 100755 verse/themes/publicthemes/.gitignore mode change 100644 => 100755 verse/themes/userthemes/.gitignore mode change 100644 => 100755 verse/tmpupload/.gitignore diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/__init.py__ b/__init.py__ old mode 100644 new mode 100755 diff --git a/makefile b/makefile old mode 100644 new mode 100755 diff --git a/pyproject.toml b/pyproject.toml old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 diff --git a/verse/= b/verse/= new file mode 100755 index 0000000..e69de29 diff --git a/verse/__init.py__ b/verse/__init.py__ old mode 100644 new mode 100755 diff --git a/verse/adminpage.py b/verse/adminpage.py old mode 100644 new mode 100755 diff --git a/verse/admintool.py b/verse/admintool.py old mode 100644 new mode 100755 diff --git a/verse/app.py b/verse/app.py old mode 100644 new mode 100755 diff --git a/verse/deploydb.py b/verse/deploydb.py old mode 100644 new mode 100755 diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py old mode 100644 new mode 100755 diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py old mode 100644 new mode 100755 diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/distribusisinfo.py b/verse/distribusikan/distribusisinfo.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusiworkflow.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/editor.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusi.html b/verse/distribusikan/templates/distribusikan/distribusi.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/templates/distribusikan/editor.html b/verse/distribusikan/templates/distribusikan/editor.html old mode 100644 new mode 100755 diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/themeselector.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py old mode 100644 new mode 100755 diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/uploadpage.py old mode 100644 new mode 100755 diff --git a/verse/file_crawler.py b/verse/file_crawler.py old mode 100644 new mode 100755 diff --git a/verse/forms/admindistribusiform.py b/verse/forms/admindistribusiform.py old mode 100644 new mode 100755 diff --git a/verse/forms/adminuserform.py b/verse/forms/adminuserform.py old mode 100644 new mode 100755 diff --git a/verse/forms/distribusiform.py b/verse/forms/distribusiform.py old mode 100644 new mode 100755 diff --git a/verse/forms/editorform.py b/verse/forms/editorform.py old mode 100644 new mode 100755 diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py old mode 100644 new mode 100755 diff --git a/verse/forms/loginform.py b/verse/forms/loginform.py old mode 100644 new mode 100755 diff --git a/verse/forms/publicthemeform.py b/verse/forms/publicthemeform.py old mode 100644 new mode 100755 diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py old mode 100644 new mode 100755 diff --git a/verse/forms/resetpasswordform.py b/verse/forms/resetpasswordform.py old mode 100644 new mode 100755 diff --git a/verse/forms/selectorform.py b/verse/forms/selectorform.py old mode 100644 new mode 100755 diff --git a/verse/forms/themeform.py b/verse/forms/themeform.py old mode 100644 new mode 100755 diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py old mode 100644 new mode 100755 diff --git a/verse/instance/.gitignore b/verse/instance/.gitignore old mode 100644 new mode 100755 diff --git a/verse/migrations/README b/verse/migrations/README old mode 100644 new mode 100755 diff --git a/verse/migrations/alembic.ini b/verse/migrations/alembic.ini old mode 100644 new mode 100755 diff --git a/verse/migrations/env.py b/verse/migrations/env.py old mode 100644 new mode 100755 diff --git a/verse/migrations/script.py.mako b/verse/migrations/script.py.mako old mode 100644 new mode 100755 diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py old mode 100644 new mode 100755 diff --git a/verse/models/distribusi_model.py b/verse/models/distribusi_model.py old mode 100644 new mode 100755 diff --git a/verse/models/user_model.py b/verse/models/user_model.py old mode 100644 new mode 100755 diff --git a/verse/settings.toml b/verse/settings.toml old mode 100644 new mode 100755 diff --git a/verse/start.py b/verse/start.py old mode 100644 new mode 100755 index 91a7c8e..8fe45df --- a/verse/start.py +++ b/verse/start.py @@ -2,8 +2,14 @@ from datetime import timedelta -from flask import (Blueprint, redirect, render_template, send_from_directory, - session, url_for) +from flask import ( + Blueprint, + redirect, + render_template, + send_from_directory, + session, + url_for, +) from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError @@ -31,7 +37,6 @@ APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(distribusikan) - @APP.before_request def session_handler(): session.permanent = True diff --git a/verse/stash/.gitignore b/verse/stash/.gitignore old mode 100644 new mode 100755 diff --git a/verse/static/css/dropdown.css b/verse/static/css/dropdown.css old mode 100644 new mode 100755 diff --git a/verse/static/css/editor.css b/verse/static/css/editor.css old mode 100644 new mode 100755 diff --git a/verse/static/css/selector.css b/verse/static/css/selector.css old mode 100644 new mode 100755 diff --git a/verse/static/css/style.css b/verse/static/css/style.css old mode 100644 new mode 100755 diff --git a/verse/static/icons/about.txt b/verse/static/icons/about.txt old mode 100644 new mode 100755 diff --git a/verse/static/icons/android-chrome-192x192.png b/verse/static/icons/android-chrome-192x192.png old mode 100644 new mode 100755 diff --git a/verse/static/icons/android-chrome-512x512.png b/verse/static/icons/android-chrome-512x512.png old mode 100644 new mode 100755 diff --git a/verse/static/icons/apple-touch-icon.png b/verse/static/icons/apple-touch-icon.png old mode 100644 new mode 100755 diff --git a/verse/static/icons/favicon-16x16.png b/verse/static/icons/favicon-16x16.png old mode 100644 new mode 100755 diff --git a/verse/static/icons/favicon-32x32.png b/verse/static/icons/favicon-32x32.png old mode 100644 new mode 100755 diff --git a/verse/static/icons/favicon.ico b/verse/static/icons/favicon.ico old mode 100644 new mode 100755 diff --git a/verse/static/icons/site.webmanifest b/verse/static/icons/site.webmanifest old mode 100644 new mode 100755 diff --git a/verse/static/js/dropdown.js b/verse/static/js/dropdown.js old mode 100644 new mode 100755 diff --git a/verse/static/js/editorupdate.js b/verse/static/js/editorupdate.js old mode 100644 new mode 100755 diff --git a/verse/static/js/script.js b/verse/static/js/script.js old mode 100644 new mode 100755 diff --git a/verse/static/svg/arrow_1.svg b/verse/static/svg/arrow_1.svg old mode 100644 new mode 100755 diff --git a/verse/static/svg/arrow_2.svg b/verse/static/svg/arrow_2.svg old mode 100644 new mode 100755 diff --git a/verse/static/svg/arrow_3.svg b/verse/static/svg/arrow_3.svg old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/__init__.py b/verse/statuspengguna/__init__.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/registeruser.py b/verse/statuspengguna/registeruser.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/css/dropdown.css b/verse/statuspengguna/static/css/dropdown.css old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/css/editor.css b/verse/statuspengguna/static/css/editor.css old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/css/selector.css b/verse/statuspengguna/static/css/selector.css old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/css/style.css b/verse/statuspengguna/static/css/style.css old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/about.txt b/verse/statuspengguna/static/icons/about.txt old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/android-chrome-192x192.png b/verse/statuspengguna/static/icons/android-chrome-192x192.png old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/android-chrome-512x512.png b/verse/statuspengguna/static/icons/android-chrome-512x512.png old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/apple-touch-icon.png b/verse/statuspengguna/static/icons/apple-touch-icon.png old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/favicon-16x16.png b/verse/statuspengguna/static/icons/favicon-16x16.png old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/favicon-32x32.png b/verse/statuspengguna/static/icons/favicon-32x32.png old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/favicon.ico b/verse/statuspengguna/static/icons/favicon.ico old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/icons/site.webmanifest b/verse/statuspengguna/static/icons/site.webmanifest old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/js/dropdown.js b/verse/statuspengguna/static/js/dropdown.js old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/js/editorupdate.js b/verse/statuspengguna/static/js/editorupdate.js old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/js/script.js b/verse/statuspengguna/static/js/script.js old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/svg/arrow_1.svg b/verse/statuspengguna/static/svg/arrow_1.svg old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/svg/arrow_2.svg b/verse/statuspengguna/static/svg/arrow_2.svg old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/static/svg/arrow_3.svg b/verse/statuspengguna/static/svg/arrow_3.svg old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/templates/statuspengguna/forgotpassword.html b/verse/statuspengguna/templates/statuspengguna/forgotpassword.html old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/templates/statuspengguna/login.html b/verse/statuspengguna/templates/statuspengguna/login.html old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/templates/statuspengguna/register.html b/verse/statuspengguna/templates/statuspengguna/register.html old mode 100644 new mode 100755 diff --git a/verse/statuspengguna/templates/statuspengguna/resetpassword.html b/verse/statuspengguna/templates/statuspengguna/resetpassword.html old mode 100644 new mode 100755 diff --git a/verse/templates/base/admin.html b/verse/templates/base/admin.html old mode 100644 new mode 100755 diff --git a/verse/templates/base/base.html b/verse/templates/base/base.html old mode 100644 new mode 100755 diff --git a/verse/templates/base/filtermenu.html b/verse/templates/base/filtermenu.html old mode 100644 new mode 100755 diff --git a/verse/templates/base/help.html b/verse/templates/base/help.html old mode 100644 new mode 100755 diff --git a/verse/templates/base/index.html b/verse/templates/base/index.html old mode 100644 new mode 100755 diff --git a/verse/themes/editor/placeholder.css b/verse/themes/editor/placeholder.css old mode 100644 new mode 100755 diff --git a/verse/themes/editor/placeholder.html b/verse/themes/editor/placeholder.html old mode 100644 new mode 100755 diff --git a/verse/themes/hacking.css b/verse/themes/hacking.css old mode 100644 new mode 100755 diff --git a/verse/themes/masonry.css b/verse/themes/masonry.css old mode 100644 new mode 100755 diff --git a/verse/themes/peachsunset.css b/verse/themes/peachsunset.css old mode 100644 new mode 100755 diff --git a/verse/themes/publicthemes/.gitignore b/verse/themes/publicthemes/.gitignore old mode 100644 new mode 100755 diff --git a/verse/themes/userthemes/.gitignore b/verse/themes/userthemes/.gitignore old mode 100644 new mode 100755 diff --git a/verse/tmpupload/.gitignore b/verse/tmpupload/.gitignore old mode 100644 new mode 100755 -- 2.39.2 From 77238e687d2ee2234bb365675e7ad5522dc550f9 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 20 May 2024 23:01:06 +0200 Subject: [PATCH 11/49] Revert "remove unused git folder" This reverts commit 2620890ddbe11a4f8042fcd6e73713e2a907ad0a. --- LICENSE | 0 README.md | 0 __init.py__ | 0 makefile | 0 pyproject.toml | 0 requirements.txt | 0 setup.py | 0 verse/= | 0 verse/__init.py__ | 0 verse/adminpage.py | 0 verse/admintool.py | 0 verse/app.py | 0 verse/deploydb.py | 0 verse/describer/describe_files.py | 0 verse/describer/forms/describe_file_form.py | 0 .../templates/describe_files/describe.html | 0 verse/distribusikan/distribusikan.py | 0 verse/distribusikan/distribusiselector.py | 0 verse/distribusikan/distribusisinfo.py | 0 verse/distribusikan/distribusiworkflow.py | 0 verse/distribusikan/editor.py | 0 .../templates/distribusikan/distribusi.html | 0 .../distribusikan/distribusiworkflow/editcss.html | 0 .../distribusikan/distribusiworkflow/launch.html | 0 .../distribusikan/distribusiworkflow/selector.html | 0 .../distribusikan/distribusiworkflow/theme.html | 0 .../distribusikan/distribusiworkflow/upload.html | 0 .../templates/distribusikan/editor.html | 0 verse/distribusikan/themeselector.py | 0 verse/distribusikan/upload.py | 0 verse/distribusikan/uploadpage.py | 0 verse/file_crawler.py | 0 verse/forms/admindistribusiform.py | 0 verse/forms/adminuserform.py | 0 verse/forms/distribusiform.py | 0 verse/forms/editorform.py | 0 verse/forms/forgotpasswordform.py | 0 verse/forms/loginform.py | 0 verse/forms/publicthemeform.py | 0 verse/forms/registerform.py | 0 verse/forms/resetpasswordform.py | 0 verse/forms/selectorform.py | 0 verse/forms/themeform.py | 0 verse/forms/uploadform.py | 0 verse/instance/.gitignore | 0 verse/migrations/README | 0 verse/migrations/alembic.ini | 0 verse/migrations/env.py | 0 verse/migrations/script.py.mako | 0 verse/models/distribusi_file_model.py | 0 verse/models/distribusi_model.py | 0 verse/models/user_model.py | 0 verse/settings.toml | 0 verse/start.py | 11 +++-------- verse/stash/.gitignore | 0 verse/static/css/dropdown.css | 0 verse/static/css/editor.css | 0 verse/static/css/selector.css | 0 verse/static/css/style.css | 0 verse/static/icons/about.txt | 0 verse/static/icons/android-chrome-192x192.png | Bin verse/static/icons/android-chrome-512x512.png | Bin verse/static/icons/apple-touch-icon.png | Bin verse/static/icons/favicon-16x16.png | Bin verse/static/icons/favicon-32x32.png | Bin verse/static/icons/favicon.ico | Bin verse/static/icons/site.webmanifest | 0 verse/static/js/dropdown.js | 0 verse/static/js/editorupdate.js | 0 verse/static/js/script.js | 0 verse/static/svg/arrow_1.svg | 0 verse/static/svg/arrow_2.svg | 0 verse/static/svg/arrow_3.svg | 0 verse/statuspengguna/__init__.py | 0 verse/statuspengguna/forgotpassword.py | 0 verse/statuspengguna/helper.py | 0 verse/statuspengguna/loginuser.py | 0 verse/statuspengguna/registeruser.py | 0 verse/statuspengguna/resetpassword.py | 0 verse/statuspengguna/static/css/dropdown.css | 0 verse/statuspengguna/static/css/editor.css | 0 verse/statuspengguna/static/css/selector.css | 0 verse/statuspengguna/static/css/style.css | 0 verse/statuspengguna/static/icons/about.txt | 0 .../static/icons/android-chrome-192x192.png | Bin .../static/icons/android-chrome-512x512.png | Bin .../static/icons/apple-touch-icon.png | Bin verse/statuspengguna/static/icons/favicon-16x16.png | Bin verse/statuspengguna/static/icons/favicon-32x32.png | Bin verse/statuspengguna/static/icons/favicon.ico | Bin verse/statuspengguna/static/icons/site.webmanifest | 0 verse/statuspengguna/static/js/dropdown.js | 0 verse/statuspengguna/static/js/editorupdate.js | 0 verse/statuspengguna/static/js/script.js | 0 verse/statuspengguna/static/svg/arrow_1.svg | 0 verse/statuspengguna/static/svg/arrow_2.svg | 0 verse/statuspengguna/static/svg/arrow_3.svg | 0 .../templates/statuspengguna/forgotpassword.html | 0 .../templates/statuspengguna/login.html | 0 .../templates/statuspengguna/register.html | 0 .../templates/statuspengguna/resetpassword.html | 0 verse/templates/base/admin.html | 0 verse/templates/base/base.html | 0 verse/templates/base/filtermenu.html | 0 verse/templates/base/help.html | 0 verse/templates/base/index.html | 0 verse/themes/editor/placeholder.css | 0 verse/themes/editor/placeholder.html | 0 verse/themes/hacking.css | 0 verse/themes/masonry.css | 0 verse/themes/peachsunset.css | 0 verse/themes/publicthemes/.gitignore | 0 verse/themes/userthemes/.gitignore | 0 verse/tmpupload/.gitignore | 0 114 files changed, 3 insertions(+), 8 deletions(-) mode change 100755 => 100644 LICENSE mode change 100755 => 100644 README.md mode change 100755 => 100644 __init.py__ mode change 100755 => 100644 makefile mode change 100755 => 100644 pyproject.toml mode change 100755 => 100644 requirements.txt mode change 100755 => 100644 setup.py delete mode 100755 verse/= mode change 100755 => 100644 verse/__init.py__ mode change 100755 => 100644 verse/adminpage.py mode change 100755 => 100644 verse/admintool.py mode change 100755 => 100644 verse/app.py mode change 100755 => 100644 verse/deploydb.py mode change 100755 => 100644 verse/describer/describe_files.py mode change 100755 => 100644 verse/describer/forms/describe_file_form.py mode change 100755 => 100644 verse/describer/templates/describe_files/describe.html mode change 100755 => 100644 verse/distribusikan/distribusikan.py mode change 100755 => 100644 verse/distribusikan/distribusiselector.py mode change 100755 => 100644 verse/distribusikan/distribusisinfo.py mode change 100755 => 100644 verse/distribusikan/distribusiworkflow.py mode change 100755 => 100644 verse/distribusikan/editor.py mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusi.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html mode change 100755 => 100644 verse/distribusikan/templates/distribusikan/editor.html mode change 100755 => 100644 verse/distribusikan/themeselector.py mode change 100755 => 100644 verse/distribusikan/upload.py mode change 100755 => 100644 verse/distribusikan/uploadpage.py mode change 100755 => 100644 verse/file_crawler.py mode change 100755 => 100644 verse/forms/admindistribusiform.py mode change 100755 => 100644 verse/forms/adminuserform.py mode change 100755 => 100644 verse/forms/distribusiform.py mode change 100755 => 100644 verse/forms/editorform.py mode change 100755 => 100644 verse/forms/forgotpasswordform.py mode change 100755 => 100644 verse/forms/loginform.py mode change 100755 => 100644 verse/forms/publicthemeform.py mode change 100755 => 100644 verse/forms/registerform.py mode change 100755 => 100644 verse/forms/resetpasswordform.py mode change 100755 => 100644 verse/forms/selectorform.py mode change 100755 => 100644 verse/forms/themeform.py mode change 100755 => 100644 verse/forms/uploadform.py mode change 100755 => 100644 verse/instance/.gitignore mode change 100755 => 100644 verse/migrations/README mode change 100755 => 100644 verse/migrations/alembic.ini mode change 100755 => 100644 verse/migrations/env.py mode change 100755 => 100644 verse/migrations/script.py.mako mode change 100755 => 100644 verse/models/distribusi_file_model.py mode change 100755 => 100644 verse/models/distribusi_model.py mode change 100755 => 100644 verse/models/user_model.py mode change 100755 => 100644 verse/settings.toml mode change 100755 => 100644 verse/start.py mode change 100755 => 100644 verse/stash/.gitignore mode change 100755 => 100644 verse/static/css/dropdown.css mode change 100755 => 100644 verse/static/css/editor.css mode change 100755 => 100644 verse/static/css/selector.css mode change 100755 => 100644 verse/static/css/style.css mode change 100755 => 100644 verse/static/icons/about.txt mode change 100755 => 100644 verse/static/icons/android-chrome-192x192.png mode change 100755 => 100644 verse/static/icons/android-chrome-512x512.png mode change 100755 => 100644 verse/static/icons/apple-touch-icon.png mode change 100755 => 100644 verse/static/icons/favicon-16x16.png mode change 100755 => 100644 verse/static/icons/favicon-32x32.png mode change 100755 => 100644 verse/static/icons/favicon.ico mode change 100755 => 100644 verse/static/icons/site.webmanifest mode change 100755 => 100644 verse/static/js/dropdown.js mode change 100755 => 100644 verse/static/js/editorupdate.js mode change 100755 => 100644 verse/static/js/script.js mode change 100755 => 100644 verse/static/svg/arrow_1.svg mode change 100755 => 100644 verse/static/svg/arrow_2.svg mode change 100755 => 100644 verse/static/svg/arrow_3.svg mode change 100755 => 100644 verse/statuspengguna/__init__.py mode change 100755 => 100644 verse/statuspengguna/forgotpassword.py mode change 100755 => 100644 verse/statuspengguna/helper.py mode change 100755 => 100644 verse/statuspengguna/loginuser.py mode change 100755 => 100644 verse/statuspengguna/registeruser.py mode change 100755 => 100644 verse/statuspengguna/resetpassword.py mode change 100755 => 100644 verse/statuspengguna/static/css/dropdown.css mode change 100755 => 100644 verse/statuspengguna/static/css/editor.css mode change 100755 => 100644 verse/statuspengguna/static/css/selector.css mode change 100755 => 100644 verse/statuspengguna/static/css/style.css mode change 100755 => 100644 verse/statuspengguna/static/icons/about.txt mode change 100755 => 100644 verse/statuspengguna/static/icons/android-chrome-192x192.png mode change 100755 => 100644 verse/statuspengguna/static/icons/android-chrome-512x512.png mode change 100755 => 100644 verse/statuspengguna/static/icons/apple-touch-icon.png mode change 100755 => 100644 verse/statuspengguna/static/icons/favicon-16x16.png mode change 100755 => 100644 verse/statuspengguna/static/icons/favicon-32x32.png mode change 100755 => 100644 verse/statuspengguna/static/icons/favicon.ico mode change 100755 => 100644 verse/statuspengguna/static/icons/site.webmanifest mode change 100755 => 100644 verse/statuspengguna/static/js/dropdown.js mode change 100755 => 100644 verse/statuspengguna/static/js/editorupdate.js mode change 100755 => 100644 verse/statuspengguna/static/js/script.js mode change 100755 => 100644 verse/statuspengguna/static/svg/arrow_1.svg mode change 100755 => 100644 verse/statuspengguna/static/svg/arrow_2.svg mode change 100755 => 100644 verse/statuspengguna/static/svg/arrow_3.svg mode change 100755 => 100644 verse/statuspengguna/templates/statuspengguna/forgotpassword.html mode change 100755 => 100644 verse/statuspengguna/templates/statuspengguna/login.html mode change 100755 => 100644 verse/statuspengguna/templates/statuspengguna/register.html mode change 100755 => 100644 verse/statuspengguna/templates/statuspengguna/resetpassword.html mode change 100755 => 100644 verse/templates/base/admin.html mode change 100755 => 100644 verse/templates/base/base.html mode change 100755 => 100644 verse/templates/base/filtermenu.html mode change 100755 => 100644 verse/templates/base/help.html mode change 100755 => 100644 verse/templates/base/index.html mode change 100755 => 100644 verse/themes/editor/placeholder.css mode change 100755 => 100644 verse/themes/editor/placeholder.html mode change 100755 => 100644 verse/themes/hacking.css mode change 100755 => 100644 verse/themes/masonry.css mode change 100755 => 100644 verse/themes/peachsunset.css mode change 100755 => 100644 verse/themes/publicthemes/.gitignore mode change 100755 => 100644 verse/themes/userthemes/.gitignore mode change 100755 => 100644 verse/tmpupload/.gitignore diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 diff --git a/__init.py__ b/__init.py__ old mode 100755 new mode 100644 diff --git a/makefile b/makefile old mode 100755 new mode 100644 diff --git a/pyproject.toml b/pyproject.toml old mode 100755 new mode 100644 diff --git a/requirements.txt b/requirements.txt old mode 100755 new mode 100644 diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 diff --git a/verse/= b/verse/= deleted file mode 100755 index e69de29..0000000 diff --git a/verse/__init.py__ b/verse/__init.py__ old mode 100755 new mode 100644 diff --git a/verse/adminpage.py b/verse/adminpage.py old mode 100755 new mode 100644 diff --git a/verse/admintool.py b/verse/admintool.py old mode 100755 new mode 100644 diff --git a/verse/app.py b/verse/app.py old mode 100755 new mode 100644 diff --git a/verse/deploydb.py b/verse/deploydb.py old mode 100755 new mode 100644 diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py old mode 100755 new mode 100644 diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py old mode 100755 new mode 100644 diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/distribusisinfo.py b/verse/distribusikan/distribusisinfo.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusiworkflow.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/editor.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusi.html b/verse/distribusikan/templates/distribusikan/distribusi.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/templates/distribusikan/editor.html b/verse/distribusikan/templates/distribusikan/editor.html old mode 100755 new mode 100644 diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/themeselector.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py old mode 100755 new mode 100644 diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/uploadpage.py old mode 100755 new mode 100644 diff --git a/verse/file_crawler.py b/verse/file_crawler.py old mode 100755 new mode 100644 diff --git a/verse/forms/admindistribusiform.py b/verse/forms/admindistribusiform.py old mode 100755 new mode 100644 diff --git a/verse/forms/adminuserform.py b/verse/forms/adminuserform.py old mode 100755 new mode 100644 diff --git a/verse/forms/distribusiform.py b/verse/forms/distribusiform.py old mode 100755 new mode 100644 diff --git a/verse/forms/editorform.py b/verse/forms/editorform.py old mode 100755 new mode 100644 diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py old mode 100755 new mode 100644 diff --git a/verse/forms/loginform.py b/verse/forms/loginform.py old mode 100755 new mode 100644 diff --git a/verse/forms/publicthemeform.py b/verse/forms/publicthemeform.py old mode 100755 new mode 100644 diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py old mode 100755 new mode 100644 diff --git a/verse/forms/resetpasswordform.py b/verse/forms/resetpasswordform.py old mode 100755 new mode 100644 diff --git a/verse/forms/selectorform.py b/verse/forms/selectorform.py old mode 100755 new mode 100644 diff --git a/verse/forms/themeform.py b/verse/forms/themeform.py old mode 100755 new mode 100644 diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py old mode 100755 new mode 100644 diff --git a/verse/instance/.gitignore b/verse/instance/.gitignore old mode 100755 new mode 100644 diff --git a/verse/migrations/README b/verse/migrations/README old mode 100755 new mode 100644 diff --git a/verse/migrations/alembic.ini b/verse/migrations/alembic.ini old mode 100755 new mode 100644 diff --git a/verse/migrations/env.py b/verse/migrations/env.py old mode 100755 new mode 100644 diff --git a/verse/migrations/script.py.mako b/verse/migrations/script.py.mako old mode 100755 new mode 100644 diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py old mode 100755 new mode 100644 diff --git a/verse/models/distribusi_model.py b/verse/models/distribusi_model.py old mode 100755 new mode 100644 diff --git a/verse/models/user_model.py b/verse/models/user_model.py old mode 100755 new mode 100644 diff --git a/verse/settings.toml b/verse/settings.toml old mode 100755 new mode 100644 diff --git a/verse/start.py b/verse/start.py old mode 100755 new mode 100644 index 8fe45df..91a7c8e --- a/verse/start.py +++ b/verse/start.py @@ -2,14 +2,8 @@ from datetime import timedelta -from flask import ( - Blueprint, - redirect, - render_template, - send_from_directory, - session, - url_for, -) +from flask import (Blueprint, redirect, render_template, send_from_directory, + session, url_for) from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError @@ -37,6 +31,7 @@ APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(distribusikan) + @APP.before_request def session_handler(): session.permanent = True diff --git a/verse/stash/.gitignore b/verse/stash/.gitignore old mode 100755 new mode 100644 diff --git a/verse/static/css/dropdown.css b/verse/static/css/dropdown.css old mode 100755 new mode 100644 diff --git a/verse/static/css/editor.css b/verse/static/css/editor.css old mode 100755 new mode 100644 diff --git a/verse/static/css/selector.css b/verse/static/css/selector.css old mode 100755 new mode 100644 diff --git a/verse/static/css/style.css b/verse/static/css/style.css old mode 100755 new mode 100644 diff --git a/verse/static/icons/about.txt b/verse/static/icons/about.txt old mode 100755 new mode 100644 diff --git a/verse/static/icons/android-chrome-192x192.png b/verse/static/icons/android-chrome-192x192.png old mode 100755 new mode 100644 diff --git a/verse/static/icons/android-chrome-512x512.png b/verse/static/icons/android-chrome-512x512.png old mode 100755 new mode 100644 diff --git a/verse/static/icons/apple-touch-icon.png b/verse/static/icons/apple-touch-icon.png old mode 100755 new mode 100644 diff --git a/verse/static/icons/favicon-16x16.png b/verse/static/icons/favicon-16x16.png old mode 100755 new mode 100644 diff --git a/verse/static/icons/favicon-32x32.png b/verse/static/icons/favicon-32x32.png old mode 100755 new mode 100644 diff --git a/verse/static/icons/favicon.ico b/verse/static/icons/favicon.ico old mode 100755 new mode 100644 diff --git a/verse/static/icons/site.webmanifest b/verse/static/icons/site.webmanifest old mode 100755 new mode 100644 diff --git a/verse/static/js/dropdown.js b/verse/static/js/dropdown.js old mode 100755 new mode 100644 diff --git a/verse/static/js/editorupdate.js b/verse/static/js/editorupdate.js old mode 100755 new mode 100644 diff --git a/verse/static/js/script.js b/verse/static/js/script.js old mode 100755 new mode 100644 diff --git a/verse/static/svg/arrow_1.svg b/verse/static/svg/arrow_1.svg old mode 100755 new mode 100644 diff --git a/verse/static/svg/arrow_2.svg b/verse/static/svg/arrow_2.svg old mode 100755 new mode 100644 diff --git a/verse/static/svg/arrow_3.svg b/verse/static/svg/arrow_3.svg old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/__init__.py b/verse/statuspengguna/__init__.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/registeruser.py b/verse/statuspengguna/registeruser.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/css/dropdown.css b/verse/statuspengguna/static/css/dropdown.css old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/css/editor.css b/verse/statuspengguna/static/css/editor.css old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/css/selector.css b/verse/statuspengguna/static/css/selector.css old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/css/style.css b/verse/statuspengguna/static/css/style.css old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/about.txt b/verse/statuspengguna/static/icons/about.txt old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/android-chrome-192x192.png b/verse/statuspengguna/static/icons/android-chrome-192x192.png old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/android-chrome-512x512.png b/verse/statuspengguna/static/icons/android-chrome-512x512.png old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/apple-touch-icon.png b/verse/statuspengguna/static/icons/apple-touch-icon.png old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/favicon-16x16.png b/verse/statuspengguna/static/icons/favicon-16x16.png old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/favicon-32x32.png b/verse/statuspengguna/static/icons/favicon-32x32.png old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/favicon.ico b/verse/statuspengguna/static/icons/favicon.ico old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/icons/site.webmanifest b/verse/statuspengguna/static/icons/site.webmanifest old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/js/dropdown.js b/verse/statuspengguna/static/js/dropdown.js old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/js/editorupdate.js b/verse/statuspengguna/static/js/editorupdate.js old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/js/script.js b/verse/statuspengguna/static/js/script.js old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/svg/arrow_1.svg b/verse/statuspengguna/static/svg/arrow_1.svg old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/svg/arrow_2.svg b/verse/statuspengguna/static/svg/arrow_2.svg old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/static/svg/arrow_3.svg b/verse/statuspengguna/static/svg/arrow_3.svg old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/templates/statuspengguna/forgotpassword.html b/verse/statuspengguna/templates/statuspengguna/forgotpassword.html old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/templates/statuspengguna/login.html b/verse/statuspengguna/templates/statuspengguna/login.html old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/templates/statuspengguna/register.html b/verse/statuspengguna/templates/statuspengguna/register.html old mode 100755 new mode 100644 diff --git a/verse/statuspengguna/templates/statuspengguna/resetpassword.html b/verse/statuspengguna/templates/statuspengguna/resetpassword.html old mode 100755 new mode 100644 diff --git a/verse/templates/base/admin.html b/verse/templates/base/admin.html old mode 100755 new mode 100644 diff --git a/verse/templates/base/base.html b/verse/templates/base/base.html old mode 100755 new mode 100644 diff --git a/verse/templates/base/filtermenu.html b/verse/templates/base/filtermenu.html old mode 100755 new mode 100644 diff --git a/verse/templates/base/help.html b/verse/templates/base/help.html old mode 100755 new mode 100644 diff --git a/verse/templates/base/index.html b/verse/templates/base/index.html old mode 100755 new mode 100644 diff --git a/verse/themes/editor/placeholder.css b/verse/themes/editor/placeholder.css old mode 100755 new mode 100644 diff --git a/verse/themes/editor/placeholder.html b/verse/themes/editor/placeholder.html old mode 100755 new mode 100644 diff --git a/verse/themes/hacking.css b/verse/themes/hacking.css old mode 100755 new mode 100644 diff --git a/verse/themes/masonry.css b/verse/themes/masonry.css old mode 100755 new mode 100644 diff --git a/verse/themes/peachsunset.css b/verse/themes/peachsunset.css old mode 100755 new mode 100644 diff --git a/verse/themes/publicthemes/.gitignore b/verse/themes/publicthemes/.gitignore old mode 100755 new mode 100644 diff --git a/verse/themes/userthemes/.gitignore b/verse/themes/userthemes/.gitignore old mode 100755 new mode 100644 diff --git a/verse/tmpupload/.gitignore b/verse/tmpupload/.gitignore old mode 100755 new mode 100644 -- 2.39.2 From 0ddbe7fdd1c524e18012fda749ea795a4e203d02 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 20 May 2024 23:26:46 +0200 Subject: [PATCH 12/49] edit requirements for newer software, including new distribusi --- requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements.txt b/requirements.txt index 952979d..3d09491 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,9 +6,9 @@ black==24.4.0 bleach==4.1.0 bleach-allowlist==1.0.3 blinker==1.7.0 -cffi==1.15.0 +cffi click==8.1.7 -distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@e291e7497e40211c2ebd54ca32a1f4bdaed71230 +distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@4cb03d1131a43669912433b0a5c18596712add20 dnspython==2.1.0 email-validator==1.1.3 Flask==3.0.3 @@ -36,7 +36,7 @@ neovim==0.3.1 packaging==24.0 passlib==1.7.4 pathspec==0.9.0 -Pillow==8.3.2 +Pillow platformdirs==2.4.0 pycparser==2.21 pynvim==0.5.0 @@ -44,7 +44,7 @@ pyparsing==3.0.7 python-dateutil==2.9.0.post0 python-magic==0.4.24 pytz==2021.3 -regex==2021.11.10 +regex six==1.16.0 speaklater==1.3 SQLAlchemy==2.0.29 -- 2.39.2 From 23ac3e76993d2141501a29cf3ab4cfffd1e05dce Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 27 May 2024 13:29:30 +0200 Subject: [PATCH 13/49] ruff as new formatter and linter --- pyproject.toml | 68 +++-- verse/adminpage.py | 126 ++++----- verse/admintool.py | 54 ++-- verse/app.py | 72 ++--- verse/deploydb.py | 30 +-- verse/describer/describe_files.py | 34 ++- verse/describer/forms/describe_file_form.py | 47 ++-- verse/distribusikan/distribusikan.py | 18 +- verse/distribusikan/distribusiselector.py | 244 ++++++++--------- verse/distribusikan/distribusisinfo.py | 54 ++-- verse/distribusikan/distribusiworkflow.py | 176 ++++++------ verse/distribusikan/editor.py | 284 ++++++++++---------- verse/distribusikan/themeselector.py | 90 +++---- verse/distribusikan/upload.py | 136 +++++----- verse/distribusikan/uploadpage.py | 64 ++--- verse/file_crawler.py | 100 ++++--- verse/forms/admindistribusiform.py | 24 +- verse/forms/adminuserform.py | 24 +- verse/forms/distribusiform.py | 4 +- verse/forms/editorform.py | 46 ++-- verse/forms/forgotpasswordform.py | 12 +- verse/forms/loginform.py | 18 +- verse/forms/publicthemeform.py | 10 +- verse/forms/registerform.py | 52 ++-- verse/forms/resetpasswordform.py | 28 +- verse/forms/selectorform.py | 10 +- verse/forms/themeform.py | 20 +- verse/forms/uploadform.py | 134 ++++----- verse/migrations/env.py | 90 ++++--- verse/models/distribusi_file_model.py | 22 +- verse/models/distribusi_model.py | 24 +- verse/models/user_model.py | 24 +- verse/start.py | 105 ++++---- verse/statuspengguna/forgotpassword.py | 78 +++--- verse/statuspengguna/helper.py | 126 ++++----- verse/statuspengguna/loginuser.py | 70 ++--- verse/statuspengguna/registeruser.py | 110 ++++---- verse/statuspengguna/resetpassword.py | 126 ++++----- 38 files changed, 1396 insertions(+), 1358 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9b286c9..17f3822 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,25 +1,49 @@ -[tool.black] +[tool.ruff] line-length = 79 -target-version = ['py311'] -include = '\.pyi?$' -exclude = ''' -/( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist - - # The following are specific to Black, you probably don't want those. - | blib2to3 - | tests/data - | profiling -)/ -''' +target-version = "py311" +#include = '\.pyi?$' +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".ipynb_checkpoints", + ".mypy_cache", + ".nox", + ".pants.d", + ".pyenv", + ".pytest_cache", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + ".vscode", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "site-packages", + "venv", +] +[tool.ruff.lint] +# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. +select = ["E4", "E7", "E9", "F"] +ignore = [] +# Allow fix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +[tool.ruff.format] +quote-style = "double" +indent-style = "tab" +docstring-code-format = true +line-ending = "auto" +skip-magic-trailing-comma = false diff --git a/verse/adminpage.py b/verse/adminpage.py index 0bb1c39..9763e3e 100644 --- a/verse/adminpage.py +++ b/verse/adminpage.py @@ -3,10 +3,10 @@ import shutil from flask import render_template from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -18,88 +18,88 @@ from models.user_model import User def AdminPage(): - adminuserform = AddUsersToForm(AdminUserForm()) - admindistribusiform = AddDistribusisToForm(AdminDistribusiForm()) - if admindistribusiform.validate_on_submit(): - DeleteDistribusis(admindistribusiform) + adminuserform = AddUsersToForm(AdminUserForm()) + admindistribusiform = AddDistribusisToForm(AdminDistribusiForm()) + if admindistribusiform.validate_on_submit(): + DeleteDistribusis(admindistribusiform) - if adminuserform.validate_on_submit(): - if adminuserform.delete.data: - DeleteUsers(adminuserform) + if adminuserform.validate_on_submit(): + if adminuserform.delete.data: + DeleteUsers(adminuserform) - template = render_template( - "admin.html", - adminuserform=adminuserform, - admindistribusiform=admindistribusiform, - ) - return template + template = render_template( + "admin.html", + adminuserform=adminuserform, + admindistribusiform=admindistribusiform, + ) + return template def DeleteUsers(adminuserform): - for userform in adminuserform: - if "user" in userform.id: - if userform.data: - useremail = userform.label.text - user = User.query.filter_by(email=useremail).first() - DeleteUserDistribusis(user) - DeleteUserFromDb(user) - userform.errors.append(f"User {useremail} deleted!") + for userform in adminuserform: + if "user" in userform.id: + if userform.data: + useremail = userform.label.text + user = User.query.filter_by(email=useremail).first() + DeleteUserDistribusis(user) + DeleteUserFromDb(user) + userform.errors.append(f"User {useremail} deleted!") def DeleteUserFromDb(user): - try: - db.session.delete(user) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() + try: + db.session.delete(user) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() def DeleteUserDistribusis(user): - distribusis = DistribusisInfo.getuserdistribusis(user.email) - for distribusi in distribusis: - DeleteDistribusiFiles(distribusi.distribusiname) - DeleteDistribusiFromDb(distribusi) + distribusis = DistribusisInfo.getuserdistribusis(user.email) + for distribusi in distribusis: + DeleteDistribusiFiles(distribusi.distribusiname) + DeleteDistribusiFromDb(distribusi) def DeleteDistribusis(admindistribusiform): - for distribusiform in admindistribusiform: - if "distribusi" in distribusiform.id: - if distribusiform.data: - distribusiname = distribusiform.label.text - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - DeleteDistribusiFromDb(distribusi) - DeleteDistribusiFiles(distribusiname) - distribusiform.errors.append("Deleted distribusi") + for distribusiform in admindistribusiform: + if "distribusi" in distribusiform.id: + if distribusiform.data: + distribusiname = distribusiform.label.text + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + DeleteDistribusiFromDb(distribusi) + DeleteDistribusiFiles(distribusiname) + distribusiform.errors.append("Deleted distribusi") def DeleteDistribusiFromDb(distribusi): - try: - db.session.delete(distribusi) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() + try: + db.session.delete(distribusi) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() def DeleteDistribusiFiles(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - shutil.rmtree(userfolder) - cssfolder = os.path.join("themes/userthemes", distribusiname) - if os.path.exists(cssfolder): - shutil.rmtree(cssfolder) + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + shutil.rmtree(userfolder) + cssfolder = os.path.join("themes/userthemes", distribusiname) + if os.path.exists(cssfolder): + shutil.rmtree(cssfolder) def AddDistribusisToForm(admindistribusiform): - distribusis = DistribusisInfo.visibledistribusis() - admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( - distribusis - ) - return admindistribusiform + distribusis = DistribusisInfo.visibledistribusis() + admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( + distribusis + ) + return admindistribusiform def AddUsersToForm(adminuserform): - users = User.query.all() - adminuserform = AdminUserForm.user_list_form_builder(users) - return adminuserform + users = User.query.all() + adminuserform = AdminUserForm.user_list_form_builder(users) + return adminuserform diff --git a/verse/admintool.py b/verse/admintool.py index c8ddac3..def02bd 100644 --- a/verse/admintool.py +++ b/verse/admintool.py @@ -1,10 +1,10 @@ import sys from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import create_app, db @@ -13,32 +13,32 @@ from models.user_model import User # noqa: F401 def admintool(): - """Admin CLI tool. To elevate a user to admin""" - app = create_app() - app.app_context().push() - elevateusertoadmin() + """Admin CLI tool. To elevate a user to admin""" + app = create_app() + app.app_context().push() + elevateusertoadmin() def elevateusertoadmin(): - """To elevates user of first command line argument to admin""" - user = User.query.filter_by(email=sys.argv[1]).first() - print(f"user {user.username} found with email {user.email}") - try: - user.admin = True - db.session.commit() - print(f"Account {user.email} succesfully made into an admin") - except InvalidRequestError: - db.session.rollback() - print("Something went wrong!") - except InterfaceError: - db.session.rollback() - print("Error connecting to the database") - except DataError: - db.session.rollback() - print("Invalid Entry") - except DatabaseError: - db.session.rollback() - print("Error connecting to the database") + """To elevates user of first command line argument to admin""" + user = User.query.filter_by(email=sys.argv[1]).first() + print(f"user {user.username} found with email {user.email}") + try: + user.admin = True + db.session.commit() + print(f"Account {user.email} succesfully made into an admin") + except InvalidRequestError: + db.session.rollback() + print("Something went wrong!") + except InterfaceError: + db.session.rollback() + print("Error connecting to the database") + except DataError: + db.session.rollback() + print("Invalid Entry") + except DatabaseError: + db.session.rollback() + print("Error connecting to the database") admintool() diff --git a/verse/app.py b/verse/app.py index 529db20..9aff866 100644 --- a/verse/app.py +++ b/verse/app.py @@ -16,56 +16,56 @@ login_manager = LoginManager() def create_app(): - APP.secret_key = os.urandom(24) - APP.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///distribusiverse.db" - APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True + APP.secret_key = os.urandom(24) + APP.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///distribusiverse.db" + APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True - APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 - APP.config["MAIL_SERVER"] = "mail.autonomic.zone" - APP.config["MAIL_PORT"] = 587 - APP.config["MAIL_USE_SSL"] = False - APP.config["MAIL_USE_TLS"] = True - APP.config["MAIL_USERNAME"] = "noreply@vvvvvvaria.org" + APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 + APP.config["MAIL_SERVER"] = "mail.autonomic.zone" + APP.config["MAIL_PORT"] = 587 + APP.config["MAIL_USE_SSL"] = False + APP.config["MAIL_USE_TLS"] = True + APP.config["MAIL_USERNAME"] = "noreply@vvvvvvaria.org" - login_manager.session_protection = "strong" - login_manager.login_view = "index" - login_manager.login_message_category = "info" + login_manager.session_protection = "strong" + login_manager.login_view = "index" + login_manager.login_message_category = "info" - csrf = CSRFProtect() + csrf = CSRFProtect() - APP.config["SECRET_KEY"] = os.urandom(24) - APP.config["UPLOAD_FOLDER"] = "tmpupload" - APP.config["PUBLIC_THEMES"] = "themes/publicthemes" + APP.config["SECRET_KEY"] = os.urandom(24) + APP.config["UPLOAD_FOLDER"] = "tmpupload" + APP.config["PUBLIC_THEMES"] = "themes/publicthemes" - # user settings_file - settings() + # user settings_file + settings() - csrf.init_app(APP) - login_manager.init_app(APP) - db.init_app(APP) - migrate.init_app(APP, db, render_as_batch=True) - bcrypt.init_app(APP) + csrf.init_app(APP) + login_manager.init_app(APP) + db.init_app(APP) + migrate.init_app(APP, db, render_as_batch=True) + bcrypt.init_app(APP) - @APP.context_processor - def inject_title(): - return dict(title=APP.config["title"]) + @APP.context_processor + def inject_title(): + return dict(title=APP.config["title"]) - return APP + return APP def settings(): - settings = settings_from_file() - APP.config.update(settings) - return APP + settings = settings_from_file() + APP.config.update(settings) + return APP def get_app(): - return APP + return APP def settings_from_file(): - if os.path.isfile("settings_development.toml"): - with open("settings_development.toml", "rb") as settings_file: - return tomllib.load(settings_file) - with open("settings.toml", "rb") as settings_file: - return tomllib.load(settings_file) + if os.path.isfile("settings_development.toml"): + with open("settings_development.toml", "rb") as settings_file: + return tomllib.load(settings_file) + with open("settings.toml", "rb") as settings_file: + return tomllib.load(settings_file) diff --git a/verse/deploydb.py b/verse/deploydb.py index 30a8364..51d8f13 100644 --- a/verse/deploydb.py +++ b/verse/deploydb.py @@ -1,23 +1,23 @@ def deploy(): - """Run deployment of database.""" - from flask_migrate import init, migrate, stamp, upgrade + """Run deployment of database.""" + from flask_migrate import init, migrate, stamp, upgrade - from app import create_app, db - from models.distribusi_model import Distribusis # noqa: F401 - from models.distribusi_file_model import DistribusiFiles # noqa: F401 + from app import create_app, db + from models.distribusi_model import Distribusis # noqa: F401 + from models.distribusi_file_model import DistribusiFiles # noqa: F401 - # This model is required for flask_migrate to make the table - from models.user_model import User # noqa: F401 + # This model is required for flask_migrate to make the table + from models.user_model import User # noqa: F401 - app = create_app() - app.app_context().push() - db.create_all() + app = create_app() + app.app_context().push() + db.create_all() - # migrate database to latest revision - init() - stamp() - migrate() - upgrade() + # migrate database to latest revision + init() + stamp() + migrate() + upgrade() deploy() diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 28154f1..015597a 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -2,23 +2,31 @@ from flask import Blueprint, render_template, redirect, url_for from flask_login import current_user from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles +from describer.forms.describe_file_form import DescribeFileForm describer = Blueprint( - "describer", - __name__, - template_folder="templates/describe_files", - static_folder="static", + "describer", + __name__, + template_folder="templates/describe_files", + static_folder="static", ) @describer.route("/") def describe_distribusi_files(distribusiname): - if not current_user.is_authenticated: - return redirect(url_for("index")) - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - distribusi_files = DistribusiFiles.query.filter_by( - distribusi=distribusi.id - ).all() - return render_template("describe.html", distribusi_files=distribusi_files) + if not current_user.is_authenticated: + return redirect(url_for("index")) + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + distribusi_files = DistribusiFiles.query.filter_by( + distribusi=distribusi.id + ).all() + # distribusi_file_forms = {} + # for distribusi_file in distribusi_files: + describe_form = DescribeFileForm() + return render_template( + "describe.html", + distribusi_files=distribusi_files, + describe_form=describe_form, + ) diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py index 286c448..2125642 100644 --- a/verse/describer/forms/describe_file_form.py +++ b/verse/describer/forms/describe_file_form.py @@ -4,28 +4,29 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, validators from wtforms.validators import Length + class DescribeFileForm(FlaskForm): - """DescribeFileForm selection form.""" + """DescribeFileForm selection form.""" - alttext = StringField( - "Alt-text for this file:", - validators=[ - validators.InputRequired(), - Length(3, 255), - ], - ) - searchtags = StringField( - "Add search tags, seperated by commas. No need for the '#' sign:", - validators=[ - validators.InputRequired(), - Length(3, 500), - ], - ) - description = StringField( - "Description of this file:", - validators=[ - validators.InputRequired(), - Length(3, 4096), - ], - ) - save = SubmitField("Save") + alttext = StringField( + "Alt-text for this file:", + validators=[ + validators.InputRequired(), + Length(3, 255), + ], + ) + searchtags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[ + validators.InputRequired(), + Length(3, 500), + ], + ) + description = StringField( + "Description of this file:", + validators=[ + validators.InputRequired(), + Length(3, 4096), + ], + ) + save = SubmitField("Save") diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py index 444cb96..8b5308d 100644 --- a/verse/distribusikan/distribusikan.py +++ b/verse/distribusikan/distribusikan.py @@ -10,38 +10,38 @@ from distribusikan.themeselector import ThemeSelector from distribusikan.uploadpage import UploadPage distribusikan = Blueprint( - "distribusikan", - __name__, - template_folder="templates/distribusikan", - static_folder="static", + "distribusikan", + __name__, + template_folder="templates/distribusikan", + static_folder="static", ) @distribusikan.route("/distribusi", methods=["GET", "POST"]) @login_required def distribusi(): - return DistribusiWorkflow() + return DistribusiWorkflow() @distribusikan.route("/upload", methods=["POST"]) @login_required def upload(): - return UploadPage() + return UploadPage() @distribusikan.route("/theme", methods=["GET", "POST"]) @login_required def theme(): - return ThemeSelector() + return ThemeSelector() @distribusikan.route("/editor", methods=["GET", "POST"]) @login_required def editor(): - return Editor() + return Editor() @distribusikan.route("/selector", methods=["GET", "POST"]) @login_required def selector(): - return DistribusiSelector() + return DistribusiSelector() diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index ea55d43..fef2c62 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -4,10 +4,10 @@ import shutil from flask import flash, render_template, redirect, url_for from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -25,148 +25,148 @@ from statuspengguna.helper import UserHelper def DistribusiSelector(): - uploadform = UploadForm() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - current_distribusi = UserHelper.current_distribusi() - if selectorform.validate_on_submit(): - if selectorform.new.data: - SelectNewDistribusi() - if selectorform.describe.data: - return SelectDescribeDistribusi(selectorform.distribusis.data) - if selectorform.delete.data: - selectorform = DeleteDistribusi(selectorform.distribusis.data) - selectorform.distribusis.choices = ( - DistribusisInfo.userdistribusinames() - ) - if selectorform.update.data: - SelectUpdateDistribusi(selectorform.distribusis.data) - current_distribusi = UserHelper.current_distribusi() - uploadform = AutoFillInUploadForm(uploadform, current_distribusi) - - return RenderDistribusiTemplate( - selectorform, uploadform, current_distribusi - ) + uploadform = UploadForm() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + current_distribusi = UserHelper.current_distribusi() + if selectorform.validate_on_submit(): + if selectorform.new.data: + SelectNewDistribusi() + if selectorform.describe.data: + return SelectDescribeDistribusi(selectorform.distribusis.data) + if selectorform.delete.data: + selectorform = DeleteDistribusi(selectorform.distribusis.data) + selectorform.distribusis.choices = ( + DistribusisInfo.userdistribusinames() + ) + if selectorform.update.data: + SelectUpdateDistribusi(selectorform.distribusis.data) + current_distribusi = UserHelper.current_distribusi() + uploadform = AutoFillInUploadForm(uploadform, current_distribusi) + + return RenderDistribusiTemplate( + selectorform, uploadform, current_distribusi + ) def AutoFillInUploadForm(uploadform, current_distribusi): - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - uploadform.sitename.data = distribusi.distribusiname - uploadform.sitename.render_kw = {"readonly": True} - uploadform.category.data = distribusi.category - uploadform.year.data = distribusi.year - uploadform.tags.data = distribusi.tags - return uploadform + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + uploadform.sitename.data = distribusi.distribusiname + uploadform.sitename.render_kw = {"readonly": True} + uploadform.category.data = distribusi.category + uploadform.year.data = distribusi.year + uploadform.tags.data = distribusi.tags + return uploadform def SelectNewDistribusi(): - print("make a new distribusi") - SelectCurrentDistribusi("new") + print("make a new distribusi") + SelectCurrentDistribusi("new") def SelectDescribeDistribusi(distribusiname): - return redirect( - url_for( - "describer.describe_distribusi_files", - distribusiname=distribusiname, - ) - ) + return redirect( + url_for( + "describer.describe_distribusi_files", + distribusiname=distribusiname, + ) + ) def SelectUpdateDistribusi(distribusiname): - print(f"Update this distribusi {distribusiname}") - SelectCurrentDistribusi(distribusiname) + print(f"Update this distribusi {distribusiname}") + SelectCurrentDistribusi(distribusiname) def DeleteDistribusi(distribusiname): - print(f"delete this distribusi {distribusiname}") - selectorform = SelectorForm() - try: - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - if distribusi.userid is user.id: - db.session.delete(distribusi) - db.session.commit() - userfolder = os.path.join("stash", distribusi.distribusiname) - if os.path.exists(userfolder): - shutil.rmtree(userfolder) - cssfolder = os.path.join( - "themes/userthemes", distribusi.distribusiname - ) - if os.path.exists(cssfolder): - shutil.rmtree(cssfolder) - if distribusi.publictheme is not None: - publicthemefolder = os.path.join( - "themes/publicthemes", distribusi.distribusiname - ) - if os.path.exists(publicthemefolder): - shutil.rmtree(publicthemefolder) - # SelectField error is list is a tuple?? why?? - # selectorform.distribusis.errors.append("Distribusi deleted!") - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - # selectorform.distribusis.errors.append("Unknown error occured!") - flash("An error occured !", "danger") - return selectorform + print(f"delete this distribusi {distribusiname}") + selectorform = SelectorForm() + try: + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + if distribusi.userid is user.id: + db.session.delete(distribusi) + db.session.commit() + userfolder = os.path.join("stash", distribusi.distribusiname) + if os.path.exists(userfolder): + shutil.rmtree(userfolder) + cssfolder = os.path.join( + "themes/userthemes", distribusi.distribusiname + ) + if os.path.exists(cssfolder): + shutil.rmtree(cssfolder) + if distribusi.publictheme is not None: + publicthemefolder = os.path.join( + "themes/publicthemes", distribusi.distribusiname + ) + if os.path.exists(publicthemefolder): + shutil.rmtree(publicthemefolder) + # SelectField error is list is a tuple?? why?? + # selectorform.distribusis.errors.append("Distribusi deleted!") + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + # selectorform.distribusis.errors.append("Unknown error occured!") + flash("An error occured !", "danger") + return selectorform def SelectCurrentDistribusi(distribusiname): - if not current_user.is_authenticated: - return - user = User.query.filter_by(email=current_user.email).first() - try: - user.currentdistribusi = distribusiname - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("An error occured !", "danger") + if not current_user.is_authenticated: + return + user = User.query.filter_by(email=current_user.email).first() + try: + user.currentdistribusi = distribusiname + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("An error occured !", "danger") def DistribusiSelected(): - user = User.query.filter_by(email=current_user.email).first() - if user.currentdistribusi is None: - return False - return True + user = User.query.filter_by(email=current_user.email).first() + if user.currentdistribusi is None: + return False + return True def SelectorVisible(): - has_distribusi = UserHelper.has_distribusi() - distribusi_selected = DistribusiSelected() - if distribusi_selected: - return False - if not has_distribusi: - return False - return True + has_distribusi = UserHelper.has_distribusi() + distribusi_selected = DistribusiSelected() + if distribusi_selected: + return False + if not has_distribusi: + return False + return True def RenderDistribusiTemplate(selectorform, uploadform, current_distribusi): - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - - # because the user has chosen to update his distribusi, we assume - # no selected css. - css_selected = False - selectorvisible = SelectorVisible() - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + + # because the user has chosen to update his distribusi, we assume + # no selected css. + css_selected = False + selectorvisible = SelectorVisible() + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/distribusisinfo.py b/verse/distribusikan/distribusisinfo.py index 19ef284..9021c3a 100644 --- a/verse/distribusikan/distribusisinfo.py +++ b/verse/distribusikan/distribusisinfo.py @@ -5,34 +5,34 @@ from models.user_model import User class DistribusisInfo: - def userdistribusinames(): - distribusinames = [] - user = User.query.filter_by(email=current_user.email).first() - for distribusi in Distribusis.query.filter_by(userid=user.id).all(): - distribusinames.append(distribusi.distribusiname) - return distribusinames + def userdistribusinames(): + distribusinames = [] + user = User.query.filter_by(email=current_user.email).first() + for distribusi in Distribusis.query.filter_by(userid=user.id).all(): + distribusinames.append(distribusi.distribusiname) + return distribusinames - def publicthemes(): - publicthemes = [] - distribusis = Distribusis.query.filter( - Distribusis.publictheme.isnot(None) - ).all() - for distribusi in distribusis: - user = User.query.filter_by(id=distribusi.userid).first() - publictheme = ( - f"{distribusi.distribusiname}/{distribusi.publictheme}", - f"""{distribusi.publictheme} used in {distribusi.distribusiname} + def publicthemes(): + publicthemes = [] + distribusis = Distribusis.query.filter( + Distribusis.publictheme.isnot(None) + ).all() + for distribusi in distribusis: + user = User.query.filter_by(id=distribusi.userid).first() + publictheme = ( + f"{distribusi.distribusiname}/{distribusi.publictheme}", + f"""{distribusi.publictheme} used in {distribusi.distribusiname} made by {user.username}""", - ) - publicthemes.append(publictheme) - return publicthemes + ) + publicthemes.append(publictheme) + return publicthemes - def visibledistribusis(): - distribusis = Distribusis.query.filter( - Distribusis.visible.isnot(False) - ).all() - return distribusis + def visibledistribusis(): + distribusis = Distribusis.query.filter( + Distribusis.visible.isnot(False) + ).all() + return distribusis - def getuserdistribusis(useremail): - user = User.query.filter_by(email=useremail).first() - return Distribusis.query.filter_by(userid=user.id).all() + def getuserdistribusis(useremail): + user = User.query.filter_by(email=useremail).first() + return Distribusis.query.filter_by(userid=user.id).all() diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusiworkflow.py index 4e3a376..7b37a5e 100644 --- a/verse/distribusikan/distribusiworkflow.py +++ b/verse/distribusikan/distribusiworkflow.py @@ -8,10 +8,10 @@ from distribusi.distribusi import distribusify from flask import flash, redirect, render_template, url_for from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -32,112 +32,112 @@ from statuspengguna.helper import UserHelper def DistribusiWorkflow(): - distribusiform = DistribusiForm() - current_distribusi = UserHelper.current_distribusi() - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - - if distribusiform.validate_on_submit(): - userfolder = os.path.join("stash", distribusi.distribusiname) - cssfile = GetCssFile(distribusi) - UnzipDistribusiFiles(distribusi, userfolder) - CleanUpDistribusiFiles(userfolder) - RunDistribusi(userfolder, cssfile) - SetDistribusiToVisible(distribusi, user) - DeleteCssFile(cssfile) - return redirect(url_for("index")) - - return RenderDistribusiTemplate(distribusiform, current_distribusi) + distribusiform = DistribusiForm() + current_distribusi = UserHelper.current_distribusi() + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + + if distribusiform.validate_on_submit(): + userfolder = os.path.join("stash", distribusi.distribusiname) + cssfile = GetCssFile(distribusi) + UnzipDistribusiFiles(distribusi, userfolder) + CleanUpDistribusiFiles(userfolder) + RunDistribusi(userfolder, cssfile) + SetDistribusiToVisible(distribusi, user) + DeleteCssFile(cssfile) + return redirect(url_for("index")) + + return RenderDistribusiTemplate(distribusiform, current_distribusi) def UnzipDistribusiFiles(distribusi, userfolder): - zipfilename = "{}.zip".format(distribusi.distribusiname) - unzipfile = os.path.join(userfolder, zipfilename) + zipfilename = "{}.zip".format(distribusi.distribusiname) + unzipfile = os.path.join(userfolder, zipfilename) - if os.path.exists(unzipfile): - with zipfile.ZipFile(unzipfile, "r") as zip_ref: - zip_ref.extractall(userfolder) - # after extracting all files remove zip file. - if os.path.exists(unzipfile): - os.remove(os.path.join(userfolder, zipfilename)) + if os.path.exists(unzipfile): + with zipfile.ZipFile(unzipfile, "r") as zip_ref: + zip_ref.extractall(userfolder) + # after extracting all files remove zip file. + if os.path.exists(unzipfile): + os.remove(os.path.join(userfolder, zipfilename)) def CleanUpDistribusiFiles(userfolder): - if os.path.exists(userfolder): - RemoveMacFolders(userfolder) + if os.path.exists(userfolder): + RemoveMacFolders(userfolder) def RemoveMacFolders(path): - for filename in os.listdir(path): - fullpath = os.path.join(path, filename) - if filename.startswith("."): - if os.path.isdir(fullpath): - shutil.rmtree(fullpath) - else: - os.remove(fullpath) - if filename == "__MACOSX": - shutil.rmtree(fullpath) - if os.path.isdir(fullpath): - RemoveMacFolders(fullpath) + for filename in os.listdir(path): + fullpath = os.path.join(path, filename) + if filename.startswith("."): + if os.path.isdir(fullpath): + shutil.rmtree(fullpath) + else: + os.remove(fullpath) + if filename == "__MACOSX": + shutil.rmtree(fullpath) + if os.path.isdir(fullpath): + RemoveMacFolders(fullpath) def GetCssFile(distribusi): - cssfile = "" - cssfolder = os.path.join("themes/userthemes", distribusi.distribusiname) - if os.path.exists(cssfolder): - for filename in os.listdir(cssfolder): - if filename.endswith(".css"): - cssfile = os.path.join(cssfolder, filename) - return cssfile + cssfile = "" + cssfolder = os.path.join("themes/userthemes", distribusi.distribusiname) + if os.path.exists(cssfolder): + for filename in os.listdir(cssfolder): + if filename.endswith(".css"): + cssfile = os.path.join(cssfolder, filename) + return cssfile def RunDistribusi(userfolder, cssfile): - parser = build_argparser() - args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) - distribusify(args, userfolder) + parser = build_argparser() + args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) + distribusify(args, userfolder) def SetDistribusiToVisible(distribusi, user): - try: - distribusi.visible = True - user.currentdistribusi = None - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("Unknown error occured!") + try: + distribusi.visible = True + user.currentdistribusi = None + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("Unknown error occured!") def DeleteCssFile(cssfile): - if os.path.exists(cssfile): - os.remove(cssfile) + if os.path.exists(cssfile): + os.remove(cssfile) def RenderDistribusiTemplate(distribusiform, current_distribusi): - uploadform = UploadForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - selectorvisible = SelectorVisible() - - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + uploadform = UploadForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorvisible = SelectorVisible() + + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/editor.py index 88e63c2..74e3a21 100644 --- a/verse/distribusikan/editor.py +++ b/verse/distribusikan/editor.py @@ -5,10 +5,10 @@ import bleach from bleach_allowlist import all_styles from flask import render_template from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from werkzeug.utils import secure_filename @@ -25,175 +25,175 @@ from statuspengguna.helper import UserHelper def Editor(): - editorform = EditorForm() - current_distribusi = UserHelper.current_distribusi() - if editorform.validate_on_submit(): - ValidateEditCssForm(editorform, current_distribusi) - return RenderDistribusiTemplate(current_distribusi) + editorform = EditorForm() + current_distribusi = UserHelper.current_distribusi() + if editorform.validate_on_submit(): + ValidateEditCssForm(editorform, current_distribusi) + return RenderDistribusiTemplate(current_distribusi) - return RenderEditorTemplate(editorform, current_distribusi) + return RenderEditorTemplate(editorform, current_distribusi) def ValidateEditCssForm(editorform, current_distribusi): - newcssfolder = os.path.join("themes/userthemes", current_distribusi) - if os.path.exists(newcssfolder): - shutil.rmtree(newcssfolder) - - publicfolder = os.path.join("themes/publicthemes", current_distribusi) - if os.path.exists(publicfolder): - shutil.rmtree(publicfolder) - - if editorform.public.data: - MakePublicTheme(editorform, current_distribusi) - if editorform.cssfile.data: - SaveUploadCssFile(editorform, publicfolder) - CopyPublicToUserFolder(editorform, publicfolder, newcssfolder) - return - else: - WriteCssToFile(editorform, publicfolder) - - if editorform.cssfile.data: - SaveUploadCssFile(editorform, newcssfolder) - return - if editorform.cssname.data: - WriteCssToFile(editorform, newcssfolder) + newcssfolder = os.path.join("themes/userthemes", current_distribusi) + if os.path.exists(newcssfolder): + shutil.rmtree(newcssfolder) + + publicfolder = os.path.join("themes/publicthemes", current_distribusi) + if os.path.exists(publicfolder): + shutil.rmtree(publicfolder) + + if editorform.public.data: + MakePublicTheme(editorform, current_distribusi) + if editorform.cssfile.data: + SaveUploadCssFile(editorform, publicfolder) + CopyPublicToUserFolder(editorform, publicfolder, newcssfolder) + return + else: + WriteCssToFile(editorform, publicfolder) + + if editorform.cssfile.data: + SaveUploadCssFile(editorform, newcssfolder) + return + if editorform.cssname.data: + WriteCssToFile(editorform, newcssfolder) def SaveUploadCssFile(editorform, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - cssfile = editorform.cssfile.data - cssfilename = f"{secure_filename(editorform.cssname.data)}.css" - cssfile.save(os.path.join(newcssfolder, cssfilename)) - openfile = open(os.path.join(newcssfolder, cssfilename), "r") - cleancss = bleach.clean(openfile.read(), all_styles) - cleancss = cleancss.replace(">", ">") - openfile.close() - cleanfile = open(os.path.join(newcssfolder, cssfilename), "w") - cleanfile.write(cleancss) - cleanfile.close() + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + cssfile = editorform.cssfile.data + cssfilename = f"{secure_filename(editorform.cssname.data)}.css" + cssfile.save(os.path.join(newcssfolder, cssfilename)) + openfile = open(os.path.join(newcssfolder, cssfilename), "r") + cleancss = bleach.clean(openfile.read(), all_styles) + cleancss = cleancss.replace(">", ">") + openfile.close() + cleanfile = open(os.path.join(newcssfolder, cssfilename), "w") + cleanfile.write(cleancss) + cleanfile.close() def WriteCssToFile(editorform, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) - cssfilename = f"{secure_filename(editorform.cssname.data)}.css" - cleancss = bleach.clean(editorform.css.data, all_styles) - cleancss = cleancss.replace(">", ">") - with open(os.path.join(newcssfolder, cssfilename), "w") as cssfile: - cssfile.write(cleancss) - cssfile.close + cssfilename = f"{secure_filename(editorform.cssname.data)}.css" + cleancss = bleach.clean(editorform.css.data, all_styles) + cleancss = cleancss.replace(">", ">") + with open(os.path.join(newcssfolder, cssfilename), "w") as cssfile: + cssfile.write(cleancss) + cssfile.close def CopyPublicToUserFolder(editorform, publicfolder, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - copycssfile = os.path.join( - publicfolder, f"{secure_filename(editorform.cssname.data)}.css" - ) - print(f"copying file: {copycssfile}") - print(f"to folder: {newcssfolder}") - shutil.copy(copycssfile, newcssfolder) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + copycssfile = os.path.join( + publicfolder, f"{secure_filename(editorform.cssname.data)}.css" + ) + print(f"copying file: {copycssfile}") + print(f"to folder: {newcssfolder}") + shutil.copy(copycssfile, newcssfolder) def MakePublicTheme(editorform, current_distribusi): - try: - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - distribusi.publictheme = secure_filename(editorform.cssname.data) - db.session.commit() - - except InvalidRequestError: - db.session.rollback() - editorform.public.errors.append("Something went wrong!") - except DataError: - db.session.rollback() - editorform.public.errors.append("Invalid Entry") - except InterfaceError: - db.session.rollback() - editorform.public.errors.append("Error connecting to the database") - except DatabaseError: - db.session.rollback() - editorform.public.errors.append("Error connecting to the database") + try: + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + distribusi.publictheme = secure_filename(editorform.cssname.data) + db.session.commit() + + except InvalidRequestError: + db.session.rollback() + editorform.public.errors.append("Something went wrong!") + except DataError: + db.session.rollback() + editorform.public.errors.append("Invalid Entry") + except InterfaceError: + db.session.rollback() + editorform.public.errors.append("Error connecting to the database") + except DatabaseError: + db.session.rollback() + editorform.public.errors.append("Error connecting to the database") def RenderDistribusiTemplate(current_distribusi): - uploadform = UploadForm() - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = True - selectorvisible = False - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + uploadform = UploadForm() + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = True + selectorvisible = False + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template def RenderEditorTemplate(editorform, current_distribusi): - htmlplaceholder = HtmlPlaceholder() + htmlplaceholder = HtmlPlaceholder() - cssplaceholder = CssPlaceholder(current_distribusi) - editorform.css.data = cssplaceholder + cssplaceholder = CssPlaceholder(current_distribusi) + editorform.css.data = cssplaceholder - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - template = render_template( - "editor.html", - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - editorform=editorform, - htmlplaceholder=htmlplaceholder, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + template = render_template( + "editor.html", + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + editorform=editorform, + htmlplaceholder=htmlplaceholder, + ) + return template def CssPlaceholder(current_distribusi): - cssplaceholder = "Try out your CSS here" - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - if distribusi is not None and distribusi.publictheme is not None: - cssplaceholder = GetPublicCssFile(distribusi) - else: - with open("themes/editor/placeholder.css") as f: - cssplaceholder = f.read() - return cssplaceholder + cssplaceholder = "Try out your CSS here" + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + if distribusi is not None and distribusi.publictheme is not None: + cssplaceholder = GetPublicCssFile(distribusi) + else: + with open("themes/editor/placeholder.css") as f: + cssplaceholder = f.read() + return cssplaceholder def HtmlPlaceholder(): - htmlplaceholder = "Write some test HTML here" - with open("themes/editor/placeholder.html") as f: - htmlplaceholder = f.read() - return htmlplaceholder + htmlplaceholder = "Write some test HTML here" + with open("themes/editor/placeholder.html") as f: + htmlplaceholder = f.read() + return htmlplaceholder def GetPublicCssFile(distribusi): - cssplaceholder = "" - publicthemefolder = os.path.join( - "themes/publicthemes", distribusi.distribusiname - ) - for filename in os.listdir(publicthemefolder): - if filename.endswith(".css"): - cssfile = os.path.join(publicthemefolder, filename) - with open(cssfile) as f: - cssplaceholder = f.read() - return cssplaceholder + cssplaceholder = "" + publicthemefolder = os.path.join( + "themes/publicthemes", distribusi.distribusiname + ) + for filename in os.listdir(publicthemefolder): + if filename.endswith(".css"): + cssfile = os.path.join(publicthemefolder, filename) + with open(cssfile) as f: + cssplaceholder = f.read() + return cssplaceholder diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/themeselector.py index 96b2d8a..67237de 100644 --- a/verse/distribusikan/themeselector.py +++ b/verse/distribusikan/themeselector.py @@ -13,55 +13,55 @@ from statuspengguna.helper import UserHelper def ThemeSelector(): - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - current_distribusi = UserHelper.current_distribusi() - if themeform.validate_on_submit(): - copycssfile = os.path.join( - "themes", - f"{themeform.theme.data}.css", - ) - MoveCssToUserFolder(current_distribusi, copycssfile) - if publicthemeform.validate_on_submit(): - copycssfile = os.path.join( - "themes/publicthemes/", - f"{publicthemeform.publicthemes.data}.css", - ) - MoveCssToUserFolder(current_distribusi, copycssfile) - return RenderDistribusiTemplate( - themeform, publicthemeform, current_distribusi - ) + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + current_distribusi = UserHelper.current_distribusi() + if themeform.validate_on_submit(): + copycssfile = os.path.join( + "themes", + f"{themeform.theme.data}.css", + ) + MoveCssToUserFolder(current_distribusi, copycssfile) + if publicthemeform.validate_on_submit(): + copycssfile = os.path.join( + "themes/publicthemes/", + f"{publicthemeform.publicthemes.data}.css", + ) + MoveCssToUserFolder(current_distribusi, copycssfile) + return RenderDistribusiTemplate( + themeform, publicthemeform, current_distribusi + ) def MoveCssToUserFolder(current_distribusi, copycssfile): - newcssfolder = os.path.join("themes/userthemes", current_distribusi) - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - shutil.copy(copycssfile, newcssfolder) + newcssfolder = os.path.join("themes/userthemes", current_distribusi) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + shutil.copy(copycssfile, newcssfolder) def RenderDistribusiTemplate(themeform, publicthemeform, current_distribusi): - uploadform = UploadForm() - distribusiform = DistribusiForm() - selectorform = SelectorForm() + uploadform = UploadForm() + distribusiform = DistribusiForm() + selectorform = SelectorForm() - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - selectorvisible = False - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + selectorvisible = False + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py index 83110b5..9ba4bae 100644 --- a/verse/distribusikan/upload.py +++ b/verse/distribusikan/upload.py @@ -4,11 +4,11 @@ import shutil from flask import flash from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -20,76 +20,76 @@ from statuspengguna.helper import UserHelper def UploadNewDistribusi(uploadfolder): - uploadform = UploadForm() - if uploadform.validate_on_submit(): - user = User.query.filter_by(email=current_user.email).first() - try: - newdistribusi = Distribusis( - distribusiname=uploadform.sitename.data, - userid=user.id, - category=uploadform.category.data, - year=uploadform.year.data, - tags=uploadform.tags.data, - ) - user.currentdistribusi = uploadform.sitename.data - db.session.add(newdistribusi) - db.session.commit() - except IntegrityError: - db.session.rollback() - uploadform.sitename.errors.append( - "distribusi name already exists!" - ) - flash("distribusi name already exists!", "warning") - return uploadform - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - uploadform.sitename.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - return uploadform - SelectCurrentDistribusi(newdistribusi.distribusiname) - zipfilename = "{}.zip".format(newdistribusi.distribusiname) - zipfile = uploadform.zipfile.data - zipfile.save(os.path.join(uploadfolder, zipfilename)) + uploadform = UploadForm() + if uploadform.validate_on_submit(): + user = User.query.filter_by(email=current_user.email).first() + try: + newdistribusi = Distribusis( + distribusiname=uploadform.sitename.data, + userid=user.id, + category=uploadform.category.data, + year=uploadform.year.data, + tags=uploadform.tags.data, + ) + user.currentdistribusi = uploadform.sitename.data + db.session.add(newdistribusi) + db.session.commit() + except IntegrityError: + db.session.rollback() + uploadform.sitename.errors.append( + "distribusi name already exists!" + ) + flash("distribusi name already exists!", "warning") + return uploadform + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + uploadform.sitename.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + return uploadform + SelectCurrentDistribusi(newdistribusi.distribusiname) + zipfilename = "{}.zip".format(newdistribusi.distribusiname) + zipfile = uploadform.zipfile.data + zipfile.save(os.path.join(uploadfolder, zipfilename)) - newuserfolder = os.path.join("stash", newdistribusi.distribusiname) - if not os.path.exists(newuserfolder): - os.mkdir(newuserfolder) + newuserfolder = os.path.join("stash", newdistribusi.distribusiname) + if not os.path.exists(newuserfolder): + os.mkdir(newuserfolder) - copyzipfile = os.path.join(uploadfolder, zipfilename) - shutil.copy(copyzipfile, newuserfolder) - os.remove(os.path.join(uploadfolder, zipfilename)) + copyzipfile = os.path.join(uploadfolder, zipfilename) + shutil.copy(copyzipfile, newuserfolder) + os.remove(os.path.join(uploadfolder, zipfilename)) - return uploadform + return uploadform def UploadUpdatedFiles(uploadfolder): - uploadform = UploadForm() - if uploadform.validate_on_submit(): - try: - current_distribusi = UserHelper.current_distribusi() - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - distribusi.category = uploadform.category.data - distribusi.year = uploadform.year.data - distribusi.tags = uploadform.tags.data - distribusi.visible = False - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - uploadform.sitename.errors.append("Something went wrong!") + uploadform = UploadForm() + if uploadform.validate_on_submit(): + try: + current_distribusi = UserHelper.current_distribusi() + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + distribusi.category = uploadform.category.data + distribusi.year = uploadform.year.data + distribusi.tags = uploadform.tags.data + distribusi.visible = False + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + uploadform.sitename.errors.append("Something went wrong!") - zipfilename = "{}.zip".format(distribusi.distribusiname) - zipfile = uploadform.zipfile.data - zipfile.save(os.path.join(uploadfolder, zipfilename)) + zipfilename = "{}.zip".format(distribusi.distribusiname) + zipfile = uploadform.zipfile.data + zipfile.save(os.path.join(uploadfolder, zipfilename)) - newuserfolder = os.path.join("stash", distribusi.distribusiname) - if os.path.exists(newuserfolder): - shutil.rmtree(newuserfolder) - os.mkdir(newuserfolder) + newuserfolder = os.path.join("stash", distribusi.distribusiname) + if os.path.exists(newuserfolder): + shutil.rmtree(newuserfolder) + os.mkdir(newuserfolder) - copyzipfile = os.path.join(uploadfolder, zipfilename) - shutil.copy(copyzipfile, newuserfolder) - os.remove(os.path.join(uploadfolder, zipfilename)) + copyzipfile = os.path.join(uploadfolder, zipfilename) + shutil.copy(copyzipfile, newuserfolder) + os.remove(os.path.join(uploadfolder, zipfilename)) - return uploadform + return uploadform diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/uploadpage.py index a8f2510..347518c 100644 --- a/verse/distribusikan/uploadpage.py +++ b/verse/distribusikan/uploadpage.py @@ -14,37 +14,37 @@ from statuspengguna.helper import UserHelper def UploadPage(): - "render upload page section of distribusi workflow" - uploadfolder = APP.config["UPLOAD_FOLDER"] - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - selectorvisible = SelectorVisible() + "render upload page section of distribusi workflow" + uploadfolder = APP.config["UPLOAD_FOLDER"] + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorvisible = SelectorVisible() - current_distribusi = UserHelper.current_distribusi() - if current_distribusi == "new" or UserHelper.has_distribusi() is False: - uploadform = UploadNewDistribusi(uploadfolder) - else: - uploadform = UploadUpdatedFiles(uploadfolder) + current_distribusi = UserHelper.current_distribusi() + if current_distribusi == "new" or UserHelper.has_distribusi() is False: + uploadform = UploadNewDistribusi(uploadfolder) + else: + uploadform = UploadUpdatedFiles(uploadfolder) - files_uploaded = UserHelper.is_zip_uploaded(uploadform.sitename.data) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(uploadform.sitename.data) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/file_crawler.py b/verse/file_crawler.py index b395138..0a86f79 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -6,70 +6,68 @@ from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from app import create_app, get_app, db from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) MIME_TYPE = magic.Magic(mime=True) def _distribusi_file_with_type(distribusi, full_path): - mime = MIME_TYPE.from_file(full_path) - type_, subtype = mime.split("/") - if type_ in FILE_TYPES: - _add_distribusi_file_to_db(distribusi, full_path, type_) + mime = MIME_TYPE.from_file(full_path) + type_, subtype = mime.split("/") + if type_ in FILE_TYPES: + _add_distribusi_file_to_db(distribusi, full_path, type_) + def _get_distribusi_from_path(path): - distribusi = Distribusis.query.filter_by(distribusiname=path).first() - return distribusi + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + return distribusi + def _add_distribusi_file_to_db(distribusi, full_path, type): - app = get_app() - print(f"adding file to database: {full_path} type: {type}") - try: - new_distribusi_file = DistribusiFiles( - path=full_path, - type=type, - distribusi=distribusi.id, - ) - db.session.add(new_distribusi_file) - db.session.commit() - return - except InvalidRequestError: - db.session.rollback() - app.logger.error("Something went wrong!") - except IntegrityError: - db.session.rollback() - app.logger.error("File %s already exists!", full_path) - except DataError: - db.session.rollback() - app.logger.error("%s Invalid Entry", full_path) - except InterfaceError: - db.session.rollback() - app.logger.error( - "Error connecting to the database" - ) - except DatabaseError: - db.session.rollback() - app.logger.error( - "Error connecting to the database" - ) + app = get_app() + print(f"adding file to database: {full_path} type: {type}") + try: + new_distribusi_file = DistribusiFiles( + path=full_path, + type=type, + distribusi=distribusi.id, + ) + db.session.add(new_distribusi_file) + db.session.commit() + return + except InvalidRequestError: + db.session.rollback() + app.logger.error("Something went wrong!") + except IntegrityError: + db.session.rollback() + app.logger.error("File %s already exists!", full_path) + except DataError: + db.session.rollback() + app.logger.error("%s Invalid Entry", full_path) + except InterfaceError: + db.session.rollback() + app.logger.error("Error connecting to the database") + except DatabaseError: + db.session.rollback() + app.logger.error("Error connecting to the database") def add_distribusi_files(path): - app = create_app() - with app.app_context(): - distribusi = _get_distribusi_from_path(path) - path = os.path.join("stash", path) - for root, dirs, files in os.walk(path, topdown=True): - files = list(filter(lambda f: not f.startswith("."), files)) - files = list(filter(lambda f: not f.endswith(".html"), files)) - for file in files: - full_path = os.path.join(root, file) - _distribusi_file_with_type(distribusi, full_path) + app = create_app() + with app.app_context(): + distribusi = _get_distribusi_from_path(path) + path = os.path.join("stash", path) + for root, dirs, files in os.walk(path, topdown=True): + files = list(filter(lambda f: not f.startswith("."), files)) + files = list(filter(lambda f: not f.endswith(".html"), files)) + for file in files: + full_path = os.path.join(root, file) + _distribusi_file_with_type(distribusi, full_path) add_distribusi_files("2018-12-WttF-Mastodon-and-the-Fediverse") diff --git a/verse/forms/admindistribusiform.py b/verse/forms/admindistribusiform.py index f00f3db..38daf8f 100644 --- a/verse/forms/admindistribusiform.py +++ b/verse/forms/admindistribusiform.py @@ -5,19 +5,19 @@ from wtforms import BooleanField, SubmitField class AdminDistribusiForm(FlaskForm): - """Admin Distribusi form.""" + """Admin Distribusi form.""" - delete = SubmitField("Delete") + delete = SubmitField("Delete") - def distribusi_list_form_builder(distribusis): - class DistribusiListForm(AdminDistribusiForm): - pass + def distribusi_list_form_builder(distribusis): + class DistribusiListForm(AdminDistribusiForm): + pass - for i, distribusi in enumerate(distribusis): - setattr( - DistribusiListForm, - f"distribusi_{i}", - BooleanField(label=distribusi.distribusiname), - ) + for i, distribusi in enumerate(distribusis): + setattr( + DistribusiListForm, + f"distribusi_{i}", + BooleanField(label=distribusi.distribusiname), + ) - return DistribusiListForm() + return DistribusiListForm() diff --git a/verse/forms/adminuserform.py b/verse/forms/adminuserform.py index aeda2e4..93e2d25 100644 --- a/verse/forms/adminuserform.py +++ b/verse/forms/adminuserform.py @@ -5,19 +5,19 @@ from wtforms import BooleanField, SubmitField class AdminUserForm(FlaskForm): - """Admin Userform form.""" + """Admin Userform form.""" - def user_list_form_builder(users): - class UserListForm(AdminUserForm): - pass + def user_list_form_builder(users): + class UserListForm(AdminUserForm): + pass - for i, user in enumerate(users): - setattr( - UserListForm, - f"user_{i}", - BooleanField(label=user.email), - ) + for i, user in enumerate(users): + setattr( + UserListForm, + f"user_{i}", + BooleanField(label=user.email), + ) - return UserListForm() + return UserListForm() - delete = SubmitField("Delete") + delete = SubmitField("Delete") diff --git a/verse/forms/distribusiform.py b/verse/forms/distribusiform.py index 6373162..bd0fb71 100644 --- a/verse/forms/distribusiform.py +++ b/verse/forms/distribusiform.py @@ -3,6 +3,6 @@ from wtforms import SubmitField class DistribusiForm(FlaskForm): - """Distribusi class to launch your distribusi website""" + """Distribusi class to launch your distribusi website""" - submit = SubmitField("Distribusi!") + submit = SubmitField("Distribusi!") diff --git a/verse/forms/editorform.py b/verse/forms/editorform.py index 284082d..1db3e0d 100644 --- a/verse/forms/editorform.py +++ b/verse/forms/editorform.py @@ -3,33 +3,33 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField, FileSize from wtforms import ( - BooleanField, - StringField, - SubmitField, - TextAreaField, - validators, + BooleanField, + StringField, + SubmitField, + TextAreaField, + validators, ) from wtforms.validators import Length class EditorForm(FlaskForm): - """Css editor form class.""" + """Css editor form class.""" - cssname = StringField( - "fill in a name for your css style:", - validators=[validators.InputRequired(), Length(5, 200)], - ) - cssfile = FileField( - "(Optional) upload your own css file:", - validators=[ - FileAllowed(["css"], "css files only!"), - FileSize( - max_size=10485760, - message="css file size must be smaller than 10MB", - ), - ], - ) - css = TextAreaField() - public = BooleanField("Make your CSS public so others can use it") + cssname = StringField( + "fill in a name for your css style:", + validators=[validators.InputRequired(), Length(5, 200)], + ) + cssfile = FileField( + "(Optional) upload your own css file:", + validators=[ + FileAllowed(["css"], "css files only!"), + FileSize( + max_size=10485760, + message="css file size must be smaller than 10MB", + ), + ], + ) + css = TextAreaField() + public = BooleanField("Make your CSS public so others can use it") - submit = SubmitField("Save") + submit = SubmitField("Save") diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py index 385327d..9e416bb 100644 --- a/verse/forms/forgotpasswordform.py +++ b/verse/forms/forgotpasswordform.py @@ -6,10 +6,10 @@ from wtforms.validators import Email, Length class ForgotPasswordForm(FlaskForm): - """Forgotten password distribusiverse form class.""" + """Forgotten password distribusiverse form class.""" - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - submit = SubmitField("Send email") + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + submit = SubmitField("Send email") diff --git a/verse/forms/loginform.py b/verse/forms/loginform.py index b446850..61830a2 100644 --- a/verse/forms/loginform.py +++ b/verse/forms/loginform.py @@ -6,13 +6,13 @@ from wtforms.validators import Email, Length class LoginForm(FlaskForm): - """Login distribusiverse form class.""" + """Login distribusiverse form class.""" - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - password = PasswordField( - "Password:", validators=[validators.InputRequired()] - ) - submit = SubmitField("Sign In") + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + password = PasswordField( + "Password:", validators=[validators.InputRequired()] + ) + submit = SubmitField("Sign In") diff --git a/verse/forms/publicthemeform.py b/verse/forms/publicthemeform.py index 103fbeb..46a2505 100644 --- a/verse/forms/publicthemeform.py +++ b/verse/forms/publicthemeform.py @@ -5,10 +5,10 @@ from wtforms import RadioField, SubmitField class PublicThemeForm(FlaskForm): - """PublicTheme selection form.""" + """PublicTheme selection form.""" - publicthemes = RadioField( - "Public themes from other distribusi-verse users:" - ) + publicthemes = RadioField( + "Public themes from other distribusi-verse users:" + ) - save = SubmitField("Save") + save = SubmitField("Save") diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py index 89c42d6..b300293 100644 --- a/verse/forms/registerform.py +++ b/verse/forms/registerform.py @@ -6,33 +6,33 @@ from wtforms.validators import Email, EqualTo, Length class RegisterForm(FlaskForm): - """Register for distribusi-verse form class""" + """Register for distribusi-verse form class""" - username = StringField( - "Username:", - validators=[validators.InputRequired(), Length(3, 150)], - ) + username = StringField( + "Username:", + validators=[validators.InputRequired(), Length(3, 150)], + ) - email = StringField( - "Email address:", - validators=[ - validators.InputRequired(), - Email(), - Length(6, 128), - ], - ) + email = StringField( + "Email address:", + validators=[ + validators.InputRequired(), + Email(), + Length(6, 128), + ], + ) - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Register to Distribusi-verse") + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Register to Distribusi-verse") diff --git a/verse/forms/resetpasswordform.py b/verse/forms/resetpasswordform.py index 481cb02..a3cbe34 100644 --- a/verse/forms/resetpasswordform.py +++ b/verse/forms/resetpasswordform.py @@ -6,18 +6,18 @@ from wtforms.validators import EqualTo, Length class ResetPasswordForm(FlaskForm): - """ResetPassword for distribusi-verse form class""" + """ResetPassword for distribusi-verse form class""" - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Reset your password") + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Reset your password") diff --git a/verse/forms/selectorform.py b/verse/forms/selectorform.py index f2f9530..ecdba27 100644 --- a/verse/forms/selectorform.py +++ b/verse/forms/selectorform.py @@ -3,12 +3,12 @@ from wtforms import SelectField, SubmitField class SelectorForm(FlaskForm): - distribusis = SelectField("Your existing distribusi:") + distribusis = SelectField("Your existing distribusi:") - new = SubmitField("new") + new = SubmitField("new") - update = SubmitField("update") + update = SubmitField("update") - describe = SubmitField("describe") + describe = SubmitField("describe") - delete = SubmitField("delete") + delete = SubmitField("delete") diff --git a/verse/forms/themeform.py b/verse/forms/themeform.py index a1c3e02..ca2b7bb 100644 --- a/verse/forms/themeform.py +++ b/verse/forms/themeform.py @@ -5,15 +5,15 @@ from wtforms import RadioField, SubmitField class ThemeForm(FlaskForm): - """Basic theme selection form.""" + """Basic theme selection form.""" - theme = RadioField( - "Select your theme:", - choices=[ - ("hacking", "Hackers (black background, green text)"), - ("peachsunset", "Peach sunset (single column)"), - ("masonry", "Masonry (white background, grid layout)"), - ], - ) + theme = RadioField( + "Select your theme:", + choices=[ + ("hacking", "Hackers (black background, green text)"), + ("peachsunset", "Peach sunset (single column)"), + ("masonry", "Masonry (white background, grid layout)"), + ], + ) - save = SubmitField("Save") + save = SubmitField("Save") diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py index 90dcd70..3f26824 100644 --- a/verse/forms/uploadform.py +++ b/verse/forms/uploadform.py @@ -1,85 +1,85 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField, FileRequired, FileSize from wtforms import ( - SelectField, - StringField, - SubmitField, - validators, + SelectField, + StringField, + SubmitField, + validators, ) from wtforms.validators import ( - DataRequired, - Length, - ValidationError, + DataRequired, + Length, + ValidationError, ) from app import settings class UploadForm(FlaskForm): - """File upload class for a new site in distribusi-verse""" + """File upload class for a new site in distribusi-verse""" - def distribusiname(form, field): - if field.data.lower() == "new": - raise ValidationError("Name has to be unique and not just new.") + def distribusiname(form, field): + if field.data.lower() == "new": + raise ValidationError("Name has to be unique and not just new.") - def category_choices(): - APP = settings() - config_categories = APP.config["categories"] - categories = [] - for config_category in config_categories: - categories.append((config_category, config_category)) - return categories + def category_choices(): + APP = settings() + config_categories = APP.config["categories"] + categories = [] + for config_category in config_categories: + categories.append((config_category, config_category)) + return categories - def year_choices(): - APP = settings() - start_time = APP.config["start_time"] - end_time = APP.config["end_time"] - year_range = range(start_time.year, end_time.year, 1) - year_choices = [] - for year in year_range: - year_choices.append((str(year), str(year))) - return year_choices + def year_choices(): + APP = settings() + start_time = APP.config["start_time"] + end_time = APP.config["end_time"] + year_range = range(start_time.year, end_time.year, 1) + year_choices = [] + for year in year_range: + year_choices.append((str(year), str(year))) + return year_choices - sitename = StringField( - "Name of your archive section:", - validators=[ - validators.InputRequired(), - Length(2, 100), - distribusiname, - ], - ) - year = SelectField( - "Year:", - validate_choice=True, - coerce=str, - choices=year_choices, - option_widget=None, - validators=[DataRequired()], - ) - category = SelectField( - "Category:", - validate_choice=True, - coerce=str, - choices=category_choices, - option_widget=None, - validators=[DataRequired()], - ) + sitename = StringField( + "Name of your archive section:", + validators=[ + validators.InputRequired(), + Length(2, 100), + distribusiname, + ], + ) + year = SelectField( + "Year:", + validate_choice=True, + coerce=str, + choices=year_choices, + option_widget=None, + validators=[DataRequired()], + ) + category = SelectField( + "Category:", + validate_choice=True, + coerce=str, + choices=category_choices, + option_widget=None, + validators=[DataRequired()], + ) - tags = StringField( - "Add search tags, seperated by commas. No need for the '#' sign:", - validators=[validators.InputRequired(), Length(3, 500)], - ) + tags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[validators.InputRequired(), Length(3, 500)], + ) - zipfile = FileField( - "Upload your zip file with content here:", - validators=[ - FileAllowed(["zip"], "Zip archives only!"), - FileRequired(), - FileSize( - max_size=1073741824, - message="Zipfile size must be smaller than 100MB", - ), - ], - ) + zipfile = FileField( + "Upload your zip file with content here:", + validators=[ + FileAllowed(["zip"], "Zip archives only!"), + FileRequired(), + FileSize( + max_size=1073741824, + message="Zipfile size must be smaller than 100MB", + ), + ], + ) - submit = SubmitField("Upload") + submit = SubmitField("Upload") diff --git a/verse/migrations/env.py b/verse/migrations/env.py index 68feded..85debe8 100644 --- a/verse/migrations/env.py +++ b/verse/migrations/env.py @@ -14,17 +14,19 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.get_engine().url).replace( - '%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.get_engine().url).replace( + "%", "%%" + ), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -33,59 +35,59 @@ target_metadata = current_app.extensions['migrate'].db.metadata def run_migrations_offline(): - """Run migrations in 'offline' mode. + """Run migrations in 'offline' mode. - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. - Calls to context.execute() here emit the given string to the - script output. + Calls to context.execute() here emit the given string to the + script output. - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) - with context.begin_transaction(): - context.run_migrations() + with context.begin_transaction(): + context.run_migrations() def run_migrations_online(): - """Run migrations in 'online' mode. + """Run migrations in 'online' mode. - In this scenario we need to create an Engine - and associate a connection with the context. + In this scenario we need to create an Engine + and associate a connection with the context. - """ + """ - # this callback is used to prevent an auto-migration from being generated - # when there are no changes to the schema - # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html - def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): - script = directives[0] - if script.upgrade_ops.is_empty(): - directives[:] = [] - logger.info('No changes in schema detected.') + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, "autogenerate", False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info("No changes in schema detected.") - connectable = current_app.extensions['migrate'].db.get_engine() + connectable = current_app.extensions["migrate"].db.get_engine() - with connectable.connect() as connection: - context.configure( - connection=connection, - target_metadata=target_metadata, - process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args - ) + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions["migrate"].configure_args, + ) - with context.begin_transaction(): - context.run_migrations() + with context.begin_transaction(): + context.run_migrations() if context.is_offline_mode(): - run_migrations_offline() + run_migrations_offline() else: - run_migrations_online() + run_migrations_online() diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 23003b1..cfb6216 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -2,17 +2,17 @@ from app import db class DistribusiFiles(db.Model): - """Distribusi file model class for a single file in a distribusi""" + """Distribusi file model class for a single file in a distribusi""" - __tablename__ = "distribusi_files" + __tablename__ = "distribusi_files" - id = db.Column(db.Integer, primary_key=True) - type = db.Column(db.String(100), nullable=True, unique=False) - distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) - path = db.Column(db.String(4096), nullable=True, unique=False) - alttext = db.Column(db.String(255), nullable=True, unique=False) - tags = db.Column(db.String(500), nullable=True, unique=False) - description = db.Column(db.String(4096), nullable=True, unique=False) + id = db.Column(db.Integer, primary_key=True) + type = db.Column(db.String(100), nullable=True, unique=False) + distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) + path = db.Column(db.String(4096), nullable=True, unique=False) + alttext = db.Column(db.String(255), nullable=True, unique=False) + tags = db.Column(db.String(500), nullable=True, unique=False) + description = db.Column(db.String(4096), nullable=True, unique=False) - def __repr__(self): - return "" % self.path + def __repr__(self): + return "" % self.path diff --git a/verse/models/distribusi_model.py b/verse/models/distribusi_model.py index d8f114e..4d23545 100644 --- a/verse/models/distribusi_model.py +++ b/verse/models/distribusi_model.py @@ -2,18 +2,18 @@ from app import db class Distribusis(db.Model): - """distribusi model class for a single distribusi in distribusi-verse""" + """distribusi model class for a single distribusi in distribusi-verse""" - __tablename__ = "distribusis" + __tablename__ = "distribusis" - id = db.Column(db.Integer, primary_key=True) - distribusiname = db.Column(db.String(300), nullable=False, unique=True) - userid = db.Column(db.Integer, db.ForeignKey("users.id")) - category = db.Column(db.String(500), nullable=True, unique=False) - year = db.Column(db.String(9), nullable=True, unique=False) - tags = db.Column(db.String(500), nullable=True, unique=False) - publictheme = db.Column(db.String(300), unique=True, nullable=True) - visible = db.Column(db.Boolean, default=False) + id = db.Column(db.Integer, primary_key=True) + distribusiname = db.Column(db.String(300), nullable=False, unique=True) + userid = db.Column(db.Integer, db.ForeignKey("users.id")) + category = db.Column(db.String(500), nullable=True, unique=False) + year = db.Column(db.String(9), nullable=True, unique=False) + tags = db.Column(db.String(500), nullable=True, unique=False) + publictheme = db.Column(db.String(300), unique=True, nullable=True) + visible = db.Column(db.Boolean, default=False) - def __repr__(self): - return "" % self.distribusiname + def __repr__(self): + return "" % self.distribusiname diff --git a/verse/models/user_model.py b/verse/models/user_model.py index 9522024..0487d94 100644 --- a/verse/models/user_model.py +++ b/verse/models/user_model.py @@ -4,18 +4,18 @@ from app import db class User(UserMixin, db.Model): - """User model class for a user in distribusi-verse""" + """User model class for a user in distribusi-verse""" - __tablename__ = "users" + __tablename__ = "users" - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(150), unique=True, nullable=False) - email = db.Column(db.String(150), unique=True, nullable=False) - password = db.Column(db.String(300), nullable=False, unique=False) - currentdistribusi = db.Column(db.String(300), nullable=True, unique=False) - resethash = db.Column(db.String(300), nullable=True, unique=True) - resettime = db.Column(db.DateTime) - admin = db.Column(db.Boolean, default=False) + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + email = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(300), nullable=False, unique=False) + currentdistribusi = db.Column(db.String(300), nullable=True, unique=False) + resethash = db.Column(db.String(300), nullable=True, unique=True) + resettime = db.Column(db.DateTime) + admin = db.Column(db.Boolean, default=False) - def __repr__(self): - return "" % self.email + def __repr__(self): + return "" % self.email diff --git a/verse/start.py b/verse/start.py index 91a7c8e..0b3be38 100644 --- a/verse/start.py +++ b/verse/start.py @@ -2,8 +2,14 @@ from datetime import timedelta -from flask import (Blueprint, redirect, render_template, send_from_directory, - session, url_for) +from flask import ( + Blueprint, + redirect, + render_template, + send_from_directory, + session, + url_for, +) from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError @@ -31,92 +37,91 @@ APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(distribusikan) - @APP.before_request def session_handler(): - session.permanent = True - APP.permanent_session_lifetime = timedelta(minutes=30) + session.permanent = True + APP.permanent_session_lifetime = timedelta(minutes=30) @APP.route("/") def index(): - UserHelper.reset_user_state() - uploadform = UploadForm() - distribusis = DistribusisInfo.visibledistribusis() - distribusisindex = {} - for distribusi in distribusis: - user = User.query.filter_by(id=distribusi.userid).first() - singledistribusi = { - "username": user.username, - "publictheme": distribusi.publictheme, - "category": distribusi.category, - "year": distribusi.year, - "tags": distribusi.tags.split(","), - } - distribusisindex[distribusi.distribusiname] = singledistribusi - years = uploadform.year.choices - categories = uploadform.category.choices - adminuser = isadminuser() - template = render_template( - "base/index.html", - distribusisindex=distribusisindex, - years=years, - categories=categories, - adminuser=adminuser, - ) - return template + UserHelper.reset_user_state() + uploadform = UploadForm() + distribusis = DistribusisInfo.visibledistribusis() + distribusisindex = {} + for distribusi in distribusis: + user = User.query.filter_by(id=distribusi.userid).first() + singledistribusi = { + "username": user.username, + "publictheme": distribusi.publictheme, + "category": distribusi.category, + "year": distribusi.year, + "tags": distribusi.tags.split(","), + } + distribusisindex[distribusi.distribusiname] = singledistribusi + years = uploadform.year.choices + categories = uploadform.category.choices + adminuser = is_adminuser() + template = render_template( + "base/index.html", + distribusisindex=distribusisindex, + years=years, + categories=categories, + adminuser=adminuser, + ) + return template @APP.route("/help") def help(): - return render_template("base/help.html") + return render_template("base/help.html") @APP.route("/publicthemes/") def publicthemes(path): - distribusi = Distribusis.query.filter_by(distribusiname=path).first() - publicthemefolder = f"publicthemes/{distribusi.distribusiname}/" - cssfile = f"{publicthemefolder}/{distribusi.publictheme}.css" - return send_from_directory("themes", cssfile, as_attachment=True) + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + publicthemefolder = f"publicthemes/{distribusi.distribusiname}/" + cssfile = f"{publicthemefolder}/{distribusi.publictheme}.css" + return send_from_directory("themes", cssfile, as_attachment=True) @APP.route("/stash") def shortstashurl(): - return redirect(url_for("index")) + return redirect(url_for("index")) @APP.route("/admin", methods=["GET", "POST"]) @login_required def admin(): - if not isadminuser(): - return redirect(url_for("index")) - return AdminPage() + if not is_adminuser(): + return redirect(url_for("index")) + return AdminPage() @APP.route("/logout") @login_required def logout(): - logout_user() - return redirect(url_for("index")) + logout_user() + return redirect(url_for("index")) @APP.errorhandler(CSRFError) def handle_csrf_error(e): - return render_template("csrf_error.html", reason=e.description), 400 + return render_template("csrf_error.html", reason=e.description), 400 @login_manager.user_loader def load_user(user_id): - return User.query.get(int(user_id)) + return User.query.get(int(user_id)) -def isadminuser(): - if not current_user.is_authenticated: - return False - user = User.query.filter_by(email=current_user.email).first() - return user.admin +def is_adminuser(): + if not current_user.is_authenticated: + return False + user = User.query.filter_by(email=current_user.email).first() + return user.admin if __name__ == "__main__": - APP.debug = True - APP.run(port=5000) + APP.debug = True + APP.run(port=5000) diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py index dbb8049..51b0ae0 100644 --- a/verse/statuspengguna/forgotpassword.py +++ b/verse/statuspengguna/forgotpassword.py @@ -4,10 +4,10 @@ from uuid import uuid1 from flask import Blueprint, render_template from flask_mail import Mail, Message from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db, get_app @@ -16,57 +16,57 @@ from models.user_model import User mail = Mail(get_app()) forgot_password = Blueprint( - "forgotpassword", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "forgotpassword", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @forgot_password.route("/", methods=["GET", "POST"]) def forgotpassword(): - return ForgotPassword(mail) + return ForgotPassword(mail) def ForgotPassword(mail): - forgotpasswordform = ForgotPasswordForm() - if forgotpasswordform.validate_on_submit(): - user = User.query.filter_by( - email=forgotpasswordform.email.data - ).first() - if user is not None: - resethash = AddResetPasswordHash(user, forgotpasswordform) - ResetPassWordMessage(user, resethash, mail) - forgotpasswordform.email.errors.append( - f"""If {forgotpasswordform.email.data} exists, an email is send with + forgotpasswordform = ForgotPasswordForm() + if forgotpasswordform.validate_on_submit(): + user = User.query.filter_by( + email=forgotpasswordform.email.data + ).first() + if user is not None: + resethash = AddResetPasswordHash(user, forgotpasswordform) + ResetPassWordMessage(user, resethash, mail) + forgotpasswordform.email.errors.append( + f"""If {forgotpasswordform.email.data} exists, an email is send with a password reset link. (If your inbox doesn't contain any new mail, please check your spam folder.)""" - ) - return render_template( - "forgotpassword.html", forgotpasswordform=forgotpasswordform - ) + ) + return render_template( + "forgotpassword.html", forgotpasswordform=forgotpasswordform + ) def AddResetPasswordHash(user, forgotpasswordform): - resethash = uuid1().hex - try: - user.resettime = datetime.now() - user.resethash = resethash - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - forgotpasswordform.email.errors.append("Something went wrong!") - db.session.rollback() - return resethash + resethash = uuid1().hex + try: + user.resettime = datetime.now() + user.resethash = resethash + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + forgotpasswordform.email.errors.append("Something went wrong!") + db.session.rollback() + return resethash def ResetPassWordMessage(user, resethash, mail): - msg = Message( - "Distribusiverse Forgotten Password ", - sender=("Distribusiverse mailer", "test@this.com"), - recipients=[user.email], - ) - msg.html = f"""{user.username} has requested a password reset for + msg = Message( + "Distribusiverse Forgotten Password ", + sender=("Distribusiverse mailer", "test@this.com"), + recipients=[user.email], + ) + msg.html = f"""{user.username} has requested a password reset for Distribusiverse.

Click here to reset your password.""" - mail.send(msg) + mail.send(msg) diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py index a8b26bd..9d01082 100644 --- a/verse/statuspengguna/helper.py +++ b/verse/statuspengguna/helper.py @@ -3,10 +3,10 @@ import os from flask import flash from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -16,68 +16,68 @@ from models.user_model import User class UserHelper: - def is_zip_uploaded(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - zipfilename = "{}.zip".format(distribusiname) - if os.path.exists(os.path.join(userfolder, zipfilename)): - print("folder with zipfile found, file uploaded") - return True - print("distribusi folder has no zipfile") - return False + def is_zip_uploaded(distribusiname): + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + zipfilename = "{}.zip".format(distribusiname) + if os.path.exists(os.path.join(userfolder, zipfilename)): + print("folder with zipfile found, file uploaded") + return True + print("distribusi folder has no zipfile") + return False - def is_distribusi_live(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - zipfilename = "{}.zip".format(distribusiname) - if os.path.exists(os.path.join(userfolder, zipfilename)): - print("folder with zipfile found, file uploaded") - return False - if len(os.listdir(userfolder)) > 0: - return True - print("distribusi folder is empty") - return False + def is_distribusi_live(distribusiname): + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + zipfilename = "{}.zip".format(distribusiname) + if os.path.exists(os.path.join(userfolder, zipfilename)): + print("folder with zipfile found, file uploaded") + return False + if len(os.listdir(userfolder)) > 0: + return True + print("distribusi folder is empty") + return False - def is_css_selected(distribusiname): - userfolder = os.path.join("themes/userthemes", distribusiname) - if os.path.exists(userfolder): - for file in os.listdir(userfolder): - if file.endswith(".css"): - return True - print("distribusi folder has no css file") - return False + def is_css_selected(distribusiname): + userfolder = os.path.join("themes/userthemes", distribusiname) + if os.path.exists(userfolder): + for file in os.listdir(userfolder): + if file.endswith(".css"): + return True + print("distribusi folder has no css file") + return False - def has_distribusi(): - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by(userid=user.id).first() - if distribusi is None: - print("no distribusi found") - return False - return True + def has_distribusi(): + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by(userid=user.id).first() + if distribusi is None: + print("no distribusi found") + return False + return True - def current_distribusi(): - user = User.query.filter_by(email=current_user.email).first() - if user.currentdistribusi is None: - return "None" - return user.currentdistribusi + def current_distribusi(): + user = User.query.filter_by(email=current_user.email).first() + if user.currentdistribusi is None: + return "None" + return user.currentdistribusi - def reset_user_state(): - """reset user state upon visiting index, so that distribusi workflow can - be done correctly""" - if not current_user.is_authenticated: - return - try: - user = User.query.filter_by(email=current_user.email).first() - user.currentdistribusi = None - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("An error occured !", "danger") + def reset_user_state(): + """reset user state upon visiting index, so that distribusi workflow can + be done correctly""" + if not current_user.is_authenticated: + return + try: + user = User.query.filter_by(email=current_user.email).first() + user.currentdistribusi = None + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("An error occured !", "danger") - def distribusi_limit_reached(): - user = User.query.filter_by(email=current_user.email).first() - distribusiamount = len(DistribusisInfo.getuserdistribusis(user.email)) - if distribusiamount > 19: - print("user already has 20 distribusis") - return True - return False + def distribusi_limit_reached(): + user = User.query.filter_by(email=current_user.email).first() + distribusiamount = len(DistribusisInfo.getuserdistribusis(user.email)) + if distribusiamount > 19: + print("user already has 20 distribusis") + return True + return False diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py index 6f18cde..69bbbee 100644 --- a/verse/statuspengguna/loginuser.py +++ b/verse/statuspengguna/loginuser.py @@ -1,11 +1,11 @@ from flask import ( - Blueprint, - abort, - flash, - redirect, - render_template, - request, - url_for, + Blueprint, + abort, + flash, + redirect, + render_template, + request, + url_for, ) from flask_bcrypt import check_password_hash from flask_login import login_user @@ -14,39 +14,39 @@ from forms.loginform import LoginForm from models.user_model import User login_section = Blueprint( - "login", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "login", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @login_section.route("/", methods=["GET", "POST"]) def login(): - return LoginUser() + return LoginUser() def LoginUser(): - loginform = LoginForm() - if loginform.validate_on_submit(): - try: - user = User.query.filter_by(email=loginform.email.data).first() - if user is None: - loginform.password.errors.append("Invalid email or password!") - return render_template("login.html", loginform=loginform) - if check_password_hash(user.password, loginform.password.data): - login_user(user) - flash("Logged in successfully.", "success") - next = request.args.get("next") - if next is not None and not is_safe_url(next): # noqa: F821 - print(next) - return abort(400) - print("index") - return redirect(next or url_for("index")) - else: - flash("Invalid email or password!", "danger") - loginform.password.errors.append("Invalid email or password!") - return render_template("login.html", loginform=loginform) - except Exception as e: - flash(e, "danger") - return render_template("login.html", loginform=loginform) + loginform = LoginForm() + if loginform.validate_on_submit(): + try: + user = User.query.filter_by(email=loginform.email.data).first() + if user is None: + loginform.password.errors.append("Invalid email or password!") + return render_template("login.html", loginform=loginform) + if check_password_hash(user.password, loginform.password.data): + login_user(user) + flash("Logged in successfully.", "success") + next = request.args.get("next") + if next is not None and not is_safe_url(next): # noqa: F821 + print(next) + return abort(400) + print("index") + return redirect(next or url_for("index")) + else: + flash("Invalid email or password!", "danger") + loginform.password.errors.append("Invalid email or password!") + return render_template("login.html", loginform=loginform) + except Exception as e: + flash(e, "danger") + return render_template("login.html", loginform=loginform) diff --git a/verse/statuspengguna/registeruser.py b/verse/statuspengguna/registeruser.py index e97f1ee..ade624a 100644 --- a/verse/statuspengguna/registeruser.py +++ b/verse/statuspengguna/registeruser.py @@ -2,11 +2,11 @@ from flask import Blueprint, flash, redirect, render_template, url_for from flask_bcrypt import generate_password_hash from flask_login import login_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from werkzeug.routing import BuildError @@ -15,64 +15,64 @@ from forms.registerform import RegisterForm from models.user_model import User register_user = Blueprint( - "register", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "register", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @register_user.route("/", methods=["GET", "POST"]) def register(): - return RegisterUser() + return RegisterUser() def RegisterUser(): - registerform = RegisterForm() - if registerform.validate_on_submit(): - try: - username = registerform.username.data - email = registerform.email.data - password = registerform.confirmpassword.data + registerform = RegisterForm() + if registerform.validate_on_submit(): + try: + username = registerform.username.data + email = registerform.email.data + password = registerform.confirmpassword.data - newuser = User( - username=username, - email=email, - password=generate_password_hash(password), - ) + newuser = User( + username=username, + email=email, + password=generate_password_hash(password), + ) - db.session.add(newuser) - db.session.commit() - flash("Account Succesfully created", "success") - login_user(newuser) - return redirect(url_for("index")) + db.session.add(newuser) + db.session.commit() + flash("Account Succesfully created", "success") + login_user(newuser) + return redirect(url_for("index")) - except InvalidRequestError: - db.session.rollback() - registerform.email.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - except IntegrityError: - db.session.rollback() - registerform.email.errors.append("User already exists!") - flash("User already exists!", "warning") - except DataError: - db.session.rollback() - registerform.email.errors.append("Invalid Entry") - flash("Invalid Entry", "warning") - except InterfaceError: - db.session.rollback() - registerform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except DatabaseError: - db.session.rollback() - registerform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except BuildError: - db.session.rollback() - registerform.email.errors.append("Unknown error occured!") - flash("An error occured !", "danger") - return render_template("register.html", registerform=registerform) + except InvalidRequestError: + db.session.rollback() + registerform.email.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except IntegrityError: + db.session.rollback() + registerform.email.errors.append("User already exists!") + flash("User already exists!", "warning") + except DataError: + db.session.rollback() + registerform.email.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + registerform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + registerform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except BuildError: + db.session.rollback() + registerform.email.errors.append("Unknown error occured!") + flash("An error occured !", "danger") + return render_template("register.html", registerform=registerform) diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py index c0288ae..e0da583 100644 --- a/verse/statuspengguna/resetpassword.py +++ b/verse/statuspengguna/resetpassword.py @@ -4,11 +4,11 @@ from flask import Blueprint, flash, redirect, render_template, url_for from flask_bcrypt import generate_password_hash from flask_login import login_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from werkzeug.routing import BuildError @@ -17,74 +17,74 @@ from forms.resetpasswordform import ResetPasswordForm from models.user_model import User reset_password = Blueprint( - "reset_password", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "reset_password", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @reset_password.route("/resetpassword/", methods=["GET", "POST"]) def resetpassword(path): - return ResetPassword(path) + return ResetPassword(path) def ResetPassword(path): - linkvalid = False - user = User.query.filter_by(resethash=path).first() - if user is None: - return redirect(url_for("index")) - timepassed = datetime.now() - user.resettime - if timepassed.days < 1: - linkvalid = True + linkvalid = False + user = User.query.filter_by(resethash=path).first() + if user is None: + return redirect(url_for("index")) + timepassed = datetime.now() - user.resettime + if timepassed.days < 1: + linkvalid = True - resetpasswordform = ResetPasswordForm() - if resetpasswordform.validate_on_submit(): - return ResetUserPasswordInDB(user, resetpasswordform) - return render_template( - "resetpassword.html", - resetpasswordform=resetpasswordform, - path=path, - linkvalid=linkvalid, - ) + resetpasswordform = ResetPasswordForm() + if resetpasswordform.validate_on_submit(): + return ResetUserPasswordInDB(user, resetpasswordform) + return render_template( + "resetpassword.html", + resetpasswordform=resetpasswordform, + path=path, + linkvalid=linkvalid, + ) def ResetUserPasswordInDB(user, resetpasswordform): - try: - newpassword = resetpasswordform.confirmpassword.data - user.password = generate_password_hash(newpassword) - user.resethash = None - user.resettime = None - db.session.commit() - flash("Password Succesfully updated", "success") - login_user(user) - return redirect(url_for("index")) + try: + newpassword = resetpasswordform.confirmpassword.data + user.password = generate_password_hash(newpassword) + user.resethash = None + user.resettime = None + db.session.commit() + flash("Password Succesfully updated", "success") + login_user(user) + return redirect(url_for("index")) - except InvalidRequestError: - db.session.rollback() - resetpasswordform.email.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - except IntegrityError: - db.session.rollback() - resetpasswordform.email.errors.append("User already exists!") - flash("User already exists!", "warning") - except DataError: - db.session.rollback() - resetpasswordform.email.errors.append("Invalid Entry") - flash("Invalid Entry", "warning") - except InterfaceError: - db.session.rollback() - resetpasswordform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except DatabaseError: - db.session.rollback() - resetpasswordform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except BuildError: - db.session.rollback() - resetpasswordform.email.errors.append("Unknown error occured!") - flash("An error occured !", "danger") + except InvalidRequestError: + db.session.rollback() + resetpasswordform.email.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except IntegrityError: + db.session.rollback() + resetpasswordform.email.errors.append("User already exists!") + flash("User already exists!", "warning") + except DataError: + db.session.rollback() + resetpasswordform.email.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + resetpasswordform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + resetpasswordform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except BuildError: + db.session.rollback() + resetpasswordform.email.errors.append("Unknown error occured!") + flash("An error occured !", "danger") -- 2.39.2 From d301ab8b5314fc997874e2eb93c1239fdc5a474e Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 27 May 2024 14:25:25 +0200 Subject: [PATCH 14/49] wip describe file form --- verse/describer/describe_files.py | 12 +++++++- verse/describer/forms/describe_file_form.py | 3 -- .../templates/describe_files/describe.html | 28 +++++++++++++++++++ verse/start.py | 2 +- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 015597a..62ec170 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -1,5 +1,5 @@ from flask import Blueprint, render_template, redirect, url_for -from flask_login import current_user +from flask_login import current_user, login_required from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from describer.forms.describe_file_form import DescribeFileForm @@ -13,6 +13,7 @@ describer = Blueprint( @describer.route("/") +@login_required def describe_distribusi_files(distribusiname): if not current_user.is_authenticated: return redirect(url_for("index")) @@ -30,3 +31,12 @@ def describe_distribusi_files(distribusiname): distribusi_files=distribusi_files, describe_form=describe_form, ) + + +@describer.route("/describe_file", methods=["POST"]) +@login_required +def describe_file(file_name): + describe_form = DescribeFileForm() + if describe_form.validate_on_submit(): + print(f"{file_name} description: {describe_form.description.data}") + return diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py index 2125642..0a97b3e 100644 --- a/verse/describer/forms/describe_file_form.py +++ b/verse/describer/forms/describe_file_form.py @@ -11,21 +11,18 @@ class DescribeFileForm(FlaskForm): alttext = StringField( "Alt-text for this file:", validators=[ - validators.InputRequired(), Length(3, 255), ], ) searchtags = StringField( "Add search tags, seperated by commas. No need for the '#' sign:", validators=[ - validators.InputRequired(), Length(3, 500), ], ) description = StringField( "Description of this file:", validators=[ - validators.InputRequired(), Length(3, 4096), ], ) diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 22b486d..6b30b14 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -29,6 +29,34 @@
{% for file in distribusi_files %}

{{file.path}}

+
+ {{ describe_form.csrf_token }} +
+ {{ describe_form.description.label }} + {{ describe_form.description }} + {% for message in describe_form.description.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.searchtags.label }} + {{ describe_form.searchtags }} + {% for message in describe_form.searchtags.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.alttext.label }} + {{ describe_form.alttext }} + {% for message in describe_form.alttext.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.save }} +
+
{% endfor%}
+ {% endblock %} diff --git a/verse/start.py b/verse/start.py index 0b3be38..0796441 100644 --- a/verse/start.py +++ b/verse/start.py @@ -30,7 +30,7 @@ APP = create_app() stash_page = Blueprint("stash_page", __name__, static_folder="stash") APP.register_blueprint(stash_page) -APP.register_blueprint(describer, url_prefix="/describe") +APP.register_blueprint(describer, url_prefix="/describer") APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") -- 2.39.2 From 30f69cf03ca03b7d09e001c2642b07ee635a5911 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 27 May 2024 17:25:27 +0200 Subject: [PATCH 15/49] wip describe file form part 2 --- verse/describer/describe_files.py | 56 +++++++++++++------ verse/describer/forms/describe_file_form.py | 29 ---------- verse/describer/forms/describe_files_form.py | 47 ++++++++++++++++ .../templates/describe_files/describe.html | 7 ++- verse/distribusikan/distribusiselector.py | 2 +- verse/file_crawler.py | 2 +- verse/start.py | 4 +- 7 files changed, 95 insertions(+), 52 deletions(-) delete mode 100644 verse/describer/forms/describe_file_form.py create mode 100644 verse/describer/forms/describe_files_form.py diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 62ec170..f64b763 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -2,7 +2,7 @@ from flask import Blueprint, render_template, redirect, url_for from flask_login import current_user, login_required from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles -from describer.forms.describe_file_form import DescribeFileForm +from describer.forms.describe_files_form import DescribeFilesForm describer = Blueprint( "describer", @@ -14,29 +14,53 @@ describer = Blueprint( @describer.route("/") @login_required -def describe_distribusi_files(distribusiname): +def show_distribusi_files(distribusiname): if not current_user.is_authenticated: return redirect(url_for("index")) distribusi = Distribusis.query.filter_by( distribusiname=distribusiname ).first() - distribusi_files = DistribusiFiles.query.filter_by( - distribusi=distribusi.id - ).all() - # distribusi_file_forms = {} - # for distribusi_file in distribusi_files: - describe_form = DescribeFileForm() + distribusi_file_forms = get_distribusi_file_forms(distribusi.id) return render_template( "describe.html", - distribusi_files=distribusi_files, - describe_form=describe_form, + distribusi_file_forms=distribusi_file_forms, ) -@describer.route("/describe_file", methods=["POST"]) +@describer.route("/describe_file/", methods=["POST"]) @login_required -def describe_file(file_name): - describe_form = DescribeFileForm() - if describe_form.validate_on_submit(): - print(f"{file_name} description: {describe_form.description.data}") - return +def describe_file(file_id): + distribusi_file = DistribusiFiles.query.filter_by(id=file_id).first() + describe_form = DescribeFilesForm(distribusi_file.id, distribusi_file.path) + print( + f"file: {describe_form.file_path} description: {describe_form.description.data}" + ) + print( + f"file: {describe_form.file_path} searchtags: {describe_form.searchtags.data}" + ) + print( + f"file: {describe_form.file_path} alttext: {describe_form.alttext.data}" + ) + distribusi_file_forms = get_distribusi_file_forms( + distribusi_file.distribusi + ) + return render_template( + "describe.html", + distribusi_file_forms=distribusi_file_forms, + ) + + +def get_distribusi_file_forms(distribusi_id): + distribusi_file_forms = {} + distribusi_files = DistribusiFiles.query.filter_by( + distribusi=distribusi_id + ).all() + for distribusi_file in distribusi_files: + describe_form = DescribeFilesForm( + distribusi_file.id, distribusi_file.path + ) + describe_form.description.data = distribusi_file.description + describe_form.alttext.data = distribusi_file.alttext + describe_form.searchtags.data = distribusi_file.tags + distribusi_file_forms[distribusi_file.id] = describe_form + return distribusi_file_forms diff --git a/verse/describer/forms/describe_file_form.py b/verse/describer/forms/describe_file_form.py deleted file mode 100644 index 0a97b3e..0000000 --- a/verse/describer/forms/describe_file_form.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Describe File Form to describe files in the distribusi archive""" - -from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField, validators -from wtforms.validators import Length - - -class DescribeFileForm(FlaskForm): - """DescribeFileForm selection form.""" - - alttext = StringField( - "Alt-text for this file:", - validators=[ - Length(3, 255), - ], - ) - searchtags = StringField( - "Add search tags, seperated by commas. No need for the '#' sign:", - validators=[ - Length(3, 500), - ], - ) - description = StringField( - "Description of this file:", - validators=[ - Length(3, 4096), - ], - ) - save = SubmitField("Save") diff --git a/verse/describer/forms/describe_files_form.py b/verse/describer/forms/describe_files_form.py new file mode 100644 index 0000000..f127751 --- /dev/null +++ b/verse/describer/forms/describe_files_form.py @@ -0,0 +1,47 @@ +"""Describe File Form to describe files in the distribusi archive""" + +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, validators +from wtforms.validators import Length +from wtforms.widgets import TextArea + + +class DescribeFilesForm(FlaskForm): + """DescribeFileForm selection form.""" + + alttext = StringField( + "Alt-text for this file:", + validators=[ + Length(3, 255), + ], + ) + searchtags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[ + Length(3, 500), + ], + ) + description = StringField( + "Description of this file:", + validators=[ + Length(3, 4096), + ], + widget=TextArea(), + ) + save = SubmitField("Save") + + def __init__(self, id, file_path=None): + super(DescribeFilesForm, self).__init__() + self.id = id + self.file_path = file_path + self.alttext.id = f"alttext-{id}" + self.searchtags.id = f"searchtags-{id}" + self.description.id = f"description-{id}" + self.save.id = f"save-{id}" + + +# def StringFieldWithId(form_name, **kwargs): +# name = kwargs.get('name', 'Bar') +# return wtf.StringField(name, render_kw={ +# 'id': f'{}{}'.format(form_name, name.lower(), +# **kwargs.get('render_kw', {})}) diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 6b30b14..5b3276e 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -27,10 +27,11 @@
- {% for file in distribusi_files %} -

{{file.path}}

-
+ {% for id, describe_form in distribusi_file_forms.items() %} + {{ describe_form.csrf_token }} +

{{describe_form.id}}

+

{{describe_form.file_path}}

{{ describe_form.description.label }} {{ describe_form.description }} diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index fef2c62..b035953 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -69,7 +69,7 @@ def SelectNewDistribusi(): def SelectDescribeDistribusi(distribusiname): return redirect( url_for( - "describer.describe_distribusi_files", + "describer.show_distribusi_files", distribusiname=distribusiname, ) ) diff --git a/verse/file_crawler.py b/verse/file_crawler.py index 0a86f79..d378f85 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -70,4 +70,4 @@ def add_distribusi_files(path): _distribusi_file_with_type(distribusi, full_path) -add_distribusi_files("2018-12-WttF-Mastodon-and-the-Fediverse") +add_distribusi_files("2018-02-16-Extratonality") diff --git a/verse/start.py b/verse/start.py index 0796441..5e9530c 100644 --- a/verse/start.py +++ b/verse/start.py @@ -14,7 +14,7 @@ from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError from adminpage import AdminPage -from app import create_app, login_manager +from app import db, create_app, login_manager from describer.describe_files import describer from distribusikan.distribusikan import distribusikan from distribusikan.distribusisinfo import DistribusisInfo @@ -112,7 +112,7 @@ def handle_csrf_error(e): @login_manager.user_loader def load_user(user_id): - return User.query.get(int(user_id)) + return db.session.get(User, int(user_id)) def is_adminuser(): -- 2.39.2 From 8cf5ca198b2e7a77decf27e84bc25b1a560f0fd9 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 27 May 2024 18:54:55 +0200 Subject: [PATCH 16/49] wip describe file now shows the files to be described --- .gitignore | 1 + verse/describer/describe_files.py | 32 +++++++++++++------ verse/describer/forms/describe_files_form.py | 3 +- .../templates/describe_files/describe.html | 14 ++++++-- verse/static/css/style.css | 17 ++++++++++ 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 705c21e..e7045b6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.pyc *.egg-info/ .eggs/ +.ruff_cache build/ dist/ pip-wheel-metadata/ diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index f64b763..31a8e79 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -1,4 +1,10 @@ -from flask import Blueprint, render_template, redirect, url_for +from flask import ( + Blueprint, + render_template, + redirect, + url_for, + send_from_directory, +) from flask_login import current_user, login_required from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles @@ -31,7 +37,9 @@ def show_distribusi_files(distribusiname): @login_required def describe_file(file_id): distribusi_file = DistribusiFiles.query.filter_by(id=file_id).first() - describe_form = DescribeFilesForm(distribusi_file.id, distribusi_file.path) + describe_form = DescribeFilesForm( + distribusi_file.id, distribusi_file.path, distribusi_file.type + ) print( f"file: {describe_form.file_path} description: {describe_form.description.data}" ) @@ -41,14 +49,20 @@ def describe_file(file_id): print( f"file: {describe_form.file_path} alttext: {describe_form.alttext.data}" ) - distribusi_file_forms = get_distribusi_file_forms( - distribusi_file.distribusi - ) - return render_template( - "describe.html", - distribusi_file_forms=distribusi_file_forms, + distribusi = Distribusis.query.filter_by( + id=distribusi_file.distribusi + ).first() + return redirect( + url_for( + "describer.show_distribusi_files", + distribusiname=distribusi.distribusiname, + ) ) +@describer.route("/stash/") +def send_stash_file(path): + return send_from_directory("stash", path) + def get_distribusi_file_forms(distribusi_id): distribusi_file_forms = {} @@ -57,7 +71,7 @@ def get_distribusi_file_forms(distribusi_id): ).all() for distribusi_file in distribusi_files: describe_form = DescribeFilesForm( - distribusi_file.id, distribusi_file.path + distribusi_file.id, distribusi_file.path, distribusi_file.type ) describe_form.description.data = distribusi_file.description describe_form.alttext.data = distribusi_file.alttext diff --git a/verse/describer/forms/describe_files_form.py b/verse/describer/forms/describe_files_form.py index f127751..517b818 100644 --- a/verse/describer/forms/describe_files_form.py +++ b/verse/describer/forms/describe_files_form.py @@ -30,10 +30,11 @@ class DescribeFilesForm(FlaskForm): ) save = SubmitField("Save") - def __init__(self, id, file_path=None): + def __init__(self, id, file_path=None, type=None): super(DescribeFilesForm, self).__init__() self.id = id self.file_path = file_path + self.type = type self.alttext.id = f"alttext-{id}" self.searchtags.id = f"searchtags-{id}" self.description.id = f"description-{id}" diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 5b3276e..db3e72e 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -28,10 +28,19 @@
{% for id, describe_form in distribusi_file_forms.items() %} +
+ {% if describe_form.type == "image" %} + + {% elif describe_form.type == "video" %} + + {% elif describe_form.type == "audio" %} + + {% else %} + file: {{describe_form.file_path}} + {% endif %} {{ describe_form.csrf_token }} -

{{describe_form.id}}

-

{{describe_form.file_path}}

+

File path: {{describe_form.file_path}}

{{ describe_form.description.label }} {{ describe_form.description }} @@ -57,6 +66,7 @@ {{ describe_form.save }}
+
{% endfor%}
diff --git a/verse/static/css/style.css b/verse/static/css/style.css index 2f772a8..900ee56 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -174,6 +174,23 @@ a:active { content: "$ "; } +.distribusi_file { + margin-top: 1em; + padding: 0.5em; + padding-left: auto; + padding-right: auto; + width: 45em; + background-color:#fdfdfd; + text-decoration: none; + scroll-behavior: smooth; + border-style: outset; +} + +.distribusi_file > img, video { + max-width: 100%; + max-height: 100%; +} + @media (prefers-reduced-motion: no-preference) { @keyframes flash { 50% { opacity: 0; } -- 2.39.2 From 7456eea083e459054e624aea14f48d535d876509 Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 27 May 2024 22:00:55 +0200 Subject: [PATCH 17/49] delete unused folder --- src/.gitignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 src/.gitignore diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 94548af..0000000 --- a/src/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -*/ -!.gitignore -- 2.39.2 From 2a018ab863ae22e4c91183e4d870d92c0850e967 Mon Sep 17 00:00:00 2001 From: crunk Date: Tue, 28 May 2024 23:02:17 +0200 Subject: [PATCH 18/49] I love trying different formatters --- pyproject.toml | 2 +- verse/adminpage.py | 126 ++++---- verse/admintool.py | 54 ++-- verse/app.py | 72 ++--- verse/deploydb.py | 30 +- verse/describer/describe_files.py | 103 ++++--- verse/describer/forms/describe_files_form.py | 60 ++-- verse/distribusikan/distribusikan.py | 18 +- verse/distribusikan/distribusiselector.py | 244 ++++++++-------- verse/distribusikan/distribusisinfo.py | 54 ++-- verse/distribusikan/distribusiworkflow.py | 176 ++++++------ verse/distribusikan/editor.py | 284 +++++++++---------- verse/distribusikan/themeselector.py | 90 +++--- verse/distribusikan/upload.py | 136 ++++----- verse/distribusikan/uploadpage.py | 64 ++--- verse/file_crawler.py | 96 +++---- verse/forms/admindistribusiform.py | 24 +- verse/forms/adminuserform.py | 24 +- verse/forms/distribusiform.py | 4 +- verse/forms/editorform.py | 46 +-- verse/forms/forgotpasswordform.py | 12 +- verse/forms/loginform.py | 18 +- verse/forms/publicthemeform.py | 10 +- verse/forms/registerform.py | 52 ++-- verse/forms/resetpasswordform.py | 28 +- verse/forms/selectorform.py | 10 +- verse/forms/themeform.py | 20 +- verse/forms/uploadform.py | 134 ++++----- verse/migrations/env.py | 86 +++--- verse/models/distribusi_file_model.py | 22 +- verse/models/distribusi_model.py | 24 +- verse/models/user_model.py | 24 +- verse/start.py | 108 +++---- verse/statuspengguna/forgotpassword.py | 78 ++--- verse/statuspengguna/helper.py | 126 ++++---- verse/statuspengguna/loginuser.py | 70 ++--- verse/statuspengguna/registeruser.py | 110 +++---- verse/statuspengguna/resetpassword.py | 126 ++++---- 38 files changed, 1379 insertions(+), 1386 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 17f3822..665a9ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.format] quote-style = "double" -indent-style = "tab" +indent-style = "space" docstring-code-format = true line-ending = "auto" skip-magic-trailing-comma = false diff --git a/verse/adminpage.py b/verse/adminpage.py index 9763e3e..0bb1c39 100644 --- a/verse/adminpage.py +++ b/verse/adminpage.py @@ -3,10 +3,10 @@ import shutil from flask import render_template from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -18,88 +18,88 @@ from models.user_model import User def AdminPage(): - adminuserform = AddUsersToForm(AdminUserForm()) - admindistribusiform = AddDistribusisToForm(AdminDistribusiForm()) - if admindistribusiform.validate_on_submit(): - DeleteDistribusis(admindistribusiform) + adminuserform = AddUsersToForm(AdminUserForm()) + admindistribusiform = AddDistribusisToForm(AdminDistribusiForm()) + if admindistribusiform.validate_on_submit(): + DeleteDistribusis(admindistribusiform) - if adminuserform.validate_on_submit(): - if adminuserform.delete.data: - DeleteUsers(adminuserform) + if adminuserform.validate_on_submit(): + if adminuserform.delete.data: + DeleteUsers(adminuserform) - template = render_template( - "admin.html", - adminuserform=adminuserform, - admindistribusiform=admindistribusiform, - ) - return template + template = render_template( + "admin.html", + adminuserform=adminuserform, + admindistribusiform=admindistribusiform, + ) + return template def DeleteUsers(adminuserform): - for userform in adminuserform: - if "user" in userform.id: - if userform.data: - useremail = userform.label.text - user = User.query.filter_by(email=useremail).first() - DeleteUserDistribusis(user) - DeleteUserFromDb(user) - userform.errors.append(f"User {useremail} deleted!") + for userform in adminuserform: + if "user" in userform.id: + if userform.data: + useremail = userform.label.text + user = User.query.filter_by(email=useremail).first() + DeleteUserDistribusis(user) + DeleteUserFromDb(user) + userform.errors.append(f"User {useremail} deleted!") def DeleteUserFromDb(user): - try: - db.session.delete(user) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() + try: + db.session.delete(user) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() def DeleteUserDistribusis(user): - distribusis = DistribusisInfo.getuserdistribusis(user.email) - for distribusi in distribusis: - DeleteDistribusiFiles(distribusi.distribusiname) - DeleteDistribusiFromDb(distribusi) + distribusis = DistribusisInfo.getuserdistribusis(user.email) + for distribusi in distribusis: + DeleteDistribusiFiles(distribusi.distribusiname) + DeleteDistribusiFromDb(distribusi) def DeleteDistribusis(admindistribusiform): - for distribusiform in admindistribusiform: - if "distribusi" in distribusiform.id: - if distribusiform.data: - distribusiname = distribusiform.label.text - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - DeleteDistribusiFromDb(distribusi) - DeleteDistribusiFiles(distribusiname) - distribusiform.errors.append("Deleted distribusi") + for distribusiform in admindistribusiform: + if "distribusi" in distribusiform.id: + if distribusiform.data: + distribusiname = distribusiform.label.text + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + DeleteDistribusiFromDb(distribusi) + DeleteDistribusiFiles(distribusiname) + distribusiform.errors.append("Deleted distribusi") def DeleteDistribusiFromDb(distribusi): - try: - db.session.delete(distribusi) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() + try: + db.session.delete(distribusi) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() def DeleteDistribusiFiles(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - shutil.rmtree(userfolder) - cssfolder = os.path.join("themes/userthemes", distribusiname) - if os.path.exists(cssfolder): - shutil.rmtree(cssfolder) + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + shutil.rmtree(userfolder) + cssfolder = os.path.join("themes/userthemes", distribusiname) + if os.path.exists(cssfolder): + shutil.rmtree(cssfolder) def AddDistribusisToForm(admindistribusiform): - distribusis = DistribusisInfo.visibledistribusis() - admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( - distribusis - ) - return admindistribusiform + distribusis = DistribusisInfo.visibledistribusis() + admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( + distribusis + ) + return admindistribusiform def AddUsersToForm(adminuserform): - users = User.query.all() - adminuserform = AdminUserForm.user_list_form_builder(users) - return adminuserform + users = User.query.all() + adminuserform = AdminUserForm.user_list_form_builder(users) + return adminuserform diff --git a/verse/admintool.py b/verse/admintool.py index def02bd..c8ddac3 100644 --- a/verse/admintool.py +++ b/verse/admintool.py @@ -1,10 +1,10 @@ import sys from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import create_app, db @@ -13,32 +13,32 @@ from models.user_model import User # noqa: F401 def admintool(): - """Admin CLI tool. To elevate a user to admin""" - app = create_app() - app.app_context().push() - elevateusertoadmin() + """Admin CLI tool. To elevate a user to admin""" + app = create_app() + app.app_context().push() + elevateusertoadmin() def elevateusertoadmin(): - """To elevates user of first command line argument to admin""" - user = User.query.filter_by(email=sys.argv[1]).first() - print(f"user {user.username} found with email {user.email}") - try: - user.admin = True - db.session.commit() - print(f"Account {user.email} succesfully made into an admin") - except InvalidRequestError: - db.session.rollback() - print("Something went wrong!") - except InterfaceError: - db.session.rollback() - print("Error connecting to the database") - except DataError: - db.session.rollback() - print("Invalid Entry") - except DatabaseError: - db.session.rollback() - print("Error connecting to the database") + """To elevates user of first command line argument to admin""" + user = User.query.filter_by(email=sys.argv[1]).first() + print(f"user {user.username} found with email {user.email}") + try: + user.admin = True + db.session.commit() + print(f"Account {user.email} succesfully made into an admin") + except InvalidRequestError: + db.session.rollback() + print("Something went wrong!") + except InterfaceError: + db.session.rollback() + print("Error connecting to the database") + except DataError: + db.session.rollback() + print("Invalid Entry") + except DatabaseError: + db.session.rollback() + print("Error connecting to the database") admintool() diff --git a/verse/app.py b/verse/app.py index 9aff866..529db20 100644 --- a/verse/app.py +++ b/verse/app.py @@ -16,56 +16,56 @@ login_manager = LoginManager() def create_app(): - APP.secret_key = os.urandom(24) - APP.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///distribusiverse.db" - APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True + APP.secret_key = os.urandom(24) + APP.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///distribusiverse.db" + APP.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True - APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 - APP.config["MAIL_SERVER"] = "mail.autonomic.zone" - APP.config["MAIL_PORT"] = 587 - APP.config["MAIL_USE_SSL"] = False - APP.config["MAIL_USE_TLS"] = True - APP.config["MAIL_USERNAME"] = "noreply@vvvvvvaria.org" + APP.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024 + APP.config["MAIL_SERVER"] = "mail.autonomic.zone" + APP.config["MAIL_PORT"] = 587 + APP.config["MAIL_USE_SSL"] = False + APP.config["MAIL_USE_TLS"] = True + APP.config["MAIL_USERNAME"] = "noreply@vvvvvvaria.org" - login_manager.session_protection = "strong" - login_manager.login_view = "index" - login_manager.login_message_category = "info" + login_manager.session_protection = "strong" + login_manager.login_view = "index" + login_manager.login_message_category = "info" - csrf = CSRFProtect() + csrf = CSRFProtect() - APP.config["SECRET_KEY"] = os.urandom(24) - APP.config["UPLOAD_FOLDER"] = "tmpupload" - APP.config["PUBLIC_THEMES"] = "themes/publicthemes" + APP.config["SECRET_KEY"] = os.urandom(24) + APP.config["UPLOAD_FOLDER"] = "tmpupload" + APP.config["PUBLIC_THEMES"] = "themes/publicthemes" - # user settings_file - settings() + # user settings_file + settings() - csrf.init_app(APP) - login_manager.init_app(APP) - db.init_app(APP) - migrate.init_app(APP, db, render_as_batch=True) - bcrypt.init_app(APP) + csrf.init_app(APP) + login_manager.init_app(APP) + db.init_app(APP) + migrate.init_app(APP, db, render_as_batch=True) + bcrypt.init_app(APP) - @APP.context_processor - def inject_title(): - return dict(title=APP.config["title"]) + @APP.context_processor + def inject_title(): + return dict(title=APP.config["title"]) - return APP + return APP def settings(): - settings = settings_from_file() - APP.config.update(settings) - return APP + settings = settings_from_file() + APP.config.update(settings) + return APP def get_app(): - return APP + return APP def settings_from_file(): - if os.path.isfile("settings_development.toml"): - with open("settings_development.toml", "rb") as settings_file: - return tomllib.load(settings_file) - with open("settings.toml", "rb") as settings_file: - return tomllib.load(settings_file) + if os.path.isfile("settings_development.toml"): + with open("settings_development.toml", "rb") as settings_file: + return tomllib.load(settings_file) + with open("settings.toml", "rb") as settings_file: + return tomllib.load(settings_file) diff --git a/verse/deploydb.py b/verse/deploydb.py index 51d8f13..30a8364 100644 --- a/verse/deploydb.py +++ b/verse/deploydb.py @@ -1,23 +1,23 @@ def deploy(): - """Run deployment of database.""" - from flask_migrate import init, migrate, stamp, upgrade + """Run deployment of database.""" + from flask_migrate import init, migrate, stamp, upgrade - from app import create_app, db - from models.distribusi_model import Distribusis # noqa: F401 - from models.distribusi_file_model import DistribusiFiles # noqa: F401 + from app import create_app, db + from models.distribusi_model import Distribusis # noqa: F401 + from models.distribusi_file_model import DistribusiFiles # noqa: F401 - # This model is required for flask_migrate to make the table - from models.user_model import User # noqa: F401 + # This model is required for flask_migrate to make the table + from models.user_model import User # noqa: F401 - app = create_app() - app.app_context().push() - db.create_all() + app = create_app() + app.app_context().push() + db.create_all() - # migrate database to latest revision - init() - stamp() - migrate() - upgrade() + # migrate database to latest revision + init() + stamp() + migrate() + upgrade() deploy() diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 31a8e79..b2c40d0 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -1,9 +1,9 @@ from flask import ( - Blueprint, - render_template, - redirect, - url_for, - send_from_directory, + Blueprint, + render_template, + redirect, + url_for, + send_from_directory, ) from flask_login import current_user, login_required from models.distribusi_model import Distribusis @@ -11,70 +11,63 @@ from models.distribusi_file_model import DistribusiFiles from describer.forms.describe_files_form import DescribeFilesForm describer = Blueprint( - "describer", - __name__, - template_folder="templates/describe_files", - static_folder="static", + "describer", + __name__, + template_folder="templates/describe_files", + static_folder="static", ) @describer.route("/") @login_required def show_distribusi_files(distribusiname): - if not current_user.is_authenticated: - return redirect(url_for("index")) - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - distribusi_file_forms = get_distribusi_file_forms(distribusi.id) - return render_template( - "describe.html", - distribusi_file_forms=distribusi_file_forms, - ) + if not current_user.is_authenticated: + return redirect(url_for("index")) + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + distribusi_file_forms = get_distribusi_file_forms(distribusi.id) + return render_template( + "describe.html", + distribusi_file_forms=distribusi_file_forms, + ) @describer.route("/describe_file/", methods=["POST"]) @login_required def describe_file(file_id): - distribusi_file = DistribusiFiles.query.filter_by(id=file_id).first() - describe_form = DescribeFilesForm( - distribusi_file.id, distribusi_file.path, distribusi_file.type - ) - print( - f"file: {describe_form.file_path} description: {describe_form.description.data}" - ) - print( - f"file: {describe_form.file_path} searchtags: {describe_form.searchtags.data}" - ) - print( - f"file: {describe_form.file_path} alttext: {describe_form.alttext.data}" - ) - distribusi = Distribusis.query.filter_by( - id=distribusi_file.distribusi - ).first() - return redirect( - url_for( - "describer.show_distribusi_files", - distribusiname=distribusi.distribusiname, - ) - ) + distribusi_file = DistribusiFiles.query.filter_by(id=file_id).first() + describe_form = DescribeFilesForm( + distribusi_file.id, distribusi_file.path, distribusi_file.type + ) + + distribusi = Distribusis.query.filter_by( + id=distribusi_file.distribusi + ).first() + return redirect( + url_for( + "describer.show_distribusi_files", + distribusiname=distribusi.distribusiname, + ) + ) + @describer.route("/stash/") def send_stash_file(path): - return send_from_directory("stash", path) + return send_from_directory("stash", path) def get_distribusi_file_forms(distribusi_id): - distribusi_file_forms = {} - distribusi_files = DistribusiFiles.query.filter_by( - distribusi=distribusi_id - ).all() - for distribusi_file in distribusi_files: - describe_form = DescribeFilesForm( - distribusi_file.id, distribusi_file.path, distribusi_file.type - ) - describe_form.description.data = distribusi_file.description - describe_form.alttext.data = distribusi_file.alttext - describe_form.searchtags.data = distribusi_file.tags - distribusi_file_forms[distribusi_file.id] = describe_form - return distribusi_file_forms + distribusi_file_forms = {} + distribusi_files = DistribusiFiles.query.filter_by( + distribusi=distribusi_id + ).all() + for distribusi_file in distribusi_files: + describe_form = DescribeFilesForm( + distribusi_file.id, distribusi_file.path, distribusi_file.type + ) + describe_form.description.data = distribusi_file.description + describe_form.alttext.data = distribusi_file.alttext + describe_form.searchtags.data = distribusi_file.tags + distribusi_file_forms[distribusi_file.id] = describe_form + return distribusi_file_forms diff --git a/verse/describer/forms/describe_files_form.py b/verse/describer/forms/describe_files_form.py index 517b818..6155be4 100644 --- a/verse/describer/forms/describe_files_form.py +++ b/verse/describer/forms/describe_files_form.py @@ -7,38 +7,38 @@ from wtforms.widgets import TextArea class DescribeFilesForm(FlaskForm): - """DescribeFileForm selection form.""" + """DescribeFileForm selection form.""" - alttext = StringField( - "Alt-text for this file:", - validators=[ - Length(3, 255), - ], - ) - searchtags = StringField( - "Add search tags, seperated by commas. No need for the '#' sign:", - validators=[ - Length(3, 500), - ], - ) - description = StringField( - "Description of this file:", - validators=[ - Length(3, 4096), - ], - widget=TextArea(), - ) - save = SubmitField("Save") + alttext = StringField( + "Alt-text for this file:", + validators=[ + Length(3, 255), + ], + ) + searchtags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[ + Length(3, 500), + ], + ) + description = StringField( + "Description of this file:", + validators=[ + Length(3, 4096), + ], + widget=TextArea(), + ) + save = SubmitField("Save") - def __init__(self, id, file_path=None, type=None): - super(DescribeFilesForm, self).__init__() - self.id = id - self.file_path = file_path - self.type = type - self.alttext.id = f"alttext-{id}" - self.searchtags.id = f"searchtags-{id}" - self.description.id = f"description-{id}" - self.save.id = f"save-{id}" + def __init__(self, id, file_path=None, type=None): + super(DescribeFilesForm, self).__init__() + self.id = id + self.file_path = file_path + self.type = type + self.alttext.id = f"alttext-{id}" + self.searchtags.id = f"searchtags-{id}" + self.description.id = f"description-{id}" + self.save.id = f"save-{id}" # def StringFieldWithId(form_name, **kwargs): diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py index 8b5308d..444cb96 100644 --- a/verse/distribusikan/distribusikan.py +++ b/verse/distribusikan/distribusikan.py @@ -10,38 +10,38 @@ from distribusikan.themeselector import ThemeSelector from distribusikan.uploadpage import UploadPage distribusikan = Blueprint( - "distribusikan", - __name__, - template_folder="templates/distribusikan", - static_folder="static", + "distribusikan", + __name__, + template_folder="templates/distribusikan", + static_folder="static", ) @distribusikan.route("/distribusi", methods=["GET", "POST"]) @login_required def distribusi(): - return DistribusiWorkflow() + return DistribusiWorkflow() @distribusikan.route("/upload", methods=["POST"]) @login_required def upload(): - return UploadPage() + return UploadPage() @distribusikan.route("/theme", methods=["GET", "POST"]) @login_required def theme(): - return ThemeSelector() + return ThemeSelector() @distribusikan.route("/editor", methods=["GET", "POST"]) @login_required def editor(): - return Editor() + return Editor() @distribusikan.route("/selector", methods=["GET", "POST"]) @login_required def selector(): - return DistribusiSelector() + return DistribusiSelector() diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index b035953..4201129 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -4,10 +4,10 @@ import shutil from flask import flash, render_template, redirect, url_for from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -25,148 +25,148 @@ from statuspengguna.helper import UserHelper def DistribusiSelector(): - uploadform = UploadForm() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - current_distribusi = UserHelper.current_distribusi() - if selectorform.validate_on_submit(): - if selectorform.new.data: - SelectNewDistribusi() - if selectorform.describe.data: - return SelectDescribeDistribusi(selectorform.distribusis.data) - if selectorform.delete.data: - selectorform = DeleteDistribusi(selectorform.distribusis.data) - selectorform.distribusis.choices = ( - DistribusisInfo.userdistribusinames() - ) - if selectorform.update.data: - SelectUpdateDistribusi(selectorform.distribusis.data) - current_distribusi = UserHelper.current_distribusi() - uploadform = AutoFillInUploadForm(uploadform, current_distribusi) - - return RenderDistribusiTemplate( - selectorform, uploadform, current_distribusi - ) + uploadform = UploadForm() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + current_distribusi = UserHelper.current_distribusi() + if selectorform.validate_on_submit(): + if selectorform.new.data: + SelectNewDistribusi() + if selectorform.describe.data: + return SelectDescribeDistribusi(selectorform.distribusis.data) + if selectorform.delete.data: + selectorform = DeleteDistribusi(selectorform.distribusis.data) + selectorform.distribusis.choices = ( + DistribusisInfo.userdistribusinames() + ) + if selectorform.update.data: + SelectUpdateDistribusi(selectorform.distribusis.data) + current_distribusi = UserHelper.current_distribusi() + uploadform = AutoFillInUploadForm(uploadform, current_distribusi) + + return RenderDistribusiTemplate( + selectorform, uploadform, current_distribusi + ) def AutoFillInUploadForm(uploadform, current_distribusi): - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - uploadform.sitename.data = distribusi.distribusiname - uploadform.sitename.render_kw = {"readonly": True} - uploadform.category.data = distribusi.category - uploadform.year.data = distribusi.year - uploadform.tags.data = distribusi.tags - return uploadform + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + uploadform.sitename.data = distribusi.distribusiname + uploadform.sitename.render_kw = {"readonly": True} + uploadform.category.data = distribusi.category + uploadform.year.data = distribusi.year + uploadform.tags.data = distribusi.tags + return uploadform def SelectNewDistribusi(): - print("make a new distribusi") - SelectCurrentDistribusi("new") + print("make a new distribusi") + SelectCurrentDistribusi("new") def SelectDescribeDistribusi(distribusiname): - return redirect( - url_for( - "describer.show_distribusi_files", - distribusiname=distribusiname, - ) - ) + return redirect( + url_for( + "describer.show_distribusi_files", + distribusiname=distribusiname, + ) + ) def SelectUpdateDistribusi(distribusiname): - print(f"Update this distribusi {distribusiname}") - SelectCurrentDistribusi(distribusiname) + print(f"Update this distribusi {distribusiname}") + SelectCurrentDistribusi(distribusiname) def DeleteDistribusi(distribusiname): - print(f"delete this distribusi {distribusiname}") - selectorform = SelectorForm() - try: - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - if distribusi.userid is user.id: - db.session.delete(distribusi) - db.session.commit() - userfolder = os.path.join("stash", distribusi.distribusiname) - if os.path.exists(userfolder): - shutil.rmtree(userfolder) - cssfolder = os.path.join( - "themes/userthemes", distribusi.distribusiname - ) - if os.path.exists(cssfolder): - shutil.rmtree(cssfolder) - if distribusi.publictheme is not None: - publicthemefolder = os.path.join( - "themes/publicthemes", distribusi.distribusiname - ) - if os.path.exists(publicthemefolder): - shutil.rmtree(publicthemefolder) - # SelectField error is list is a tuple?? why?? - # selectorform.distribusis.errors.append("Distribusi deleted!") - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - # selectorform.distribusis.errors.append("Unknown error occured!") - flash("An error occured !", "danger") - return selectorform + print(f"delete this distribusi {distribusiname}") + selectorform = SelectorForm() + try: + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + if distribusi.userid is user.id: + db.session.delete(distribusi) + db.session.commit() + userfolder = os.path.join("stash", distribusi.distribusiname) + if os.path.exists(userfolder): + shutil.rmtree(userfolder) + cssfolder = os.path.join( + "themes/userthemes", distribusi.distribusiname + ) + if os.path.exists(cssfolder): + shutil.rmtree(cssfolder) + if distribusi.publictheme is not None: + publicthemefolder = os.path.join( + "themes/publicthemes", distribusi.distribusiname + ) + if os.path.exists(publicthemefolder): + shutil.rmtree(publicthemefolder) + # SelectField error is list is a tuple?? why?? + # selectorform.distribusis.errors.append("Distribusi deleted!") + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + # selectorform.distribusis.errors.append("Unknown error occured!") + flash("An error occured !", "danger") + return selectorform def SelectCurrentDistribusi(distribusiname): - if not current_user.is_authenticated: - return - user = User.query.filter_by(email=current_user.email).first() - try: - user.currentdistribusi = distribusiname - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("An error occured !", "danger") + if not current_user.is_authenticated: + return + user = User.query.filter_by(email=current_user.email).first() + try: + user.currentdistribusi = distribusiname + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("An error occured !", "danger") def DistribusiSelected(): - user = User.query.filter_by(email=current_user.email).first() - if user.currentdistribusi is None: - return False - return True + user = User.query.filter_by(email=current_user.email).first() + if user.currentdistribusi is None: + return False + return True def SelectorVisible(): - has_distribusi = UserHelper.has_distribusi() - distribusi_selected = DistribusiSelected() - if distribusi_selected: - return False - if not has_distribusi: - return False - return True + has_distribusi = UserHelper.has_distribusi() + distribusi_selected = DistribusiSelected() + if distribusi_selected: + return False + if not has_distribusi: + return False + return True def RenderDistribusiTemplate(selectorform, uploadform, current_distribusi): - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - - # because the user has chosen to update his distribusi, we assume - # no selected css. - css_selected = False - selectorvisible = SelectorVisible() - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + + # because the user has chosen to update his distribusi, we assume + # no selected css. + css_selected = False + selectorvisible = SelectorVisible() + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/distribusisinfo.py b/verse/distribusikan/distribusisinfo.py index 9021c3a..19ef284 100644 --- a/verse/distribusikan/distribusisinfo.py +++ b/verse/distribusikan/distribusisinfo.py @@ -5,34 +5,34 @@ from models.user_model import User class DistribusisInfo: - def userdistribusinames(): - distribusinames = [] - user = User.query.filter_by(email=current_user.email).first() - for distribusi in Distribusis.query.filter_by(userid=user.id).all(): - distribusinames.append(distribusi.distribusiname) - return distribusinames + def userdistribusinames(): + distribusinames = [] + user = User.query.filter_by(email=current_user.email).first() + for distribusi in Distribusis.query.filter_by(userid=user.id).all(): + distribusinames.append(distribusi.distribusiname) + return distribusinames - def publicthemes(): - publicthemes = [] - distribusis = Distribusis.query.filter( - Distribusis.publictheme.isnot(None) - ).all() - for distribusi in distribusis: - user = User.query.filter_by(id=distribusi.userid).first() - publictheme = ( - f"{distribusi.distribusiname}/{distribusi.publictheme}", - f"""{distribusi.publictheme} used in {distribusi.distribusiname} + def publicthemes(): + publicthemes = [] + distribusis = Distribusis.query.filter( + Distribusis.publictheme.isnot(None) + ).all() + for distribusi in distribusis: + user = User.query.filter_by(id=distribusi.userid).first() + publictheme = ( + f"{distribusi.distribusiname}/{distribusi.publictheme}", + f"""{distribusi.publictheme} used in {distribusi.distribusiname} made by {user.username}""", - ) - publicthemes.append(publictheme) - return publicthemes + ) + publicthemes.append(publictheme) + return publicthemes - def visibledistribusis(): - distribusis = Distribusis.query.filter( - Distribusis.visible.isnot(False) - ).all() - return distribusis + def visibledistribusis(): + distribusis = Distribusis.query.filter( + Distribusis.visible.isnot(False) + ).all() + return distribusis - def getuserdistribusis(useremail): - user = User.query.filter_by(email=useremail).first() - return Distribusis.query.filter_by(userid=user.id).all() + def getuserdistribusis(useremail): + user = User.query.filter_by(email=useremail).first() + return Distribusis.query.filter_by(userid=user.id).all() diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusiworkflow.py index 7b37a5e..4e3a376 100644 --- a/verse/distribusikan/distribusiworkflow.py +++ b/verse/distribusikan/distribusiworkflow.py @@ -8,10 +8,10 @@ from distribusi.distribusi import distribusify from flask import flash, redirect, render_template, url_for from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -32,112 +32,112 @@ from statuspengguna.helper import UserHelper def DistribusiWorkflow(): - distribusiform = DistribusiForm() - current_distribusi = UserHelper.current_distribusi() - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - - if distribusiform.validate_on_submit(): - userfolder = os.path.join("stash", distribusi.distribusiname) - cssfile = GetCssFile(distribusi) - UnzipDistribusiFiles(distribusi, userfolder) - CleanUpDistribusiFiles(userfolder) - RunDistribusi(userfolder, cssfile) - SetDistribusiToVisible(distribusi, user) - DeleteCssFile(cssfile) - return redirect(url_for("index")) - - return RenderDistribusiTemplate(distribusiform, current_distribusi) + distribusiform = DistribusiForm() + current_distribusi = UserHelper.current_distribusi() + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + + if distribusiform.validate_on_submit(): + userfolder = os.path.join("stash", distribusi.distribusiname) + cssfile = GetCssFile(distribusi) + UnzipDistribusiFiles(distribusi, userfolder) + CleanUpDistribusiFiles(userfolder) + RunDistribusi(userfolder, cssfile) + SetDistribusiToVisible(distribusi, user) + DeleteCssFile(cssfile) + return redirect(url_for("index")) + + return RenderDistribusiTemplate(distribusiform, current_distribusi) def UnzipDistribusiFiles(distribusi, userfolder): - zipfilename = "{}.zip".format(distribusi.distribusiname) - unzipfile = os.path.join(userfolder, zipfilename) + zipfilename = "{}.zip".format(distribusi.distribusiname) + unzipfile = os.path.join(userfolder, zipfilename) - if os.path.exists(unzipfile): - with zipfile.ZipFile(unzipfile, "r") as zip_ref: - zip_ref.extractall(userfolder) - # after extracting all files remove zip file. - if os.path.exists(unzipfile): - os.remove(os.path.join(userfolder, zipfilename)) + if os.path.exists(unzipfile): + with zipfile.ZipFile(unzipfile, "r") as zip_ref: + zip_ref.extractall(userfolder) + # after extracting all files remove zip file. + if os.path.exists(unzipfile): + os.remove(os.path.join(userfolder, zipfilename)) def CleanUpDistribusiFiles(userfolder): - if os.path.exists(userfolder): - RemoveMacFolders(userfolder) + if os.path.exists(userfolder): + RemoveMacFolders(userfolder) def RemoveMacFolders(path): - for filename in os.listdir(path): - fullpath = os.path.join(path, filename) - if filename.startswith("."): - if os.path.isdir(fullpath): - shutil.rmtree(fullpath) - else: - os.remove(fullpath) - if filename == "__MACOSX": - shutil.rmtree(fullpath) - if os.path.isdir(fullpath): - RemoveMacFolders(fullpath) + for filename in os.listdir(path): + fullpath = os.path.join(path, filename) + if filename.startswith("."): + if os.path.isdir(fullpath): + shutil.rmtree(fullpath) + else: + os.remove(fullpath) + if filename == "__MACOSX": + shutil.rmtree(fullpath) + if os.path.isdir(fullpath): + RemoveMacFolders(fullpath) def GetCssFile(distribusi): - cssfile = "" - cssfolder = os.path.join("themes/userthemes", distribusi.distribusiname) - if os.path.exists(cssfolder): - for filename in os.listdir(cssfolder): - if filename.endswith(".css"): - cssfile = os.path.join(cssfolder, filename) - return cssfile + cssfile = "" + cssfolder = os.path.join("themes/userthemes", distribusi.distribusiname) + if os.path.exists(cssfolder): + for filename in os.listdir(cssfolder): + if filename.endswith(".css"): + cssfile = os.path.join(cssfolder, filename) + return cssfile def RunDistribusi(userfolder, cssfile): - parser = build_argparser() - args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) - distribusify(args, userfolder) + parser = build_argparser() + args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) + distribusify(args, userfolder) def SetDistribusiToVisible(distribusi, user): - try: - distribusi.visible = True - user.currentdistribusi = None - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("Unknown error occured!") + try: + distribusi.visible = True + user.currentdistribusi = None + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("Unknown error occured!") def DeleteCssFile(cssfile): - if os.path.exists(cssfile): - os.remove(cssfile) + if os.path.exists(cssfile): + os.remove(cssfile) def RenderDistribusiTemplate(distribusiform, current_distribusi): - uploadform = UploadForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - selectorvisible = SelectorVisible() - - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + uploadform = UploadForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorvisible = SelectorVisible() + + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/editor.py index 74e3a21..88e63c2 100644 --- a/verse/distribusikan/editor.py +++ b/verse/distribusikan/editor.py @@ -5,10 +5,10 @@ import bleach from bleach_allowlist import all_styles from flask import render_template from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from werkzeug.utils import secure_filename @@ -25,175 +25,175 @@ from statuspengguna.helper import UserHelper def Editor(): - editorform = EditorForm() - current_distribusi = UserHelper.current_distribusi() - if editorform.validate_on_submit(): - ValidateEditCssForm(editorform, current_distribusi) - return RenderDistribusiTemplate(current_distribusi) + editorform = EditorForm() + current_distribusi = UserHelper.current_distribusi() + if editorform.validate_on_submit(): + ValidateEditCssForm(editorform, current_distribusi) + return RenderDistribusiTemplate(current_distribusi) - return RenderEditorTemplate(editorform, current_distribusi) + return RenderEditorTemplate(editorform, current_distribusi) def ValidateEditCssForm(editorform, current_distribusi): - newcssfolder = os.path.join("themes/userthemes", current_distribusi) - if os.path.exists(newcssfolder): - shutil.rmtree(newcssfolder) - - publicfolder = os.path.join("themes/publicthemes", current_distribusi) - if os.path.exists(publicfolder): - shutil.rmtree(publicfolder) - - if editorform.public.data: - MakePublicTheme(editorform, current_distribusi) - if editorform.cssfile.data: - SaveUploadCssFile(editorform, publicfolder) - CopyPublicToUserFolder(editorform, publicfolder, newcssfolder) - return - else: - WriteCssToFile(editorform, publicfolder) - - if editorform.cssfile.data: - SaveUploadCssFile(editorform, newcssfolder) - return - if editorform.cssname.data: - WriteCssToFile(editorform, newcssfolder) + newcssfolder = os.path.join("themes/userthemes", current_distribusi) + if os.path.exists(newcssfolder): + shutil.rmtree(newcssfolder) + + publicfolder = os.path.join("themes/publicthemes", current_distribusi) + if os.path.exists(publicfolder): + shutil.rmtree(publicfolder) + + if editorform.public.data: + MakePublicTheme(editorform, current_distribusi) + if editorform.cssfile.data: + SaveUploadCssFile(editorform, publicfolder) + CopyPublicToUserFolder(editorform, publicfolder, newcssfolder) + return + else: + WriteCssToFile(editorform, publicfolder) + + if editorform.cssfile.data: + SaveUploadCssFile(editorform, newcssfolder) + return + if editorform.cssname.data: + WriteCssToFile(editorform, newcssfolder) def SaveUploadCssFile(editorform, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - cssfile = editorform.cssfile.data - cssfilename = f"{secure_filename(editorform.cssname.data)}.css" - cssfile.save(os.path.join(newcssfolder, cssfilename)) - openfile = open(os.path.join(newcssfolder, cssfilename), "r") - cleancss = bleach.clean(openfile.read(), all_styles) - cleancss = cleancss.replace(">", ">") - openfile.close() - cleanfile = open(os.path.join(newcssfolder, cssfilename), "w") - cleanfile.write(cleancss) - cleanfile.close() + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + cssfile = editorform.cssfile.data + cssfilename = f"{secure_filename(editorform.cssname.data)}.css" + cssfile.save(os.path.join(newcssfolder, cssfilename)) + openfile = open(os.path.join(newcssfolder, cssfilename), "r") + cleancss = bleach.clean(openfile.read(), all_styles) + cleancss = cleancss.replace(">", ">") + openfile.close() + cleanfile = open(os.path.join(newcssfolder, cssfilename), "w") + cleanfile.write(cleancss) + cleanfile.close() def WriteCssToFile(editorform, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) - cssfilename = f"{secure_filename(editorform.cssname.data)}.css" - cleancss = bleach.clean(editorform.css.data, all_styles) - cleancss = cleancss.replace(">", ">") - with open(os.path.join(newcssfolder, cssfilename), "w") as cssfile: - cssfile.write(cleancss) - cssfile.close + cssfilename = f"{secure_filename(editorform.cssname.data)}.css" + cleancss = bleach.clean(editorform.css.data, all_styles) + cleancss = cleancss.replace(">", ">") + with open(os.path.join(newcssfolder, cssfilename), "w") as cssfile: + cssfile.write(cleancss) + cssfile.close def CopyPublicToUserFolder(editorform, publicfolder, newcssfolder): - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - copycssfile = os.path.join( - publicfolder, f"{secure_filename(editorform.cssname.data)}.css" - ) - print(f"copying file: {copycssfile}") - print(f"to folder: {newcssfolder}") - shutil.copy(copycssfile, newcssfolder) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + copycssfile = os.path.join( + publicfolder, f"{secure_filename(editorform.cssname.data)}.css" + ) + print(f"copying file: {copycssfile}") + print(f"to folder: {newcssfolder}") + shutil.copy(copycssfile, newcssfolder) def MakePublicTheme(editorform, current_distribusi): - try: - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - distribusi.publictheme = secure_filename(editorform.cssname.data) - db.session.commit() - - except InvalidRequestError: - db.session.rollback() - editorform.public.errors.append("Something went wrong!") - except DataError: - db.session.rollback() - editorform.public.errors.append("Invalid Entry") - except InterfaceError: - db.session.rollback() - editorform.public.errors.append("Error connecting to the database") - except DatabaseError: - db.session.rollback() - editorform.public.errors.append("Error connecting to the database") + try: + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + distribusi.publictheme = secure_filename(editorform.cssname.data) + db.session.commit() + + except InvalidRequestError: + db.session.rollback() + editorform.public.errors.append("Something went wrong!") + except DataError: + db.session.rollback() + editorform.public.errors.append("Invalid Entry") + except InterfaceError: + db.session.rollback() + editorform.public.errors.append("Error connecting to the database") + except DatabaseError: + db.session.rollback() + editorform.public.errors.append("Error connecting to the database") def RenderDistribusiTemplate(current_distribusi): - uploadform = UploadForm() - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = True - selectorvisible = False - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + uploadform = UploadForm() + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = True + selectorvisible = False + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template def RenderEditorTemplate(editorform, current_distribusi): - htmlplaceholder = HtmlPlaceholder() + htmlplaceholder = HtmlPlaceholder() - cssplaceholder = CssPlaceholder(current_distribusi) - editorform.css.data = cssplaceholder + cssplaceholder = CssPlaceholder(current_distribusi) + editorform.css.data = cssplaceholder - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - template = render_template( - "editor.html", - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - editorform=editorform, - htmlplaceholder=htmlplaceholder, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + template = render_template( + "editor.html", + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + editorform=editorform, + htmlplaceholder=htmlplaceholder, + ) + return template def CssPlaceholder(current_distribusi): - cssplaceholder = "Try out your CSS here" - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - if distribusi is not None and distribusi.publictheme is not None: - cssplaceholder = GetPublicCssFile(distribusi) - else: - with open("themes/editor/placeholder.css") as f: - cssplaceholder = f.read() - return cssplaceholder + cssplaceholder = "Try out your CSS here" + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + if distribusi is not None and distribusi.publictheme is not None: + cssplaceholder = GetPublicCssFile(distribusi) + else: + with open("themes/editor/placeholder.css") as f: + cssplaceholder = f.read() + return cssplaceholder def HtmlPlaceholder(): - htmlplaceholder = "Write some test HTML here" - with open("themes/editor/placeholder.html") as f: - htmlplaceholder = f.read() - return htmlplaceholder + htmlplaceholder = "Write some test HTML here" + with open("themes/editor/placeholder.html") as f: + htmlplaceholder = f.read() + return htmlplaceholder def GetPublicCssFile(distribusi): - cssplaceholder = "" - publicthemefolder = os.path.join( - "themes/publicthemes", distribusi.distribusiname - ) - for filename in os.listdir(publicthemefolder): - if filename.endswith(".css"): - cssfile = os.path.join(publicthemefolder, filename) - with open(cssfile) as f: - cssplaceholder = f.read() - return cssplaceholder + cssplaceholder = "" + publicthemefolder = os.path.join( + "themes/publicthemes", distribusi.distribusiname + ) + for filename in os.listdir(publicthemefolder): + if filename.endswith(".css"): + cssfile = os.path.join(publicthemefolder, filename) + with open(cssfile) as f: + cssplaceholder = f.read() + return cssplaceholder diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/themeselector.py index 67237de..96b2d8a 100644 --- a/verse/distribusikan/themeselector.py +++ b/verse/distribusikan/themeselector.py @@ -13,55 +13,55 @@ from statuspengguna.helper import UserHelper def ThemeSelector(): - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - current_distribusi = UserHelper.current_distribusi() - if themeform.validate_on_submit(): - copycssfile = os.path.join( - "themes", - f"{themeform.theme.data}.css", - ) - MoveCssToUserFolder(current_distribusi, copycssfile) - if publicthemeform.validate_on_submit(): - copycssfile = os.path.join( - "themes/publicthemes/", - f"{publicthemeform.publicthemes.data}.css", - ) - MoveCssToUserFolder(current_distribusi, copycssfile) - return RenderDistribusiTemplate( - themeform, publicthemeform, current_distribusi - ) + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + current_distribusi = UserHelper.current_distribusi() + if themeform.validate_on_submit(): + copycssfile = os.path.join( + "themes", + f"{themeform.theme.data}.css", + ) + MoveCssToUserFolder(current_distribusi, copycssfile) + if publicthemeform.validate_on_submit(): + copycssfile = os.path.join( + "themes/publicthemes/", + f"{publicthemeform.publicthemes.data}.css", + ) + MoveCssToUserFolder(current_distribusi, copycssfile) + return RenderDistribusiTemplate( + themeform, publicthemeform, current_distribusi + ) def MoveCssToUserFolder(current_distribusi, copycssfile): - newcssfolder = os.path.join("themes/userthemes", current_distribusi) - if not os.path.exists(newcssfolder): - os.mkdir(newcssfolder) - shutil.copy(copycssfile, newcssfolder) + newcssfolder = os.path.join("themes/userthemes", current_distribusi) + if not os.path.exists(newcssfolder): + os.mkdir(newcssfolder) + shutil.copy(copycssfile, newcssfolder) def RenderDistribusiTemplate(themeform, publicthemeform, current_distribusi): - uploadform = UploadForm() - distribusiform = DistribusiForm() - selectorform = SelectorForm() + uploadform = UploadForm() + distribusiform = DistribusiForm() + selectorform = SelectorForm() - files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - selectorvisible = False - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + selectorvisible = False + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py index 9ba4bae..83110b5 100644 --- a/verse/distribusikan/upload.py +++ b/verse/distribusikan/upload.py @@ -4,11 +4,11 @@ import shutil from flask import flash from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -20,76 +20,76 @@ from statuspengguna.helper import UserHelper def UploadNewDistribusi(uploadfolder): - uploadform = UploadForm() - if uploadform.validate_on_submit(): - user = User.query.filter_by(email=current_user.email).first() - try: - newdistribusi = Distribusis( - distribusiname=uploadform.sitename.data, - userid=user.id, - category=uploadform.category.data, - year=uploadform.year.data, - tags=uploadform.tags.data, - ) - user.currentdistribusi = uploadform.sitename.data - db.session.add(newdistribusi) - db.session.commit() - except IntegrityError: - db.session.rollback() - uploadform.sitename.errors.append( - "distribusi name already exists!" - ) - flash("distribusi name already exists!", "warning") - return uploadform - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - uploadform.sitename.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - return uploadform - SelectCurrentDistribusi(newdistribusi.distribusiname) - zipfilename = "{}.zip".format(newdistribusi.distribusiname) - zipfile = uploadform.zipfile.data - zipfile.save(os.path.join(uploadfolder, zipfilename)) + uploadform = UploadForm() + if uploadform.validate_on_submit(): + user = User.query.filter_by(email=current_user.email).first() + try: + newdistribusi = Distribusis( + distribusiname=uploadform.sitename.data, + userid=user.id, + category=uploadform.category.data, + year=uploadform.year.data, + tags=uploadform.tags.data, + ) + user.currentdistribusi = uploadform.sitename.data + db.session.add(newdistribusi) + db.session.commit() + except IntegrityError: + db.session.rollback() + uploadform.sitename.errors.append( + "distribusi name already exists!" + ) + flash("distribusi name already exists!", "warning") + return uploadform + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + uploadform.sitename.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + return uploadform + SelectCurrentDistribusi(newdistribusi.distribusiname) + zipfilename = "{}.zip".format(newdistribusi.distribusiname) + zipfile = uploadform.zipfile.data + zipfile.save(os.path.join(uploadfolder, zipfilename)) - newuserfolder = os.path.join("stash", newdistribusi.distribusiname) - if not os.path.exists(newuserfolder): - os.mkdir(newuserfolder) + newuserfolder = os.path.join("stash", newdistribusi.distribusiname) + if not os.path.exists(newuserfolder): + os.mkdir(newuserfolder) - copyzipfile = os.path.join(uploadfolder, zipfilename) - shutil.copy(copyzipfile, newuserfolder) - os.remove(os.path.join(uploadfolder, zipfilename)) + copyzipfile = os.path.join(uploadfolder, zipfilename) + shutil.copy(copyzipfile, newuserfolder) + os.remove(os.path.join(uploadfolder, zipfilename)) - return uploadform + return uploadform def UploadUpdatedFiles(uploadfolder): - uploadform = UploadForm() - if uploadform.validate_on_submit(): - try: - current_distribusi = UserHelper.current_distribusi() - distribusi = Distribusis.query.filter_by( - distribusiname=current_distribusi - ).first() - distribusi.category = uploadform.category.data - distribusi.year = uploadform.year.data - distribusi.tags = uploadform.tags.data - distribusi.visible = False - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - uploadform.sitename.errors.append("Something went wrong!") + uploadform = UploadForm() + if uploadform.validate_on_submit(): + try: + current_distribusi = UserHelper.current_distribusi() + distribusi = Distribusis.query.filter_by( + distribusiname=current_distribusi + ).first() + distribusi.category = uploadform.category.data + distribusi.year = uploadform.year.data + distribusi.tags = uploadform.tags.data + distribusi.visible = False + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + uploadform.sitename.errors.append("Something went wrong!") - zipfilename = "{}.zip".format(distribusi.distribusiname) - zipfile = uploadform.zipfile.data - zipfile.save(os.path.join(uploadfolder, zipfilename)) + zipfilename = "{}.zip".format(distribusi.distribusiname) + zipfile = uploadform.zipfile.data + zipfile.save(os.path.join(uploadfolder, zipfilename)) - newuserfolder = os.path.join("stash", distribusi.distribusiname) - if os.path.exists(newuserfolder): - shutil.rmtree(newuserfolder) - os.mkdir(newuserfolder) + newuserfolder = os.path.join("stash", distribusi.distribusiname) + if os.path.exists(newuserfolder): + shutil.rmtree(newuserfolder) + os.mkdir(newuserfolder) - copyzipfile = os.path.join(uploadfolder, zipfilename) - shutil.copy(copyzipfile, newuserfolder) - os.remove(os.path.join(uploadfolder, zipfilename)) + copyzipfile = os.path.join(uploadfolder, zipfilename) + shutil.copy(copyzipfile, newuserfolder) + os.remove(os.path.join(uploadfolder, zipfilename)) - return uploadform + return uploadform diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/uploadpage.py index 347518c..a8f2510 100644 --- a/verse/distribusikan/uploadpage.py +++ b/verse/distribusikan/uploadpage.py @@ -14,37 +14,37 @@ from statuspengguna.helper import UserHelper def UploadPage(): - "render upload page section of distribusi workflow" - uploadfolder = APP.config["UPLOAD_FOLDER"] - distribusiform = DistribusiForm() - themeform = ThemeForm() - publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() - selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() - selectorvisible = SelectorVisible() + "render upload page section of distribusi workflow" + uploadfolder = APP.config["UPLOAD_FOLDER"] + distribusiform = DistribusiForm() + themeform = ThemeForm() + publicthemeform = PublicThemeForm() + publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + selectorform = SelectorForm() + selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorvisible = SelectorVisible() - current_distribusi = UserHelper.current_distribusi() - if current_distribusi == "new" or UserHelper.has_distribusi() is False: - uploadform = UploadNewDistribusi(uploadfolder) - else: - uploadform = UploadUpdatedFiles(uploadfolder) + current_distribusi = UserHelper.current_distribusi() + if current_distribusi == "new" or UserHelper.has_distribusi() is False: + uploadform = UploadNewDistribusi(uploadfolder) + else: + uploadform = UploadUpdatedFiles(uploadfolder) - files_uploaded = UserHelper.is_zip_uploaded(uploadform.sitename.data) - distribusi_live = UserHelper.is_distribusi_live(current_distribusi) - css_selected = UserHelper.is_css_selected(current_distribusi) - limit_reached = UserHelper.distribusi_limit_reached() - template = render_template( - "distribusi.html", - uploadform=uploadform, - distribusiform=distribusiform, - themeform=themeform, - publicthemeform=publicthemeform, - selectorform=selectorform, - files_uploaded=files_uploaded, - distribusi_live=distribusi_live, - css_selected=css_selected, - selectorvisible=selectorvisible, - limit_reached=limit_reached, - ) - return template + files_uploaded = UserHelper.is_zip_uploaded(uploadform.sitename.data) + distribusi_live = UserHelper.is_distribusi_live(current_distribusi) + css_selected = UserHelper.is_css_selected(current_distribusi) + limit_reached = UserHelper.distribusi_limit_reached() + template = render_template( + "distribusi.html", + uploadform=uploadform, + distribusiform=distribusiform, + themeform=themeform, + publicthemeform=publicthemeform, + selectorform=selectorform, + files_uploaded=files_uploaded, + distribusi_live=distribusi_live, + css_selected=css_selected, + selectorvisible=selectorvisible, + limit_reached=limit_reached, + ) + return template diff --git a/verse/file_crawler.py b/verse/file_crawler.py index d378f85..ff57d14 100644 --- a/verse/file_crawler.py +++ b/verse/file_crawler.py @@ -6,68 +6,68 @@ from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from app import create_app, get_app, db from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) MIME_TYPE = magic.Magic(mime=True) def _distribusi_file_with_type(distribusi, full_path): - mime = MIME_TYPE.from_file(full_path) - type_, subtype = mime.split("/") - if type_ in FILE_TYPES: - _add_distribusi_file_to_db(distribusi, full_path, type_) + mime = MIME_TYPE.from_file(full_path) + type_, subtype = mime.split("/") + if type_ in FILE_TYPES: + _add_distribusi_file_to_db(distribusi, full_path, type_) def _get_distribusi_from_path(path): - distribusi = Distribusis.query.filter_by(distribusiname=path).first() - return distribusi + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + return distribusi def _add_distribusi_file_to_db(distribusi, full_path, type): - app = get_app() - print(f"adding file to database: {full_path} type: {type}") - try: - new_distribusi_file = DistribusiFiles( - path=full_path, - type=type, - distribusi=distribusi.id, - ) - db.session.add(new_distribusi_file) - db.session.commit() - return - except InvalidRequestError: - db.session.rollback() - app.logger.error("Something went wrong!") - except IntegrityError: - db.session.rollback() - app.logger.error("File %s already exists!", full_path) - except DataError: - db.session.rollback() - app.logger.error("%s Invalid Entry", full_path) - except InterfaceError: - db.session.rollback() - app.logger.error("Error connecting to the database") - except DatabaseError: - db.session.rollback() - app.logger.error("Error connecting to the database") + app = get_app() + print(f"adding file to database: {full_path} type: {type}") + try: + new_distribusi_file = DistribusiFiles( + path=full_path, + type=type, + distribusi=distribusi.id, + ) + db.session.add(new_distribusi_file) + db.session.commit() + return + except InvalidRequestError: + db.session.rollback() + app.logger.error("Something went wrong!") + except IntegrityError: + db.session.rollback() + app.logger.error("File %s already exists!", full_path) + except DataError: + db.session.rollback() + app.logger.error("%s Invalid Entry", full_path) + except InterfaceError: + db.session.rollback() + app.logger.error("Error connecting to the database") + except DatabaseError: + db.session.rollback() + app.logger.error("Error connecting to the database") def add_distribusi_files(path): - app = create_app() - with app.app_context(): - distribusi = _get_distribusi_from_path(path) - path = os.path.join("stash", path) - for root, dirs, files in os.walk(path, topdown=True): - files = list(filter(lambda f: not f.startswith("."), files)) - files = list(filter(lambda f: not f.endswith(".html"), files)) - for file in files: - full_path = os.path.join(root, file) - _distribusi_file_with_type(distribusi, full_path) + app = create_app() + with app.app_context(): + distribusi = _get_distribusi_from_path(path) + path = os.path.join("stash", path) + for root, dirs, files in os.walk(path, topdown=True): + files = list(filter(lambda f: not f.startswith("."), files)) + files = list(filter(lambda f: not f.endswith(".html"), files)) + for file in files: + full_path = os.path.join(root, file) + _distribusi_file_with_type(distribusi, full_path) -add_distribusi_files("2018-02-16-Extratonality") +add_distribusi_files("2018-12-WttF-Mastodon-and-the-Fediverse") diff --git a/verse/forms/admindistribusiform.py b/verse/forms/admindistribusiform.py index 38daf8f..f00f3db 100644 --- a/verse/forms/admindistribusiform.py +++ b/verse/forms/admindistribusiform.py @@ -5,19 +5,19 @@ from wtforms import BooleanField, SubmitField class AdminDistribusiForm(FlaskForm): - """Admin Distribusi form.""" + """Admin Distribusi form.""" - delete = SubmitField("Delete") + delete = SubmitField("Delete") - def distribusi_list_form_builder(distribusis): - class DistribusiListForm(AdminDistribusiForm): - pass + def distribusi_list_form_builder(distribusis): + class DistribusiListForm(AdminDistribusiForm): + pass - for i, distribusi in enumerate(distribusis): - setattr( - DistribusiListForm, - f"distribusi_{i}", - BooleanField(label=distribusi.distribusiname), - ) + for i, distribusi in enumerate(distribusis): + setattr( + DistribusiListForm, + f"distribusi_{i}", + BooleanField(label=distribusi.distribusiname), + ) - return DistribusiListForm() + return DistribusiListForm() diff --git a/verse/forms/adminuserform.py b/verse/forms/adminuserform.py index 93e2d25..aeda2e4 100644 --- a/verse/forms/adminuserform.py +++ b/verse/forms/adminuserform.py @@ -5,19 +5,19 @@ from wtforms import BooleanField, SubmitField class AdminUserForm(FlaskForm): - """Admin Userform form.""" + """Admin Userform form.""" - def user_list_form_builder(users): - class UserListForm(AdminUserForm): - pass + def user_list_form_builder(users): + class UserListForm(AdminUserForm): + pass - for i, user in enumerate(users): - setattr( - UserListForm, - f"user_{i}", - BooleanField(label=user.email), - ) + for i, user in enumerate(users): + setattr( + UserListForm, + f"user_{i}", + BooleanField(label=user.email), + ) - return UserListForm() + return UserListForm() - delete = SubmitField("Delete") + delete = SubmitField("Delete") diff --git a/verse/forms/distribusiform.py b/verse/forms/distribusiform.py index bd0fb71..6373162 100644 --- a/verse/forms/distribusiform.py +++ b/verse/forms/distribusiform.py @@ -3,6 +3,6 @@ from wtforms import SubmitField class DistribusiForm(FlaskForm): - """Distribusi class to launch your distribusi website""" + """Distribusi class to launch your distribusi website""" - submit = SubmitField("Distribusi!") + submit = SubmitField("Distribusi!") diff --git a/verse/forms/editorform.py b/verse/forms/editorform.py index 1db3e0d..284082d 100644 --- a/verse/forms/editorform.py +++ b/verse/forms/editorform.py @@ -3,33 +3,33 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField, FileSize from wtforms import ( - BooleanField, - StringField, - SubmitField, - TextAreaField, - validators, + BooleanField, + StringField, + SubmitField, + TextAreaField, + validators, ) from wtforms.validators import Length class EditorForm(FlaskForm): - """Css editor form class.""" + """Css editor form class.""" - cssname = StringField( - "fill in a name for your css style:", - validators=[validators.InputRequired(), Length(5, 200)], - ) - cssfile = FileField( - "(Optional) upload your own css file:", - validators=[ - FileAllowed(["css"], "css files only!"), - FileSize( - max_size=10485760, - message="css file size must be smaller than 10MB", - ), - ], - ) - css = TextAreaField() - public = BooleanField("Make your CSS public so others can use it") + cssname = StringField( + "fill in a name for your css style:", + validators=[validators.InputRequired(), Length(5, 200)], + ) + cssfile = FileField( + "(Optional) upload your own css file:", + validators=[ + FileAllowed(["css"], "css files only!"), + FileSize( + max_size=10485760, + message="css file size must be smaller than 10MB", + ), + ], + ) + css = TextAreaField() + public = BooleanField("Make your CSS public so others can use it") - submit = SubmitField("Save") + submit = SubmitField("Save") diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py index 9e416bb..385327d 100644 --- a/verse/forms/forgotpasswordform.py +++ b/verse/forms/forgotpasswordform.py @@ -6,10 +6,10 @@ from wtforms.validators import Email, Length class ForgotPasswordForm(FlaskForm): - """Forgotten password distribusiverse form class.""" + """Forgotten password distribusiverse form class.""" - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - submit = SubmitField("Send email") + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + submit = SubmitField("Send email") diff --git a/verse/forms/loginform.py b/verse/forms/loginform.py index 61830a2..b446850 100644 --- a/verse/forms/loginform.py +++ b/verse/forms/loginform.py @@ -6,13 +6,13 @@ from wtforms.validators import Email, Length class LoginForm(FlaskForm): - """Login distribusiverse form class.""" + """Login distribusiverse form class.""" - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - password = PasswordField( - "Password:", validators=[validators.InputRequired()] - ) - submit = SubmitField("Sign In") + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + password = PasswordField( + "Password:", validators=[validators.InputRequired()] + ) + submit = SubmitField("Sign In") diff --git a/verse/forms/publicthemeform.py b/verse/forms/publicthemeform.py index 46a2505..103fbeb 100644 --- a/verse/forms/publicthemeform.py +++ b/verse/forms/publicthemeform.py @@ -5,10 +5,10 @@ from wtforms import RadioField, SubmitField class PublicThemeForm(FlaskForm): - """PublicTheme selection form.""" + """PublicTheme selection form.""" - publicthemes = RadioField( - "Public themes from other distribusi-verse users:" - ) + publicthemes = RadioField( + "Public themes from other distribusi-verse users:" + ) - save = SubmitField("Save") + save = SubmitField("Save") diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py index b300293..89c42d6 100644 --- a/verse/forms/registerform.py +++ b/verse/forms/registerform.py @@ -6,33 +6,33 @@ from wtforms.validators import Email, EqualTo, Length class RegisterForm(FlaskForm): - """Register for distribusi-verse form class""" + """Register for distribusi-verse form class""" - username = StringField( - "Username:", - validators=[validators.InputRequired(), Length(3, 150)], - ) + username = StringField( + "Username:", + validators=[validators.InputRequired(), Length(3, 150)], + ) - email = StringField( - "Email address:", - validators=[ - validators.InputRequired(), - Email(), - Length(6, 128), - ], - ) + email = StringField( + "Email address:", + validators=[ + validators.InputRequired(), + Email(), + Length(6, 128), + ], + ) - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Register to Distribusi-verse") + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Register to Distribusi-verse") diff --git a/verse/forms/resetpasswordform.py b/verse/forms/resetpasswordform.py index a3cbe34..481cb02 100644 --- a/verse/forms/resetpasswordform.py +++ b/verse/forms/resetpasswordform.py @@ -6,18 +6,18 @@ from wtforms.validators import EqualTo, Length class ResetPasswordForm(FlaskForm): - """ResetPassword for distribusi-verse form class""" + """ResetPassword for distribusi-verse form class""" - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Reset your password") + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Reset your password") diff --git a/verse/forms/selectorform.py b/verse/forms/selectorform.py index ecdba27..f2f9530 100644 --- a/verse/forms/selectorform.py +++ b/verse/forms/selectorform.py @@ -3,12 +3,12 @@ from wtforms import SelectField, SubmitField class SelectorForm(FlaskForm): - distribusis = SelectField("Your existing distribusi:") + distribusis = SelectField("Your existing distribusi:") - new = SubmitField("new") + new = SubmitField("new") - update = SubmitField("update") + update = SubmitField("update") - describe = SubmitField("describe") + describe = SubmitField("describe") - delete = SubmitField("delete") + delete = SubmitField("delete") diff --git a/verse/forms/themeform.py b/verse/forms/themeform.py index ca2b7bb..a1c3e02 100644 --- a/verse/forms/themeform.py +++ b/verse/forms/themeform.py @@ -5,15 +5,15 @@ from wtforms import RadioField, SubmitField class ThemeForm(FlaskForm): - """Basic theme selection form.""" + """Basic theme selection form.""" - theme = RadioField( - "Select your theme:", - choices=[ - ("hacking", "Hackers (black background, green text)"), - ("peachsunset", "Peach sunset (single column)"), - ("masonry", "Masonry (white background, grid layout)"), - ], - ) + theme = RadioField( + "Select your theme:", + choices=[ + ("hacking", "Hackers (black background, green text)"), + ("peachsunset", "Peach sunset (single column)"), + ("masonry", "Masonry (white background, grid layout)"), + ], + ) - save = SubmitField("Save") + save = SubmitField("Save") diff --git a/verse/forms/uploadform.py b/verse/forms/uploadform.py index 3f26824..90dcd70 100644 --- a/verse/forms/uploadform.py +++ b/verse/forms/uploadform.py @@ -1,85 +1,85 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField, FileRequired, FileSize from wtforms import ( - SelectField, - StringField, - SubmitField, - validators, + SelectField, + StringField, + SubmitField, + validators, ) from wtforms.validators import ( - DataRequired, - Length, - ValidationError, + DataRequired, + Length, + ValidationError, ) from app import settings class UploadForm(FlaskForm): - """File upload class for a new site in distribusi-verse""" + """File upload class for a new site in distribusi-verse""" - def distribusiname(form, field): - if field.data.lower() == "new": - raise ValidationError("Name has to be unique and not just new.") + def distribusiname(form, field): + if field.data.lower() == "new": + raise ValidationError("Name has to be unique and not just new.") - def category_choices(): - APP = settings() - config_categories = APP.config["categories"] - categories = [] - for config_category in config_categories: - categories.append((config_category, config_category)) - return categories + def category_choices(): + APP = settings() + config_categories = APP.config["categories"] + categories = [] + for config_category in config_categories: + categories.append((config_category, config_category)) + return categories - def year_choices(): - APP = settings() - start_time = APP.config["start_time"] - end_time = APP.config["end_time"] - year_range = range(start_time.year, end_time.year, 1) - year_choices = [] - for year in year_range: - year_choices.append((str(year), str(year))) - return year_choices + def year_choices(): + APP = settings() + start_time = APP.config["start_time"] + end_time = APP.config["end_time"] + year_range = range(start_time.year, end_time.year, 1) + year_choices = [] + for year in year_range: + year_choices.append((str(year), str(year))) + return year_choices - sitename = StringField( - "Name of your archive section:", - validators=[ - validators.InputRequired(), - Length(2, 100), - distribusiname, - ], - ) - year = SelectField( - "Year:", - validate_choice=True, - coerce=str, - choices=year_choices, - option_widget=None, - validators=[DataRequired()], - ) - category = SelectField( - "Category:", - validate_choice=True, - coerce=str, - choices=category_choices, - option_widget=None, - validators=[DataRequired()], - ) + sitename = StringField( + "Name of your archive section:", + validators=[ + validators.InputRequired(), + Length(2, 100), + distribusiname, + ], + ) + year = SelectField( + "Year:", + validate_choice=True, + coerce=str, + choices=year_choices, + option_widget=None, + validators=[DataRequired()], + ) + category = SelectField( + "Category:", + validate_choice=True, + coerce=str, + choices=category_choices, + option_widget=None, + validators=[DataRequired()], + ) - tags = StringField( - "Add search tags, seperated by commas. No need for the '#' sign:", - validators=[validators.InputRequired(), Length(3, 500)], - ) + tags = StringField( + "Add search tags, seperated by commas. No need for the '#' sign:", + validators=[validators.InputRequired(), Length(3, 500)], + ) - zipfile = FileField( - "Upload your zip file with content here:", - validators=[ - FileAllowed(["zip"], "Zip archives only!"), - FileRequired(), - FileSize( - max_size=1073741824, - message="Zipfile size must be smaller than 100MB", - ), - ], - ) + zipfile = FileField( + "Upload your zip file with content here:", + validators=[ + FileAllowed(["zip"], "Zip archives only!"), + FileRequired(), + FileSize( + max_size=1073741824, + message="Zipfile size must be smaller than 100MB", + ), + ], + ) - submit = SubmitField("Upload") + submit = SubmitField("Upload") diff --git a/verse/migrations/env.py b/verse/migrations/env.py index 85debe8..68a0091 100644 --- a/verse/migrations/env.py +++ b/verse/migrations/env.py @@ -21,10 +21,10 @@ logger = logging.getLogger("alembic.env") # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - "sqlalchemy.url", - str(current_app.extensions["migrate"].db.get_engine().url).replace( - "%", "%%" - ), + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.get_engine().url).replace( + "%", "%%" + ), ) target_metadata = current_app.extensions["migrate"].db.metadata @@ -35,59 +35,59 @@ target_metadata = current_app.extensions["migrate"].db.metadata def run_migrations_offline(): - """Run migrations in 'offline' mode. + """Run migrations in 'offline' mode. - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. - Calls to context.execute() here emit the given string to the - script output. + Calls to context.execute() here emit the given string to the + script output. - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=target_metadata, literal_binds=True - ) + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True + ) - with context.begin_transaction(): - context.run_migrations() + with context.begin_transaction(): + context.run_migrations() def run_migrations_online(): - """Run migrations in 'online' mode. + """Run migrations in 'online' mode. - In this scenario we need to create an Engine - and associate a connection with the context. + In this scenario we need to create an Engine + and associate a connection with the context. - """ + """ - # this callback is used to prevent an auto-migration from being generated - # when there are no changes to the schema - # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html - def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, "autogenerate", False): - script = directives[0] - if script.upgrade_ops.is_empty(): - directives[:] = [] - logger.info("No changes in schema detected.") + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, "autogenerate", False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info("No changes in schema detected.") - connectable = current_app.extensions["migrate"].db.get_engine() + connectable = current_app.extensions["migrate"].db.get_engine() - with connectable.connect() as connection: - context.configure( - connection=connection, - target_metadata=target_metadata, - process_revision_directives=process_revision_directives, - **current_app.extensions["migrate"].configure_args, - ) + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + process_revision_directives=process_revision_directives, + **current_app.extensions["migrate"].configure_args, + ) - with context.begin_transaction(): - context.run_migrations() + with context.begin_transaction(): + context.run_migrations() if context.is_offline_mode(): - run_migrations_offline() + run_migrations_offline() else: - run_migrations_online() + run_migrations_online() diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index cfb6216..23003b1 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -2,17 +2,17 @@ from app import db class DistribusiFiles(db.Model): - """Distribusi file model class for a single file in a distribusi""" + """Distribusi file model class for a single file in a distribusi""" - __tablename__ = "distribusi_files" + __tablename__ = "distribusi_files" - id = db.Column(db.Integer, primary_key=True) - type = db.Column(db.String(100), nullable=True, unique=False) - distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) - path = db.Column(db.String(4096), nullable=True, unique=False) - alttext = db.Column(db.String(255), nullable=True, unique=False) - tags = db.Column(db.String(500), nullable=True, unique=False) - description = db.Column(db.String(4096), nullable=True, unique=False) + id = db.Column(db.Integer, primary_key=True) + type = db.Column(db.String(100), nullable=True, unique=False) + distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) + path = db.Column(db.String(4096), nullable=True, unique=False) + alttext = db.Column(db.String(255), nullable=True, unique=False) + tags = db.Column(db.String(500), nullable=True, unique=False) + description = db.Column(db.String(4096), nullable=True, unique=False) - def __repr__(self): - return "" % self.path + def __repr__(self): + return "" % self.path diff --git a/verse/models/distribusi_model.py b/verse/models/distribusi_model.py index 4d23545..d8f114e 100644 --- a/verse/models/distribusi_model.py +++ b/verse/models/distribusi_model.py @@ -2,18 +2,18 @@ from app import db class Distribusis(db.Model): - """distribusi model class for a single distribusi in distribusi-verse""" + """distribusi model class for a single distribusi in distribusi-verse""" - __tablename__ = "distribusis" + __tablename__ = "distribusis" - id = db.Column(db.Integer, primary_key=True) - distribusiname = db.Column(db.String(300), nullable=False, unique=True) - userid = db.Column(db.Integer, db.ForeignKey("users.id")) - category = db.Column(db.String(500), nullable=True, unique=False) - year = db.Column(db.String(9), nullable=True, unique=False) - tags = db.Column(db.String(500), nullable=True, unique=False) - publictheme = db.Column(db.String(300), unique=True, nullable=True) - visible = db.Column(db.Boolean, default=False) + id = db.Column(db.Integer, primary_key=True) + distribusiname = db.Column(db.String(300), nullable=False, unique=True) + userid = db.Column(db.Integer, db.ForeignKey("users.id")) + category = db.Column(db.String(500), nullable=True, unique=False) + year = db.Column(db.String(9), nullable=True, unique=False) + tags = db.Column(db.String(500), nullable=True, unique=False) + publictheme = db.Column(db.String(300), unique=True, nullable=True) + visible = db.Column(db.Boolean, default=False) - def __repr__(self): - return "" % self.distribusiname + def __repr__(self): + return "" % self.distribusiname diff --git a/verse/models/user_model.py b/verse/models/user_model.py index 0487d94..9522024 100644 --- a/verse/models/user_model.py +++ b/verse/models/user_model.py @@ -4,18 +4,18 @@ from app import db class User(UserMixin, db.Model): - """User model class for a user in distribusi-verse""" + """User model class for a user in distribusi-verse""" - __tablename__ = "users" + __tablename__ = "users" - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(150), unique=True, nullable=False) - email = db.Column(db.String(150), unique=True, nullable=False) - password = db.Column(db.String(300), nullable=False, unique=False) - currentdistribusi = db.Column(db.String(300), nullable=True, unique=False) - resethash = db.Column(db.String(300), nullable=True, unique=True) - resettime = db.Column(db.DateTime) - admin = db.Column(db.Boolean, default=False) + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + email = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(300), nullable=False, unique=False) + currentdistribusi = db.Column(db.String(300), nullable=True, unique=False) + resethash = db.Column(db.String(300), nullable=True, unique=True) + resettime = db.Column(db.DateTime) + admin = db.Column(db.Boolean, default=False) - def __repr__(self): - return "" % self.email + def __repr__(self): + return "" % self.email diff --git a/verse/start.py b/verse/start.py index 5e9530c..728fabc 100644 --- a/verse/start.py +++ b/verse/start.py @@ -3,18 +3,18 @@ from datetime import timedelta from flask import ( - Blueprint, - redirect, - render_template, - send_from_directory, - session, - url_for, + Blueprint, + redirect, + render_template, + send_from_directory, + session, + url_for, ) from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError from adminpage import AdminPage -from app import db, create_app, login_manager +from app import create_app, login_manager, db from describer.describe_files import describer from distribusikan.distribusikan import distribusikan from distribusikan.distribusisinfo import DistribusisInfo @@ -29,7 +29,6 @@ from statuspengguna.registeruser import register_user APP = create_app() stash_page = Blueprint("stash_page", __name__, static_folder="stash") APP.register_blueprint(stash_page) - APP.register_blueprint(describer, url_prefix="/describer") APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") @@ -39,89 +38,90 @@ APP.register_blueprint(distribusikan) @APP.before_request def session_handler(): - session.permanent = True - APP.permanent_session_lifetime = timedelta(minutes=30) + session.permanent = True + APP.permanent_session_lifetime = timedelta(minutes=30) @APP.route("/") def index(): - UserHelper.reset_user_state() - uploadform = UploadForm() - distribusis = DistribusisInfo.visibledistribusis() - distribusisindex = {} - for distribusi in distribusis: - user = User.query.filter_by(id=distribusi.userid).first() - singledistribusi = { - "username": user.username, - "publictheme": distribusi.publictheme, - "category": distribusi.category, - "year": distribusi.year, - "tags": distribusi.tags.split(","), - } - distribusisindex[distribusi.distribusiname] = singledistribusi - years = uploadform.year.choices - categories = uploadform.category.choices - adminuser = is_adminuser() - template = render_template( - "base/index.html", - distribusisindex=distribusisindex, - years=years, - categories=categories, - adminuser=adminuser, - ) - return template + UserHelper.reset_user_state() + uploadform = UploadForm() + distribusis = DistribusisInfo.visibledistribusis() + distribusisindex = {} + for distribusi in distribusis: + user = User.query.filter_by(id=distribusi.userid).first() + singledistribusi = { + "username": user.username, + "publictheme": distribusi.publictheme, + "category": distribusi.category, + "year": distribusi.year, + "tags": distribusi.tags.split(","), + } + distribusisindex[distribusi.distribusiname] = singledistribusi + + years = uploadform.year.choices + categories = uploadform.category.choices + adminuser = is_adminuser() + template = render_template( + "base/index.html", + distribusisindex=distribusisindex, + years=years, + categories=categories, + adminuser=adminuser, + ) + return template @APP.route("/help") def help(): - return render_template("base/help.html") + return render_template("base/help.html") @APP.route("/publicthemes/") def publicthemes(path): - distribusi = Distribusis.query.filter_by(distribusiname=path).first() - publicthemefolder = f"publicthemes/{distribusi.distribusiname}/" - cssfile = f"{publicthemefolder}/{distribusi.publictheme}.css" - return send_from_directory("themes", cssfile, as_attachment=True) + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + publicthemefolder = f"publicthemes/{distribusi.distribusiname}/" + cssfile = f"{publicthemefolder}/{distribusi.publictheme}.css" + return send_from_directory("themes", cssfile, as_attachment=True) @APP.route("/stash") def shortstashurl(): - return redirect(url_for("index")) + return redirect(url_for("index")) @APP.route("/admin", methods=["GET", "POST"]) @login_required def admin(): - if not is_adminuser(): - return redirect(url_for("index")) - return AdminPage() + if not is_adminuser(): + return redirect(url_for("index")) + return AdminPage() @APP.route("/logout") @login_required def logout(): - logout_user() - return redirect(url_for("index")) + logout_user() + return redirect(url_for("index")) @APP.errorhandler(CSRFError) def handle_csrf_error(e): - return render_template("csrf_error.html", reason=e.description), 400 + return render_template("csrf_error.html", reason=e.description), 400 @login_manager.user_loader def load_user(user_id): - return db.session.get(User, int(user_id)) + return db.session.get(User, int(user_id)) def is_adminuser(): - if not current_user.is_authenticated: - return False - user = User.query.filter_by(email=current_user.email).first() - return user.admin + if not current_user.is_authenticated: + return False + user = User.query.filter_by(email=current_user.email).first() + return user.admin if __name__ == "__main__": - APP.debug = True - APP.run(port=5000) + APP.debug = True + APP.run(port=5000) diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py index 51b0ae0..dbb8049 100644 --- a/verse/statuspengguna/forgotpassword.py +++ b/verse/statuspengguna/forgotpassword.py @@ -4,10 +4,10 @@ from uuid import uuid1 from flask import Blueprint, render_template from flask_mail import Mail, Message from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db, get_app @@ -16,57 +16,57 @@ from models.user_model import User mail = Mail(get_app()) forgot_password = Blueprint( - "forgotpassword", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "forgotpassword", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @forgot_password.route("/", methods=["GET", "POST"]) def forgotpassword(): - return ForgotPassword(mail) + return ForgotPassword(mail) def ForgotPassword(mail): - forgotpasswordform = ForgotPasswordForm() - if forgotpasswordform.validate_on_submit(): - user = User.query.filter_by( - email=forgotpasswordform.email.data - ).first() - if user is not None: - resethash = AddResetPasswordHash(user, forgotpasswordform) - ResetPassWordMessage(user, resethash, mail) - forgotpasswordform.email.errors.append( - f"""If {forgotpasswordform.email.data} exists, an email is send with + forgotpasswordform = ForgotPasswordForm() + if forgotpasswordform.validate_on_submit(): + user = User.query.filter_by( + email=forgotpasswordform.email.data + ).first() + if user is not None: + resethash = AddResetPasswordHash(user, forgotpasswordform) + ResetPassWordMessage(user, resethash, mail) + forgotpasswordform.email.errors.append( + f"""If {forgotpasswordform.email.data} exists, an email is send with a password reset link. (If your inbox doesn't contain any new mail, please check your spam folder.)""" - ) - return render_template( - "forgotpassword.html", forgotpasswordform=forgotpasswordform - ) + ) + return render_template( + "forgotpassword.html", forgotpasswordform=forgotpasswordform + ) def AddResetPasswordHash(user, forgotpasswordform): - resethash = uuid1().hex - try: - user.resettime = datetime.now() - user.resethash = resethash - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - forgotpasswordform.email.errors.append("Something went wrong!") - db.session.rollback() - return resethash + resethash = uuid1().hex + try: + user.resettime = datetime.now() + user.resethash = resethash + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + forgotpasswordform.email.errors.append("Something went wrong!") + db.session.rollback() + return resethash def ResetPassWordMessage(user, resethash, mail): - msg = Message( - "Distribusiverse Forgotten Password ", - sender=("Distribusiverse mailer", "test@this.com"), - recipients=[user.email], - ) - msg.html = f"""{user.username} has requested a password reset for + msg = Message( + "Distribusiverse Forgotten Password ", + sender=("Distribusiverse mailer", "test@this.com"), + recipients=[user.email], + ) + msg.html = f"""{user.username} has requested a password reset for Distribusiverse.

Click here to reset your password.""" - mail.send(msg) + mail.send(msg) diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py index 9d01082..a8b26bd 100644 --- a/verse/statuspengguna/helper.py +++ b/verse/statuspengguna/helper.py @@ -3,10 +3,10 @@ import os from flask import flash from flask_login import current_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, ) from app import db @@ -16,68 +16,68 @@ from models.user_model import User class UserHelper: - def is_zip_uploaded(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - zipfilename = "{}.zip".format(distribusiname) - if os.path.exists(os.path.join(userfolder, zipfilename)): - print("folder with zipfile found, file uploaded") - return True - print("distribusi folder has no zipfile") - return False + def is_zip_uploaded(distribusiname): + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + zipfilename = "{}.zip".format(distribusiname) + if os.path.exists(os.path.join(userfolder, zipfilename)): + print("folder with zipfile found, file uploaded") + return True + print("distribusi folder has no zipfile") + return False - def is_distribusi_live(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - zipfilename = "{}.zip".format(distribusiname) - if os.path.exists(os.path.join(userfolder, zipfilename)): - print("folder with zipfile found, file uploaded") - return False - if len(os.listdir(userfolder)) > 0: - return True - print("distribusi folder is empty") - return False + def is_distribusi_live(distribusiname): + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + zipfilename = "{}.zip".format(distribusiname) + if os.path.exists(os.path.join(userfolder, zipfilename)): + print("folder with zipfile found, file uploaded") + return False + if len(os.listdir(userfolder)) > 0: + return True + print("distribusi folder is empty") + return False - def is_css_selected(distribusiname): - userfolder = os.path.join("themes/userthemes", distribusiname) - if os.path.exists(userfolder): - for file in os.listdir(userfolder): - if file.endswith(".css"): - return True - print("distribusi folder has no css file") - return False + def is_css_selected(distribusiname): + userfolder = os.path.join("themes/userthemes", distribusiname) + if os.path.exists(userfolder): + for file in os.listdir(userfolder): + if file.endswith(".css"): + return True + print("distribusi folder has no css file") + return False - def has_distribusi(): - user = User.query.filter_by(email=current_user.email).first() - distribusi = Distribusis.query.filter_by(userid=user.id).first() - if distribusi is None: - print("no distribusi found") - return False - return True + def has_distribusi(): + user = User.query.filter_by(email=current_user.email).first() + distribusi = Distribusis.query.filter_by(userid=user.id).first() + if distribusi is None: + print("no distribusi found") + return False + return True - def current_distribusi(): - user = User.query.filter_by(email=current_user.email).first() - if user.currentdistribusi is None: - return "None" - return user.currentdistribusi + def current_distribusi(): + user = User.query.filter_by(email=current_user.email).first() + if user.currentdistribusi is None: + return "None" + return user.currentdistribusi - def reset_user_state(): - """reset user state upon visiting index, so that distribusi workflow can - be done correctly""" - if not current_user.is_authenticated: - return - try: - user = User.query.filter_by(email=current_user.email).first() - user.currentdistribusi = None - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - flash("An error occured !", "danger") + def reset_user_state(): + """reset user state upon visiting index, so that distribusi workflow can + be done correctly""" + if not current_user.is_authenticated: + return + try: + user = User.query.filter_by(email=current_user.email).first() + user.currentdistribusi = None + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + flash("An error occured !", "danger") - def distribusi_limit_reached(): - user = User.query.filter_by(email=current_user.email).first() - distribusiamount = len(DistribusisInfo.getuserdistribusis(user.email)) - if distribusiamount > 19: - print("user already has 20 distribusis") - return True - return False + def distribusi_limit_reached(): + user = User.query.filter_by(email=current_user.email).first() + distribusiamount = len(DistribusisInfo.getuserdistribusis(user.email)) + if distribusiamount > 19: + print("user already has 20 distribusis") + return True + return False diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py index 69bbbee..6f18cde 100644 --- a/verse/statuspengguna/loginuser.py +++ b/verse/statuspengguna/loginuser.py @@ -1,11 +1,11 @@ from flask import ( - Blueprint, - abort, - flash, - redirect, - render_template, - request, - url_for, + Blueprint, + abort, + flash, + redirect, + render_template, + request, + url_for, ) from flask_bcrypt import check_password_hash from flask_login import login_user @@ -14,39 +14,39 @@ from forms.loginform import LoginForm from models.user_model import User login_section = Blueprint( - "login", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "login", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @login_section.route("/", methods=["GET", "POST"]) def login(): - return LoginUser() + return LoginUser() def LoginUser(): - loginform = LoginForm() - if loginform.validate_on_submit(): - try: - user = User.query.filter_by(email=loginform.email.data).first() - if user is None: - loginform.password.errors.append("Invalid email or password!") - return render_template("login.html", loginform=loginform) - if check_password_hash(user.password, loginform.password.data): - login_user(user) - flash("Logged in successfully.", "success") - next = request.args.get("next") - if next is not None and not is_safe_url(next): # noqa: F821 - print(next) - return abort(400) - print("index") - return redirect(next or url_for("index")) - else: - flash("Invalid email or password!", "danger") - loginform.password.errors.append("Invalid email or password!") - return render_template("login.html", loginform=loginform) - except Exception as e: - flash(e, "danger") - return render_template("login.html", loginform=loginform) + loginform = LoginForm() + if loginform.validate_on_submit(): + try: + user = User.query.filter_by(email=loginform.email.data).first() + if user is None: + loginform.password.errors.append("Invalid email or password!") + return render_template("login.html", loginform=loginform) + if check_password_hash(user.password, loginform.password.data): + login_user(user) + flash("Logged in successfully.", "success") + next = request.args.get("next") + if next is not None and not is_safe_url(next): # noqa: F821 + print(next) + return abort(400) + print("index") + return redirect(next or url_for("index")) + else: + flash("Invalid email or password!", "danger") + loginform.password.errors.append("Invalid email or password!") + return render_template("login.html", loginform=loginform) + except Exception as e: + flash(e, "danger") + return render_template("login.html", loginform=loginform) diff --git a/verse/statuspengguna/registeruser.py b/verse/statuspengguna/registeruser.py index ade624a..e97f1ee 100644 --- a/verse/statuspengguna/registeruser.py +++ b/verse/statuspengguna/registeruser.py @@ -2,11 +2,11 @@ from flask import Blueprint, flash, redirect, render_template, url_for from flask_bcrypt import generate_password_hash from flask_login import login_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from werkzeug.routing import BuildError @@ -15,64 +15,64 @@ from forms.registerform import RegisterForm from models.user_model import User register_user = Blueprint( - "register", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "register", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @register_user.route("/", methods=["GET", "POST"]) def register(): - return RegisterUser() + return RegisterUser() def RegisterUser(): - registerform = RegisterForm() - if registerform.validate_on_submit(): - try: - username = registerform.username.data - email = registerform.email.data - password = registerform.confirmpassword.data + registerform = RegisterForm() + if registerform.validate_on_submit(): + try: + username = registerform.username.data + email = registerform.email.data + password = registerform.confirmpassword.data - newuser = User( - username=username, - email=email, - password=generate_password_hash(password), - ) + newuser = User( + username=username, + email=email, + password=generate_password_hash(password), + ) - db.session.add(newuser) - db.session.commit() - flash("Account Succesfully created", "success") - login_user(newuser) - return redirect(url_for("index")) + db.session.add(newuser) + db.session.commit() + flash("Account Succesfully created", "success") + login_user(newuser) + return redirect(url_for("index")) - except InvalidRequestError: - db.session.rollback() - registerform.email.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - except IntegrityError: - db.session.rollback() - registerform.email.errors.append("User already exists!") - flash("User already exists!", "warning") - except DataError: - db.session.rollback() - registerform.email.errors.append("Invalid Entry") - flash("Invalid Entry", "warning") - except InterfaceError: - db.session.rollback() - registerform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except DatabaseError: - db.session.rollback() - registerform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except BuildError: - db.session.rollback() - registerform.email.errors.append("Unknown error occured!") - flash("An error occured !", "danger") - return render_template("register.html", registerform=registerform) + except InvalidRequestError: + db.session.rollback() + registerform.email.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except IntegrityError: + db.session.rollback() + registerform.email.errors.append("User already exists!") + flash("User already exists!", "warning") + except DataError: + db.session.rollback() + registerform.email.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + registerform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + registerform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except BuildError: + db.session.rollback() + registerform.email.errors.append("Unknown error occured!") + flash("An error occured !", "danger") + return render_template("register.html", registerform=registerform) diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py index e0da583..c0288ae 100644 --- a/verse/statuspengguna/resetpassword.py +++ b/verse/statuspengguna/resetpassword.py @@ -4,11 +4,11 @@ from flask import Blueprint, flash, redirect, render_template, url_for from flask_bcrypt import generate_password_hash from flask_login import login_user from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, ) from werkzeug.routing import BuildError @@ -17,74 +17,74 @@ from forms.resetpasswordform import ResetPasswordForm from models.user_model import User reset_password = Blueprint( - "reset_password", - __name__, - template_folder="templates/statuspengguna", - static_folder="static", + "reset_password", + __name__, + template_folder="templates/statuspengguna", + static_folder="static", ) @reset_password.route("/resetpassword/", methods=["GET", "POST"]) def resetpassword(path): - return ResetPassword(path) + return ResetPassword(path) def ResetPassword(path): - linkvalid = False - user = User.query.filter_by(resethash=path).first() - if user is None: - return redirect(url_for("index")) - timepassed = datetime.now() - user.resettime - if timepassed.days < 1: - linkvalid = True + linkvalid = False + user = User.query.filter_by(resethash=path).first() + if user is None: + return redirect(url_for("index")) + timepassed = datetime.now() - user.resettime + if timepassed.days < 1: + linkvalid = True - resetpasswordform = ResetPasswordForm() - if resetpasswordform.validate_on_submit(): - return ResetUserPasswordInDB(user, resetpasswordform) - return render_template( - "resetpassword.html", - resetpasswordform=resetpasswordform, - path=path, - linkvalid=linkvalid, - ) + resetpasswordform = ResetPasswordForm() + if resetpasswordform.validate_on_submit(): + return ResetUserPasswordInDB(user, resetpasswordform) + return render_template( + "resetpassword.html", + resetpasswordform=resetpasswordform, + path=path, + linkvalid=linkvalid, + ) def ResetUserPasswordInDB(user, resetpasswordform): - try: - newpassword = resetpasswordform.confirmpassword.data - user.password = generate_password_hash(newpassword) - user.resethash = None - user.resettime = None - db.session.commit() - flash("Password Succesfully updated", "success") - login_user(user) - return redirect(url_for("index")) + try: + newpassword = resetpasswordform.confirmpassword.data + user.password = generate_password_hash(newpassword) + user.resethash = None + user.resettime = None + db.session.commit() + flash("Password Succesfully updated", "success") + login_user(user) + return redirect(url_for("index")) - except InvalidRequestError: - db.session.rollback() - resetpasswordform.email.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - except IntegrityError: - db.session.rollback() - resetpasswordform.email.errors.append("User already exists!") - flash("User already exists!", "warning") - except DataError: - db.session.rollback() - resetpasswordform.email.errors.append("Invalid Entry") - flash("Invalid Entry", "warning") - except InterfaceError: - db.session.rollback() - resetpasswordform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except DatabaseError: - db.session.rollback() - resetpasswordform.email.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except BuildError: - db.session.rollback() - resetpasswordform.email.errors.append("Unknown error occured!") - flash("An error occured !", "danger") + except InvalidRequestError: + db.session.rollback() + resetpasswordform.email.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except IntegrityError: + db.session.rollback() + resetpasswordform.email.errors.append("User already exists!") + flash("User already exists!", "warning") + except DataError: + db.session.rollback() + resetpasswordform.email.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + resetpasswordform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + resetpasswordform.email.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except BuildError: + db.session.rollback() + resetpasswordform.email.errors.append("Unknown error occured!") + flash("An error occured !", "danger") -- 2.39.2 From 659acc902e077d92a77a31ac6a6a9a28bdec9a4d Mon Sep 17 00:00:00 2001 From: crunk Date: Tue, 28 May 2024 23:27:21 +0200 Subject: [PATCH 19/49] quick untested late night db adding function --- verse/describer/describe_files.py | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index b2c40d0..f980dfe 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -4,12 +4,22 @@ from flask import ( redirect, url_for, send_from_directory, + flash, ) from flask_login import current_user, login_required +from sqlalchemy.exc import ( + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, +) +from app import db from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from describer.forms.describe_files_form import DescribeFilesForm + describer = Blueprint( "describer", __name__, @@ -40,7 +50,7 @@ def describe_file(file_id): describe_form = DescribeFilesForm( distribusi_file.id, distribusi_file.path, distribusi_file.type ) - + save_described_file_to_db(describe_form, distribusi_file) distribusi = Distribusis.query.filter_by( id=distribusi_file.distribusi ).first() @@ -71,3 +81,40 @@ def get_distribusi_file_forms(distribusi_id): describe_form.searchtags.data = distribusi_file.tags distribusi_file_forms[distribusi_file.id] = describe_form return distribusi_file_forms + + +def save_described_file_to_db(describe_form, distribusi_file): + if describe_form.validate_on_submit(): + try: + if describe_form.description.data: + distribusi_file.description = describe_form.description + if describe_form.alttext.data: + distribusi_file.alttext = describe_form.alttext + if describe_form.searchtags.data: + distribusi_file.tags = describe_form.searchtags + db.session.add(distribusi_file) + db.session.commit() + except InvalidRequestError: + db.session.rollback() + describe_form.save.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except IntegrityError: + db.session.rollback() + describe_form.save.errors.append("User already exists!") + flash("User already exists!", "warning") + except DataError: + db.session.rollback() + describe_form.save.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + describe_form.save.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + describe_form.save.errors.append( + "Error connecting to the database" + ) + flash("Error connecting to the database", "danger") -- 2.39.2 From b71a694777cd087bc42706514e6b604a296f08ac Mon Sep 17 00:00:00 2001 From: crunk Date: Tue, 28 May 2024 23:35:40 +0200 Subject: [PATCH 20/49] remove copied user db integrity error --- verse/describer/describe_files.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index f980dfe..3c6da74 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -94,14 +94,10 @@ def save_described_file_to_db(describe_form, distribusi_file): distribusi_file.tags = describe_form.searchtags db.session.add(distribusi_file) db.session.commit() - except InvalidRequestError: + except (InvalidRequestError, IntegrityError): db.session.rollback() describe_form.save.errors.append("Something went wrong!") flash("Something went wrong!", "danger") - except IntegrityError: - db.session.rollback() - describe_form.save.errors.append("User already exists!") - flash("User already exists!", "warning") except DataError: db.session.rollback() describe_form.save.errors.append("Invalid Entry") -- 2.39.2 From 90d4251fd9af62b6c3f5e64afc662e89dfbdb3dc Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 21:49:27 +0200 Subject: [PATCH 21/49] working file desriber --- verse/describer/describe_files.py | 56 ++++++++++++++----------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 3c6da74..93239fa 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -84,33 +84,29 @@ def get_distribusi_file_forms(distribusi_id): def save_described_file_to_db(describe_form, distribusi_file): - if describe_form.validate_on_submit(): - try: - if describe_form.description.data: - distribusi_file.description = describe_form.description - if describe_form.alttext.data: - distribusi_file.alttext = describe_form.alttext - if describe_form.searchtags.data: - distribusi_file.tags = describe_form.searchtags - db.session.add(distribusi_file) - db.session.commit() - except (InvalidRequestError, IntegrityError): - db.session.rollback() - describe_form.save.errors.append("Something went wrong!") - flash("Something went wrong!", "danger") - except DataError: - db.session.rollback() - describe_form.save.errors.append("Invalid Entry") - flash("Invalid Entry", "warning") - except InterfaceError: - db.session.rollback() - describe_form.save.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") - except DatabaseError: - db.session.rollback() - describe_form.save.errors.append( - "Error connecting to the database" - ) - flash("Error connecting to the database", "danger") + try: + if describe_form.description.data: + print(distribusi_file.id) + distribusi_file.description = describe_form.description.data + if describe_form.alttext.data: + distribusi_file.alttext = describe_form.alttext.data + if describe_form.searchtags.data: + distribusi_file.tags = describe_form.searchtags.data + db.session.add(distribusi_file) + db.session.commit() + except (InvalidRequestError, IntegrityError): + db.session.rollback() + describe_form.save.errors.append("Something went wrong!") + flash("Something went wrong!", "danger") + except DataError: + db.session.rollback() + describe_form.save.errors.append("Invalid Entry") + flash("Invalid Entry", "warning") + except InterfaceError: + db.session.rollback() + describe_form.save.errors.append("Error connecting to the database") + flash("Error connecting to the database", "danger") + except DatabaseError: + db.session.rollback() + describe_form.save.errors.append("Error connecting to the database") + flash("Error connecting to the database", "danger") -- 2.39.2 From 475a41235449feca3d9fca31392af28c69e16881 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 21:59:54 +0200 Subject: [PATCH 22/49] a bit of css wrangling --- .../templates/describe_files/describe.html | 85 ++++++++++--------- verse/static/css/style.css | 2 - 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index db3e72e..8c5e084 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -26,48 +26,49 @@ -
- {% for id, describe_form in distribusi_file_forms.items() %} -
- {% if describe_form.type == "image" %} - - {% elif describe_form.type == "video" %} - - {% elif describe_form.type == "audio" %} - - {% else %} - file: {{describe_form.file_path}} - {% endif %} -
- {{ describe_form.csrf_token }} -

File path: {{describe_form.file_path}}

-
- {{ describe_form.description.label }} - {{ describe_form.description }} - {% for message in describe_form.description.errors %} -
{{ message }}
- {% endfor %} -
-
- {{ describe_form.searchtags.label }} - {{ describe_form.searchtags }} - {% for message in describe_form.searchtags.errors %} -
{{ message }}
- {% endfor %} -
-
- {{ describe_form.alttext.label }} - {{ describe_form.alttext }} - {% for message in describe_form.alttext.errors %} -
{{ message }}
- {% endfor %} -
-
- {{ describe_form.save }} -
-
+
+
+ {% for id, describe_form in distribusi_file_forms.items() %} +
+ {% if describe_form.type == "image" %} + + {% elif describe_form.type == "video" %} + + {% elif describe_form.type == "audio" %} + + {% else %} + file: {{describe_form.file_path}} + {% endif %} +
+ {{ describe_form.csrf_token }} +

File path: {{describe_form.file_path}}

+
+ {{ describe_form.description.label }} + {{ describe_form.description }} + {% for message in describe_form.description.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.searchtags.label }} + {{ describe_form.searchtags }} + {% for message in describe_form.searchtags.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.alttext.label }} + {{ describe_form.alttext }} + {% for message in describe_form.alttext.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ describe_form.save }} +
+
+
+ {% endfor%}
- {% endfor%}
- {% endblock %} diff --git a/verse/static/css/style.css b/verse/static/css/style.css index 900ee56..c0939f0 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -177,8 +177,6 @@ a:active { .distribusi_file { margin-top: 1em; padding: 0.5em; - padding-left: auto; - padding-right: auto; width: 45em; background-color:#fdfdfd; text-decoration: none; -- 2.39.2 From b5c9bfc8d76936028256996913a59c388fdc340d Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 22:14:13 +0200 Subject: [PATCH 23/49] refactor: moved distribusi workflow forms do distribusikan folder --- verse/distribusikan/distribusiselector.py | 10 +++++----- verse/distribusikan/distribusiworkflow.py | 10 +++++----- verse/distribusikan/editor.py | 12 ++++++------ verse/{ => distribusikan}/forms/distribusiform.py | 0 verse/{ => distribusikan}/forms/editorform.py | 0 verse/{ => distribusikan}/forms/publicthemeform.py | 0 verse/{ => distribusikan}/forms/selectorform.py | 0 verse/{ => distribusikan}/forms/themeform.py | 0 verse/{ => distribusikan}/forms/uploadform.py | 0 verse/distribusikan/themeselector.py | 10 +++++----- verse/distribusikan/upload.py | 2 +- verse/distribusikan/uploadpage.py | 8 ++++---- verse/start.py | 2 +- 13 files changed, 27 insertions(+), 27 deletions(-) rename verse/{ => distribusikan}/forms/distribusiform.py (100%) rename verse/{ => distribusikan}/forms/editorform.py (100%) rename verse/{ => distribusikan}/forms/publicthemeform.py (100%) rename verse/{ => distribusikan}/forms/selectorform.py (100%) rename verse/{ => distribusikan}/forms/themeform.py (100%) rename verse/{ => distribusikan}/forms/uploadform.py (100%) diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusiselector.py index 4201129..ac0e040 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusiselector.py @@ -12,11 +12,11 @@ from sqlalchemy.exc import ( from app import db from distribusikan.distribusisinfo import DistribusisInfo -from forms.distribusiform import DistribusiForm -from forms.publicthemeform import PublicThemeForm -from forms.selectorform import SelectorForm -from forms.themeform import ThemeForm -from forms.uploadform import UploadForm +from distribusikan.forms.distribusiform import DistribusiForm +from distribusikan.forms.publicthemeform import PublicThemeForm +from distribusikan.forms.selectorform import SelectorForm +from distribusikan.forms.themeform import ThemeForm +from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusiworkflow.py index 4e3a376..f728292 100644 --- a/verse/distribusikan/distribusiworkflow.py +++ b/verse/distribusikan/distribusiworkflow.py @@ -17,13 +17,13 @@ from sqlalchemy.exc import ( from app import db from distribusikan.distribusiselector import SelectorVisible from distribusikan.distribusisinfo import DistribusisInfo -from forms.distribusiform import DistribusiForm -from forms.publicthemeform import PublicThemeForm -from forms.selectorform import SelectorForm -from forms.themeform import ThemeForm +from distribusikan.forms.distribusiform import DistribusiForm +from distribusikan.forms.publicthemeform import PublicThemeForm +from distribusikan.forms.selectorform import SelectorForm +from distribusikan.forms.themeform import ThemeForm # Forms! -from forms.uploadform import UploadForm +from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/editor.py index 88e63c2..384c8b1 100644 --- a/verse/distribusikan/editor.py +++ b/verse/distribusikan/editor.py @@ -14,12 +14,12 @@ from werkzeug.utils import secure_filename from app import db from distribusikan.distribusisinfo import DistribusisInfo -from forms.distribusiform import DistribusiForm -from forms.editorform import EditorForm -from forms.publicthemeform import PublicThemeForm -from forms.selectorform import SelectorForm -from forms.themeform import ThemeForm -from forms.uploadform import UploadForm +from distribusikan.forms.distribusiform import DistribusiForm +from distribusikan.forms.editorform import EditorForm +from distribusikan.forms.publicthemeform import PublicThemeForm +from distribusikan.forms.selectorform import SelectorForm +from distribusikan.forms.themeform import ThemeForm +from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from statuspengguna.helper import UserHelper diff --git a/verse/forms/distribusiform.py b/verse/distribusikan/forms/distribusiform.py similarity index 100% rename from verse/forms/distribusiform.py rename to verse/distribusikan/forms/distribusiform.py diff --git a/verse/forms/editorform.py b/verse/distribusikan/forms/editorform.py similarity index 100% rename from verse/forms/editorform.py rename to verse/distribusikan/forms/editorform.py diff --git a/verse/forms/publicthemeform.py b/verse/distribusikan/forms/publicthemeform.py similarity index 100% rename from verse/forms/publicthemeform.py rename to verse/distribusikan/forms/publicthemeform.py diff --git a/verse/forms/selectorform.py b/verse/distribusikan/forms/selectorform.py similarity index 100% rename from verse/forms/selectorform.py rename to verse/distribusikan/forms/selectorform.py diff --git a/verse/forms/themeform.py b/verse/distribusikan/forms/themeform.py similarity index 100% rename from verse/forms/themeform.py rename to verse/distribusikan/forms/themeform.py diff --git a/verse/forms/uploadform.py b/verse/distribusikan/forms/uploadform.py similarity index 100% rename from verse/forms/uploadform.py rename to verse/distribusikan/forms/uploadform.py diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/themeselector.py index 96b2d8a..b32a338 100644 --- a/verse/distribusikan/themeselector.py +++ b/verse/distribusikan/themeselector.py @@ -4,11 +4,11 @@ import shutil from flask import render_template from distribusikan.distribusisinfo import DistribusisInfo -from forms.distribusiform import DistribusiForm -from forms.publicthemeform import PublicThemeForm -from forms.selectorform import SelectorForm -from forms.themeform import ThemeForm -from forms.uploadform import UploadForm +from distribusikan.forms.distribusiform import DistribusiForm +from distribusikan.forms.publicthemeform import PublicThemeForm +from distribusikan.forms.selectorform import SelectorForm +from distribusikan.forms.themeform import ThemeForm +from distribusikan.forms.uploadform import UploadForm from statuspengguna.helper import UserHelper diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py index 83110b5..47a9009 100644 --- a/verse/distribusikan/upload.py +++ b/verse/distribusikan/upload.py @@ -13,7 +13,7 @@ from sqlalchemy.exc import ( from app import db from distribusikan.distribusiselector import SelectCurrentDistribusi -from forms.uploadform import UploadForm +from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User from statuspengguna.helper import UserHelper diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/uploadpage.py index a8f2510..8a500cd 100644 --- a/verse/distribusikan/uploadpage.py +++ b/verse/distribusikan/uploadpage.py @@ -4,10 +4,10 @@ from app import APP from distribusikan.distribusiselector import SelectorVisible from distribusikan.distribusisinfo import DistribusisInfo from distribusikan.upload import UploadNewDistribusi, UploadUpdatedFiles -from forms.distribusiform import DistribusiForm -from forms.publicthemeform import PublicThemeForm -from forms.selectorform import SelectorForm -from forms.themeform import ThemeForm +from distribusikan.forms.distribusiform import DistribusiForm +from distribusikan.forms.publicthemeform import PublicThemeForm +from distribusikan.forms.selectorform import SelectorForm +from distribusikan.forms.themeform import ThemeForm # UserPengguna from statuspengguna.helper import UserHelper diff --git a/verse/start.py b/verse/start.py index 728fabc..da78a23 100644 --- a/verse/start.py +++ b/verse/start.py @@ -18,7 +18,7 @@ from app import create_app, login_manager, db from describer.describe_files import describer from distribusikan.distribusikan import distribusikan from distribusikan.distribusisinfo import DistribusisInfo -from forms.uploadform import UploadForm +from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User from statuspengguna.forgotpassword import forgot_password -- 2.39.2 From 280ce2f1964a535dc0bdc124125b44a0f2aaaccd Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 22:16:52 +0200 Subject: [PATCH 24/49] refactor: moved user forms to statuspengguna folder --- .../forms/forgotpasswordform.py | 15 ++++++++ verse/statuspengguna/forms/loginform.py | 18 +++++++++ verse/statuspengguna/forms/registerform.py | 38 +++++++++++++++++++ .../statuspengguna/forms/resetpasswordform.py | 23 +++++++++++ verse/statuspengguna/loginuser.py | 2 +- verse/statuspengguna/registeruser.py | 2 +- verse/statuspengguna/resetpassword.py | 2 +- 7 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 verse/statuspengguna/forms/forgotpasswordform.py create mode 100644 verse/statuspengguna/forms/loginform.py create mode 100644 verse/statuspengguna/forms/registerform.py create mode 100644 verse/statuspengguna/forms/resetpasswordform.py diff --git a/verse/statuspengguna/forms/forgotpasswordform.py b/verse/statuspengguna/forms/forgotpasswordform.py new file mode 100644 index 0000000..385327d --- /dev/null +++ b/verse/statuspengguna/forms/forgotpasswordform.py @@ -0,0 +1,15 @@ +"""Forgotten password form to help user.""" + +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, validators +from wtforms.validators import Email, Length + + +class ForgotPasswordForm(FlaskForm): + """Forgotten password distribusiverse form class.""" + + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + submit = SubmitField("Send email") diff --git a/verse/statuspengguna/forms/loginform.py b/verse/statuspengguna/forms/loginform.py new file mode 100644 index 0000000..b446850 --- /dev/null +++ b/verse/statuspengguna/forms/loginform.py @@ -0,0 +1,18 @@ +"""Login form to validate user.""" + +from flask_wtf import FlaskForm +from wtforms import PasswordField, StringField, SubmitField, validators +from wtforms.validators import Email, Length + + +class LoginForm(FlaskForm): + """Login distribusiverse form class.""" + + email = StringField( + "Email address:", + validators=[validators.InputRequired(), Email(), Length(6, 64)], + ) + password = PasswordField( + "Password:", validators=[validators.InputRequired()] + ) + submit = SubmitField("Sign In") diff --git a/verse/statuspengguna/forms/registerform.py b/verse/statuspengguna/forms/registerform.py new file mode 100644 index 0000000..89c42d6 --- /dev/null +++ b/verse/statuspengguna/forms/registerform.py @@ -0,0 +1,38 @@ +"""Register form to make a new user.""" + +from flask_wtf import FlaskForm +from wtforms import PasswordField, StringField, SubmitField, validators +from wtforms.validators import Email, EqualTo, Length + + +class RegisterForm(FlaskForm): + """Register for distribusi-verse form class""" + + username = StringField( + "Username:", + validators=[validators.InputRequired(), Length(3, 150)], + ) + + email = StringField( + "Email address:", + validators=[ + validators.InputRequired(), + Email(), + Length(6, 128), + ], + ) + + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) + + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Register to Distribusi-verse") diff --git a/verse/statuspengguna/forms/resetpasswordform.py b/verse/statuspengguna/forms/resetpasswordform.py new file mode 100644 index 0000000..481cb02 --- /dev/null +++ b/verse/statuspengguna/forms/resetpasswordform.py @@ -0,0 +1,23 @@ +"""Reset Password Form form to reset a users PasswordField.""" + +from flask_wtf import FlaskForm +from wtforms import PasswordField, SubmitField, validators +from wtforms.validators import EqualTo, Length + + +class ResetPasswordForm(FlaskForm): + """ResetPassword for distribusi-verse form class""" + + password = PasswordField( + "New password:", + validators=[validators.InputRequired(), Length(12, 72)], + ) + confirmpassword = PasswordField( + "Confirm your password:", + validators=[ + validators.InputRequired(), + Length(12, 72), + EqualTo("password", message="Passwords must match !"), + ], + ) + submit = SubmitField("Reset your password") diff --git a/verse/statuspengguna/loginuser.py b/verse/statuspengguna/loginuser.py index 6f18cde..ba28c72 100644 --- a/verse/statuspengguna/loginuser.py +++ b/verse/statuspengguna/loginuser.py @@ -10,7 +10,7 @@ from flask import ( from flask_bcrypt import check_password_hash from flask_login import login_user -from forms.loginform import LoginForm +from statuspengguna.forms.loginform import LoginForm from models.user_model import User login_section = Blueprint( diff --git a/verse/statuspengguna/registeruser.py b/verse/statuspengguna/registeruser.py index e97f1ee..af1216f 100644 --- a/verse/statuspengguna/registeruser.py +++ b/verse/statuspengguna/registeruser.py @@ -11,7 +11,7 @@ from sqlalchemy.exc import ( from werkzeug.routing import BuildError from app import db -from forms.registerform import RegisterForm +from statuspengguna.forms.registerform import RegisterForm from models.user_model import User register_user = Blueprint( diff --git a/verse/statuspengguna/resetpassword.py b/verse/statuspengguna/resetpassword.py index c0288ae..a9fc1b5 100644 --- a/verse/statuspengguna/resetpassword.py +++ b/verse/statuspengguna/resetpassword.py @@ -13,7 +13,7 @@ from sqlalchemy.exc import ( from werkzeug.routing import BuildError from app import db -from forms.resetpasswordform import ResetPasswordForm +from statuspengguna.forms.resetpasswordform import ResetPasswordForm from models.user_model import User reset_password = Blueprint( -- 2.39.2 From 102032bd6eb10301d28cba4d5ec99471db11178d Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 22:37:55 +0200 Subject: [PATCH 25/49] refactor: no more main forms folder --- verse/admin.py | 8 ++ verse/admin_page/admin_page.py | 118 ++++++++++++++++++ verse/admin_page/forms/admindistribusiform.py | 23 ++++ verse/admin_page/forms/adminuserform.py | 23 ++++ .../base => admin_page/templates}/admin.html | 0 verse/start.py | 19 +-- verse/statuspengguna/forgotpassword.py | 2 +- 7 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 verse/admin.py create mode 100644 verse/admin_page/admin_page.py create mode 100644 verse/admin_page/forms/admindistribusiform.py create mode 100644 verse/admin_page/forms/adminuserform.py rename verse/{templates/base => admin_page/templates}/admin.html (100%) diff --git a/verse/admin.py b/verse/admin.py new file mode 100644 index 0000000..834af10 --- /dev/null +++ b/verse/admin.py @@ -0,0 +1,8 @@ +from flask_login import current_user +from models.user_model import User + +def is_adminuser(): + if not current_user.is_authenticated: + return False + user = User.query.filter_by(email=current_user.email).first() + return user.admin diff --git a/verse/admin_page/admin_page.py b/verse/admin_page/admin_page.py new file mode 100644 index 0000000..3857cfe --- /dev/null +++ b/verse/admin_page/admin_page.py @@ -0,0 +1,118 @@ +import os +import shutil + +from flask import render_template, Blueprint +from flask_login import current_user, login_required +from sqlalchemy.exc import ( + DatabaseError, + DataError, + InterfaceError, + InvalidRequestError, +) + +from app import db +from admin import is_adminuser +from distribusikan.distribusisinfo import DistribusisInfo +from admin_page.forms.admindistribusiform import AdminDistribusiForm +from admin_page.forms.adminuserform import AdminUserForm +from models.distribusi_model import Distribusis +from models.user_model import User + +admin_page = Blueprint( + "admin", + __name__, + template_folder="templates/describe_files", + static_folder="static", +) + + +@admin_page.route("/admin", methods=["GET", "POST"]) +@login_required +def admin(): + if not is_adminuser(): + return redirect(url_for("index")) + adminuserform = add_users_to_form(AdminUserForm()) + admindistribusiform = add_distribusis_to_form(AdminDistribusiForm()) + if admindistribusiform.validate_on_submit(): + delete_distribusis(admindistribusiform) + + if adminuserform.validate_on_submit(): + if adminuserform.delete.data: + delete_users(adminuserform) + + template = render_template( + "admin.html", + adminuserform=adminuserform, + admindistribusiform=admindistribusiform, + ) + return template + + +def delete_users(adminuserform): + for userform in adminuserform: + if "user" in userform.id: + if userform.data: + useremail = userform.label.text + user = User.query.filter_by(email=useremail).first() + delete_User_distribusis(user) + delete_user_from_db(user) + userform.errors.append(f"User {useremail} deleted!") + + +def delete_user_from_db(user): + try: + db.session.delete(user) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + + +def delete_User_distribusis(user): + distribusis = DistribusisInfo.getuserdistribusis(user.email) + for distribusi in distribusis: + delete_distribusi_files(distribusi.distribusiname) + delete_distribusi_from_db(distribusi) + + +def delete_distribusis(admindistribusiform): + for distribusiform in admindistribusiform: + if "distribusi" in distribusiform.id: + if distribusiform.data: + distribusiname = distribusiform.label.text + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + delete_distribusi_from_db(distribusi) + delete_distribusi_files(distribusiname) + distribusiform.errors.append("Deleted distribusi") + + +def delete_distribusi_from_db(distribusi): + try: + db.session.delete(distribusi) + db.session.commit() + except (InvalidRequestError, DataError, InterfaceError, DatabaseError): + db.session.rollback() + + +def delete_distribusi_files(distribusiname): + userfolder = os.path.join("stash", distribusiname) + if os.path.exists(userfolder): + shutil.rmtree(userfolder) + cssfolder = os.path.join("themes/userthemes", distribusiname) + if os.path.exists(cssfolder): + shutil.rmtree(cssfolder) + + +def add_distribusis_to_form(admindistribusiform): + distribusis = DistribusisInfo.visibledistribusis() + admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( + distribusis + ) + return admindistribusiform + + +def add_users_to_form(adminuserform): + users = User.query.all() + adminuserform = AdminUserForm.user_list_form_builder(users) + return adminuserform diff --git a/verse/admin_page/forms/admindistribusiform.py b/verse/admin_page/forms/admindistribusiform.py new file mode 100644 index 0000000..f00f3db --- /dev/null +++ b/verse/admin_page/forms/admindistribusiform.py @@ -0,0 +1,23 @@ +"""Form object declaration.""" + +from flask_wtf import FlaskForm +from wtforms import BooleanField, SubmitField + + +class AdminDistribusiForm(FlaskForm): + """Admin Distribusi form.""" + + delete = SubmitField("Delete") + + def distribusi_list_form_builder(distribusis): + class DistribusiListForm(AdminDistribusiForm): + pass + + for i, distribusi in enumerate(distribusis): + setattr( + DistribusiListForm, + f"distribusi_{i}", + BooleanField(label=distribusi.distribusiname), + ) + + return DistribusiListForm() diff --git a/verse/admin_page/forms/adminuserform.py b/verse/admin_page/forms/adminuserform.py new file mode 100644 index 0000000..aeda2e4 --- /dev/null +++ b/verse/admin_page/forms/adminuserform.py @@ -0,0 +1,23 @@ +"""Form object declaration.""" + +from flask_wtf import FlaskForm +from wtforms import BooleanField, SubmitField + + +class AdminUserForm(FlaskForm): + """Admin Userform form.""" + + def user_list_form_builder(users): + class UserListForm(AdminUserForm): + pass + + for i, user in enumerate(users): + setattr( + UserListForm, + f"user_{i}", + BooleanField(label=user.email), + ) + + return UserListForm() + + delete = SubmitField("Delete") diff --git a/verse/templates/base/admin.html b/verse/admin_page/templates/admin.html similarity index 100% rename from verse/templates/base/admin.html rename to verse/admin_page/templates/admin.html diff --git a/verse/start.py b/verse/start.py index da78a23..7deb7e5 100644 --- a/verse/start.py +++ b/verse/start.py @@ -13,7 +13,8 @@ from flask import ( from flask_login import current_user, login_required, logout_user from flask_wtf.csrf import CSRFError -from adminpage import AdminPage +from admin import is_adminuser +from admin_page.admin_page import admin_page from app import create_app, login_manager, db from describer.describe_files import describer from distribusikan.distribusikan import distribusikan @@ -33,6 +34,7 @@ APP.register_blueprint(describer, url_prefix="/describer") APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") +APP.register_blueprint (admin_page, url_prefix="/admin") APP.register_blueprint(distribusikan) @@ -90,14 +92,6 @@ def shortstashurl(): return redirect(url_for("index")) -@APP.route("/admin", methods=["GET", "POST"]) -@login_required -def admin(): - if not is_adminuser(): - return redirect(url_for("index")) - return AdminPage() - - @APP.route("/logout") @login_required def logout(): @@ -115,13 +109,6 @@ def load_user(user_id): return db.session.get(User, int(user_id)) -def is_adminuser(): - if not current_user.is_authenticated: - return False - user = User.query.filter_by(email=current_user.email).first() - return user.admin - - if __name__ == "__main__": APP.debug = True APP.run(port=5000) diff --git a/verse/statuspengguna/forgotpassword.py b/verse/statuspengguna/forgotpassword.py index dbb8049..3137e1f 100644 --- a/verse/statuspengguna/forgotpassword.py +++ b/verse/statuspengguna/forgotpassword.py @@ -11,7 +11,7 @@ from sqlalchemy.exc import ( ) from app import db, get_app -from forms.forgotpasswordform import ForgotPasswordForm +from statuspengguna.forms.forgotpasswordform import ForgotPasswordForm from models.user_model import User mail = Mail(get_app()) -- 2.39.2 From 44258881168c7f60518b45434f072352dc62f886 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 2 Jun 2024 22:39:04 +0200 Subject: [PATCH 26/49] deleted files --- verse/adminpage.py | 105 ----------------------------- verse/forms/admindistribusiform.py | 23 ------- verse/forms/adminuserform.py | 23 ------- verse/forms/forgotpasswordform.py | 15 ----- verse/forms/loginform.py | 18 ----- verse/forms/registerform.py | 38 ----------- verse/forms/resetpasswordform.py | 23 ------- 7 files changed, 245 deletions(-) delete mode 100644 verse/adminpage.py delete mode 100644 verse/forms/admindistribusiform.py delete mode 100644 verse/forms/adminuserform.py delete mode 100644 verse/forms/forgotpasswordform.py delete mode 100644 verse/forms/loginform.py delete mode 100644 verse/forms/registerform.py delete mode 100644 verse/forms/resetpasswordform.py diff --git a/verse/adminpage.py b/verse/adminpage.py deleted file mode 100644 index 0bb1c39..0000000 --- a/verse/adminpage.py +++ /dev/null @@ -1,105 +0,0 @@ -import os -import shutil - -from flask import render_template -from sqlalchemy.exc import ( - DatabaseError, - DataError, - InterfaceError, - InvalidRequestError, -) - -from app import db -from distribusikan.distribusisinfo import DistribusisInfo -from forms.admindistribusiform import AdminDistribusiForm -from forms.adminuserform import AdminUserForm -from models.distribusi_model import Distribusis -from models.user_model import User - - -def AdminPage(): - adminuserform = AddUsersToForm(AdminUserForm()) - admindistribusiform = AddDistribusisToForm(AdminDistribusiForm()) - if admindistribusiform.validate_on_submit(): - DeleteDistribusis(admindistribusiform) - - if adminuserform.validate_on_submit(): - if adminuserform.delete.data: - DeleteUsers(adminuserform) - - template = render_template( - "admin.html", - adminuserform=adminuserform, - admindistribusiform=admindistribusiform, - ) - return template - - -def DeleteUsers(adminuserform): - for userform in adminuserform: - if "user" in userform.id: - if userform.data: - useremail = userform.label.text - user = User.query.filter_by(email=useremail).first() - DeleteUserDistribusis(user) - DeleteUserFromDb(user) - userform.errors.append(f"User {useremail} deleted!") - - -def DeleteUserFromDb(user): - try: - db.session.delete(user) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - - -def DeleteUserDistribusis(user): - distribusis = DistribusisInfo.getuserdistribusis(user.email) - for distribusi in distribusis: - DeleteDistribusiFiles(distribusi.distribusiname) - DeleteDistribusiFromDb(distribusi) - - -def DeleteDistribusis(admindistribusiform): - for distribusiform in admindistribusiform: - if "distribusi" in distribusiform.id: - if distribusiform.data: - distribusiname = distribusiform.label.text - distribusi = Distribusis.query.filter_by( - distribusiname=distribusiname - ).first() - DeleteDistribusiFromDb(distribusi) - DeleteDistribusiFiles(distribusiname) - distribusiform.errors.append("Deleted distribusi") - - -def DeleteDistribusiFromDb(distribusi): - try: - db.session.delete(distribusi) - db.session.commit() - except (InvalidRequestError, DataError, InterfaceError, DatabaseError): - db.session.rollback() - - -def DeleteDistribusiFiles(distribusiname): - userfolder = os.path.join("stash", distribusiname) - if os.path.exists(userfolder): - shutil.rmtree(userfolder) - cssfolder = os.path.join("themes/userthemes", distribusiname) - if os.path.exists(cssfolder): - shutil.rmtree(cssfolder) - - -def AddDistribusisToForm(admindistribusiform): - distribusis = DistribusisInfo.visibledistribusis() - admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( - distribusis - ) - return admindistribusiform - - -def AddUsersToForm(adminuserform): - users = User.query.all() - adminuserform = AdminUserForm.user_list_form_builder(users) - return adminuserform diff --git a/verse/forms/admindistribusiform.py b/verse/forms/admindistribusiform.py deleted file mode 100644 index f00f3db..0000000 --- a/verse/forms/admindistribusiform.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Form object declaration.""" - -from flask_wtf import FlaskForm -from wtforms import BooleanField, SubmitField - - -class AdminDistribusiForm(FlaskForm): - """Admin Distribusi form.""" - - delete = SubmitField("Delete") - - def distribusi_list_form_builder(distribusis): - class DistribusiListForm(AdminDistribusiForm): - pass - - for i, distribusi in enumerate(distribusis): - setattr( - DistribusiListForm, - f"distribusi_{i}", - BooleanField(label=distribusi.distribusiname), - ) - - return DistribusiListForm() diff --git a/verse/forms/adminuserform.py b/verse/forms/adminuserform.py deleted file mode 100644 index aeda2e4..0000000 --- a/verse/forms/adminuserform.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Form object declaration.""" - -from flask_wtf import FlaskForm -from wtforms import BooleanField, SubmitField - - -class AdminUserForm(FlaskForm): - """Admin Userform form.""" - - def user_list_form_builder(users): - class UserListForm(AdminUserForm): - pass - - for i, user in enumerate(users): - setattr( - UserListForm, - f"user_{i}", - BooleanField(label=user.email), - ) - - return UserListForm() - - delete = SubmitField("Delete") diff --git a/verse/forms/forgotpasswordform.py b/verse/forms/forgotpasswordform.py deleted file mode 100644 index 385327d..0000000 --- a/verse/forms/forgotpasswordform.py +++ /dev/null @@ -1,15 +0,0 @@ -"""Forgotten password form to help user.""" - -from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField, validators -from wtforms.validators import Email, Length - - -class ForgotPasswordForm(FlaskForm): - """Forgotten password distribusiverse form class.""" - - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - submit = SubmitField("Send email") diff --git a/verse/forms/loginform.py b/verse/forms/loginform.py deleted file mode 100644 index b446850..0000000 --- a/verse/forms/loginform.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Login form to validate user.""" - -from flask_wtf import FlaskForm -from wtforms import PasswordField, StringField, SubmitField, validators -from wtforms.validators import Email, Length - - -class LoginForm(FlaskForm): - """Login distribusiverse form class.""" - - email = StringField( - "Email address:", - validators=[validators.InputRequired(), Email(), Length(6, 64)], - ) - password = PasswordField( - "Password:", validators=[validators.InputRequired()] - ) - submit = SubmitField("Sign In") diff --git a/verse/forms/registerform.py b/verse/forms/registerform.py deleted file mode 100644 index 89c42d6..0000000 --- a/verse/forms/registerform.py +++ /dev/null @@ -1,38 +0,0 @@ -"""Register form to make a new user.""" - -from flask_wtf import FlaskForm -from wtforms import PasswordField, StringField, SubmitField, validators -from wtforms.validators import Email, EqualTo, Length - - -class RegisterForm(FlaskForm): - """Register for distribusi-verse form class""" - - username = StringField( - "Username:", - validators=[validators.InputRequired(), Length(3, 150)], - ) - - email = StringField( - "Email address:", - validators=[ - validators.InputRequired(), - Email(), - Length(6, 128), - ], - ) - - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) - - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Register to Distribusi-verse") diff --git a/verse/forms/resetpasswordform.py b/verse/forms/resetpasswordform.py deleted file mode 100644 index 481cb02..0000000 --- a/verse/forms/resetpasswordform.py +++ /dev/null @@ -1,23 +0,0 @@ -"""Reset Password Form form to reset a users PasswordField.""" - -from flask_wtf import FlaskForm -from wtforms import PasswordField, SubmitField, validators -from wtforms.validators import EqualTo, Length - - -class ResetPasswordForm(FlaskForm): - """ResetPassword for distribusi-verse form class""" - - password = PasswordField( - "New password:", - validators=[validators.InputRequired(), Length(12, 72)], - ) - confirmpassword = PasswordField( - "Confirm your password:", - validators=[ - validators.InputRequired(), - Length(12, 72), - EqualTo("password", message="Passwords must match !"), - ], - ) - submit = SubmitField("Reset your password") -- 2.39.2 From 681c34e05e1ff33d6f37dc5ebb2129f0bfccc1ef Mon Sep 17 00:00:00 2001 From: crunk Date: Thu, 6 Jun 2024 19:42:06 +0200 Subject: [PATCH 27/49] start of search --- verse/search/forms/searchform.py | 6 ++++++ verse/search/search.py | 8 ++++++++ verse/search/templates/search/search.html | 3 +++ 3 files changed, 17 insertions(+) create mode 100644 verse/search/forms/searchform.py create mode 100644 verse/search/search.py create mode 100644 verse/search/templates/search/search.html diff --git a/verse/search/forms/searchform.py b/verse/search/forms/searchform.py new file mode 100644 index 0000000..8925c53 --- /dev/null +++ b/verse/search/forms/searchform.py @@ -0,0 +1,6 @@ +"""SearchForm to search files and distribusis in the distribusi archive""" + +from flask_wtf import FlaskForm +from wtforms import StringField, SubmitField, validators +from wtforms.validators import Length +from wtforms.widgets import TextArea diff --git a/verse/search/search.py b/verse/search/search.py new file mode 100644 index 0000000..83a40b0 --- /dev/null +++ b/verse/search/search.py @@ -0,0 +1,8 @@ +import os + +from whoosh.fields import * +from whoosh.index import open_dir +from whoosh.qparser import QueryParser + +SCRIPT_DIR = os.path.dirname(__file__) +DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../data")) diff --git a/verse/search/templates/search/search.html b/verse/search/templates/search/search.html new file mode 100644 index 0000000..6925b8d --- /dev/null +++ b/verse/search/templates/search/search.html @@ -0,0 +1,3 @@ +{% extends "base/base.html" %} +{% block main %} +{% endblock %} -- 2.39.2 From 94efe6ad838ace763fcbcfc64e719e1f36775b32 Mon Sep 17 00:00:00 2001 From: crunk Date: Fri, 14 Jun 2024 23:11:05 +0200 Subject: [PATCH 28/49] WIP distribusi descriptions through front matter markdown --- verse/distribusikan/forms/uploadform.py | 22 ++++++++++++++++++- .../distribusiworkflow/upload.html | 14 ++++++++++++ verse/static/css/style.css | 11 +++++----- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/verse/distribusikan/forms/uploadform.py b/verse/distribusikan/forms/uploadform.py index 90dcd70..994952b 100644 --- a/verse/distribusikan/forms/uploadform.py +++ b/verse/distribusikan/forms/uploadform.py @@ -4,6 +4,7 @@ from wtforms import ( SelectField, StringField, SubmitField, + TextAreaField, validators, ) from wtforms.validators import ( @@ -11,6 +12,7 @@ from wtforms.validators import ( Length, ValidationError, ) +from wtforms.widgets import TextArea from app import settings @@ -48,6 +50,24 @@ class UploadForm(FlaskForm): distribusiname, ], ) + description = StringField( + "Description of this distribusi:", + validators=[ + Length(10, 4096), + ], + widget=TextArea(), + ) + mdfile = FileField( + "Alternatively upload a markdown file with a description:", + validators=[ + FileAllowed(["md"], "markdown only"), + FileRequired(), + FileSize( + max_size=10485760, + message="markdown file size should be smaller than 10MB", + ), + ], + ) year = SelectField( "Year:", validate_choice=True, @@ -77,7 +97,7 @@ class UploadForm(FlaskForm): FileRequired(), FileSize( max_size=1073741824, - message="Zipfile size must be smaller than 100MB", + message="Zipfile size must be smaller than 1024MB", ), ], ) diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html b/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html index fe3aa78..38157af 100644 --- a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html +++ b/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html @@ -10,6 +10,20 @@
{{ message }}
{% endfor %} +
+ {{ uploadform.description.label }} + {{ uploadform.description }} + {% for message in uploadform.description.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ uploadform.mdfile.label }} + {{ uploadform.mdfile }} + {% for message in uploadform.mdfile.errors %} +
{{ message }}
+ {% endfor %} +
{{ uploadform.year.label }}
diff --git a/verse/static/css/style.css b/verse/static/css/style.css index c0939f0..b2bab63 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -31,15 +31,10 @@ input[type=text], input[type=password], input[type=file] { border: 1px solid #E0B0FF; } -div#upload form { - padding-right: 15%; -} .workflow{ margin-top: 1em; padding: 0.5em; - padding-left: auto; - padding-right: auto; width: 31em; background-color:#fdfdfd; text-decoration: none; @@ -69,7 +64,11 @@ div#upload form { #distribusi-index { padding-left: 1em; } - +textarea#description { + width: 100%; + height: 15em; + resize: none; +} div#buttons{ position: fixed; top: 0.5em; -- 2.39.2 From 7b76f63ed8a572fbca95c35f70c352ee6ed535fb Mon Sep 17 00:00:00 2001 From: crunk Date: Fri, 14 Jun 2024 23:36:22 +0200 Subject: [PATCH 29/49] increased the character limit to 32000 based on current Varia website description lenghts --- verse/distribusikan/forms/uploadform.py | 2 +- verse/static/css/style.css | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/verse/distribusikan/forms/uploadform.py b/verse/distribusikan/forms/uploadform.py index 994952b..8bec973 100644 --- a/verse/distribusikan/forms/uploadform.py +++ b/verse/distribusikan/forms/uploadform.py @@ -53,7 +53,7 @@ class UploadForm(FlaskForm): description = StringField( "Description of this distribusi:", validators=[ - Length(10, 4096), + Length(10, 32000), ], widget=TextArea(), ) diff --git a/verse/static/css/style.css b/verse/static/css/style.css index b2bab63..d5f8f68 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -35,7 +35,6 @@ input[type=text], input[type=password], input[type=file] { .workflow{ margin-top: 1em; padding: 0.5em; - width: 31em; background-color:#fdfdfd; text-decoration: none; scroll-behavior: smooth; @@ -54,7 +53,7 @@ input[type=text], input[type=password], input[type=file] { #mainworkflow { - width: 30em; + width: 40em; margin:0 auto; } @@ -66,7 +65,7 @@ input[type=text], input[type=password], input[type=file] { } textarea#description { width: 100%; - height: 15em; + height: 20em; resize: none; } div#buttons{ -- 2.39.2 From 10b56e7479a41620431418204e43b82797af0e80 Mon Sep 17 00:00:00 2001 From: crunk Date: Fri, 14 Jun 2024 23:44:59 +0200 Subject: [PATCH 30/49] late nite freaks --- verse/describer/templates/describe_files/describe.html | 2 +- verse/static/css/style.css | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 8c5e084..7616461 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -42,7 +42,7 @@
{{ describe_form.csrf_token }}

File path: {{describe_form.file_path}}

-
+
{{ describe_form.description.label }} {{ describe_form.description }} {% for message in describe_form.description.errors %} diff --git a/verse/static/css/style.css b/verse/static/css/style.css index d5f8f68..7c6a1b5 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -63,6 +63,11 @@ input[type=text], input[type=password], input[type=file] { #distribusi-index { padding-left: 1em; } +.description > textarea { + width: 100%; + height: 10em; + resize: none; +} textarea#description { width: 100%; height: 20em; -- 2.39.2 From 62428e84ae3a56f0f87d1259a159056b64969b6c Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 17 Jun 2024 22:36:23 +0200 Subject: [PATCH 31/49] refactor after hours: added description with md file to distribusi --- verse/admin.py | 1 + verse/admin_page/admin_page.py | 6 +- .../{editor.py => css_editor_page.py} | 72 +++++++++---------- ...busiselector.py => distribusi_selector.py} | 41 +++++------ ...busiworkflow.py => distribusi_workflow.py} | 44 ++++++------ verse/distribusikan/distribusikan.py | 20 +++--- ...distribusisinfo.py => distribusis_info.py} | 8 +-- verse/distribusikan/forms/uploadform.py | 11 --- .../templates/distribusikan/distribusi.html | 10 +-- .../editcss.html | 0 .../launch.html | 0 .../selector.html | 0 .../theme.html | 0 .../upload.html | 7 -- .../templates/distribusikan/editor.html | 2 +- .../{themeselector.py => theme_selector.py} | 16 ++--- verse/distribusikan/upload.py | 10 +-- .../{uploadpage.py => upload_page.py} | 16 ++--- verse/models/distribusi_model.py | 1 + verse/start.py | 6 +- verse/statuspengguna/helper.py | 4 +- 21 files changed, 131 insertions(+), 144 deletions(-) rename verse/distribusikan/{editor.py => css_editor_page.py} (74%) rename verse/distribusikan/{distribusiselector.py => distribusi_selector.py} (81%) rename verse/distribusikan/{distribusiworkflow.py => distribusi_workflow.py} (78%) rename verse/distribusikan/{distribusisinfo.py => distribusis_info.py} (90%) rename verse/distribusikan/templates/distribusikan/{distribusiworkflow => distribusi_workflow}/editcss.html (100%) rename verse/distribusikan/templates/distribusikan/{distribusiworkflow => distribusi_workflow}/launch.html (100%) rename verse/distribusikan/templates/distribusikan/{distribusiworkflow => distribusi_workflow}/selector.html (100%) rename verse/distribusikan/templates/distribusikan/{distribusiworkflow => distribusi_workflow}/theme.html (100%) rename verse/distribusikan/templates/distribusikan/{distribusiworkflow => distribusi_workflow}/upload.html (89%) rename verse/distribusikan/{themeselector.py => theme_selector.py} (83%) rename verse/distribusikan/{uploadpage.py => upload_page.py} (78%) diff --git a/verse/admin.py b/verse/admin.py index 834af10..f95623b 100644 --- a/verse/admin.py +++ b/verse/admin.py @@ -1,6 +1,7 @@ from flask_login import current_user from models.user_model import User + def is_adminuser(): if not current_user.is_authenticated: return False diff --git a/verse/admin_page/admin_page.py b/verse/admin_page/admin_page.py index 3857cfe..faf46ac 100644 --- a/verse/admin_page/admin_page.py +++ b/verse/admin_page/admin_page.py @@ -12,7 +12,7 @@ from sqlalchemy.exc import ( from app import db from admin import is_adminuser -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from admin_page.forms.admindistribusiform import AdminDistribusiForm from admin_page.forms.adminuserform import AdminUserForm from models.distribusi_model import Distribusis @@ -68,7 +68,7 @@ def delete_user_from_db(user): def delete_User_distribusis(user): - distribusis = DistribusisInfo.getuserdistribusis(user.email) + distribusis = DistribusisInfo.get_user_distribusis(user.email) for distribusi in distribusis: delete_distribusi_files(distribusi.distribusiname) delete_distribusi_from_db(distribusi) @@ -105,7 +105,7 @@ def delete_distribusi_files(distribusiname): def add_distribusis_to_form(admindistribusiform): - distribusis = DistribusisInfo.visibledistribusis() + distribusis = DistribusisInfo.visible_distribusis() admindistribusiform = AdminDistribusiForm.distribusi_list_form_builder( distribusis ) diff --git a/verse/distribusikan/editor.py b/verse/distribusikan/css_editor_page.py similarity index 74% rename from verse/distribusikan/editor.py rename to verse/distribusikan/css_editor_page.py index 384c8b1..8e9997e 100644 --- a/verse/distribusikan/editor.py +++ b/verse/distribusikan/css_editor_page.py @@ -13,7 +13,7 @@ from sqlalchemy.exc import ( from werkzeug.utils import secure_filename from app import db -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.editorform import EditorForm from distribusikan.forms.publicthemeform import PublicThemeForm @@ -24,17 +24,17 @@ from models.distribusi_model import Distribusis from statuspengguna.helper import UserHelper -def Editor(): +def css_editor_page(): editorform = EditorForm() current_distribusi = UserHelper.current_distribusi() if editorform.validate_on_submit(): - ValidateEditCssForm(editorform, current_distribusi) - return RenderDistribusiTemplate(current_distribusi) + validate_edit_css_form(editorform, current_distribusi) + return render_distribusi_template(current_distribusi) - return RenderEditorTemplate(editorform, current_distribusi) + return render_editor_template(editorform, current_distribusi) -def ValidateEditCssForm(editorform, current_distribusi): +def validate_edit_css_form(editorform, current_distribusi): newcssfolder = os.path.join("themes/userthemes", current_distribusi) if os.path.exists(newcssfolder): shutil.rmtree(newcssfolder) @@ -44,22 +44,22 @@ def ValidateEditCssForm(editorform, current_distribusi): shutil.rmtree(publicfolder) if editorform.public.data: - MakePublicTheme(editorform, current_distribusi) + make_public_theme(editorform, current_distribusi) if editorform.cssfile.data: - SaveUploadCssFile(editorform, publicfolder) - CopyPublicToUserFolder(editorform, publicfolder, newcssfolder) + save_upload_css_file(editorform, publicfolder) + copy_public_to_user_folder(editorform, publicfolder, newcssfolder) return else: - WriteCssToFile(editorform, publicfolder) + write_css_to_file(editorform, publicfolder) if editorform.cssfile.data: - SaveUploadCssFile(editorform, newcssfolder) + save_upload_css_file(editorform, newcssfolder) return if editorform.cssname.data: - WriteCssToFile(editorform, newcssfolder) + write_css_to_file(editorform, newcssfolder) -def SaveUploadCssFile(editorform, newcssfolder): +def save_upload_css_file(editorform, newcssfolder): if not os.path.exists(newcssfolder): os.mkdir(newcssfolder) cssfile = editorform.cssfile.data @@ -74,7 +74,7 @@ def SaveUploadCssFile(editorform, newcssfolder): cleanfile.close() -def WriteCssToFile(editorform, newcssfolder): +def write_css_to_file(editorform, newcssfolder): if not os.path.exists(newcssfolder): os.mkdir(newcssfolder) @@ -86,7 +86,7 @@ def WriteCssToFile(editorform, newcssfolder): cssfile.close -def CopyPublicToUserFolder(editorform, publicfolder, newcssfolder): +def copy_public_to_user_folder(editorform, publicfolder, newcssfolder): if not os.path.exists(newcssfolder): os.mkdir(newcssfolder) copycssfile = os.path.join( @@ -97,7 +97,7 @@ def CopyPublicToUserFolder(editorform, publicfolder, newcssfolder): shutil.copy(copycssfile, newcssfolder) -def MakePublicTheme(editorform, current_distribusi): +def make_public_theme(editorform, current_distribusi): try: distribusi = Distribusis.query.filter_by( distribusiname=current_distribusi @@ -119,12 +119,12 @@ def MakePublicTheme(editorform, current_distribusi): editorform.public.errors.append("Error connecting to the database") -def RenderDistribusiTemplate(current_distribusi): +def render_distribusi_template(current_distribusi): uploadform = UploadForm() distribusiform = DistribusiForm() themeform = ThemeForm() publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() selectorform = SelectorForm() files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) @@ -148,11 +148,11 @@ def RenderDistribusiTemplate(current_distribusi): return template -def RenderEditorTemplate(editorform, current_distribusi): - htmlplaceholder = HtmlPlaceholder() +def render_editor_template(editorform, current_distribusi): + html_placeholder = get_html_placeholder() - cssplaceholder = CssPlaceholder(current_distribusi) - editorform.css.data = cssplaceholder + css_placeholder = get_css_placeholder(current_distribusi) + editorform.css.data = css_placeholder files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) distribusi_live = UserHelper.is_distribusi_live(current_distribusi) @@ -161,33 +161,33 @@ def RenderEditorTemplate(editorform, current_distribusi): files_uploaded=files_uploaded, distribusi_live=distribusi_live, editorform=editorform, - htmlplaceholder=htmlplaceholder, + html_placeholder=html_placeholder, ) return template -def CssPlaceholder(current_distribusi): - cssplaceholder = "Try out your CSS here" +def get_css_placeholder(current_distribusi): + css_placeholder = "Try out your CSS here" distribusi = Distribusis.query.filter_by( distribusiname=current_distribusi ).first() if distribusi is not None and distribusi.publictheme is not None: - cssplaceholder = GetPublicCssFile(distribusi) + css_placeholder = get_public_css_file(distribusi) else: with open("themes/editor/placeholder.css") as f: - cssplaceholder = f.read() - return cssplaceholder + css_placeholder = f.read() + return css_placeholder -def HtmlPlaceholder(): - htmlplaceholder = "Write some test HTML here" +def get_html_placeholder(): + html_placeholder = "Write some test HTML here" with open("themes/editor/placeholder.html") as f: - htmlplaceholder = f.read() - return htmlplaceholder + html_placeholder = f.read() + return html_placeholder -def GetPublicCssFile(distribusi): - cssplaceholder = "" +def get_public_css_file(distribusi): + css_placeholder = "" publicthemefolder = os.path.join( "themes/publicthemes", distribusi.distribusiname ) @@ -195,5 +195,5 @@ def GetPublicCssFile(distribusi): if filename.endswith(".css"): cssfile = os.path.join(publicthemefolder, filename) with open(cssfile) as f: - cssplaceholder = f.read() - return cssplaceholder + css_placeholder = f.read() + return css_placeholder diff --git a/verse/distribusikan/distribusiselector.py b/verse/distribusikan/distribusi_selector.py similarity index 81% rename from verse/distribusikan/distribusiselector.py rename to verse/distribusikan/distribusi_selector.py index ac0e040..39f46ca 100644 --- a/verse/distribusikan/distribusiselector.py +++ b/verse/distribusikan/distribusi_selector.py @@ -11,7 +11,7 @@ from sqlalchemy.exc import ( ) from app import db -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.publicthemeform import PublicThemeForm from distribusikan.forms.selectorform import SelectorForm @@ -24,49 +24,50 @@ from models.user_model import User from statuspengguna.helper import UserHelper -def DistribusiSelector(): +def distribusi_selector(): uploadform = UploadForm() selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorform.distribusis.choices = DistribusisInfo.user_distribusinames() current_distribusi = UserHelper.current_distribusi() if selectorform.validate_on_submit(): if selectorform.new.data: - SelectNewDistribusi() + select_new_distribusi() if selectorform.describe.data: - return SelectDescribeDistribusi(selectorform.distribusis.data) + return select_describe_distribusi(selectorform.distribusis.data) if selectorform.delete.data: - selectorform = DeleteDistribusi(selectorform.distribusis.data) + selectorform = delete_distribusi(selectorform.distribusis.data) selectorform.distribusis.choices = ( - DistribusisInfo.userdistribusinames() + DistribusisInfo.user_distribusinames() ) if selectorform.update.data: - SelectUpdateDistribusi(selectorform.distribusis.data) + select_update_distribusi(selectorform.distribusis.data) current_distribusi = UserHelper.current_distribusi() - uploadform = AutoFillInUploadForm(uploadform, current_distribusi) + uploadform = auto_fill_in_upload_form(uploadform, current_distribusi) - return RenderDistribusiTemplate( + return render_distribusi_template( selectorform, uploadform, current_distribusi ) -def AutoFillInUploadForm(uploadform, current_distribusi): +def auto_fill_in_upload_form(uploadform, current_distribusi): distribusi = Distribusis.query.filter_by( distribusiname=current_distribusi ).first() uploadform.sitename.data = distribusi.distribusiname uploadform.sitename.render_kw = {"readonly": True} + uploadform.description.data = distribusi.description uploadform.category.data = distribusi.category uploadform.year.data = distribusi.year uploadform.tags.data = distribusi.tags return uploadform -def SelectNewDistribusi(): +def select_new_distribusi(): print("make a new distribusi") - SelectCurrentDistribusi("new") + select_current_distribusi("new") -def SelectDescribeDistribusi(distribusiname): +def select_describe_distribusi(distribusiname): return redirect( url_for( "describer.show_distribusi_files", @@ -75,12 +76,12 @@ def SelectDescribeDistribusi(distribusiname): ) -def SelectUpdateDistribusi(distribusiname): +def select_update_distribusi(distribusiname): print(f"Update this distribusi {distribusiname}") - SelectCurrentDistribusi(distribusiname) + select_current_distribusi(distribusiname) -def DeleteDistribusi(distribusiname): +def delete_distribusi(distribusiname): print(f"delete this distribusi {distribusiname}") selectorform = SelectorForm() try: @@ -114,7 +115,7 @@ def DeleteDistribusi(distribusiname): return selectorform -def SelectCurrentDistribusi(distribusiname): +def select_current_distribusi(distribusiname): if not current_user.is_authenticated: return user = User.query.filter_by(email=current_user.email).first() @@ -143,11 +144,11 @@ def SelectorVisible(): return True -def RenderDistribusiTemplate(selectorform, uploadform, current_distribusi): +def render_distribusi_template(selectorform, uploadform, current_distribusi): distribusiform = DistribusiForm() themeform = ThemeForm() publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) distribusi_live = UserHelper.is_distribusi_live(current_distribusi) diff --git a/verse/distribusikan/distribusiworkflow.py b/verse/distribusikan/distribusi_workflow.py similarity index 78% rename from verse/distribusikan/distribusiworkflow.py rename to verse/distribusikan/distribusi_workflow.py index f728292..0f91425 100644 --- a/verse/distribusikan/distribusiworkflow.py +++ b/verse/distribusikan/distribusi_workflow.py @@ -15,8 +15,8 @@ from sqlalchemy.exc import ( ) from app import db -from distribusikan.distribusiselector import SelectorVisible -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusi_selector import SelectorVisible +from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.publicthemeform import PublicThemeForm from distribusikan.forms.selectorform import SelectorForm @@ -31,7 +31,7 @@ from models.user_model import User from statuspengguna.helper import UserHelper -def DistribusiWorkflow(): +def distribusi_workflow(): distribusiform = DistribusiForm() current_distribusi = UserHelper.current_distribusi() user = User.query.filter_by(email=current_user.email).first() @@ -41,18 +41,18 @@ def DistribusiWorkflow(): if distribusiform.validate_on_submit(): userfolder = os.path.join("stash", distribusi.distribusiname) - cssfile = GetCssFile(distribusi) - UnzipDistribusiFiles(distribusi, userfolder) - CleanUpDistribusiFiles(userfolder) - RunDistribusi(userfolder, cssfile) - SetDistribusiToVisible(distribusi, user) - DeleteCssFile(cssfile) + cssfile = get_css_file(distribusi) + unzip_distribusi_files(distribusi, userfolder) + clean_up_distribusi_files(userfolder) + run_distribusi(userfolder, cssfile) + set_distribusi_to_visible(distribusi, user) + delete_css_file(cssfile) return redirect(url_for("index")) - return RenderDistribusiTemplate(distribusiform, current_distribusi) + return render_distribusi_template(distribusiform, current_distribusi) -def UnzipDistribusiFiles(distribusi, userfolder): +def unzip_distribusi_files(distribusi, userfolder): zipfilename = "{}.zip".format(distribusi.distribusiname) unzipfile = os.path.join(userfolder, zipfilename) @@ -64,12 +64,12 @@ def UnzipDistribusiFiles(distribusi, userfolder): os.remove(os.path.join(userfolder, zipfilename)) -def CleanUpDistribusiFiles(userfolder): +def clean_up_distribusi_files(userfolder): if os.path.exists(userfolder): - RemoveMacFolders(userfolder) + remove_mac_folders(userfolder) -def RemoveMacFolders(path): +def remove_mac_folders(path): for filename in os.listdir(path): fullpath = os.path.join(path, filename) if filename.startswith("."): @@ -80,10 +80,10 @@ def RemoveMacFolders(path): if filename == "__MACOSX": shutil.rmtree(fullpath) if os.path.isdir(fullpath): - RemoveMacFolders(fullpath) + remove_mac_folders(fullpath) -def GetCssFile(distribusi): +def get_css_file(distribusi): cssfile = "" cssfolder = os.path.join("themes/userthemes", distribusi.distribusiname) if os.path.exists(cssfolder): @@ -93,13 +93,13 @@ def GetCssFile(distribusi): return cssfile -def RunDistribusi(userfolder, cssfile): +def run_distribusi(userfolder, cssfile): parser = build_argparser() args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) distribusify(args, userfolder) -def SetDistribusiToVisible(distribusi, user): +def set_distribusi_to_visible(distribusi, user): try: distribusi.visible = True user.currentdistribusi = None @@ -109,18 +109,18 @@ def SetDistribusiToVisible(distribusi, user): flash("Unknown error occured!") -def DeleteCssFile(cssfile): +def delete_css_file(cssfile): if os.path.exists(cssfile): os.remove(cssfile) -def RenderDistribusiTemplate(distribusiform, current_distribusi): +def render_distribusi_template(distribusiform, current_distribusi): uploadform = UploadForm() themeform = ThemeForm() publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorform.distribusis.choices = DistribusisInfo.user_distribusinames() selectorvisible = SelectorVisible() files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) diff --git a/verse/distribusikan/distribusikan.py b/verse/distribusikan/distribusikan.py index 444cb96..870ac47 100644 --- a/verse/distribusikan/distribusikan.py +++ b/verse/distribusikan/distribusikan.py @@ -1,13 +1,13 @@ from flask import Blueprint from flask_login import login_required -from distribusikan.distribusiselector import DistribusiSelector +from distribusikan.distribusi_selector import distribusi_selector # Distribusi Information -from distribusikan.distribusiworkflow import DistribusiWorkflow -from distribusikan.editor import Editor -from distribusikan.themeselector import ThemeSelector -from distribusikan.uploadpage import UploadPage +from distribusikan.distribusi_workflow import distribusi_workflow +from distribusikan.css_editor_page import css_editor_page +from distribusikan.theme_selector import theme_selector +from distribusikan.upload_page import upload_page distribusikan = Blueprint( "distribusikan", @@ -20,28 +20,28 @@ distribusikan = Blueprint( @distribusikan.route("/distribusi", methods=["GET", "POST"]) @login_required def distribusi(): - return DistribusiWorkflow() + return distribusi_workflow() @distribusikan.route("/upload", methods=["POST"]) @login_required def upload(): - return UploadPage() + return upload_page() @distribusikan.route("/theme", methods=["GET", "POST"]) @login_required def theme(): - return ThemeSelector() + return theme_selector() @distribusikan.route("/editor", methods=["GET", "POST"]) @login_required def editor(): - return Editor() + return css_editor_page() @distribusikan.route("/selector", methods=["GET", "POST"]) @login_required def selector(): - return DistribusiSelector() + return distribusi_selector() diff --git a/verse/distribusikan/distribusisinfo.py b/verse/distribusikan/distribusis_info.py similarity index 90% rename from verse/distribusikan/distribusisinfo.py rename to verse/distribusikan/distribusis_info.py index 19ef284..aa614bb 100644 --- a/verse/distribusikan/distribusisinfo.py +++ b/verse/distribusikan/distribusis_info.py @@ -5,14 +5,14 @@ from models.user_model import User class DistribusisInfo: - def userdistribusinames(): + def user_distribusinames(): distribusinames = [] user = User.query.filter_by(email=current_user.email).first() for distribusi in Distribusis.query.filter_by(userid=user.id).all(): distribusinames.append(distribusi.distribusiname) return distribusinames - def publicthemes(): + def public_themes(): publicthemes = [] distribusis = Distribusis.query.filter( Distribusis.publictheme.isnot(None) @@ -27,12 +27,12 @@ made by {user.username}""", publicthemes.append(publictheme) return publicthemes - def visibledistribusis(): + def visible_distribusis(): distribusis = Distribusis.query.filter( Distribusis.visible.isnot(False) ).all() return distribusis - def getuserdistribusis(useremail): + def get_user_distribusis(useremail): user = User.query.filter_by(email=useremail).first() return Distribusis.query.filter_by(userid=user.id).all() diff --git a/verse/distribusikan/forms/uploadform.py b/verse/distribusikan/forms/uploadform.py index 8bec973..f0af89b 100644 --- a/verse/distribusikan/forms/uploadform.py +++ b/verse/distribusikan/forms/uploadform.py @@ -57,17 +57,6 @@ class UploadForm(FlaskForm): ], widget=TextArea(), ) - mdfile = FileField( - "Alternatively upload a markdown file with a description:", - validators=[ - FileAllowed(["md"], "markdown only"), - FileRequired(), - FileSize( - max_size=10485760, - message="markdown file size should be smaller than 10MB", - ), - ], - ) year = SelectField( "Year:", validate_choice=True, diff --git a/verse/distribusikan/templates/distribusikan/distribusi.html b/verse/distribusikan/templates/distribusikan/distribusi.html index e85f04c..38874d5 100644 --- a/verse/distribusikan/templates/distribusikan/distribusi.html +++ b/verse/distribusikan/templates/distribusikan/distribusi.html @@ -20,23 +20,23 @@
{% if selectorvisible %} {% block selector %} - {% include "distribusiworkflow/selector.html" %} + {% include "distribusi_workflow/selector.html" %} {% endblock selector%} {% else %} {% block upload %} - {% include "distribusiworkflow/upload.html" %} + {% include "distribusi_workflow/upload.html" %} {% endblock upload%} {% block theme %} - {% include "distribusiworkflow/theme.html" %} + {% include "distribusi_workflow/theme.html" %} {% endblock theme%} {% block editcss %} - {% include "distribusiworkflow/editcss.html" %} + {% include "distribusi_workflow/editcss.html" %} {% endblock editcss%} {% block launch %} - {% include "distribusiworkflow/launch.html" %} + {% include "distribusi_workflow/launch.html" %} {% endblock launch%} {%endif%}
diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html similarity index 100% rename from verse/distribusikan/templates/distribusikan/distribusiworkflow/editcss.html rename to verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/launch.html similarity index 100% rename from verse/distribusikan/templates/distribusikan/distribusiworkflow/launch.html rename to verse/distribusikan/templates/distribusikan/distribusi_workflow/launch.html diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html similarity index 100% rename from verse/distribusikan/templates/distribusikan/distribusiworkflow/selector.html rename to verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/theme.html similarity index 100% rename from verse/distribusikan/templates/distribusikan/distribusiworkflow/theme.html rename to verse/distribusikan/templates/distribusikan/distribusi_workflow/theme.html diff --git a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/upload.html similarity index 89% rename from verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html rename to verse/distribusikan/templates/distribusikan/distribusi_workflow/upload.html index 38157af..f8a0502 100644 --- a/verse/distribusikan/templates/distribusikan/distribusiworkflow/upload.html +++ b/verse/distribusikan/templates/distribusikan/distribusi_workflow/upload.html @@ -17,13 +17,6 @@
{{ message }}
{% endfor %}
-
- {{ uploadform.mdfile.label }} - {{ uploadform.mdfile }} - {% for message in uploadform.mdfile.errors %} -
{{ message }}
- {% endfor %} -
{{ uploadform.year.label }}
diff --git a/verse/distribusikan/templates/distribusikan/editor.html b/verse/distribusikan/templates/distribusikan/editor.html index b6e39f4..273d3fe 100644 --- a/verse/distribusikan/templates/distribusikan/editor.html +++ b/verse/distribusikan/templates/distribusikan/editor.html @@ -5,7 +5,7 @@
diff --git a/verse/distribusikan/themeselector.py b/verse/distribusikan/theme_selector.py similarity index 83% rename from verse/distribusikan/themeselector.py rename to verse/distribusikan/theme_selector.py index b32a338..30388e4 100644 --- a/verse/distribusikan/themeselector.py +++ b/verse/distribusikan/theme_selector.py @@ -3,7 +3,7 @@ import shutil from flask import render_template -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.publicthemeform import PublicThemeForm from distribusikan.forms.selectorform import SelectorForm @@ -12,36 +12,36 @@ from distribusikan.forms.uploadform import UploadForm from statuspengguna.helper import UserHelper -def ThemeSelector(): +def theme_selector(): themeform = ThemeForm() publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() current_distribusi = UserHelper.current_distribusi() if themeform.validate_on_submit(): copycssfile = os.path.join( "themes", f"{themeform.theme.data}.css", ) - MoveCssToUserFolder(current_distribusi, copycssfile) + move_css_to_user_folder(current_distribusi, copycssfile) if publicthemeform.validate_on_submit(): copycssfile = os.path.join( "themes/publicthemes/", f"{publicthemeform.publicthemes.data}.css", ) - MoveCssToUserFolder(current_distribusi, copycssfile) - return RenderDistribusiTemplate( + move_css_to_user_folder(current_distribusi, copycssfile) + return render_distribusi_template( themeform, publicthemeform, current_distribusi ) -def MoveCssToUserFolder(current_distribusi, copycssfile): +def move_css_to_user_folder(current_distribusi, copycssfile): newcssfolder = os.path.join("themes/userthemes", current_distribusi) if not os.path.exists(newcssfolder): os.mkdir(newcssfolder) shutil.copy(copycssfile, newcssfolder) -def RenderDistribusiTemplate(themeform, publicthemeform, current_distribusi): +def render_distribusi_template(themeform, publicthemeform, current_distribusi): uploadform = UploadForm() distribusiform = DistribusiForm() selectorform = SelectorForm() diff --git a/verse/distribusikan/upload.py b/verse/distribusikan/upload.py index 47a9009..b81e3e6 100644 --- a/verse/distribusikan/upload.py +++ b/verse/distribusikan/upload.py @@ -12,14 +12,14 @@ from sqlalchemy.exc import ( ) from app import db -from distribusikan.distribusiselector import SelectCurrentDistribusi +from distribusikan.distribusi_selector import select_current_distribusi from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User from statuspengguna.helper import UserHelper -def UploadNewDistribusi(uploadfolder): +def upload_new_distribusi(uploadfolder): uploadform = UploadForm() if uploadform.validate_on_submit(): user = User.query.filter_by(email=current_user.email).first() @@ -28,6 +28,7 @@ def UploadNewDistribusi(uploadfolder): distribusiname=uploadform.sitename.data, userid=user.id, category=uploadform.category.data, + description=uploadform.description.data, year=uploadform.year.data, tags=uploadform.tags.data, ) @@ -46,7 +47,7 @@ def UploadNewDistribusi(uploadfolder): uploadform.sitename.errors.append("Something went wrong!") flash("Something went wrong!", "danger") return uploadform - SelectCurrentDistribusi(newdistribusi.distribusiname) + select_current_distribusi(newdistribusi.distribusiname) zipfilename = "{}.zip".format(newdistribusi.distribusiname) zipfile = uploadform.zipfile.data zipfile.save(os.path.join(uploadfolder, zipfilename)) @@ -62,7 +63,7 @@ def UploadNewDistribusi(uploadfolder): return uploadform -def UploadUpdatedFiles(uploadfolder): +def upload_updates_files(uploadfolder): uploadform = UploadForm() if uploadform.validate_on_submit(): try: @@ -71,6 +72,7 @@ def UploadUpdatedFiles(uploadfolder): distribusiname=current_distribusi ).first() distribusi.category = uploadform.category.data + distribusi.description = (uploadform.description.data,) distribusi.year = uploadform.year.data distribusi.tags = uploadform.tags.data distribusi.visible = False diff --git a/verse/distribusikan/uploadpage.py b/verse/distribusikan/upload_page.py similarity index 78% rename from verse/distribusikan/uploadpage.py rename to verse/distribusikan/upload_page.py index 8a500cd..fc3b7d1 100644 --- a/verse/distribusikan/uploadpage.py +++ b/verse/distribusikan/upload_page.py @@ -1,9 +1,9 @@ from flask import render_template from app import APP -from distribusikan.distribusiselector import SelectorVisible -from distribusikan.distribusisinfo import DistribusisInfo -from distribusikan.upload import UploadNewDistribusi, UploadUpdatedFiles +from distribusikan.distribusi_selector import SelectorVisible +from distribusikan.distribusis_info import DistribusisInfo +from distribusikan.upload import upload_new_distribusi, upload_updates_files from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.publicthemeform import PublicThemeForm from distribusikan.forms.selectorform import SelectorForm @@ -13,22 +13,22 @@ from distribusikan.forms.themeform import ThemeForm from statuspengguna.helper import UserHelper -def UploadPage(): +def upload_page(): "render upload page section of distribusi workflow" uploadfolder = APP.config["UPLOAD_FOLDER"] distribusiform = DistribusiForm() themeform = ThemeForm() publicthemeform = PublicThemeForm() - publicthemeform.publicthemes.choices = DistribusisInfo.publicthemes() + publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() selectorform = SelectorForm() - selectorform.distribusis.choices = DistribusisInfo.userdistribusinames() + selectorform.distribusis.choices = DistribusisInfo.user_distribusinames() selectorvisible = SelectorVisible() current_distribusi = UserHelper.current_distribusi() if current_distribusi == "new" or UserHelper.has_distribusi() is False: - uploadform = UploadNewDistribusi(uploadfolder) + uploadform = upload_new_distribusi(uploadfolder) else: - uploadform = UploadUpdatedFiles(uploadfolder) + uploadform = upload_updates_files(uploadfolder) files_uploaded = UserHelper.is_zip_uploaded(uploadform.sitename.data) distribusi_live = UserHelper.is_distribusi_live(current_distribusi) diff --git a/verse/models/distribusi_model.py b/verse/models/distribusi_model.py index d8f114e..dd9f040 100644 --- a/verse/models/distribusi_model.py +++ b/verse/models/distribusi_model.py @@ -11,6 +11,7 @@ class Distribusis(db.Model): userid = db.Column(db.Integer, db.ForeignKey("users.id")) category = db.Column(db.String(500), nullable=True, unique=False) year = db.Column(db.String(9), nullable=True, unique=False) + description = db.Column(db.String(32000), nullable=True, unique=False) tags = db.Column(db.String(500), nullable=True, unique=False) publictheme = db.Column(db.String(300), unique=True, nullable=True) visible = db.Column(db.Boolean, default=False) diff --git a/verse/start.py b/verse/start.py index 7deb7e5..7391dcb 100644 --- a/verse/start.py +++ b/verse/start.py @@ -18,7 +18,7 @@ from admin_page.admin_page import admin_page from app import create_app, login_manager, db from describer.describe_files import describer from distribusikan.distribusikan import distribusikan -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.uploadform import UploadForm from models.distribusi_model import Distribusis from models.user_model import User @@ -34,7 +34,7 @@ APP.register_blueprint(describer, url_prefix="/describer") APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") -APP.register_blueprint (admin_page, url_prefix="/admin") +APP.register_blueprint(admin_page, url_prefix="/admin") APP.register_blueprint(distribusikan) @@ -48,7 +48,7 @@ def session_handler(): def index(): UserHelper.reset_user_state() uploadform = UploadForm() - distribusis = DistribusisInfo.visibledistribusis() + distribusis = DistribusisInfo.visible_distribusis() distribusisindex = {} for distribusi in distribusis: user = User.query.filter_by(id=distribusi.userid).first() diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py index a8b26bd..5605bd9 100644 --- a/verse/statuspengguna/helper.py +++ b/verse/statuspengguna/helper.py @@ -10,7 +10,7 @@ from sqlalchemy.exc import ( ) from app import db -from distribusikan.distribusisinfo import DistribusisInfo +from distribusikan.distribusis_info import DistribusisInfo from models.distribusi_model import Distribusis from models.user_model import User @@ -76,7 +76,7 @@ class UserHelper: def distribusi_limit_reached(): user = User.query.filter_by(email=current_user.email).first() - distribusiamount = len(DistribusisInfo.getuserdistribusis(user.email)) + distribusiamount = len(DistribusisInfo.get_user_distribusis(user.email)) if distribusiamount > 19: print("user already has 20 distribusis") return True -- 2.39.2 From 03792eadebf5aefa2e95e5f43c14a728f6d73a2b Mon Sep 17 00:00:00 2001 From: crunk Date: Mon, 17 Jun 2024 23:06:51 +0200 Subject: [PATCH 32/49] further working on describer and fixed found errors --- verse/distribusikan/add_files_to_describer.py | 68 +++++++++++++++++++ verse/distribusikan/distribusi_selector.py | 10 +-- verse/distribusikan/distribusi_workflow.py | 6 +- verse/distribusikan/upload_page.py | 4 +- verse/models/distribusi_file_model.py | 2 +- 5 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 verse/distribusikan/add_files_to_describer.py diff --git a/verse/distribusikan/add_files_to_describer.py b/verse/distribusikan/add_files_to_describer.py new file mode 100644 index 0000000..3ce1eb5 --- /dev/null +++ b/verse/distribusikan/add_files_to_describer.py @@ -0,0 +1,68 @@ +import os + +import magic +from distribusi.mappings import FILE_TYPES +from models.distribusi_model import Distribusis +from models.distribusi_file_model import DistribusiFiles +from app import create_app, get_app, db +from sqlalchemy.exc import ( + DatabaseError, + DataError, + IntegrityError, + InterfaceError, + InvalidRequestError, +) + +MIME_TYPE = magic.Magic(mime=True) + + +def _distribusi_file_with_type(distribusi, full_path): + mime = MIME_TYPE.from_file(full_path) + type_, subtype = mime.split("/") + if type_ in FILE_TYPES: + _add_distribusi_file_to_db(distribusi, full_path, type_) + + +def _get_distribusi_from_path(path): + distribusi = Distribusis.query.filter_by(distribusiname=path).first() + return distribusi + + +def _add_distribusi_file_to_db(distribusi, full_path, type): + app = get_app() + app.logger.info(f"adding file to database: {full_path} type: {type}") + try: + new_distribusi_file = DistribusiFiles( + path=full_path, + type=type, + distribusi=distribusi.id, + ) + db.session.add(new_distribusi_file) + db.session.commit() + return + except InvalidRequestError: + db.session.rollback() + app.logger.error("Something went wrong!") + except IntegrityError: + db.session.rollback() + app.logger.error("File %s already exists!", full_path) + except DataError: + db.session.rollback() + app.logger.error("%s Invalid Entry", full_path) + except InterfaceError: + db.session.rollback() + app.logger.error("Error connecting to the database") + except DatabaseError: + db.session.rollback() + app.logger.error("Error connecting to the database") + + +def add_distribusi_files_to_db(path): + distribusi = _get_distribusi_from_path(path) + path = os.path.join("stash", path) + for root, dirs, files in os.walk(path, topdown=True): + files = list(filter(lambda f: not f.startswith("."), files)) + files = list(filter(lambda f: not f.endswith(".html"), files)) + for file in files: + full_path = os.path.join(root, file) + _distribusi_file_with_type(distribusi, full_path) diff --git a/verse/distribusikan/distribusi_selector.py b/verse/distribusikan/distribusi_selector.py index 39f46ca..f42bd2e 100644 --- a/verse/distribusikan/distribusi_selector.py +++ b/verse/distribusikan/distribusi_selector.py @@ -127,17 +127,17 @@ def select_current_distribusi(distribusiname): flash("An error occured !", "danger") -def DistribusiSelected(): +def distribusi_selected(): user = User.query.filter_by(email=current_user.email).first() if user.currentdistribusi is None: return False return True -def SelectorVisible(): +def selector_visible(): has_distribusi = UserHelper.has_distribusi() - distribusi_selected = DistribusiSelected() - if distribusi_selected: + is_distribusi_selected = distribusi_selected() + if is_distribusi_selected: return False if not has_distribusi: return False @@ -155,7 +155,7 @@ def render_distribusi_template(selectorform, uploadform, current_distribusi): # because the user has chosen to update his distribusi, we assume # no selected css. css_selected = False - selectorvisible = SelectorVisible() + selectorvisible = selector_visible() limit_reached = UserHelper.distribusi_limit_reached() template = render_template( "distribusi.html", diff --git a/verse/distribusikan/distribusi_workflow.py b/verse/distribusikan/distribusi_workflow.py index 0f91425..43b6666 100644 --- a/verse/distribusikan/distribusi_workflow.py +++ b/verse/distribusikan/distribusi_workflow.py @@ -15,7 +15,8 @@ from sqlalchemy.exc import ( ) from app import db -from distribusikan.distribusi_selector import SelectorVisible +from distribusikan.add_files_to_describer import add_distribusi_files_to_db +from distribusikan.distribusi_selector import selector_visible from distribusikan.distribusis_info import DistribusisInfo from distribusikan.forms.distribusiform import DistribusiForm from distribusikan.forms.publicthemeform import PublicThemeForm @@ -44,6 +45,7 @@ def distribusi_workflow(): cssfile = get_css_file(distribusi) unzip_distribusi_files(distribusi, userfolder) clean_up_distribusi_files(userfolder) + add_distribusi_files_to_db(distribusi.distribusiname) run_distribusi(userfolder, cssfile) set_distribusi_to_visible(distribusi, user) delete_css_file(cssfile) @@ -121,7 +123,7 @@ def render_distribusi_template(distribusiform, current_distribusi): publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() selectorform = SelectorForm() selectorform.distribusis.choices = DistribusisInfo.user_distribusinames() - selectorvisible = SelectorVisible() + selectorvisible = selector_visible() files_uploaded = UserHelper.is_zip_uploaded(current_distribusi) distribusi_live = UserHelper.is_distribusi_live(current_distribusi) diff --git a/verse/distribusikan/upload_page.py b/verse/distribusikan/upload_page.py index fc3b7d1..06070f3 100644 --- a/verse/distribusikan/upload_page.py +++ b/verse/distribusikan/upload_page.py @@ -1,7 +1,7 @@ from flask import render_template from app import APP -from distribusikan.distribusi_selector import SelectorVisible +from distribusikan.distribusi_selector import selector_visible from distribusikan.distribusis_info import DistribusisInfo from distribusikan.upload import upload_new_distribusi, upload_updates_files from distribusikan.forms.distribusiform import DistribusiForm @@ -22,7 +22,7 @@ def upload_page(): publicthemeform.publicthemes.choices = DistribusisInfo.public_themes() selectorform = SelectorForm() selectorform.distribusis.choices = DistribusisInfo.user_distribusinames() - selectorvisible = SelectorVisible() + selectorvisible = selector_visible() current_distribusi = UserHelper.current_distribusi() if current_distribusi == "new" or UserHelper.has_distribusi() is False: diff --git a/verse/models/distribusi_file_model.py b/verse/models/distribusi_file_model.py index 23003b1..edddc71 100644 --- a/verse/models/distribusi_file_model.py +++ b/verse/models/distribusi_file_model.py @@ -9,7 +9,7 @@ class DistribusiFiles(db.Model): id = db.Column(db.Integer, primary_key=True) type = db.Column(db.String(100), nullable=True, unique=False) distribusi = db.Column(db.Integer, db.ForeignKey("distribusis.id")) - path = db.Column(db.String(4096), nullable=True, unique=False) + path = db.Column(db.String(4096), nullable=True, unique=True) alttext = db.Column(db.String(255), nullable=True, unique=False) tags = db.Column(db.String(500), nullable=True, unique=False) description = db.Column(db.String(4096), nullable=True, unique=False) -- 2.39.2 From 1c9af6e6e67cde1bc9222fe72ff6a2cdcf7bff95 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 11:02:17 +0200 Subject: [PATCH 33/49] don't add files again when updating distribusi --- verse/distribusikan/add_files_to_describer.py | 6 +- verse/file_crawler.py | 73 ------------------- verse/migrations/env.py | 20 +++-- 3 files changed, 14 insertions(+), 85 deletions(-) delete mode 100644 verse/file_crawler.py diff --git a/verse/distribusikan/add_files_to_describer.py b/verse/distribusikan/add_files_to_describer.py index 3ce1eb5..5310e90 100644 --- a/verse/distribusikan/add_files_to_describer.py +++ b/verse/distribusikan/add_files_to_describer.py @@ -65,4 +65,8 @@ def add_distribusi_files_to_db(path): files = list(filter(lambda f: not f.endswith(".html"), files)) for file in files: full_path = os.path.join(root, file) - _distribusi_file_with_type(distribusi, full_path) + distribusi_file = DistribusiFiles.query.filter_by( + path=full_path + ).first() + if distribusi_file is None: + _distribusi_file_with_type(distribusi, full_path) diff --git a/verse/file_crawler.py b/verse/file_crawler.py deleted file mode 100644 index ff57d14..0000000 --- a/verse/file_crawler.py +++ /dev/null @@ -1,73 +0,0 @@ -import os - -import magic -from distribusi.mappings import FILE_TYPES -from models.distribusi_model import Distribusis -from models.distribusi_file_model import DistribusiFiles -from app import create_app, get_app, db -from sqlalchemy.exc import ( - DatabaseError, - DataError, - IntegrityError, - InterfaceError, - InvalidRequestError, -) - -MIME_TYPE = magic.Magic(mime=True) - - -def _distribusi_file_with_type(distribusi, full_path): - mime = MIME_TYPE.from_file(full_path) - type_, subtype = mime.split("/") - if type_ in FILE_TYPES: - _add_distribusi_file_to_db(distribusi, full_path, type_) - - -def _get_distribusi_from_path(path): - distribusi = Distribusis.query.filter_by(distribusiname=path).first() - return distribusi - - -def _add_distribusi_file_to_db(distribusi, full_path, type): - app = get_app() - print(f"adding file to database: {full_path} type: {type}") - try: - new_distribusi_file = DistribusiFiles( - path=full_path, - type=type, - distribusi=distribusi.id, - ) - db.session.add(new_distribusi_file) - db.session.commit() - return - except InvalidRequestError: - db.session.rollback() - app.logger.error("Something went wrong!") - except IntegrityError: - db.session.rollback() - app.logger.error("File %s already exists!", full_path) - except DataError: - db.session.rollback() - app.logger.error("%s Invalid Entry", full_path) - except InterfaceError: - db.session.rollback() - app.logger.error("Error connecting to the database") - except DatabaseError: - db.session.rollback() - app.logger.error("Error connecting to the database") - - -def add_distribusi_files(path): - app = create_app() - with app.app_context(): - distribusi = _get_distribusi_from_path(path) - path = os.path.join("stash", path) - for root, dirs, files in os.walk(path, topdown=True): - files = list(filter(lambda f: not f.startswith("."), files)) - files = list(filter(lambda f: not f.endswith(".html"), files)) - for file in files: - full_path = os.path.join(root, file) - _distribusi_file_with_type(distribusi, full_path) - - -add_distribusi_files("2018-12-WttF-Mastodon-and-the-Fediverse") diff --git a/verse/migrations/env.py b/verse/migrations/env.py index 68a0091..68feded 100644 --- a/verse/migrations/env.py +++ b/verse/migrations/env.py @@ -14,19 +14,17 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger("alembic.env") +logger = logging.getLogger('alembic.env') # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - "sqlalchemy.url", - str(current_app.extensions["migrate"].db.get_engine().url).replace( - "%", "%%" - ), -) -target_metadata = current_app.extensions["migrate"].db.metadata + 'sqlalchemy.url', + str(current_app.extensions['migrate'].db.get_engine().url).replace( + '%', '%%')) +target_metadata = current_app.extensions['migrate'].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -67,20 +65,20 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, "autogenerate", False): + if getattr(config.cmd_opts, 'autogenerate', False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info("No changes in schema detected.") + logger.info('No changes in schema detected.') - connectable = current_app.extensions["migrate"].db.get_engine() + connectable = current_app.extensions['migrate'].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions["migrate"].configure_args, + **current_app.extensions['migrate'].configure_args ) with context.begin_transaction(): -- 2.39.2 From b7310c837b39afedab74b7f776825eed62f9dc03 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 11:30:11 +0200 Subject: [PATCH 34/49] categories same as current hugo work in progress page --- verse/settings.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/verse/settings.toml b/verse/settings.toml index 1206e1d..86ee959 100644 --- a/verse/settings.toml +++ b/verse/settings.toml @@ -1,4 +1,7 @@ title = "Varia Archive X Distribusi-Verse" -categories = ["event","gathering","workgroup","talk","music event"] +categories = [ "article", "booklaunch", "broadcast", "curriculum", "game", +"gathering", "lecture", "opencall", "party", "performance", "presentation", +"publication", "report", "screening", "statement", "workgroup", "worksession", +"workshop"] start_time = 2017-11-03 end_time = 2025-12-31 -- 2.39.2 From e5d8da25686393a5352c965eb93283b1fd0679a0 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 14:19:38 +0200 Subject: [PATCH 35/49] adding exif data start --- verse/describer/describe_files.py | 20 ++++++++++++++++++++ verse/describer/forms/redistribusi_form.py | 8 ++++++++ 2 files changed, 28 insertions(+) create mode 100644 verse/describer/forms/redistribusi_form.py diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 93239fa..b7f7ea8 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -14,6 +14,7 @@ from sqlalchemy.exc import ( InterfaceError, InvalidRequestError, ) +from exif import Image from app import db from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles @@ -51,6 +52,7 @@ def describe_file(file_id): distribusi_file.id, distribusi_file.path, distribusi_file.type ) save_described_file_to_db(describe_form, distribusi_file) + add_exif_to_image(describe_form, distribusi_file) distribusi = Distribusis.query.filter_by( id=distribusi_file.distribusi ).first() @@ -110,3 +112,21 @@ def save_described_file_to_db(describe_form, distribusi_file): db.session.rollback() describe_form.save.errors.append("Error connecting to the database") flash("Error connecting to the database", "danger") + + +def add_exif_to_image(describe_form, distribusi_file): + if not describe_form.alttext.data: + return + if distribusi_file.type != "image": + return + updating_image = bytearray() + with open(distribusi_file.path, "rb") as image_file: + image_bytes = image_file.read() + updating_image = Image(image_bytes) + updating_image.communication = describe_form.alttext.data + with open(distribusi_file.path, "wb") as new_image_file: + new_image_file.write(updating_image.get_file()) + print( + f"{updating_image.communication} is set from form data: {describe_form.alttext.data}" + ) + return diff --git a/verse/describer/forms/redistribusi_form.py b/verse/describer/forms/redistribusi_form.py new file mode 100644 index 0000000..71c5bd8 --- /dev/null +++ b/verse/describer/forms/redistribusi_form.py @@ -0,0 +1,8 @@ +from flask_wtf import FlaskForm +from wtforms import SubmitField + + +class DistribusiForm(FlaskForm): + """Distribusi class to launch your distribusi website""" + + submit = SubmitField("Re-Distribusi!") -- 2.39.2 From c8b1171cadf69daca465014392ddf230b8ba72d0 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 14:42:30 +0200 Subject: [PATCH 36/49] redistribusi for adding exif --- verse/describer/describe_files.py | 21 ++++++++++++++++++- verse/describer/forms/redistribusi_form.py | 4 ++-- .../templates/describe_files/describe.html | 3 +++ .../describe_files/redistribusi.html | 14 +++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 verse/describer/templates/describe_files/redistribusi.html diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index b7f7ea8..a3106ee 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -19,7 +19,7 @@ from app import db from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from describer.forms.describe_files_form import DescribeFilesForm - +from describer.forms.redistribusi_form import ReDistribusiForm describer = Blueprint( "describer", @@ -37,9 +37,28 @@ def show_distribusi_files(distribusiname): distribusi = Distribusis.query.filter_by( distribusiname=distribusiname ).first() + redistribusi_form = ReDistribusiForm() + distribusi_file_forms = get_distribusi_file_forms(distribusi.id) + return render_template( + "describe.html", + distribusiname=distribusiname, + redistribusi_form=redistribusi_form, + distribusi_file_forms=distribusi_file_forms, + ) + + +@describer.route("/redistribusi/") +@login_required +def re_distribusi_files(distribusiname): + distribusi = Distribusis.query.filter_by( + distribusiname=distribusiname + ).first() + redistribusi_form = ReDistribusiForm() distribusi_file_forms = get_distribusi_file_forms(distribusi.id) return render_template( "describe.html", + distribusiname=distribusiname, + redistribusi_form=redistribusi_form, distribusi_file_forms=distribusi_file_forms, ) diff --git a/verse/describer/forms/redistribusi_form.py b/verse/describer/forms/redistribusi_form.py index 71c5bd8..1d7676a 100644 --- a/verse/describer/forms/redistribusi_form.py +++ b/verse/describer/forms/redistribusi_form.py @@ -2,7 +2,7 @@ from flask_wtf import FlaskForm from wtforms import SubmitField -class DistribusiForm(FlaskForm): - """Distribusi class to launch your distribusi website""" +class ReDistribusiForm(FlaskForm): + """Re-Distribusi form class to re-distrusi with desribed files""" submit = SubmitField("Re-Distribusi!") diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 7616461..9267722 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -70,5 +70,8 @@
{% endfor%}
+ {% block redistribusi %} + {% include "redistribusi.html" %} + {% endblock redistribusi%}
{% endblock %} diff --git a/verse/describer/templates/describe_files/redistribusi.html b/verse/describer/templates/describe_files/redistribusi.html new file mode 100644 index 0000000..9269d45 --- /dev/null +++ b/verse/describer/templates/describe_files/redistribusi.html @@ -0,0 +1,14 @@ +
+

Run distribusi again after describing your files.Distribusi will run again and add your alttext and descriptions. +

+ + {{ redistribusi_form.csrf_token }} +
+ {{ redistribusi_form.submit.label }} + {{ redistribusi_form.submit }} + {% for message in redistribusi_form.submit.errors %} +
{{ message }}
+ {% endfor %} +
+ +
-- 2.39.2 From ad1a7108036da97a7a4f81e8b4fb958d4e08dd08 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 16:59:51 +0200 Subject: [PATCH 37/49] more modular css --- verse/describer/static/css/describer.css | 22 ++ .../templates/describe_files/describe.html | 9 +- .../static/css/distribusikan.css | 29 ++ .../{ => distribusikan}/static/css/editor.css | 6 +- .../templates/distribusikan/distribusi.html | 1 + .../templates/distribusikan/editor.html | 2 +- verse/start.py | 2 +- verse/static/css/dropdown.css | 4 +- verse/static/css/selector.css | 8 +- verse/static/css/style.css | 104 +------ verse/statuspengguna/static/css/dropdown.css | 69 ----- verse/statuspengguna/static/css/editor.css | 50 ---- verse/statuspengguna/static/css/login.css | 22 ++ verse/statuspengguna/static/css/selector.css | 53 ---- verse/statuspengguna/static/css/style.css | 281 ------------------ verse/statuspengguna/static/icons/about.txt | 6 - .../static/icons/android-chrome-192x192.png | Bin 5479 -> 0 bytes .../static/icons/android-chrome-512x512.png | Bin 12656 -> 0 bytes .../static/icons/apple-touch-icon.png | Bin 4441 -> 0 bytes .../static/icons/favicon-16x16.png | Bin 322 -> 0 bytes .../static/icons/favicon-32x32.png | Bin 666 -> 0 bytes verse/statuspengguna/static/icons/favicon.ico | Bin 15406 -> 0 bytes .../static/icons/site.webmanifest | 1 - verse/statuspengguna/static/js/dropdown.js | 92 ------ .../statuspengguna/static/js/editorupdate.js | 19 -- verse/statuspengguna/static/js/script.js | 25 -- verse/statuspengguna/static/svg/arrow_1.svg | 75 ----- verse/statuspengguna/static/svg/arrow_2.svg | 12 - verse/statuspengguna/static/svg/arrow_3.svg | 12 - .../statuspengguna/forgotpassword.html | 5 +- .../templates/statuspengguna/login.html | 1 + .../templates/statuspengguna/register.html | 1 + .../statuspengguna/resetpassword.html | 1 + verse/templates/base/help.html | 2 +- verse/templates/base/index.html | 2 +- 35 files changed, 111 insertions(+), 805 deletions(-) create mode 100644 verse/describer/static/css/describer.css create mode 100644 verse/distribusikan/static/css/distribusikan.css rename verse/{ => distribusikan}/static/css/editor.css (89%) delete mode 100644 verse/statuspengguna/static/css/dropdown.css delete mode 100644 verse/statuspengguna/static/css/editor.css create mode 100644 verse/statuspengguna/static/css/login.css delete mode 100644 verse/statuspengguna/static/css/selector.css delete mode 100644 verse/statuspengguna/static/css/style.css delete mode 100644 verse/statuspengguna/static/icons/about.txt delete mode 100644 verse/statuspengguna/static/icons/android-chrome-192x192.png delete mode 100644 verse/statuspengguna/static/icons/android-chrome-512x512.png delete mode 100644 verse/statuspengguna/static/icons/apple-touch-icon.png delete mode 100644 verse/statuspengguna/static/icons/favicon-16x16.png delete mode 100644 verse/statuspengguna/static/icons/favicon-32x32.png delete mode 100644 verse/statuspengguna/static/icons/favicon.ico delete mode 100644 verse/statuspengguna/static/icons/site.webmanifest delete mode 100644 verse/statuspengguna/static/js/dropdown.js delete mode 100644 verse/statuspengguna/static/js/editorupdate.js delete mode 100644 verse/statuspengguna/static/js/script.js delete mode 100644 verse/statuspengguna/static/svg/arrow_1.svg delete mode 100644 verse/statuspengguna/static/svg/arrow_2.svg delete mode 100644 verse/statuspengguna/static/svg/arrow_3.svg diff --git a/verse/describer/static/css/describer.css b/verse/describer/static/css/describer.css new file mode 100644 index 0000000..fcf1e9a --- /dev/null +++ b/verse/describer/static/css/describer.css @@ -0,0 +1,22 @@ +.redistribusi { + position: sticky; + position: -webkit-sticky; /* Safari */ + top: 1em; + width: 15em; + border-style: outset; +} + +.distribusi_file { + margin-top: 1em; + padding: 0.5em; + width: 45em; + background-color:#fdfdfd; + text-decoration: none; + scroll-behavior: smooth; + border-style: outset; +} + +.distribusi_file > img, video { + max-width: 100%; + max-height: 100%; +} diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 9267722..5b2dbc9 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -3,7 +3,7 @@
{% if current_user.is_authenticated %} @@ -27,6 +27,9 @@
+ {% block redistribusi %} + {% include "redistribusi.html" %} + {% endblock redistribusi%}
{% for id, describe_form in distribusi_file_forms.items() %}
@@ -70,8 +73,6 @@
{% endfor%}
- {% block redistribusi %} - {% include "redistribusi.html" %} - {% endblock redistribusi%}
+ {% endblock %} diff --git a/verse/distribusikan/static/css/distribusikan.css b/verse/distribusikan/static/css/distribusikan.css new file mode 100644 index 0000000..55a5302 --- /dev/null +++ b/verse/distribusikan/static/css/distribusikan.css @@ -0,0 +1,29 @@ +#publicthemes > ul { + max-height: 20em; + overflow: auto; +} + +#publicthemes > ul > li{ + word-break: break-all; +} + +.workflow{ + margin-top: 1em; + padding: 0.5em; + background-color:#fdfdfd; + text-decoration: none; + scroll-behavior: smooth; + border-style: outset; +} + +.workflow > p { + padding-left: 1em; +} + +.workflow > h2 { + padding-left: 0.4em;; +} + +.workflow input{ + max-width: 20em; +} diff --git a/verse/static/css/editor.css b/verse/distribusikan/static/css/editor.css similarity index 89% rename from verse/static/css/editor.css rename to verse/distribusikan/static/css/editor.css index d087622..46c6e86 100644 --- a/verse/static/css/editor.css +++ b/verse/distribusikan/static/css/editor.css @@ -5,7 +5,7 @@ } .editarea { width: 30%; - border: 3px solid #E0B0FF; + border: 3px solid #9de457; border-style: outset; margin-right: 1em; margin-left: 0; @@ -31,7 +31,7 @@ textarea { height: 100%; box-sizing: border-box; min-height: 250px; - background: #E0B0FF; + background: #9de457; outline: none; font-family: Courier, sans-serif; font-size: 16px; @@ -45,6 +45,6 @@ iframe { height: 30em; } #html { - background-color: #60337F; + background-color: #9de457; color: lightgrey; } diff --git a/verse/distribusikan/templates/distribusikan/distribusi.html b/verse/distribusikan/templates/distribusikan/distribusi.html index 38874d5..1e9c563 100644 --- a/verse/distribusikan/templates/distribusikan/distribusi.html +++ b/verse/distribusikan/templates/distribusikan/distribusi.html @@ -43,4 +43,5 @@ {% if css_selected %} {% endif %} + {% endblock main %} diff --git a/verse/distribusikan/templates/distribusikan/editor.html b/verse/distribusikan/templates/distribusikan/editor.html index 273d3fe..7ed5b84 100644 --- a/verse/distribusikan/templates/distribusikan/editor.html +++ b/verse/distribusikan/templates/distribusikan/editor.html @@ -54,6 +54,6 @@ - + {% endblock main %} diff --git a/verse/start.py b/verse/start.py index 7391dcb..75de5be 100644 --- a/verse/start.py +++ b/verse/start.py @@ -35,7 +35,7 @@ APP.register_blueprint(login_section, url_prefix="/login") APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(admin_page, url_prefix="/admin") -APP.register_blueprint(distribusikan) +APP.register_blueprint(distribusikan, url_prefix="/distribusikan") @APP.before_request diff --git a/verse/static/css/dropdown.css b/verse/static/css/dropdown.css index 07509d5..6005155 100644 --- a/verse/static/css/dropdown.css +++ b/verse/static/css/dropdown.css @@ -2,7 +2,7 @@ /* for sorting on year and category */ button { - background-color: #E0B0FF; + background-color: #9de457; text-decoration: none; border: none; } @@ -26,7 +26,7 @@ button { .dropdown-content { display: none; position: absolute; - background-color: #E0B0FF; + background-color: #9de457; min-width: 120px; border: 2px solid; z-index: 1; diff --git a/verse/static/css/selector.css b/verse/static/css/selector.css index a500a61..0f9ec0c 100644 --- a/verse/static/css/selector.css +++ b/verse/static/css/selector.css @@ -4,7 +4,7 @@ max-width: 20em; position: relative; border: none; - background: #E0B0FF; + background: #9de457; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; @@ -18,7 +18,7 @@ max-width: 20em; border: none; box-shadow: none; - background-color: #E0B0FF; + background-color: #9de457; background-image: none; -webkit-appearance: none; -moz-appearance: none; @@ -41,7 +41,7 @@ } select.selector option{ color: white; - background-color: #60337F; + background-color: #9de457; padding: 0 10px; } @@ -49,5 +49,5 @@ select.selector option{ outline: none; } .selector-style select option:hover { - background: #60337F; + background: #9de457; } diff --git a/verse/static/css/style.css b/verse/static/css/style.css index 7c6a1b5..1f656a2 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -3,54 +3,13 @@ body font-family: monospace, monospace; font-size: 15px; background-color: #fdfdfd; - color:#29d148; + color:#091411; word-wrap: break-word; line-height: 1.1; } -div#login{ - width: 30%; - margin-left: auto; - margin-right: auto; - background-color:#fdfdfd; - text-decoration: none; -} - -div#login form { - width: 24em; - margin: 0 auto; - padding-left: 15%; - padding-right: 15%; -} - -input[type=text], input[type=password], input[type=file] { - color: #C397DF; - width: 18em; - max-width: 18em; - background-color: #fdfdfd; - border: 1px solid #E0B0FF; -} -.workflow{ - margin-top: 1em; - padding: 0.5em; - background-color:#fdfdfd; - text-decoration: none; - scroll-behavior: smooth; - border-style: outset; -} -.workflow > p { - padding-left: 1em; -} -.workflow > h2 { - padding-left: 0.4em;; -} - -.workflow input{ - max-width: 20em; -} - #mainworkflow { width: 40em; @@ -85,13 +44,13 @@ div#buttons{ div#buttons .distribusi input{ border: none; - background: #fff600; + background: #9de457; text-decoration: none; margin: 0.2em; } div#buttons .distribusi input:hover{ background: #ffbf00; - + color: #6df2cc; } fieldset.required { border: none; @@ -104,21 +63,15 @@ fieldset.required > ul { fieldset.required > ul > li{ list-style-type: none; } + fieldset.tagfield > input { width: 100%; max-width: 100%; } -#publicthemes > ul { - max-height: 20em; - overflow: auto; -} -#publicthemes > ul > li{ - word-break: break-all; -} input { border: none; - background: #E0B0FF; + background: #9de457; text-decoration: none; text-overflow: ellipsis; white-space: nowrap; @@ -127,7 +80,8 @@ input { } input:hover { - background: #60337F; + background: #ffbf00; + color: #6df2cc; } input[type="submit"]:disabled:hover, @@ -147,26 +101,11 @@ input[type="submit"]:disabled:focus { background-color: #F92020; } -#update { +#update, #describe { color: black; background-color: #62b264; } -/* unvisited link */ -a:link { - color: #fff600; -} - -/* visited link */ -a:visited { - color: #d28cff; -} - -/* mouse over link */ -a:hover { - color: #60337F; -} - /* selected link */ a:active { color: white; @@ -177,21 +116,6 @@ a:active { content: "$ "; } -.distribusi_file { - margin-top: 1em; - padding: 0.5em; - width: 45em; - background-color:#fdfdfd; - text-decoration: none; - scroll-behavior: smooth; - border-style: outset; -} - -.distribusi_file > img, video { - max-width: 100%; - max-height: 100%; -} - @media (prefers-reduced-motion: no-preference) { @keyframes flash { 50% { opacity: 0; } @@ -207,7 +131,7 @@ a:active { white-space: nowrap; animation: reveal 4s linear; text-overflow: "â–ˆ"; - background-color: #2D3039; + background-color: #9de457; } #fancyboi::after { content: "â–ˆ"; @@ -217,7 +141,7 @@ a:active { div.maincontent{ width: 55%; - border: 3px #E0B0FF; + border: 3px #9de457; margin-top: 0.5em; padding: 0.5em; border-style: outset; @@ -256,8 +180,6 @@ div.maincontent{ bottom: 100%; left: 50%; margin-left: -60px; - - /* Fade in tooltip - takes 1 second to go from 0% to 100% opac: */ opacity: 0; transition: opacity 2s; } @@ -272,7 +194,7 @@ div.maincontent{ color: black; padding: 1em; box-sizing: border-box; - background: #E0B0FF; + background: #9de457; outline: none; font-family: Courier, sans-serif; font-size: 16px; @@ -280,11 +202,11 @@ div.maincontent{ /* Project colors so far. light -#E0B0FF +#9de457 medium #d28cff dark -#60337F +#9de457 background dark #2D3039 diff --git a/verse/statuspengguna/static/css/dropdown.css b/verse/statuspengguna/static/css/dropdown.css deleted file mode 100644 index 07509d5..0000000 --- a/verse/statuspengguna/static/css/dropdown.css +++ /dev/null @@ -1,69 +0,0 @@ -/* Dropdown Button */ -/* for sorting on year and category -*/ -button { - background-color: #E0B0FF; - text-decoration: none; - border: none; -} -.filter { - display: none; -} - -.activebtn { - background-color: #62b264; -} - -.show { - display: block; -} -.dropdown { - position: relative; - display: inline-block; -} - -/* Dropdown Content (Hidden by Default) */ -.dropdown-content { - display: none; - position: absolute; - background-color: #E0B0FF; - min-width: 120px; - border: 2px solid; - z-index: 1; - border-style: outset; -} - -/* Links inside the dropdown */ -.dropdown-content button { - color: black; - padding: 6px; - border: none; - min-width: inherit; - text-align: left; - text-decoration: none; - display: block; -} -.dropbtn { - margin-top: 1em; -} -/* Change color of dropdown links on hover */ -.dropdown-content button:hover {background-color: #62b264;} - - -/* Show the dropdown menu on hover */ -.dropdown:hover .dropdown-content {display: block;} - -/* Change the background color of the dropdown button when the dropdown content is shown */ -.dropdown:hover .dropbtn {background-color: #62b264;} - -@media only screen and (min-device-width: 320px) and (max-device-width: 480px) { - .dropdown-content button { - font-size: 0.7em; - } - .container > button { - font-size: 0.7em; - } - .dropdown > button { - font-size: 0.7em; - } -} diff --git a/verse/statuspengguna/static/css/editor.css b/verse/statuspengguna/static/css/editor.css deleted file mode 100644 index d087622..0000000 --- a/verse/statuspengguna/static/css/editor.css +++ /dev/null @@ -1,50 +0,0 @@ -.editareas { - margin: auto; - display: flex; - justify-content: flex-start; -} -.editarea { - width: 30%; - border: 3px solid #E0B0FF; - border-style: outset; - margin-right: 1em; - margin-left: 0; -} - -.editor { - min-width: 35%; -} -.editform { - width: 100%%; - margin: 0 auto; -} -#editorsubmitform { - padding-top: 1em; -} -.required label { - display: block; - padding-bottom: 2px; - width: 100% -} -textarea { - width: 100%; - height: 100%; - box-sizing: border-box; - min-height: 250px; - background: #E0B0FF; - outline: none; - font-family: Courier, sans-serif; - font-size: 16px; -} - -iframe { - bottom: 0; - position: relative; - margin-top: 1em; - width: 100%; - height: 30em; -} -#html { - background-color: #60337F; - color: lightgrey; -} diff --git a/verse/statuspengguna/static/css/login.css b/verse/statuspengguna/static/css/login.css new file mode 100644 index 0000000..74308d0 --- /dev/null +++ b/verse/statuspengguna/static/css/login.css @@ -0,0 +1,22 @@ +div#login{ + width: 30%; + margin-left: auto; + margin-right: auto; + background-color:#fdfdfd; + text-decoration: none; +} + +div#login form { + width: 24em; + margin: 0 auto; + padding-left: 15%; + padding-right: 15%; +} + +input[type=text], input[type=password], input[type=file] { + color: #091411; + width: 18em; + max-width: 18em; + background-color: #fdfdfd; + border: 1px solid #9de457; +} diff --git a/verse/statuspengguna/static/css/selector.css b/verse/statuspengguna/static/css/selector.css deleted file mode 100644 index a500a61..0000000 --- a/verse/statuspengguna/static/css/selector.css +++ /dev/null @@ -1,53 +0,0 @@ -.selector-style { - padding: 0; - width: 20em; - max-width: 20em; - position: relative; - border: none; - background: #E0B0FF; - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - margin: 1px; -} - -.selector-style select { - padding: 0.2em 0.2em; - width: 20em; - max-width: 20em; - border: none; - box-shadow: none; - background-color: #E0B0FF; - background-image: none; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -.selector-style:after { - top: 50%; - left: 95%; - border: solid; - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - border-color: rgba(0, 0, 0, 0); - border-top-color: #000000; - margin-top: -2px; - z-index: 100; -} -select.selector option{ - color: white; - background-color: #60337F; - padding: 0 10px; -} - -.selector-style select:focus { - outline: none; -} -.selector-style select option:hover { - background: #60337F; -} diff --git a/verse/statuspengguna/static/css/style.css b/verse/statuspengguna/static/css/style.css deleted file mode 100644 index fb743fc..0000000 --- a/verse/statuspengguna/static/css/style.css +++ /dev/null @@ -1,281 +0,0 @@ -body -{ - font-family: monospace, monospace; - font-size: 15px; - background-color: #fdfdfd; - color:#29d148; - word-wrap: break-word; - line-height: 1.1; -} - -div#login{ - width: 30%; - margin-left: auto; - margin-right: auto; - background-color:#fdfdfd; - text-decoration: none; -} - -div#login form { - width: 24em; - margin: 0 auto; - padding-left: 15%; - padding-right: 15%; -} - -input[type=text], input[type=password], input[type=file] { - color: #C397DF; - width: 18em; - max-width: 18em; - background-color: #fdfdfd; - border: 1px solid #E0B0FF; -} - -div#upload form { - padding-right: 15%; -} - -.workflow{ - margin-top: 1em; - padding: 0.5em; - padding-left: auto; - padding-right: auto; - width: 31em; - background-color:#fdfdfd; - text-decoration: none; - scroll-behavior: smooth; - border-style: outset; -} -.workflow > p { - padding-left: 1em; -} -.workflow > h2 { - padding-left: 0.4em;; -} - -.workflow input{ - max-width: 20em; -} - -#mainworkflow -{ - width: 30em; - margin:0 auto; -} - -#distribusiverse { - margin-bottom: 11em; -} -#distribusi-index { - padding-left: 1em; -} - -div#buttons{ - position: fixed; - top: 0.5em; - right: 0.5em; - display:flex; - flex-direction: row; - justify-content: center; - align-items: center; -} - -div#buttons .distribusi input{ - border: none; - background: #fff600; - text-decoration: none; - margin: 0.2em; -} -div#buttons .distribusi input:hover{ - background: #ffbf00; - -} -fieldset.required { - border: none; -} - -fieldset.required > ul { - padding-left: 0px; -} - -fieldset.required > ul > li{ - list-style-type: none; -} -fieldset.tagfield > input { - width: 100%; - max-width: 100%; -} -#publicthemes > ul { - max-height: 20em; - overflow: auto; -} -#publicthemes > ul > li{ - word-break: break-all; -} - -input { - border: none; - background: #E0B0FF; - text-decoration: none; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - margin: 0.2em; -} - -input:hover { - background: #60337F; -} - -input[type="submit"]:disabled:hover, -input[type="submit"]:disabled, -input[type="submit"]:disabled:focus { - background-color: #2D3039; - color: #d28cff; -} - -.error { - font-size: 110%; - color: #F92020; -} - -#delete { - color: black; - background-color: #F92020; -} - -#update { - color: black; - background-color: #62b264; -} - - -/* unvisited link */ -a:link { - color: #fff600; -} - -/* visited link */ -a:visited { - color: #d28cff; -} - -/* mouse over link */ -a:hover { - color: #60337F; -} - -/* selected link */ -a:active { - color: white; -} - -/* STOLEN GOODS */ -#fancyboi::before { - content: "$ "; -} - -@media (prefers-reduced-motion: no-preference) { - @keyframes flash { - 50% { opacity: 0; } - } - @keyframes reveal { - from { width: 2em; } /* Width of ::before */ - to { width: 55%; } - } - #fancyboi { - width: 55%; - padding: 0.5em; - overflow: hidden; - white-space: nowrap; - animation: reveal 4s linear; - text-overflow: "â–ˆ"; - background-color: #2D3039; - } - #fancyboi::after { - content: "â–ˆ"; - animation: flash 0.5s step-end infinite; - } -} - -div.maincontent{ - width: 55%; - border: 3px #E0B0FF; - margin-top: 0.5em; - padding: 0.5em; - border-style: outset; -} - -.tags{ - background-color: #000; - color: #fff; - display: inline-block; - padding-left: 4px; - padding-right: 4px; - text-align: center; - margin: 1px; -} - -.searched { - background: #fff600 !important; - color: black !important; -} - -.tooltip { - position: relative; - display: inline-block; - border-bottom: 1px dotted black; -} - -.tooltip .tooltiptext { - visibility: hidden; - width: 120px; - background-color: black; - color: #fff; - text-align: center; - padding: 5px 0; - position: absolute; - z-index: 1; - bottom: 100%; - left: 50%; - margin-left: -60px; - - /* Fade in tooltip - takes 1 second to go from 0% to 100% opac: */ - opacity: 0; - transition: opacity 2s; -} - -.tooltip:hover .tooltiptext { - visibility: visible; - opacity: 1; -} - -.code-example { - width: 100%; - color: black; - padding: 1em; - box-sizing: border-box; - background: #E0B0FF; - outline: none; - font-family: Courier, sans-serif; - font-size: 16px; -} -/* -Project colors so far. -light -#E0B0FF -medium -#d28cff -dark -#60337F - -background dark -#2D3039 - -yellow important -#fff600 - -red: danger -ff5a5a -backgrounds -*/ diff --git a/verse/statuspengguna/static/icons/about.txt b/verse/statuspengguna/static/icons/about.txt deleted file mode 100644 index f6a9f45..0000000 --- a/verse/statuspengguna/static/icons/about.txt +++ /dev/null @@ -1,6 +0,0 @@ -This favicon was generated using the following font: - -- Font Title: Klee One -- Font Author: Copyright 2020 The Klee Project Authors (https://github.com/fontworks-fonts/Klee) -- Font Source: http://fonts.gstatic.com/s/kleeone/v5/LDIxapCLNRc6A8oT4q4AOeekWPrP.ttf -- Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL)) diff --git a/verse/statuspengguna/static/icons/android-chrome-192x192.png b/verse/statuspengguna/static/icons/android-chrome-192x192.png deleted file mode 100644 index 3b958ff2fe8d23b1731a3b4ae5bfedd63de5351d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5479 zcmb7IWmuDM)F1q51O_r<)M!MI7Nj>?Bqk*xrIbhsNOw&d6OcwiLJ)+hbO<7?5)MI1 zLTWICk$a!vr61le@AZDzvupRW``qW8--+M39~c|z(9u9?Kp+sEp04I~;Jcmpp`rku z*T3JT1c4xz^fck7fjJw~Zhy-dIHXBMb%eW+S^|-=f=b zk(BawI-I#XM*6XyE4!7|)$Er3z+Ea)KE6+;BFq@)Em(BHxlb_D?EP@#&7X$_-}D|; zJz30OJ_y@vGM{*^;_L;N#Nkd7ur=Qw;A#0NMEK0v1UQWaY)l2dn+vc(sA1jl$?-qN zF##0Rl$UgGyhO3>=ElDLj3CQw$}@|&gwi$Dye-P)SBI*k5x?KbP%Ji|2#>v;E~)n| z>JVJ;`cr2DD230lim%A@DVCNpMsRT$vcRgobdq#BNGnJ=tyGONpGpC z(jHwM#aD#pn}5q!nEhLw>UAs}(ZDyqM#I=LXm!jgaL!C1v}Pn+)hAS2tJ6uVv%cbf z2s2~LlOHT2e6SFKl z)CZf365}QK^xN?#eYEFF2RDs4bQ7#kA#tt+x*|^8$>1ZAqx-^+1T?4)Wx@RZqn6DF zFV_AZnrIl669>2)HQA@k%)2Mx=zhRWM*WHYtGq5gDhP&H@5ffN=pmdK<1hMQ9=(M! zjzP2n%}0`M3@e}G6^V@qmWhdFAh+x^s)_-3>SndWsSugzf;MHO;Ac+h z*hm_68z?05t*j`>$ITQp|G6C0U4kS*=@$dJ~SdJ*ru0O6eWBk#R@^TYO_T7kem#Z_E{_BUY9 z#7u&1RlFE9E3Iz~Ny1&oTIq9V%}AlPlvHWv1o{rA+Vd;o&g;O=-~mqDB_aB(IMzeM z?pe=UBQ;-){fsu!48?5>H7RLwVsawm?t-K1*=HK@G1^Q0ONy?I=ZI+i-z5JQkK9PeXIe7u*4in>FFA* z#y-o-ji;->KfgPkpE;ay(Hld$;yfHBw+m^WCGi zp!#O&o2M$RO{UlSebuVqs1)LdyG!!2}O5bi(Ta zpu`gGd!ge{(vem-#U6&7)ZaB*?V|=3tN4zqIYl60-x`O}ex8C`I8W3AR6?5(45#Hz z3r(TmjdE~(I6_lHXBWx;?OEnbMP0IM+VjIAo$)Rx)0br6dSjprBh z4hU_5wI7uyRDLNbqa?lEdsqKRX?!rsK4LR$CtFm*#w#3Mh^QiuhGZBgQE=wJjX4)3b*O=;ttp^rpx(r?69u)wmo|? zJ90>?kQKu96LVD2>gF_xk|9T9e;#^mZ#fBm%st|1R=Pm>C}FU7R@hE`>aigeU1Du8 z$J=a^N7VaSj3d3kikG+I^)!}YF5{k|Z;oYK@#-C~ z2i1rvak)jYlC=_P2yR}IIrC|#pX)fJiQxbEfRLy|ZwJyk z+$frO!CODKv3hHKUe`dci=CbU+K>LBvsZO<<)B-p9AY)K?xT`ggXWnD58}E?>p40; z%V>xs?&O=aUYICCPCHi&)A+lMB?WD^6-}5ev}a!x%gRhS%}wA{7OB$~#Cq>{%j703 zEI?c`(^6OsO+Z?tqW%on11lBtYZoG$o;P)|&hlEy&VL<$j`y~tmZrD{_f{|eAm|<7 ztK)c=e^CM-d+;`J)|5Q(F}e)>g?ScP=h}T*C4Fv1nv<8rVdO?2UH1=pu%!ttvas4w zRp@Csi1T(stQZv8yhx?3{F@0u+9@Uq*VJVuCc(Xpu%!iuIGT32xqe>}W61%!AnXW+ zk^SY0qz-L9k$mqZH006N8>%d3Orr4d4xLk6!1hi7I~BDofw>}~Nmz(3Yw#z#lyxzw zclwx>XktaW(mubR$F%jBUZl=J@X@W~0(ONhM{8115T#}H##&B4+qCd`Tkg{3S)^^= z4BHgJ%#``vP?QuTGN!807`c0qs1>LUhD)Vx4t?#~Nm(v(_~d|XJ&LHJb%qvyoy!KI z3t#H|1SZ7C{Y@r7df1D>6hvQ#d1z~qQlw=E<1H=xCI}R;he6?g)Z(VEdZ~`Mrr}EV z8*Pui=9zHb`jynMr~cWle&NcYxd%PDW(0bmqMSdUFo5{h*fdZ-MMKnRk1uI#vSn9+ z$?>6?7denUuTQFnvs};+qB$D|!OOLlXrmWj-J^gg&RlLJCoWrl%xdAt;6+yGOD?VI z83u(#5>;pU)L<6qKdBt}GE*2121D6Wqvh3{@}@9Ec$`WEwkQ;3L$3cexA#U%iTKyu zLy*%>WnY7{Lmy>Hh#~#O(!r0Chs`Y{hpkP{{=L}$ zo7GrNsBiK6JGbw(yKV9^f8V^Y3E?R|x?O>x@w+qHHOEu0OFj#`=yiGMTaqNisB#aB zB}VR2kb5-IMKd`=1olCusd7cOJn3VDzsuYP90yM;NM()gCS9dGB~c;bqI~F>Tl8xW zg`L$6ZT{?&f7yU2IPLZ*YR}+(W{!p$PefJLE5I+;&osOf-gDKgOrtC%l(x>bNq%*b zi72G`(DlI0%&RPDvyas{dn>c;d;!s07C-JbM|V$Z3oUPZ88poUAv=JxI#bX#cZfi3 z)VSe(k9$p9c)ngPHOQLmOp@q?xr1pwwb1hD)ECN-8KoiR8bKl=Kc9#}rNX{CzHJK1 z%+c3rQOPD6n%AP_#t(FkYePSelb;OK|B;^OkyEcT76xC)%NkIw{IlJ1`(X{3i`)I) zB}zZ;j=!tlTA#Qe%gj~Ea`lN(5_CVXOY3Wm$04QkAjcc0yfLOTqu0Biy1N<+e^|7+ zj52Wew+ghybmoc4MVlTiLCN7e)PE%0pW+gz4D7vOdgC0f>gkyuT!36RYq>2UEsz*w zu1`$=PxYUVt#wn~9q(N#?pph|+5BOE#u(gNnd?7n9F0Af&b>>O!DTmqTD4>;4kzL= ztZIET6<<#F$oHG{ORj(No1SrNT+__ydw0!i?D@YVs&V_ge3QGkzT~ee=lol(dKpKx z!*Kb^Ge3C|mvYd!)YbnOCxP&tJcom28p#o!IjpH#xlBiZbjn_zyT!_gVjY zpDcSNjeC=OvSF7E*Zjvq3*kl^jmpLQLd#M>Ey=G^9R3U2*c=@zBa{u0WG#s91%6~L zH~c{wBfYO-c0@1=fF?d{=J*#GbQas=x+w+lC0`k?J;v2D0LlSs_A%Y{k?+dS)fB<3 zZ}dkM0%zWS<2Gb#)}+=!;s9oi=u@sKISUm7K>NcoIuo-dA;NV)HJ?^EfKUtKQg9$$GCLU5@bu5*! zt$;q^#tq1w!C>TapyGbE-ZyW+pM;UVc3(vTViJilYFm~4 zo(l>ut^iG6KbpfY@npHY`m+T)*t0d-46ms8u(diz?CymVSC*dh@@NsEb_b~34BL@v zbIaF_Bb|g^#dW2QQxs9)IQ^?f8Ju2+a~2FKJhIb;!zXHI2aU(y=b=r}o^Fk(9>FMN zgrxkfT9B4k(0*Yrvy;KCrKQv>guwhDPxm5XhLT&#B98XpW?m6NB620?TQOKJ-1@jC z@qAi% z6rzG5qJwR5dK%6e#Xcr2_^udthlw^$LdDj?S?800Xqjb79dh9-1Gj%`0D%;E^wZza z7lTV9g4d96&jVs^Fh#HC6)~1%$L~5Kv9SfvoLry>5lisc_|+ZH*@ijV*@d6(z*$m6`kJDW zNleUs%pIfy4CLvx0S8rz5Mr*5VRql&as8o+0$A*T6+Rj}b<40c)dp2RwJFJypmJt_ zhxJl;?EBFN6%zMU?p*r;G^SR<@Smm*5D0)T+0V~fI&bYzMS~<5ypq@DW?nJ`@+1JB z8PEQ_R*@kS!hn%mB@K{gsAmNfWB_J?jgjH~*UZEmliLO;oK)RJU@W;-b_tpyT7k>2}PjV)xkfeNbgDHEm-1XN$`+JPc>OIC}vYRRVEs z=EVSMcAg%_>0J12W&b6orCg-qFOe}@0C>?2>~$7sk9=GWJ6cBBux9T+AN%T=3*ldF z&-#&SD!_Hj16dQ~ZMvITExx*1EElS`*H$DiYxi5u-$>7h14g9sVD^S9$Dzlgz^tHZ zb3gHb5ba_L;&3h(3y$pKxP(BjfS(!-^?uEum8x=~0QhX`O90ubDB>mF6~l)eoTo?E2z$uNC#hrL?#xA=KKg}01CZN=`4$(*9kQ+wg4zp z0ya_Gy=sd*sT?Y_?+9;JlA^3Rmm5Qpt5cwdaIX({a}tN9a3Dy#MgXGE+`M|czd04% z#WD*Rj|ZCS;=oLb(<2;q9N&qmkMGm1R-J0FJBNA+$a&Pgs#luxebUkw7E#ikdQUlsbWt3i- zM*@sX>b;TBudfveBkfdVc#4kRepXv~$5D8~rYb*_An7o7$ zXC0`%=Q!!W@r_(c4;@J>yd3b>=F5{>$E&UVGquk8^p=rJbQo#7f=2KhLq$< z&^4~t;O9&0A0{~3TvUGy4e-)R`e4PDk{U|CfB%jYuH$~+u#q&d?Cdywj+$VJOau^} z_d6Xei&x!CY*EFA%DF;cQup{nVg=P!9L7Zd?025#F{Xj0wxDPOC0VqIF z+mf_5Pzv2Tf-v4jM(DUld?|JHsOUSDJlF5+xmLUC`@)CCc4dWu06mffQo9*H;QoLFuYUtu?jgmT<;{)^f2c3*|>WWGQBQT?adtpMPO?W@4y@A{Lg+Ew;;_|wo= zw-IxL$VEfzw`o$n4j6&rj?9jr1>zO?s=CNJkt^p5Bogdv{QtW)`Ck_=WLnV~{!|Dy zDVoIC5Kc1Q*tn2rzBy@1IMr(<%T6aaSbf zQPD18JkahOLy)lvF#Cd0;E>Pk_jyghWN=ATX1OjtF2*=^ zGDmE_Rm`y&i!Ej@YUP^~ShJ6vj1imv9>6poOE^+5MzQrPvhnW0^x628H;b8Xr6F8m zQMd|o&Gpdrc~&yGf?X_`Wv5TvRrQ=SB#Y0B>j{f$;vkSg3BA!pKdZ+I`D?*k!S#S?`IeDmdeMcFZMu;YU}mYohUv764~ zrwL6O6x1mY>ZU7fRJ_hIs7cFr=kZ} zwu>bYH!VB$>!^?!-rr!OuNddLw%oUi_z>dbSKS*I0Fy$cLMy@z9=0gRi`rXcOVu**7Xm(h><*MmA+;i%OAu$;u|< za&6bTT=#y@z1REm?tl3HBF^i~=X^Xzk5CtMwsG#}1ORN)J$uR!02cTw3)s8~{`k4b!+RyK9g33AKLV6e8jd@8)lKYj@39V5Lfok556otVeZOT@Ftcshg3*d*G)p z6S&Ld;&-r`NuG>!3$_>Lw!b8qpgfq6SF1Hu&t>nWl-7er+1w9aJtFc7fY5}Q8d{ff z$-4y45Y{e1PAOH{w9Y}y!_k`)e|khrTq_i>FRk7!!!>Xb-=k3xAwjEd0%`*Q2z>&+%sB0YY^Xu_i?H*E0Px^|07^-um4be{yR5JHqRUhRs;xZX zz{8-fiPg^tQ2nqR9+|H|mF>(J^Wm|qns;qIAktb?o)F-^js#%f`*So>c%H?c=p(B` zSyi%(8fGt)I_0g zMg=|!I>`dW_e`n2%2vr)UdQK@i&%+q64xY^ATj=Q_G@<%i9R#F@dWR|gj;7m--A!& zL5Om(d%Wx(!6t>oim?GebyE{*wNq@+te)op)$fMdZMG=ICXHV_ssz6YHGM=O6)%}n zA$wHBb^;JPd(!&pk+89OJXhLvrSILVEP(fBCFjiy>r=03_YRvto`p&7myCXD?WqngrBsMQO>ioJ8bt4mk0bzSpAa{9tHHyx1d9;z6){K~ZOOD; zo||c<&GR((vR}1YqGOl zdXwt{*#>Kr&ccCIO6XUu@`hvI=2n4zU}O zi>y=hotnK z4~m(3z`|KpxgCHj2G*#F@}q$)n*pX@ZT$4-^KeF)wFLY*i)Doy0V>IiZg<4?(TDc_ zzx@@nc@5p5=tKI5U-(sj(#L1ew?4i?|Lshm^~8+-nTQMCdJ#R5Ns;{d1@1LMGUbj* zqrH^q(cZiZVNTu2Df~tDBVP`yyP7@S6F2{=y?^b=34=iE&n3=dDUl%y)Y05HJcsy+ z?V$ShWGAK2`ckFAu6*lXd8$SB-@XgR$lDctvvw=qjWW|ZlOlrQc`c8oyN&*#$azO?b(O*fNOipNq8cvztTFjlWNU%7u$5Qm(et9mZ6>C@Ez0)%Fp@;~kcU{Rp$fYY;16*>MSKjcXpcy->B-#k^V!1I z8OQh6tJ+vg`i-A{obDE89V6#i*w;CmLdsPK2X#O~(^U6TMUY#6)53Or569GZ88-PJ z4PO|=${zR~6&;;+i(r%WBbYEoP7zb4b+OIbuz@EP1yW{Q&fRHRy>(+XU5&3|zvR{Z zXiK-YDPFF!QGGq*MfKoX5k+8Fe0>I;=w#`&v`Lyzkyf^m3O&EgUZHvTv)cku!W&oh z9-+Appe;i3p4!*?+QQv*!^orDDsGPJNY=KD$cSn=Y5Zo z!Ausx1R>718BppTKYAl&p7n}!Fkm3n(CAldW-nkTR1Q*n*+LJp0Re73%UhEuJ=YA< zLEnK6`KpBMJ@F#OPD{rK{c^}G36OwBWmrx55e%l00c}}^I&wPMt$k0N;{s>E$HxE@ zZ$+sj9dsW!_e#cGtJvBL>*>5&PhQ^6>#!NvwI$yn7z|?`z4)p(u|!=a&3#28cmZAJ zV>R!wK6vLomsdKp`eqfw3oe8KjA>6vBbi?j6Ff9dN(fC~W}E#|9QY4+Rof{dhZw9e0vtp|W z_uA$;RZLrlPpFzmv1>>xYSQ+q{KRD?OgjSVZ!)l7l*~! z;e_M2rd#F0JSPej#3qumX$4EsQ+Tz+jt;-XgM^9{om7n!1vHnE!wOsrPhDBf662qWtF|#v#Bud z;W+LdkKK>^b&(2dCKZ*V{Dg?`bj5bRM7oTPOS~pNY^WRm)9-HhhHoSmTjnsLXVUto zTg;2P0&;l4O2o&Go+*m1@(Za~Ia#LLRK`}FlHB`0oc6gxbY85<^Y5yf3MJ)x4Mv94 zTDTBSgcId-9fduX90e|SO}b9`41XZiv3>{#)q#_J3yP7lCO^phdFg!PDXke=9NQ+8 zt=;OfFD^}5`8Z3+F2`SxL|?|suAj|6lWmOmTsJAXY(j`gk%21h&^7zDzEOinaRGPs zf?2uDnR*xMjmx|@^O*CyX=h z?jl5ZB`ajKXhSnKMd?8ZL;Z-*5Z$C4xKHEF{rhZjUQ6u64)0IUo$Rb?bnN_`B^G&X zVt+VMUDpGDdyF!%*AQBLd6xm!axd^_4+2B`=-Xm;ad8~8=%CO}EWIQ*>K&l?-8(A|(0Z~tN(oR4R0H`AfNKpC z4jRp`_L7E(Ra=fYw?r*(L-s(@WLkSGWqtFo-~&n$&`wX3Hax8R>U%EMBqs(6oO{4~ z@0x1RHsAB z`WzKuq~|IH=PtEUiaku$?&&=m&Mv+Y>OG9P%uIJz?J&|c{Qw!cdXz0KKGnCOXyx` zv7s+}#lII-=|1U)G^x8~HU`zoJ-`zgzzdFQ1My!PcPU~}$6x$13{$e1CA(am8ufAL zwZ-ALDT%_f?yyyxuz{donGwV3wq;b@4!;27+{MKyWfHaIU5G((1UShC5}V^2 zZN`cE9I7@esXqI!Oub5t#coG3PcE`I^fV6Wx?*9!J>VEGZaafkT@|b7OX0Y(@8n;! zl!bj?1)|qVNu+y$%&$Ts-_;U@b3c8hf2G^_Vy-@y0FBv$432$yVe&FBX}U4E{`KM9 z9Z@r00Vig~m|tR|O!xd^R}faVp=f$IwfXpX4bhY}g;%%`K!OciYYwrjyjVA?9xF@5 z+FzvciGHViCU;hAZU#H|0^Us5{D|@QnbYXXl|UkVjI@B#H090!50gY5Bq#IKSIGi| z2HJg94vhiIxqrWKblekFU0 zQ<-dxKdsMZe8kMeIeV=Kj#e^9`$T`PUbM2b9#LcIQXC(p9OkuQP-K9ELoP7%@#bg< zc1Zb1ia1>@Fg7ATDOzzyN`Ku30@4=Rvbpsh0YafnD$TxJf1?9!uW#!1rbOy~Xj19B ztuc2~^gR)n?L&}v-;FSGiX~7){{5hno2`*mKa!!sg(-L?uU*c5u6!4M3z*8y;LebIU>KH@h+H^5on;($yp`xCB0h_~-)edJx@OANXI+WdUR zGrg!#%5v?G)(i`?wPODn%2r-W#&a;VE_A<~-r2KgJ_P@!pY9r(*O*c^>!!F^TB{2L zbY<#g*%Fb=*;v(Q-lw+V9f|+2ta_FFAX7p`88@n?`2=)Y3+l?)tAiJOFBfX^DsTjy zI}B2T3)Aw3HcHynAb{ePZ=?}uuuHxvIiVoWsm}-F1459>7Hl;fo^7Z zjKe=2)1k{4ppHg?f zW%#lsOQ-t%?efz{FEHnS$98l4{ICZ=r;pZ9Ok|SznI^~aK-82y!7>6f*;y6~&ty_` zxWDU=fdvodX``nc3OyTPL^kGcw1Kfnc68w-3%AFCuQ&bnl7KbnF6hu|hr$|Q^J=u?DT z_9kTK3&DcG?(Oh{&%Ymn>u5PpLCwQ4KzBfQJ1DW1i4ze@7WCDc6iC^5eG!mB;^F$LUm&cpR1kL4v1$kM)6XlVBy6# zG0DFI(O{1S+u=P`o#b+KFq4CREe~ajgg`|%kGqC!4^u`t`@1JJ%nS|lB7vl3UOBX( z%Gg~?%-1|`{^-r)kjuh0T0ZJ${hKL}r@ocH70VX_Lpg8${59A;QH8puofrx1EFv^H z79<##7I%$lceuVE7``+rlpRtfkZO)>j340ktJVW|<5L~;tvxklCmAjq>?6E6?VH68 zoVg}7nGd`{M?!kQ{f_4YlKEAp-13?Smxh1j11VuqCQg`T)>(e$rg^U~{JypyTG|%3 zFikYvlu6Nj6XAt{c|rifM%Vuab73@X%93D17{u8=P-h-Cyf}XJyB?6w>HbB|`Vhh( zT4*`PncO@+0E1-|J+?0Yz$9j9IUy?G2II7bOxHL(mnxIf-?`YIX5MXnVajr4(MlO| zifJb>qK&v>QVC#~8tF+U?I(Bsb}WblV=i+Z@Dl${g!e4q10J}X89&qCS_~ubdwVn~ zCK8-Ie_=!x;TOcX*oPq)1xZ3EsK-|RamfHjI6chd+ET01gqk$s83go%{C)F`YXM)C z6J<4efFTcAp=u0*RmVfvmd^+Hp*!?5J+&e7_+CXd_^wUvyT<<-tbb%~$};fcfK?p+ z@pn4hftfFFn8tu4gwEyfL9bex`4-GV!8M%izc=y}l(wkRW1DPTX(wle9%de%Q`#nc zX$$DvDoJJD+q3XaQ=cAC%eN~gnQu2|umoe(Yq1DfZE0IR25%$8)Jn4|Tx~X6b%t&y zJmbd3>hNi~PCf8*SAN%DXTYG{VhaZTRKW^9Kh312g6*WeG~#F}{stsZ9+Ny}d*TH? z@PXjc2oDYEeK6#N2JeHzPyr!}4G9mUzmF-Qll9RhEqY*K{OIq$j+s=>g>RPbUUK_y zbwm3>7Ei~vy1%B`3QfVch`wD$|2J*o!A;+6HYAKv{yN0R+aw2SQfETNUzEtrrv8S) znceaC1I_ku!;@il=&uJBUMB}gBhVMuJ^vyP-7QNannr7${x!Jn`B@cm(Enx5UxOoR zD;#j?*0Rz_j zCn%7tkb}|(ZvC}-@h#~HJcj`b{u8{%H*s*Vn@~X)@C}i|-}@<{H_MmBR*j3~h{K2d z%Wm(H!Do>pGv4uiy(?w}(!cWJd;C_#jhp1u6rqa@qwud#$DbZjgl}+@!cP39JYTf( zA&bLSqm&@6m{#<6%S_%NBp^MI_@ACE$*Wd{M}nQ5YZv~~Ts=W)XhNq&i@rlzZD{UO zO^wwZ(hdEjyTVthHjK${KN?p%i#Xx4Vl2G>hK@#STuUzmzw^n`@bVkBKy{O+u;Wc~ zl&sYcXy%ya>_gIE$@y$HFoPI?H47LjA%~|LSLi7Ucu5<=_Wv0&70=ni4D4L#0=)!UbA|A1)vIuHgFBe%rd{u`fY)0xj&U+Dkj zqz^p>%wR&dC!TjJ+~T$jaQfsIOY*+T1Q)#KFqh^i17Kzs2hZ9t)UiF2*V{D^O(Zo2 z1eL4Z*ugc(&8E1B5+-;krw3GlF__$9yzku3qqP>GAg!Oi2UF!kV{Z|PKMH|bpQm2% zUK>tn2>K60ZS9~!a7p1%H~Htklb`s8$mA7K`1$x2`o2}EV0STLEqLBs5ML2R6K=Kt z&p`@QcC`E5SsbBluQ;IeKL`83x&9fs{dE<=o1QR9Jhe&=-pO{WYApRlYMB#35(zl1`ck9zhhP4!U8p}bu;z9O}Pkmx8 ztBe(%W`eQ@L-Qy6;U=yrQc{X*X{3@tZl-N^B0LV(J9oBVH&|DRfLODKNyML>)D}%V zsesy-8i(J;L`6W(Id|>y?L()tj?iHE0QZR|bq;PQLY5hw)7>+u1 zqMzp}j*WeuOsY4p&dZt>+}G$@HGnW2rr==?0I)BQUdN`NwJ2Q#pQiJ!;%s#mHek{; zOoW-+zzA`?^Xm*9h;Lx3XhPJK34~9JBmFrSZQ)KEaF)HLQrGOD=6Y@!!3%EV&cq_~ z&Qq@r#vP`SaFs}i;0dIEr<2`|PH?nk7}n{6pQ2^oV0@v$6jSQC5|{XwBQ`n4r>9_E zn?(K>dAImN)AU$nB_EPi{&tfH+)IV&3R63Znr~is9r)(Oi1(0KEFXh0vlBvnMa@6v zm(>hja*$dyHv$8tLa+9~^t}Djvn`s5%$aC=m`o<52A+~(5^MN%|MS5+V;2ZL7wFV&H0T8CrVLlElldQazp35!P&D-OCf#k0o)r= z7lvLrv2xe4Wb6nF7fmpzEMl_o7tDhwSy4~7{90U%iHO6pZp3vIr#H1#%bJ6IFtmh& zOiMyJO!%ys7Mf&0Rvm;%{K&Wdtz`3!_^~?I+QR$nh+c^|mc~zy?OG{bu~_zN{0w?h z#wx-C+e+Gq%2rS)Zl6-%Z zpp-+;P1;bPFb2hhuY3>_;AF7sOBu{==FF)4BL9JGPCsZa^TOcZ$!86`m?i^>zSU9o?PG3fKwTNbnk>g|!bMRH)ZIx* zI6V6tGmMZ=QGH~_nBO4Hct}OYL!1PY$66GI z1wm#tM3)%t|D~^Dv!ZEIsO_;n_pwSzQ}_$4twPiAC9hro9Q>Mhug9K8Iml z$wuQ4;Lsy6P3aY8$dlNZ(-zXUTB9E)yJFKa^k>3d5*pq7pelyAh{yb_^6+o1$n2M0 zoIV;l5|Or%yPI8Fm2E9KElX%vcZY?`S{hlxo^h4x!jOX;Nz=i87jF4gjpOi~D~A{t z`IKi%>LB(8B#^!asBEzgdcV!)52YMq!(ai%v81z39-?OxNvlq>t7cqs@{Pu-n{gyL z)(a0A0&~JKZY~j4T!#HV5_IMg_ZPTyx#93zl>`}^|Nh|iRf}G!Af?3Hm`KOg>a6Y~ zG9U0_>CUR2gwJ_Ky$OD;QqC>u^P7|-*mA@&9m~E!)Y8R9krM5j`ljg0Cay$>hRlWL z_COU)O>uex@Z)x1wjETuK)ML^7U>pd#?AP>*>MVnr1VgeOh&NNy<9FxI4T0OWjs$U zGk4p@5#SW#AJ23+T7lmR7_R)_}Wn+|GQ!-4l2K}C6AHk$oD^8Fj7At{1zz|jR zfu&o1nGnR9j<}k{$*rzp*a201EJLtPANm1U_O<`n=5-sIm^iHJ6^2zs`YFLQ8w~c+TsqEO zgeD;JRrIjmv2J?ULeH}i2t1$Yl)-M=`Ias*!l~-1syW#7rSqkSD$X7wH2i*_A(-Lt zV=6*5Py|H5rws~X#=M}jP*g`UhZ!5G7Z$DLKOQo$s75cL_YD@W-J>yJ0h+MhXyX8@ z)UZTx&8qu$+V1#nV`z7AQI7Ju=gt}C>Tj|m)Cc3lWW~D}dUvXi>exTg`PH|8g4-HC zqiAJix!A58iC>&*SRp@u6`c$XyF=Z)KTb?j+=8JR0`bd=f!PDW&USr`5x0$J9+gfe zN}J^CiS|>@1YA9PLGNP!g_A3f#J)424JJrAnjCC>*##NVOH!p*onef1VF&HKQBP%N zybLs-_TL4I$0AMk5+aWAN;7y*?WlY*v#_>b%zm-gz>fHgy!*G~lP(2fB8*}(lap7- z39)vl{Ce-06Mm00dggfu5vuee?#?+&K<|?Xs2V=$SUzJ;H}f$^uRMhQM=vgB85L}C z-ni0zKh;^IhOeBh(6QCrAyq9MVsu>90n8;Bi=WNnKspUX_gO5L(2K<<`f25_d#Ima zpo6-eTWQ&0b>duHj7|C(4~wx$Jq4&fz2tdPe&TJ|6XB5@P_=N9V6%)=gM3JS@*v_~ zMaFtHcKvNgUIdYzE-Y^Me{UxCqlKie`OApZZ`wX-)ulA0OfNved}7{vk?bjtvNTt|99on}yHXp(eCep?o5Z@$wDN?bdTrcr>UZAlIP3poz&2oXq zw=fI&fS1s^AnC+}&_7(=2O+d*g;)`)TKdUOowz_Om7z%713#G*-SCD$3KemV zn}{6c!BxqEDhcqXC;q%mx?!gj4oex-gbrbMt9>F}HPMo;m^5whrNlSnhGA$y6>FyJ0xD&29xkGwCebF8$S*mGQoxf=0iZJ zTZiXvqMw#{KypfQx^Ay2ohz^VOU~!!lE08UlrVB9;Tf>@sbaG`)XJnDn+=1?Hduia zfJw0>=b?js;?}&tWqMHon+8iXgfO<|TzF%9x2rngV+!}M(+Dwf;CE#yS|?U^$Egrl z&V@O}lcF)69kcPp4zMMM-a`cKQzNrrb zER(0bUhJYayYWEL2EzXqK5I?3;gUM1}de!ze#Tyh>7bzV^VKsW_T@+^mUT~42O(iozEWT zete3A6E0R9B=%k9D*S_UtdA$fc*06cuzC5*JwT2PP$gjGWo^0sG4EDY#(w^yu^i!1 z``M8p=bSn(k>5PSbIrN8_;4j0+^u838)cF#66Ait&LI17QyZEWq%)qF(?ky%>W3c06 z0;2H6flq}NF1GJa^ejJNakFl5)7NNn$mDUrzt4U3*8eAYh#jQDvTUOEy&<1KQvV{c z_Nux9&CxNQ%8(A8C)O#Cf^SW`M?b|32KBH;%k^|pXFc?N}HKIRIrpoPYdryTG z-Mhf_bUQ!vdi4IKIB9Mo6tc0nMH?c_y^f)TX3Ti1#Wus9Jik!*qdMgO>8~*7y%0R{ z7Ls7;KFjK7E{?_U31I{PLhK7XvLdZJaL%xY@%O@;9o+Ud0zHsOA7Bfvj|t9J5XG2bX==4(_qN9rUKj$sb&Hui>%+#(t*TNZN?Ph#>mjMK>}dm&ZLLy#ipH zWcBMIo8h$k1n>AAoMUK#9$wf3UGCraNLr-z8?$TEJA!f$XlwNfuq(p5>^m&0(?MGn z#B6PI_df|+KL0!=jHbOHiB!t_4ay$RO?xzoPgW*z9?KKqI!3`5EX zSN$vL86s<^q5yvGu}cCy^03R-O-Gx&K2G~0$ZhX0&;vV(m5dOL(oHbD$E(IBNx^nk zmjDs~3Dw$K{zZy9`#D8mP0IUS!hzB~kWB)YCDVlQb}*|$xE=DM7BS@lD$DV}e24Q# z*juB#wy*(lz2UL4T4nnk%_D(-R79F239PIDlLR}l4Wt|3OF8XK1-5d-0=6g*hkPq> z9@fiYn_yZ#oL$dlcUeFLZcBZZG{eo&+AvPv_trQOjp|p{gqQncj->72&M2Iypyf+1 z+_!iby!wSa2-zH>jhLb;=@eScti816IBvXGq=~yDgbg4s|7d;)`PI7^PixaRyr!hH zOtOYzx07?M`*KIsq*;@+0BQ}56jRYugFV%-jW}-bPTY(S7TdfyDwT5I&0R++A@GyN zS@`h_cAllQZ;@N}m2_-M{ydA%VNPyA*zvw-C8^^^oqzJUq_6uyfarJQbu_9wao`yO zgbMXP2(oZj(lNO_GahOaa@@mODd8(*>Z71w*hBsRKOa;|xKbol+SkyYi$bRG5bXTm ze*uuZ3&k(=6AI~kKVM-Wcxy^&U+qPg2X3uOB2DYwT2r3u15oHfpN_(&dx2KR!Gp#v zitey~Q%|RpeU4wVOT28M2)R%e8*FW}M z;=99zTR9YOO~-4J6R%o6QZ$8LnB+Z?1U_3H>4S5-|`lNGPa0p8GE*@Wn@&y zmSJoW#!rMS@Ac{T_xs2D$G!J+pZlD1p68tJ_nhM*@B6&1UPi9XyiJbz<0!hvh|WMKPBK8SU2nZ_6`CcBj8x$tz^Lg86ysrOw+ zHAE16SW@lQTJ9g3%_PkdK`k%(`fAgb+4nQ8^I$MR@E^PJVc+MbGViv8`;K?lU#YAF zE=GAStE3O?oQ@D8u0ENZhw(fQxL0nmc#U>6O+Ryh-{e}g1WCZ8OWx!fR)Q+7x$wqe zL!sQ$*bzx;Ujrf9qz7!-1(<6#{8o6B2gZuf&6qe~^tp!m*1JWxTo#=Jd&JM@bP_Kb z3X_anLp6v_3)}5HZ$w5_gyx$^1LdL>Fx)l0X-wgGC6XIR-)@ z64VS5)TK_f9C1g&LZxEqJv>d~)=0vEdap5!wwpFg^tZLtKQIS(ySMH2t}dJtQTV?; z&*{|_Ln8QWwtw)mM_HI-3c~2HTd0)XfaqAREI(Uie>v{7*|>w^3AdBgU0c;q6^je* zV$pW2e)Z>F%-3WDXDQ~8Z~pMbp`4m@r&Wzr-9J!4+X(6(UqW4%eP8oV`O-u-MzAAX zg$)`={N=7J=*~M_w$ZdCue$dWKN*rIc|5Z~p2d8xbQJS0*5*Xd1LJD~u~fbyXc}EM zo>|`GR@T1!l7?@2q4a%eZG;KON>zbheNY|oFvoNExdnTkG=;i+U)|-M4xo<=6HKsX znHGO*s7jDhfu&Uj7d{#zHkx=zv{R&>BWBVZlg$+lEof zrY3Z^nE$=sTg7w=T#*;W26f^Y!JGF^y{1X}8I}_ergqbVxYyDGD8U-pVAsYX>GHfb z4P(X;tv*E!I2-dimGdc}>bKjm zjF$T|sRm@k?$e+1w!AD9B2H#o6=tsHNF%3e8>*(2JIS4@0o zlSI1s6G9Pf&VHSIwwhL53{2)EQbjVX<-i`|u9MRixfBLHU)_49nZWy&?p|&%`h)HE zI!T*e_-k51-<>;m5}77-R8H^N-tr(mrL2dn*hHqF`+k<~4+QXXrtjRooHOFIx!+%t zseF-Tc)iK6fm90?e!?8?152y!jB|DBoT#%Bz)MgW>}eYFH8QhX30wRsZbCIfcd(~~ z$3LgPwNPN5%(u~i?cavGQIjC81lzxE> ztm)WjdEEjl?R`n=9}igDhKBVGg0Ati3I&FH%DLN?>ni|!KA;?BnLt$>cl?iqFp(0X zs^zUiE@6J7(3T&Pgo#4sn?%{C1tFY#^?QXueoWalvBCZas-M} z=t!Gwyvwub;V||K!3(x4{dDj2T)oj7LtAe|AN%mdRBgn1tl%?@4?8t@*1mAxYjZm6W+b9Y*Kfd3@E=?px zB}4G^(eI7~kB%#(!5Tyz-XCAWlnW+-Y?jKgENl=yW^90LN-!l7rk5c2C&MOomHTcQ z#ZEc>C?|6qPVFaZoJDI|8;K-Z&rzZ9i^2r2YH6??+04HK9lx&njAg2ePZ2*64w)P~ zp1lgTV`%&|l}y!nZL+*FK92mYe~7SB#Rv?4@|x{>0ClnmUR5eL;@F9hL!-wNY2}!l zm2)8m?Uy&0cOqsD;Om1WkG5pMhtGtHE&t>*fU3j?)Ex|OxJOUo$VCF=gzIyGg}9KC z!5AL#!yB2$){P&$4G&dAzF#fDg?NUo$=F68d;I>~E+pKAvJSgR)cCr-P5l=B$L`4T zKtc#qr5E+(Q&%}DY2Y352f-_Z3siM0UHh|>`YP*ifyFFS0|aj-a}aE28J@D%u>yy$ zTY7%fwydL{4T}PS;zWG+;LG)`z`9@0gh(blJrF5LPiJQu@N?I$l#}*;A^Ua?u1ijP zJ1|t0qmZ>u1^#8tp7izUU`Rw>EQehU5Zh}Q5`wUZPX1rPEG`t{N8-K^VZ|~DJ>DWZl9t7C*k|_8<*(Tg(^Ywa;Lpjo{+*6+wf{(e zH2@#kF#>qmHj`Xkbo#u(?Nb@S%L@ia z;X-bF=sEV8_5_0UV)}$r==GNy>Z`rgdf1UQFxajv^wO{%K)gwu7pvpPzfov#wcsX5 z4MjI)k4*@#mp%M9IJ?(JkYF=L@wyAUsynwGft3(}%2#Y{3!TIX^s5fEZ0INzOaNhG zEj1hbPb!uSV~&x+YKMOUgQ^IV_jJS*TI>7>^q*p1Fr@<%t$^sfdFdK&uX1j}+82Vp+w84pil0^tn@a zgVLJhs?LWnh8DbT)xl(+7zEJCf&r4VfX}JjLOz&7iu}F2&d-Los*hW<6}#R z*+(7Q5WM#2z;`=qK&wOPnHA)4i@Isu`t8YO(d@_HCZ%*749utBD7X&0oSxX1Gn*Jw1 z0y8l4aO&|LX@5kLEmRno0W<(r`SuqjQyNee_@FV5ja$%Q-4N=)3g7`BuqSc^aaRb<2SMW3e)T0Np=d+epwu7f* zD8DOdFx~ALSJL$ABdcm3dOTV-KiPbY_ADXBF#NHBIPXF$ndC&yE4?kiTNNS5W`Ts^u_e)dVI=W9fVp|V z@%b}H@~l+~`g>6i2NvNE*lH-lzLF?ZN&+|?{;}4hIRhb@U5vYWZE+|gJBaK3(MVk& zLF(PfkwmchD#mkHSPv*L*#YK5uWwgzzhchC^i(DXN4-H^g5U+feod6__gUdy`^vvI zVQfGek_#3q`%h;8)e{{ZcF^S7v4212RU6KrgZc5ECJYF5neu6>o4_S9WliiSLX*~| z8|mJ$qcr~RN7wthJjI;`ONk2|sgGuja8bI#XTTj?Ln`Q0+-8?5=DU{{+@B(voZ0rt zB+6YL$6@+Ppt@99|;kw(2nCT zWH09yd_wHfc_Wqb{wtUvF#h2u(iB5 zOdsH-^ry&dICAx9^~?Txf)&67f#qq3R7=iZ0L!pOD|hKJ)FD3O1C{3K{cAFzz{XPR z@t4Pqh*zgO2DPq*VN;~`|A0hPYx%`0#@=UDMb6L8%LN9GfgqaKu>tn-NCfeZ&0?_| z>T(XkbNSKtJZd<#s5jdzBb3}GTDN}l1}}w`J7qGVO69k6z!YEpZ0L)F#;?j_bdH-l zyVW0_k~&^6xZUV%s&${?X52{^yF`|S zDk#2c#hnuRpq(V33#<#6y#38n*zgel!dANE84}cR&zv-4MkPFTNQg`fm){7dO zhizDo50qTNW+?_r3*_V!!ieq&!(^!(Ym$#vy>;#m_di?iImoz3H~7`@MdN!d%;gj z;oN>V(-ZMtE}aCem!uQF%=@)B7m#ZpJr1!U8Jy)pre}Tkei=M_QN)6S!nY1Thr|&+ zkaOIPhILX~P%`+!m&Re|6T{>`<84C=1U*^z|27Y1cK`i=~(U zk$fm1CMh(ePd(A@EXnvtg2aHlR^hD|XR4HaskU2sa@3^AG%`-9EcWSB!QkeVbGT#| zdkN}ded_oULDV{A^*Un&>AEDfjlK|rfslA#Dy1@T@S#IKma)CJxMi^`WA5c=O|f&$ z65wX}(QWmhJ6H+Q^Q-|Ij&z5zSStfoW`$53wt2g0dJ>#{O0~`Y?eH{E;TZU3LSOa6=d<(ER_whX4OD3`p?F`){so|KHBQ z{lBe&>wjB)xBsmfGydOM`-?aO(gI5U&#Br7=U-X=>3?Z->wimK$NyKBeHpVt9w*;`aF^u&8@f)A zXTZI6fBvh=StgRK#`skN3_cJrIx0dGtTpJ>$QJMbQ77tG?qm;M}6u|6R@e z|9e`6{Eu=^|L;KmR0KZF9 UF$%_tssI2007*qoM6N<$f)4Gf%>V!Z diff --git a/verse/statuspengguna/static/icons/favicon-32x32.png b/verse/statuspengguna/static/icons/favicon-32x32.png deleted file mode 100644 index 8478c1eef1176757365a114418036d6fd10fcc68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 666 zcmV;L0%iS)P)AUOi6{<1x<3iAVd_Me+ye?4&|KV;#qwkJU_no+q~j-V;S{vR8tw# zRCG;+5J%Tk#xx%;KoM=CJk+I=rC$6#KAH&lASRZhspw_{nE8PI)&S=Zb+W&tfem@3 zl>d!14v15AR;J=g(Pb#1=;Hf z5E15t&1Gj%6>r)%UeVQXJN%3&;34~KJNgbd6PseV{ zByvGCBRxNi2WTp|%DspPy`Gom0J7`*rgxc+=%mF;U@D357ZpUeJ z0By(bBO)|aT{j1?Z}SmEgg)z^mG672tt_|0We}8oGiL%6HBRC zfPiQ|TxJ1Adub528_RD*z@TyHnvZ~{QV%G<0LThWlbn&F^8f$<07*qoM6N<$f(fl4 ATmS$7 diff --git a/verse/statuspengguna/static/icons/favicon.ico b/verse/statuspengguna/static/icons/favicon.ico deleted file mode 100644 index f3757b92dd496a92dafd7e5252e463ab68f6ccc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15406 zcmeHO2T)X36#Xb50tOhdVM7tc7D^O5f`VAE#D*2I#g36^G%5X^Nu_g+lVwXi@ zCW*#LV#OL`kA)>MYD_g6jT*Bj_dZ-_%`D6Q7n430qG)?F|rauA~1Mj^ICKYThj3mTQ$DE$%# zyp26G*S;wG{o11#8#x%gTXx1@+rNGBURSQ}_y5+{=B32Uz@%=&Os@YdCm)S#)yMtK z7Yw#hlzhf9GCUf2@8_CapKW?X`uSShf=Fn$m_Q=f*7Rt2?IDRiciiY+e*rOZ0b9vTfo0fq9z|85n|qI*m}@ zs}360@Ig@BCJ1fPlJ>H$Vol48TMYFFht0AEJ=l5?M^biy<}SK5>wr(@WMR{krAUdH zjuGMg(afhQ9Lm~@{8kNuuzlJJqxVxe_P3MlFgjwOULEgkK93J4q@aOUU4bL4X=~ih zJfXL&9GSXh4awJ*d%E*Fc#kb(R|d5!Radl6jFGR!u{nO3z~JxQ5RZ3URm2W*RzkJ=d&%(+l)zz ztRnx?^3R3*?P4KMX zfePhaaBA^KipV~f_L;C{Q9c&;HLr1lLVAMjRJ~$VoLID55!u`?O~|+9aa_jEPVDhf zbPgF#zB}XT*`gC_d3uR_Cx>$6N5|r~P2VUco8|LaV#_<}nALA028Q&YvsWu|9&1$7 z7kuW43GI!w6Bgo^jb{~=Tilo|&6meZ>9ZI6AC&Iu%d^Bgl6?!Rf&@#*(kp{~VD`TY z`MNu75547R9w_y`(B|axvfoYqH_h$;^@n*9qG+X9N``n6%9e<;aHsJylsJQ&=HVF9{!L8m8iS;PQ?NcR6^D~|;_~tXxSesrsJl3G>#=m?9CQw9 zk2+Oq3g5)h-T}eB0d&vhPaJMNRCTZPf;Z)Do&6^EmD@E6#st!f{ntC>chJ03?A#?s z=chZb;Sb_fXFTVyssCsaCfdCbY*?Y zJ37Ia`06Di5)|?On>b*Kz{FhO59^K_v?br+?wYU)}kpWESa|6uDSF}EG<9fc0A zPA=fP4t;XW_0ClMx_FqA@uKm^W68tS4M&o9S!`Y_fuH$1<~NwrB4-W#=-%m93vnGv z;OD-0LiZpXqriQ@<7w~g42z5-rSP*3ch{d1+#c(|u?PQHU~f8O{%fnggsYRY&>?+vlFi}gIHkU|w_O%IIpc3wv!2c2f3)oioxOVr`}u+=T`EG;9J&&L0 zHc>W*|K{3bbQY>2@Gpv`@GIIA%$by4e|EmRO85mF<8hwu#mtGF+g1`k$BFWtERUTw ze$5n#izrTirSLQMHRF;6cJ`&WPE9wv?Uk}W`!ab8Rq&}=Ti}oIZ;K!4ELWWEl*m`Y z{y&kw&*O#t;R@wl#o5^sXU~$_pW||wvuN2MP}rUChdCxkiFhDm`^HrJvwxK~DiOZb zyajgly%PGzDHhLV41Qj#nfu`Ng87r1>+%eaSsv$iGEaizPU;cvat>O*-5FVvQwe+V zG4jUXGPX=~+wKB8w`^3Bz*M_ZjhDDWtv>pm9E<5kF`^?n_7_~%eTCvr^%0HgyJ+mW8I2JC9=T35uu2` diff --git a/verse/statuspengguna/static/icons/site.webmanifest b/verse/statuspengguna/static/icons/site.webmanifest deleted file mode 100644 index 45dc8a2..0000000 --- a/verse/statuspengguna/static/icons/site.webmanifest +++ /dev/null @@ -1 +0,0 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/verse/statuspengguna/static/js/dropdown.js b/verse/statuspengguna/static/js/dropdown.js deleted file mode 100644 index 505d4a8..0000000 --- a/verse/statuspengguna/static/js/dropdown.js +++ /dev/null @@ -1,92 +0,0 @@ -filterSelection("all", "None"); -function filterSelection(c, name, id) { - resetDropDownButtons(); - var i; - var button = document.getElementById(id); - if(button){ - button.innerText = name; - addClass(button, "activebtn"); - } - var alldistribusis = document.getElementsByClassName("filter"); - if (c == "all") { - for (i = 0; i < alldistribusis.length; i++) { - addClass(alldistribusis[i], "show"); - } - } - else { - for (i = 0; i < alldistribusis.length; i++) { - removeClass(alldistribusis[i], "show"); - if (alldistribusis[i].className.indexOf(c) > -1) { - addClass(alldistribusis[i], "show"); - } - } - } -} - -function resetDropDownButtons(){ - document.getElementById("Year").innerText = "Year"; - document.getElementById("Category").innerText = "Category"; - allactivebuttons = document.getElementsByClassName("activebtn"); - for(var i = 0;allactivebuttons.length; i++) { - removeClass(allactivebuttons[i], "activebtn"); - } -} -function addClass(element, name) { - var i, arr1, arr2; - arr1 = element.className.split(" "); - arr2 = name.split(" "); - for (i = 0; i < arr2.length; i++) { - if (arr1.indexOf(arr2[i]) == -1) {element.className += " " + arr2[i];} - } -} - -function removeClass(element, name) { - var i, arr1, arr2; - arr1 = element.className.split(" "); - arr2 = name.split(" "); - for (i = 0; i < arr2.length; i++) { - while (arr1.indexOf(arr2[i]) > -1) { - arr1.splice(arr1.indexOf(arr2[i]), 1); - } - } - element.className = arr1.join(" "); -} - - -let searchInput = document.getElementById('tagsearch'); -let timeout = null; -// Listen for keystroke events -searchInput.addEventListener('keyup', function (e) { - // Clear the timeout if it has already been set. - clearTimeout(timeout); - // Make a new timeout set to go off in 1000ms (1 second) - timeout = setTimeout(function () { - console.log('Input Value:', searchInput.value); - if (searchInput.value.length > 2) { - searchTags(searchInput.value); - } else { - clearSearchTags(); - } - }, 1000); -}); - -function searchTags(searchInput) { - let tag_ele = document.getElementsByClassName('tags'); - for (var i = 0; i < tag_ele.length; ++i) { - let searchText = searchInput.toLowerCase().trim(); - let tagtext = tag_ele[i].innerText.toLowerCase(); - if(searchText.includes(tagtext) || tagtext.includes(searchText)) { - addClass(tag_ele[i], "searched"); - } - else { - removeClass(tag_ele[i], "searched"); - } - } -} - -function clearSearchTags() { - let tag_ele = document.getElementsByClassName('tags'); - for (var i = 0; i < tag_ele.length; ++i) { - removeClass(tag_ele[i], "searched"); - } -} diff --git a/verse/statuspengguna/static/js/editorupdate.js b/verse/statuspengguna/static/js/editorupdate.js deleted file mode 100644 index f76219e..0000000 --- a/verse/statuspengguna/static/js/editorupdate.js +++ /dev/null @@ -1,19 +0,0 @@ -function update() { - -var html = document.getElementById("html"); -var css = document.getElementById("css"); -var code = document.getElementById("code").contentWindow.document; - -document.body.onkeyup = function(){ - code.open(); - code.writeln(html.value+""); - code.close(); - }; -document.addEventListener("DOMContentLoaded", function(){ - code.open(); - code.writeln(html.value+""); - code.close(); - }); -}; - -update(); diff --git a/verse/statuspengguna/static/js/script.js b/verse/statuspengguna/static/js/script.js deleted file mode 100644 index 2bd662b..0000000 --- a/verse/statuspengguna/static/js/script.js +++ /dev/null @@ -1,25 +0,0 @@ -console.log("everything is still smooth") - -function scrollToTheme() { - var uploadsuccessful = document.getElementById("uploadsuccessful"); - if(uploadsuccessful){ - const theme = document.getElementById('theme') - theme.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } -} - -function scrollToLaunch() { - var cssSelected = document.getElementById("cssSelected"); - if(cssSelected){ - const launch = document.getElementById('launch') - launch.scrollIntoView({ behavior: 'smooth', block: 'end' }); - } -} - - -document.addEventListener("DOMContentLoaded", scrollToTheme); -document.addEventListener("DOMContentLoaded", scrollToLaunch); - -// function(e) { -// (e.keyCode === 13 || e.keyCode === 32) && $(this).trigger("click") -// } diff --git a/verse/statuspengguna/static/svg/arrow_1.svg b/verse/statuspengguna/static/svg/arrow_1.svg deleted file mode 100644 index 21073fd..0000000 --- a/verse/statuspengguna/static/svg/arrow_1.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/verse/statuspengguna/static/svg/arrow_2.svg b/verse/statuspengguna/static/svg/arrow_2.svg deleted file mode 100644 index ea2a026..0000000 --- a/verse/statuspengguna/static/svg/arrow_2.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/verse/statuspengguna/static/svg/arrow_3.svg b/verse/statuspengguna/static/svg/arrow_3.svg deleted file mode 100644 index c447811..0000000 --- a/verse/statuspengguna/static/svg/arrow_3.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/verse/statuspengguna/templates/statuspengguna/forgotpassword.html b/verse/statuspengguna/templates/statuspengguna/forgotpassword.html index bed8afc..59416fc 100644 --- a/verse/statuspengguna/templates/statuspengguna/forgotpassword.html +++ b/verse/statuspengguna/templates/statuspengguna/forgotpassword.html @@ -1,7 +1,7 @@ {% extends "base/base.html" %} {% block main %}
-
+ -
+ {% endblock main %} diff --git a/verse/statuspengguna/templates/statuspengguna/login.html b/verse/statuspengguna/templates/statuspengguna/login.html index 70a02b2..6cde1d3 100644 --- a/verse/statuspengguna/templates/statuspengguna/login.html +++ b/verse/statuspengguna/templates/statuspengguna/login.html @@ -23,4 +23,5 @@
+ {% endblock main %} diff --git a/verse/statuspengguna/templates/statuspengguna/register.html b/verse/statuspengguna/templates/statuspengguna/register.html index dcdcbad..8a3b152 100644 --- a/verse/statuspengguna/templates/statuspengguna/register.html +++ b/verse/statuspengguna/templates/statuspengguna/register.html @@ -36,4 +36,5 @@ + {% endblock main %} diff --git a/verse/statuspengguna/templates/statuspengguna/resetpassword.html b/verse/statuspengguna/templates/statuspengguna/resetpassword.html index bf2438e..e97dfc0 100644 --- a/verse/statuspengguna/templates/statuspengguna/resetpassword.html +++ b/verse/statuspengguna/templates/statuspengguna/resetpassword.html @@ -26,4 +26,5 @@

Password reset link no longer valid.

{% endif %} + {% endblock main %} diff --git a/verse/templates/base/help.html b/verse/templates/base/help.html index 2abef0c..8858b58 100644 --- a/verse/templates/base/help.html +++ b/verse/templates/base/help.html @@ -19,7 +19,7 @@ {% else %} diff --git a/verse/templates/base/index.html b/verse/templates/base/index.html index e828dcd..65ed3b4 100644 --- a/verse/templates/base/index.html +++ b/verse/templates/base/index.html @@ -15,7 +15,7 @@ {% else %} -- 2.39.2 From c435250a61440246d655973ba92326846193abe7 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 17:22:00 +0200 Subject: [PATCH 38/49] final css edit of sunday --- verse/static/css/style.css | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/verse/static/css/style.css b/verse/static/css/style.css index 1f656a2..37a7c61 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -82,6 +82,7 @@ input { input:hover { background: #ffbf00; color: #6df2cc; + cursor: pointer; } input[type="submit"]:disabled:hover, @@ -106,11 +107,6 @@ input[type="submit"]:disabled:focus { background-color: #62b264; } -/* selected link */ -a:active { - color: white; -} - /* STOLEN GOODS */ #fancyboi::before { content: "$ "; -- 2.39.2 From 955e29e19d5b91ee443e0b3be8e818de5d3353a8 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 18:01:14 +0200 Subject: [PATCH 39/49] redistribusi button in flex with correct sticky --- verse/describer/static/css/describer.css | 18 ++++++++++++++---- .../templates/describe_files/describe.html | 8 ++++---- .../templates/describe_files/redistribusi.html | 1 - 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/verse/describer/static/css/describer.css b/verse/describer/static/css/describer.css index fcf1e9a..c80d69c 100644 --- a/verse/describer/static/css/describer.css +++ b/verse/describer/static/css/describer.css @@ -1,15 +1,25 @@ +#describe_workflow { + display: flex; + width: 60em; + margin:0 auto; +} + .redistribusi { position: sticky; - position: -webkit-sticky; /* Safari */ - top: 1em; + top: 2em; + margin-top: 2em; + margin-left: 1em; width: 15em; + height: 10em; border-style: outset; + float: right; + padding: 0.5em; } .distribusi_file { - margin-top: 1em; + margin-top: 2em; padding: 0.5em; - width: 45em; + width: 42em; background-color:#fdfdfd; text-decoration: none; scroll-behavior: smooth; diff --git a/verse/describer/templates/describe_files/describe.html b/verse/describer/templates/describe_files/describe.html index 5b2dbc9..65d7120 100644 --- a/verse/describer/templates/describe_files/describe.html +++ b/verse/describer/templates/describe_files/describe.html @@ -26,10 +26,7 @@ -
- {% block redistribusi %} - {% include "redistribusi.html" %} - {% endblock redistribusi%} +
{% for id, describe_form in distribusi_file_forms.items() %}
@@ -73,6 +70,9 @@
{% endfor%}
+ {% block redistribusi %} + {% include "redistribusi.html" %} + {% endblock redistribusi%}
{% endblock %} diff --git a/verse/describer/templates/describe_files/redistribusi.html b/verse/describer/templates/describe_files/redistribusi.html index 9269d45..d373311 100644 --- a/verse/describer/templates/describe_files/redistribusi.html +++ b/verse/describer/templates/describe_files/redistribusi.html @@ -4,7 +4,6 @@
{{ redistribusi_form.csrf_token }}
- {{ redistribusi_form.submit.label }} {{ redistribusi_form.submit }} {% for message in redistribusi_form.submit.errors %}
{{ message }}
-- 2.39.2 From 098727f2825a4b91f360b9664b00e49f728093fb Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 18:24:05 +0200 Subject: [PATCH 40/49] redistribusi work in progress --- verse/describer/describe_files.py | 19 ++++++++++++------- verse/distribusikan/distribusi_workflow.py | 1 + 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index a3106ee..30d0131 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -1,3 +1,4 @@ +import os from flask import ( Blueprint, render_template, @@ -20,6 +21,7 @@ from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles from describer.forms.describe_files_form import DescribeFilesForm from describer.forms.redistribusi_form import ReDistribusiForm +from distribusikan.distribusi_workflow import run_distribusi, get_css_file describer = Blueprint( "describer", @@ -47,19 +49,22 @@ def show_distribusi_files(distribusiname): ) -@describer.route("/redistribusi/") +@describer.route("/redistribusi/", methods=["POST"]) @login_required def re_distribusi_files(distribusiname): distribusi = Distribusis.query.filter_by( distribusiname=distribusiname ).first() redistribusi_form = ReDistribusiForm() - distribusi_file_forms = get_distribusi_file_forms(distribusi.id) - return render_template( - "describe.html", - distribusiname=distribusiname, - redistribusi_form=redistribusi_form, - distribusi_file_forms=distribusi_file_forms, + if redistribusi_form.validate_on_submit(): + userfolder = os.path.join("stash", distribusi.distribusiname) + cssfile = get_css_file(distribusi) + run_distribusi(userfolder, cssfile) + return redirect( + url_for( + "describer.show_distribusi_files", + distribusiname=distribusi.distribusiname, + ) ) diff --git a/verse/distribusikan/distribusi_workflow.py b/verse/distribusikan/distribusi_workflow.py index 43b6666..d7a524e 100644 --- a/verse/distribusikan/distribusi_workflow.py +++ b/verse/distribusikan/distribusi_workflow.py @@ -96,6 +96,7 @@ def get_css_file(distribusi): def run_distribusi(userfolder, cssfile): + print(f"Run distribusi on this folder: {userfolder} with css:{cssfile}") parser = build_argparser() args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) distribusify(args, userfolder) -- 2.39.2 From 64feae3475a0276616dd9d8288ae3ff83aeb3106 Mon Sep 17 00:00:00 2001 From: crunk Date: Sun, 23 Jun 2024 22:31:12 +0200 Subject: [PATCH 41/49] alttext done by redistribusi --- requirements.txt | 2 +- verse/describer/describe_files.py | 24 ++++++++-------------- verse/distribusikan/distribusi_workflow.py | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3d09491..4ce5362 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ bleach-allowlist==1.0.3 blinker==1.7.0 cffi click==8.1.7 -distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@4cb03d1131a43669912433b0a5c18596712add20 +distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@5934122c6ec1452d975b7cfe6582f9417fd5fdd0 dnspython==2.1.0 email-validator==1.1.3 Flask==3.0.3 diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 30d0131..32ee77b 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -15,7 +15,8 @@ from sqlalchemy.exc import ( InterfaceError, InvalidRequestError, ) -from exif import Image +import piexif +from PIL import Image from app import db from models.distribusi_model import Distribusis from models.distribusi_file_model import DistribusiFiles @@ -76,7 +77,7 @@ def describe_file(file_id): distribusi_file.id, distribusi_file.path, distribusi_file.type ) save_described_file_to_db(describe_form, distribusi_file) - add_exif_to_image(describe_form, distribusi_file) + add_alttext_to_file(describe_form, distribusi_file) distribusi = Distribusis.query.filter_by( id=distribusi_file.distribusi ).first() @@ -138,19 +139,10 @@ def save_described_file_to_db(describe_form, distribusi_file): flash("Error connecting to the database", "danger") -def add_exif_to_image(describe_form, distribusi_file): +def add_alttext_to_file(describe_form, distribusi_file): if not describe_form.alttext.data: return - if distribusi_file.type != "image": - return - updating_image = bytearray() - with open(distribusi_file.path, "rb") as image_file: - image_bytes = image_file.read() - updating_image = Image(image_bytes) - updating_image.communication = describe_form.alttext.data - with open(distribusi_file.path, "wb") as new_image_file: - new_image_file.write(updating_image.get_file()) - print( - f"{updating_image.communication} is set from form data: {describe_form.alttext.data}" - ) - return + filename_no_ext = os.path.splitext(distribusi_file.path)[0] + with open(f'{filename_no_ext}_alttext.txt', 'w') as alttext_file: + alttext_file.write(describe_form.alttext.data) + return diff --git a/verse/distribusikan/distribusi_workflow.py b/verse/distribusikan/distribusi_workflow.py index d7a524e..f9977fb 100644 --- a/verse/distribusikan/distribusi_workflow.py +++ b/verse/distribusikan/distribusi_workflow.py @@ -98,7 +98,7 @@ def get_css_file(distribusi): def run_distribusi(userfolder, cssfile): print(f"Run distribusi on this folder: {userfolder} with css:{cssfile}") parser = build_argparser() - args = parser.parse_args(["-t", "--menu-with-index", "-s", cssfile]) + args = parser.parse_args(["-t", "-a", "--menu-with-index", "-s", cssfile]) distribusify(args, userfolder) -- 2.39.2 From b9cc82b8f2a9d6b4ebd2eef39a5fb097c714109c Mon Sep 17 00:00:00 2001 From: crunk Date: Thu, 27 Jun 2024 11:03:35 +0200 Subject: [PATCH 42/49] descriptions added --- requirements.txt | 2 +- verse/describer/describe_files.py | 14 ++++++++++++- verse/distribusikan/add_files_to_describer.py | 8 ++++++++ verse/distribusikan/distribusi_selector.py | 4 +++- verse/migrations/env.py | 20 ++++++++++--------- verse/statuspengguna/helper.py | 4 +++- 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/requirements.txt b/requirements.txt index 4ce5362..374fc78 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ bleach-allowlist==1.0.3 blinker==1.7.0 cffi click==8.1.7 -distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@5934122c6ec1452d975b7cfe6582f9417fd5fdd0 +distribusi @ git+https://git.vvvvvvaria.org/crunk/distribusi@3eefd6e5ca7048555d441df8c6fbf4f2e255acac dnspython==2.1.0 email-validator==1.1.3 Flask==3.0.3 diff --git a/verse/describer/describe_files.py b/verse/describer/describe_files.py index 32ee77b..f53c329 100644 --- a/verse/describer/describe_files.py +++ b/verse/describer/describe_files.py @@ -78,6 +78,7 @@ def describe_file(file_id): ) save_described_file_to_db(describe_form, distribusi_file) add_alttext_to_file(describe_form, distribusi_file) + add_description_to_file(describe_form, distribusi_file) distribusi = Distribusis.query.filter_by( id=distribusi_file.distribusi ).first() @@ -143,6 +144,17 @@ def add_alttext_to_file(describe_form, distribusi_file): if not describe_form.alttext.data: return filename_no_ext = os.path.splitext(distribusi_file.path)[0] - with open(f'{filename_no_ext}_alttext.txt', 'w') as alttext_file: + with open(f"{filename_no_ext}_alttext.txt", "w") as alttext_file: alttext_file.write(describe_form.alttext.data) return + + +def add_description_to_file(describe_form, distribusi_file): + if not describe_form.description.data: + return + filename_no_ext = os.path.splitext(distribusi_file.path)[0] + with open( + f"{filename_no_ext}_dv_description.txt", "w" + ) as description_file: + description_file.write(describe_form.description.data) + return diff --git a/verse/distribusikan/add_files_to_describer.py b/verse/distribusikan/add_files_to_describer.py index 5310e90..6773279 100644 --- a/verse/distribusikan/add_files_to_describer.py +++ b/verse/distribusikan/add_files_to_describer.py @@ -31,6 +31,10 @@ def _get_distribusi_from_path(path): def _add_distribusi_file_to_db(distribusi, full_path, type): app = get_app() app.logger.info(f"adding file to database: {full_path} type: {type}") + distribusi_file = DistribusiFiles.query.filter_by(path=full_path).first() + if distribusi_file is not None: + app.logger.error(f"File already in database: {full_path}") + return try: new_distribusi_file = DistribusiFiles( path=full_path, @@ -63,6 +67,10 @@ def add_distribusi_files_to_db(path): for root, dirs, files in os.walk(path, topdown=True): files = list(filter(lambda f: not f.startswith("."), files)) files = list(filter(lambda f: not f.endswith(".html"), files)) + files = list(filter(lambda f: not f.endswith("_thumbnail.jpg"), files)) + files = list(filter(lambda f: not f.endswith("_alttext.txt"), files)) + files = list(filter(lambda f: not f.endswith("_dv_description.txt"), files)) + for file in files: full_path = os.path.join(root, file) distribusi_file = DistribusiFiles.query.filter_by( diff --git a/verse/distribusikan/distribusi_selector.py b/verse/distribusikan/distribusi_selector.py index f42bd2e..b47b227 100644 --- a/verse/distribusikan/distribusi_selector.py +++ b/verse/distribusikan/distribusi_selector.py @@ -42,7 +42,9 @@ def distribusi_selector(): if selectorform.update.data: select_update_distribusi(selectorform.distribusis.data) current_distribusi = UserHelper.current_distribusi() - uploadform = auto_fill_in_upload_form(uploadform, current_distribusi) + uploadform = auto_fill_in_upload_form( + uploadform, current_distribusi + ) return render_distribusi_template( selectorform, uploadform, current_distribusi diff --git a/verse/migrations/env.py b/verse/migrations/env.py index 68feded..68a0091 100644 --- a/verse/migrations/env.py +++ b/verse/migrations/env.py @@ -14,17 +14,19 @@ config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata config.set_main_option( - 'sqlalchemy.url', - str(current_app.extensions['migrate'].db.get_engine().url).replace( - '%', '%%')) -target_metadata = current_app.extensions['migrate'].db.metadata + "sqlalchemy.url", + str(current_app.extensions["migrate"].db.get_engine().url).replace( + "%", "%%" + ), +) +target_metadata = current_app.extensions["migrate"].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -65,20 +67,20 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") - connectable = current_app.extensions['migrate'].db.get_engine() + connectable = current_app.extensions["migrate"].db.get_engine() with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata, process_revision_directives=process_revision_directives, - **current_app.extensions['migrate'].configure_args + **current_app.extensions["migrate"].configure_args, ) with context.begin_transaction(): diff --git a/verse/statuspengguna/helper.py b/verse/statuspengguna/helper.py index 5605bd9..c227155 100644 --- a/verse/statuspengguna/helper.py +++ b/verse/statuspengguna/helper.py @@ -76,7 +76,9 @@ class UserHelper: def distribusi_limit_reached(): user = User.query.filter_by(email=current_user.email).first() - distribusiamount = len(DistribusisInfo.get_user_distribusis(user.email)) + distribusiamount = len( + DistribusisInfo.get_user_distribusis(user.email) + ) if distribusiamount > 19: print("user already has 20 distribusis") return True -- 2.39.2 From 74035637ee98c218344283d0140324a4ae7571e7 Mon Sep 17 00:00:00 2001 From: crunk Date: Thu, 27 Jun 2024 11:23:02 +0200 Subject: [PATCH 43/49] small bugfixes --- verse/distribusikan/add_files_to_describer.py | 4 +++- verse/distribusikan/static/css/distribusikan.css | 3 +++ verse/distribusikan/static/css/editor.css | 2 +- .../templates/distribusikan/distribusi_workflow/editcss.html | 2 +- .../templates/distribusikan/distribusi_workflow/selector.html | 1 + 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/verse/distribusikan/add_files_to_describer.py b/verse/distribusikan/add_files_to_describer.py index 6773279..466f912 100644 --- a/verse/distribusikan/add_files_to_describer.py +++ b/verse/distribusikan/add_files_to_describer.py @@ -69,7 +69,9 @@ def add_distribusi_files_to_db(path): files = list(filter(lambda f: not f.endswith(".html"), files)) files = list(filter(lambda f: not f.endswith("_thumbnail.jpg"), files)) files = list(filter(lambda f: not f.endswith("_alttext.txt"), files)) - files = list(filter(lambda f: not f.endswith("_dv_description.txt"), files)) + files = list( + filter(lambda f: not f.endswith("_dv_description.txt"), files) + ) for file in files: full_path = os.path.join(root, file) diff --git a/verse/distribusikan/static/css/distribusikan.css b/verse/distribusikan/static/css/distribusikan.css index 55a5302..2083035 100644 --- a/verse/distribusikan/static/css/distribusikan.css +++ b/verse/distribusikan/static/css/distribusikan.css @@ -27,3 +27,6 @@ .workflow input{ max-width: 20em; } +.new_divider { + height: 5em; +} diff --git a/verse/distribusikan/static/css/editor.css b/verse/distribusikan/static/css/editor.css index 46c6e86..d8f2ed6 100644 --- a/verse/distribusikan/static/css/editor.css +++ b/verse/distribusikan/static/css/editor.css @@ -46,5 +46,5 @@ iframe { } #html { background-color: #9de457; - color: lightgrey; + color: black; } diff --git a/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html index 0170599..5c3f350 100644 --- a/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html +++ b/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html @@ -1,7 +1,7 @@

Step 3: Edit Custom CSS (Optional)

{% if files_uploaded or distribusi_live %} -

Go to CSS editor

+

Go to CSS editor

{% else %}

You need to upload your files first before you can select a css theme diff --git a/verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html index 6c95a0b..3880148 100644 --- a/verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html +++ b/verse/distribusikan/templates/distribusikan/distribusi_workflow/selector.html @@ -36,6 +36,7 @@ {% endfor %}


+
{% if limit_reached %}

You have reached your limit of distribusi websites

{% else %} -- 2.39.2 From 69dff0b24ca5793d6c9ac328c99f7cef97fd1df2 Mon Sep 17 00:00:00 2001 From: crunk Date: Thu, 27 Jun 2024 13:05:45 +0200 Subject: [PATCH 44/49] fix typo in link --- .../templates/distribusikan/distribusi_workflow/editcss.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html b/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html index 5c3f350..bd003fd 100644 --- a/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html +++ b/verse/distribusikan/templates/distribusikan/distribusi_workflow/editcss.html @@ -1,7 +1,7 @@

Step 3: Edit Custom CSS (Optional)

{% if files_uploaded or distribusi_live %} -

Go to CSS editor

+

Go to CSS editor

{% else %}

You need to upload your files first before you can select a css theme -- 2.39.2 From dd228c6c73720a5b5da63f8c41c7a1e116988643 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 29 Jun 2024 15:19:02 +0200 Subject: [PATCH 45/49] invert color buttons --- verse/static/css/style.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/verse/static/css/style.css b/verse/static/css/style.css index 37a7c61..85aabbf 100644 --- a/verse/static/css/style.css +++ b/verse/static/css/style.css @@ -49,7 +49,7 @@ div#buttons .distribusi input{ margin: 0.2em; } div#buttons .distribusi input:hover{ - background: #ffbf00; + background: #091411; color: #6df2cc; } fieldset.required { @@ -80,7 +80,7 @@ input { } input:hover { - background: #ffbf00; + background: #091411; color: #6df2cc; cursor: pointer; } -- 2.39.2 From d6f5d41fb709e49b3e83420bdc2cfe0a7bd525ac Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 29 Jun 2024 15:20:29 +0200 Subject: [PATCH 46/49] remove wdka from placeholder html --- verse/themes/editor/placeholder.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/verse/themes/editor/placeholder.html b/verse/themes/editor/placeholder.html index ffbc168..8846a56 100644 --- a/verse/themes/editor/placeholder.html +++ b/verse/themes/editor/placeholder.html @@ -6,14 +6,14 @@

example_video.mp4
-- 2.39.2 From 0ac59269e7ff9c270ee37d72fdda18b792fee260 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 29 Jun 2024 15:21:47 +0200 Subject: [PATCH 47/49] start of search --- verse/app.py | 3 ++ verse/search/forms/searchform.py | 4 ++ verse/search/search.py | 37 +++++++++++++++++- verse/search/search_index.py | 47 +++++++++++++++++++++++ verse/search/templates/search/search.html | 20 ++++++++++ verse/start.py | 5 ++- 6 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 verse/search/search_index.py diff --git a/verse/app.py b/verse/app.py index 529db20..8c9c355 100644 --- a/verse/app.py +++ b/verse/app.py @@ -8,6 +8,8 @@ from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from flask_wtf.csrf import CSRFProtect + + APP = Flask(__name__, static_folder="static") db = SQLAlchemy() migrate = Migrate() @@ -46,6 +48,7 @@ def create_app(): migrate.init_app(APP, db, render_as_batch=True) bcrypt.init_app(APP) + @APP.context_processor def inject_title(): return dict(title=APP.config["title"]) diff --git a/verse/search/forms/searchform.py b/verse/search/forms/searchform.py index 8925c53..d32296a 100644 --- a/verse/search/forms/searchform.py +++ b/verse/search/forms/searchform.py @@ -4,3 +4,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, validators from wtforms.validators import Length from wtforms.widgets import TextArea + +class SearchForm(FlaskForm): + searchfield = StringField("Search distribusi-verse archive") + submit = SubmitField("Search") diff --git a/verse/search/search.py b/verse/search/search.py index 83a40b0..8129d08 100644 --- a/verse/search/search.py +++ b/verse/search/search.py @@ -1,8 +1,41 @@ import os - +from flask import Blueprint, render_template from whoosh.fields import * from whoosh.index import open_dir from whoosh.qparser import QueryParser +from search.forms.searchform import SearchForm + +searchpages = Blueprint( + "search", + __name__, + template_folder="templates/search", + static_folder="static", +) SCRIPT_DIR = os.path.dirname(__file__) -DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../data")) +SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + +@searchpages.route("/", methods=["GET", "POST"]) +def searchpage(): + searchform = SearchForm() + found_distribusis = [] + if searchform.validate_on_submit(): + found_distribusis = search(searchform.searchfield.data) + template = render_template( + "search.html", + searchform=searchform, + found_distribusis=found_distribusis, + ) + return template + + +def search(searchinput): + """search and get search result titles and return them as distribusi ids""" + ix = open_dir(SEARCH_DATA_DIR) + with ix.searcher() as searcher: + query = QueryParser("content", ix.schema).parse(searchinput) + search_results = searcher.search(query) + found_distribusis = [] + for result in search_results: + found_distribusis.append(result["title"]) + return found_distribusis diff --git a/verse/search/search_index.py b/verse/search/search_index.py new file mode 100644 index 0000000..11d75d4 --- /dev/null +++ b/verse/search/search_index.py @@ -0,0 +1,47 @@ +import os +from whoosh.fields import * +from whoosh.index import create_in +from whoosh.qparser import QueryParser +from models.distribusi_model import Distribusis +import flask_apscheduler + + +SCRIPT_DIR = os.path.dirname(__file__) +SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + +def init_search_index(APP): + scheduler = flask_apscheduler.APScheduler() + scheduler.api_enabled = False + scheduler.init_app(APP) + scheduler.start() + index_distribusis(APP) + index_distribusi_files(APP) + + @scheduler.task("interval", id="update", minutes=60) + def update_search_index(): + index_distribusis(APP) + index_distribusi_files(APP) + + +def index_distribusis(APP): + schema = Schema( + title=TEXT(stored=True), path=ID(stored=True), content=TEXT + ) + ix = create_in(SEARCH_DATA_DIR, schema) + writer = ix.writer() + distribusis = _visible_distribusis(APP) + for distribusi in distribusis: + writer.add_document(title=distribusi.distribusiname, path="/a", content=distribusi.description) + writer.commit() + + +def index_distribusi_files(APP): + APP.logger.info("searching distribusi files not implemented yet.") + + +def _visible_distribusis(APP): + with APP.app_context(): + distribusis = Distribusis.query.filter( + Distribusis.visible.isnot(False) + ).all() + return distribusis diff --git a/verse/search/templates/search/search.html b/verse/search/templates/search/search.html index 6925b8d..a4261cc 100644 --- a/verse/search/templates/search/search.html +++ b/verse/search/templates/search/search.html @@ -1,3 +1,23 @@ {% extends "base/base.html" %} {% block main %} +
+ + {{ searchform.csrf_token }} +
+ {{ searchform.searchfield.label }} + {{ searchform.searchfield }} + {% for message in searchform.searchfield.errors %} +
{{ message }}
+ {% endfor %} +
+
+ {{ searchform.submit }} +
+ +
+ {% for found_distribusis in found_distribusis %} +

{{found_distribusis}}

+ {% endfor %} +
+
{% endblock %} diff --git a/verse/start.py b/verse/start.py index 75de5be..f5bf472 100644 --- a/verse/start.py +++ b/verse/start.py @@ -26,6 +26,8 @@ from statuspengguna.forgotpassword import forgot_password from statuspengguna.helper import UserHelper from statuspengguna.loginuser import login_section from statuspengguna.registeruser import register_user +from search.search import searchpages +from search.search_index import init_search_index APP = create_app() stash_page = Blueprint("stash_page", __name__, static_folder="stash") @@ -36,7 +38,8 @@ APP.register_blueprint(register_user, url_prefix="/register") APP.register_blueprint(forgot_password, url_prefix="/login/forgotpassword") APP.register_blueprint(admin_page, url_prefix="/admin") APP.register_blueprint(distribusikan, url_prefix="/distribusikan") - +APP.register_blueprint(searchpages, url_prefix="/search") +init_search_index(APP) @APP.before_request def session_handler(): -- 2.39.2 From d9d33a877abdde1522aa3528b4be5fbdf3a2e886 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 29 Jun 2024 15:25:28 +0200 Subject: [PATCH 48/49] ruff formatting --- .gitignore | 1 + verse/app.py | 2 -- verse/search/forms/searchform.py | 1 + verse/search/search.py | 2 +- verse/search/search_index.py | 7 ++++++- verse/start.py | 1 + 6 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e7045b6..f273bbd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ pip-wheel-metadata/ verse/tmpupload/* verse/stash/* +verse/search/searchdata/* *.db diff --git a/verse/app.py b/verse/app.py index 8c9c355..ff47f2b 100644 --- a/verse/app.py +++ b/verse/app.py @@ -9,7 +9,6 @@ from flask_sqlalchemy import SQLAlchemy from flask_wtf.csrf import CSRFProtect - APP = Flask(__name__, static_folder="static") db = SQLAlchemy() migrate = Migrate() @@ -48,7 +47,6 @@ def create_app(): migrate.init_app(APP, db, render_as_batch=True) bcrypt.init_app(APP) - @APP.context_processor def inject_title(): return dict(title=APP.config["title"]) diff --git a/verse/search/forms/searchform.py b/verse/search/forms/searchform.py index d32296a..707c9b7 100644 --- a/verse/search/forms/searchform.py +++ b/verse/search/forms/searchform.py @@ -5,6 +5,7 @@ from wtforms import StringField, SubmitField, validators from wtforms.validators import Length from wtforms.widgets import TextArea + class SearchForm(FlaskForm): searchfield = StringField("Search distribusi-verse archive") submit = SubmitField("Search") diff --git a/verse/search/search.py b/verse/search/search.py index 8129d08..8628da2 100644 --- a/verse/search/search.py +++ b/verse/search/search.py @@ -31,7 +31,7 @@ def searchpage(): def search(searchinput): """search and get search result titles and return them as distribusi ids""" - ix = open_dir(SEARCH_DATA_DIR) + ix = open_dir(SEARCH_DATA_DIRgi) with ix.searcher() as searcher: query = QueryParser("content", ix.schema).parse(searchinput) search_results = searcher.search(query) diff --git a/verse/search/search_index.py b/verse/search/search_index.py index 11d75d4..88c9dd0 100644 --- a/verse/search/search_index.py +++ b/verse/search/search_index.py @@ -9,6 +9,7 @@ import flask_apscheduler SCRIPT_DIR = os.path.dirname(__file__) SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + def init_search_index(APP): scheduler = flask_apscheduler.APScheduler() scheduler.api_enabled = False @@ -31,7 +32,11 @@ def index_distribusis(APP): writer = ix.writer() distribusis = _visible_distribusis(APP) for distribusi in distribusis: - writer.add_document(title=distribusi.distribusiname, path="/a", content=distribusi.description) + writer.add_document( + title=distribusi.distribusiname, + path="/a", + content=distribusi.description, + ) writer.commit() diff --git a/verse/start.py b/verse/start.py index f5bf472..368a594 100644 --- a/verse/start.py +++ b/verse/start.py @@ -41,6 +41,7 @@ APP.register_blueprint(distribusikan, url_prefix="/distribusikan") APP.register_blueprint(searchpages, url_prefix="/search") init_search_index(APP) + @APP.before_request def session_handler(): session.permanent = True -- 2.39.2 From b6313e2dc4b6a08903185e3af841cff742080a74 Mon Sep 17 00:00:00 2001 From: crunk Date: Sat, 29 Jun 2024 15:41:31 +0200 Subject: [PATCH 49/49] clickable link in search results --- verse/search/search.py | 3 ++- verse/search/templates/search/search.html | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/verse/search/search.py b/verse/search/search.py index 8628da2..d38a0e6 100644 --- a/verse/search/search.py +++ b/verse/search/search.py @@ -15,6 +15,7 @@ searchpages = Blueprint( SCRIPT_DIR = os.path.dirname(__file__) SEARCH_DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "searchdata")) + @searchpages.route("/", methods=["GET", "POST"]) def searchpage(): searchform = SearchForm() @@ -31,7 +32,7 @@ def searchpage(): def search(searchinput): """search and get search result titles and return them as distribusi ids""" - ix = open_dir(SEARCH_DATA_DIRgi) + ix = open_dir(SEARCH_DATA_DIR) with ix.searcher() as searcher: query = QueryParser("content", ix.schema).parse(searchinput) search_results = searcher.search(query) diff --git a/verse/search/templates/search/search.html b/verse/search/templates/search/search.html index a4261cc..709b965 100644 --- a/verse/search/templates/search/search.html +++ b/verse/search/templates/search/search.html @@ -15,8 +15,8 @@
- {% for found_distribusis in found_distribusis %} -

{{found_distribusis}}

+ {% for found_distribusi in found_distribusis %} + {{found_distribusi}} {% endfor %}
-- 2.39.2