Изменена страница списка проектов, создан шаблон страницы создания нового проекта, изменены таблицы в базе данных
This commit is contained in:
parent
afca8cf50c
commit
709d2f971d
@ -11,7 +11,7 @@ class Projects(SqlAlchemyBase, UserMixin):
|
|||||||
id = sqlalchemy.Column(sqlalchemy.Integer,
|
id = sqlalchemy.Column(sqlalchemy.Integer,
|
||||||
primary_key=True, autoincrement=True)
|
primary_key=True, autoincrement=True)
|
||||||
name = sqlalchemy.Column(sqlalchemy.String, nullable=False)
|
name = sqlalchemy.Column(sqlalchemy.String, nullable=False)
|
||||||
about = sqlalchemy.Column(sqlalchemy.String, nullable=True)
|
description = sqlalchemy.Column(sqlalchemy.String, nullable=True)
|
||||||
photo = sqlalchemy.Column(sqlalchemy.Text)
|
photo = sqlalchemy.Column(sqlalchemy.Text)
|
||||||
date_create = sqlalchemy.Column(sqlalchemy.Date,
|
date_create = sqlalchemy.Column(sqlalchemy.Date,
|
||||||
default=date.today())
|
default=date.today())
|
||||||
|
|||||||
@ -11,6 +11,8 @@ class StaffProjects(SqlAlchemyBase, UserMixin):
|
|||||||
primary_key=True, autoincrement=True)
|
primary_key=True, autoincrement=True)
|
||||||
user = sqlalchemy.Column(sqlalchemy.Integer,
|
user = sqlalchemy.Column(sqlalchemy.Integer,
|
||||||
sqlalchemy.ForeignKey("users.id"), nullable=True, default=None)
|
sqlalchemy.ForeignKey("users.id"), nullable=True, default=None)
|
||||||
|
project = sqlalchemy.Column(sqlalchemy.Integer,
|
||||||
|
sqlalchemy.ForeignKey("projects.id"), nullable=True, default=None)
|
||||||
role = sqlalchemy.Column(sqlalchemy.Text)
|
role = sqlalchemy.Column(sqlalchemy.Text)
|
||||||
permission = sqlalchemy.Column(sqlalchemy.Integer,
|
permission = sqlalchemy.Column(sqlalchemy.Integer,
|
||||||
sqlalchemy.ForeignKey("roles.id"), nullable=True, default=None)
|
sqlalchemy.ForeignKey("roles.id"), nullable=True, default=None)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ from wtforms.validators import DataRequired
|
|||||||
class EditProfileForm(FlaskForm):
|
class EditProfileForm(FlaskForm):
|
||||||
email = EmailField('Почта', validators=[DataRequired()])
|
email = EmailField('Почта', validators=[DataRequired()])
|
||||||
name = StringField('Имя', validators=[DataRequired()])
|
name = StringField('Имя', validators=[DataRequired()])
|
||||||
surname = StringField('Фамилия', )
|
surname = StringField('Фамилия')
|
||||||
about = TextAreaField('Расскажите о себе', default='')
|
about = TextAreaField('Расскажите о себе', default='')
|
||||||
birthday = DateField('Дата рождения')
|
birthday = DateField('Дата рождения')
|
||||||
photo = FileField('Фото', validators=[FileAllowed(['jpg', 'png', 'bmp'], 'Только фотографии!')])
|
photo = FileField('Фото', validators=[FileAllowed(['jpg', 'png', 'bmp'], 'Только фотографии!')])
|
||||||
|
|||||||
10
forms/new_project.py
Normal file
10
forms/new_project.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, SubmitField, TextAreaField, FileField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
|
||||||
|
class NewProjectForm(FlaskForm):
|
||||||
|
name = StringField('Название', validators=[DataRequired()])
|
||||||
|
description = TextAreaField('Описание')
|
||||||
|
logo = FileField('Логотип')
|
||||||
|
submit = SubmitField('Регистрация')
|
||||||
@ -1,5 +1,4 @@
|
|||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from flask_wtf.file import FileAllowed
|
|
||||||
from wtforms import EmailField, StringField, PasswordField, SubmitField
|
from wtforms import EmailField, StringField, PasswordField, SubmitField
|
||||||
from wtforms.validators import DataRequired
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
|||||||
27
functions.py
27
functions.py
@ -1,6 +1,8 @@
|
|||||||
import smtplib
|
import smtplib
|
||||||
from email.message import EmailMessage
|
from email.message import EmailMessage
|
||||||
from data.roles import Roles
|
from data.roles import Roles
|
||||||
|
from data.users import User
|
||||||
|
from data.staff_projects import StaffProjects
|
||||||
from data import db_session
|
from data import db_session
|
||||||
|
|
||||||
|
|
||||||
@ -50,3 +52,28 @@ def init_db_default():
|
|||||||
data_session.add(role)
|
data_session.add(role)
|
||||||
data_session.commit()
|
data_session.commit()
|
||||||
data_session.close()
|
data_session.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_data(user):
|
||||||
|
resp = {
|
||||||
|
'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()
|
||||||
|
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_(*data_session.query(StaffProjects.user).filter(StaffProjects.id == project.id).all())).all()))
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
|||||||
30
main.py
30
main.py
@ -1,18 +1,24 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
|
import pprint
|
||||||
|
|
||||||
from flask import Flask, render_template, request, url_for
|
from flask import Flask, render_template, request, url_for
|
||||||
from flask_login import login_user, current_user, LoginManager, logout_user, login_required
|
from flask_login import login_user, current_user, LoginManager, logout_user, login_required
|
||||||
from werkzeug.datastructures import CombinedMultiDict
|
from werkzeug.datastructures import CombinedMultiDict
|
||||||
from werkzeug.utils import redirect
|
from werkzeug.utils import redirect
|
||||||
from itsdangerous import URLSafeTimedSerializer, SignatureExpired
|
from itsdangerous import URLSafeTimedSerializer, SignatureExpired
|
||||||
|
from sqlalchemy import or_
|
||||||
|
|
||||||
from functions import check_password, mail, init_db_default
|
from functions import check_password, mail, init_db_default, get_projects_data
|
||||||
from forms.edit_profile import EditProfileForm
|
from forms.edit_profile import EditProfileForm
|
||||||
from forms.login import LoginForm
|
from forms.login import LoginForm
|
||||||
from forms.register import RegisterForm
|
from forms.register import RegisterForm
|
||||||
|
from forms.new_project import NewProjectForm
|
||||||
|
|
||||||
from data.users import User
|
from data.users import User
|
||||||
from data.files import Files
|
from data.files import Files
|
||||||
|
from data.projects import Projects
|
||||||
|
from data.staff_projects import StaffProjects
|
||||||
from waitress import serve
|
from waitress import serve
|
||||||
from data import db_session
|
from data import db_session
|
||||||
|
|
||||||
@ -32,12 +38,30 @@ def base():
|
|||||||
return redirect('/projects')
|
return redirect('/projects')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/projects/new', methods=['GET', 'POST'])
|
||||||
|
def new_project():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
form = NewProjectForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
pass
|
||||||
|
return render_template('new_project.html', title='Новый проект', form=form)
|
||||||
|
else:
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/projects', methods=['GET', 'POST'])
|
@app.route('/projects', methods=['GET', 'POST'])
|
||||||
def project():
|
def project():
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
|
data_session = db_session.create_session()
|
||||||
|
resp = []
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
print(request.form.to_dict())
|
pass
|
||||||
return render_template('projects.html', title='Проекты')
|
else:
|
||||||
|
projects = data_session.query(Projects).filter(or_(Projects.creator == current_user.id, current_user.id in
|
||||||
|
data_session.query(StaffProjects.project).filter(
|
||||||
|
StaffProjects.user == current_user.id).all())).all()
|
||||||
|
resp = list(map(lambda x: get_projects_data(x), projects))
|
||||||
|
return render_template('projects.html', title='Проекты', list_projects=resp)
|
||||||
else:
|
else:
|
||||||
return redirect('/login')
|
return redirect('/login')
|
||||||
|
|
||||||
|
|||||||
38
static/css/new_project.css
Normal file
38
static/css/new_project.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.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: 10vw;
|
||||||
|
height: 5vw;
|
||||||
|
border-radius: 5vw;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.form_label {
|
||||||
|
font-size: 1.3vw;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
@ -51,7 +51,6 @@ form {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-left: 2%;
|
margin-left: 2%;
|
||||||
margin-left: 2%;
|
|
||||||
}
|
}
|
||||||
.form_data_button {
|
.form_data_button {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -64,4 +64,201 @@
|
|||||||
margin-left: 2.5%;
|
margin-left: 2.5%;
|
||||||
height: 95%;
|
height: 95%;
|
||||||
margin-top: 2.5%;
|
margin-top: 2.5%;
|
||||||
|
overflow-y: auto;
|
||||||
|
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:2px 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;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
.new_project_button {
|
||||||
|
width: 13vw;
|
||||||
|
height: 5vw;
|
||||||
|
background-color: #000000;
|
||||||
|
border: 2px solid #ffffff;
|
||||||
|
border-radius: 3vw;
|
||||||
|
margin-left: 2vw;
|
||||||
|
}
|
||||||
|
.new_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 {
|
||||||
|
width: 13vw;
|
||||||
|
height: 5vw;
|
||||||
|
}
|
||||||
|
.new_project_button_link:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
.form_project_block {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
BIN
static/images/none_project.png
Normal file
BIN
static/images/none_project.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
45
templates/new_project.html
Normal file
45
templates/new_project.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<link rel="stylesheet" href="../static/css/new_project.css"/>
|
||||||
|
{% extends "base.html" %} {% block content %}
|
||||||
|
<div class="new_project_page">
|
||||||
|
<div class="form_block">
|
||||||
|
<form action="" method="post" class="register_form" enctype="multipart/form-data">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<div class="name_form_block">
|
||||||
|
<div class="form_data">
|
||||||
|
<label class="form_label">{{ form.name.label }}</label>
|
||||||
|
{{ form.name(class="input_data", type="name", placeholder='your project name') }}
|
||||||
|
{% for error in form.name.errors %}
|
||||||
|
<div class="alert alert-danger" role="alert">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="form_data">
|
||||||
|
<label class="form_label">{{ form.description.label }}</label>
|
||||||
|
{{ form.description(class="input_data", type="description", placeholder='your project description') }}
|
||||||
|
{% for error in form.description.errors %}
|
||||||
|
<div class="alert alert-danger" role="alert">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="data_form_block">
|
||||||
|
<div class="staff_form_block">
|
||||||
|
<div class="staff_list">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="buttons_form_block">
|
||||||
|
<div class="form_data">
|
||||||
|
<label class="form_label">{{ form.logo.label }}</label>
|
||||||
|
{{ form.logo(class="input_data file_data", type="file") }}
|
||||||
|
{% for error in form.logo.errors %}
|
||||||
|
<div class="alert alert-danger" role="alert">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="form_data_button">
|
||||||
|
{{ form.submit(type="submit", class="project_button") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -5,7 +5,8 @@
|
|||||||
<div class="open_button_content">
|
<div class="open_button_content">
|
||||||
<h2 class="open_button_title">Профиль</h2>
|
<h2 class="open_button_title">Профиль</h2>
|
||||||
<p class="open_button_article">Здесь можно поменять настройки учетной записи</p>
|
<p class="open_button_article">Здесь можно поменять настройки учетной записи</p>
|
||||||
<a class="open_button" data-bs-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
|
<a class="open_button" data-bs-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false"
|
||||||
|
aria-controls="collapseExample">
|
||||||
<div class="open_button_text">
|
<div class="open_button_text">
|
||||||
Редикторовать
|
Редикторовать
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,34 +7,67 @@
|
|||||||
добавлять участников в своей проект.</strong>
|
добавлять участников в своей проект.</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="find_block">
|
<div class="find_block">
|
||||||
<form action="" method="post">
|
<form action="" method="post" class="form_project_block">
|
||||||
<input class="find_input_text" type="text" placeholder="Имя проекта" name="find_text">
|
<input class="find_input_text" type="text" placeholder="Имя проекта" name="find_text">
|
||||||
<button class="find_input_button">Поиск</button>
|
<button class="find_input_button">Поиск</button>
|
||||||
|
<div class="new_project_button">
|
||||||
|
<a class="new_project_button_link" href="/projects/new">
|
||||||
|
<p class="new_project_button_text">Создать</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="list_project_block">
|
<div class="list_project_block">
|
||||||
|
{% for project in list_projects %}
|
||||||
<div class="accordion list_project" id="accordionPanelsStayOpenExample">
|
<div class="accordion list_project" id="accordionPanelsStayOpenExample">
|
||||||
<div class="accordion-item project">
|
<div class="accordion-item project">
|
||||||
<h2 class="accordion-header project_header" id="panelsStayOpen-headingOne">
|
<h2 class="accordion-header project_header" id="panelsStayOpen-headingOne">
|
||||||
<button class="accordion-button priject_header_button" type="button" data-bs-toggle="collapse"
|
<button class="accordion-button project_header_button" type="button" data-bs-toggle="collapse"
|
||||||
data-bs-target="#panelsStayOpen-collapseOne" aria-expanded="true"
|
data-bs-target="#panelsStayOpen-collapseOne" aria-expanded="true"
|
||||||
aria-controls="panelsStayOpen-collapseOne">
|
aria-controls="panelsStayOpen-collapseOne">
|
||||||
Project 1
|
<div class="project_button_block_one">
|
||||||
|
<div class="project_logo_block">
|
||||||
|
<img src="{{ project.logo }}" class="project_logo">
|
||||||
|
</div>
|
||||||
|
<div class="project_title_block">
|
||||||
|
<p class="project_title">{{ project.name }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse"
|
<div id="panelsStayOpen-collapseOne" class="accordion-collapse collapse project_description_block"
|
||||||
aria-labelledby="panelsStayOpen-headingOne">
|
aria-labelledby="panelsStayOpen-headingOne">
|
||||||
<div class="accordion-body">
|
<div class="accordion-body project_description">
|
||||||
<strong>This is the first item's accordion body.</strong> It is shown by default, until the
|
<div class="collaborator_block">
|
||||||
collapse plugin adds the appropriate classes that we use to style each element. These classes
|
<div class="staff_block">
|
||||||
control the overall appearance, as well as the showing and hiding via CSS transitions. You can
|
{% for user in project.staff %}
|
||||||
modify any of this with custom CSS or overriding our default variables. It's also worth noting
|
<div class="user">
|
||||||
that just about any HTML can go within the <code>.accordion-body</code>, though the transition
|
<img class="user_logo" src="{{user.photo}}">
|
||||||
does limit overflow.
|
<p class="user_names">{{user.name}}</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="description_block">
|
||||||
|
<div class="description_header_block">
|
||||||
|
<p class="description_header_text">Описание</p>
|
||||||
|
</div>
|
||||||
|
<div class="description_block_text">
|
||||||
|
<p class="description_text">{{ project.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="open_project_block">
|
||||||
|
<div class="open_button">
|
||||||
|
<a class="open_button_link" href="/projects/{{ project.id }}">
|
||||||
|
<p class="open_button_text">Открыть</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user