fix: add basic support for install/setup of terminal
only if installing alongside existing server app; can improve later
This commit is contained in:
parent
d6c1e688b1
commit
7225d6b453
6 changed files with 206 additions and 19 deletions
|
|
@ -9,7 +9,7 @@ For now this only describes a *development* setup, which assumes the following:
|
|||
* Python 3.11 or newer
|
||||
* database in PostgreSQL or MySQL
|
||||
|
||||
These steps will setup both the server and terminal in a shared
|
||||
These steps will setup both the Server and Terminal in a shared
|
||||
virtual environment.
|
||||
|
||||
|
||||
|
|
@ -40,13 +40,13 @@ Install Server
|
|||
|
||||
**Please note, you must create your database before running the installer.**
|
||||
|
||||
Run the WuttaPOS installer to setup the server app:
|
||||
Run the WuttaPOS installer to setup the Server app:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
bin/wuttapos install
|
||||
|
||||
Now you can run the server app via command line:
|
||||
Now you can run the Server app via command line:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
|
|
@ -86,4 +86,48 @@ should be improved - but that will come later.
|
|||
Install Terminal
|
||||
----------------
|
||||
|
||||
TODO: this is not yet documented
|
||||
**Please note, this assumes you already installed the Server as described above.**
|
||||
|
||||
For now, we'll just install the Terminal alongside the Server. They
|
||||
will share the same virtual environment, installed code, app database,
|
||||
and "most of" the config files.
|
||||
|
||||
So within your virtual environment, run the same installer again:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
bin/wuttapos install
|
||||
|
||||
.. note::
|
||||
|
||||
You will be asked for store and terminal IDs - these should be
|
||||
valid and refer to actual records for those types, within the
|
||||
database. See the Admin menu of the Server web app to manage those
|
||||
records.
|
||||
|
||||
At this point the Terminal app should be ready to go. To run the
|
||||
standalone GUI:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
bin/wuttapos -c app/terminal.conf run
|
||||
|
||||
You will need to login; the POS uses a special set of permissions but
|
||||
the first admin user should already have all that are needed. So just
|
||||
login using same credentials as for the Server app.
|
||||
|
||||
It's also possible (due to the magic of Flet/Flutter) to *serve* the
|
||||
Terminal as a web app:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
bin/wuttapos -c app/terminal.conf serve
|
||||
|
||||
In that case (by default) you can browse it at http://localhost:8332
|
||||
|
||||
That might be useful for online demo purposes etc. but definitely the
|
||||
intention is to run as standalone GUI for production. (However the
|
||||
story around tablets is TBD.)
|
||||
|
||||
For now, running as a web service like that is not a supported
|
||||
feature.
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ classifiers = [
|
|||
]
|
||||
dependencies = [
|
||||
"psycopg2",
|
||||
"WuttJamaican[db]>=0.28.2",
|
||||
"WuttJamaican[db]>=0.28.4",
|
||||
"WuttaSync",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
See also: :ref:`wuttapos-run`
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import typer
|
||||
|
||||
from wuttapos.cli import wuttapos_typer
|
||||
|
|
@ -37,4 +39,11 @@ def run(ctx: typer.Context):
|
|||
from wuttapos.terminal.app import run_app
|
||||
|
||||
config = ctx.parent.wutta_config
|
||||
run_app(config)
|
||||
|
||||
# nb. it does not seem possible (?) to inject our config when
|
||||
# launching the Flet app, which means it will create a *separate*
|
||||
# config for itself..this should ensure it has the right settings.
|
||||
# see also notes in wuttapos.terminal.app module, for run_app()
|
||||
os.environ["WUTTA_CONFIG_FILES"] = os.pathsep.join(config.get_prioritized_files())
|
||||
|
||||
run_app()
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
Install handler for WuttaPOS
|
||||
"""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
|
@ -37,14 +38,62 @@ class InstallHandler(base.InstallHandler):
|
|||
|
||||
template_paths = ["wuttapos:installer-templates"]
|
||||
|
||||
store_id = None
|
||||
terminal_id = None
|
||||
alongside = False
|
||||
|
||||
def do_install_steps(self):
|
||||
|
||||
# prompt for install type first
|
||||
self.get_install_type()
|
||||
|
||||
# install server/terminal dependencies
|
||||
self.install_app_deps()
|
||||
|
||||
# then everything else
|
||||
super().do_install_steps()
|
||||
|
||||
def sanity_check(self):
|
||||
"""
|
||||
We override this because the normal up-front sanity check
|
||||
includes a check for the app dir. But we need to delay that
|
||||
one a bit, so behavior depends on which "install type" we're
|
||||
doing.
|
||||
"""
|
||||
|
||||
def check_appdir(self):
|
||||
"""
|
||||
We bypass the normal check here, if the current install is for
|
||||
terminal alongside server.
|
||||
"""
|
||||
if self.install_type == "terminal":
|
||||
|
||||
# does appdir exist yet?
|
||||
appdir = os.path.join(sys.prefix, "app")
|
||||
if os.path.exists(appdir):
|
||||
|
||||
# install alongside server?
|
||||
self.alongside = self.prompt_bool(
|
||||
"install alongside server?", default=False
|
||||
)
|
||||
if self.alongside:
|
||||
# this mode expects the appdir to exist, so continue
|
||||
return
|
||||
|
||||
else:
|
||||
# no appdir - means we should install "everything" for
|
||||
# the terminal, but we don't support that yet
|
||||
self.rprint(
|
||||
f"\n\t[bold red]sorry, full terminal install not yet supported[/bold red]\n"
|
||||
)
|
||||
self.rprint(
|
||||
f"\n\tPlease install the server, then terminal alongside that.\n"
|
||||
)
|
||||
sys.exit(2)
|
||||
|
||||
# do normal check
|
||||
super().check_appdir()
|
||||
|
||||
def get_install_type(self):
|
||||
|
||||
# prompt user
|
||||
|
|
@ -55,22 +104,88 @@ class InstallHandler(base.InstallHandler):
|
|||
# remember the answer
|
||||
self.install_type = install_type
|
||||
|
||||
if self.install_type != "server":
|
||||
self.rprint(
|
||||
"[bold red]sorry, terminal install is not yet implemented[/bold red]\n"
|
||||
)
|
||||
sys.exit(1)
|
||||
# now we can check the app dir; do this before further questions
|
||||
self.check_appdir()
|
||||
|
||||
# install dependencies
|
||||
# stop here for server, but we have more questions for terminal
|
||||
if self.install_type == "server":
|
||||
self.install_server_deps()
|
||||
return
|
||||
|
||||
def install_server_deps(self):
|
||||
subprocess.check_call(
|
||||
[sys.executable, "-m", "pip", "install", "WuttaPOS[server]"]
|
||||
self.rprint(
|
||||
"\n\n\t[blue]Next you must specify the Store and Terminal IDs.[/blue]"
|
||||
)
|
||||
self.rprint(
|
||||
"\n\tThese should match records in your DB; see the Server app for info.\n"
|
||||
)
|
||||
|
||||
# store_id
|
||||
while not self.store_id:
|
||||
self.store_id = self.prompt_generic("Store ID")
|
||||
|
||||
# terminal_id
|
||||
while not self.terminal_id:
|
||||
self.terminal_id = self.prompt_generic("Terminal ID")
|
||||
|
||||
def install_app_deps(self):
|
||||
|
||||
if self.install_type == "server":
|
||||
subprocess.check_call(
|
||||
[sys.executable, "-m", "pip", "install", "WuttaPOS[server]"]
|
||||
)
|
||||
|
||||
elif self.install_type == "terminal":
|
||||
subprocess.check_call(
|
||||
[sys.executable, "-m", "pip", "install", "WuttaPOS[terminal]"]
|
||||
)
|
||||
|
||||
def get_dbinfo(self):
|
||||
if self.alongside:
|
||||
return {"dburl": self.config.appdb_engine.url}
|
||||
|
||||
return super().get_dbinfo()
|
||||
|
||||
def make_template_context(self, dbinfo, **kwargs):
|
||||
context = super().make_template_context(dbinfo, **kwargs)
|
||||
|
||||
context["install_type"] = self.install_type
|
||||
context["store_id"] = self.store_id
|
||||
context["terminal_id"] = self.terminal_id
|
||||
|
||||
return context
|
||||
|
||||
def write_all_config_files(self, appdir, context):
|
||||
if self.alongside:
|
||||
# just want to add terminal.conf for this mode
|
||||
self.write_terminal_conf(appdir, context)
|
||||
return
|
||||
|
||||
# new app, so write normal files
|
||||
super().write_all_config_files(appdir, context)
|
||||
|
||||
def write_terminal_conf(self, appdir, context):
|
||||
term_context = dict(context)
|
||||
self.make_config_file(
|
||||
"terminal.conf.mako", os.path.join(appdir, "terminal.conf"), **term_context
|
||||
)
|
||||
|
||||
def install_db_schema(self, db_url, appdir=None):
|
||||
if self.alongside:
|
||||
# no need to install schema here
|
||||
return False
|
||||
|
||||
return super().install_db_schema(db_url, appdir=appdir)
|
||||
|
||||
def show_goodbye(self):
|
||||
"""
|
||||
Show the final message; this assumes setup completed okay.
|
||||
|
||||
This is normally called by :meth:`run()`.
|
||||
"""
|
||||
if self.alongside:
|
||||
self.rprint("\n\t[bold green]initial setup is complete![/bold green]")
|
||||
self.rprint("\n\tyou can run the terminal GUI app with:")
|
||||
self.rprint(f"\n\t[blue]cd {sys.prefix}[/blue]")
|
||||
self.rprint("\t[blue]bin/wuttapos -c app/terminal.conf run[/blue]\n")
|
||||
return
|
||||
|
||||
super().show_goodbye()
|
||||
|
|
|
|||
17
src/wuttapos/installer-templates/terminal.conf.mako
Normal file
17
src/wuttapos/installer-templates/terminal.conf.mako
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
## -*- mode: conf; -*-
|
||||
|
||||
<%text>############################################################</%text>
|
||||
#
|
||||
# ${app_title} - terminal installed alongside the server
|
||||
#
|
||||
<%text>############################################################</%text>
|
||||
|
||||
[wutta.config]
|
||||
require = %(here)s/wutta.conf
|
||||
|
||||
[wuttapos]
|
||||
store_id = ${store_id}
|
||||
terminal_id = ${terminal_id}
|
||||
|
||||
[wutta_continuum]
|
||||
enable_versioning = false
|
||||
|
|
@ -282,9 +282,11 @@ def main(page: ft.Page):
|
|||
page.go("/login")
|
||||
|
||||
|
||||
# TODO: can we inject config to the main() via ft.app() kwargs somehow?
|
||||
# pretty sure the `wuttapos open` command is trying to anyway..
|
||||
def run_app(config=None):
|
||||
# TODO: is there any way to inject a config object into the new Flet
|
||||
# app? if so this would be the place to do it. currently in main()
|
||||
# it always makes a new config for itself, as workaround. but also
|
||||
# see notes in the wuttapos.cli.run module
|
||||
def run_app():
|
||||
ft.app(target=main, assets_dir=resource_path("wuttapos.terminal:assets"))
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue