Skip to content

Commit

Permalink
3.11.1 - More HTML UI dev
Browse files Browse the repository at this point in the history
  • Loading branch information
vkottler committed Mar 19, 2024
1 parent 11fbe97 commit 7877832
Show file tree
Hide file tree
Showing 21 changed files with 206 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
- run: |
mk python-release owner=vkottler \
repo=runtimepy version=3.11.0
repo=runtimepy version=3.11.1
if: |
matrix.python-version == '3.11'
&& 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=16b2cf0b2122fb98367ad624135dcbb3
hash=bedc870d38c09f3340b08f2d190a45f6
=====================================
-->

# runtimepy ([3.11.0](https://pypi.org/project/runtimepy/))
# runtimepy ([3.11.1](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/configs/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ entry: {{entry}}

requirements:
- vcorelib>=3.2.0
- svgen>=0.5.2
- svgen>=0.6.0
- websockets
- "windows-curses; sys_platform == 'win32' and python_version < '3.12'"

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: 3
minor: 11
patch: 0
patch: 1
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 = "3.11.0"
version = "3.11.1"
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=b07cee45d00e3ed8152c5fef04b7d2c9
# hash=d7d74df416629b2e2b52a6f7acab3ddc
# =====================================

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

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "3.11.0"
VERSION = "3.11.1"

# runtimepy-specific content.
METRICS_NAME = "metrics"
8 changes: 8 additions & 0 deletions runtimepy/data/css/bootstrap_extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
height: 100%;
overflow: scroll;
}

.button-bodge {
text-align: left;
}

.collapsing {
transition: none !important;
}
2 changes: 0 additions & 2 deletions runtimepy/data/html/dev.html

This file was deleted.

3 changes: 0 additions & 3 deletions runtimepy/data/html/example.html

This file was deleted.

8 changes: 6 additions & 2 deletions runtimepy/data/js/tabs/dev.js → runtimepy/data/js/env.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
console.log("env.js");

/*
tab.container.querySelector("button").onclick = async event => {
/**/
//
tab.send_message({kind : "button.pressed"});
/**/
//
};
tab.message_handlers.push((data) => {
console.log("-----" + tab.name + "-----");
console.log(data);
console.log("---------------------------");
});
*/
12 changes: 12 additions & 0 deletions runtimepy/data/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ function worker_config(config) {
return worker_cfg;
}

function bootstrap_init() {
/*
* Enable tooltips.
* https://getbootstrap.com/docs/5.3/components/tooltips/#overview
*/
const tooltipTriggerList = document.querySelectorAll(".has-tooltip");
const tooltipList = [...tooltipTriggerList ].map(
tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
}

class App {
constructor(config, worker) {
this.config = config;
Expand Down Expand Up @@ -53,6 +63,8 @@ class App {

/* Start worker. */
this.worker.postMessage(this.config);

bootstrap_init();
}
}

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion runtimepy/data/server_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ config:
caching: false

# This is the default.
# html_method: runtimepy.net.server.app.sample
# html_method: runtimepy.net.server.app.channel_environments

port_overrides:
runtimepy_http_server: 8000
32 changes: 20 additions & 12 deletions runtimepy/net/server/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,36 @@
from runtimepy.net.server import RuntimepyServerConnection
from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
from runtimepy.net.server.app.create import config_param, create_app
from runtimepy.net.server.app.tab import Tab


def sample(app: AppInfo, tabs: TabbedContent) -> None:
"""Populate application elements."""

# Add dev tab.
Tab("example", app, tabs, source="dev").entry()

for idx in range(10):
Tab(f"test{idx}", app, tabs, source="example").entry()
from runtimepy.net.server.app.env import ChannelEnvironmentTab


async def setup(app: AppInfo) -> int:
"""Perform server application setup steps."""

# Set default application.
module, method = import_str_and_item(
config_param(app, "html_method", "runtimepy.net.server.app.sample")
config_param(
app, "html_method", "runtimepy.net.server.app.channel_environments"
)
)
RuntimepyServerConnection.default_app = create_app(
app, getattr(_import_module(module), method)
)

return 0


def channel_environments(app: AppInfo, tabs: TabbedContent) -> None:
"""Populate application elements."""

# Connection tabs.
for name, conn in app.connections.items():
ChannelEnvironmentTab(
name, conn.command, app, tabs, icon="ethernet"
).entry()

# Task tabs.
for name, task in app.tasks.items():
ChannelEnvironmentTab(
name, task.command, app, tabs, icon="arrow-repeat"
).entry()
58 changes: 38 additions & 20 deletions runtimepy/net/server/app/bootstrap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,54 @@
# third-party
from svgen.element import Element

# internal
from runtimepy.net.server.app.elements import div

CDN = "cdn.jsdelivr.net"
BOOTSTRAP_VERSION = "5.3.3"
ICONS_VERSION = "1.11.3"


def icon_str(icon: str) -> str:
"""Get a boostrap icon string."""
return f'<i class="bi bi-{icon}"></i>'


def add_bootstrap_css(element: Element) -> None:
"""Add boostrap CSS sources as a child of element."""

element.children.append(
Element(
tag="link",
href=(
"https://cdn.jsdelivr.net/npm/bootstrap"
f"@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css"
),
rel="stylesheet",
crossorigin="anonymous",
)
div(
tag="link",
rel="stylesheet",
href=(
f"https://{CDN}/npm/"
f"bootstrap-icons@{ICONS_VERSION}/font/bootstrap-icons.min.css"
),
parent=element,
)

div(
tag="link",
href=(
f"https://{CDN}/npm/bootstrap"
f"@{BOOTSTRAP_VERSION}/dist/css/bootstrap.min.css"
),
rel="stylesheet",
crossorigin="anonymous",
parent=element,
)


def add_bootstrap_js(element: Element) -> None:
"""Add bootstrap JavaScript as a child of element."""

element.children.append(
Element(
tag="script",
src=(
"https://cdn.jsdelivr.net/npm/bootstrap"
f"@{BOOTSTRAP_VERSION}/dist/js/bootstrap.bundle.min.js"
),
crossorigin="anonymous",
text="/* null */",
)
div(
tag="script",
src=(
"https://cdn.jsdelivr.net/npm/bootstrap"
f"@{BOOTSTRAP_VERSION}/dist/js/bootstrap.bundle.min.js"
),
crossorigin="anonymous",
text="/* null */",
parent=element,
)
50 changes: 46 additions & 4 deletions runtimepy/net/server/app/bootstrap/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
from svgen.element import Element

# internal
from runtimepy import PKG_NAME
from runtimepy.net.server.app.bootstrap import icon_str
from runtimepy.net.server.app.elements import div

BOOTSTRAP_BUTTON = "rounded-0 font-monospace button-bodge"


def create_nav_button(
parent: Element, name: str, item: str, active_tab: bool
Expand All @@ -24,7 +28,7 @@ def create_nav_button(
button["aria-controls"] = f"{name}-{item}"
button["aria-selected"] = str(active_tab).lower()

class_str = "nav-link rounded-0 font-monospace"
class_str = "nav-link " + BOOTSTRAP_BUTTON
if active_tab:
class_str += " active"

Expand All @@ -51,6 +55,35 @@ def create_nav_container(
return content


def set_tooltip(element: Element, data: str, placement: str = "right") -> None:
"""Set a tooltip on an element."""

element["data-bs-title"] = data
element["data-bs-placement"] = placement

# Should we use another mechanism for this?
element["class"] += " has-tooltip"


def collapse_button(tooltip: str = None, **kwargs) -> Element:
"""Create a collapse button."""

collapse = div(
tag="button",
type="button",
text=icon_str("arrows-collapse-vertical"),
**kwargs,
)
collapse["class"] = "btn btn-secondary " + BOOTSTRAP_BUTTON
if tooltip:
set_tooltip(collapse, tooltip)

collapse["data-bs-toggle"] = "collapse"
collapse["data-bs-target"] = f"#{PKG_NAME}-tabs"

return collapse


class TabbedContent:
"""A tabbed-content container."""

Expand All @@ -65,13 +98,22 @@ def __init__(self, name: str, parent: Element) -> None:
self.container["data-bs-theme"] = "dark"
self.container["class"] = "d-flex align-items-start"

# Collapse button.
self.button_column = div(parent=self.container)
self.button_column["class"] = "d-flex flex-column bg-dark h-100"
self.collapse = collapse_button(
parent=self.button_column, tooltip="Collapse tabs."
)

# Placeholder.
collapse_button(parent=self.button_column, tooltip="YUP 2")

# Create tab container.
self.tabs = div(parent=self.container)
tabs_class = "bg-dark nav flex-column nav-pills"
self.tabs = div(id=f"{PKG_NAME}-tabs", parent=self.container)
tabs_class = "bg-dark nav flex-column nav-pills show"

# Created a custom class to fix scroll behavior.
tabs_class += " flex-column-scroll-bodge"

self.tabs["class"] = tabs_class

# Create content container.
Expand Down
42 changes: 42 additions & 0 deletions runtimepy/net/server/app/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
A module implementing a channel-environment tab HTML interface.
"""

# third-party
from svgen.element import Element

# internal
from runtimepy.channel.environment.command.processor import (
ChannelCommandProcessor,
)
from runtimepy.net.arbiter.info import AppInfo
from runtimepy.net.server.app.bootstrap import icon_str
from runtimepy.net.server.app.bootstrap.tabs import TabbedContent
from runtimepy.net.server.app.elements import div
from runtimepy.net.server.app.tab import Tab


class ChannelEnvironmentTab(Tab):
"""A channel-environment tab interface."""

def __init__(
self,
name: str,
command: ChannelCommandProcessor,
app: AppInfo,
tabs: TabbedContent,
icon: str = "alarm",
) -> None:
"""Initialize this instance."""

self.command = command
super().__init__(name, app, tabs, source="env")

# Use an icon as the start of the button.
self.button.text = icon_str(icon) + " " + self.name

def compose(self, parent: Element) -> None:
"""Compose the tab's HTML elements."""

for name in self.command.env.names:
div(text=name, parent=parent)
Loading

0 comments on commit 7877832

Please sign in to comment.