Преглед на файлове

Сделал задачи в проектах, можно создавать задачу, устанавливать дедлайн, отвечать на задачу файлами или текстом

Andrei преди 2 години
родител
ревизия
88c2430ef4
променени са 13 файла, в които са добавени 514 реда и са изтрити 185 реда
  1. 2 3
      data/answer.py
  2. 12 0
      data/proof_file.py
  3. 7 3
      forms/task.py
  4. 35 2
      functions.py
  5. 100 6
      main.py
  6. 0 0
      static/app_files/all_projects/заглушка
  7. 243 0
      static/css/answer.css
  8. 0 124
      static/css/decision.css
  9. 2 1
      static/js/project.js
  10. 94 0
      templates/answer.html
  11. 0 41
      templates/decision.html
  12. 1 2
      templates/login.html
  13. 18 3
      templates/project.html

+ 2 - 3
data/proof_to_quests.py → data/answer.py

@@ -5,12 +5,11 @@ from datetime import datetime
 from .db_session import SqlAlchemyBase
 
 
-class Proofs(SqlAlchemyBase, UserMixin):
-    __tablename__ = 'proofs'
+class Answer(SqlAlchemyBase, UserMixin):
+    __tablename__ = 'answer'
 
     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)
     text = sqlalchemy.Column(sqlalchemy.Text, nullable=True, default=None)
     creator = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("users.id"), nullable=True,
                                 default=None)

+ 12 - 0
data/proof_file.py

@@ -0,0 +1,12 @@
+import sqlalchemy
+from flask_login import UserMixin
+from datetime import datetime
+
+from .db_session import SqlAlchemyBase
+
+
+class FileProof(SqlAlchemyBase, UserMixin):
+    __tablename__ = 'file_proof'
+    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True)
+    answer = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("answer.id"), nullable=True, default=None)
+    file = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("files.id"), nullable=True, default=None)

+ 7 - 3
forms/task.py

@@ -1,5 +1,6 @@
 from flask_wtf import FlaskForm
-from wtforms import StringField, SubmitField, TextAreaField, DateField, TimeField, FileField
+from wtforms import StringField, SubmitField, TextAreaField, DateField, TimeField, MultipleFileField, \
+    BooleanField
 from wtforms.validators import DataRequired
 
 
@@ -13,5 +14,8 @@ class NewTask(FlaskForm):
 
 class AnswerTask(FlaskForm):
     text = TextAreaField('Письменный ответ')
-    file = FileField('Файловый ответ')
-    submit = SubmitField('Ответить')
+    file = MultipleFileField('Файловый ответ')
+    realized = BooleanField('Задача решена')
+    deadline_date = DateField('Дедлайн', validators=[DataRequired()])
+    deadline_time = TimeField('', validators=[DataRequired()])
+    submit = SubmitField('Сохранить')

+ 35 - 2
functions.py

@@ -1,10 +1,13 @@
 import datetime
+import os
 import smtplib
 from json import loads
 from email.message import EmailMessage
 from data.roles import Roles
 from data.users import User
 from data.staff_projects import StaffProjects
+from data.answer import Answer
+from data.files import Files
 from data import db_session
 import uuid
 import pymorphy2
@@ -95,12 +98,14 @@ def save_project_logo(photo):
 
 
 def overdue_quest_project(quest):
-    if str(quest.deadline.date()) == str(datetime.datetime.now().date()):
+    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)
-    else:
+    elif quest.deadline > datetime.datetime.now():
         quest.overdue = 'no'
         quest.time_left = 'Еще есть: ' + round_date(quest.deadline)
     return quest
@@ -120,3 +125,31 @@ def round_date(date_time):
     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('/')}

+ 100 - 6
main.py

@@ -12,7 +12,7 @@ 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, \
-    overdue_quest_project
+    overdue_quest_project, save_proof_quest, find_files_answer
 from forms.edit_profile import EditProfileForm
 from forms.login import LoginForm
 from forms.find_project import FindProjectForm
@@ -24,6 +24,8 @@ from forms.task import NewTask, AnswerTask
 
 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
@@ -50,7 +52,35 @@ def base():
         return redirect('/projects')
 
 
-@app.route('/project/<int:id_project>/quest/<int:id_task>')
+@app.route('/project/<int:id_project>/file/<int:id_file>/delete')
+def delete_file(id_project, id_file):
+    if current_user.is_authenticated:
+        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:
+                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()
+                    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/<int:id_project>/quest/<int:id_task>', methods=['GET', 'POST'])
 def task_project(id_project, id_task):
     if current_user.is_authenticated:
         data_session = db_session.create_session()
@@ -58,15 +88,75 @@ def task_project(id_project, id_task):
         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:
             form = AnswerTask()
-            return render_template('decision.html', title='Решение', project=current_project, task=current_task,
-                                   form=form)
+            current_answer = data_session.query(Answer).filter(Answer.quest == current_task.id).first()
+            list_files = None
+            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.deadline = deadline
+                if current_answer:
+                    current_answer.text = form.text.data if form.text.data else None
+                    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 if form.text.data else None,
+                        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(
+                                proof=current_answer.id,
+                                file=i
+                            )
+                            data_session.add(proof_file)
+                    data_session.commit()
+                return redirect(f'/project/{current_project.id}')
+            if current_answer:
+                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))
+            if current_task.deadline and current_task.deadline:
+                form.deadline_date.data = current_task.deadline.date()
+                form.deadline_time.data = current_task.deadline.time()
+            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/<int:id_project>/task/new', methods=['GET', 'POST'])
+@app.route('/project/<int:id_project>/quest/new', methods=['GET', 'POST'])
 def new_task_project(id_project):
     if current_user.is_authenticated:
         data_session = db_session.create_session()
@@ -166,7 +256,11 @@ def project(id_project):
                     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(key=lambda x: (x.realized, x.deadline))
+                    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))
                 return render_template('project.html',
                                        project=current_project,

+ 0 - 0
static/app_files/all_projects/заглушка


+ 243 - 0
static/css/answer.css

@@ -0,0 +1,243 @@
+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 {
+    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;
+}
+.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;
+}
+.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: 100%;
+}
+.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;
+}

+ 0 - 124
static/css/decision.css

@@ -1,124 +0,0 @@
-.decision_page {
-    height: 90vw;
-    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;
-}
-.name_block {
-    margin-top: 3vw;
-    width: 90%;
-    height: 25vw;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-}
-.title_block {
-    width: 90%;
-    display: flex;
-    justify-content: center;
-}
-.title_task {
-    text-align: center;
-    color: #000000;
-    font-size: 4vw;
-}
-.description_task {
-    width: 80%;
-    background-color: #EDCBB0;
-    height: auto;
-    max-height: 15vw;
-    border-radius: 2vw;
-    display: flex;
-    overflow-y: auto;
-}
-.description {
-    margin: 15px;
-}
-.description_text {
-    font-size: 1.5vw;
-    text-align: justify;
-}
-.data_block {
-    width: 90%;
-    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;
-}
-.text_data {
-    border-radius: 2vw !important;
-    width: 35vw;
-}
-.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;
-}

+ 2 - 1
static/js/project.js

@@ -2,6 +2,7 @@ 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");
+
 edit_button.href = String(window.location.href) + '/edit';
-new_task_link.href = String(window.location.href) + '/task/new';
+new_task_link.href = String(window.location.href) + '/quest/new';
 quest_solve_link.href = String(window.location.href) + '/quest/' + quest_solve_link_id.className;

+ 94 - 0
templates/answer.html

@@ -0,0 +1,94 @@
+<link rel="stylesheet" href="../../../static/css/answer.css"/>
+{% extends "base.html" %} {% block content %}
+<div class="decision_page">
+    <div class="link_back_block">
+        <a class="link_back" href="../../../project/{{ project.id }}">
+            <p class="link_back_text">К проекту</p>
+        </a>
+    </div>
+    <div class="name_block">
+        <div class="title_block">
+            <h3 class="title_task">{{ task.name }}</h3>
+        </div>
+        <div class="description_task">
+            <div class="description">
+                <p class="description_text">{{ task.description }}</p>
+            </div>
+        </div>
+        {% if list_files %}
+        <div class="files">
+            <h2 class="files_title">Файлы</h2>
+            <div class="files_block">
+                <div class="files_list">
+                    {% for file in list_files %}
+                    <div class="file">
+                        <div class="file_head">
+                            <nav class="file_head_group" style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
+                                <ol class="breadcrumb file_head_path">
+                                    {% for path in file['current_path'] %}
+                                    <li class="breadcrumb-item active file_path" aria-current="page">{{ path }}</li>
+                                    {% endfor %}
+                                </ol>
+                            </nav>
+                        </div>
+                        <div class="file_buttons">
+                            <div class="btn-group file_buttons_groud">
+                                {% if current_user.id == project.creator or task.creator == current_user.id or file.user == current_user.id %}
+                                <a href="../file/{{ file.id }}/delete" class="btn btn-primary file_delete"><p class="button_text">Удалить</p></a>
+                                {% endif %}
+                                <a href="../../../{{ file['path'] }}" download="" class="btn btn-primary file_download"><p class="button_text">Скачать</p></a>
+                            </div>
+                        </div>
+                    </div>
+                    {% endfor %}
+                </div>
+            </div>
+        </div>
+        {% endif %}
+        <div class="form_data bottom_data form_text_one">
+            <label class="form_label">{{ form.text.label }}</label>
+            {{ form.text(class="input_data text_data", type="text", id="text_data", placeholder='your answer') }}
+            {% for error in form.text.errors %}
+            <div class="alert alert-danger" role="alert">{{ error }}</div>
+            {% endfor %}
+        </div>
+    </div>
+    <div class="decision_block">
+        <form action="" method="post" class="answer_form" enctype="multipart/form-data">
+            {{ form.hidden_tag() }}
+            <div class="data_block">
+                <div class="form_data bottom_data">
+                    <label class="form_label">{{ form.file.label }}</label>
+                    {{ form.file(class="input_data padding_data", type="file") }}
+                    {% for error in form.file.errors %}
+                    <div class="alert alert-danger" role="alert">{{ error }}</div>
+                    {% endfor %}
+                </div>
+            </div>
+            {% if current_user.id == project.creator %}
+            <div class="form_data">
+                <label class="form_label">{{ form.deadline_date.label }}</label>
+                {{ form.deadline_date(class="input_data deadline padding_data", type="date") }}
+                {% for error in form.deadline_date.errors %}
+                <div class="alert alert-danger" role="alert">{{ error }}</div>
+                {% endfor %}
+                {{ form.deadline_time(class="input_data deadline padding_data", type="time") }}
+                {% for error in form.deadline_time.errors %}
+                <div class="alert alert-danger" role="alert">{{ error }}</div>
+                {% endfor %}
+            </div>
+            {% endif %}
+            <div class="form_data_button">
+                {{ form.submit(type="submit", class="quest_button") }}
+                <div class="box">
+                    {{ form.realized(class="realized")}}
+                    {{form.realized.label }}<br/>
+                    {% for error in form.realized.errors %}
+                    <div class="alert alert-danger" role="alert">{{ error }}</div>
+                    {% endfor %}
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+{% endblock %}

+ 0 - 41
templates/decision.html

@@ -1,41 +0,0 @@
-<link rel="stylesheet" href="../../../static/css/decision.css"/>
-{% extends "base.html" %} {% block content %}
-<div class="decision_page">
-    <div class="link_back_block">
-        <a class="link_back" href="../../../project/{{ project.id }}">
-            <p class="link_back_text">К проекту</p>
-        </a>
-    </div>
-    <div class="name_block">
-        <div class="title_block">
-            <h3 class="title_task">{{ task.name }}</h3>
-        </div>
-        <div class="description_task">
-            <div class="description">
-                <p class="description_text">{{ task.description }}</p>
-            </div>
-        </div>
-    </div>
-    <div class="decision_block">
-        <form action="" method="post" class="answer_form" enctype="multipart/form-data">
-            {{ form.hidden_tag() }}
-            <div class="data_block">
-                <div class="form_data bottom_data">
-                    <label class="form_label">{{ form.text.label }}</label>
-                    {{ form.text(class="input_data label_data text_data", type="text", placeholder='your answer') }}
-                    {% for error in form.text.errors %}
-                    <div class="alert alert-danger" role="alert">{{ error }}</div>
-                    {% endfor %}
-                </div>
-                <div class="form_data bottom_data">
-                    <label class="form_label">{{ form.file.label }}</label>
-                    {{ form.file(class="input_data padding_data", type="file") }}
-                    {% for error in form.file.errors %}
-                    <div class="alert alert-danger" role="alert">{{ error }}</div>
-                    {% endfor %}
-                </div>
-            </div>
-        </form>
-    </div>
-</div>
-{% endblock %}

+ 1 - 2
templates/login.html

@@ -32,8 +32,7 @@
                     </div>
                 </div>
                 <div class="box">
-                    {{ form.remember_me(class="remember")}} {{
-                    form.remember_me.label }}<br/>
+                    {{ form.remember_me(class="remember")}} {{form.remember_me.label }}<br/>
                     {% for error in form.remember_me.errors %}
                     <div class="alert alert-danger" role="alert">{{ error }}</div>
                     {% endfor %}

+ 18 - 3
templates/project.html

@@ -72,6 +72,10 @@
                                     <div class="deadline_block alert alert-success" role="alert">
                                         {{ quest.time_left }}
                                     </div>
+                                    {% elif quest.overdue == '' and quest.realized != 1 %}
+                                    <div class="deadline_block alert alert-warning" role="alert">
+                                        Дедлайна нет
+                                    </div>
                                     {% else %}
                                     <div class="deadline_block alert alert-success" role="alert">
                                         Задача выполнена
@@ -92,14 +96,25 @@
                                             </div>
                                         </div>
                                         <div class="quest_solve_button">
-                                            <a class="quest_solve_link" id="quest_solve_link">
-                                                <p id="quest_solve_link_id" class="{{ quest.id }}"></p>
+                                            <a class="quest_solve_link" href="{{ project.id }}/quest/{{ quest.id }}">
                                                 <p class="quest_solve_text">Решить</p>
                                             </a>
                                         </div>
                                     </div>
                                     {% else %}
-
+                                    <div class="quest_body">
+                                        <div class="quest_description_block">
+                                            <p class="quest_description_title">Описание</p>
+                                            <div class="quest_description">
+                                                <p class="quest_description_text">{{ quest.description }}</p>
+                                            </div>
+                                        </div>
+                                        <div class="quest_solve_button">
+                                            <a class="quest_solve_link" href="{{ project.id }}/quest/{{ quest.id }}">
+                                                <p class="quest_solve_text">Посмотреть</p>
+                                            </a>
+                                        </div>
+                                    </div>
                                     {% endif %}
                                 </div>
                             </div>