Эх сурвалжийг харах

Начал работать над задачами в проектах, сделал файл конфигурации для задания логина и пароля от почты сайта и задания ключа шифрования

Andrei 3 жил өмнө
parent
commit
03b523bea8

+ 17 - 0
data/proof_to_quests.py

@@ -0,0 +1,17 @@
+import sqlalchemy
+from flask_login import UserMixin
+from datetime import datetime
+
+from .db_session import SqlAlchemyBase
+
+
+class Proofs(SqlAlchemyBase, UserMixin):
+    __tablename__ = 'proofs'
+
+    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
+    quest = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("quests.id"), nullable=True, default=None)
+    file = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("files.id"), nullable=True, default=None)
+    creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True,
+                                default=None)
+    date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
+    date_edit = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())

+ 3 - 3
data/quests.py

@@ -1,6 +1,6 @@
 import sqlalchemy
 from flask_login import UserMixin
-from datetime import date
+from datetime import datetime
 
 from .db_session import SqlAlchemyBase
 
@@ -13,6 +13,6 @@ class Quests(SqlAlchemyBase, UserMixin):
     creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True, default=None)
     name = sqlalchemy.Column(sqlalchemy.String, nullable=False)
     description = sqlalchemy.Column(sqlalchemy.String, nullable=True)
-    date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=date.today())
-    deadline = sqlalchemy.Column(sqlalchemy.DateTime, default=date.today())
+    date_create = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
+    deadline = sqlalchemy.Column(sqlalchemy.DateTime, default=datetime.now())
     realized = sqlalchemy.Column(sqlalchemy.Boolean, default=False)

+ 4 - 2
functions.py

@@ -1,4 +1,5 @@
 import smtplib
+from json import loads
 from email.message import EmailMessage
 from data.roles import Roles
 from data.users import User
@@ -22,8 +23,9 @@ def check_password(password=''):
 
 
 def mail(msg, to, topic='Подтверждение почты'):
-    file = open('mail.incepted', 'r', encoding='utf-8').readline().split()
-    login, password = file[0], file[1]
+    with open('incepted.config', 'r', encoding='utf-8').read() as file:
+        file = loads(file)
+    login, password = file["mail_login"], file["mail_password"]
     email_server = "smtp.yandex.ru"
     sender = "incepted@yandex.ru"
     em = EmailMessage()

+ 17 - 5
main.py

@@ -9,6 +9,7 @@ from werkzeug.datastructures import CombinedMultiDict
 from werkzeug.utils import redirect
 from itsdangerous import URLSafeTimedSerializer, SignatureExpired
 from sqlalchemy import or_
+from json import loads
 
 from functions import check_password, mail, init_db_default, get_projects_data, get_user_data, save_project_logo
 from forms.edit_profile import EditProfileForm
@@ -28,7 +29,10 @@ from waitress import serve
 from data import db_session
 
 app = Flask(__name__)
-key = 'test_secret_key'
+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
 csrf = CSRFProtect(app)
 s = URLSafeTimedSerializer(key)
@@ -83,7 +87,7 @@ def edit_project(id_project):
                     current_project.name = form.name.data
                     current_project.description = form.description.data
                     data_session.commit()
-                    return redirect(f'/project/{current_project.id}/edit')
+                    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'
@@ -109,8 +113,9 @@ def project(id_project):
         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)):
-
-                return render_template('project.html', project=current_project, title=current_project.name)
+                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 []
+                return render_template('project.html', project=current_project, title=current_project.name, staff=staff)
             else:
                 abort(403)
         else:
@@ -180,6 +185,7 @@ def delete_project(id_project):
                         data_session.delete(i)
                     if 'none_project' not in project_del.photo:
                         os.remove(project_del.photo)
+                    shutil.rmtree(f'static/app_files/all_projects/{str(project_del.id)}')
                     data_session.delete(project_del)
                     data_session.commit()
                     return redirect('/projects')
@@ -241,6 +247,7 @@ def new_project():
                     )
                     data_session.add(new_staffer)
             data_session.commit()
+            os.mkdir(f'static/app_files/all_projects/{str(currnet_project.id)}')
             return redirect('/projects')
         return render_template('new_project.html', title='Новый проект', form=form, list_users=list_users)
     else:
@@ -302,7 +309,12 @@ def profile():
                 return render_template('profile.html', title='Профиль', form=form,
                                        message='Ошибка, пользователь ненайден')
             if form.email.data != current_user.email:
-                pass
+                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)

BIN
requirements.txt


+ 107 - 12
static/css/project.css

@@ -22,20 +22,10 @@
     flex-direction: column;
     align-items: center;
     justify-content: space-between;
-    color: #dcb495
-    #a8886f
-    #f5d3b8
-    #a65b1e
-    #d49d51
-    #face7d
-    #ffe8d6
-    #a8876b
-    #fff2e8
-    #c79b77
-    #d69d5c;
+    color: #dcb495;
 }
 .name_project {
-    font-size: 3vw;
+    font-size: 3vw !important;
 }
 .edit_block {
     display: flex;
@@ -52,4 +42,109 @@
 .edit_button_image {
     height: 3vw;
     width: 3vw;
+}
+.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;
+}
+.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 {
+    width: 100%;
+}
+.header_task_block {
+    width: 60vw;
+    height: 30vw;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+.task_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: flex-start;
+    flex-direction: row;
+}
+.new_task_block {
+    width: 4.5vw;
+    height: 4.5vw;
+}
+.new_task_link {
+    width: 4.5vw;
+    height: 4.5vw;
+}
+.new_task_image {
+    width: 4.5vw;
+    height: 4.5vw;
+}
+.head_task {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    width: 60vw;
 }

BIN
static/images/plus_b.png


BIN
static/images/plus_w.png


+ 2 - 2
templates/base.html

@@ -29,8 +29,8 @@
         <a class="nav_chapter" href="/projects">
           <p class="nav_chapter_text">Проекты</p>
         </a>
-        <a class="nav_chapter" href="/messages">
-          <p class="nav_chapter_text">Сообщения</p>
+        <a class="nav_chapter" href="/showcase">
+          <p class="nav_chapter_text">Витрина</p>
         </a>
       </div>
     </nav>

+ 29 - 5
templates/project.html

@@ -9,18 +9,42 @@
         </div>
         <div class="brand_block">
             <img class="project_logo" src="../{{project.photo}}"/>
-            <p class="name_project">{{ project.name }}</p>
+            <p class="name_project header_title">{{ project.name }}</p>
         </div>
         <div class="notification_block">
 
         </div>
     </div>
     <div class="body_block">
-        <div class="staff_block">
-
+        <div class="head_staff_block">
+            <h3 class="header_title">Участники</h3>
+            <div class="collaborator_block">
+                <div class="staff_block">
+                    {% for user in staff %}
+                    <div class="user">
+                        <a class="link_to_user" href="/user/{{ user.login }}">
+                            <img class="user_logo" src="../{{user.photo}}">
+                            <p class="user_names">{{user.name}}</p>
+                        </a>
+                    </div>
+                    {% endfor %}
+                </div>
+            </div>
         </div>
-        <div class="task_block">
-
+        <div class="header_task_block">
+            <div class="head_task">
+                <h3 class="header_title_2">Задачи</h3>
+                <div class="new_task_block">
+                    <a class="new_task_link" href="/">
+                        <img class="new_task_image" src="../static/images/plus_b.png">
+                    </a>
+                </div>
+            </div>
+            <div class="task_block">
+                <div class="task">
+                    p
+                </div>
+            </div>
         </div>
     </div>
     <div class="files_block">