diff --git a/forms/edit_profile.py b/forms/edit_profile.py new file mode 100644 index 0000000..8aff299 --- /dev/null +++ b/forms/edit_profile.py @@ -0,0 +1,15 @@ +from flask_wtf import FlaskForm +from flask_wtf.file import FileAllowed +from wtforms import EmailField, StringField, TextAreaField, FileField, SubmitField, DateField +from wtforms.validators import DataRequired + + +class EditProfileForm(FlaskForm): + email = EmailField('Почта', validators=[DataRequired()]) + name = StringField('Имя', validators=[DataRequired()]) + surname = StringField('Фамилия', ) + about = TextAreaField('Расскажите о себе', default='') + birthday = DateField('Дата рождения') + photo = FileField('Фото', validators=[FileAllowed(['jpg', 'png', 'bmp'], 'Только фотографии!')]) + del_photo = SubmitField('Удалить фотографию') + submit = SubmitField('Сохранить') \ No newline at end of file diff --git a/forms/register.py b/forms/register.py index 5872b19..0e6613e 100644 --- a/forms/register.py +++ b/forms/register.py @@ -1,6 +1,6 @@ from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed -from wtforms import EmailField, StringField, PasswordField, SubmitField, FileField, DateField, TextAreaField +from wtforms import EmailField, StringField, PasswordField, SubmitField from wtforms.validators import DataRequired diff --git a/functions.py b/functions.py index 215254e..d28d749 100644 --- a/functions.py +++ b/functions.py @@ -1,37 +1,37 @@ -import smtplib -from email.message import EmailMessage - - -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='Подтверждение почты'): - file = open('mail.incepted', 'r', encoding='utf-8').readline().split() - login, password = file[0], file[1] - 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() +import smtplib +from email.message import EmailMessage + + +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='Подтверждение почты'): + file = open('mail.incepted', 'r', encoding='utf-8').readline().split() + login, password = file[0], file[1] + 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() diff --git a/main.py b/main.py index a35329a..b399594 100644 --- a/main.py +++ b/main.py @@ -1,133 +1,195 @@ -import datetime - -from flask import Flask, render_template, request, url_for -from flask_login import login_user, current_user, LoginManager, logout_user, login_required -from werkzeug.utils import redirect -from itsdangerous import URLSafeTimedSerializer, SignatureExpired - -from functions import check_password, mail -from forms.login import LoginForm -from forms.register import RegisterForm -from data.users import User -from waitress import serve -from data import db_session - -app = Flask(__name__) -key = 'test_secret_key' -app.config['SECRET_KEY'] = key -s = URLSafeTimedSerializer(key) -login_manager = LoginManager() -login_manager.init_app(app) - - -@app.route('/') -def base(): - return render_template('main.html', title='Главная') - - -@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(): - db_sess = db_session.create_session() - user = db_sess.query(User).filter(User.email == form.login.data).first() - if user and user.check_password(form.password.data): - if user.activated: - login_user(user, remember=form.remember_me.data) - return redirect('/') - 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('/') - - -@app.route('/logout') -@login_required -def logout(): - logout_user() - return redirect("/") - - -@app.route('/register', methods=['GET', 'POST']) -def register(): - if not current_user.is_authenticated: - 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='Регистрация') - if data_session.query(User).filter(User.email == form.email.data).first(): - return render_template('register.html', form=form, message="Такая почта уже есть", title='Регистрация') - status_password = check_password(form.password.data) - if status_password != 'OK': - return render_template('register.html', form=form, message=status_password, title='Регистрация') - user = User( - email=form.email.data, - name=form.name.data, - login=form.login.data, - activity=datetime.datetime.now() - ) - user.set_password(form.password.data) - data_session.add(user) - data_session.commit() - data_session.close() - token = s.dumps(form.email.data) - link_conf = url_for('confirmation', token=token, _external=True) - mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, - 'Подтверждение регистрации') - return redirect('/login?message=Мы выслали ссылку для подтверждения почты') - return render_template('register.html', form=form, message='', title='Регистрация') - else: - return redirect('/') - - -@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() - data_session.close() - 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() - data_session.close() - return redirect('/login?message=Срок действия ссылки истек, данные удалены&danger=True') - - -def main(): - db_session.global_init("db/incepted.db") - serve(app, host='0.0.0.0', port=5000) - - -if __name__ == '__main__': - main() +import datetime +import os + +from flask import Flask, render_template, request, url_for +from flask_login import login_user, current_user, LoginManager, logout_user, login_required +from werkzeug.datastructures import CombinedMultiDict +from werkzeug.utils import redirect +from itsdangerous import URLSafeTimedSerializer, SignatureExpired + +from functions import check_password, mail +from forms.edit_profile import EditProfileForm +from forms.login import LoginForm +from forms.register import RegisterForm +from data.users import User +from waitress import serve +from data import db_session + +app = Flask(__name__) +key = 'test_secret_key' +app.config['SECRET_KEY'] = key +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('/project') + + +@app.route('/project') +def project(): + if current_user.is_authenticated: + return redirect(f'/profile') + else: + return redirect('/login') + + +@app.route('/profile', methods=['GET', 'POST']) +def profile(): + if current_user.is_authenticated: + 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: + data_session = db_session.create_session() + user = data_session.query(User).filter(User.id == current_user.id).first() + if not user: + return render_template('profile.html', title='Профиль', form=form, + message='Ошибка, пользователь ненайден') + os.remove(current_user.photo) + user.photo = 'static/images/none_logo.png' + data_session.commit() + data_session.close() + if form.validate_on_submit(): + data_session = db_session.create_session() + user = data_session.query(User).filter(User.id == current_user.id).first() + if not user: + return render_template('profile.html', title='Профиль', form=form, + message='Ошибка, пользователь ненайден') + if form.email.data != current_user.email: + pass + 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() + data_session.close() + return redirect('/profile') + return render_template('profile.html', title='Профиль', form=form, message='') + 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(): + db_sess = db_session.create_session() + user = db_sess.query(User).filter(User.email == form.login.data).first() + if user and user.check_password(form.password.data): + if user.activated: + login_user(user, remember=form.remember_me.data) + return redirect('/') + 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('/project') + + +@app.route('/logout') +@login_required +def logout(): + logout_user() + return redirect("/") + + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if not current_user.is_authenticated: + 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='Регистрация') + if data_session.query(User).filter(User.email == form.email.data).first(): + return render_template('register.html', form=form, message="Такая почта уже есть", title='Регистрация') + status_password = check_password(form.password.data) + if status_password != 'OK': + return render_template('register.html', form=form, message=status_password, 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='user' + ) + user.set_password(form.password.data) + data_session.add(user) + data_session.commit() + data_session.close() + token = s.dumps(form.email.data) + link_conf = url_for('confirmation', token=token, _external=True) + mail(f'Для завершения регистрации пройдите по ссылке: {link_conf}', form.email.data, + 'Подтверждение регистрации') + return redirect('/login?message=Мы выслали ссылку для подтверждения почты') + return render_template('register.html', form=form, message='', title='Регистрация') + else: + return redirect('/project') + + +@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() + data_session.close() + 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() + data_session.close() + return redirect('/login?message=Срок действия ссылки истек, данные удалены&danger=True') + + +def main(): + db_session.global_init("db/incepted.db") + serve(app, host='0.0.0.0', port=5000) + + +if __name__ == '__main__': + main() diff --git a/static/app_files/заглушка b/static/app_files/user_logo/заглушка similarity index 100% rename from static/app_files/заглушка rename to static/app_files/user_logo/заглушка diff --git a/static/css/base.css b/static/css/base.css index f8d2a3c..5cf1eea 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -1,51 +1,91 @@ -html { - background-color: #fdf5e6; - height: 100%; -} -body { - min-height: 100%; -} -.navbar { - background-color: #dcb495; - display: inline-flex; - height: 8vw; -} -#navbar { - 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; +html { + background-color: #fdf5e6; + height: 100%; +} +body { + min-height: 100%; +} +.navbar { + background-color: #dcb495; + display: inline-flex; + height: 8vw; +} +#navbar { + 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: 10px; + align-self: center; +} +.nav_chapter_text { + height: 100%; + font-family: Georgia, 'Times New Roman', Times, serif; + 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%; } \ No newline at end of file diff --git a/static/css/login.css b/static/css/login.css index 071fe13..4af0234 100644 --- a/static/css/login.css +++ b/static/css/login.css @@ -1,95 +1,95 @@ -#navbar { - display: none; -} -.login_page { - 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; +#navbar { + display: none; +} +.login_page { + 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; } \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index 76437d1..0d02ec7 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,258 +1,271 @@ -main, html { - background-color: #dcb495; -} -#header_block { - position: absolute; - margin-bottom: 60%; -} -.header_block { - 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; +main, html { + background-color: #dcb495; +} +#header_block { + position: absolute; + margin-bottom: 60%; +} +.header_block { + 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_button:hover { + background-color: #1c59fe; } \ No newline at end of file diff --git a/static/css/profile.css b/static/css/profile.css new file mode 100644 index 0000000..9845021 --- /dev/null +++ b/static/css/profile.css @@ -0,0 +1,95 @@ +.profile_page { + display: flex; + flex-direction: column; + height: 70vw; + 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 { + height: 80%; + width: 85%; + margin-left: 7.5%; + margin-top: 10%; + 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; +} +.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%; + 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: 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; +} +#delete_button { + margin-top: 45px; +} \ No newline at end of file diff --git a/static/css/register.css b/static/css/register.css index 715c677..4c989ac 100644 --- a/static/css/register.css +++ b/static/css/register.css @@ -1,80 +1,80 @@ -#navbar { - display: none; -} -.register_page { - 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; +#navbar { + display: none; +} +.register_page { + 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/images/back_profile_one.jpg b/static/images/back_profile_one.jpg new file mode 100644 index 0000000..c487af0 Binary files /dev/null and b/static/images/back_profile_one.jpg differ diff --git a/static/images/back_profile_two.jpg b/static/images/back_profile_two.jpg new file mode 100644 index 0000000..57cc6c1 Binary files /dev/null and b/static/images/back_profile_two.jpg differ diff --git a/static/images/none_logo.png b/static/images/none_logo.png new file mode 100755 index 0000000..ddd8fad Binary files /dev/null and b/static/images/none_logo.png differ diff --git a/templates/base.html b/templates/base.html index e3a0825..224b790 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,45 +1,58 @@ - - - - - - - - {{title}} - - - - - -
{% block content %}{% endblock %}
-
- -
- - + + + + + + + + {{title}} + + + + {% if current_user.is_authenticated %} + + {% else %} + + {% endif %} + +
{% block content %}{% endblock %}
+
+ +
+ + diff --git a/templates/login.html b/templates/login.html index bda424d..67795d5 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,55 +1,55 @@ - -{% extends "base.html" %} {% block content %} - -{% endblock %} + +{% extends "base.html" %} {% block content %} + +{% endblock %} diff --git a/templates/main.html b/templates/main.html index 80c9627..8906d04 100644 --- a/templates/main.html +++ b/templates/main.html @@ -1,115 +1,118 @@ - -{% extends "base.html" %} - -{% block content %} -
-
-
-

INCEPTED

- Самый удобный сайт для создания проектов -
- -
-
-
-
-

Почему INCEPTED?

-
-
-
- - Проект INCEPTED позволяет создавать проекты, поддерживать их, вести - учет активности участников, - контролировать их материалы и получать уведомления по истечению срока дедлайна -
-
- - Индивидуальные и расширенные возможности по созданию проектов -
-
- - Быстро, удобно, без лишних функций -
-
- -
-
-
-

Как это работает ?

-
-
- -
- Появление идеи -

Вы в любой момент можете создать и заполнить описание проекта, как - и построить задачи для него.

-
-
-
- -
- Сбор команды -

Вы можете добавить участников в свою команду и дать им необходимые - задачи.

-
-
-
- -
- Проверка выполнения -

В редакторе проекта вы можете отслеживать выполнение задач - участников и проверять их

-
-
-
- -
- Представление проекта -

После завершения проекта вы можете вывести в виде архива со всеми - нужными файлами или заморозить его.

-
-
-
-
-
-

Зарегистрируйся и пользуйся!

-
-
-

Проектирование ждет тебя !

- -

Регистрируясь, вы подтверждаете политику конфиденциальности.

-
- -
-
- -
+ +{% extends "base.html" %} + +{% block content %} + + + +
+
+
+

INCEPTED

+ Самый удобный сайт для создания проектов +
+ +
+
+
+
+

Почему INCEPTED?

+
+
+
+ + Проект INCEPTED позволяет создавать проекты, поддерживать их, вести + учет активности участников, + контролировать их материалы и получать уведомления по истечению срока дедлайна +
+
+ + Индивидуальные и расширенные возможности по созданию проектов +
+
+ + Быстро, удобно, без лишних функций +
+
+ +
+
+
+

Как это работает ?

+
+
+ +
+ Появление идеи +

Вы в любой момент можете создать и заполнить описание проекта, как + и построить задачи для него.

+
+
+
+ +
+ Сбор команды +

Вы можете добавить участников в свою команду и дать им необходимые + задачи.

+
+
+
+ +
+ Проверка выполнения +

В редакторе проекта вы можете отслеживать выполнение задач + участников и проверять их

+
+
+
+ +
+ Представление проекта +

После завершения проекта вы можете вывести в виде архива со всеми + нужными файлами или заморозить его.

+
+
+
+
+
+

Зарегистрируйся и пользуйся!

+
+
+

Проектирование ждет тебя !

+ +

Регистрируясь, вы подтверждаете политику конфиденциальности.

+
+ +
+
+ +
{% endblock %} \ No newline at end of file diff --git a/templates/profile.html b/templates/profile.html new file mode 100644 index 0000000..92eba32 --- /dev/null +++ b/templates/profile.html @@ -0,0 +1,79 @@ + +{% 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", type="name", placeholder='about') }} {% + for error in form.about.errors %} + + {% endfor %} +
+ {% if 'none' in current_user.photo %} +
+ + {{ form.photo(class="input_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") }} +
+
+
+
+
+{% endblock %} \ No newline at end of file