Compare commits
14 Commits
0d93a37a5c
...
f5f1fa721b
Author | SHA1 | Date | |
---|---|---|---|
f5f1fa721b | |||
3ab1c58c14 | |||
66ef5e9e25 | |||
14343422d3 | |||
9d02b2529a | |||
dfc925d5c2 | |||
5f95d59f2e | |||
5c76f8f9be | |||
abf12212f5 | |||
3e1fa025cc | |||
674c8741e7 | |||
5ecfe3b836 | |||
b21a9c71a1 | |||
4592591c4e |
@ -1,6 +1,7 @@
|
||||
from flask import render_template, Blueprint
|
||||
from flask import render_template, Blueprint, flash, redirect
|
||||
from flask_login import current_user, login_required
|
||||
from aula.models import get_group
|
||||
from aula.models import get_group, insert_group, group_exist
|
||||
from aula.forms import CreateThreadForm, CreateGroupForm, CreatePostForm
|
||||
|
||||
Group = Blueprint('Group', __name__)
|
||||
|
||||
@ -8,15 +9,50 @@ Group = Blueprint('Group', __name__)
|
||||
@login_required
|
||||
def groups():
|
||||
groups = current_user.get_groups_joinable()
|
||||
return render_template('groups.html', groups=groups)
|
||||
form = CreateGroupForm()
|
||||
return render_template('groups.html', groups=groups, form=form)
|
||||
|
||||
@Group.route("/group/<int:group_id>", methods=['GET'])
|
||||
@Group.route("/groups/<int:group_id>", methods=['GET'])
|
||||
@login_required
|
||||
def show(group_id):
|
||||
group = get_group(group_id)
|
||||
posts = group.get_posts()
|
||||
threads = group.get_threads()
|
||||
form = CreateThreadForm()
|
||||
formpost = CreatePostForm()
|
||||
if (group is not None):
|
||||
return render_template('group_show.html', group=group, posts=posts)
|
||||
return render_template('group_show.html', group=group, posts=posts, threads=threads, form=form, formpost=formpost)
|
||||
else:
|
||||
return f"Der findes ikke en gruppe med id {group_id}."
|
||||
|
||||
@Group.route("/groups/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreateGroupForm()
|
||||
|
||||
# Make sure we dont try to create group with same name as others
|
||||
# Since name has UNIQUE constraint.
|
||||
if group_exist(form.title.data):
|
||||
flash('En gruppe med det navn findes allerede', 'danger')
|
||||
return redirect(f"/groups")
|
||||
|
||||
group = insert_group(form.title.data, form.mandatory.data)
|
||||
current_user.join_group(group.group_id)
|
||||
flash('Gruppen blev oprettet', 'success')
|
||||
return redirect(f"/groups")
|
||||
|
||||
@Group.route("/groups/join/<int:group_id>", methods=['GET'])
|
||||
def join(group_id):
|
||||
group = get_group(group_id)
|
||||
|
||||
current_user.join_group(group_id)
|
||||
flash(f'Du er nu tilmeldt {group.name} gruppen', 'success')
|
||||
return redirect(f"/groups/{group_id}")
|
||||
|
||||
@Group.route("/groups/leave/<int:group_id>", methods=['GET'])
|
||||
def leave(group_id):
|
||||
group = get_group(group_id)
|
||||
|
||||
current_user.leave_group(group_id)
|
||||
flash(f'Du er frameldt {group.name} gruppen', 'success')
|
||||
return redirect(f"/groups")
|
14
aula/Post/routes.py
Normal file
14
aula/Post/routes.py
Normal file
@ -0,0 +1,14 @@
|
||||
from flask import render_template, Blueprint, flash, redirect
|
||||
from flask_login import current_user, login_required
|
||||
from aula.models import insert_post
|
||||
from aula.forms import CreatePostForm
|
||||
|
||||
Post = Blueprint('Post', __name__)
|
||||
|
||||
@Post.route("/posts/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreatePostForm()
|
||||
insert_post(form.group_id.data, form.author_id.data, form.title.data, form.content.data)
|
||||
flash('Opslag blev oprettet', 'success')
|
||||
return redirect(f"/groups/{form.group_id.data}")
|
@ -1,7 +1,7 @@
|
||||
from flask import redirect, render_template, Blueprint
|
||||
from flask import redirect, render_template, Blueprint, flash
|
||||
from flask_login import login_required, current_user
|
||||
from aula.models import get_thread, insert_message
|
||||
from aula.forms import SendMessageForm
|
||||
from aula.models import get_thread, insert_message, insert_thread
|
||||
from aula.forms import SendMessageForm, CreateThreadForm
|
||||
|
||||
Threads = Blueprint('Threads', __name__)
|
||||
|
||||
@ -17,7 +17,7 @@ def show(thread_id):
|
||||
thread = get_thread(thread_id)
|
||||
if thread is None:
|
||||
return f"Der findes ikke en tråd med id {thread_id}."
|
||||
elif not current_user.in_thread(thread_id):
|
||||
elif not current_user.is_member_of_group(thread.group_id):
|
||||
return f"Du har ikke adgang til tråden med id {thread_id}."
|
||||
else:
|
||||
form = SendMessageForm()
|
||||
@ -27,3 +27,12 @@ def show(thread_id):
|
||||
return redirect(f"/threads/{thread_id}")
|
||||
|
||||
return render_template("thread_show.html", thread=thread, messages=thread.get_messages(), form=form)
|
||||
|
||||
@Threads.route("/threads/create", methods=['POST'])
|
||||
@login_required
|
||||
def create():
|
||||
form = CreateThreadForm()
|
||||
insert_thread(form.group_id.data, form.title.data)
|
||||
flash('Tråden blev oprettet', 'success')
|
||||
return redirect(f"/groups/{form.group_id.data}")
|
||||
|
||||
|
@ -17,9 +17,11 @@ login_manager.login_message_category = 'info'
|
||||
from aula.Login.routes import Login
|
||||
from aula.Group.routes import Group
|
||||
from aula.Threads.routes import Threads
|
||||
from aula.Post.routes import Post
|
||||
|
||||
app.register_blueprint(Login)
|
||||
app.register_blueprint(Group)
|
||||
app.register_blueprint(Threads)
|
||||
app.register_blueprint(Post)
|
||||
|
||||
#from bank import routes
|
||||
|
@ -1,5 +1,5 @@
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, PasswordField, SubmitField, BooleanField
|
||||
from wtforms import StringField, PasswordField, SubmitField, BooleanField, HiddenField
|
||||
from wtforms.validators import DataRequired, Length
|
||||
|
||||
class AddUserForm(FlaskForm):
|
||||
@ -19,3 +19,21 @@ class UserLoginForm(FlaskForm):
|
||||
class SendMessageForm(FlaskForm):
|
||||
besked = StringField('Besked', validators=[DataRequired()])
|
||||
submit = SubmitField('Send')
|
||||
|
||||
class CreateThreadForm(FlaskForm):
|
||||
group_id = HiddenField('GroupID', validators=[DataRequired()])
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
submit = SubmitField()
|
||||
|
||||
class CreateGroupForm(FlaskForm):
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
mandatory = BooleanField('Obligatorisk gruppe')
|
||||
submit = SubmitField("Opret gruppe")
|
||||
|
||||
class CreatePostForm(FlaskForm):
|
||||
title = StringField('Title', validators=[DataRequired()])
|
||||
content = StringField('Indhold', validators=[DataRequired()])
|
||||
author_id = HiddenField('AuthorID', validators=[DataRequired()])
|
||||
group_id = HiddenField('GroupID', validators=[DataRequired()])
|
||||
submit = SubmitField("Opret opslag")
|
||||
|
||||
|
160
aula/models.py
160
aula/models.py
@ -25,14 +25,17 @@ class Group(tuple):
|
||||
def __init__(self, group_data):
|
||||
self.group_id = group_data[0]
|
||||
self.name = group_data[1]
|
||||
self.hidden = group_data[2]
|
||||
self.mandatory = group_data[2]
|
||||
super().__init__()
|
||||
|
||||
def get_posts(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM posts
|
||||
WHERE group_id = %s
|
||||
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.user_id, u.first_name, u.last_name, u.email, u.address, u.role FROM posts as p
|
||||
INNER JOIN groups g on g.group_id = p.group_id
|
||||
INNER JOIN users u on u.user_id = p.author_id
|
||||
WHERE p.group_id = %s
|
||||
ORDER BY created_date DESC;
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
Posts = cur.fetchall()
|
||||
@ -45,7 +48,8 @@ class Group(tuple):
|
||||
def get_threads(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM threads
|
||||
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
|
||||
INNER JOIN groups g on g.group_id = threads.group_id
|
||||
WHERE threads.group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
@ -61,20 +65,15 @@ class Message(tuple):
|
||||
self.message_id = message_data[0]
|
||||
self.content = message_data[1]
|
||||
self.thread_id = message_data[2]
|
||||
self.author_id = message_data[3]
|
||||
self.author = None
|
||||
self._created_date = message_data[4]
|
||||
self._get_author()
|
||||
self._created_date = message_data[3]
|
||||
self.author = {
|
||||
"user_id": message_data[4],
|
||||
"first_name": message_data[5],
|
||||
"last_name": message_data[6],
|
||||
"role": message_data[7],
|
||||
}
|
||||
super().__init__()
|
||||
|
||||
def _get_author(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users WHERE user_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.author_id,))
|
||||
self.author = User(cur.fetchone())
|
||||
|
||||
@property
|
||||
def created_date(self):
|
||||
now = datetime.now()
|
||||
@ -101,46 +100,44 @@ class Message(tuple):
|
||||
class Post(tuple):
|
||||
def __init__(self, post_data):
|
||||
self.post_id = post_data[0]
|
||||
self.group_id = post_data[1]
|
||||
self.group = None
|
||||
self.author_id = post_data[2]
|
||||
self.author = None
|
||||
self.title = post_data[3]
|
||||
self.content = post_data[4]
|
||||
self.created_date = post_data[5]
|
||||
self._get_group()
|
||||
self._get_author()
|
||||
self.title = post_data[1]
|
||||
self.content = post_data[2]
|
||||
self.created_date = post_data[3]
|
||||
self.group = {
|
||||
'group_id': post_data[4],
|
||||
'name': post_data[5],
|
||||
'mandatory': post_data[6],
|
||||
}
|
||||
self.author = {
|
||||
'user_id': post_data[7],
|
||||
'first_name': post_data[8],
|
||||
'last_name': post_data[9],
|
||||
'email': post_data[10],
|
||||
'address': post_data[11],
|
||||
'role': post_data[12],
|
||||
}
|
||||
super().__init__()
|
||||
|
||||
def _get_author(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM users WHERE user_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.author_id,))
|
||||
self.author = User(cur.fetchone())
|
||||
|
||||
def _get_group(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM groups WHERE group_id = %s
|
||||
"""
|
||||
cur.execute(sql_call, (self.group_id,))
|
||||
self.group = Group(cur.fetchone())
|
||||
|
||||
class Thread(tuple):
|
||||
def __init__(self, thread_data):
|
||||
self.thread_id = thread_data[0]
|
||||
self.title = thread_data[1]
|
||||
self.group = {
|
||||
"group_id": thread_data[2],
|
||||
"name": thread_data[3],
|
||||
"mandatory": thread_data[4]
|
||||
}
|
||||
self.group_id = thread_data[2]
|
||||
if len(thread_data) == 6:
|
||||
self.last_message_date = thread_data[5]
|
||||
super().__init__()
|
||||
|
||||
def get_messages(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM messages
|
||||
WHERE thread_id = %s
|
||||
ORDER BY created_date ASC
|
||||
SELECT message_id, content, thread_id, created_date ,u.user_id, u.first_name, u.last_name, u.role FROM messages
|
||||
INNER JOIN users u on u.user_id = messages.author_id
|
||||
WHERE messages.thread_id = %s;
|
||||
"""
|
||||
cur.execute(sql_call, (self.thread_id,))
|
||||
messages = cur.fetchall()
|
||||
@ -193,8 +190,8 @@ class User(tuple, UserMixin):
|
||||
sql_call = """
|
||||
SELECT groups.* FROM groups INNER JOIN users_groups ON groups.group_id = users_groups.group_id WHERE users_groups.user_id = %s
|
||||
UNION
|
||||
SELECT groups.* FROM groups WHERE groups.hidden = TRUE
|
||||
ORDER BY hidden ASC, name DESC
|
||||
SELECT groups.* FROM groups WHERE groups.mandatory = FALSE
|
||||
ORDER BY mandatory ASC, name DESC
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id,))
|
||||
groups = cur.fetchall()
|
||||
@ -226,11 +223,19 @@ class User(tuple, UserMixin):
|
||||
def get_threads(self):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM threads WHERE thread_id IN
|
||||
(
|
||||
SELECT thread_id FROM users_threads
|
||||
WHERE user_id = %s
|
||||
)
|
||||
SELECT threads.thread_id, title, g.group_id, g.name, g.mandatory, lm.last_message_date FROM threads
|
||||
INNER JOIN
|
||||
groups g
|
||||
ON g.group_id = threads.group_id
|
||||
LEFT JOIN
|
||||
(SELECT thread_id, MAX(created_date) as last_message_date FROM messages GROUP BY thread_id) lm
|
||||
ON threads.thread_id = lm.thread_id
|
||||
WHERE g.group_id IN
|
||||
(
|
||||
SELECT group_id FROM users_groups
|
||||
WHERE user_id = %s
|
||||
)
|
||||
ORDER BY last_message_date DESC NULLS LAST;
|
||||
"""
|
||||
cur.execute(sql_call, (self.user_id,))
|
||||
threads = cur.fetchall()
|
||||
@ -250,8 +255,6 @@ class User(tuple, UserMixin):
|
||||
cur.execute(sql_call, (self.user_id, thread_id))
|
||||
return cur.rowcount > 0
|
||||
|
||||
|
||||
|
||||
def insert_users(user_id, first_name, last_name, password, email, adresse, role):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
@ -288,11 +291,14 @@ def select_users_by_email(email):
|
||||
def get_posts_for_user(user_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
SELECT * FROM posts
|
||||
WHERE group_id in (
|
||||
SELECT group_id FROM users_groups
|
||||
SELECT post_id, title, content, created_date, g.group_id, g.name, g.mandatory, u.user_id, u.first_name, u.last_name, u.email, u.address, u.role FROM posts as p
|
||||
INNER JOIN groups g on g.group_id = p.group_id
|
||||
INNER JOIN users u on u.user_id = p.author_id
|
||||
WHERE g.group_id in (
|
||||
SELECT g.group_id FROM users_groups
|
||||
WHERE user_id = %s
|
||||
)
|
||||
ORDER BY created_date DESC
|
||||
"""
|
||||
cur.execute(sql_call, (user_id,))
|
||||
user = [Post(i) for i in cur.fetchmany(50)] if cur.rowcount > 0 else []
|
||||
@ -313,7 +319,8 @@ def get_group(group_id):
|
||||
def get_thread(thread_id):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT * FROM threads
|
||||
SELECT thread_id, title, g.group_id, g.name, g.mandatory FROM threads
|
||||
INNER JOIN groups g on g.group_id = threads.group_id
|
||||
WHERE thread_id = %s
|
||||
"""
|
||||
cur.execute(sql, (thread_id,))
|
||||
@ -321,6 +328,45 @@ def get_thread(thread_id):
|
||||
cur.close()
|
||||
return thread
|
||||
|
||||
def insert_thread(group_id, title):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO threads(group_id, title) VALUES (%s, %s)
|
||||
"""
|
||||
cur.execute(sql, (group_id, title))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def group_exist(name):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
SELECT COUNT(*) FROM groups WHERE name = %s
|
||||
"""
|
||||
cur.execute(sql, (name,))
|
||||
return cur.fetchone()[0] > 0
|
||||
|
||||
def insert_group(name, mandatory):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO groups(name, mandatory) VALUES (%s, %s) RETURNING *
|
||||
"""
|
||||
cur.execute(sql, (name, mandatory))
|
||||
|
||||
result = Group(cur.fetchone()) if cur.rowcount > 0 else None
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
return result
|
||||
|
||||
def insert_post(group_id, author_id, title, content):
|
||||
cur = conn.cursor()
|
||||
sql = """
|
||||
INSERT INTO posts(group_id, author_id, title, content) VALUES (%s, %s, %s, %s)
|
||||
"""
|
||||
cur.execute(sql, (group_id, author_id, title, content))
|
||||
conn.commit()
|
||||
cur.close()
|
||||
|
||||
def insert_message(content, thread_id, author_id):
|
||||
cur = conn.cursor()
|
||||
sql_call = """
|
||||
|
@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
group_id SERIAL PRIMARY KEY,
|
||||
name varchar(64) NOT NULL UNIQUE,
|
||||
hidden boolean DEFAULT TRUE
|
||||
mandatory boolean DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS threads (
|
||||
|
@ -8,7 +8,7 @@ INSERT INTO public.users(user_id, first_name, last_name, password, email, addres
|
||||
(5004,'Phoebe', 'Buffay', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'phoebe@test.dk', 'Central Perk', 'parent'),
|
||||
(5005,'Ross', 'Geller', '$2b$12$KFkp1IEMGT4QrWwjPGhE3ejOv6Z3pYhx/S4qOoFbanR2sMiZqgeJO', 'ross@test.dk', 'Central Perk', 'student');
|
||||
|
||||
INSERT INTO public.groups(group_id, name, hidden) VALUES
|
||||
INSERT INTO public.groups(group_id, name, mandatory) VALUES
|
||||
(1000, 'fodbold', TRUE),
|
||||
(1001,'3a', FALSE);
|
||||
|
||||
@ -19,8 +19,8 @@ INSERT INTO threads(thread_id ,title, group_id) VALUES
|
||||
|
||||
INSERT INTO messages (content, thread_id, author_id, created_date) VALUES
|
||||
('Eleverne har ondt i fødderne når de spiller fodbild. Hvem kender et godt skomærke?', 2000, 5000, NOW() - INTERVAL '3.189 day'),
|
||||
('Jeg tror min søn har nogle han er glad for. Jeg spørger ham lige 😀', 2000, 5002, NOW() - INTERVAL '2.951 day'),
|
||||
('Tak 👍', 2000, 5000, NOW() - INTERVAL '1.894 day'),
|
||||
('Jeg tror min søn har nogle han er glad for. Jeg spørger ham lige', 2000, 5002, NOW() - INTERVAL '2.951 day'),
|
||||
('Tak', 2000, 5000, NOW() - INTERVAL '1.894 day'),
|
||||
('Er det meningen vi skal give dem sko med????', 2000, 5001, NOW() - INTERVAL '1.05 hour'),
|
||||
('Rachel, giver du ikke dine børn sko med til fodbold?', 2000, 5002, NOW() - INTERVAL '0.95 hour'),
|
||||
('Hvad er der galt med dig?', 2000, 5003, NOW() - INTERVAL '0.94 hour'),
|
||||
|
@ -1,4 +1,78 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ current_user.name }}</h1>
|
||||
{% endblock content %}
|
||||
<h1>Bruger Information</h1>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Attribute</th>
|
||||
<th scope="col">værdi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">user_id</th>
|
||||
<td>{{ current_user.user_id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">first_name</th>
|
||||
<td>{{ current_user.first_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">last_name</th>
|
||||
<td>{{ current_user.last_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">email</th>
|
||||
<td>{{ current_user.email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">address</th>
|
||||
<td>{{ current_user.address }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">role</th>
|
||||
<td>{{ current_user.role }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><b>Grupper</b></p>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">group_id</th>
|
||||
<th scope="col">name</th>
|
||||
<th scope="col">mandatory</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for group in current_user.get_groups() %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.group_id }}</a></td>
|
||||
<td>{{ group.name }}</td>
|
||||
<td>{{ group.mandatory }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><b>Tråde</b></p>
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">thread_id</th>
|
||||
<th scope="col">title</th>
|
||||
<th scope="col">group_id</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for thread in current_user.get_threads() %}
|
||||
<tr>
|
||||
<td><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.thread_id }}</a></td>
|
||||
<td>{{ thread.title }}</td>
|
||||
<td>{{ thread.group_id }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock content %}
|
@ -1,59 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Add a new customer</legend>
|
||||
<div class="form-group">
|
||||
{{ form.username.label(class="form-control-label") }}
|
||||
|
||||
{% if form.username.errors %}
|
||||
{{ form.username(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.username.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.username(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.CPR_number.label(class="form-control-label") }}
|
||||
{% if form.CPR_number.errors %}
|
||||
{{ form.CPR_number(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.CPR_number.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.CPR_number(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.password.label(class="form-control-label") }}
|
||||
{% if form.password.errors %}
|
||||
{{ form.password(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.password.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.password(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
{{ form.submit(class="btn btn-outline-info") }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="border-top pt-3">
|
||||
<small class="text-muted">
|
||||
Already Have An Account? <a class="ml-2" href="{{ url_for('Login.login') }}">Sign In</a>
|
||||
</small>
|
||||
</div>
|
||||
{% endblock content %}
|
@ -1,17 +1,74 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ group.name }}</h1>
|
||||
<h1>{{ group.name }}
|
||||
</h1>
|
||||
<hr>
|
||||
{% if posts|length == 0 %}
|
||||
<p>Gruppen har ingen opslag endnu</p>
|
||||
{% endif %}
|
||||
{% for post in posts %}
|
||||
<article class="media content-section">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
|
||||
<small class="text-muted">{{ post.date_posted }}</small>
|
||||
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }} </a>
|
||||
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
|
||||
</div>
|
||||
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
|
||||
<p class="article-content">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p style="font-weight: bold;">Skriv opslag</p>
|
||||
<form method="POST" action="{{ url_for('Post.create')}}">
|
||||
{{ formpost.group_id(value=group.group_id) }}
|
||||
{{ formpost.author_id(value=current_user.user_id) }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">{{ formpost.title(class="form-control", placeholder="Title") }}</div>
|
||||
<div class="col-md-8">{{ formpost.content(class="form-control", placeholder="Indhold") }}</div>
|
||||
<div class="col-md-12 mt-2">{{ formpost.submit(class="btn btn-primary btn-block btn-sm", value="Opret opslag") }}</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<p style="font-weight: bold;">Gruppe tråde</p>
|
||||
{% if threads|length == 0 %}
|
||||
<p>Gruppen har ingen tråde endnu</p>
|
||||
{% endif %}
|
||||
{% for thread in threads %}
|
||||
<p><a href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}">{{ thread.title }}</a></p>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<form method="POST" action="{{ url_for('Threads.create')}}">
|
||||
{{ form.group_id(value=group.group_id) }}
|
||||
<p>{{ form.title(class="form-control", placeholder="Trådens title") }}</p>
|
||||
<p>{{ form.submit(class="btn btn-primary btn-block", value="Start tråd") }}</p>
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
<p>Tilmeld dig gruppe for at se gruppe tråde og skrive opslag</p>
|
||||
<p><a class="btn btn-success btn-sm btn-block" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a></p>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<p>
|
||||
<hr>
|
||||
{% if group.mandatory %}
|
||||
<a class="btn btn-secondary btn-sm disabled" href="#">Obligatorisk gruppe</a>
|
||||
{% else %}
|
||||
<a class="btn btn-danger btn-sm btn-block" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Forlad gruppen</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock sidebar %}
|
||||
|
@ -1,14 +1,39 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>Grupper</h1>
|
||||
<hr>
|
||||
{% if groups|length == 0%}
|
||||
<p>Ikke medlem af nogle grupper</p>
|
||||
{% else %}
|
||||
{% for group in groups %}
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<p><a class="group-name" href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.name }}</a></p>
|
||||
<p>
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = group.group_id) }}">{{ group.name }}</a>
|
||||
{% if not group.mandatory %}
|
||||
{% if current_user.is_member_of_group(group.group_id) %}
|
||||
<a class="btn btn-danger btn-sm float-right" href="{{ url_for('Group.leave', group_id = group.group_id) }}">Afmeld</a>
|
||||
{% else %}
|
||||
<a class="btn btn-success btn-sm float-right" href="{{ url_for('Group.join', group_id = group.group_id) }}">Tilmeld</a>
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
<a class="btn btn-secondary btn-sm float-right" href="#" disabled>Obligatorisk</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
<p style="font-weight: bold;">Opret gruppe</p>
|
||||
<form method="POST" action="{{ url_for('Group.create')}}">
|
||||
<p>{{ form.title(class="form-control", placeholder="Gruppens navn") }}</p>
|
||||
|
||||
<p>{{ form.mandatory() }} {{ form.mandatory.label(class="form-check-label") }}</p>
|
||||
<p>{{ form.submit(class="btn btn-primary btn-block") }}</p>
|
||||
</form>
|
||||
{% endblock sidebar %}
|
||||
|
@ -9,11 +9,11 @@
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2 author-name" href="#">{{ post.author.first_name }} {{ post.author.last_name }}</a>
|
||||
<small class="text-muted">{{ post.date_posted }}</small>
|
||||
<small class="text-muted float-right">{{ post.created_date.strftime('%H:%M %d-%m-%Y')}}</small>
|
||||
</div>
|
||||
<h2><a class="article-title" href="#">{{ post.title }}</a></h2>
|
||||
<p class="article-content">{{ post.content }}</p>
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = post.group.group_id) }}"">
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = post.group.group_id) }}">
|
||||
{{ post.group.name }}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -1,79 +0,0 @@
|
||||
{% extends "layout_acc.html" %}
|
||||
{% block content %}
|
||||
<h1>{{ current_user.name }}</h1>
|
||||
|
||||
|
||||
<div class="content-section">
|
||||
<p>Investments:</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">account_number</th>
|
||||
<th scope="col">cpr_number</th>
|
||||
<th scope="col">creation date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for n in inv %}
|
||||
<tr>
|
||||
<th scope="row">{{n[0]}}</th>
|
||||
<td>{{n[1]}}</td>
|
||||
<td>{{n[2]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="content-section">
|
||||
<p>Investment accounts:</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">account_number</th>
|
||||
<th scope="col">cpr_number</th>
|
||||
<th scope="col">account created</th>
|
||||
<th scope="col">deposit total (CD)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for n in inv_sums %}
|
||||
<tr>
|
||||
<th scope="row">{{n[0]}}</th>
|
||||
<td>{{n[1]}}</td>
|
||||
<td>{{n[2]}}</td>
|
||||
<td>{{n[3]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="content-section">
|
||||
<p>Investment certificats of deposit:</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">acc</th>
|
||||
<th scope="col">cd_number</th>
|
||||
<th scope="col">start_date</th>
|
||||
<th scope="col">maturity_date</th>
|
||||
<th scope="col">rate</th>
|
||||
<th scope="col">amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for n in inv_cd_list %}
|
||||
<tr>
|
||||
<th scope="row">{{n[0]}}</th>
|
||||
<td>{{n[3]}}</td>
|
||||
<td>{{n[4]}}</td>
|
||||
<td>{{n[5]}}</td>
|
||||
<td>{{n[6]}}</td>
|
||||
<td>{{n[7]}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock content %}
|
@ -50,10 +50,21 @@
|
||||
<main role="main" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="content-section">
|
||||
{% block sidebar %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,100 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||
|
||||
{% if title %}
|
||||
<title>UIS Prototype - {{ title }}</title>
|
||||
{% else %}
|
||||
<title>UIS Prototype</title>
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand mr-4" href="/">UIS Prototype</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarToggle">
|
||||
<div class="navbar-nav mr-auto">
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.home') }}">Home</a>
|
||||
{% if current_user.is_authenticated %}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="nav-item nav-link dropdown-toggle" data-toggle="dropdown">UIS bank<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a></li>
|
||||
<li><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a class="nav-item nav-link" href="https://www.pgadmin.org">site pgAdmin</a></li>
|
||||
<li><a class="nav-item nav-link" href="http://127.0.0.1:58653/browser/ ">pgAdmin4</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.about') }}">About</a>
|
||||
</div>
|
||||
<!-- Navbar Right Side -->
|
||||
<div class="navbar-nav">
|
||||
{% if current_user.is_authenticated %}
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.account') }}">Account</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">Investments</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.logout') }}">Logout</a>
|
||||
{% else %}
|
||||
<a class="nav-item nav-link" href="{{ url_for('Login.login') }}">Login</a>
|
||||
<a class="nav-item nav-link" href="{{ url_for('Employee.addcustomer') }}">Register</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
<main role="main" class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="content-section">
|
||||
<h3>Account</h3>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Employee.transfer') }}">Transfer</a></li>
|
||||
<li class="list-group-item list-group-item-light">Checking Accounts</li>
|
||||
<li class="list-group-item list-group-item-light">Investment Accounts</li>
|
||||
<li class="list-group-item list-group-item-light"><a class="nav-item nav-link" href="{{ url_for('Customer.invest') }}">View investment accounts</a></li>
|
||||
<li class="list-group-item list-group-item-light">etc</li>
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,70 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<h1>Test Page</h1>
|
||||
<p>Dette er en testside. Hej med dig. <b>fed tekst,</b> <i>kursiv tekst</i> </p>
|
||||
<p><b>fed tekst, <i>fed og kursiv tekst</i></b></p>
|
||||
|
||||
<p>Liste af ansatte:</p>
|
||||
<ul>
|
||||
{% for e in emp %}
|
||||
<li>{{ e[1] }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4">Add a new employee</legend>
|
||||
<!-- Id-felt -->
|
||||
<div class="form-group">
|
||||
{{ form.id.label(class="form-control-label") }}
|
||||
|
||||
{% if form.id.errors %}
|
||||
{{ form.id(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.id.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.id(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- Username-felt -->
|
||||
<div class="form-group">
|
||||
{{ form.username.label(class="form-control-label") }}
|
||||
|
||||
{% if form.username.errors %}
|
||||
{{ form.username(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.username.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.username(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
<!-- Password-felt -->
|
||||
<div class="form-group">
|
||||
{{ form.password.label(class="form-control-label") }}
|
||||
{% if form.password.errors %}
|
||||
{{ form.password(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.password.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.password(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
<!-- Submit-knap -->
|
||||
<div class="form-group">
|
||||
{{ form.submit(class="btn btn-outline-info") }}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
@ -4,7 +4,7 @@
|
||||
<h1>{{ thread.title }}</h1>
|
||||
<div id="messages" class="messages">
|
||||
{% for message in messages %}
|
||||
{% if message.author_id == current_user.user_id %}
|
||||
{% if message.author.user_id == current_user.user_id %}
|
||||
<div class="message-container self">
|
||||
{% else %}
|
||||
<div class="message-container">
|
||||
@ -30,3 +30,8 @@
|
||||
</script>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block sidebar %}
|
||||
<a class="group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
|
||||
|
||||
{% endblock sidebar %}
|
||||
|
@ -5,6 +5,7 @@
|
||||
{% for thread in threads %}
|
||||
<div class="content-section">
|
||||
<a class="thread-name" href="{{ url_for('Threads.show', thread_id = thread.thread_id) }}"">{{thread.title}}</a>
|
||||
<a class="float-right group-name" href="{{ url_for('Group.show', group_id = thread.group_id) }}">{{thread.group.name}}</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock content %}
|
||||
|
@ -1,46 +0,0 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="POST" action="">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-group">
|
||||
{{ form.sourceAccount.label(class="form-control-label") }}
|
||||
{{ form.sourceAccount(class="form-control")}}
|
||||
</div>
|
||||
<fieldset class="form-group">
|
||||
<div class="form-group">
|
||||
{{ form.amount.label(class="form-control-label") }}
|
||||
{% if form.amount.errors %}
|
||||
{{ form.amount(class="form-control form-control-lg is-invalid") }}
|
||||
<div class="invalid-feedback">
|
||||
{% for error in form.password.errors %}
|
||||
<span>{{ error }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form.amount(class="form-control form-control-lg") }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
{{ form.targetAccount.label(class="form-control-label") }}
|
||||
{{ form.targetAccount(class="form-control") }}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{ form.submit(class="btn btn-outline-info") }}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="content-section">
|
||||
<p>Dropdown customer account tuples:</p>
|
||||
<ul class="list-group">
|
||||
{% for n in drop_cus_acc %}
|
||||
<li class="list-group-item list-group-item-light">{{n}}}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<br>
|
||||
<p>Same list with a filter: {{ drop_cus_acc|join(', ') }}</p>
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
Reference in New Issue
Block a user