diff --git a/.gitignore b/.gitignore index 2ac87d2..44dd5d9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,7 @@ /venv/ .idea/ /.idea -/static -static/ \ No newline at end of file +/incepted/static +incepted/static/ +/incepted/logfiles/main.log +/incepted/db/incepted.db diff --git a/configuration_template b/incepted/configuration_template similarity index 100% rename from configuration_template rename to incepted/configuration_template diff --git a/data/__all_models.py b/incepted/data/__all_models.py similarity index 100% rename from data/__all_models.py rename to incepted/data/__all_models.py diff --git a/data/answer.py b/incepted/data/answer.py similarity index 100% rename from data/answer.py rename to incepted/data/answer.py diff --git a/data/db_session.py b/incepted/data/db_session.py similarity index 100% rename from data/db_session.py rename to incepted/data/db_session.py diff --git a/data/files.py b/incepted/data/files.py similarity index 100% rename from data/files.py rename to incepted/data/files.py diff --git a/data/projects.py b/incepted/data/projects.py similarity index 100% rename from data/projects.py rename to incepted/data/projects.py diff --git a/data/proof_file.py b/incepted/data/proof_file.py similarity index 100% rename from data/proof_file.py rename to incepted/data/proof_file.py diff --git a/data/quests.py b/incepted/data/quests.py similarity index 100% rename from data/quests.py rename to incepted/data/quests.py diff --git a/data/roles.py b/incepted/data/roles.py similarity index 100% rename from data/roles.py rename to incepted/data/roles.py diff --git a/data/showcase_link.py b/incepted/data/showcase_link.py similarity index 100% rename from data/showcase_link.py rename to incepted/data/showcase_link.py diff --git a/data/staff_projects.py b/incepted/data/staff_projects.py similarity index 100% rename from data/staff_projects.py rename to incepted/data/staff_projects.py diff --git a/data/users.py b/incepted/data/users.py similarity index 100% rename from data/users.py rename to incepted/data/users.py diff --git a/db/заглушка b/incepted/db/заглушка similarity index 100% rename from db/заглушка rename to incepted/db/заглушка diff --git a/forms/conf_delete_project.py b/incepted/forms/conf_delete_project.py similarity index 100% rename from forms/conf_delete_project.py rename to incepted/forms/conf_delete_project.py diff --git a/forms/edit_profile.py b/incepted/forms/edit_profile.py similarity index 100% rename from forms/edit_profile.py rename to incepted/forms/edit_profile.py diff --git a/forms/egg.py b/incepted/forms/egg.py similarity index 100% rename from forms/egg.py rename to incepted/forms/egg.py diff --git a/forms/encrypt_form.py b/incepted/forms/encrypt_form.py similarity index 100% rename from forms/encrypt_form.py rename to incepted/forms/encrypt_form.py diff --git a/forms/find_project.py b/incepted/forms/find_project.py similarity index 100% rename from forms/find_project.py rename to incepted/forms/find_project.py diff --git a/forms/link_showcase.py b/incepted/forms/link_showcase.py similarity index 100% rename from forms/link_showcase.py rename to incepted/forms/link_showcase.py diff --git a/forms/login.py b/incepted/forms/login.py similarity index 100% rename from forms/login.py rename to incepted/forms/login.py diff --git a/forms/project.py b/incepted/forms/project.py similarity index 100% rename from forms/project.py rename to incepted/forms/project.py diff --git a/forms/recovery.py b/incepted/forms/recovery.py similarity index 100% rename from forms/recovery.py rename to incepted/forms/recovery.py diff --git a/forms/register.py b/incepted/forms/register.py similarity index 100% rename from forms/register.py rename to incepted/forms/register.py diff --git a/forms/task.py b/incepted/forms/task.py similarity index 100% rename from forms/task.py rename to incepted/forms/task.py diff --git a/functions.py b/incepted/functions.py similarity index 96% rename from functions.py rename to incepted/functions.py index 36f7489..4c2e5d9 100644 --- a/functions.py +++ b/incepted/functions.py @@ -1,267 +1,267 @@ -import datetime -import os -import shutil -import smtplib -from json import loads -from email.message import EmailMessage - -from data.answer import Answer -from data.proof_file import FileProof -from data.quests import Quests -from data.roles import Roles -from data.users import User -from data.staff_projects import StaffProjects -from data.files import Files -from data import db_session - -import uuid -import pymorphy2 - - -def check_password(password=''): - smb = 'qwertyuiopasdfghjklzxcvbnm' - if len(password) < 6: - return 'Пароль должен быть длиннее 6 символов' - elif False in [True if i.isalpha() and i.lower() in smb or i.isdigit() else False for i in password]: - return 'Пароль может содержать только буквы латинского алфавита и цифры' - elif True not in [True if i.isdigit() else False for i in password]: - return 'Пароль должен содержать буквы разного регистра и цифры' - elif False not in [True if i.islower() and i.isalpha() else False for i in password]: - return 'Пароль должен содержать буквы разного регистра и цифры' - else: - return 'OK' - - -def mail(msg, to, topic='Подтверждение почты'): - with open('incepted.config', 'r', encoding='utf-8') as file: - file = loads(file.read()) - login, password = file["mail_login"], file["mail_password"] - email_server = "smtp.yandex.ru" - sender = "incepted@yandex.ru" - em = EmailMessage() - em.set_content(msg) - em['To'] = to - em['From'] = sender - em['Subject'] = topic - mailServer = smtplib.SMTP(email_server) - mailServer.set_debuglevel(1) - mailServer.ehlo() - mailServer.starttls() - mailServer.ehlo() - mailServer.login(login, password) - mailServer.ehlo() - mailServer.send_message(em) - mailServer.quit() - - -def init_db_default(): - data_session = db_session.create_session() - roles = [['admin', 90], ['moderator', 75], ['counselor', 45], ['user', 0]] - for i in roles: - role = Roles( - name=i[0], - rights=i[1] - ) - data_session.add(role) - data_session.commit() - data_session.close() - - -def get_user_data(user): - resp = { - 'id': user.id, - 'name': user.name, - 'surname': user.surname, - 'login': user.login, - 'email': user.email, - 'photo': user.photo, - 'role': user.role - } - return resp - - -def get_projects_data(project): - data_session = db_session.create_session() - staff = data_session.query(StaffProjects.user).filter(StaffProjects.project == project.id).all() - resp = { - 'id': project.id, - 'name': project.name, - 'logo': project.photo, - 'description': project.description, - 'staff': list(map(lambda x: get_user_data(x), data_session.query(User).filter( - User.id.in_(list(map(lambda x: x[0], staff)))).all())) if staff else [] - } - resp['staff'].insert(0, get_user_data(data_session.query(User).filter(User.id == project.creator).first())) - return resp - - -def save_project_logo(photo): - filename = f'static/app_files/project_logo/{uuid.uuid4()}.png' - with open(filename, 'wb') as f: - photo.save(f) - return filename - - -def overdue_quest_project(quest): - if quest.deadline is None: - quest.overdue = '' - elif str(quest.deadline.date()) == str(datetime.datetime.now().date()): - quest.overdue = 'today' - elif quest.deadline < datetime.datetime.now(): - quest.overdue = 'yes' - quest.time_left = 'Просрочено на' + round_date(quest.deadline) - elif quest.deadline > datetime.datetime.now(): - quest.overdue = 'no' - quest.time_left = 'Еще есть: ' + round_date(quest.deadline) - return quest - - -def round_date(date_time): - morph = pymorphy2.MorphAnalyzer() - difference = abs(date_time - datetime.datetime.now()).days - resp = '' - if difference // 365: - resp += f'{difference // 365} {morph.parse("год")[0].make_agree_with_number(difference // 365).word}' - difference -= 365 * (difference // 365) - if difference // 30: - resp += ', ' if resp else ' ' + f'{difference // 30}' \ - f' {morph.parse("месяц")[0].make_agree_with_number(difference // 30).word}' - difference -= 30 * (difference // 30) - if difference: - resp += ', ' if resp else ' ' + f'{difference} {morph.parse("день")[0].make_agree_with_number(difference).word}' - return f'{resp}' - - -def save_proof_quest(project, file, user_id): - data_session = db_session.create_session() - path = f'static/app_files/all_projects/{str(project.id)}/{str(file.filename)}' - file_check = data_session.query(Files).filter(Files.path == path).first() - file.save(path) - if file_check: - return file_check.id - file = Files( - path=path, - user=user_id, - up_date=datetime.datetime.now() - ) - data_session.add(file) - data_session.flush() - data_session.refresh(file) - file_id = file.id - data_session.commit() - data_session.close() - return file_id - - -def find_files_answer(file_id): - data_session = db_session.create_session() - file = data_session.query(Files).filter(Files.id == file_id).first() - return {'id': file.id, 'path': file.path, 'user': file.user, 'up_date': file.up_date, - 'current_path': file.path[str(file.path).find('all_projects') + 13:].split('/')} - - -def file_tree(path): - tree = [] - data_session = db_session.create_session() - h = 1 - for i in os.listdir(path): - if os.path.isfile(f'{path}/{i}'): - file = data_session.query(Files).filter(Files.path == f'{path}/{i}').first() - tree.append( - { - 'path': f'{path}/{i}', - 'type': 'file', - 'object': file if file else None, - 'current_path': f'{path}/{i}'[str(file.path).find('all_projects') + 13:].split('/') - } - ) - else: - tree.append( - { - 'id': h, - 'name': i, - 'path': f'{path}/{i}', - 'type': 'folder', - 'tree': file_tree(f'{path}/{i}') - } - ) - h += 1 - data_session.close() - return tree - - -def delete_file_proof_data(file_proof, data_session): - file = data_session.query(Files).filter(Files.id == file_proof.file).first() - data_session.delete(file) - - -def delete_answer_data(answer, data_session): - file_proofs = data_session.query(FileProof).filter(FileProof.answer == answer.id).all() - list(map(lambda file: delete_file_proof_data(file, data_session), file_proofs)) - list(map(data_session.delete, file_proofs)) - - -def delete_quest_data(quest, data_session): - answers = data_session.query(Answer).filter(Answer.quest == quest.id).all() - list(map(lambda answer: delete_answer_data(answer, data_session), answers)) - list(map(data_session.delete, answers)) - - -def delete_project_data(project, data_session): - staff = data_session.query(StaffProjects).filter(StaffProjects.project == project.id).all() - list(map(data_session.delete, staff)) - if 'none_project' not in project.photo: - os.remove(project.photo) - quests = data_session.query(Quests).filter(Quests.project == project.id).all() - list(map(lambda quest: delete_quest_data(quest, data_session), quests)) - list(map(data_session.delete, quests)) - list(map(data_session.delete, - data_session.query(Files).filter(Files.path.contains(f'all_projects/{str(project.id)}/')).all())) - shutil.rmtree(f'static/app_files/all_projects/{str(project.id)}') - data_session.delete(project) - data_session.commit() - - -def copy_file_from_template(file, new_project, data_session, current_user): - path = f'static/app_files/all_projects/{str(new_project.id)}/{str(file.path).split("/")[-1]}' - shutil.copy(file.path, path) - new_file = Files( - path=path, - user=current_user.id, - up_date=datetime.datetime.now() - ) - data_session.add(new_file) - - -def copy_quests_from_template(quest, new_project, data_session, current_user): - new_quest = Quests( - project=new_project.id, - creator=current_user.id, - name=quest.name, - description=quest.description, - date_create=datetime.datetime.now(), - deadline=quest.deadline, - realized=False - ) - data_session.add(new_quest) - - -def copy_template(template, new_project, data_session, current_user): - os.mkdir(f'static/app_files/all_projects/{str(new_project.id)}') - if 'none_project' not in template.photo: - filename = f'static/app_files/project_logo/{uuid.uuid4()}.png' - shutil.copy(template.photo, filename) - new_project.photo = filename - else: - new_project.photo = 'static/images/none_project.png' - list(map(lambda file: copy_file_from_template(file, new_project, data_session, current_user), - data_session.query(Files).filter(Files.path.contains(f'all_projects/{str(template.id)}/')).all())) - list(map(lambda quest: copy_quests_from_template(quest, new_project, data_session, current_user), - data_session.query(Quests).filter(Quests.project == template.id).all())) - data_session.commit() - - -def save_admin_data(data, data_session): - user = data_session.query(User).filter(User.id == data[0].split('_')[-1]).first() - if user.role != data[1]: - user.role = data[1] +import datetime +import os +import shutil +import smtplib +from json import loads +from email.message import EmailMessage + +from data.answer import Answer +from data.proof_file import FileProof +from data.quests import Quests +from data.roles import Roles +from data.users import User +from data.staff_projects import StaffProjects +from data.files import Files +from data import db_session + +import uuid +import pymorphy2 + + +def check_password(password=''): + smb = 'qwertyuiopasdfghjklzxcvbnm' + if len(password) < 6: + return 'Пароль должен быть длиннее 6 символов' + elif False in [True if i.isalpha() and i.lower() in smb or i.isdigit() else False for i in password]: + return 'Пароль может содержать только буквы латинского алфавита и цифры' + elif True not in [True if i.isdigit() else False for i in password]: + return 'Пароль должен содержать буквы разного регистра и цифры' + elif False not in [True if i.islower() and i.isalpha() else False for i in password]: + return 'Пароль должен содержать буквы разного регистра и цифры' + else: + return 'OK' + + +def mail(msg, to, topic='Подтверждение почты'): + with open('../incepted.config', 'r', encoding='utf-8') as file: + file = loads(file.read()) + login, password = file["mail_login"], file["mail_password"] + email_server = "smtp.yandex.ru" + sender = "incepted@yandex.ru" + em = EmailMessage() + em.set_content(msg) + em['To'] = to + em['From'] = sender + em['Subject'] = topic + mailServer = smtplib.SMTP(email_server) + mailServer.set_debuglevel(1) + mailServer.ehlo() + mailServer.starttls() + mailServer.ehlo() + mailServer.login(login, password) + mailServer.ehlo() + mailServer.send_message(em) + mailServer.quit() + + +def init_db_default(): + data_session = db_session.create_session() + roles = [['admin', 90], ['moderator', 75], ['counselor', 45], ['user', 0]] + for i in roles: + role = Roles( + name=i[0], + rights=i[1] + ) + data_session.add(role) + data_session.commit() + data_session.close() + + +def get_user_data(user): + resp = { + 'id': user.id, + 'name': user.name, + 'surname': user.surname, + 'login': user.login, + 'email': user.email, + 'photo': user.photo, + 'role': user.role + } + return resp + + +def get_projects_data(project): + data_session = db_session.create_session() + staff = data_session.query(StaffProjects.user).filter(StaffProjects.project == project.id).all() + resp = { + 'id': project.id, + 'name': project.name, + 'logo': project.photo, + 'description': project.description, + 'staff': list(map(lambda x: get_user_data(x), data_session.query(User).filter( + User.id.in_(list(map(lambda x: x[0], staff)))).all())) if staff else [] + } + resp['staff'].insert(0, get_user_data(data_session.query(User).filter(User.id == project.creator).first())) + return resp + + +def save_project_logo(photo): + filename = f'static/app_files/project_logo/{uuid.uuid4()}.png' + with open(filename, 'wb') as f: + photo.save(f) + return filename + + +def overdue_quest_project(quest): + if quest.deadline is None: + quest.overdue = '' + elif str(quest.deadline.date()) == str(datetime.datetime.now().date()): + quest.overdue = 'today' + elif quest.deadline < datetime.datetime.now(): + quest.overdue = 'yes' + quest.time_left = 'Просрочено на' + round_date(quest.deadline) + elif quest.deadline > datetime.datetime.now(): + quest.overdue = 'no' + quest.time_left = 'Еще есть: ' + round_date(quest.deadline) + return quest + + +def round_date(date_time): + morph = pymorphy2.MorphAnalyzer() + difference = abs(date_time - datetime.datetime.now()).days + resp = '' + if difference // 365: + resp += f'{difference // 365} {morph.parse("год")[0].make_agree_with_number(difference // 365).word}' + difference -= 365 * (difference // 365) + if difference // 30: + resp += ', ' if resp else ' ' + f'{difference // 30}' \ + f' {morph.parse("месяц")[0].make_agree_with_number(difference // 30).word}' + difference -= 30 * (difference // 30) + if difference: + resp += ', ' if resp else ' ' + f'{difference} {morph.parse("день")[0].make_agree_with_number(difference).word}' + return f'{resp}' + + +def save_proof_quest(project, file, user_id): + data_session = db_session.create_session() + path = f'static/app_files/all_projects/{str(project.id)}/{str(file.filename)}' + file_check = data_session.query(Files).filter(Files.path == path).first() + file.save(path) + if file_check: + return file_check.id + file = Files( + path=path, + user=user_id, + up_date=datetime.datetime.now() + ) + data_session.add(file) + data_session.flush() + data_session.refresh(file) + file_id = file.id + data_session.commit() + data_session.close() + return file_id + + +def find_files_answer(file_id): + data_session = db_session.create_session() + file = data_session.query(Files).filter(Files.id == file_id).first() + return {'id': file.id, 'path': file.path, 'user': file.user, 'up_date': file.up_date, + 'current_path': file.path[str(file.path).find('all_projects') + 13:].split('/')} + + +def file_tree(path): + tree = [] + data_session = db_session.create_session() + h = 1 + for i in os.listdir(path): + if os.path.isfile(f'{path}/{i}'): + file = data_session.query(Files).filter(Files.path == f'{path}/{i}').first() + tree.append( + { + 'path': f'{path}/{i}', + 'type': 'file', + 'object': file if file else None, + 'current_path': f'{path}/{i}'[str(file.path).find('all_projects') + 13:].split('/') + } + ) + else: + tree.append( + { + 'id': h, + 'name': i, + 'path': f'{path}/{i}', + 'type': 'folder', + 'tree': file_tree(f'{path}/{i}') + } + ) + h += 1 + data_session.close() + return tree + + +def delete_file_proof_data(file_proof, data_session): + file = data_session.query(Files).filter(Files.id == file_proof.file).first() + data_session.delete(file) + + +def delete_answer_data(answer, data_session): + file_proofs = data_session.query(FileProof).filter(FileProof.answer == answer.id).all() + list(map(lambda file: delete_file_proof_data(file, data_session), file_proofs)) + list(map(data_session.delete, file_proofs)) + + +def delete_quest_data(quest, data_session): + answers = data_session.query(Answer).filter(Answer.quest == quest.id).all() + list(map(lambda answer: delete_answer_data(answer, data_session), answers)) + list(map(data_session.delete, answers)) + + +def delete_project_data(project, data_session): + staff = data_session.query(StaffProjects).filter(StaffProjects.project == project.id).all() + list(map(data_session.delete, staff)) + if 'none_project' not in project.photo: + os.remove(project.photo) + quests = data_session.query(Quests).filter(Quests.project == project.id).all() + list(map(lambda quest: delete_quest_data(quest, data_session), quests)) + list(map(data_session.delete, quests)) + list(map(data_session.delete, + data_session.query(Files).filter(Files.path.contains(f'all_projects/{str(project.id)}/')).all())) + shutil.rmtree(f'static/app_files/all_projects/{str(project.id)}') + data_session.delete(project) + data_session.commit() + + +def copy_file_from_template(file, new_project, data_session, current_user): + path = f'static/app_files/all_projects/{str(new_project.id)}/{str(file.path).split("/")[-1]}' + shutil.copy(file.path, path) + new_file = Files( + path=path, + user=current_user.id, + up_date=datetime.datetime.now() + ) + data_session.add(new_file) + + +def copy_quests_from_template(quest, new_project, data_session, current_user): + new_quest = Quests( + project=new_project.id, + creator=current_user.id, + name=quest.name, + description=quest.description, + date_create=datetime.datetime.now(), + deadline=quest.deadline, + realized=False + ) + data_session.add(new_quest) + + +def copy_template(template, new_project, data_session, current_user): + os.mkdir(f'static/app_files/all_projects/{str(new_project.id)}') + if 'none_project' not in template.photo: + filename = f'static/app_files/project_logo/{uuid.uuid4()}.png' + shutil.copy(template.photo, filename) + new_project.photo = filename + else: + new_project.photo = 'static/images/none_project.png' + list(map(lambda file: copy_file_from_template(file, new_project, data_session, current_user), + data_session.query(Files).filter(Files.path.contains(f'all_projects/{str(template.id)}/')).all())) + list(map(lambda quest: copy_quests_from_template(quest, new_project, data_session, current_user), + data_session.query(Quests).filter(Quests.project == template.id).all())) + data_session.commit() + + +def save_admin_data(data, data_session): + user = data_session.query(User).filter(User.id == data[0].split('_')[-1]).first() + if user.role != data[1]: + user.role = data[1] diff --git a/logfiles/заглушка b/incepted/logfiles/заглушка similarity index 100% rename from logfiles/заглушка rename to incepted/logfiles/заглушка diff --git a/main.py b/incepted/main.py similarity index 97% rename from main.py rename to incepted/main.py index 644e782..7b442b7 100644 --- a/main.py +++ b/incepted/main.py @@ -1,874 +1,874 @@ -import datetime -import os -import logging - -from flask import Flask, render_template, request, url_for -from flask_login import login_user, current_user, LoginManager, logout_user, login_required -from flask_wtf import CSRFProtect -from flask_restful import abort -from werkzeug.datastructures import CombinedMultiDict -from werkzeug.utils import redirect -from itsdangerous import URLSafeTimedSerializer, SignatureExpired -from sqlalchemy import or_ -from json import loads -from waitress import serve - -from forms.egg import EggForm -from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo, \ - overdue_quest_project, save_proof_quest, find_files_answer, file_tree, delete_project_data, delete_quest_data, \ - copy_template, save_admin_data - -from forms.edit_profile import EditProfileForm -from forms.link_showcase import AddLink -from forms.login import LoginForm -from forms.find_project import FindProjectForm -from forms.register import RegisterForm -from forms.project import ProjectForm, AddFileProject -from forms.recovery import RecoveryForm, NewPasswordForm -from forms.conf_delete_project import DeleteProjectForm -from forms.task import Task, AnswerTask -from forms.encrypt_form import EncryptForm - -from data.users import User -from data.quests import Quests -from data.answer import Answer -from data.proof_file import FileProof -from data.files import Files -from data.projects import Projects -from data.staff_projects import StaffProjects -from data.roles import Roles -from data.showcase_link import ShowCaseLink -from data import db_session - -app = Flask(__name__) -with open('incepted.config', 'r', encoding='utf-8') as file: - file = file.read() - file = loads(file) -key = file["encrypt_key"] -app.config['SECRET_KEY'] = key -logging.basicConfig(level=logging.INFO, filename="logfiles/main.log", format="%(asctime)s %(levelname)s %(message)s", - encoding='utf-8') -csrf = CSRFProtect(app) -s = URLSafeTimedSerializer(key) -login_manager = LoginManager() -login_manager.init_app(app) - - -@app.route('/') -def base(): - if not current_user.is_authenticated: - return render_template('main.html', title='Главная') - else: - return redirect('/projects') - - -@app.route('/admin/user/', methods=['GET', 'POST']) -def admin_user(login_usr): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - if current_user.role == 1: - data_session = db_session.create_session() - user = data_session.query(User).filter(User.login == login_usr).first() - if user and user.role != 1: - form = EditProfileForm( - CombinedMultiDict((request.files, request.form)), - email=user.email, - name=user.name, - surname=user.surname, - about=user.about, - birthday=user.birthday - ) - if form.del_photo.data: - os.remove(user.photo) - user.photo = 'static/images/none_logo.png' - data_session.commit() - if form.validate_on_submit(): - if form.photo.data: - with open(f'static/app_files/user_logo/{user.login}.png', 'wb') as file: - form.photo.data.save(file) - user.photo = f'static/app_files/user_logo/{user.login}.png' - user.name = form.name.data - user.surname = form.surname.data - user.about = form.about.data - user.birthday = form.birthday.data - user.email = form.email.data - data_session.commit() - return redirect(f'/admin/user/{str(login_usr)}') - return render_template('profile.html', title=user.login, form=form, message='', user=user, admin=True) - else: - abort(403) - abort(404) - - -@app.route('/admin', methods=['GET', 'POST']) -def admin(): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - if current_user.role == 1: - data_session = db_session.create_session() - roles, users = data_session.query(Roles).all(), \ - data_session.query(User).filter(User.id != current_user.id).all() - form = EncryptForm() - egg_form = EggForm() - if request.method == 'POST': - if egg_form.egg.data: - with open('egg.txt', 'w', encoding='utf-8') as file_egg: - file_egg.write('1') - else: - with open('egg.txt', 'w', encoding='utf-8') as file_egg: - file_egg.write('2') - data_form = request.form.to_dict() - del data_form['csrf_token'], data_form['submit'] - data_form = list(map(lambda x: (x[0], x[1]), data_form.items())) - list( - map(lambda x: save_admin_data(x, data_session), list(filter(lambda x: 'role_' in x[0], data_form)))) - activ_id = list( - map(lambda user: int(user[0].split('_')[-1]), list(filter(lambda x: 'active_' in x[0], data_form)))) - banned_id = list( - map(lambda user: int(user[0].split('_')[-1]), list(filter(lambda x: 'banned_' in x[0], data_form)))) - for user in users: - if int(user.role) != 1: - user.activated = 0 if user.id not in activ_id else 1 - user.banned = 0 if user.id not in banned_id else 1 - else: - user.banned = 0 - user.activated = 1 - data_session.commit() - with open('egg.txt', 'r', encoding='utf-8') as file_egg: - egg_form.egg.data = True if int(file_egg.read()) == 1 else False - return render_template('admin.html', title='Панель админа', roles=roles, users=users, - form=form, egg_form=egg_form) - abort(404) - - -@app.route('/template//create') -def create_by_template(id_template): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_template = data_session.query(Projects).filter(Projects.id == id_template).first() - if current_template: - add_project = Projects( - name=current_template.name, - description=current_template.description, - date_create=datetime.datetime.now(), - creator=current_user.id, - is_open=False, - is_template=False - ) - data_session.add(add_project) - data_session.flush() - data_session.refresh(add_project) - data_session.commit() - copy_template(current_template, add_project, data_session, current_user) - return redirect('/projects') - else: - abort(403) - else: - return redirect('/login') - - -@app.route('/template/') -def template_project(id_template): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_template).first() - if current_project: - quests = data_session.query(Quests).filter(Quests.project == current_project.id).all() - files_list = file_tree(f'static/app_files/all_projects/{current_project.id}') - return render_template('template_project.html', title=f'Шаблон {current_project.name}', - project=current_project, quests=quests, file_tree=files_list) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/showcase/link//delete') -def delete_link(id_link): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - if current_user.role in [1, 4]: - data_session = db_session.create_session() - link = data_session.query(ShowCaseLink).filter(ShowCaseLink.id == id_link).first() - if link: - data_session.delete(link) - data_session.commit() - return redirect('/showcase') - else: - abort(404) - else: - abort(403) - return redirect('/login') - - -@app.route('/showcase', methods=['GET', 'POST']) -def showcase(): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - form = AddLink() if current_user.role in [1, 4] else None - data_session = db_session.create_session() - if request.method == 'POST' and current_user.role in [1, 4]: - if form.validate_on_submit(): - link = ShowCaseLink( - link=form.link.data, - name=form.name.data, - user=current_user.id, - up_date=datetime.datetime.now() - ) - data_session.add(link) - data_session.commit() - return redirect('/showcase') - list_template = list(map(lambda curr_project: get_projects_data(curr_project), - data_session.query(Projects).filter(Projects.is_template == 1).all())) - list_links = data_session.query(ShowCaseLink).all() - return render_template('showcase.html', title='Витрина', list_template=list_template, list_links=list_links, - form=form) - else: - return redirect('/login') - - -@app.route('/project//quest//edit', methods=['GET', 'POST']) -def edit_quest(id_project, id_task): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - current_task = data_session.query(Quests).filter(Quests.id == id_task).first() - if current_project and current_task and current_task.project == current_project.id and ( - current_task.creator == current_user.id or current_project.creator == current_user.id) \ - or current_user.role == 1: - form = Task() - if request.method == 'GET': - form.name.data = current_task.name - form.description.data = current_task.description - if current_task.deadline: - form.deadline_time.data = current_task.deadline.time() - form.deadline_date.data = current_task.deadline.date() - if form.delete.data: - delete_quest_data(current_task, data_session) - data_session.delete(current_task) - data_session.commit() - return redirect(f'/project/{str(current_project.id)}') - if form.validate_on_submit(): - if form.deadline_date.data and form.deadline_time.data: - deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data) - else: - deadline = None - current_task.name = form.name.data if form.name.data else None - current_task.description = form.description.data if form.description.data else None - current_task.deadline = deadline - data_session.commit() - return redirect(f'/project/{str(current_project.id)}/quest/{str(current_task.id)}') - return render_template('edit_task.html', title='Редактирование задачи', form=form, porject=current_project, - task=current_task) - else: - abort(403) - else: - return redirect('/login') - - -@app.route('/project//file//delete') -def delete_file(id_project, id_file): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - from_path = request.args.get('from') if request.args.get('from') else '' - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - current_file = data_session.query(Files).filter(Files.id == id_file).first() - if current_project and current_file: - if current_user.id in map(lambda x: x[0], data_session.query(StaffProjects.user).filter( - StaffProjects.project == current_project.id).all()) or current_user.id == current_project.creator \ - or current_user.role == 1: - current_proof = data_session.query(FileProof).filter(FileProof.file == id_file).all() - os.remove(current_file.path) - data_session.delete(current_file) - if current_proof: - quest = data_session.query(Answer.quest).filter(Answer.id == current_proof[0].answer).first() - for i in current_proof: - data_session.delete(i) - data_session.commit() - if from_path == 'project': - return redirect(f'/project/{current_project.id}') - return redirect(f'/project/{current_project.id}/quest/{quest[0]}') - data_session.commit() - return redirect(f'/project/{current_project.id}') - else: - abort(403) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/project//quest/', methods=['GET', 'POST']) -def task_project(id_project, id_task): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - current_task = data_session.query(Quests).filter(Quests.id == id_task).first() - if current_project and current_task and current_task.project == current_project.id or current_user.role == 1: - form = AnswerTask() - current_answer = data_session.query(Answer).filter(Answer.quest == current_task.id).first() - list_files = None - if form.submit.data and request.method == 'POST': - if current_answer: - current_answer.text = form.text.data - current_answer.date_edit = datetime.datetime.now() - current_task.realized = form.realized.data - data_session.commit() - if form.file.data[0].filename: - files = list( - map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data)) - for i in files: - if not data_session.query(FileProof).filter(FileProof.answer == current_answer.id, - FileProof.file == i).first(): - proof_file = FileProof( - answer=current_answer.id, - file=i - ) - data_session.add(proof_file) - data_session.commit() - else: - if form.file.data[0].filename: - files = list( - map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data)) - else: - files = False - current_task.realized = form.realized.data - current_answer = Answer( - quest=current_task.id, - text=form.text.data, - creator=current_user.id, - date_create=datetime.datetime.now(), - date_edit=datetime.datetime.now() - ) - data_session.add(current_answer) - data_session.flush() - data_session.refresh(current_answer) - if files: - for i in files: - proof_file = FileProof( - answer=current_answer.id, - file=i - ) - data_session.add(proof_file) - data_session.commit() - return redirect(f'/project/{current_project.id}') - if current_answer and request.method == 'GET': - form.text.data = current_answer.text - form.realized.data = current_task.realized - files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all() - if files: - list_files = list(map(lambda x: find_files_answer(x.file), files)) - return render_template('answer.html', title='Решение', project=current_project, task=current_task, - form=form, list_files=list_files) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/project//quest/new', methods=['GET', 'POST']) -def new_task_project(id_project): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - if current_project: - form = Task() - if form.validate_on_submit(): - if form.deadline_date.data and form.deadline_time.data: - deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data) - else: - deadline = None - quest = Quests( - project=current_project.id, - creator=current_user.id, - name=form.name.data if form.name.data else None, - description=form.description.data if form.description.data else None, - date_create=datetime.datetime.now(), - deadline=deadline, - realized=False - ) - data_session.add(quest) - data_session.commit() - return redirect(f'/project/{str(current_project.id)}') - return render_template('new_task.html', title='Новая задача', form=form, porject=current_project) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/project//edit', methods=['GET', 'POST']) -def edit_project(id_project): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - if current_project: - staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all() - if current_user.id == current_project.creator or current_user.role == 1: - list_users = list( - map(lambda x: get_user_data(x), - data_session.query(User).filter(User.id != current_user.id, User.activated == 1).all())) - staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter( - User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else [] - form = ProjectForm() - if form.save.data: - new_staff = [] - for i in list_users: - if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id: - new_staff.append(i) - if i not in staff: - new_staffer = StaffProjects( - user=i['id'], - project=current_project.id, - role='user', - permission=3 - ) - data_session.add(new_staffer) - data_session.commit() - if sorted(new_staff, key=lambda x: x['id']) != sorted(staff, key=lambda x: x['id']): - for i in staff: - if i not in new_staff: - data_session.delete(data_session.query(StaffProjects).filter( - StaffProjects.user == i['id'], StaffProjects.project == current_project.id).first()) - data_session.commit() - if form.logo.data: - current_project.photo = save_project_logo(form.logo.data) - data_session.commit() - current_project.name = form.name.data - current_project.description = form.description.data - current_project.is_template = form.is_template.data - data_session.commit() - return redirect(f'/project/{current_project.id}') - if form.del_photo.data: - os.remove(current_project.photo) - current_project.photo = 'static/images/none_project.png' - data_session.commit() - return redirect(f'/project/{current_project.id}/edit') - form.name.data = current_project.name - form.description.data = current_project.description - form.is_template.data = current_project.is_template - return render_template('edit_project.html', title='Изменение проекта', form=form, list_users=list_users, - staff=staff, project=current_project) - else: - abort(403) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/project/', methods=['POST', 'GET']) -def project(id_project): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - current_project = data_session.query(Projects).filter(Projects.id == id_project).first() - if current_project: - staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all() - if current_user.id == current_project.creator or current_user.id in list( - map(lambda x: x.user, staff)) or current_user.role == 1: - staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter( - User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else [] - quests = data_session.query(Quests).filter(Quests.project == current_project.id).all() - if quests: - quests_sort = sorted(list(filter(lambda x: x.deadline is not None, quests)), - key=lambda x: (x.realized, x.deadline)) - quests = list(filter(lambda x: x.realized == 0, quests_sort)) + list( - filter(lambda x: x.deadline is None, quests)) + list( - filter(lambda x: x.realized == 1, quests_sort)) - quests = list(map(lambda x: overdue_quest_project(x), quests)) - files_list = file_tree(f'static/app_files/all_projects/{current_project.id}') - form_file = AddFileProject() - if form_file.validate_on_submit(): - if form_file.file.data[0].filename: - files = list( - map(lambda x: save_proof_quest(current_project, x, current_user.id), form_file.file.data)) - return redirect(f'/project/{str(current_project.id)}') - return render_template('project.html', - project=current_project, - title=current_project.name, - staff=staff, - quests=quests, - file_tree=files_list, - form_file=form_file) - else: - abort(403) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/recovery/confirmation/', methods=['GET', 'POST']) -def conf_recovery(token): - try: - user_email = s.loads(token, max_age=86400) - data_session = db_session.create_session() - user = data_session.query(User).filter(User.email == user_email).first() - if user: - form = NewPasswordForm() - if form.validate_on_submit(): - if form.password.data != form.repeat_password.data: - return render_template('recovery.html', title='Восстановление', form=form, recovery=0, - message='Пароли не совпадают') - status_password = check_password(form.password.data) - if status_password != 'OK': - return render_template('recovery.html', title='Восстановление', form=form, recovery=0, - message=str(status_password)) - user.set_password(form.password.data) - data_session.commit() - mail(f'Для аккаунта {user.login}, успешно был обновлен пароль', user.email, - 'Изменение пароля') - return redirect('/login?message=Пароль обновлен') - return render_template('recovery.html', title='Восстановление', form=form, recovery=0, message='') - else: - return redirect('/login?message=Пользователь не найден&danger=True') - except SignatureExpired: - return redirect('/login?message=Срок действия ссылки истек&danger=True') - - -@app.route('/recovery', methods=['GET', 'POST']) -def recovery(): - if not current_user.is_authenticated: - form = RecoveryForm() - if form.validate_on_submit(): - token = s.dumps(form.email.data) - link_conf = url_for('conf_recovery', token=token, _external=True) - mail(f'Для сбросы пароля пройдите по ссылке: {link_conf}', form.email.data, - 'Восстановление доступа') - return redirect('/login?message=Мы выслали ссылку для сброса вам на почту') - return render_template('recovery.html', title='Восстановление пароля', form=form, recovery=True, message='') - else: - return redirect('/') - - -@app.route('/project//delete', methods=['GET', 'POST']) -def delete_project(id_project): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - project_del = data_session.query(Projects).filter(Projects.id == id_project).first() - if project_del: - if project_del.creator == current_user.id: - form = DeleteProjectForm() - if form.validate_on_submit(): - if str(form.conf.data).lower().strip() != f'delete/{str(project_del.name)}'.lower().strip(): - return render_template('delete_project.html', title='Удаление проекта', form=form, - project=project_del, - message='Вы не правильно ввели фразу') - delete_project_data(project_del, data_session) - return redirect('/projects') - return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del, - message='') - else: - abort(403) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/user/', methods=['GET', 'POST']) -def user_view(_login): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - user = data_session.query(User).filter(User.login == _login).first() - if user: - current_projects = data_session.query(Projects).filter(or_(Projects.creator == user.id, Projects.id.in_( - list(map(lambda x: x[0], data_session.query( - StaffProjects.project).filter( - StaffProjects.user == user.id).all()))))).all() - resp = list(map(lambda x: get_projects_data(x), current_projects)) - return render_template('user_view.html', - title=user.name if user.name else '' + ' ' + user.surname if user.surname else '', - user=user, - list_projects=resp) - else: - abort(404) - else: - return redirect('/login') - - -@app.route('/projects/new', methods=['GET', 'POST']) -def new_project(): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - form = ProjectForm() - data_session = db_session.create_session() - list_users = list( - map(lambda x: get_user_data(x), data_session.query(User).filter(User.id != current_user.id).all())) - if form.validate_on_submit(): - current_project = Projects( - name=form.name.data, - description=form.description.data, - date_create=datetime.datetime.now(), - creator=current_user.id, - is_template=form.is_template.data - ) - current_project.photo = save_project_logo( - form.logo.data) if form.logo.data else 'static/images/none_project.png' - data_session.add(current_project) - data_session.flush() - data_session.refresh(current_project) - for i in list_users: - if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id: - new_staffer = StaffProjects( - user=i['id'], - project=current_project.id, - role='user', - permission=3 - ) - data_session.add(new_staffer) - data_session.commit() - os.mkdir(f'static/app_files/all_projects/{str(current_project.id)}') - return redirect('/projects') - return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users) - else: - return redirect('/login') - - -@app.route('/projects', methods=['GET', 'POST']) -def projects(): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - find = False - form = FindProjectForm() - data_session = db_session.create_session() - resp = [] - current_projects = \ - data_session.query(Projects).filter(or_(Projects.creator == current_user.id, - Projects.id.in_( - list(map(lambda x: x[0], - data_session.query( - StaffProjects.project).filter( - StaffProjects.user - == current_user.id).all()))))).all() - if form.validate_on_submit(): - new_resp = [] - for i in range(len(current_projects)): - if str(form.project.data).lower().strip() in str(current_projects[i].name).lower().strip(): - new_resp.append(current_projects[i]) - current_projects = new_resp - find = True - resp = list(map(lambda x: get_projects_data(x), current_projects)) - return render_template('projects.html', title='Проекты', list_projects=resp, form=form, find=find) - else: - return redirect('/login') - - -@app.route('/profile', methods=['GET', 'POST']) -def profile(): - if current_user.is_authenticated: - if current_user.banned: - return redirect('/logout') - data_session = db_session.create_session() - form = EditProfileForm( - CombinedMultiDict((request.files, request.form)), - email=current_user.email, - name=current_user.name, - surname=current_user.surname, - about=current_user.about, - birthday=current_user.birthday - ) - if form.del_photo.data: - user = data_session.query(User).filter(User.id == current_user.id).first() - if not user: - return render_template('profile.html', title='Профиль', form=form, - message='Ошибка, пользователь ненайден', user=current_user, admin=False) - os.remove(current_user.photo) - user.photo = 'static/images/none_logo.png' - data_session.commit() - if form.validate_on_submit(): - user = data_session.query(User).filter(User.id == current_user.id).first() - if not user: - return render_template('profile.html', title='Профиль', form=form, - message='Ошибка, пользователь ненайден', user=current_user, admin=False) - if form.email.data != current_user.email: - token = s.dumps(form.email.data) - link_conf = url_for('confirmation', token=token, _external=True) - mail(f'Для изменения почты пройдите по ссылке: {link_conf}', form.email.data, - 'Изменение почты') - user.activated = False - user.email = form.email.data - if form.photo.data: - with open(f'static/app_files/user_logo/{current_user.login}.png', 'wb') as file: - form.photo.data.save(file) - user.photo = f'static/app_files/user_logo/{current_user.login}.png' - user.name = form.name.data - user.surname = form.surname.data - user.about = form.about.data - user.birthday = form.birthday.data - data_session.commit() - return redirect('/profile') - return render_template('profile.html', title='Профиль', form=form, message='', user=current_user, admin=False) - else: - return redirect('/login') - - -@login_manager.user_loader -def load_user(user_id): - db_sess = db_session.create_session() - return db_sess.query(User).get(user_id) - - -@app.route('/login', methods=['GET', 'POST']) -def login(): - if not current_user.is_authenticated: - message = request.args.get('message') if request.args.get('message') else '' - danger = request.args.get('danger') if request.args.get('danger') else False - form = LoginForm() - if form.validate_on_submit(): - data_session = db_session.create_session() - user = data_session.query(User).filter(User.email == form.login.data).first() - if not user: - user = data_session.query(User).filter(User.login == form.login.data).first() - if user and user.check_password(form.password.data): - if user.activated and not user.banned: - login_user(user, remember=form.remember_me.data) - logging.info(f'{user.login} logged in') - return redirect('/projects') - elif user.banned: - return render_template('login.html', - message="Ваш аккаунт заблокирован, обратитесь в поддержку: inepted@yandex.ru", - danger=True, - form=form) - else: - return render_template('login.html', - message="Ваша почта не подтверждена", - danger=True, - form=form) - return render_template('login.html', - message="Неправильный логин или пароль", - danger=True, - form=form) - return render_template('login.html', title='Авторизация', form=form, message=message, - danger=danger) - else: - return redirect('/projects') - - -@app.route('/logout') -@login_required -def logout(): - logging.info(f'{current_user.login} logged out') - logout_user() - return redirect("/") - - -@app.route('/register', methods=['GET', 'POST']) -def register(): - if not current_user.is_authenticated: - with open('egg.txt', 'r', encoding='utf-8') as file_egg: - egg = int(file_egg.read()) - form = RegisterForm() - if form.validate_on_submit(): - data_session = db_session.create_session() - if data_session.query(User).filter(User.login == form.login.data).first(): - return render_template('register.html', form=form, message="Такой пользователь уже есть", - title='Регистрация', egg=0) - if data_session.query(User).filter(User.email == form.email.data).first(): - return render_template('register.html', form=form, message="Такая почта уже есть", egg=0, - title='Регистрация') - status_password = check_password(form.password.data) - if status_password != 'OK': - return render_template('register.html', form=form, message=status_password, egg=0, - title='Регистрация') - user = User( - email=form.email.data, - name=form.name.data, - login=form.login.data, - activity=datetime.datetime.now(), - data_reg=datetime.date.today(), - photo='static/images/none_logo.png', - role=3 - ) - user.set_password(form.password.data) - data_session.add(user) - data_session.commit() - token = s.dumps(form.email.data) - link_conf = url_for('confirmation', token=token, _external=True) - mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, - 'Подтверждение регистрации') - logging.info(f'{form.login.data} was registered') - return redirect('/login?message=Мы выслали ссылку для подтверждения почты') - return render_template('register.html', form=form, message='', title='Регистрация', egg=egg) - else: - return redirect('/projects') - - -@app.route('/confirmation/') -def confirmation(token): - try: - user_email = s.loads(token, max_age=86400) - data_session = db_session.create_session() - user = data_session.query(User).filter(User.email == user_email).first() - if user: - user.activated = True - data_session.commit() - logging.info(f'{user.login} has been confirmed') - return redirect('/login?message=Почта успешно подтверждена') - else: - return redirect('/login?message=Пользователь не найден&danger=True') - except SignatureExpired: - data_session = db_session.create_session() - users = data_session.query(User).filter( - User.activated == 0 and User.activated < datetime.datetime.now() - datetime.timedelta(days=1)).all() - if users: - list(map(lambda x: data_session.delete(x), users)) - data_session.commit() - return redirect('/login?message=Срок действия ссылки истек, данные удалены&danger=True') - - -@app.errorhandler(500) -def internal_server_error(error): - return render_template('page_error.html', title='Ошибка сервера', error='500', message='Технические шоколадки') - - -@app.errorhandler(404) -def page_not_found(error): - return render_template('page_error.html', title='Страница не найдена', error='404', message='Страница не найдена') - - -@app.errorhandler(403) -def access_error(error): - return render_template('page_error.html', title='Ошибка доступа', error='403', message='Доступ сюда запрещен') - - -def main(): - db_path = 'db/incepted.db' - db = os.path.exists(db_path) - db_session.global_init(db_path) - if not db: - init_db_default() - serve(app, host='0.0.0.0', port=5000, threads=100) - - -if __name__ == '__main__': - try: - main() - except Exception as error: - logging.warning(f'{error}') +import datetime +import os +import logging + +from flask import Flask, render_template, request, url_for +from flask_login import login_user, current_user, LoginManager, logout_user, login_required +from flask_wtf import CSRFProtect +from flask_restful import abort +from werkzeug.datastructures import CombinedMultiDict +from werkzeug.utils import redirect +from itsdangerous import URLSafeTimedSerializer, SignatureExpired +from sqlalchemy import or_ +from json import loads +from waitress import serve + +from forms.egg import EggForm +from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo, \ + overdue_quest_project, save_proof_quest, find_files_answer, file_tree, delete_project_data, delete_quest_data, \ + copy_template, save_admin_data + +from forms.edit_profile import EditProfileForm +from forms.link_showcase import AddLink +from forms.login import LoginForm +from forms.find_project import FindProjectForm +from forms.register import RegisterForm +from forms.project import ProjectForm, AddFileProject +from forms.recovery import RecoveryForm, NewPasswordForm +from forms.conf_delete_project import DeleteProjectForm +from forms.task import Task, AnswerTask +from forms.encrypt_form import EncryptForm + +from data.users import User +from data.quests import Quests +from data.answer import Answer +from data.proof_file import FileProof +from data.files import Files +from data.projects import Projects +from data.staff_projects import StaffProjects +from data.roles import Roles +from data.showcase_link import ShowCaseLink +from data import db_session + +app = Flask(__name__) +with open('../incepted.config', 'r', encoding='utf-8') as file: + file = file.read() + file = loads(file) +key = file["encrypt_key"] +app.config['SECRET_KEY'] = key +logging.basicConfig(level=logging.INFO, filename="logfiles/main.log", format="%(asctime)s %(levelname)s %(message)s", + encoding='utf-8') +csrf = CSRFProtect(app) +s = URLSafeTimedSerializer(key) +login_manager = LoginManager() +login_manager.init_app(app) + + +@app.route('/') +def base(): + if not current_user.is_authenticated: + return render_template('main.html', title='Главная') + else: + return redirect('/projects') + + +@app.route('/admin/user/', methods=['GET', 'POST']) +def admin_user(login_usr): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + if current_user.role == 1: + data_session = db_session.create_session() + user = data_session.query(User).filter(User.login == login_usr).first() + if user and user.role != 1: + form = EditProfileForm( + CombinedMultiDict((request.files, request.form)), + email=user.email, + name=user.name, + surname=user.surname, + about=user.about, + birthday=user.birthday + ) + if form.del_photo.data: + os.remove(user.photo) + user.photo = 'static/images/none_logo.png' + data_session.commit() + if form.validate_on_submit(): + if form.photo.data: + with open(f'static/app_files/user_logo/{user.login}.png', 'wb') as file: + form.photo.data.save(file) + user.photo = f'static/app_files/user_logo/{user.login}.png' + user.name = form.name.data + user.surname = form.surname.data + user.about = form.about.data + user.birthday = form.birthday.data + user.email = form.email.data + data_session.commit() + return redirect(f'/admin/user/{str(login_usr)}') + return render_template('profile.html', title=user.login, form=form, message='', user=user, admin=True) + else: + abort(403) + abort(404) + + +@app.route('/admin', methods=['GET', 'POST']) +def admin(): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + if current_user.role == 1: + data_session = db_session.create_session() + roles, users = data_session.query(Roles).all(), \ + data_session.query(User).filter(User.id != current_user.id).all() + form = EncryptForm() + egg_form = EggForm() + if request.method == 'POST': + if egg_form.egg.data: + with open('../egg.txt', 'w', encoding='utf-8') as file_egg: + file_egg.write('1') + else: + with open('../egg.txt', 'w', encoding='utf-8') as file_egg: + file_egg.write('2') + data_form = request.form.to_dict() + del data_form['csrf_token'], data_form['submit'] + data_form = list(map(lambda x: (x[0], x[1]), data_form.items())) + list( + map(lambda x: save_admin_data(x, data_session), list(filter(lambda x: 'role_' in x[0], data_form)))) + activ_id = list( + map(lambda user: int(user[0].split('_')[-1]), list(filter(lambda x: 'active_' in x[0], data_form)))) + banned_id = list( + map(lambda user: int(user[0].split('_')[-1]), list(filter(lambda x: 'banned_' in x[0], data_form)))) + for user in users: + if int(user.role) != 1: + user.activated = 0 if user.id not in activ_id else 1 + user.banned = 0 if user.id not in banned_id else 1 + else: + user.banned = 0 + user.activated = 1 + data_session.commit() + with open('../egg.txt', 'r', encoding='utf-8') as file_egg: + egg_form.egg.data = True if int(file_egg.read()) == 1 else False + return render_template('admin.html', title='Панель админа', roles=roles, users=users, + form=form, egg_form=egg_form) + abort(404) + + +@app.route('/template//create') +def create_by_template(id_template): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_template = data_session.query(Projects).filter(Projects.id == id_template).first() + if current_template: + add_project = Projects( + name=current_template.name, + description=current_template.description, + date_create=datetime.datetime.now(), + creator=current_user.id, + is_open=False, + is_template=False + ) + data_session.add(add_project) + data_session.flush() + data_session.refresh(add_project) + data_session.commit() + copy_template(current_template, add_project, data_session, current_user) + return redirect('/projects') + else: + abort(403) + else: + return redirect('/login') + + +@app.route('/template/') +def template_project(id_template): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_template).first() + if current_project: + quests = data_session.query(Quests).filter(Quests.project == current_project.id).all() + files_list = file_tree(f'static/app_files/all_projects/{current_project.id}') + return render_template('template_project.html', title=f'Шаблон {current_project.name}', + project=current_project, quests=quests, file_tree=files_list) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/showcase/link//delete') +def delete_link(id_link): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + if current_user.role in [1, 4]: + data_session = db_session.create_session() + link = data_session.query(ShowCaseLink).filter(ShowCaseLink.id == id_link).first() + if link: + data_session.delete(link) + data_session.commit() + return redirect('/showcase') + else: + abort(404) + else: + abort(403) + return redirect('/login') + + +@app.route('/showcase', methods=['GET', 'POST']) +def showcase(): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + form = AddLink() if current_user.role in [1, 4] else None + data_session = db_session.create_session() + if request.method == 'POST' and current_user.role in [1, 4]: + if form.validate_on_submit(): + link = ShowCaseLink( + link=form.link.data, + name=form.name.data, + user=current_user.id, + up_date=datetime.datetime.now() + ) + data_session.add(link) + data_session.commit() + return redirect('/showcase') + list_template = list(map(lambda curr_project: get_projects_data(curr_project), + data_session.query(Projects).filter(Projects.is_template == 1).all())) + list_links = data_session.query(ShowCaseLink).all() + return render_template('showcase.html', title='Витрина', list_template=list_template, list_links=list_links, + form=form) + else: + return redirect('/login') + + +@app.route('/project//quest//edit', methods=['GET', 'POST']) +def edit_quest(id_project, id_task): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + current_task = data_session.query(Quests).filter(Quests.id == id_task).first() + if current_project and current_task and current_task.project == current_project.id and ( + current_task.creator == current_user.id or current_project.creator == current_user.id) \ + or current_user.role == 1: + form = Task() + if request.method == 'GET': + form.name.data = current_task.name + form.description.data = current_task.description + if current_task.deadline: + form.deadline_time.data = current_task.deadline.time() + form.deadline_date.data = current_task.deadline.date() + if form.delete.data: + delete_quest_data(current_task, data_session) + data_session.delete(current_task) + data_session.commit() + return redirect(f'/project/{str(current_project.id)}') + if form.validate_on_submit(): + if form.deadline_date.data and form.deadline_time.data: + deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data) + else: + deadline = None + current_task.name = form.name.data if form.name.data else None + current_task.description = form.description.data if form.description.data else None + current_task.deadline = deadline + data_session.commit() + return redirect(f'/project/{str(current_project.id)}/quest/{str(current_task.id)}') + return render_template('edit_task.html', title='Редактирование задачи', form=form, porject=current_project, + task=current_task) + else: + abort(403) + else: + return redirect('/login') + + +@app.route('/project//file//delete') +def delete_file(id_project, id_file): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + from_path = request.args.get('from') if request.args.get('from') else '' + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + current_file = data_session.query(Files).filter(Files.id == id_file).first() + if current_project and current_file: + if current_user.id in map(lambda x: x[0], data_session.query(StaffProjects.user).filter( + StaffProjects.project == current_project.id).all()) or current_user.id == current_project.creator \ + or current_user.role == 1: + current_proof = data_session.query(FileProof).filter(FileProof.file == id_file).all() + os.remove(current_file.path) + data_session.delete(current_file) + if current_proof: + quest = data_session.query(Answer.quest).filter(Answer.id == current_proof[0].answer).first() + for i in current_proof: + data_session.delete(i) + data_session.commit() + if from_path == 'project': + return redirect(f'/project/{current_project.id}') + return redirect(f'/project/{current_project.id}/quest/{quest[0]}') + data_session.commit() + return redirect(f'/project/{current_project.id}') + else: + abort(403) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/project//quest/', methods=['GET', 'POST']) +def task_project(id_project, id_task): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + current_task = data_session.query(Quests).filter(Quests.id == id_task).first() + if current_project and current_task and current_task.project == current_project.id or current_user.role == 1: + form = AnswerTask() + current_answer = data_session.query(Answer).filter(Answer.quest == current_task.id).first() + list_files = None + if form.submit.data and request.method == 'POST': + if current_answer: + current_answer.text = form.text.data + current_answer.date_edit = datetime.datetime.now() + current_task.realized = form.realized.data + data_session.commit() + if form.file.data[0].filename: + files = list( + map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data)) + for i in files: + if not data_session.query(FileProof).filter(FileProof.answer == current_answer.id, + FileProof.file == i).first(): + proof_file = FileProof( + answer=current_answer.id, + file=i + ) + data_session.add(proof_file) + data_session.commit() + else: + if form.file.data[0].filename: + files = list( + map(lambda x: save_proof_quest(current_project, x, current_user.id), form.file.data)) + else: + files = False + current_task.realized = form.realized.data + current_answer = Answer( + quest=current_task.id, + text=form.text.data, + creator=current_user.id, + date_create=datetime.datetime.now(), + date_edit=datetime.datetime.now() + ) + data_session.add(current_answer) + data_session.flush() + data_session.refresh(current_answer) + if files: + for i in files: + proof_file = FileProof( + answer=current_answer.id, + file=i + ) + data_session.add(proof_file) + data_session.commit() + return redirect(f'/project/{current_project.id}') + if current_answer and request.method == 'GET': + form.text.data = current_answer.text + form.realized.data = current_task.realized + files = data_session.query(FileProof).filter(FileProof.answer == current_answer.id).all() + if files: + list_files = list(map(lambda x: find_files_answer(x.file), files)) + return render_template('answer.html', title='Решение', project=current_project, task=current_task, + form=form, list_files=list_files) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/project//quest/new', methods=['GET', 'POST']) +def new_task_project(id_project): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + if current_project: + form = Task() + if form.validate_on_submit(): + if form.deadline_date.data and form.deadline_time.data: + deadline = datetime.datetime.combine(form.deadline_date.data, form.deadline_time.data) + else: + deadline = None + quest = Quests( + project=current_project.id, + creator=current_user.id, + name=form.name.data if form.name.data else None, + description=form.description.data if form.description.data else None, + date_create=datetime.datetime.now(), + deadline=deadline, + realized=False + ) + data_session.add(quest) + data_session.commit() + return redirect(f'/project/{str(current_project.id)}') + return render_template('new_task.html', title='Новая задача', form=form, porject=current_project) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/project//edit', methods=['GET', 'POST']) +def edit_project(id_project): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + if current_project: + staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all() + if current_user.id == current_project.creator or current_user.role == 1: + list_users = list( + map(lambda x: get_user_data(x), + data_session.query(User).filter(User.id != current_user.id, User.activated == 1).all())) + staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter( + User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else [] + form = ProjectForm() + if form.save.data: + new_staff = [] + for i in list_users: + if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id: + new_staff.append(i) + if i not in staff: + new_staffer = StaffProjects( + user=i['id'], + project=current_project.id, + role='user', + permission=3 + ) + data_session.add(new_staffer) + data_session.commit() + if sorted(new_staff, key=lambda x: x['id']) != sorted(staff, key=lambda x: x['id']): + for i in staff: + if i not in new_staff: + data_session.delete(data_session.query(StaffProjects).filter( + StaffProjects.user == i['id'], StaffProjects.project == current_project.id).first()) + data_session.commit() + if form.logo.data: + current_project.photo = save_project_logo(form.logo.data) + data_session.commit() + current_project.name = form.name.data + current_project.description = form.description.data + current_project.is_template = form.is_template.data + data_session.commit() + return redirect(f'/project/{current_project.id}') + if form.del_photo.data: + os.remove(current_project.photo) + current_project.photo = 'static/images/none_project.png' + data_session.commit() + return redirect(f'/project/{current_project.id}/edit') + form.name.data = current_project.name + form.description.data = current_project.description + form.is_template.data = current_project.is_template + return render_template('edit_project.html', title='Изменение проекта', form=form, list_users=list_users, + staff=staff, project=current_project) + else: + abort(403) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/project/', methods=['POST', 'GET']) +def project(id_project): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + current_project = data_session.query(Projects).filter(Projects.id == id_project).first() + if current_project: + staff = data_session.query(StaffProjects).filter(StaffProjects.project == current_project.id).all() + if current_user.id == current_project.creator or current_user.id in list( + map(lambda x: x.user, staff)) or current_user.role == 1: + staff = list(map(lambda x: get_user_data(x), data_session.query(User).filter( + User.id.in_(list(map(lambda x: x.user, staff)))).all())) if staff else [] + quests = data_session.query(Quests).filter(Quests.project == current_project.id).all() + if quests: + quests_sort = sorted(list(filter(lambda x: x.deadline is not None, quests)), + key=lambda x: (x.realized, x.deadline)) + quests = list(filter(lambda x: x.realized == 0, quests_sort)) + list( + filter(lambda x: x.deadline is None, quests)) + list( + filter(lambda x: x.realized == 1, quests_sort)) + quests = list(map(lambda x: overdue_quest_project(x), quests)) + files_list = file_tree(f'static/app_files/all_projects/{current_project.id}') + form_file = AddFileProject() + if form_file.validate_on_submit(): + if form_file.file.data[0].filename: + files = list( + map(lambda x: save_proof_quest(current_project, x, current_user.id), form_file.file.data)) + return redirect(f'/project/{str(current_project.id)}') + return render_template('project.html', + project=current_project, + title=current_project.name, + staff=staff, + quests=quests, + file_tree=files_list, + form_file=form_file) + else: + abort(403) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/recovery/confirmation/', methods=['GET', 'POST']) +def conf_recovery(token): + try: + user_email = s.loads(token, max_age=86400) + data_session = db_session.create_session() + user = data_session.query(User).filter(User.email == user_email).first() + if user: + form = NewPasswordForm() + if form.validate_on_submit(): + if form.password.data != form.repeat_password.data: + return render_template('recovery.html', title='Восстановление', form=form, recovery=0, + message='Пароли не совпадают') + status_password = check_password(form.password.data) + if status_password != 'OK': + return render_template('recovery.html', title='Восстановление', form=form, recovery=0, + message=str(status_password)) + user.set_password(form.password.data) + data_session.commit() + mail(f'Для аккаунта {user.login}, успешно был обновлен пароль', user.email, + 'Изменение пароля') + return redirect('/login?message=Пароль обновлен') + return render_template('recovery.html', title='Восстановление', form=form, recovery=0, message='') + else: + return redirect('/login?message=Пользователь не найден&danger=True') + except SignatureExpired: + return redirect('/login?message=Срок действия ссылки истек&danger=True') + + +@app.route('/recovery', methods=['GET', 'POST']) +def recovery(): + if not current_user.is_authenticated: + form = RecoveryForm() + if form.validate_on_submit(): + token = s.dumps(form.email.data) + link_conf = url_for('conf_recovery', token=token, _external=True) + mail(f'Для сбросы пароля пройдите по ссылке: {link_conf}', form.email.data, + 'Восстановление доступа') + return redirect('/login?message=Мы выслали ссылку для сброса вам на почту') + return render_template('recovery.html', title='Восстановление пароля', form=form, recovery=True, message='') + else: + return redirect('/') + + +@app.route('/project//delete', methods=['GET', 'POST']) +def delete_project(id_project): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + project_del = data_session.query(Projects).filter(Projects.id == id_project).first() + if project_del: + if project_del.creator == current_user.id: + form = DeleteProjectForm() + if form.validate_on_submit(): + if str(form.conf.data).lower().strip() != f'delete/{str(project_del.name)}'.lower().strip(): + return render_template('delete_project.html', title='Удаление проекта', form=form, + project=project_del, + message='Вы не правильно ввели фразу') + delete_project_data(project_del, data_session) + return redirect('/projects') + return render_template('delete_project.html', title='Удаление проекта', form=form, project=project_del, + message='') + else: + abort(403) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/user/', methods=['GET', 'POST']) +def user_view(_login): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + user = data_session.query(User).filter(User.login == _login).first() + if user: + current_projects = data_session.query(Projects).filter(or_(Projects.creator == user.id, Projects.id.in_( + list(map(lambda x: x[0], data_session.query( + StaffProjects.project).filter( + StaffProjects.user == user.id).all()))))).all() + resp = list(map(lambda x: get_projects_data(x), current_projects)) + return render_template('user_view.html', + title=user.name if user.name else '' + ' ' + user.surname if user.surname else '', + user=user, + list_projects=resp) + else: + abort(404) + else: + return redirect('/login') + + +@app.route('/projects/new', methods=['GET', 'POST']) +def new_project(): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + form = ProjectForm() + data_session = db_session.create_session() + list_users = list( + map(lambda x: get_user_data(x), data_session.query(User).filter(User.id != current_user.id).all())) + if form.validate_on_submit(): + current_project = Projects( + name=form.name.data, + description=form.description.data, + date_create=datetime.datetime.now(), + creator=current_user.id, + is_template=form.is_template.data + ) + current_project.photo = save_project_logo( + form.logo.data) if form.logo.data else 'static/images/none_project.png' + data_session.add(current_project) + data_session.flush() + data_session.refresh(current_project) + for i in list_users: + if request.form.getlist(f"choose_{i['login']}") and i['id'] != current_user.id: + new_staffer = StaffProjects( + user=i['id'], + project=current_project.id, + role='user', + permission=3 + ) + data_session.add(new_staffer) + data_session.commit() + os.mkdir(f'static/app_files/all_projects/{str(current_project.id)}') + return redirect('/projects') + return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users) + else: + return redirect('/login') + + +@app.route('/projects', methods=['GET', 'POST']) +def projects(): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + find = False + form = FindProjectForm() + data_session = db_session.create_session() + resp = [] + current_projects = \ + data_session.query(Projects).filter(or_(Projects.creator == current_user.id, + Projects.id.in_( + list(map(lambda x: x[0], + data_session.query( + StaffProjects.project).filter( + StaffProjects.user + == current_user.id).all()))))).all() + if form.validate_on_submit(): + new_resp = [] + for i in range(len(current_projects)): + if str(form.project.data).lower().strip() in str(current_projects[i].name).lower().strip(): + new_resp.append(current_projects[i]) + current_projects = new_resp + find = True + resp = list(map(lambda x: get_projects_data(x), current_projects)) + return render_template('projects.html', title='Проекты', list_projects=resp, form=form, find=find) + else: + return redirect('/login') + + +@app.route('/profile', methods=['GET', 'POST']) +def profile(): + if current_user.is_authenticated: + if current_user.banned: + return redirect('/logout') + data_session = db_session.create_session() + form = EditProfileForm( + CombinedMultiDict((request.files, request.form)), + email=current_user.email, + name=current_user.name, + surname=current_user.surname, + about=current_user.about, + birthday=current_user.birthday + ) + if form.del_photo.data: + user = data_session.query(User).filter(User.id == current_user.id).first() + if not user: + return render_template('profile.html', title='Профиль', form=form, + message='Ошибка, пользователь ненайден', user=current_user, admin=False) + os.remove(current_user.photo) + user.photo = 'static/images/none_logo.png' + data_session.commit() + if form.validate_on_submit(): + user = data_session.query(User).filter(User.id == current_user.id).first() + if not user: + return render_template('profile.html', title='Профиль', form=form, + message='Ошибка, пользователь ненайден', user=current_user, admin=False) + if form.email.data != current_user.email: + token = s.dumps(form.email.data) + link_conf = url_for('confirmation', token=token, _external=True) + mail(f'Для изменения почты пройдите по ссылке: {link_conf}', form.email.data, + 'Изменение почты') + user.activated = False + user.email = form.email.data + if form.photo.data: + with open(f'static/app_files/user_logo/{current_user.login}.png', 'wb') as file: + form.photo.data.save(file) + user.photo = f'static/app_files/user_logo/{current_user.login}.png' + user.name = form.name.data + user.surname = form.surname.data + user.about = form.about.data + user.birthday = form.birthday.data + data_session.commit() + return redirect('/profile') + return render_template('profile.html', title='Профиль', form=form, message='', user=current_user, admin=False) + else: + return redirect('/login') + + +@login_manager.user_loader +def load_user(user_id): + db_sess = db_session.create_session() + return db_sess.query(User).get(user_id) + + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if not current_user.is_authenticated: + message = request.args.get('message') if request.args.get('message') else '' + danger = request.args.get('danger') if request.args.get('danger') else False + form = LoginForm() + if form.validate_on_submit(): + data_session = db_session.create_session() + user = data_session.query(User).filter(User.email == form.login.data).first() + if not user: + user = data_session.query(User).filter(User.login == form.login.data).first() + if user and user.check_password(form.password.data): + if user.activated and not user.banned: + login_user(user, remember=form.remember_me.data) + logging.info(f'{user.login} logged in') + return redirect('/projects') + elif user.banned: + return render_template('login.html', + message="Ваш аккаунт заблокирован, обратитесь в поддержку: inepted@yandex.ru", + danger=True, + form=form) + else: + return render_template('login.html', + message="Ваша почта не подтверждена", + danger=True, + form=form) + return render_template('login.html', + message="Неправильный логин или пароль", + danger=True, + form=form) + return render_template('login.html', title='Авторизация', form=form, message=message, + danger=danger) + else: + return redirect('/projects') + + +@app.route('/logout') +@login_required +def logout(): + logging.info(f'{current_user.login} logged out') + logout_user() + return redirect("/") + + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if not current_user.is_authenticated: + with open('../egg.txt', 'r', encoding='utf-8') as file_egg: + egg = int(file_egg.read()) + form = RegisterForm() + if form.validate_on_submit(): + data_session = db_session.create_session() + if data_session.query(User).filter(User.login == form.login.data).first(): + return render_template('register.html', form=form, message="Такой пользователь уже есть", + title='Регистрация', egg=0) + if data_session.query(User).filter(User.email == form.email.data).first(): + return render_template('register.html', form=form, message="Такая почта уже есть", egg=0, + title='Регистрация') + status_password = check_password(form.password.data) + if status_password != 'OK': + return render_template('register.html', form=form, message=status_password, egg=0, + title='Регистрация') + user = User( + email=form.email.data, + name=form.name.data, + login=form.login.data, + activity=datetime.datetime.now(), + data_reg=datetime.date.today(), + photo='static/images/none_logo.png', + role=3 + ) + user.set_password(form.password.data) + data_session.add(user) + data_session.commit() + token = s.dumps(form.email.data) + link_conf = url_for('confirmation', token=token, _external=True) + mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, + 'Подтверждение регистрации') + logging.info(f'{form.login.data} was registered') + return redirect('/login?message=Мы выслали ссылку для подтверждения почты') + return render_template('register.html', form=form, message='', title='Регистрация', egg=egg) + else: + return redirect('/projects') + + +@app.route('/confirmation/') +def confirmation(token): + try: + user_email = s.loads(token, max_age=86400) + data_session = db_session.create_session() + user = data_session.query(User).filter(User.email == user_email).first() + if user: + user.activated = True + data_session.commit() + logging.info(f'{user.login} has been confirmed') + return redirect('/login?message=Почта успешно подтверждена') + else: + return redirect('/login?message=Пользователь не найден&danger=True') + except SignatureExpired: + data_session = db_session.create_session() + users = data_session.query(User).filter( + User.activated == 0 and User.activated < datetime.datetime.now() - datetime.timedelta(days=1)).all() + if users: + list(map(lambda x: data_session.delete(x), users)) + data_session.commit() + return redirect('/login?message=Срок действия ссылки истек, данные удалены&danger=True') + + +@app.errorhandler(500) +def internal_server_error(error): + return render_template('page_error.html', title='Ошибка сервера', error='500', message='Технические шоколадки') + + +@app.errorhandler(404) +def page_not_found(error): + return render_template('page_error.html', title='Страница не найдена', error='404', message='Страница не найдена') + + +@app.errorhandler(403) +def access_error(error): + return render_template('page_error.html', title='Ошибка доступа', error='403', message='Доступ сюда запрещен') + + +def main(): + db_path = 'db/incepted.db' + db = os.path.exists(db_path) + db_session.global_init(db_path) + if not db: + init_db_default() + serve(app, host='0.0.0.0', port=5000, threads=100) + + +if __name__ == '__main__': + try: + main() + except Exception as error: + logging.warning(f'{error}') diff --git a/templates/admin.html b/incepted/templates/admin.html similarity index 100% rename from templates/admin.html rename to incepted/templates/admin.html diff --git a/templates/answer.html b/incepted/templates/answer.html similarity index 100% rename from templates/answer.html rename to incepted/templates/answer.html diff --git a/templates/base.html b/incepted/templates/base.html similarity index 97% rename from templates/base.html rename to incepted/templates/base.html index 8db6faf..8ec3ae7 100644 --- a/templates/base.html +++ b/incepted/templates/base.html @@ -1,66 +1,66 @@ - - - - - - - - {{title}} - - - -{% if current_user.is_authenticated %} - -{% else %} - -{% endif %} - -
{% block content %}{% endblock %}
-
- -
- - - + + + + + + + + {{title}} + + + +{% if current_user.is_authenticated %} + +{% else %} + +{% endif %} + +
{% block content %}{% endblock %}
+
+ +
+ + + diff --git a/templates/delete_project.html b/incepted/templates/delete_project.html similarity index 100% rename from templates/delete_project.html rename to incepted/templates/delete_project.html diff --git a/templates/edit_project.html b/incepted/templates/edit_project.html similarity index 100% rename from templates/edit_project.html rename to incepted/templates/edit_project.html diff --git a/templates/edit_task.html b/incepted/templates/edit_task.html similarity index 100% rename from templates/edit_task.html rename to incepted/templates/edit_task.html diff --git a/templates/login.html b/incepted/templates/login.html similarity index 98% rename from templates/login.html rename to incepted/templates/login.html index 24fb22b..9983d6a 100644 --- a/templates/login.html +++ b/incepted/templates/login.html @@ -1,57 +1,57 @@ - -{% extends "base.html" %} {% block content %} - -{% endblock %} + +{% extends "base.html" %} {% block content %} + +{% endblock %} diff --git a/templates/main.html b/incepted/templates/main.html similarity index 100% rename from templates/main.html rename to incepted/templates/main.html diff --git a/templates/new_project.html b/incepted/templates/new_project.html similarity index 100% rename from templates/new_project.html rename to incepted/templates/new_project.html diff --git a/templates/new_task.html b/incepted/templates/new_task.html similarity index 100% rename from templates/new_task.html rename to incepted/templates/new_task.html diff --git a/templates/page_error.html b/incepted/templates/page_error.html similarity index 100% rename from templates/page_error.html rename to incepted/templates/page_error.html diff --git a/templates/profile.html b/incepted/templates/profile.html similarity index 98% rename from templates/profile.html rename to incepted/templates/profile.html index 497bced..f79032d 100644 --- a/templates/profile.html +++ b/incepted/templates/profile.html @@ -1,98 +1,98 @@ - -{% extends "base.html" %} {% block content %} -
-
-
- -
-
-
- {{ form.hidden_tag() }} -
-
-
- - {{ form.email(class="input_data", type="email", - placeholder='example@mail.ex') }} {% for error in - form.email.errors %} - - {% endfor %} -
-
- - {{ form.name(class="input_data", type="name", placeholder='name') - }} {% for error in form.name.errors %} - - {% endfor %} -
-
- - {{ form.surname(class="input_data", type="surname", - placeholder='surname') }} {% for error in form.surname.errors %} - - {% endfor %} -
-
-
-
- - {{ form.birthday(class="input_data", type="date") }} {% for error - in form.birthday.errors %} - - {% endfor %} -
-
- - {{ form.about(class="input_data dop_data about", type="name", - placeholder='about') }} {% for error in form.about.errors %} - - {% endfor %} -
- {% if 'none' in user.photo %} -
- - {{ form.photo(class="input_data dop_data", type="file") }} {% for - error in form.photo.errors %} - - {% endfor %} -
- {% else %} -
- {{ form.del_photo(type="submit", class="profile_button", - id="delete_button") }} -
- {% endif %} -
- {% if message != '' %} - - {% endif %} -
-
-
-
- {{ form.submit(type="submit", class="profile_button") }} - {% if admin %} - -
-

Профиль

-
-
- {% else %} - -
-

Выйти

-
-
- {% endif %} -
-
-
-
-
-{% endblock %} + +{% extends "base.html" %} {% block content %} +
+
+
+ +
+
+
+ {{ form.hidden_tag() }} +
+
+
+ + {{ form.email(class="input_data", type="email", + placeholder='example@mail.ex') }} {% for error in + form.email.errors %} + + {% endfor %} +
+
+ + {{ form.name(class="input_data", type="name", placeholder='name') + }} {% for error in form.name.errors %} + + {% endfor %} +
+
+ + {{ form.surname(class="input_data", type="surname", + placeholder='surname') }} {% for error in form.surname.errors %} + + {% endfor %} +
+
+
+
+ + {{ form.birthday(class="input_data", type="date") }} {% for error + in form.birthday.errors %} + + {% endfor %} +
+
+ + {{ form.about(class="input_data dop_data about", type="name", + placeholder='about') }} {% for error in form.about.errors %} + + {% endfor %} +
+ {% if 'none' in user.photo %} +
+ + {{ form.photo(class="input_data dop_data", type="file") }} {% for + error in form.photo.errors %} + + {% endfor %} +
+ {% else %} +
+ {{ form.del_photo(type="submit", class="profile_button", + id="delete_button") }} +
+ {% endif %} +
+ {% if message != '' %} + + {% endif %} +
+
+
+
+ {{ form.submit(type="submit", class="profile_button") }} + {% if admin %} + +
+

Профиль

+
+
+ {% else %} + +
+

Выйти

+
+
+ {% endif %} +
+
+
+
+
+{% endblock %} diff --git a/templates/project.html b/incepted/templates/project.html similarity index 100% rename from templates/project.html rename to incepted/templates/project.html diff --git a/templates/projects.html b/incepted/templates/projects.html similarity index 100% rename from templates/projects.html rename to incepted/templates/projects.html diff --git a/templates/recovery.html b/incepted/templates/recovery.html similarity index 100% rename from templates/recovery.html rename to incepted/templates/recovery.html diff --git a/templates/register.html b/incepted/templates/register.html similarity index 100% rename from templates/register.html rename to incepted/templates/register.html diff --git a/templates/showcase.html b/incepted/templates/showcase.html similarity index 100% rename from templates/showcase.html rename to incepted/templates/showcase.html diff --git a/templates/template_project.html b/incepted/templates/template_project.html similarity index 100% rename from templates/template_project.html rename to incepted/templates/template_project.html diff --git a/templates/user_view.html b/incepted/templates/user_view.html similarity index 100% rename from templates/user_view.html rename to incepted/templates/user_view.html diff --git a/static/app_files/all_projects/заглушка b/static/app_files/all_projects/заглушка deleted file mode 100644 index e69de29..0000000 diff --git a/static/app_files/project_logo/заглушка b/static/app_files/project_logo/заглушка deleted file mode 100644 index e69de29..0000000 diff --git a/static/app_files/user_logo/заглушка b/static/app_files/user_logo/заглушка deleted file mode 100644 index e69de29..0000000 diff --git a/static/css/admin.css b/static/css/admin.css deleted file mode 100644 index f2e7475..0000000 --- a/static/css/admin.css +++ /dev/null @@ -1,95 +0,0 @@ -.admin_page { - height: 120vw; - background-color: #dcb495; - display: flex; - flex-direction: column; - align-items: center; -} -.admin_block { - width: 90%; - height: 35vw; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; - overflow-x: hidden; -} -.admin_block::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.admin_block::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.users_block { - margin: 20px; - display: flex; - flex-direction: column; - align-items: center; -} -.user { - width: 90%; - height: 5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; -} -.user_logo { - margin-left: 3px; - width: 4vw; - height: 4vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; - color: #000000 !important; - font-size: 2vw; -} -.admine_title { - font-size: 3vw; -} -.link_to_user { - width: 16vw; - height: 3.5vw; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; - text-decoration: none; -} -.link_to_user:hover { - text-decoration: none; -} -.role_div { - width: 8vw; - height: 3vw; - border-radius: 2vw; -} -.save_button { - margin-top: 15px; - width: 35vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.edit_user_form { - width: 90%; - display: flex; - flex-direction: column; - align-items: center; -} -.user_active, .user_banned { - margin-left: 1vw; -} \ No newline at end of file diff --git a/static/css/answer.css b/static/css/answer.css deleted file mode 100644 index ce9e565..0000000 --- a/static/css/answer.css +++ /dev/null @@ -1,251 +0,0 @@ -body { - background-color: #dcb495 !important; - display: flex; - flex-direction: column; - justify-content: space-between; -} -.decision_page { - background-color: #dcb495; - min-height: 100vw; - height: auto; - display: flex; - flex-direction: column; - align-items: center; - margin: 3vw; - margin-bottom: 20vw; -} -.link_back_block { - margin-right: 0.5vw; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.head_buttons_block { - display: flex; - flex-direction: row; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.name_block { - margin-top: 3vw; - width: 90%; - height: auto; - display: flex; - flex-direction: column; - align-items: center; -} -.title_block { - width: 90%; - display: flex; - justify-content: center; -} -.title_task, .files_title { - text-align: center; - color: #000000; - font-size: 4vw; - max-width: 80%; - overflow-x: auto; - overflow-y: hidden; -} -.description_task { - width: 80%; - background-color: #EDCBB0; - height: auto; - max-height: 15vw; - border-radius: 2vw; - display: flex; - overflow-y: auto; -} -.description_task::-webkit-scrollbar { - width: 0.8vw !important; - height: auto; -} -.description_task::-webkit-scrollbar-thumb { - background-color: #d49d51 !important; /* цвет плашки */ - border-radius: 5vw !important; /* закругления плашки */ - border: 0.25vw solid #ffffff !important; -} -.description { - margin: 15px; -} -.description_text { - font-size: 1.5vw; - text-align: justify; -} -.data_block { - width: 100%; - display: flex; - align-items: flex-start; - justify-content: center -} -.bottom_data { - margin: 2vw; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #000000; - font-weight: bold; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 30vw; - background-color: #dbc3af; - border-radius: 5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.input_button { - width: 10vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form_data { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.decision_block { - margin-top: 3vw; - width: 90%; - height: 25vw; - display: flex; - flex-direction: column; - align-items: center; -} -.padding_data { - padding: 1vw; -} -.quest_button { - color: #ffffff; - width: 13vw; - height: 5vw; - background-color: #000000; - border: 2px solid #ffffff; - border-radius: 3vw; - margin-left: 2vw; -} -form { - display: flex; - flex-direction: column; - align-items: center; -} -.form_data_button { - margin-top: 20px; - display: flex; - width: 30vw; - align-items: center; - justify-content: space-between; -} -.deadline { - margin-top: 5px; -} -.text_data { - width: 80%; - border-radius: 2vw !important; - min-height: 10vw; - max-height: 20vw; -} -.form_text_one { - width: 200%; -} -.files_block { - width: 100%; - margin: 2vw; - background-color: #dbc3af; - display: flex; - flex-direction: column; - align-items: stretch; - border-radius: 2vw; - min-height: 25vw; -} -.files_list { - margin: 2vw; - height: auto; - overflow-y: auto; - overflow-x: hidden; -} -.files { - width: 80%; - margin: 2vw; - display: flex; - flex-direction: column; - align-items: center; - min-height: 25vw; - max-height: 30vw; -} -.file { - width: 98%; - display: flex; - background-color: #694a2d; - margin: 0.5vw; - align-items: center; - justify-content: space-between; - flex-direction: row; - height: 4.5vw; - border-radius: 2vw; -} -.file_head { - width: 30vw; - margin-left: 1vw; - height: 4vw; - background-color: #694a2d !important; - overflow-y: hidden; - overflow-x: auto; -} -.file_head_path, .file_path { - font-size: 1.5vw; - color: #ffffff !important; - font-weight: bold; - height: 3vw; - display: flex; - align-items: flex-start; - background-color: #694a2d !important; -} -.file_buttons { - margin-right: 2vw; -} -.file_delete, .file_download { - border-radius: 1vw !important; - margin: 1vw; - width: 8vw; - height: 3vw; -} -.file_delete { - background-color: hsla(0, 100%, 62%, 0.785) !important; - border-color: hsla(0, 100%, 62%, 0.785) !important; -} -.button_text { - font-size: 1.3vw; -} \ No newline at end of file diff --git a/static/css/base.css b/static/css/base.css deleted file mode 100644 index 0c4bcdc..0000000 --- a/static/css/base.css +++ /dev/null @@ -1,100 +0,0 @@ -html { - background-color: #fdf5e6; - height: 100%; -} -body { - min-height: 100%; -} -.navbar { - margin-top: -1.4vw; - background-color: #dcb495; - display: inline-flex; - height: 8vw; -} -#navbar { - margin-top: -80px; - position: fixed; - width: 100%; - transition: top 0.3s; - opacity: .9; - border-bottom: 1px solid #bf9c81; -} -.auth_button { - color: #ffffff; - font-size: 1.5vw; - transition: color 0.5s ease-in, border-bottom 0.5s ease-in; -} -.auth_button:hover { - color: #694a2d; - border-bottom: 3px solid #f3c79e; - text-decoration: none; -} -.footer { - background-color: #171717; - height: 15vw; -} -.footer_block { - height: 100%; - width: 90%; - margin-left: 5%; - display: flex; - align-content: center; - align-items: center; -} -.footer_logo, .nav_logo { - width: 7vw; - height: 6vw; -} -.footer_rights { - color: #ffffff; - font-size: 1.5vw; - width: 85%; - text-align: center; -} -.nav_panel { - width: 100%; - display: inline-flex; - justify-content: center; -} -.nav_user { - display: flex; - flex-direction: row; - justify-content: center; - height: 100%; - align-items: center; -} -.nav_user_name { - margin-left: 1vw; - align-self: center; -} -.nav_chapter_text { - height: 100%; - font-style: bold; - color: #946137; - font-size: 2vw; - transition: color 0.3s ease-in; -} -.nav_chapter_text:hover { - color: #f3d5be; -} -.nav_chapter { - text-align: center; - width: 30%; - border-bottom: 0.2vw solid #d49d51; - transition: border-bottom 0.3s ease-in; -} -.nav_chapter:hover { - text-decoration: none; - border-bottom: 0.2vw solid #face7d; -} -.nav_user_name_div { - height: 100%; -} -body::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -body::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} \ No newline at end of file diff --git a/static/css/delete_project.css b/static/css/delete_project.css deleted file mode 100644 index f073bb8..0000000 --- a/static/css/delete_project.css +++ /dev/null @@ -1,60 +0,0 @@ -.delete_project_page { - height: 60vw; - background-color: #dcb495; -} -.form_block { - width: 100%; - height: 60vw; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; -} -.form_data { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 35vw; - background-color: #dbc3af; - border-radius: 4.5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.delete_project_button { - margin-left: 15px; - width: 25vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -form { - display: flex; - align-items: flex-end; - justify-content: center; -} -.conf_text { - color: #ff0000; -} -.header_title { - text-align: center; - color: #000000; - font-size: 3.5vw; - width: 100%; - margin-bottom: 15px; -} \ No newline at end of file diff --git a/static/css/edit_project.css b/static/css/edit_project.css deleted file mode 100644 index 8c93c3e..0000000 --- a/static/css/edit_project.css +++ /dev/null @@ -1,179 +0,0 @@ -.edit_project_page { - height: 120vw; - background-color: #dcb495; -} -.form_data, .form_data_button { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 35vw; - background-color: #dbc3af; - border-radius: 4.5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.input_button { - width: 35vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.description { - border-radius: 2vw !important; - width: 50vw; -} -.padding_data { - padding-top: 1vw; - padding-left: 1vw; -} -.label_data { - padding-left: 0.8vw; - width: 50vw; -} -.project_button, .delete_button, .delete_project_link { - margin-top: 15px; - width: 35vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.collaborator_block { - width: 30%; - height: 20vw; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; -} -.user { - width: 30vw; - height: 3.5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: inline-flex; - justify-content: space-between; -} -.user_logo { - margin-left: 3px; - width: 3vw; - height: 3vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; -} -.name_form_block { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} -.data_form_block { - width: 100%; - display: flex; - align-items: center; - justify-content: center; - flex-direction: row; -} -.buttons_form_block { - width: 45%; - display: flex; - flex-direction: column; - align-items: center; -} -.staff_form_block, .collaborator_block { - margin-top: 10px; - width: 60%; - height: 20vw; - display: flex; - align-items: center; - justify-content: center; -} -.staff_block { - margin: 5%; - width: 90%; - height: 20vw; -} -.choose_user { - align-self: flex-end; - margin-bottom: 1.1vw; - width: 10%; -} -.user_data { - display: inline-flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; -} -.delete_project_link { - background-color: #ff3f3f; -} -.delete_project_link:hover { - background-color: #ff3f3f; - text-decoration: none; - color: #ffffff; -} -.delete_project_link_text { - width: 35vw; - height: 5vw; - display: flex; - align-items: center; - justify-content: center; - margin-top: 10px; -} -.link_back_block { - margin-right: 0.5vw; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} \ No newline at end of file diff --git a/static/css/edit_task.css b/static/css/edit_task.css deleted file mode 100644 index 9195acc..0000000 --- a/static/css/edit_task.css +++ /dev/null @@ -1,106 +0,0 @@ -.new_task_page { - height: 50vw; - background-color: #dcb495; -} -.form_data { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.form_block { - display: flex; - align-items: center; - justify-content: center; -} -.form_data_button { - margin-top: 2.5vw; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 50vw; - background-color: #dbc3af; - border-radius: 4.5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.description { - border-radius: 2vw !important; - width: 50vw; - max-height: 10vw !important; -} -.name_form_block { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} -.deadline { - width: 20vw; -} -.quest_button { - margin-top: 1vw; - margin-left: 5vw; - width: 20vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.data_form_block { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} -.deadline { - margin: 5px; -} -.link_back_block { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.delete_project_link { - background-color: #ff3f3f; - border: #ff3f3f; -} \ No newline at end of file diff --git a/static/css/login.css b/static/css/login.css deleted file mode 100644 index e2c499d..0000000 --- a/static/css/login.css +++ /dev/null @@ -1,106 +0,0 @@ -#navbar { - display: none; -} -.login_page { - margin-top: -1.1vw; - display: flex; - justify-content: center; - align-items: center; - height: 75vw; - background: linear-gradient( rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.55) ), url(../images/back_main_one.jpg);background-repeat: repeat; background-position: center; -} -.login { - width: 80%; - height: 50%; - margin-left: 10%; - margin-right: 10%; - background-color: #dbc3af; - display: flex; - flex-direction: column; - justify-content: space-evenly; -} -.login_form { - margin-bottom: 10%; -} -.header_title { - text-align: center; - color: #000000; - font-size: 3.5vw; - width: 100%; -} -.data_block { - width: 100%; - display: inline-flex; - justify-content: center; -} -.form_data, .form_data_button { - display: flex; - flex-direction: column; - margin-left: 2%; - margin-left: 2%; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.7vw; - width: 20vw; - background-color: #dbc3af; - border-radius: 5vw; - font-size: 1.3vw; -} -.input_button { - width: 20vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form-label { - font-size: 1.3vw; -} -.login_button { - background-color: #000000; - color: #ffffff; - font-size: 1.5vw; - margin-bottom: 5px; -} -.register_button { - margin-top: 5px; - background-color: #f5c99f; - width: 20vw; - height: 5vw; - color: #000000; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.register_button:hover { - text-decoration: none; - color: #000000; -} -.register { - width: 100%; - text-align: center; - height: 100%; - display: flex; - align-items: center; - justify-content: center; -} -.box { - margin-left: 9vw; -} -.recovery_button { - color: #ffffff; - font-size: 1.5vw; - transition: color 0.5s ease-in, border-bottom 0.5s ease-in; -} -.recovery_button:hover { - color: #694a2d; - border-bottom: 3px solid #f3c79e; - text-decoration: none; -} \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css deleted file mode 100644 index 7d3cd4a..0000000 --- a/static/css/main.css +++ /dev/null @@ -1,279 +0,0 @@ -main, html { - background-color: #dcb495; -} -#header_block { - position: absolute; - margin-bottom: 60%; -} -.header_block { - margin-top: -1.1vw; - width: 100%; - height: 75vw; - background-position: center; - display: flex; - justify-content: center; - flex-direction: column; - background: linear-gradient( rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.85) ), url(../images/back_main_one.jpg);background-repeat: repeat; background-position: center; -} -.header_title { - margin-left: 10%; - color: #ffffff; - font: bold; - font-size: 4vw; - transition: font-size 0.5s ease-in, text-shadow 1s ease-in; -} -.header_title:hover { - font-size: 4.05vw; - text-shadow: 0px 0px 20px #ffffff; -} -.header_title_2 { - margin-left: 10%; - color: #afafaf; - font: bold; - font-size: 2vw; - transition: font-size 0.5s ease-in, text-shadow 1s ease-in; -} -.header_title_2:hover { - font-size: 2.05vw; - text-shadow: 0px 0px 20px #ffffff; -} -.header_buttons { - margin-top: 5%; - margin-left: 10%; - width: 90%; - display: flex; - justify-content: flex-start; - align-items: center; -} -.header_button { - background-color: #f5c99f; - width: 20vw; - height: 5vw; - color: #000000; - border-radius: 30px; - vertical-align: middle; -} -.header_button:hover { - text-decoration: none; - color: #000000; -} -#link_to_about { - margin-left: 40px; - background-color: #000000; - color: #ffffff; - border: 2px solid #ffffff; -} -.header_button_text { - width: 100%; - height: 100%; - text-align: center; - font-size: 1.5vw; - margin-top: 5%; -} -.body_block { - background-color: #dcb495; -} -.about_block { - margin-top: 10%; - margin-left: 5%; - width: 90%; -} -.about_title { - color: #000000; - font-size: 4vw; -} -.about_info_block { - margin-top: 50px; - width: 100%; - display: inline-flex; - justify-content: space-between; -} -.about_article_block { - display: flex; - flex-direction: column; - align-content: space-around; -} -.about_article { - display: inline-flex; - justify-content: flex-start; - align-items: center; -} -.article_image { - width: 10vw; - height: 10vw; -} -.main_image { - width: 40vw; - height: 26vw; -} -.article_text { - max-width: 70%; - margin-left: 10px; - font-size: 1.3vw; -} -.how_work_block { - margin-top: 20%; - margin-left: 5%; - width: 90%; -} -.how_work_title { - text-align: center; - color: #000000; - font-size: 4vw; -} -.how_work_info_block { - display: inline-flex; - justify-content: space-evenly; - margin-top: 100px; -} -.how_work_image { - width: 10vw; - height: 10vw; -} -.how_work_info, .how_work_article { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.how_work_article_title { - text-align: center; - font-size: 1.5vw; -} -.how_work_article_text { - text-align: center; - margin-top: 1vw; - font-size: 1.1vw; -} -.reg_block { - margin-top: 20%; - width: 100%; - height: 50vw; -} -.reg_content_block { - margin-top: 100px; - width: 90%; - margin-left: 5%; - display: inline-flex; - justify-content: space-between; - flex-wrap: nowrap; - align-content: center; -} -.reg_title { - text-align: center; - color: #000000; - font-size: 4vw; -} -.reg_content { - display: flex; - flex-direction: column; - align-self: center; - align-content: space-evenly; -} -.reg_button_group { - display: flex; - justify-content: flex-start; - align-items: center; -} -.reg_button_title { - margin-bottom: 10%; - color: #000000; - font-size: 2.5vw; - text-align: left; -} -.reg_button_info { - margin-top: 8%; -} -.reg_button_group { - width: 100%; - display: flex; - justify-content: space-between; - align-items: center; -} -.reg_button { - background-color: #a8886f; - width: 20vw; - height: 5vw; - color: #ffffff; - border-radius: 30px; - vertical-align: middle; -} -.reg_button:hover { - text-decoration: none; - color: #ffffff; -} -.reg_button_text { - width: 100%; - height: 100%; - text-align: center; - font-size: 1.5vw; - margin-top: 6%; -} -#link_to_start{ - width: 18vw; - background-color:#f5d3b8; -} -#link_to_start_text { - color: #000000; -} -.feedback_block { - display: flex; - justify-content: center; - align-items: center; - height: 75vw; - background: linear-gradient( rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.85) ), url(../images/back_main_two.jpg);background-repeat: repeat; background-position: center; -} -.feedback { - width: 50%; - height: 80%; - margin-left: 25%; - margin-right: 25%; - background-color: #dcb495; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - align-content: space-around; -} -.feedback_title { - width: 80%; - margin-bottom: 20%; - text-align: center; - color: #000000; - font-size: 3vw; -} -.feedback_logo { - margin-bottom: 20%; - width: 10vw; - height: 10vw; -} -.feedback_mail, .feedback_mail_link { - font-size: 1.5vw; - color: #000000; - transition: color 0.5s ease-in, border-bottom 0.5s ease-in; -} -.feedback_mail_link:hover { - color: #694a2d; - border-bottom: 3px solid #f3c79e; - text-decoration: none; -} -.scroll_button { - position: fixed; - width: 50px; - height: 50px; - background-color: #e5e5e5; - border-radius: 2vw; - margin-left: 95%; - margin-top: 45%; - transition: background-color 0.5s ease-in; -} -.scroll_image { - margin-top: 5px; - margin-left: 5px; - width: 40px; - height: 40px; - border-radius: 2vw; -} -.scroll_button:hover { - background-color: #1c59fe; -} \ No newline at end of file diff --git a/static/css/new_project.css b/static/css/new_project.css deleted file mode 100644 index 919c0be..0000000 --- a/static/css/new_project.css +++ /dev/null @@ -1,162 +0,0 @@ -.new_project_page { - height: 120vw; - background-color: #dcb495; -} -.form_data, .form_data_button { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 35vw; - background-color: #dbc3af; - border-radius: 4.5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.input_button { - width: 35vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.description { - border-radius: 2vw !important; - width: 50vw; -} -.padding_data { - padding-top: 1vw; - padding-left: 1vw; -} -.label_data { - padding-left: 0.8vw; - width: 50vw; -} -.project_button { - margin-top: 15px; - width: 35vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.collaborator_block { - width: 30%; - height: 20vw; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; -} -.user { - width: 30vw; - height: 3.5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: inline-flex; - justify-content: space-between; -} -.user_logo { - margin-left: 3px; - width: 3vw; - height: 3vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; -} -.name_form_block { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} -.data_form_block { - width: 100%; - display: flex; - align-items: center; - justify-content: center; - flex-direction: row; -} -.buttons_form_block { - width: 45%; - display: flex; - flex-direction: column; - align-items: center; -} -.staff_form_block, .collaborator_block { - margin-top: 10px; - width: 60%; - height: 20vw; - display: flex; - align-items: center; - justify-content: center; -} -.staff_block { - margin: 5%; - width: 90%; - height: 20vw; -} -.choose_user { - align-self: flex-end; - margin-bottom: 1.1vw; - width: 10%; -} -.user_data { - display: inline-flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; -} -.link_back_block { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} \ No newline at end of file diff --git a/static/css/new_task.css b/static/css/new_task.css deleted file mode 100644 index ff9c228..0000000 --- a/static/css/new_task.css +++ /dev/null @@ -1,101 +0,0 @@ -.new_task_page { - height: 50vw; - background-color: #dcb495; -} -.form_data { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.form_block { - display: flex; - align-items: center; - justify-content: center; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 50vw; - background-color: #dbc3af; - border-radius: 4.5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.form_label { - margin-top: 10px; - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.description { - border-radius: 2vw !important; - width: 50vw; - max-height: 10vw; -} -.name_form_block { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; -} -.deadline { - width: 20vw; -} -.quest_button { - margin-top: 5vw; - margin-left: 5vw; - width: 20vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.data_form_block { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} -.deadline { - margin: 5px; -} -.link_back_block { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} \ No newline at end of file diff --git a/static/css/page_error.css b/static/css/page_error.css deleted file mode 100644 index 689f64a..0000000 --- a/static/css/page_error.css +++ /dev/null @@ -1,73 +0,0 @@ -.navbar { - display: none !important; -} -.page_error { - margin-top: -1.4vw; - height: 55vw; - background-color: #dcb495; - display: flex; - flex-direction: column; -} -.header_block { - display: flex; - flex-direction: column; - width: 80%; - height: 15vw; - margin-left: 10%; - margin-top: 80px; - justify-content: space-around; -} -.header { - display: flex; - align-items: center; - justify-content: center; -} -.line_top { - height: 0.03vw; - background: #000000; - width: 32vw; -} -.header_rect { - width: 15vw; - height: 3.3vw; - background-color: #000000; - display: flex; - justify-content: center; - align-items: center; -} -.header_rect_text { - color: #ffffff; - font-size: 1.6vw; -} -.header_title { - color: #000000; - font-size: 3vw; -} -.line_bottom { - height: 0.03vw; - background: #000000; - width: 100%; -} -.link_block { - width: 100%; - margin-top: 50px; - display: flex; - justify-content: center; -} -.block_to_home { - width: 20vw; - height: 20vw; - background-color: #000000; - display: flex; - justify-content: center; - align-items: center; - border-radius: 10vw; -} -.link_to_home { - height: 12.3vw; - width: 15vw; -} -.link_image { - height: 12.3vw; - width: 15vw; -} \ No newline at end of file diff --git a/static/css/profile.css b/static/css/profile.css deleted file mode 100644 index 36d0584..0000000 --- a/static/css/profile.css +++ /dev/null @@ -1,176 +0,0 @@ -.profile_page { - display: flex; - flex-direction: column; - height: auto; - width: 100%; - background: linear-gradient( rgba(0, 0, 0, 0.8), rgba(0, 0, 0, 0.8) ), url(../images/back_profile_one.jpg);background-repeat: repeat; background-position: center; -} -.profile_block { - margin-top: 5vw; - height: 65vw; - width: 85%; - margin-left: 7.5%; - margin-bottom: 6%; - background: linear-gradient( rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(../images/back_profile_two.jpg);background-repeat: repeat; background-position: center; - display: flex; - flex-direction: column; - overflow-y: auto; -} -.header_profile { - display: inline; - flex-direction: column; - width: 15vw; - height: 15vw; - margin-top: 50px; - align-self: center; -} -.user_photo { - width: 15vw; - height: 15vw; - border: 0.2vw solid #ffffff; - border-radius: 2vw; -} -.edit_form { - align-self: center; - margin-top: 20px; - width: 80%; -} -form { - display: flex; - flex-direction: column; -} -.form_data_button { - align-self: center; -} -.form_blocks { - width: 100%; - margin-top: 50px; - display: inline-flex; - justify-content: space-evenly; -} -.form_data, .form_data_button { - display: flex; - flex-direction: column; - margin-left: 2%; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - min-height: 4.5vw; - width: 20vw; - background-color: #dbc3af; - border-radius: 5vw; - font-size: 1.3vw; - display: inline-flex; - align-items: center; -} -.input_button { - width: 10vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form-label { - font-size: 1.3vw; - color: #ffffff; - font-weight: bold; -} -.profile_button { - margin-top: 15px; - width: 20vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.profile_button:hover { - color: #ffffff; - text-decoration: none; -} -#delete_button { - margin-top: 45px; -} -.dop_data { - padding-top:15px; - padding-left: 15px; -} -#logout_button { - color: #ffffff; - background-color:#ff3f3f; -} -#logout_button:hover { - text-decoration: none; - color: #ffffff; -} -.profile_button_text { - width: 100%; - height: 100%; - text-align: center; - font-size: 1.5vw; - margin-top: 6%; -} -.open_button_block { - height: 35vw; - width: 85%; - margin-left: 7.5%; - margin-top: 3%; - margin-bottom: 6%; - background: linear-gradient( rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3) ), url(../images/back_profile_two.jpg);background-repeat: repeat; background-position: center; - display: flex; - flex-direction: column; - overflow-y: auto; -} -.open_button_content { - display: flex; - flex-direction: column; - width: 100%; - height: 100%; - justify-content: center; - align-items: center; -} -.open_button_title { - margin-bottom: 3%; - color: #ffffff; - font: bold; - font-size: 4.5vw; -} -.open_button_article { - margin-bottom: 5%; - color: #ffffff; - font: bold; - font-size: 2vw; -} -.open_button { - background-color: #ffffff; - color: #000000; - width: 20vw; - height: 5vw; - vertical-align: middle; - border-radius: 5vw; -} -.open_button:hover { - text-decoration: none; - color: #000000; -} -.open_button_text { - width: 100%; - height: 100%; - text-align: center; - font-size: 1.5vw; - margin-top: 5%; -} -.about { - border-radius: 2vw !important; -} -.profile_button_text { - color: #ffffff; -} \ No newline at end of file diff --git a/static/css/project.css b/static/css/project.css deleted file mode 100644 index a961f31..0000000 --- a/static/css/project.css +++ /dev/null @@ -1,448 +0,0 @@ -.projects_page { - height: 120vw; - background-color: #dcb495; - display: flex; - flex-direction: column; - align-items: center; -} -.project_header { - height: 25vw; - width: 100%; - display: flex; - align-items: center; - justify-content: space-around; -} -.project_logo { - margin-right: 4vw; - margin-top: 30px; - width: 15vw; - height: 15vw; - border: 0.2vw solid #ffffff; - border-radius: 2vw; -} -.brand_block { - height: 25vw; - margin-left: -8vw; - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-between; - color: #dcb495; -} -.name_project { - font-size: 3vw !important; - margin-right: 4vw; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap; - max-width: 40vw; -} -.name_project::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.name_project::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.edit_block { - display: flex; - align-items: center; - justify-content: center; -} -.edit_button { - background-color: #9E795A; - border: #9E795A; - width: 15vw; - height: 5vw; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.edit_button_text { - color: #ffffff; - height: 5vw; - margin-top: 25%; -} -.edit_button_link { - width: 15vw; - height: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.edit_button_link:hover { - text-decoration: none; - color: #ffffff; -} -.collaborator_block { - width: 95%; - height: 25vw; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; -} -.staff_block { - margin: 20px; -} -.user { - width: 24vw; - height: 3.5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; -} -.user_logo { - margin-left: 3px; - width: 3vw; - height: 3vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; - color: #000000 !important; - font-size: 1.5vw; -} -.link_to_user { - width: 26vw; - height: 3.5vw; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; - text-decoration: none; -} -.link_to_user:hover { - text-decoration: none; -} -.head_staff_block { - display: flex; - width: 30vw; - flex-direction: column; - align-items: center; -} -.header_title, .header_title_2 { - text-align: center; - color: #000000; - font-size: 3vw; - margin-bottom: 15px; -} -.header_title_2 { - width: 51vw !important; -} -.header_title { - width: 100%; -} -.header_task_block { - width: 60vw; - height: 30vw; - display: flex; - flex-direction: column; - align-items: center; -} -.task_block, .list_files_block { - background-color: #EDCBB0; - width: 95%; - height: 25vw; - border-radius: 2vw; - overflow-y: auto; -} -.task { - margin: 20px; -} -.task_block::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.task_block::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.body_block { - display: flex; - justify-content: space-evenly; - align-items: flex-start; - flex-direction: row; -} -.new_task_block { - width: 13vw; - height: 5vw; - background-color: #000000; - border: 2px solid #ffffff; - border-radius: 3vw; - margin-left: 2vw; - margin-bottom: 0.5vw; -} -.new_task_link { - color: #ffffff; - width: 13vw; - height: 5vw; -} -.new_task_link:hover { - text-decoration: none; - color: #ffffff; -} -.new_task_text { - width: 13vw; - height: 5vw; - text-align: center; - font-size: 1.5vw; - color: #ffffff; - display: flex; - align-items: center; - justify-content: center; -} -.new_task_image { - width: 4.5vw; - height: 4.5vw; -} -.head_task { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - width: 60vw; - justify-content: center; - align-items: flex-start; -} -.list_quests { - width: 95%; - margin-left: 2.5%; - margin-top: 0.5vw; - overflow-y: hidden; - overflow-x: hidden; -} -.quest_header_button { - height: 4.5vw; - width: 100%; - text-align: left; - border-radius: 5vw; - background-color: #9E795A; - border-color: #9E795A; - border-bottom-color: #9E795A; - color: #ffffff; - display: flex; - align-items: center; -} -.quest_button_block_one { - width: 68%; - display: flex; - justify-content: space-between; - align-items: flex-start; -} -.quest_title_block { - width: 96%; - height: 4vw; - display: flex; - align-items: center; -} -.quest_title { - overflow-y: hidden; - overflow-x: auto; - max-height: 5vw; - font-size: 2.1vw !important; - display: flex; - align-items: center; - margin-top: 0.8vw; - margin-left: 1.8vw; - font-size: 3.5vw; - white-space: nowrap -} -.quest_title::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.quest_title::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.deadline_block { - border-radius: 5vw !important; - width: 15vw !important; - height: 3vw !important; - margin-top: 2%; - font-size: 1vw; - display: flex; - color: #000000 !important; - align-items: center; - justify-content: center; - flex-direction: row; -} -.quest_body_block { - background-color: #9E795A; - width: 100%; - height: 20vw; - border-radius: 2vw; - display: flex; - align-items: center; - justify-content: center; -} -.quest_body { - width: 94%; - height: 94%; - display: flex; - align-items: center; - justify-content: space-around; -} -.quest_description_block { - width: 70%; - height: 90%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.quest_description { - width: 100%; - height: 100%; - background-color: #dcb495; - border-radius: 2vw; - overflow-y: auto; -} -.quest_description::-webkit-scrollbar, .task_block::-webkit-scrollbar-thumb { - width: 0.8vw !important; -} -.quest_description::-webkit-scrollbar-thumb, .task_block::-webkit-scrollbar-thumb { - background-color: #d49d51 !important; /* цвет плашки */ - border-radius: 5vw !important; /* закругления плашки */ - border: 0.25vw solid #ffffff !important; -} -.quest_description_text { - margin: 20px; -} -.quest_solve_button { - width: 13vw; - height: 5vw; - background-color: #000000; - border: 2px solid #ffffff; - border-radius: 3vw; -} -.quest_solve_link:hover { - text-decoration: none; - color: #000000; -} -.quest_solve_text { - width: 13vw; - height: 5vw; - text-align: center; - font-size: 1.5vw; - color: #ffffff; - display: flex; - align-items: center; - justify-content: center; -} -#quest_solve_link_id { - display: none; -} -.link_back_block, .link_edit_block { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back, .link_edit { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_edit { - width: 13vw; -} -.link_back:hover, .link_edit:hover { - text-decoration: none; - color: #000000; -} -.link_back_text, .link_edit_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.files_block { - display: flex; - flex-direction: column; - align-items: center; - width: 95%; - height: 50vw; -} -.list_files { - margin: 2vw; -} -.files_title { - text-align: center; - color: #000000; - font-size: 4vw; -} -.file { - width: 98%; - display: flex; - background-color: #9E795A; - margin: 0.5vw; - align-items: center; - justify-content: space-between; - flex-direction: row; - height: 4.5vw; - border-radius: 2vw; -} -.file_head { - width: 30vw; - margin-left: 1vw; - height: 4vw; - background-color: #9E795A !important; - overflow-y: hidden; - overflow-x: auto; -} -.file_head_path, .file_path { - font-size: 1.5vw; - color: #ffffff !important; - font-weight: bold; - height: 3vw; - display: flex; - align-items: flex-start; - background-color: #9E795A !important; -} -.file_buttons { - margin-right: 2vw; -} -.file_delete, .file_download, .upload_button { - border-radius: 1vw !important; - margin: 1vw; - width: 8vw; - height: 3vw; -} -.file_delete { - background-color: hsla(0, 100%, 62%, 0.785) !important; - border-color: hsla(0, 100%, 62%, 0.785) !important; -} -.button_text { - font-size: 1.3vw; -} -.quest_buttons_block { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: 15vw; - margin-top: 3vw; -} -.link_edit_block { - margin-top: 1vw; -} \ No newline at end of file diff --git a/static/css/projects.css b/static/css/projects.css deleted file mode 100644 index ee9d18e..0000000 --- a/static/css/projects.css +++ /dev/null @@ -1,318 +0,0 @@ -.projects_page { - height: 120vw; - background-color: #dcb495; -} -.header_block { - width: 100%; - height: 20vw; - background-position: center; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background: linear-gradient( rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.85) ), url(../images/back_project_one.jpg);background-repeat: repeat; background-position: center; -} -.header_title { - color: #ffffff; - font-size: 7vw; -} -.header_title_2 { - color: #ffffff; - text-align: center; - font-size: 1.5vw; - width: 50vw; -} -.find_block { - width: 100%; - height: 15vw; - background-color: #dcb495; - display: flex; - align-items: center; - flex-direction: row; - justify-content: center; -} -.find_input_text { - margin-right: 12px; - background-color: #EDCBB0; - border: #EDCBB0; - width: 45vw; - height: 5vw; - color: #776658; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.find_input_button { - margin-left: 12px; - background-color: #9E795A; - border: #9E795A; - width: 10vw; - height: 5vw; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.list_project_block { - margin-left: 3%; - border: 0.2vw solid #694a2d; - border-radius: 4.5vw; - width: 94%; - height: 45vw; - overflow-y: auto; - padding-top: 2vw; -} -.list_project_block::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.list_project_block::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.list_project { - width: 95%; - margin-left: 2.5%; - margin-top: 0.5vw; - overflow-y: hidden; - overflow-x: hidden; -} -.project_header_button { - height: 5.5vw; - width: 100%; - text-align: left; - border-radius: 5vw; - background-color: #9E795A; - border-color: #9E795A; - border-bottom-color: #9E795A; - color: #ffffff; - display: flex; - align-items: center; -} -.project_description_block { - background-color: #9E795A; - width: 100%; - height: 20vw; - border-radius: 2vw; -} -.project_logo_block { - width: 4.5vw; - height: 4.5vw; - border: 0.3vw solid #ffffff; - background-color: #ffffff; - border-radius: 2vw; - display: flex; - justify-content: center; - align-items: center; -} -.project_logo { - width: 4vw; - height: 4vw; - border-radius: 5vw; -} -.project_title_block { - width: 100%; - height: 4vw; - margin-left: 1vw; -} -.project_title { - font-size: 3.5vw; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap -} -.project_title::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.project_title::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.project_button_block_one { - width: 90%; - display: flex; - justify-content: flex-start; - align-items: flex-start; -} -.project_description { - width: 98%; - height: 100%; - margin-left: 1%; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-content: center; - align-items: center; - justify-content: space-evenly; -} -.collaborator_block { - width: 22%; - height: 90%; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; -} -.collaborator_block::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.collaborator_block::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.description_block { - width: 48%; - height: 90%; - display: flex; - flex-direction: column; - align-items: center; - flex-wrap: nowrap; -} -.description_header_text { - font-size: 2vw; -} -.description_block_text { - overflow-y: auto; - overflow-x: hidden; - width: 90% !important; - height: 80% !important; - width: 50%; - background-color: #dcb495; - border-radius: 2vw; -} -.description_block_text::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.description_block_text::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.description_text { - width: 100% !important; - height: 100%; - font-size: 1.5vw; - overflow-wrap: normal; /* не поддерживает IE, Firefox; является копией word-wrap */ - word-wrap: normal; - word-break: normal; /* не поддерживает Opera12.14, значение keep-all не поддерживается IE, Chrome */ - line-break: auto; /* нет поддержки для русского языка */ - hyphens: manual; /* значение auto не поддерживается Chrome */ - margin: 2vw; -} -.open_project_block { - width: 20%; - height: 90%; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.open_button { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.open_button:hover { - text-decoration: none; - color: #000000; -} -.open_button_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.open_button, .open_button_link { - display: flex; - align-items: center; - justify-content: center; - width: 15vw; - height: 4.5vw; - color: #000000; -} -.open_button_link:hover { - text-decoration: none; - color: #000000; -} -.staff_block { - margin: 20px; -} -.user { - width: 16vw; - height: 3.5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; -} -.user_logo { - margin-left: 3px; - width: 3vw; - height: 3vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; - color: #000000 !important; -} -.new_project_button, .find_project_button { - width: 13vw; - height: 5vw; - background-color: #000000; - border: 2px solid #ffffff; - border-radius: 3vw; - margin-left: 2vw; -} -.new_project_button_text, .find_project_button_text { - width: 13vw; - height: 5vw; - text-align: center; - font-size: 1.5vw; - color: #ffffff; - display: flex; - align-items: center; - justify-content: center; -} -.new_project_button_link, find_project_button_linkk { - width: 13vw; - height: 5vw; -} -.new_project_button_link:hover, .find_project_button_linkk:hover { - text-decoration: none; - color: #000000; -} -.form_project_block { - display: flex; - align-items: center; - justify-content: center; -} -.link_to_user { - width: 16vw; - height: 3.5vw; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; - text-decoration: none; -} -.link_to_user:hover { - text-decoration: none; -} \ No newline at end of file diff --git a/static/css/recovery.css b/static/css/recovery.css deleted file mode 100644 index 5728f65..0000000 --- a/static/css/recovery.css +++ /dev/null @@ -1,62 +0,0 @@ -.recovery_page { - height: 60vw; - background-color: #dcb495; - margin-top: -1.1vw; -} -.recovery { - width: 100%; - height: 60vw; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.header_title { - text-align: center; - color: #000000; - font-size: 3.5vw; - width: 100%; -} -.recovery_form { - margin-top: 55px; - width: 70%; - display: flex; -} -.data_block { - width: 100%; - height: 100%; - display: flex; - flex-direction: row; - align-items: flex-end; - flex-wrap: nowrap; - justify-content: space-evenly; -} -.form_data { - display: flex; - flex-direction: column; - margin-left: 2%; - margin-left: 2%; - height: 100%; -} -.form-label { - font-size: 1.3vw; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.7vw; - width: 30vw; - background-color: #dbc3af; - border-radius: 5vw; - font-size: 1.3vw; -} -.recovery_button { - background-color: #000000; - color: #ffffff; - min-width: 20vw !important; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; - margin-left: 20px; -} \ No newline at end of file diff --git a/static/css/register.css b/static/css/register.css deleted file mode 100644 index 4539d6f..0000000 --- a/static/css/register.css +++ /dev/null @@ -1,84 +0,0 @@ -#navbar { - display: none; -} -#btn_cooc { - display: none -} -.register_page { - margin-top: -1.1vw; - display: flex; - justify-content: center; - align-items: center; - height: 75vw; - background: linear-gradient( rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0.55) ), url(../images/back_main_one.jpg);background-repeat: repeat; background-position: center; -} -.register { - width: 70%; - height: 70%; - margin-left: 15%; - margin-right: 15%; - background-color: #dbc3af; - display: flex; - flex-direction: column; - justify-content: space-evenly; -} -.register_form { - margin-bottom: 10%; -} -.header_title { - text-align: center; - color: #000000; - font-size: 3.5vw; - width: 100%; -} -.data_block { - width: 100%; - display: flex; - flex-direction: column; - flex-direction: column; - justify-content: center; - align-items: center; -} -.form_data, .form_data_button { - display: flex; - flex-direction: column; - margin-left: 2%; - margin-left: 2%; -} -.form_data_button { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} -.input_data { - color: #000000; - border: 0.1vw solid #595008; - height: 4.5vw; - width: 60vw; - background-color: #dbc3af; - border-radius: 5vw; - font-size: 1.3vw; -} -.input_button { - width: 20vw; - height: 5vw; - border-radius: 5vw; - vertical-align: middle; -} -.form-label { - font-size: 1.3vw; -} -.register_button { - margin-top: 15px; - width: 20vw; - height: 5vw; - background-color: #000000; - color: #ffffff; - border-radius: 5vw; - vertical-align: middle; - font-size: 1.5vw; -} -.box { - margin-left: 9vw; -} \ No newline at end of file diff --git a/static/css/showcase.css b/static/css/showcase.css deleted file mode 100644 index 76af687..0000000 --- a/static/css/showcase.css +++ /dev/null @@ -1,253 +0,0 @@ -.showscale_page { - height: 120vw; - background-color: #dcb495; - display: flex; - flex-direction: column; - align-items: center; -} -.header_block { - width: 100%; - height: 20vw; - background-position: center; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - background: linear-gradient( rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.85) ), url(../images/showcase.jpg);background-repeat: repeat; background-position: center; -} -.header_title { - color: #ffffff; - font-size: 7vw; -} -.header_title_2 { - color: #ffffff; - text-align: center; - font-size: 1.5vw; - width: 50vw; -} -.templates_block { - width: 95%; - margin-top: 5vw; -} -.templates_title, .links_title { - display: flex; - justify-content: center; - font-size: 3.5vw; -} -.templates_list { - height: 30vw; - margin-top: 2vw; - border: 0.2vw solid #694a2d; - border-radius: 2vw; - overflow-x: auto; - overflow-y: hidden; - display: flex; - align-items: center; - justify-content: flex-start; -} -.templates_list::-webkit-scrollbar { - height: 1vw; /* ширина scrollbar */ - } -.templates_list::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; - } -.template { - display: flex; - justify-content: start; - flex-direction: column; - align-items: center; - min-height: 28vw; - min-width: 25vw; - max-width: 25vw; - background-color: #9E795A; - margin: 1vw; - border-radius: 2vw; -} -.template_title { - margin-top: 1vw; - max-width: 90%; - text-align: center; - color: #ffffff; - font-size: 2vw; - font-weight: 500; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap -} -.template_title::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.template_title::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.description { - background-color: #EDCBB0; - max-width: 90; - height: auto; - height: 15vw; - min-width: 85%; - max-width: 85%; - border-radius: 0.5vw; -} -.description_text { - margin: 0.8vw; - overflow-wrap: normal; /* не поддерживает IE, Firefox; является копией word-wrap */ - word-wrap: normal; - word-break: normal; /* не поддерживает Opera12.14, значение keep-all не поддерживается IE, Chrome */ - line-break: auto; /* нет поддержки для русского языка */ - hyphens: manual; -} -.description { - overflow-y: auto; -} -.description::-webkit-scrollbar { - width: 0.8vw; /* ширина scrollbar */ -} -.description::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.open_button { - margin-top: 1vw; - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.open_button:hover { - text-decoration: none; - color: #000000; -} -.open_button_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.open_button, .open_button_link { - display: flex; - align-items: center; - justify-content: center; - width: 15vw; - height: 4.5vw; - color: #000000; -} -.open_button_link:hover { - text-decoration: none; - color: #000000; -} -.links_block { - margin-top: 4vw; - height: 17vw; - display: flex; - flex-direction: column; - align-items: center; - width: 100%; -} -.link_list { - width: 95%; - background-color: #EDCBB0; - height: 16vw; - border-radius: 1.5vw; - display: flex; - align-items: center; - overflow-x: auto; - overflow-y: hidden; -} -.link_list::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.link_list::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.link_block { - margin: 1vw; - width: 25vw; - height: 6vw; - background-color: #9E795A; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - border-radius: 1vw; -} -.link { - width: auto; - min-width: 15vw; - max-width: 20vw; - height: 6vw; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} -.link:hover { - text-decoration: none; - color: #ffffff; -} -.link_text { - margin-top: 1vw; - width: 13vw; - height: 3.5vw; - color: #ffffff; - font-size: 2vw; - overflow-x: auto; - overflow-y: hidden; - overflow-wrap: normal; /* не поддерживает IE, Firefox; является копией word-wrap */ - word-wrap: normal; - word-break: normal; /* не поддерживает Opera12.14, значение keep-all не поддерживается IE, Chrome */ - line-break: auto; /* нет поддержки для русского языка */ - hyphens: manual; - white-space: nowrap -} -.link_text::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.link_text::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.add_button, .link_delete, .repeal_button, .submit_button { - border-radius: 1vw !important; - margin: 1vw; - width: 8vw; - height: 3vw; -} -.link_delete, .repeal_button { - background-color: hsla(0, 100%, 62%, 0.785) !important; - border-color: hsla(0, 100%, 62%, 0.785) !important; -} -.delete_text { - font-size: 1.3vw; -} -.header_link { - display: flex; - flex-direction: column; - align-items: center; -} -.form_link, .file_form { - width: 90%; -} -.link_form { - display: flex; - align-items: center; - flex-direction: row; - justify-content: center; -} -.form_data { - margin: 0.5vw; -} \ No newline at end of file diff --git a/static/css/template_project.css b/static/css/template_project.css deleted file mode 100644 index 90b3853..0000000 --- a/static/css/template_project.css +++ /dev/null @@ -1,262 +0,0 @@ -.template_page { - height: 120vw; - background-color: #dcb495; - display: flex; - flex-direction: column; - align-items: center; -} -.link_back_block { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.link_back { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.link_back:hover { - text-decoration: none; - color: #000000; -} -.link_back_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.project_logo { - margin-top: 30px; - width: 15vw; - height: 15vw; - border: 0.2vw solid #ffffff; - border-radius: 2vw; -} -.brand_block { - height: 25vw; - display: flex; - flex-direction: column; - align-items: center; - justify-content: space-between; - color: #000000; -} -.name_project { - font-size: 3vw !important; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap -} -.header_task_block { - width: 60vw; - height: 30vw; - display: flex; - flex-direction: column; - align-items: center; -} -.task_block, .list_files_block { - background-color: #EDCBB0; - width: 95%; - height: 25vw; - border-radius: 2vw; - overflow-y: auto; -} -.task { - margin: 20px; -} -.body_block { - display: flex; - justify-content: space-evenly; - align-items: center; - flex-direction: column; -} -.head_task { - display: flex; - flex-direction: row; - flex-wrap: nowrap; - width: 60vw; - justify-content: center; - align-items: flex-start; -} -.list_quests { - width: 95%; - margin-left: 2.5%; - margin-top: 0.5vw; - overflow-y: hidden; - overflow-x: hidden; -} -.quest_header_button { - height: 4.5vw; - width: 100%; - text-align: left; - border-radius: 5vw; - background-color: #9E795A; - border-color: #9E795A; - border-bottom-color: #9E795A; - color: #ffffff; - display: flex; - align-items: center; -} -.quest_button_block_one { - width: 95%; - display: flex; - justify-content: space-between; - align-items: flex-start; -} -.quest_title_block { - width: 100%; - height: 4vw; - display: flex; - align-items: center; -} -.quest_title { - overflow-y: hidden; - overflow-x: auto; - max-height: 4vw; - font-size: 1.5vw; - display: flex; - align-items: center; - margin-top: 0.7vw; - margin-left: 1.8vw; - font-size: 3.5vw; - white-space: nowrap -} -.quest_title::-webkit-scrollbar { - height: 0.8vw; /* ширина scrollbar */ -} -.quest_title::-webkit-scrollbar-thumb { - background-color: #d49d51; /* цвет плашки */ - border-radius: 5vw; /* закругления плашки */ - border: 0.25vw solid #ffffff; -} -.quest_body_block { - background-color: #9E795A; - width: 100%; - height: 20vw; - border-radius: 2vw; - display: flex; - align-items: center; - justify-content: center; -} -.quest_body { - width: 94%; - height: 94%; - display: flex; - align-items: center; - justify-content: space-around; -} -.quest_description_block { - width: 100%; - height: 90%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} -.quest_description { - width: 100%; - height: 100%; - background-color: #dcb495; - border-radius: 2vw; - overflow-y: auto; -} -.quest_description::-webkit-scrollbar, .task_block::-webkit-scrollbar-thumb { - width: 0.8vw !important; -} -.quest_description::-webkit-scrollbar-thumb, .task_block::-webkit-scrollbar-thumb { - background-color: #d49d51 !important; /* цвет плашки */ - border-radius: 5vw !important; /* закругления плашки */ - border: 0.25vw solid #ffffff !important; -} -.quest_description_text { - margin: 20px; -} -.files_block { - display: flex; - flex-direction: column; - align-items: center; - width: 100%; - height: 35vw; -} -.list_files { - margin: 2vw; -} -.files_title { - text-align: center; - color: #000000; - font-size: 4vw; -} -.file { - width: 98%; - display: flex; - background-color: #9E795A; - margin: 0.5vw; - align-items: center; - justify-content: space-between; - flex-direction: row; - height: 4.5vw; - border-radius: 2vw; -} -.file_head { - width: 30vw; - margin-left: 1vw; - height: 4vw; - background-color: #9E795A !important; - overflow-y: hidden; - overflow-x: auto; -} -.file_head_path, .file_path { - font-size: 1.5vw; - color: #ffffff !important; - font-weight: bold; - height: 3vw; - display: flex; - align-items: flex-start; - background-color: #9E795A !important; -} -.file_buttons { - margin-right: 2vw; -} -.file_delete, .file_download, .upload_button { - border-radius: 1vw !important; - margin: 1vw; - width: 8vw; - height: 3vw; -} -.file_delete { - background-color: hsla(0, 100%, 62%, 0.785) !important; - border-color: hsla(0, 100%, 62%, 0.785) !important; -} -.button_text { - font-size: 1.3vw; -} -.create_project_block { - width: 13vw; - height: 5vw; - background-color: #000000; - border: 2px solid #ffffff; - border-radius: 3vw; - margin-left: 2vw; -} -.create_link:hover { - text-decoration: none; - color: #000000; -} -.create_text { - width: 13vw; - height: 5vw; - text-align: center; - font-size: 1.5vw; - color: #ffffff; - display: flex; - align-items: center; - justify-content: center; -} \ No newline at end of file diff --git a/static/css/user_view.css b/static/css/user_view.css deleted file mode 100644 index 5bead1e..0000000 --- a/static/css/user_view.css +++ /dev/null @@ -1,263 +0,0 @@ -.user_view_page { - height: 120vw; - background-color: #dcb495; -} -.user_data_block { - width: 85%; - height: 65vw; - margin-left: 7.5%; - display: flex; - flex-direction: column; - align-items: center; - background-color:#a8886f; - border-radius: 4vw; -} -.user_photo { - margin-top: 30px; - width: 15vw; - height: 15vw; - border: 0.2vw solid #ffffff; - border-radius: 2vw; -} -.first_data_block { - width: 100%; - display: flex; - align-items: center; - justify-content: space-evenly; -} -.user_data { - width: 95%; - height: 30vw; - display: flex; - flex-direction: column; - align-items: center; -} -.data_header { - font-size: 2vw; - color: #ffffff; - font-weight: bold; -} -.data_block { - background-color:#f5d3b8; - width: 25vw; - height: 5vw; - border-radius: 5vw; - display: flex; - justify-content: center; - align-items: center; -} -.data_text { - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - margin-top: 5px; - font-size: 1.5vw; - color: #000000; - overflow-x: auto; -} -.surname_block, .about_block { - width: 90%; -} -.about_bottom { - border-radius: 3vw; - height: 20vw !important; -} -.data_bottom { - width: 100% !important; -} -.list_project { - width: 95%; - margin-left: 2.5%; - margin-top: 2vw; - overflow-y: hidden; - overflow-x: hidden; -} -.project_header_button { - height: 5.5vw; - width: 100%; - text-align: left; - border-radius: 5vw; - background-color: #9E795A; - border-color: #9E795A; - border-bottom-color: #9E795A; - color: #ffffff; - display: flex; - align-items: center; -} -.project_description_block { - background-color: #9E795A; - width: 100%; - height: 20vw; - border-radius: 2vw; -} -.project_logo_block { - width: 4.5vw; - height: 4.5vw; - border: 0.3vw solid #ffffff; - background-color: #ffffff; - border-radius: 2vw; - display: flex; - justify-content: center; - align-items: center; -} -.project_logo { - width: 4vw; - height: 4vw; - border-radius: 5vw; -} -.project_title_block { - width: 70%; - height: 4vw; -} -.project_title { - font-size: 3.5vw; - overflow-y: hidden; - overflow-x: auto; - white-space: nowrap -} -.project_button_block_one { - width: 50%; - display: flex; - justify-content: space-evenly; - align-items: flex-start; -} -.project_description { - width: 98%; - height: 100%; - margin-left: 1%; - display: flex; - flex-direction: row; - flex-wrap: nowrap; - align-content: center; - align-items: center; - justify-content: space-evenly; -} -.collaborator_block { - width: 22%; - height: 90%; - background-color: #EDCBB0; - border-radius: 2vw; - overflow-y: auto; -} -.description_block { - width: 48%; - height: 90%; - display: flex; - flex-direction: column; - align-items: center; - flex-wrap: nowrap; -} -.description_header_text { - font-size: 2vw; -} -.description_block_text { - width: 90% !important; - height: 80% !important; - width: 50%; - background-color: #dcb495; - border-radius: 2vw; -} -.description_text { - width: 100% !important; - height: 100%; - font-size: 1.5vw; - overflow-wrap: normal; /* не поддерживает IE, Firefox; является копией word-wrap */ - word-wrap: normal; - word-break: normal; /* не поддерживает Opera12.14, значение keep-all не поддерживается IE, Chrome */ - line-break: auto; /* нет поддержки для русского языка */ - hyphens: manual; /* значение auto не поддерживается Chrome */ - margin: 2vw; -} -.user_projects_block { - margin-top: 35px; - margin-left: 3%; - border: 0.2vw solid #694a2d; - border-radius: 4.5vw; - width: 94%; - height: 45vw; - overflow-y: auto; -} -.user { - width: 16vw; - height: 3.5vw; - background-color: #ffffff; - border: 2px solid #9E795A; - border-radius: 3vw; - margin-top: 5px; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; -} -.user_logo { - margin-left: 3px; - width: 3vw; - height: 3vw; - border-radius: 5vw; - background-color: #000000; -} -.user_names { - margin-left: 9px; - margin-top: 10px; - overflow-x: auto; - color: #000000 !important; -} -.link_to_user { - width: 16vw; - height: 3.5vw; - display: flex; - align-items: center; - justify-content: flex-start; - flex-direction: row; - flex-wrap: no-wrap; - text-decoration: none; -} -.link_to_user:hover { - text-decoration: none; -} -.open_project_block { - width: 20%; - height: 90%; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - flex-wrap: nowrap; -} -.open_button { - background-color: #ffffff; - color: #000000; - width: 15vw; - height: 4.5vw; - vertical-align: middle; - border-radius: 5vw; - display: flex; - align-items: center; - justify-content: center; -} -.open_button:hover { - text-decoration: none; - color: #000000; -} -.open_button_text { - font-size: 1.5vw; - margin-top: 15px; - display: flex; - align-items: center; - justify-content: center; -} -.open_button, .open_button_link { - display: flex; - align-items: center; - justify-content: center; - width: 15vw; - height: 4.5vw; - color: #000000; -} -.open_button_link:hover { - text-decoration: none; - color: #000000; -} \ No newline at end of file diff --git a/static/images/back_main_one.jpg b/static/images/back_main_one.jpg deleted file mode 100644 index 7621181..0000000 Binary files a/static/images/back_main_one.jpg and /dev/null differ diff --git a/static/images/back_main_two.jpg b/static/images/back_main_two.jpg deleted file mode 100644 index 496a7b8..0000000 Binary files a/static/images/back_main_two.jpg and /dev/null differ diff --git a/static/images/back_profile_one.jpg b/static/images/back_profile_one.jpg deleted file mode 100644 index c487af0..0000000 Binary files a/static/images/back_profile_one.jpg and /dev/null differ diff --git a/static/images/back_profile_two.jpg b/static/images/back_profile_two.jpg deleted file mode 100644 index 57cc6c1..0000000 Binary files a/static/images/back_profile_two.jpg and /dev/null differ diff --git a/static/images/back_project_one.jpg b/static/images/back_project_one.jpg deleted file mode 100644 index 0619403..0000000 Binary files a/static/images/back_project_one.jpg and /dev/null differ diff --git a/static/images/black_arrow.png b/static/images/black_arrow.png deleted file mode 100644 index 6a84006..0000000 Binary files a/static/images/black_arrow.png and /dev/null differ diff --git a/static/images/logo_b.ico b/static/images/logo_b.ico deleted file mode 100644 index 54b0d84..0000000 Binary files a/static/images/logo_b.ico and /dev/null differ diff --git a/static/images/logo_b.png b/static/images/logo_b.png deleted file mode 100644 index 9e04d48..0000000 Binary files a/static/images/logo_b.png and /dev/null differ diff --git a/static/images/logo_w.ico b/static/images/logo_w.ico deleted file mode 100644 index 2a5cfb8..0000000 Binary files a/static/images/logo_w.ico and /dev/null differ diff --git a/static/images/logo_w.png b/static/images/logo_w.png deleted file mode 100644 index f128b02..0000000 Binary files a/static/images/logo_w.png and /dev/null differ diff --git a/static/images/main_image_1.jpg b/static/images/main_image_1.jpg deleted file mode 100644 index 0619403..0000000 Binary files a/static/images/main_image_1.jpg and /dev/null differ diff --git a/static/images/main_image_2.png b/static/images/main_image_2.png deleted file mode 100644 index 589a0c9..0000000 Binary files a/static/images/main_image_2.png and /dev/null differ diff --git a/static/images/main_image_3.png b/static/images/main_image_3.png deleted file mode 100644 index 947c5c7..0000000 Binary files a/static/images/main_image_3.png and /dev/null differ diff --git a/static/images/main_image_4.png b/static/images/main_image_4.png deleted file mode 100644 index b8b1cab..0000000 Binary files a/static/images/main_image_4.png and /dev/null differ diff --git a/static/images/main_image_5.png b/static/images/main_image_5.png deleted file mode 100644 index 4787f8a..0000000 Binary files a/static/images/main_image_5.png and /dev/null differ diff --git a/static/images/main_image_6.jpg b/static/images/main_image_6.jpg deleted file mode 100644 index e0ad3fe..0000000 Binary files a/static/images/main_image_6.jpg and /dev/null differ diff --git a/static/images/none_logo.png b/static/images/none_logo.png deleted file mode 100755 index ddd8fad..0000000 Binary files a/static/images/none_logo.png and /dev/null differ diff --git a/static/images/none_project.png b/static/images/none_project.png deleted file mode 100644 index 4aabb8b..0000000 Binary files a/static/images/none_project.png and /dev/null differ diff --git a/static/images/pen_b.png b/static/images/pen_b.png deleted file mode 100644 index ac9e99e..0000000 Binary files a/static/images/pen_b.png and /dev/null differ diff --git a/static/images/pen_w.png b/static/images/pen_w.png deleted file mode 100644 index f94d2a9..0000000 Binary files a/static/images/pen_w.png and /dev/null differ diff --git a/static/images/plus_b.png b/static/images/plus_b.png deleted file mode 100644 index 840785b..0000000 Binary files a/static/images/plus_b.png and /dev/null differ diff --git a/static/images/plus_w.png b/static/images/plus_w.png deleted file mode 100644 index 6609de4..0000000 Binary files a/static/images/plus_w.png and /dev/null differ diff --git a/static/images/showcase.jpg b/static/images/showcase.jpg deleted file mode 100644 index 730881b..0000000 Binary files a/static/images/showcase.jpg and /dev/null differ diff --git a/static/images/yellow_cup.svg b/static/images/yellow_cup.svg deleted file mode 100644 index aeb03c0..0000000 --- a/static/images/yellow_cup.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/static/images/yellow_like.svg b/static/images/yellow_like.svg deleted file mode 100644 index a619b71..0000000 --- a/static/images/yellow_like.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - diff --git a/static/images/yellow_man.svg b/static/images/yellow_man.svg deleted file mode 100644 index 6438d81..0000000 --- a/static/images/yellow_man.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - diff --git a/static/js/project.js b/static/js/project.js deleted file mode 100644 index 22f4e38..0000000 --- a/static/js/project.js +++ /dev/null @@ -1,15 +0,0 @@ -var edit_button = document.getElementById("edit_button"), -new_task_link = document.getElementById("new_task_link"), -quest_solve_link = document.getElementById("quest_solve_link"), -quest_solve_link_id = document.getElementById("quest_solve_link_id"), -is_template = document.getElementById("is_template"); - -edit_button.href = String(window.location.href) + '/edit'; -new_task_link.href = String(window.location.href) + '/quest/new'; - -function push_file() -{ - document.getElementById('selectedFile').click(); - document.getElementById('upload_button').style = 'display: block;'; - document.getElementById('select_file_button').style = 'display: none;'; -} \ No newline at end of file diff --git a/static/js/scroll.js b/static/js/scroll.js deleted file mode 100644 index 0486bd5..0000000 --- a/static/js/scroll.js +++ /dev/null @@ -1,18 +0,0 @@ -var prevScrollpos = window.pageYOffset; -window.onload = function() -{ -document.getElementById("navbar").style.display = "none"; -} -window.onscroll = function() { - var currentScrollPos = window.pageYOffset; - - // 20 is an arbitrary number here, just to make you think if you need the prevScrollpos variable: - if (currentScrollPos > 1250) { - // I am using 'display' instead of 'top': - document.getElementById("navbar").style.display = "initial"; - } - else { - document.getElementById("navbar").style.display = "none"; - } -} - diff --git a/static/js/showcase.js b/static/js/showcase.js deleted file mode 100644 index ca863f6..0000000 --- a/static/js/showcase.js +++ /dev/null @@ -1,12 +0,0 @@ -function add_link() -{ - document.getElementById('add_link_button').style = 'display: none;'; - document.getElementById('repeal_link_button').style = 'display: block;'; - document.getElementById('form_link').style = 'display: block;'; -} -function repeal_link() -{ - document.getElementById('add_link_button').style = 'display: block;'; - document.getElementById('repeal_link_button').style = 'display: none;'; - document.getElementById('form_link').style = 'display: none;'; -} \ No newline at end of file