diff --git a/Dockerfile b/Dockerfile index 050df56..339302d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# Use the official Python image from the Docker Hub +# Stage 1: Build stage FROM python:3.11-slim AS build # Set the working directory in the container @@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y \ libssl-dev \ python3-dev \ cargo \ + g++ \ curl \ && rm -rf /var/lib/apt/lists/* @@ -30,17 +31,25 @@ FROM python:3.11-slim # Set the working directory in the container WORKDIR /app -# Copy only the necessary files from the build stage -COPY --from=build /app /app -COPY --from=build /root/.cargo /root/.cargo - # Install runtime dependencies RUN apt-get update && apt-get install -y \ libffi-dev \ libssl-dev \ + g++ \ + curl \ && rm -rf /var/lib/apt/lists/* -# Install Gunicorn +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" + +# Copy only the necessary files from the build stage +COPY --from=build /app /app +COPY --from=build /root/.cargo /root/.cargo + +# Install Gunicorn and other Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt RUN pip install gunicorn # Make port 5000 available to the world outside this container diff --git a/__pycache__/app.cpython-311.pyc b/__pycache__/app.cpython-311.pyc index 035afd5..72a25e6 100644 Binary files a/__pycache__/app.cpython-311.pyc and b/__pycache__/app.cpython-311.pyc differ diff --git a/app.py b/app.py index f57292e..54552c3 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ import os -from flask import Flask, render_template, request, redirect, url_for +from flask import Flask, render_template, request, redirect, url_for, session from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user from flask_bcrypt import Bcrypt @@ -32,7 +32,7 @@ migrate = Migrate(app, db) @login_manager.user_loader def load_user(user_id): - return User.query.get(int(user_id)) + return db.session.get(User, int(user_id)) # Modele pentru baza de date class User(db.Model, UserMixin): @@ -40,22 +40,20 @@ class User(db.Model, UserMixin): username = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) role = db.Column(db.String(20), nullable=False, default='user') + theme = db.Column(db.String(10), nullable=False, default='light') class Player(db.Model): id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(80), nullable=False) - hostname = db.Column(db.String(120), nullable=False) - ip = db.Column(db.String(15), nullable=False) + username = db.Column(db.String(80), unique=True, nullable=False) + hostname = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) - user_id = db.Column(db.Integer, db.ForeignKey('user.id', name='fk_user_id'), nullable=True) class Group(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), unique=True, nullable=False) - players = db.relationship('Player', secondary='group_players', backref='groups') - content = db.relationship('Content', backref='group', lazy=True) + players = db.relationship('Player', secondary='group_player', backref='groups') -group_players = db.Table('group_players', +group_player = db.Table('group_player', db.Column('group_id', db.Integer, db.ForeignKey('group.id'), primary_key=True), db.Column('player_id', db.Integer, db.ForeignKey('player.id'), primary_key=True) ) @@ -113,25 +111,18 @@ def logout(): @app.route('/upload_content', methods=['GET', 'POST']) @login_required +@admin_required def upload_content(): + if request.method == 'POST': + # Handle file upload logic here + pass + + target_type = request.args.get('target_type') + target_id = request.args.get('target_id') + return_url = request.args.get('return_url', url_for('dashboard')) players = Player.query.all() groups = Group.query.all() - if request.method == 'POST': - target_type = request.form['target_type'] - target_id = request.form['target_id'] - files = request.files.getlist('files') - duration = int(request.form['duration']) - - for file in files: - filename = secure_filename(file.filename) - file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) - file.save(file_path) - new_content = Content(file_name=filename, duration=duration, player_id=target_id if target_type == 'player' else None, group_id=target_id if target_type == 'group' else None) - db.session.add(new_content) - - db.session.commit() - return redirect(url_for('dashboard')) - return render_template('upload_content.html', players=players, groups=groups) + return render_template('upload_content.html', target_type=target_type, target_id=target_id, players=players, groups=groups, return_url=return_url) @app.route('/admin') @login_required @@ -243,7 +234,7 @@ def delete_group_content(content_id): @login_required @admin_required def delete_group(group_id): - group = Group.query.get_or_404(group_id) + group = db.session.get(Group, group_id) db.session.delete(group) db.session.commit() return redirect(url_for('dashboard')) @@ -251,7 +242,7 @@ def delete_group(group_id): @app.route('/player/') @login_required def player_page(player_id): - player = Player.query.get_or_404(player_id) + player = db.session.get(Player, player_id) content = Content.query.filter_by(player_id=player_id).all() return render_template('player_page.html', player=player, content=content) @@ -339,10 +330,8 @@ def add_player(): if request.method == 'POST': username = request.form['username'] hostname = request.form['hostname'] - ip = request.form['ip'] - password = request.form['password'] - hashed_password = bcrypt.generate_password_hash(password).decode('utf-8') - new_player = Player(username=username, hostname=hostname, ip=ip, password=hashed_password) + password = bcrypt.generate_password_hash(request.form['password']).decode('utf-8') + new_player = Player(username=username, hostname=hostname, password=password) db.session.add(new_player) db.session.commit() return redirect(url_for('dashboard')) @@ -376,13 +365,29 @@ def edit_player(player_id): if request.method == 'POST': player.username = request.form['username'] player.hostname = request.form['hostname'] - player.ip = request.form['ip'] if request.form['password']: player.password = bcrypt.generate_password_hash(request.form['password']).decode('utf-8') db.session.commit() return redirect(url_for('player_page', player_id=player.id)) return render_template('edit_player.html', player=player) +@app.route('/change_theme', methods=['POST']) +@login_required +@admin_required +def change_theme(): + theme = request.form['theme'] + current_user.theme = theme + db.session.commit() + return redirect(url_for('admin')) + +@app.context_processor +def inject_theme(): + if current_user.is_authenticated: + theme = current_user.theme + else: + theme = 'light' + return dict(theme=theme) + if __name__ == '__main__': with app.app_context(): db.create_all() # Creează toate tabelele diff --git a/dashboard.db b/dashboard.db new file mode 100644 index 0000000..40690eb Binary files /dev/null and b/dashboard.db differ diff --git a/docker-compose.yml b/docker-compose.yml index a95f6d5..3abb56b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ -version: '3.8' + services: web: - image: digi_signage_server_app:latest + image: digi_signage:latest ports: - "7100:5000" environment: diff --git a/instance/dashboard.db b/instance/dashboard.db index f79e5f3..fdd839d 100644 Binary files a/instance/dashboard.db and b/instance/dashboard.db differ diff --git a/migrations/__pycache__/env.cpython-311.pyc b/migrations/__pycache__/env.cpython-311.pyc index 0205ce4..9ced6a7 100644 Binary files a/migrations/__pycache__/env.cpython-311.pyc and b/migrations/__pycache__/env.cpython-311.pyc differ diff --git a/migrations/alembic.ini b/migrations/alembic.ini index ec9d45c..11a47f2 100644 --- a/migrations/alembic.ini +++ b/migrations/alembic.ini @@ -1,17 +1,56 @@ -# A generic, single database configuration. - [alembic] -# template used to generate migration files -# file_template = %%(rev)s_%%(slug)s +# path to migration scripts +script_location = migrations -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate +# template used to generate migration files +file_template = %%(rev)s_%%(slug)s + +# timezone to use when rendering the date within the migration file as well as the filename. +# string value is passed to datetime.datetime.strftime(), default is to use UTC. +# output_timezone = UTC + +# max length of characters to apply to the "slug" field +# truncate_slug_length = 40 + +# set to 'true' to run the environment during the 'revision' command, regardless of autogenerate # revision_environment = false +# set to 'true' to allow .pyc and .pyo files without a source .py file to be detected as revisions +# sourceless = false + +# version location specification; this defaults +# to migrations/versions. When using multiple version +# directories, initial revisions must be specified with --version-path. +# The path separator used here should be the separator specified by "os.pathsep". +# version_locations = %(here)s/bar:%(here)s/bat:migrations/versions + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = sqlite:///dashboard.db + +[post_write_hooks] +# post_write_hooks defines scripts or Python functions that are run +# on newly generated revision scripts. See the documentation for further +# detail and examples +# hooks = + +# format the generated revision script to be PEP8 compliant +# hooks = pep8 + +# python +# hook_1.type = python +# hook_1.entrypoint = myproject.please_run_pep8 +# hook_1.options = {"treat-as-warning": "true"} + +# exec +# hook_2.type = exec +# hook_2.entrypoint = /usr/bin/pep8 +# hook_2.options = -# Logging configuration [loggers] -keys = root,sqlalchemy,alembic,flask_migrate +keys = root,sqlalchemy,alembic [handlers] keys = console @@ -26,18 +65,15 @@ qualname = [logger_sqlalchemy] level = WARN -handlers = +handlers = console qualname = sqlalchemy.engine +# propagate = 0 [logger_alembic] level = INFO -handlers = +handlers = console qualname = alembic - -[logger_flask_migrate] -level = INFO -handlers = -qualname = flask_migrate +# propagate = 0 [handler_console] class = StreamHandler @@ -47,4 +83,4 @@ formatter = generic [formatter_generic] format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S +datefmt = %H:%M:%S \ No newline at end of file diff --git a/migrations/env.py b/migrations/env.py index 4c97092..4c1a2cd 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,8 +1,8 @@ +from __future__ import with_statement import logging from logging.config import fileConfig -from flask import current_app - +from sqlalchemy import engine_from_config, pool from alembic import context # this is the Alembic Config object, which provides @@ -14,30 +14,13 @@ config = context.config fileConfig(config.config_file_name) logger = logging.getLogger('alembic.env') - -def get_engine(): - try: - # this works with Flask-SQLAlchemy<3 and Alchemical - return current_app.extensions['migrate'].db.get_engine() - except (TypeError, AttributeError): - # this works with Flask-SQLAlchemy>=3 - return current_app.extensions['migrate'].db.engine - - -def get_engine_url(): - try: - return get_engine().url.render_as_string(hide_password=False).replace( - '%', '%%') - except AttributeError: - return str(get_engine().url).replace('%', '%%') - - # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata -config.set_main_option('sqlalchemy.url', get_engine_url()) -target_db = current_app.extensions['migrate'].db +from flask import current_app +config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI')) +target_metadata = current_app.extensions['migrate'].db.metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -45,12 +28,6 @@ target_db = current_app.extensions['migrate'].db # ... etc. -def get_metadata(): - if hasattr(target_db, 'metadatas'): - return target_db.metadatas[None] - return target_db.metadata - - def run_migrations_offline(): """Run migrations in 'offline' mode. @@ -65,7 +42,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") context.configure( - url=url, target_metadata=get_metadata(), literal_binds=True + url=url, target_metadata=target_metadata, literal_binds=True ) with context.begin_transaction(): @@ -79,29 +56,14 @@ def run_migrations_online(): and associate a connection with the context. """ - - # this callback is used to prevent an auto-migration from being generated - # when there are no changes to the schema - # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html - def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): - script = directives[0] - if script.upgrade_ops.is_empty(): - directives[:] = [] - logger.info('No changes in schema detected.') - - conf_args = current_app.extensions['migrate'].configure_args - if conf_args.get("process_revision_directives") is None: - conf_args["process_revision_directives"] = process_revision_directives - - connectable = get_engine() + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix="sqlalchemy.", + poolclass=pool.NullPool, + ) with connectable.connect() as connection: - context.configure( - connection=connection, - target_metadata=get_metadata(), - **conf_args - ) + context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() diff --git a/migrations/versions/0de18b4ddaa3_initial_migration.py b/migrations/versions/0de18b4ddaa3_initial_migration.py deleted file mode 100644 index 0f61892..0000000 --- a/migrations/versions/0de18b4ddaa3_initial_migration.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Initial migration - -Revision ID: 0de18b4ddaa3 -Revises: -Create Date: 2025-01-20 14:50:44.116314 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '0de18b4ddaa3' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('player', schema=None) as batch_op: - batch_op.add_column(sa.Column('user_id', sa.Integer(), nullable=True)) - batch_op.create_foreign_key('fk_user_id', 'user', ['user_id'], ['id']) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('player', schema=None) as batch_op: - batch_op.drop_constraint('fk_user_id', type_='foreignkey') - batch_op.drop_column('user_id') - - # ### end Alembic commands ### diff --git a/migrations/versions/173774695298_add_theme_column_to_user_table.py b/migrations/versions/173774695298_add_theme_column_to_user_table.py new file mode 100644 index 0000000..4259dce --- /dev/null +++ b/migrations/versions/173774695298_add_theme_column_to_user_table.py @@ -0,0 +1,28 @@ +"""Add theme column to user table + +Revision ID: 173774695298 +Revises: c07c6e720021 +Create Date: 2025-01-23 15:16:46.761912 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '173774695298' +down_revision = 'c07c6e720021' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/migrations/versions/__pycache__/0de18b4ddaa3_initial_migration.cpython-311.pyc b/migrations/versions/__pycache__/0de18b4ddaa3_initial_migration.cpython-311.pyc deleted file mode 100644 index 149862f..0000000 Binary files a/migrations/versions/__pycache__/0de18b4ddaa3_initial_migration.cpython-311.pyc and /dev/null differ diff --git a/migrations/versions/__pycache__/173774695298_add_theme_column_to_user_table.cpython-311.pyc b/migrations/versions/__pycache__/173774695298_add_theme_column_to_user_table.cpython-311.pyc new file mode 100644 index 0000000..e7fa50c Binary files /dev/null and b/migrations/versions/__pycache__/173774695298_add_theme_column_to_user_table.cpython-311.pyc differ diff --git a/migrations/versions/__pycache__/c07c6e720021_add_theme_column_to_user_table.cpython-311.pyc b/migrations/versions/__pycache__/c07c6e720021_add_theme_column_to_user_table.cpython-311.pyc new file mode 100644 index 0000000..2cc478f Binary files /dev/null and b/migrations/versions/__pycache__/c07c6e720021_add_theme_column_to_user_table.cpython-311.pyc differ diff --git a/migrations/versions/__pycache__/e341b0e3043c_initial_migration.cpython-311.pyc b/migrations/versions/__pycache__/e341b0e3043c_initial_migration.cpython-311.pyc new file mode 100644 index 0000000..82cb72b Binary files /dev/null and b/migrations/versions/__pycache__/e341b0e3043c_initial_migration.cpython-311.pyc differ diff --git a/migrations/versions/c07c6e720021_add_theme_column_to_user_table.py b/migrations/versions/c07c6e720021_add_theme_column_to_user_table.py new file mode 100644 index 0000000..c1cdff2 --- /dev/null +++ b/migrations/versions/c07c6e720021_add_theme_column_to_user_table.py @@ -0,0 +1,28 @@ +"""Add theme column to user table + +Revision ID: c07c6e720021 +Revises: e341b0e3043c +Create Date: 2025-01-23 15:13:01.413532 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c07c6e720021' +down_revision = 'e341b0e3043c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### diff --git a/migrations/versions/e341b0e3043c_initial_migration.py b/migrations/versions/e341b0e3043c_initial_migration.py new file mode 100644 index 0000000..a991de2 --- /dev/null +++ b/migrations/versions/e341b0e3043c_initial_migration.py @@ -0,0 +1,72 @@ +"""Initial migration + +Revision ID: e341b0e3043c +Revises: +Create Date: 2025-01-23 15:09:25.485823 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'e341b0e3043c' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('group', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=80), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('name') + ) + op.create_table('player', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('username', sa.String(length=80), nullable=False), + sa.Column('hostname', sa.String(length=120), nullable=False), + sa.Column('password', sa.String(length=120), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('hostname'), + sa.UniqueConstraint('username') + ) + op.create_table('user', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('username', sa.String(length=80), nullable=False), + sa.Column('password', sa.String(length=120), nullable=False), + sa.Column('role', sa.String(length=20), nullable=False), + sa.Column('theme', sa.String(length=10), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('username') + ) + op.create_table('content', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('file_name', sa.String(length=120), nullable=False), + sa.Column('duration', sa.Integer(), nullable=False), + sa.Column('player_id', sa.Integer(), nullable=True), + sa.Column('group_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), + sa.ForeignKeyConstraint(['player_id'], ['player.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('group_players', + sa.Column('group_id', sa.Integer(), nullable=False), + sa.Column('player_id', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['group_id'], ['group.id'], ), + sa.ForeignKeyConstraint(['player_id'], ['player.id'], ), + sa.PrimaryKeyConstraint('group_id', 'player_id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('group_players') + op.drop_table('content') + op.drop_table('user') + op.drop_table('player') + op.drop_table('group') + # ### end Alembic commands ### diff --git a/requirements.txt b/requirements.txt index 87f0dab..665263c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ bcrypt==4.2.1 blinker==1.9.0 click==8.1.8 Flask==3.1.0 - +Flask-Bcrypt==1.0.1 Flask-Login==0.6.3 Flask-Migrate==4.1.0 Flask-SQLAlchemy==3.1.1 @@ -16,4 +16,3 @@ SQLAlchemy==2.0.37 typing_extensions==4.12.2 Werkzeug==3.1.3 gunicorn==20.1.0 -Flask-Bcrypt==1.0.1 \ No newline at end of file diff --git a/templates/add_group.html b/templates/add_group.html index a14e2e9..84410da 100644 --- a/templates/add_group.html +++ b/templates/add_group.html @@ -3,8 +3,21 @@ Add Group + - +

Add Group

diff --git a/templates/add_player.html b/templates/add_player.html index 85f3e96..446b9b4 100644 --- a/templates/add_player.html +++ b/templates/add_player.html @@ -3,11 +3,24 @@ Add Player + - +

Add Player

- +
@@ -16,10 +29,6 @@
-
- - -
diff --git a/templates/admin.html b/templates/admin.html index 7267c26..6de9995 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -3,60 +3,101 @@ Admin Panel + - +

Admin Panel

-

Manage Users

- - - - - - - - - - {% for user in users %} - - - - - - {% endfor %} - -
UsernameRoleActions
{{ user.username }}{{ user.role }} - - - - -
- -
-
+
+
+

Manage Users

+
+
+ +

Manage User Roles

+ + + + + + + + + + {% for user in users %} + + + + + + {% endfor %} + +
UsernameRoleActions
{{ user.username }}{{ user.role }} +
+ + +
+
+ +
+
-

Create New User

-
-
- - + +

Add New User

+ +
+ + +
+
+ + +
+
+ + +
+ +
-
- - +
+ + +
+
+

Change Theme

-
- - +
+
+
+ + +
+ +
- - +
Back to Dashboard @@ -65,4 +106,4 @@ - \ No newline at end of file + diff --git a/templates/dashboard.html b/templates/dashboard.html index e86e88f..8d9e5e6 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -5,8 +5,18 @@ Dashboard + - +

Dashboard

@@ -15,110 +25,116 @@ Sign Out
- - {% if current_user.role == 'admin' %} -
-
-

Users Management

-
- -
- {% endif %} +
+
+ +
+
+

Players

+
+
+
    + {% for player in players %} +
  • +
    + {{ player.username }} +
    +
    + Manage Player + Full Screen + {% if current_user.role == 'admin' %} +
    + +
    + {% endif %} +
    +
  • + {% endfor %} +
+ {% if current_user.role == 'admin' %} + + {% endif %} +
+
- -
-
-

Players

-
-
-
    - {% for player in players %} -
  • -
    - {{ player.username }} ({{ player.ip }}) -
    -
    - Manage Player - Full Screen - {% if current_user.role == 'admin' %} -
    - -
    - {% endif %} -
    -
  • - {% endfor %} -
+ +
+
+

Player Groups

+
+
+
    + {% for group in groups %} +
  • +
    + {{ group.name }} ({{ group.players | length }} players) +
      + {% for player in group.players %} +
    • + {{ player.username }} +
    • + {% endfor %} +
    +
    +
    + Manage Group + Full Screen + {% if current_user.role == 'admin' %} +
    + +
    + {% endif %} +
    +
  • + {% endfor %} +
+ {% if current_user.role == 'admin' %} +
+ Add Group +
+ {% endif %} +
+
+ + +
+
+

Content Upload

+
+ +
+ + {% if current_user.role == 'admin' %} -
- Add Player +
+
+

Integrate Player

+
+
{% endif %}
-
- -
-
-

Player Groups

-
-
-
    - {% for group in groups %} -
  • -
    - {{ group.name }} ({{ group.players | length }} players) -
      - {% for player in group.players %} -
    • - {{ player.username }} ({{ player.ip }}) -
    • - {% endfor %} -
    -
    -
    - Manage Group - Full Screen - {% if current_user.role == 'admin' %} -
    - -
    - {% endif %} -
    -
  • - {% endfor %} -
- {% if current_user.role == 'admin' %} -
- Add Group + + {% if current_user.role == 'admin' %} +
+
+
+

App Settings

+
+
- {% endif %}
+ {% endif %}
- - -
-
-

Content Upload

-
- -
- - - {% if current_user.role == 'admin' %} -
-
-

Integrate Player

-
- -
- {% endif %}
diff --git a/templates/integrate_player.html b/templates/integrate_player.html index b84871a..7ef9f41 100644 --- a/templates/integrate_player.html +++ b/templates/integrate_player.html @@ -3,13 +3,26 @@ Integrate Player + - +

Integrate Player

-
+

Players

@@ -17,7 +30,7 @@
{% for player in players %}
-
+
{{ player.username }}

{{ player.ip }}

@@ -35,7 +48,7 @@
-
+

Groups

@@ -43,7 +56,7 @@
{% for group in groups %}
-
+
{{ group.name }}

{{ group.players | length }} players

diff --git a/templates/manage_group.html b/templates/manage_group.html index eefcd82..e46ccfa 100644 --- a/templates/manage_group.html +++ b/templates/manage_group.html @@ -3,13 +3,26 @@ Manage Group + - +

Manage Group: {{ group.name }}

-
+

Add Players to Group

@@ -29,17 +42,17 @@
-
+

Players in Group

    {% for player in group.players %} -
  • -
    {{ player.username }} ({{ player.ip }})
    +
  • + {{ player.username }} ({{ player.ip }})
    - +
  • {% endfor %} @@ -47,57 +60,15 @@
- -
-
-

Upload Content for Group

-
-
-
-
- - -
-
- - -
- -
-
-
- - -
-
-

Manage Group Content

-
-
-
    - {% for content in group.content %} -
  • -
    {{ content.file_name }} - {{ content.duration }} seconds
    -
    - -
    - - -
    - -
    - -
    -
    -
  • - {% endfor %} -
- Full Screen -
+ + {% if current_user.role == 'admin' %} + + {% endif %} Back to Dashboard
- \ No newline at end of file diff --git a/templates/player_auth.html b/templates/player_auth.html index 2ff29e6..754172c 100644 --- a/templates/player_auth.html +++ b/templates/player_auth.html @@ -3,8 +3,21 @@ Player Authentication + - +

Player Authentication

diff --git a/templates/player_page.html b/templates/player_page.html index ddbf382..496ae9b 100644 --- a/templates/player_page.html +++ b/templates/player_page.html @@ -3,13 +3,26 @@ Player Schedule + - +

Player Schedule for {{ player.username }}

-
+

Player Info

@@ -32,76 +45,24 @@

Member of Group(s):

    {% for group in player.groups %} -
  • -
    {{ group.name }}
    - - -
  • - +
  • {{ group.name }}
  • {% endfor %}
{% else %} -

Not a member of any group

+

This player is not a member of any groups.

{% endif %}
- -
-
-

Schedule

-
-
-
    - {% for item in content %} -
  • -
    - {{ item.file_name }} - {{ item.duration }} seconds -
    - {% if not player.groups %} -
    - -
    - - -
    - -
    - -
    -
    - {% endif %} -
  • - {% endfor %} -
-
-
- - - {% if not player.groups %} -
-
-

Upload Content

-
-
-
-
- - -
-
- - -
- -
-
+ + {% if current_user.role == 'admin' %} + {% endif %} Back to Dashboard Full Screen
- \ No newline at end of file diff --git a/templates/register.html b/templates/register.html index 982a6f0..f4d1d17 100644 --- a/templates/register.html +++ b/templates/register.html @@ -3,8 +3,21 @@ Register + - +

Register

diff --git a/templates/upload_content.html b/templates/upload_content.html index 87f85c6..a7d1aca 100644 --- a/templates/upload_content.html +++ b/templates/upload_content.html @@ -3,32 +3,58 @@ Upload Content + - +

Upload Content

- + + + {% if target_type %} + + {% endif %}
- {% for player in players %} - + {% endfor %} {% for group in groups %} - + {% endfor %} + {% if target_id %} + + {% endif %} +
+
+ +
@@ -40,8 +66,26 @@
+ Back Back to Dashboard
+