Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
39c3933
New theme added to theme.py: FomanticUI
princerb Jul 25, 2025
9c4b4e4
Merge branch 'master' into f-theme-fomanticui
princerb Jul 26, 2025
3fa4e1f
Merge branch 'master' of https://github.com/princerb/flask-admin into…
princerb Jul 26, 2025
63af33b
Merge branch 'master' of https://github.com/princerb/flask-admin into…
princerb Jul 27, 2025
c05a77a
Theme FomanticUI templates: add index.html
princerb Jul 27, 2025
cf2113b
Theme FomanticUI templates: add master.html
princerb Jul 27, 2025
82c22a8
Theme FomanticUI templates: add static.html
princerb Jul 27, 2025
490f13c
Theme FomanticUI templates: add layout.html
princerb Jul 27, 2025
cc40388
Theme FomanticUI templates: add actions.html
princerb Jul 27, 2025
ea2ea43
Theme FomanticUI: add actions.js
princerb Jul 27, 2025
29c701f
Theme FomanticUI templates: add model/layout.html
princerb Jul 27, 2025
7b7891c
Theme FomanticUI templates: add model/list.html
princerb Jul 27, 2025
dad7c54
Theme FomanticUI templates: add inline_form.html
princerb Jul 27, 2025
331b7be
Theme FomanticUI templates: add inline_list_base.html
princerb Jul 27, 2025
0fa05bd
Theme FomanticUI templates: add row_actions.html
princerb Jul 27, 2025
e6a23a1
Add type="button" to Inline Field adder button element & format doc
princerb Jul 28, 2025
e83306e
Theme FomanticUI: add RedisCLI templates
princerb Jul 30, 2025
dd70021
Theme FomanticUI: add initial base.html for testing
princerb Jul 30, 2025
8debbf6
Refactor list template: remove inline styles, improve modal handling,…
princerb Jul 30, 2025
0f316c5
Update row actions: add modal support and fix icon classes
princerb Jul 30, 2025
6ebf954
Add FomanticUI admin library with form rendering and pagination macros
princerb Jul 30, 2025
03f360e
Add breadcrumb utility for admin navigation
princerb Jul 30, 2025
08eab7f
Add footer template with menu-based navigation links
princerb Jul 30, 2025
ca9b4fe
Add modal templates for create, edit, and details views
princerb Jul 30, 2025
1eaa8e8
Add modal functionality for form handling
princerb Jul 30, 2025
7a01d61
Add model CRUD templates for create, edit, and details views
princerb Jul 30, 2025
0c12609
Add file management templates with modal support
princerb Jul 30, 2025
accfd07
Add helper functions for confirm dialogs and UI components
princerb Jul 30, 2025
a83c6cb
Add sidebar toggle functionality with localStorage persistence
princerb Jul 30, 2025
65e8855
Add advanced filtering functionality for admin lists
princerb Jul 30, 2025
113c3f7
Add form handling and validation JavaScript
princerb Jul 30, 2025
51949db
Add details view filtering functionality
princerb Jul 30, 2025
cb1a3cc
FomanticUI: Add Redis CLI interface JavaScript
princerb Jul 30, 2025
7f0ab13
Theme FomanticUI: main CSS styles for admin interface - FomanticUI
princerb Jul 30, 2025
e2ab9b4
Show loading state during modal form request
princerb Aug 1, 2025
a51a6ac
Show loading state from beginning & apply _gettext for button texts
princerb Aug 1, 2025
f3804bc
Replace is_modal param with modal_action_type for getting action name…
princerb Aug 1, 2025
7dc581b
Remove bs4-editable script/style includings from lib.html
princerb Aug 1, 2025
4fd36ec
Add an optimal and universal max-width to admin forms
princerb Aug 1, 2025
d91c8a0
Remove unnecessary cases and comments from form.js
princerb Aug 1, 2025
411f643
Merge branch 'master' into f-theme-fomanticui
princerb Aug 11, 2025
56a839d
Merge branch 'master' into f-theme-fomanticui
princerb Nov 10, 2025
6e4e93f
Add an example fomanticui-test
princerb Nov 10, 2025
de7c988
Add an example fomanticui [Refactor mypy test]
princerb Nov 10, 2025
f5b9ce3
Merge branch 'master' into f-theme-fomanticui
princerb Mar 1, 2026
e177bb0
add static local files
samialfattani Mar 16, 2026
bb3793b
fix css class generated by column name #2730
samialfattani Mar 17, 2026
6f00def
fix #2829
samialfattani Mar 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/fomanticui/.python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
19 changes: 19 additions & 0 deletions examples/fomanticui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# FomanticUI Theme
This example contains different types of implementations of each section/feature of flask-admin to test FomanticUI theme. Can also be used to test other upcoming new themes.

## How to run this example

Clone the repository and navigate to this example:

```shell
git clone https://github.com/pallets-eco/flask-admin.git
cd flask-admin/examples/fomanticui
```

> This example uses [`uv`](https://docs.astral.sh/uv/) to manage its dependencies and developer environment.

Run the example using `uv`, which will manage the environment and dependencies automatically:

```shell
uv run main.py
```
Empty file added examples/fomanticui/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions examples/fomanticui/bp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from flask import Blueprint
from flask import redirect
from flask import render_template_string
from flask import url_for

bp = Blueprint("main", __name__, template_folder="my_admin/templates")


@bp.route("/")
def index():
return render_template_string("""
<h1>Hello, World!</h1>
<ul>
<li>
<a href="{{ url_for('basicadmin.index') }}">
Basic Admin Panel
</a>
</li>
<li>
<a href="{{ url_for('superadmin.index') }}">
Super Admin Panel
</a>
</li>
<li>
<a href="{{ url_for('proadmin.index') }}">
Pro Admin Panel
</a>
</li>
</ul>
""")


@bp.app_errorhandler(404)
def not_found(error):
return redirect(url_for("main.index"))
9 changes: 9 additions & 0 deletions examples/fomanticui/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import os


class MyConfig:
DEBUG = True
SECRET_KEY = os.environ.get("SECRET_KEY", os.urandom(16))
DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///sqlite3-fomanticui.sqlite")
SQLALCHEMY_DATABASE_URI = DATABASE_URL
SQLALCHEMY_TRACK_MODIFICATIONS = False
272 changes: 272 additions & 0 deletions examples/fomanticui/fake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
from random import choice
from random import randint

from faker import Faker
from models import Address
from models import Category
from models import Comment
from models import db
from models import Department
from models import Employee
from models import Order
from models import OrderItem
from models import OrderStatus
from models import Payment
from models import PaymentMethod
from models import Post
from models import Product
from models import Profile
from models import Project
from models import Role
from models import Tag
from models import User

fake = Faker()


def generate_fake_data(app):
"""Populate the database with a rich set of example data covering all models."""
with app.app_context():
db.create_all()

# ----- Roles -----
if Role.query.count() == 0:
for name in ("admin", "editor", "user"):
db.session.add(Role(name=name))
db.session.commit()

roles = Role.query.all()

# ----- Categories -----
while Category.query.count() < 5:
db.session.add(
Category(name=fake.unique.word(), description=fake.sentence())
)
db.session.commit()
categories = Category.query.all()

# ----- Tags -----
while Tag.query.count() < 10:
db.session.add(Tag(name=fake.unique.word()))
db.session.commit()
tags = Tag.query.all()

# ----- Products -----
while Product.query.count() < 20:
db.session.add(
Product(
name=fake.unique.word().title(),
description=fake.text(max_nb_chars=200),
price=round(
fake.pyfloat(
left_digits=3,
right_digits=2,
positive=True,
min_value=5,
max_value=200,
),
2,
),
stock=randint(0, 100),
data={
"color": fake.color_name(),
"size": choice(["S", "M", "L", "XL"]),
},
)
)
db.session.commit()
products = Product.query.all()

# ----- Users -----
while User.query.count() < 50:
user = User(
email=fake.unique.email(),
name=fake.name(),
age=randint(18, 65),
active=choice([True, False]),
preferences={"newsletter": choice([True, False])},
balance=round(
fake.pyfloat(left_digits=3, right_digits=2, positive=True), 2
),
last_login=fake.date_time_this_year(),
)
# assign 1-3 random roles
user.roles.extend(
fake.random_elements(elements=roles, length=randint(1, 3), unique=True)
)
db.session.add(user)
db.session.commit()

users = User.query.all()

# ----- Addresses & Profiles -----
for user in users:
if not user.addresses:
addr = Address(
street=fake.street_address(),
city=fake.city(),
state=fake.state(),
postal_code=fake.postcode(),
country=fake.country(),
is_primary=True,
user_id=user.id,
)
db.session.add(addr)
if not user.profile:
profile = Profile(bio=fake.sentence(), avatar=None, user_id=user.id)
db.session.add(profile)
db.session.commit()

# ----- Posts -----
while Post.query.count() < 100:
author = choice(users)
post = Post(
author_id=author.id,
category=choice(categories),
title=fake.sentence(),
body=fake.text(max_nb_chars=800),
)
post.tags = fake.random_elements(
elements=tags, length=randint(1, 4), unique=True
)
db.session.add(post)
db.session.commit()

posts = Post.query.all()

# ----- Comments -----
while Comment.query.count() < 300:
db.session.add(
Comment(
post_id=choice(posts).id,
user_id=choice(users).id,
body=fake.sentence(),
)
)
db.session.commit()

# ----- Orders, Items, Payments -----
while Order.query.count() < 200:
user = choice(users)
order = Order(
user_id=user.id,
status=choice(list(OrderStatus)),
total_price=0, # will update after adding items
)
db.session.add(order)
db.session.commit()

orders = Order.query.all()

for order in orders:
if not order.items:
chosen_products = fake.random_elements( # type: ignore
elements=products, length=randint(1, 5), unique=True
)
total = 0
for prod in chosen_products:
qty = randint(1, 3)
total += prod.price * qty
db.session.add(
OrderItem(
order_id=order.id,
product_id=prod.id,
quantity=qty,
price=prod.price,
)
)
order.total_price = round(total, 2)
db.session.add(
Payment(
order_id=order.id,
amount=order.total_price,
paid_at=fake.date_time_this_year(),
method=choice(list(PaymentMethod)),
)
)
db.session.commit()

# ----- Departments -----
while Department.query.count() < 5:
db.session.add(
Department(
name=fake.unique.company(),
budget=round(
fake.pyfloat(
left_digits=7,
right_digits=2,
positive=True,
min_value=10000,
max_value=1000000,
),
2,
),
)
)
db.session.commit()
departments = Department.query.all()

# ----- Projects -----
while Project.query.count() < 10:
db.session.add(
Project(
name=fake.unique.catch_phrase(),
deadline=fake.date_this_year(after_today=True),
description=fake.text(max_nb_chars=200),
budget=round(
fake.pyfloat(
left_digits=6,
right_digits=2,
positive=True,
min_value=5000,
max_value=500000,
),
2,
),
)
)
db.session.commit()
projects = Project.query.all()

# ----- Employees -----
while Employee.query.count() < 100:
dept = choice(departments)
emp = Employee(
department_id=dept.id,
first_name=fake.first_name(),
last_name=fake.last_name(),
salary=round(
fake.pyfloat(
left_digits=6,
right_digits=2,
positive=True,
min_value=30000,
max_value=150000,
),
2,
),
hire_date=fake.date_between(start_date="-10y", end_date="today"),
shift_start=fake.time_object(),
is_full_time=choice([True, False]),
rating=round(
fake.pyfloat(
left_digits=1,
right_digits=2,
positive=True,
min_value=1,
max_value=5,
),
2,
),
)
db.session.add(emp)
db.session.commit()

employees = Employee.query.all()

for emp in employees:
if not emp.projects:
emp.projects = fake.random_elements(
elements=projects, length=randint(1, 4), unique=True
)
db.session.commit()
27 changes: 27 additions & 0 deletions examples/fomanticui/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from bp import bp
from config import MyConfig
from fake import generate_fake_data
from flask import Flask
from models import db_init
from my_admin.basic_admin import admin as basic_admin
from my_admin.pro_admin import admin as pro_admin
from my_admin.super_admin import admin as super_admin

app = Flask(__name__)

app.config.from_object(MyConfig)
db_init(app)
generate_fake_data(app)

# Init admin instances

basic_admin.init_app(app)
super_admin.init_app(app)
pro_admin.init_app(app)


app.register_blueprint(bp)


if __name__ == "__main__":
app.run(debug=True)
Loading