Skip to content

feat: build x0 github2stackfield application#1

Merged
clauspruefer merged 7 commits into
mainfrom
copilot/build-x0-application
May 27, 2026
Merged

feat: build x0 github2stackfield application#1
clauspruefer merged 7 commits into
mainfrom
copilot/build-x0-application

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 26, 2026

Summary

Full implementation of the github2stackfield x0 application — a modern Bootstrap-styled browser frontend that connects GitHub Issues with Stackfield Tasks via Python backend services built on the python-micro-esb framework.

The entire stack starts with a single docker compose up --build — no manual configuration, no post-start database commands.


Changes

  • static/menu.json — 3 navigation links (User Credentials, Issue / Task Mapping, Connect Stackfield Task)
  • static/object.json — all x0 UI objects for 3 screens: sysObjectFormfieldList, sysObjectList, sysObjContextMenu, sysObjButton, ServiceConnector
  • static/skeleton.json — screen layout wiring objects to screens / connectors
  • python/service_implementation.pyGitHubService + StackfieldService subclassing microesb.ClassHandler
  • python/user_routing.py — python-micro-esb ServiceRouter routing functions for all 5 backend operations
  • python/VerifyGitHubCredentials.py — WSGI endpoint: validate + persist GitHub credentials
  • python/VerifyStackfieldCredentials.py — WSGI endpoint: validate + persist Stackfield credentials
  • python/SearchGitHubIssues.py — WSGI endpoint: search GitHub issues, return indexed rows for x0 List
  • python/GetGitHubIssueDetails.py — WSGI endpoint: fetch full issue data, pre-populate Screen 3 formfields
  • python/CreateStackfieldTask.py — WSGI endpoint: create Stackfield task via REST API
  • python/POSTData.py + python/StdoutLogger.py — x0 helper modules
  • database/01-create-schema.sqlgithub2sf schema: credentials, app_config, issue_task_mapping tables (targets the x0 database)
  • database/02-insert-config.sql — x0 system.config rows for appid=github2sf (idempotent: DELETE + INSERT)
  • database/03-insert-text.sqlwebui.text entries in English and German for all UI labels (idempotent: ON CONFLICT (id) DO NOTHING)
  • docker/Dockerfile — extends ghcr.io/webcodex1/x0-app; installs Python deps; COPYs static/, python/, and apache2.conf into the image at build time
  • docker/Dockerfile.db — extends ghcr.io/webcodex1/x0-db; copies SQL scripts; overrides CMD with db-init.sh for automatic schema + data init on startup
  • docker/db-init.sh — starts PostgreSQL in background, waits for pg_isready, runs all three SQL scripts against the x0 database, then keeps the container alive
  • docker/docker-compose.yml — both services built from custom Dockerfiles; no volume mounts (all content baked in)
  • docker/apache2.confconf-enabled snippet granting Apache2 access to the github2sf static and WSGI paths
  • README.md — architecture, screen overview, and Docker quick-start documentation; ## Installation section removed (everything is automated)

Screen Overview

Screen 1 — User Credentials

Two sysObjectFormfieldList groups (GitHub + Stackfield), each with a Verify credentials button. On success the credentials are stored in the database.

Screen 2 — Issue / Task Mapping

Search sysObjectFormfieldList + search button (fires SearchGitHubIssues event) → ServiceConnectorsysObjectList with sysObjContextMenu entry Connect Stackfield Task (right-click → navigate to Screen 3, fire ConnectStackfieldTask event).

Screen 3 — Connect Stackfield Task

IssueDetailsConnector (ServiceConnector, listens to ConnectStackfieldTask) populates two sysObjectFormfieldList instances:

  • GitHub issue properties (read-only: number, state, title, URL)
  • Stackfield mapping fields (editable: room ID, task title, description, priority) — pre-populated from the issue data

sysObjButton Create New Stackfield Task calls the backend to POST to Stackfield's task API.


Container architecture

Both services use the official x0 container images as their base:

  • ghcr.io/webcodex1/x0-app — Apache2 + mod_wsgi with the x0 JavaScript framework pre-installed. The custom docker/Dockerfile copies all static JSON configs, Python WSGI scripts, and the Apache2 config snippet directly into the image at build time.
  • ghcr.io/webcodex1/x0-db — PostgreSQL 16 with the x0 schema pre-installed. The custom docker/Dockerfile.db bundles the database/0*.sql scripts and overrides the container CMD with docker/db-init.sh, which auto-initialises the github2sf schema and seed data in the x0 database on every container start (all scripts are idempotent).

python-micro-esb integration

GitHubService and StackfieldService both extend microesb.ClassHandler. Each WSGI endpoint constructs a ServiceRouter and calls router.send(routing_function, request_data), dispatching to the appropriate function in user_routing.py.

- static/menu.json: 3 navigation links (User Credentials, Issue/Task Mapping, Connect Stackfield Task)
- static/object.json: all x0 UI objects for 3 screens (formfields, lists, buttons, service connectors, context menu)
- static/skeleton.json: screen layout wiring objects to screens
- python/service_implementation.py: GitHubService + StackfieldService ClassHandlers (python-micro-esb)
- python/user_routing.py: ServiceRouter routing functions for all 5 backend operations
- python/VerifyGitHubCredentials.py: WSGI endpoint
- python/VerifyStackfieldCredentials.py: WSGI endpoint
- python/SearchGitHubIssues.py: WSGI endpoint – populates issue list
- python/GetGitHubIssueDetails.py: WSGI endpoint – pre-populates Screen 3
- python/CreateStackfieldTask.py: WSGI endpoint – creates Stackfield task
- python/POSTData.py + StdoutLogger.py: x0 helper modules
- database/01-create-schema.sql: github2sf schema, credentials + mapping tables
- database/02-insert-config.sql: x0 app configuration rows
- database/03-insert-text.sql: EN + DE UI text entries
- docker/Dockerfile + docker-compose.yml + apache2.conf: containerised deployment
- README.md: full setup and architecture documentation

Agent-Logs-Url: https://github.com/WEBcodeX1/github2stackfield/sessions/9b620d8f-bd1b-45df-84a8-b2f02204213e

Co-authored-by: clauspruefer <17313789+clauspruefer@users.noreply.github.com>
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The x0 application is a native javascript application, not a Python app.

# Install x0 framework Python modules	
RUN pip install --no-cache-dir \
    git+https://github.com/WEBcodeX1/x0.git

Use the official https://github.com/WEBcodeX1/x0/pkgs/container/x0-app and https://github.com/WEBcodeX1/x0/pkgs/container/x0-db instead.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

The x0 application is a native javascript application, not a Python app.

# Install x0 framework Python modules	...

Fixed in commit fix: use official ghcr.io/webcodex1/x0-app and x0-db container images.

Changes made:

  • docker/Dockerfile: Base image changed to ghcr.io/webcodex1/x0-app. Removed the incorrect pip install git+https://github.com/WEBcodeX1/x0.git (x0 is a native JavaScript framework, not a Python package). Also removed manual Apache2/mod_wsgi installation — those are already included in the official image. The Dockerfile now only adds our app-specific Python backend dependencies (requests, psycopg2-binary, pgdbpool, python-micro-esb) on top of the base image.
  • docker/docker-compose.yml: DB service now uses ghcr.io/webcodex1/x0-db. Network is configured as 172.20.0.0/24 with the db at 172.20.0.20 aliased as mypostgres (matching what the x0-app image expects). Volume mounts updated to /var/www/vhosts/x0/… to match the x0-app container's internal paths.
  • docker/apache2.conf: Rewritten as a conf-enabled snippet (no standalone VirtualHost). The x0-app base image already configures the Apache2 vhost; this file just grants directory access to the app-specific static and python paths.

Copilot AI requested a review from clauspruefer May 27, 2026 09:13
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Please ensure that everything is atomatically put inside the correct containers / databases so that the containers will be started and the application runs without the need of configuring anything. The database scripts /database/* must use the x0 database. Also check if all web-server content and web-server wsgi content is put at the correct location. Ensure that from README.md "## Installation" section everything will be put automatically in the correct container(s) and afterwards remove the section completely from the README.md.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot Please ensure that everything is atomatically put inside the correct containers / databases so that the containers will be started and the application runs without the need of configuring any...

Done in commit fix: automate full container self-initialisation; remove ## Installation from README.

  • docker/Dockerfile.db (new) — extends ghcr.io/webcodex1/x0-db, copies database/0*.sql into the image, and overrides the container's CMD with docker/db-init.sh.
  • docker/db-init.sh (new) — starts PostgreSQL in the background, waits for pg_isready, then runs all three SQL scripts against the x0 database as the postgres user via local socket (no password needed). All scripts are idempotent (IF NOT EXISTS in schema creation; DELETE + INSERT in config; ON CONFLICT (id) DO NOTHING added to every row in 03-insert-text.sql).
  • docker/Dockerfile — now COPYs static/, python/, and docker/apache2.conf directly into the image at build time; the volume mounts are gone.
  • docker/docker-compose.ymlx0-db now builds from docker/Dockerfile.db (context ..); all three volume mounts removed from x0-app.
  • README.md## Installation section removed; ## Prerequisites simplified to Docker + API tokens; ## Docker (quick start) updated to state that no further configuration is required after docker compose up --build.

Copilot AI requested a review from clauspruefer May 27, 2026 10:15
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot: 1. the following default stylesheets from the x0 base system are missing: bootstrap.css, all-min.css and globalstyles.css 2. The Python WSGI scripts are missing / not working (XHRPOST
http://127.0.0.1:8080/python/VerifyGitHubCredentials.py?a__=9216039810
[HTTP/1.1 404 Not Found 2ms])

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot: 1. the following default stylesheets from the x0 base system are missing: bootstrap.css, all-min.css and globalstyles.css 2. The Python WSGI scripts are missing / not working (XHRPOST
...

Fixed in commit fix: resolve missing stylesheets and WSGI 404 errors.

1. Missing stylesheetsdocker/Dockerfile now creates symlinks into the app's static subdir after copying static files:

RUN ln -s /var/www/vhosts/x0/static/bootstrap.css /var/www/vhosts/x0/static/github2sf/bootstrap.css \
    && ln -s /var/www/vhosts/x0/static/globalstyles.css /var/www/vhosts/x0/static/github2sf/globalstyles.css \
    && ln -s /var/www/vhosts/x0/static/fontawesome /var/www/vhosts/x0/static/github2sf/fontawesome

The x0 framework generates HTML <link> tags using the app's subdir prefix (/static/github2sf/), so these three resources must live inside that subdir. The symlinks point back to the base image's copies.

2. WSGI 404 — Two root causes, both fixed:

  • Wrong URL path in static/object.json: All 5 WSGI endpoint references were /python/XYZ.py; updated to /python/github2sf/XYZ.py to match where the Dockerfile copies the scripts.

  • Broken import + missing Python path in WSGI scripts: from router import ServiceRouter was incorrect — router is a submodule of the installed microesb package, not a top-level module. Changed to from microesb.router import ServiceRouter in all 5 scripts. Also added sys.path.insert(0, '/var/www/vhosts/x0/python/github2sf') before that import so that user_routing and service_implementation (which live in the app's python subdir, outside the global WSGIPythonPath) are importable at runtime when microesb.router calls importlib.import_module('user_routing').

Copilot AI requested a review from clauspruefer May 27, 2026 10:34
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the menu buttons currently are displayed side by side, the must be displayed among themselves.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot the menu buttons currently are displayed side by side, the must be displayed among themselves.

Fixed in commit fix: display menu buttons vertically (stacked) instead of side by side.

Changed the menu link styles in static/object.json from btn btn-outline-secondary me-2 (Bootstrap me-2 = margin-end, used for horizontal layouts) to btn btn-outline-secondary d-block mb-2. The d-block class forces each button to display as a block element so they stack vertically, and mb-2 adds bottom margin for spacing between them.

Copilot AI requested a review from clauspruefer May 27, 2026 10:49
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct the style for unsuccessful notifications, currently it is green with a black small exlamation mark (where it should be red), the icon also should be better fitted (e.g. with a circle border or similar). An successful notoification must be green with a green hook icon.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

Please correct the style for unsuccessful notifications, currently it is green with a black small exlamation mark (where it should be red), the icon also should be better fitted (e.g. with a circle bo...

Fixed in commit fix: correct notification styles for success (green check) and error (red circled exclamation).

The x0 framework's sysAsyncNotifyIndicatorItem.js applies the CSS classes IndicatorSuccess (success), IndicatorWarning (error), and IndicatorError (system error) to the notification card. These were previously undefined, so the base alert-success (green) showed for all states.

Changes made:

  • static/globalstyles.css (new) — app-specific global stylesheet that extends the x0 base styles with notification indicator overrides:
    • .IndicatorSuccess: keeps the green background (#d1e7dd) with green text/icon (#198754) — the fa-check icon displays as a clear green hook.
    • .IndicatorWarning: overrides to red (#f8d7da background, #58151c text), with the fa-exclamation icon enclosed in a circular red border (border-radius: 50%, border: 2px solid #dc3545).
    • .IndicatorError: amber/orange styling for system errors.
  • docker/Dockerfile — removed the globalstyles.css symlink to the x0 base file; the new static/globalstyles.css is already copied via COPY static/ /var/www/vhosts/x0/static/github2sf/ and includes all base x0 styles plus the indicator overrides.

Copilot AI requested a review from clauspruefer May 27, 2026 10:58
Copy link
Copy Markdown
Member

@clauspruefer clauspruefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not tested with correct credentials.

@clauspruefer clauspruefer marked this pull request as ready for review May 27, 2026 11:00
Copilot AI review requested due to automatic review settings May 27, 2026 11:00
@clauspruefer clauspruefer merged commit f016b4f into main May 27, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a complete github2stackfield x0 application stack (x0 UI + Python WSGI backend + PostgreSQL schema/seed + Docker packaging) to search GitHub issues and create Stackfield tasks from them.

Changes:

  • Added x0 UI configuration (menu, objects, skeleton) for 3 screens and their service connectors.
  • Added Python WSGI endpoints + python-micro-esb routing + service classes for GitHub/Stackfield API integration.
  • Added PostgreSQL schema + seed data and Docker images/compose to run the full stack with one command.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
static/skeleton.json Wires UI objects/connectors to Screen1–3 layouts.
static/object.json Defines x0 UI objects (forms, list, connectors, buttons) and field mappings.
static/menu.json Adds 3 navigation links for the three screens.
static/globalstyles.css Adds app-specific CSS overrides (incl. notification indicator styles).
README.md Documents architecture, screens, and Docker quick start for the new app.
python/VerifyStackfieldCredentials.py WSGI endpoint to verify Stackfield creds via router.
python/VerifyGitHubCredentials.py WSGI endpoint to verify GitHub creds via router.
python/user_routing.py micro-esb routing functions; DB credential persistence and orchestration.
python/StdoutLogger.py Logging setup for WSGI scripts.
python/service_implementation.py GitHub/Stackfield API client logic (verify/search/details/create).
python/SearchGitHubIssues.py WSGI endpoint for issue search list population.
python/POSTData.py Helper to read POST bodies from WSGI environ.
python/GetGitHubIssueDetails.py WSGI endpoint to fetch issue details for Screen3 population.
python/CreateStackfieldTask.py WSGI endpoint to create Stackfield tasks from Screen3 data.
docker/Dockerfile.db Builds a DB image that runs init SQL automatically on startup.
docker/Dockerfile Builds an app image bundling static configs + Python scripts + Apache conf.
docker/docker-compose.yml Compose stack for app + DB containers on a fixed bridge network.
docker/db-init.sh Custom DB entrypoint: starts Postgres, runs init SQL, keeps server alive.
docker/apache2.conf Apache snippet granting access to static and WSGI directories.
database/03-insert-text.sql Seeds i18n UI text labels (EN/DE) into webui.text.
database/02-insert-config.sql Seeds x0 system.config entries for appid=github2sf.
database/01-create-schema.sql Creates github2sf schema and tables for credentials/config/mapping log.
AI-prompt.md Captures the original build prompt/spec for the app.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/user_routing.py
Comment on lines +161 to +165
# Repo may be stored as a mapping state or passed via global var.
# Fall back to a stored repo config entry.
repo = metadata.get('repo', '')
if not repo:
with pool.Handler('x0') as db:
Comment thread python/user_routing.py
Comment on lines +207 to +210
svc.room_id = metadata.get('StackfieldRoomInput', '')
svc.task_title = metadata.get('TaskTitleInput', '')
svc.task_description = metadata.get('TaskDescInput', '')
svc.task_priority = metadata.get('TaskPriorityPulldown', 'medium')
Comment on lines +33 to +36
request_data = service_json.get('RequestData', {})

logger.debug('VerifyGitHubCredentials RequestData:{}'.format(request_data))

Comment on lines +33 to +36
request_data = service_json.get('RequestData', {})

logger.debug('VerifyStackfieldCredentials RequestData:{}'.format(request_data))

Comment thread python/user_routing.py
Comment on lines +79 to +83
logger.debug('user_routing.verify_github() metadata:{}'.format(metadata))

svc = GitHubService()
svc.github_user = metadata.get('GitHubUserInput', '')
svc.github_token = metadata.get('GitHubTokenInput', '')
Comment thread python/POSTData.py
class Environment:
@staticmethod
def getPOSTData(environ):
ContentLength = int(environ.get('CONTENT_LENGTH', 0))
Comment thread docker/Dockerfile
requests \
psycopg2-binary \
pgdbpool \
git+https://github.com/clauspruefer/python-micro-esb.git
Comment thread docker/docker-compose.yml
Comment on lines +14 to +16
ports:
- "5432:5432"
networks:
Comment on lines +16 to +21
CREATE TABLE IF NOT EXISTS github2sf.credentials (
credential_type VARCHAR(20) NOT NULL,
username_or_email TEXT NOT NULL,
api_token TEXT NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
CONSTRAINT pk_credentials PRIMARY KEY (credential_type)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants