starting admin work

This commit is contained in:
2025-06-28 02:55:17 -05:00
parent 13d56066ab
commit adbb3250ad
11 changed files with 205 additions and 89 deletions

View File

@ -26,6 +26,8 @@ services:
timeout: 3s timeout: 3s
retries: 3 retries: 3
start_period: 30s start_period: 30s
networks:
- appnet
db: db:
image: mysql:8 image: mysql:8
@ -39,12 +41,18 @@ services:
- "42000:3306" - "42000:3306"
volumes: volumes:
- ./mysql_data:/var/lib/mysql - ./mysql_data:/var/lib/mysql
entrypoint: ["sh", "-c", "mkdir -p /var/lib/mysql && chown -R 1000:998 /var/lib/mysql && chmod -R 770 /var/lib/mysql && exec docker-entrypoint.sh mysqld"] entrypoint: >
sh -c "mkdir -p /var/lib/mysql &&
chown -R 1000:998 /var/lib/mysql &&
chmod -R 770 /var/lib/mysql &&
exec docker-entrypoint.sh mysqld"
healthcheck: healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s interval: 10s
timeout: 5s timeout: 5s
retries: 5 retries: 5
networks:
- appnet
adminer: adminer:
image: adminer image: adminer
@ -55,6 +63,8 @@ services:
- ADMINER_DEFAULT_SERVER=db - ADMINER_DEFAULT_SERVER=db
depends_on: depends_on:
- db - db
networks:
- appnet
neo4j: neo4j:
image: neo4j:5.18 image: neo4j:5.18
@ -66,6 +76,12 @@ services:
- NEO4J_AUTH=neo4j/your_secure_password - NEO4J_AUTH=neo4j/your_secure_password
volumes: volumes:
- neo4j_data:/data - neo4j_data:/data
networks:
- appnet
volumes: volumes:
neo4j_data: neo4j_data:
networks:
appnet:
driver: bridge

View File

@ -0,0 +1,28 @@
"""auto-migrate
Revision ID: 19e2a1b15b5e
Revises: f00a9585a348
Create Date: 2025-06-27 22:59:54.162560
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '19e2a1b15b5e'
down_revision = 'f00a9585a348'
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 ###

View File

@ -0,0 +1,28 @@
"""auto-migrate
Revision ID: 85b7ca21ec19
Revises: 8c1e8db7b3cb
Create Date: 2025-06-27 23:34:04.669553
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '85b7ca21ec19'
down_revision = '8c1e8db7b3cb'
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 ###

View File

@ -0,0 +1,28 @@
"""auto-migrate
Revision ID: 8c1e8db7b3cb
Revises: 19e2a1b15b5e
Create Date: 2025-06-27 23:21:19.031362
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '8c1e8db7b3cb'
down_revision = '19e2a1b15b5e'
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 ###

BIN
nip.zip

Binary file not shown.

View File

@ -16,24 +16,28 @@
<h2 class="mb-4">View Entries</h2> <h2 class="mb-4">View Entries</h2>
{# ── Import / Export, Stats, Filters & View Toggle ─────────────────────── #} {# ── Import / Export / Stats & Filters / View Toggle ───────────────────── #}
<div class="mb-3 d-flex flex-wrap justify-content-between align-items-center"> <div class="mb-3 d-flex flex-wrap justify-content-between align-items-start">
<!-- Left: import/export & stats toggle --> {# LEFT: Import/Export + Stats toggles #}
<div class="d-flex align-items-center mb-2"> <div class="btn-toolbar mb-2" role="toolbar">
<button class="btn btn-primary me-2" data-bs-toggle="modal" data-bs-target="#importModal"> <div class="btn-group me-2" role="group">
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#importModal">
Import CSV Import CSV
</button> </button>
<a href="{{ url_for('utility.export_data') }}" class="btn btn-secondary me-2"> </div>
<div class="btn-group me-2" role="group">
<a href="{{ url_for('utility.export_data') }}" class="btn btn-secondary">
Export My Data Export My Data
</a> </a>
<button <button
class="btn btn-secondary me-2 d-inline-block d-md-none" class="btn btn-secondary d-inline-block d-md-none"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#statsModal"> data-bs-target="#statsModal">
Stats Stats
</button> </button>
<button <button
class="btn btn-secondary me-2 d-none d-md-inline-block" class="btn btn-secondary d-none d-md-inline-block"
data-bs-toggle="collapse" data-bs-toggle="collapse"
data-bs-target="#statsBox" data-bs-target="#statsBox"
aria-expanded="false" aria-expanded="false"
@ -42,14 +46,16 @@
Stats <i class="bi bi-chevron-down"></i> Stats <i class="bi bi-chevron-down"></i>
</button> </button>
</div> </div>
</div>
<!-- Right: filter form + view toggle --> {# RIGHT: filter form + view toggle #}
<form <form
method="get" method="get"
action="{{ url_for('plant.index') }}" action="{{ url_for('plant.index') }}"
class="d-flex flex-wrap align-items-center mb-2" class="row gx-2 gy-2 align-items-center mb-2"
> >
<div class="input-group me-2" style="min-width:200px;"> <div class="col-auto">
<div class="input-group">
<span class="input-group-text">Search</span> <span class="input-group-text">Search</span>
<input <input
type="search" type="search"
@ -59,10 +65,12 @@
placeholder="by name…" placeholder="by name…"
/> />
</div> </div>
</div>
<div class="col-auto">
<select <select
name="type" name="type"
class="form-select me-2" class="form-select"
style="min-width:140px;" style="min-width:140px;"
onchange="this.form.submit()" onchange="this.form.submit()"
> >
@ -74,10 +82,12 @@
>{{ t }}</option> >{{ t }}</option>
{% endfor %} {% endfor %}
</select> </select>
</div>
<div class="col-auto">
<select <select
name="per_page" name="per_page"
class="form-select me-2" class="form-select"
style="min-width:140px;" style="min-width:140px;"
onchange="this.form.submit()" onchange="this.form.submit()"
> >
@ -87,12 +97,16 @@
</option> </option>
{% endfor %} {% endfor %}
</select> </select>
</div>
{# keep the current view so Apply doesnt reset it #} {# preserve current view so Apply doesnt reset it #}
<input type="hidden" name="view" value="{{ view_mode }}" /> <input type="hidden" name="view" value="{{ view_mode }}" />
<button type="submit" class="btn btn-primary me-2">Apply</button> <div class="col-auto">
<button type="submit" class="btn btn-primary">Apply</button>
</div>
<div class="col-auto">
<div class="btn-group" role="group" aria-label="View mode"> <div class="btn-group" role="group" aria-label="View mode">
<a <a
href="{{ url_for('plant.index', href="{{ url_for('plant.index',
@ -100,23 +114,25 @@
per_page=per_page, per_page=per_page,
q=q, q=q,
type=type_filter, type=type_filter,
view='grid' view='grid') }}"
) }}"
class="btn btn-outline-secondary {% if view_mode=='grid' %}active{% endif %}" class="btn btn-outline-secondary {% if view_mode=='grid' %}active{% endif %}"
title="Card View" title="Card View"
><i class="bi bi-grid-3x3-gap-fill"></i></a> >
<i class="bi bi-grid-3x3-gap-fill"></i>
</a>
<a <a
href="{{ url_for('plant.index', href="{{ url_for('plant.index',
page=pagination.page, page=pagination.page,
per_page=per_page, per_page=per_page,
q=q, q=q,
type=type_filter, type=type_filter,
view='list' view='list') }}"
) }}"
class="btn btn-outline-secondary {% if view_mode=='list' %}active{% endif %}" class="btn btn-outline-secondary {% if view_mode=='list' %}active{% endif %}"
title="List View" title="List View"
><i class="bi bi-list-ul"></i></a> >
<i class="bi bi-list-ul"></i>
</a>
</div>
</div> </div>
</form> </form>
</div> </div>