Skip to content

Commit

Permalink
Revert responsive layout
Browse files Browse the repository at this point in the history
  • Loading branch information
daya0576 committed Feb 3, 2025
1 parent 0934f4a commit 319b550
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 90 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ To avoid [permission issues](https://github.com/daya0576/beaverhabits/discussion
| **MAX_USER_COUNT**(int) | By setting it to `1`, you can prevent others from signing up in the future. |
| **ENABLE_IOS_STANDALONE**(bool) | Experiential feature to enable standalone mode on iOS. The default setting is `false`. |
| **INDEX_SHOW_HABIT_COUNT**(bool) | To display total completed count along with the habit name on the index page. The default setting is `false`. |
| **INDEX_HABIT_DATE_COLUMNS**(int) | Customize the date columns count for the index page. The default value is `5`. |
| **INDEX_HABIT_NAME_WIDTH**(int) | Customize the habit name width for the index page. The default value is `115`. |
| **INDEX_HABIT_NAME_COLUMNS**(int) | Customize the habit name column count for the index page. The default value is `5`. |
| **INDEX_HABIT_DATE_COLUMNS**(int) | Customize the date column count for the index page. The default value is `2`. |
| **TRUSTED_EMAIL_HEADER**(str) | Delegate authentication to an authenticating reverse proxy that passes in the user's details in HTTP headers, e.g. `Cf-Access-Authenticated-User-Email`. An existing account is required. |
| **TRUSTED_LOCAL_EMAIL**(str) | Disables authentication entirely. A new account with the specified email will be created if it does not exist. |

Expand Down
2 changes: 1 addition & 1 deletion beaverhabits/configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Settings(BaseSettings):
ENABLE_DESKTOP_ALGIN_CENTER: bool = True

INDEX_SHOW_HABIT_COUNT: bool = False
INDEX_HABIT_NAME_WIDTH: int = 115
INDEX_HABIT_NAME_COLUMNS: int = 2
INDEX_HABIT_DATE_COLUMNS: int = 5

def is_dev(self):
Expand Down
138 changes: 51 additions & 87 deletions beaverhabits/frontend/index_page.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import datetime
import os
from contextlib import contextmanager
from typing import Iterable
from typing import List

from nicegui import ui

Expand All @@ -12,113 +11,78 @@
from beaverhabits.storage.meta import get_root_path
from beaverhabits.storage.storage import Habit, HabitList, HabitListBuilder, HabitStatus

HABIT_LIST_RECORD_COUNT = settings.INDEX_HABIT_DATE_COLUMNS

LEFT_ITEM_CLASSES = (
f"w-[{settings.INDEX_HABIT_NAME_WIDTH}px] "
f"sm:w-[{settings.INDEX_HABIT_NAME_WIDTH + 13}px]"
"wrap self-center"
)
RIGHT_ITEM_CLASSES = "w-10 self-center"
def grid(columns, rows):
g = ui.grid(columns=columns, rows=rows)
g.classes("w-full gap-0 items-center")
return g


def week_headers(days: list[datetime.date]):
if settings.INDEX_SHOW_HABIT_COUNT:
yield "Sum"
for day in days:
yield day.strftime("%a")
if settings.INDEX_SHOW_HABIT_COUNT:
yield "Sum"


def day_headers(days: list[datetime.date]):
if settings.INDEX_SHOW_HABIT_COUNT:
yield "#"
for day in days:
yield day.strftime("%d")
if settings.INDEX_SHOW_HABIT_COUNT:
yield "#"


@contextmanager
def row():
with ui.row().classes("pl-4 pr-1 py-0").classes("no-wrap gap-0"):
yield


@contextmanager
def card():
with ui.card().classes("shadow-none gap-1.5 p-0"):
with row():
yield


@contextmanager
def flex(height: int):
# Responsive flex container
with ui.element("div") as f:
# Auto hide flex items when it overflows the flex parent
f.classes("flex flex-row-reverse justify-start")
# Auto ajust gap with screen size
f.classes("gap-x-[5px] sm:gap-x-[8px]")
f.classes(f"overflow-hidden h-{height}")
yield f


def name(habit: Habit):
# truncate name
redirect_page = os.path.join(get_root_path(), "habits", str(habit.id))
name = link(habit.name, target=redirect_page)
name.classes(LEFT_ITEM_CLASSES)


def headers(labels: Iterable[str]):
with flex(4):
for text in labels:
label = ui.label(text)
label.classes(RIGHT_ITEM_CLASSES)
label.style(
"font-size: 85%; font-weight: 500; color: #9e9e9e; text-align: center"
)
@ui.refreshable
def habit_list_ui(days: list[datetime.date], active_habits: List[Habit]):
# Calculate column count
name_columns, date_columns = 2 * settings.INDEX_HABIT_NAME_COLUMNS, 2
count_columns = 2 if settings.INDEX_SHOW_HABIT_COUNT else 0
columns = name_columns + len(days) * date_columns + count_columns

row_compat_classes = "pl-4 pr-0 py-0"
left_classes, right_classes = (
# grid 4
f"col-span-{name_columns} truncate",
# grid 2 2 2 2 2
f"col-span-{date_columns} px-1.5 place-self-center",
)
header_styles = "font-size: 85%; font-weight: 500; color: #9e9e9e"

with ui.column().classes("gap-1.5"):
# Date Headers
with grid(columns, 2).classes(row_compat_classes):
for it in (week_headers(days), day_headers(days)):
ui.label("").classes(left_classes)
for label in it:
ui.label(label).classes(right_classes).style(header_styles)

# Habit List
for habit in active_habits:
with ui.card().classes(row_compat_classes).classes("shadow-none"):
with grid(columns, 1):
# truncate name
root_path = get_root_path()
redirect_page = os.path.join(root_path, "habits", str(habit.id))
name = link(habit.name, target=redirect_page).classes(left_classes)
name.style(f"max-width: {52 * name_columns / date_columns}px;")

def checkboxes(habit: Habit, days: list[datetime.date]):
with flex(10):
if settings.INDEX_SHOW_HABIT_COUNT:
with ui.element("div").classes("w-10 h-10 flex place-content-center"):
IndexBadge(habit)
ticked_days = set(habit.ticked_days)
for day in days:
checkbox = HabitCheckBox(habit, day, day in ticked_days)
checkbox.classes(right_classes)

ticked_days = set(habit.ticked_days)
for day in days:
checkbox = HabitCheckBox(habit, day, day in ticked_days)
checkbox.classes(RIGHT_ITEM_CLASSES)
if settings.INDEX_SHOW_HABIT_COUNT:
IndexBadge(habit).classes(right_classes)


@ui.refreshable
def habit_list_ui(days: list[datetime.date], habit_list: HabitList):
active_habits = HabitListBuilder(habit_list).status(HabitStatus.ACTIVE).build()
def index_page_ui(days: list[datetime.date], habits: HabitList):
active_habits = HabitListBuilder(habits).status(HabitStatus.ACTIVE).build()
if not active_habits:
ui.label("List is empty.")
ui.label("List is empty.").classes("mx-auto w-80")
return

days = list(reversed(days))

# Date Headers
with ui.column().classes("gap-2"):
with ui.column().classes("gap-0.5"):
for it in (week_headers(days), day_headers(days)):
with row():
ui.label("").classes(LEFT_ITEM_CLASSES)
headers(it)

with ui.column().classes("gap-1.5"):
# Habit List
for habit in active_habits:
with card():
# Truncated habit name
name(habit)
checkboxes(habit, days)


def index_page_ui(days: list[datetime.date], habits: HabitList):
with layout():
habit_list_ui(days, habits)
habit_list_ui(days, active_habits)

# Prevent long press context menu for svg image elements
ui.context.client.on_connect(javascript.prevent_context_menu)

0 comments on commit 319b550

Please sign in to comment.