Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.7.4 - Working on initial landing page impl #278

Merged
merged 3 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:

- run: |
mk python-release owner=vkottler \
repo=runtimepy version=5.7.3
repo=runtimepy version=5.7.4
if: |
matrix.python-version == '3.12'
&& matrix.system == 'ubuntu-latest'
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
=====================================
generator=datazen
version=3.1.4
hash=ef917873929a5dc6a70367fde7f1447f
hash=fbb71900eae64b008d2a2df1b7dde92b
=====================================
-->

# runtimepy ([5.7.3](https://pypi.org/project/runtimepy/))
# runtimepy ([5.7.4](https://pypi.org/project/runtimepy/))

[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
Expand Down
2 changes: 1 addition & 1 deletion local/variables/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
major: 5
minor: 7
patch: 3
patch: 4
entry: runtimepy
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"

[project]
name = "runtimepy"
version = "5.7.3"
version = "5.7.4"
description = "A framework for implementing Python services."
readme = "README.md"
requires-python = ">=3.11"
Expand Down
4 changes: 2 additions & 2 deletions runtimepy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# =====================================
# generator=datazen
# version=3.1.4
# hash=37a32f51e0bf04276100ce27658b7f8f
# hash=cb3ed2d01203d78ad794d39500d706f9
# =====================================

"""
Expand All @@ -10,7 +10,7 @@

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "5.7.3"
VERSION = "5.7.4"

# runtimepy-specific content.
METRICS_NAME = "metrics"
Expand Down
24 changes: 24 additions & 0 deletions runtimepy/data/js/markdown_page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/* Dark is hard-coded initial state (in HTML). */
let lightMode = false;

function lightDarkClick(event) {
lightMode = !lightMode;

document.getElementById("runtimepy")
.setAttribute("data-bs-theme", lightMode ? "light" : "dark");

window.location.hash = lightMode ? "#light-mode" : "";
}

let lightDarkButton = document.getElementById("theme-button");
if (lightDarkButton) {
lightDarkButton.addEventListener("click", lightDarkClick);
}

if (window.location.hash) {
let parts = window.location.hash.slice(1).split(",");

if (parts.includes("light-mode")) {
lightDarkButton.click();
}
}
163 changes: 163 additions & 0 deletions runtimepy/net/html/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"""
A module implementing HTML-related interfaces.
"""

# built-in
from io import StringIO
from typing import Optional

# third-party
from svgen.element import Element
from svgen.element.html import Html, div
from vcorelib import DEFAULT_ENCODING
from vcorelib.io import IndentedFileWriter
from vcorelib.paths import find_file

# internal
from runtimepy import PKG_NAME
from runtimepy.net.html.bootstrap import (
add_bootstrap_css,
add_bootstrap_js,
icon_str,
)
from runtimepy.net.html.bootstrap.elements import (
bootstrap_button,
centered_markdown,
)


def create_app_shell(parent: Element, **kwargs) -> tuple[Element, Element]:
"""Create a bootstrap-based application shell."""

container = div(parent=parent, **kwargs)
container.add_class("d-flex", "align-items-start", "bg-body")

# Dark theme.
container["data-bs-theme"] = "dark"

# Buttons.
button_column = div(parent=container)
button_column.add_class("d-flex", "flex-column", "h-100", "bg-dark-subtle")

# Dark/light theme switch button.
bootstrap_button(
icon_str("lightbulb"),
tooltip=" Toggle light/dark.",
id="theme-button",
parent=button_column,
)

return container, button_column


def markdown_page(parent: Element, markdown: str, **kwargs) -> None:
"""Compose a landing page."""

container = centered_markdown(
create_app_shell(parent, **kwargs)[0], markdown, "h-100", "text-body"
)
container.add_class("overflow-y-auto")


def common_css(document: Html) -> None:
"""Add common CSS to an HTML document."""

append_kind(document.head, "font", kind="css", tag="style")
add_bootstrap_css(document.head)
append_kind(
document.head, "main", "bootstrap_extra", kind="css", tag="style"
)


def full_markdown_page(document: Html, markdown: str) -> None:
"""Render a full markdown HTML app."""

common_css(document)
markdown_page(document.body, markdown, id=PKG_NAME)

# JavaScript.
append_kind(document.body, "markdown_page")
add_bootstrap_js(document.body)


def handle_worker(writer: IndentedFileWriter) -> int:
"""Boilerplate contents for worker thread block."""

# Not currently used.
# return write_found_file(
# writer, kind_url("js", "webgl-debug", subdir="third-party")
# )
del writer

return 0


def write_found_file(writer: IndentedFileWriter, *args, **kwargs) -> bool:
"""Write a file's contents to the file-writer's stream."""

result = False

entry = find_file(*args, **kwargs)
if entry is not None:
with entry.open(encoding=DEFAULT_ENCODING) as path_fd:
for line in path_fd:
writer.write(line)

result = True

return result


def kind_url(
kind: str, name: str, subdir: str = None, package: str = PKG_NAME
) -> str:
"""Return a URL to find a package resource."""

path = kind

if subdir is not None:
path += "/" + subdir

path += f"/{name}"

return f"package://{package}/{path}.{kind}"


WORKER_TYPE = "text/js-worker"


def append_kind(
element: Element,
*names: str,
package: str = PKG_NAME,
kind: str = "js",
tag: str = "script",
subdir: str = None,
worker: bool = False,
) -> Optional[Element]:
"""Append a new script element."""

elem = Element(tag=tag, allow_no_end_tag=False)

with StringIO() as stream:
writer = IndentedFileWriter(stream, per_indent=2)
found_count = 0
for name in names:
if write_found_file(
writer, kind_url(kind, name, subdir=subdir, package=package)
):
found_count += 1

if worker:
found_count += handle_worker(writer)

if found_count:
elem.text = stream.getvalue()

if found_count:
element.children.append(elem)

if worker:
elem["type"] = WORKER_TYPE

return elem if found_count else None
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from vcorelib.io.file_writer import IndentedFileWriter

# internal
from runtimepy.net.server.app.bootstrap import icon_str
from runtimepy.net.html.bootstrap import icon_str

TEXT = "font-monospace"
BOOTSTRAP_BUTTON = f"rounded-0 {TEXT} button-bodge text-nowrap"
Expand Down Expand Up @@ -167,7 +167,7 @@ def slider(

def centered_markdown(
parent: Element, markdown: str, *container_classes: str
) -> None:
) -> Element:
"""Add centered markdown."""

container = div(parent=parent)
Expand Down Expand Up @@ -198,3 +198,5 @@ def centered_markdown(
div(parent=horiz_container)

div(parent=container)

return container
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@

# internal
from runtimepy import PKG_NAME
from runtimepy.net.server.app.bootstrap import icon_str
from runtimepy.net.server.app.bootstrap.elements import (
from runtimepy.net.html import create_app_shell
from runtimepy.net.html.bootstrap.elements import (
BOOTSTRAP_BUTTON,
bootstrap_button,
collapse_button,
flex,
toggle_button,
Expand Down Expand Up @@ -84,27 +83,7 @@ def __init__(self, name: str, parent: Element) -> None:
"""Initialize this instance."""

self.name = name

# Create application container.
self.container = div(parent=parent, id=name)
self.container.add_class("d-flex", "align-items-start", "bg-body")

# Dark theme.
self.container["data-bs-theme"] = "dark"

# Buttons.
self.button_column = div(parent=self.container)
self.button_column.add_class(
"d-flex", "flex-column", "h-100", "bg-dark-subtle"
)

# Dark/light theme switch button.
bootstrap_button(
icon_str("lightbulb"),
tooltip=" Toggle light/dark.",
id="theme-button",
parent=self.button_column,
)
self.container, self.button_column = create_app_shell(parent, id=name)

# Toggle tabs button.
self.add_button("Toggle tabs", f"#{PKG_NAME}-tabs", id="tabs-button")
Expand Down
Loading
Loading