[IMP] todo: menu sections, icons and prompts
Groups the long menus into sections with icons, accepts o/oui everywhere, shows the default of each yes/no question, and stops offering a traceback line as a database name when PostgreSQL is unreachable. --- FR --- Regroupe les menus longs en sections avec icônes, accepte o/oui partout, affiche la valeur par défaut de chaque question oui/non, et cesse de proposer une ligne de trace d'appel comme nom de base quand PostgreSQL est injoignable. Assisted-by: Claude Opus 4.8 Assisted-by: Claude Opus 5
This commit is contained in:
parent
1208c919a1
commit
67e902e416
3 changed files with 710 additions and 8 deletions
|
|
@ -31,28 +31,51 @@ class DatabaseManager:
|
|||
self._dir_path = path
|
||||
|
||||
def select_database(self) -> str | bool:
|
||||
"""Faire choisir une base parmi celles que PostgreSQL expose.
|
||||
|
||||
Le code de retour de « db --list » est vérifié AVANT de construire le
|
||||
menu. Sans cette vérification, un PostgreSQL injoignable ne se distingue
|
||||
pas d'une base absente : la sortie et l'erreur sont fusionnées dans le
|
||||
même flux (`stderr=STDOUT`, execute.py), donc les lignes de la trace
|
||||
d'appel devenaient les entrées du menu. « Traceback (most recent call
|
||||
last): » s'affichait comme la base [1], et la choisir renvoyait cette
|
||||
ligne comme nom de base à l'appelant, qui la passait à sa commande.
|
||||
"""
|
||||
cmd_server = "./odoo_bin.sh db --list"
|
||||
status, databases = self._execute.exec_command_live(
|
||||
status, output = self._execute.exec_command_live(
|
||||
cmd_server,
|
||||
return_status_and_output=True,
|
||||
quiet=True,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=True,
|
||||
)
|
||||
choices = [{"prompt_description": a.strip()} for a in databases]
|
||||
if status:
|
||||
print(f"❌ {t('Cannot list the databases (exit code): ')}{status}")
|
||||
print(f" {t('Is PostgreSQL running?')}")
|
||||
for line in output[-5:]:
|
||||
print(f" {line}")
|
||||
return False
|
||||
|
||||
databases = [a.strip() for a in output if a.strip()]
|
||||
if not databases:
|
||||
print(f"ℹ️ {t('No database on this PostgreSQL server.')}")
|
||||
return False
|
||||
|
||||
choices = [{"prompt_description": a} for a in databases]
|
||||
help_info = self._fill_help_info(choices)
|
||||
valid_choices = [str(a) for a in range(len(choices) + 1) if a]
|
||||
valid_choices = [str(a + 1) for a in range(len(databases))]
|
||||
|
||||
while True:
|
||||
status = click.prompt(help_info)
|
||||
answer = click.prompt(help_info)
|
||||
print()
|
||||
if status == "0":
|
||||
if answer == "0":
|
||||
return False
|
||||
elif status in valid_choices:
|
||||
database_name = databases[int(status) - 1].strip()
|
||||
elif answer in valid_choices:
|
||||
database_name = databases[int(answer) - 1]
|
||||
print(database_name)
|
||||
return database_name
|
||||
else:
|
||||
print(t("cmd_not_found"))
|
||||
print(t("Command not found !"))
|
||||
|
||||
def _confirm_drop(self, message: str) -> bool:
|
||||
"""Ask for an explicit 'oui'/'yes' confirmation, default is no."""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import ast
|
|||
import configparser
|
||||
import datetime
|
||||
import getpass
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
|
|
@ -173,6 +174,34 @@ class TODO:
|
|||
print(t("Command not found !"))
|
||||
|
||||
print(status)
|
||||
# manipuler()
|
||||
|
||||
def execute_prompt_ia(self):
|
||||
while True:
|
||||
help_info = f"""{self._menu_header()}
|
||||
[0] {t("Back")}
|
||||
{t("Write your question ")}"""
|
||||
status = click.prompt(help_info)
|
||||
print()
|
||||
if status == "0":
|
||||
return
|
||||
kp = self.kdbx_manager.get_kdbx()
|
||||
if not kp:
|
||||
return
|
||||
config_name = self.config_file.get_config_value(
|
||||
["kdbx_config", "openai", "kdbx_key"]
|
||||
)
|
||||
entry = kp.find_entries_by_title(config_name, first=True)
|
||||
|
||||
client = openai.OpenAI(api_key=entry.password)
|
||||
prompt_update = status
|
||||
completion = client.chat.completions.create(
|
||||
model="gpt-4o",
|
||||
messages=[{"role": "user", "content": prompt_update}],
|
||||
)
|
||||
|
||||
print(completion.choices[0].message.content)
|
||||
print()
|
||||
|
||||
def prompt_execute(self):
|
||||
help_info = f"""{self._menu_header()}
|
||||
|
|
@ -268,6 +297,184 @@ class TODO:
|
|||
else:
|
||||
print(t("Command not found !"))
|
||||
|
||||
def prompt_install(self):
|
||||
print("Detect first installation from code source.")
|
||||
|
||||
first_installation_input = (
|
||||
input(
|
||||
"💬 First system installation? This will process system installation"
|
||||
" before (Y/N): "
|
||||
)
|
||||
.strip()
|
||||
.lower()
|
||||
)
|
||||
if self._is_yes(first_installation_input):
|
||||
cmd = "./script/version/update_env_version.py --install"
|
||||
self.execute.exec_command_live(cmd, source_erplibre=True)
|
||||
print("Wait after OS installation before continue.")
|
||||
|
||||
# First detect pycharm, need to be open before installation and close to increase speed
|
||||
has_pycharm = False
|
||||
has_pycharm_community = False
|
||||
result = subprocess.run(
|
||||
["which", "pycharm"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
has_pycharm = True
|
||||
else:
|
||||
result = subprocess.run(
|
||||
["which", "pycharm-community"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
)
|
||||
has_pycharm_community = result.returncode == 0
|
||||
if (has_pycharm or has_pycharm_community) and not os.path.exists(
|
||||
".idea"
|
||||
):
|
||||
pycharm_configuration_input = (
|
||||
input("💬 Open Pycharm? (Y/N): ").strip().lower()
|
||||
)
|
||||
if self._is_yes(pycharm_configuration_input):
|
||||
pycharm_bin = "pycharm" if has_pycharm else "pycharm-community"
|
||||
|
||||
cmd = f"cd {os.getcwd()} && {pycharm_bin} ./"
|
||||
self.execute.exec_command_live(
|
||||
cmd,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=False,
|
||||
new_window=True,
|
||||
)
|
||||
print(
|
||||
"👹 WAIT and Close Pycharm when processing is done before continue"
|
||||
" this guide."
|
||||
)
|
||||
# TODO detect last version supported
|
||||
# cmd_intern = "./script/install/install_erplibre.sh"
|
||||
# TODO maybe update q to only install erplibre from install_locally
|
||||
# TODO problem installing with q, the script depend on odoo
|
||||
key_i = 0
|
||||
commands_begin = {
|
||||
"q": (
|
||||
"q",
|
||||
"q: ERPLibre only with system python without Odoo",
|
||||
"./script/install/install_erplibre.sh",
|
||||
),
|
||||
"w": (
|
||||
"w",
|
||||
"w: Install all Odoo version with ERPLibre",
|
||||
"make install_odoo_all_version",
|
||||
),
|
||||
"m": (
|
||||
"m",
|
||||
"m: ERPLibre with mobile home",
|
||||
"./mobile/install_and_run.sh",
|
||||
),
|
||||
"0": (
|
||||
"0",
|
||||
f"0: {t('Quit')}",
|
||||
),
|
||||
}
|
||||
commands_end = {}
|
||||
versions, installed_versions, odoo_installed_version = (
|
||||
get_odoo_version()
|
||||
)
|
||||
|
||||
for version_info in versions[::-1]:
|
||||
key_i += 1
|
||||
key_s = str(key_i)
|
||||
label = f"{key_s}: Odoo {version_info.get('odoo_version')}"
|
||||
|
||||
odoo_version = f"odoo{version_info.get('odoo_version')}"
|
||||
if odoo_version in installed_versions:
|
||||
label += " - Installed"
|
||||
if odoo_version == odoo_installed_version:
|
||||
label += " - Actual"
|
||||
if version_info.get("Default"):
|
||||
label += " - Default"
|
||||
if version_info.get("is_deprecated"):
|
||||
label += " - Deprecated"
|
||||
erplibre_version = version_info.get("erplibre_version")
|
||||
commands_begin[key_s] = (
|
||||
key_s,
|
||||
label,
|
||||
f"./script/version/update_env_version.py --erplibre_version {erplibre_version} --install_dev",
|
||||
)
|
||||
|
||||
# Add final command
|
||||
install_commands = {**commands_begin, **commands_end}
|
||||
|
||||
# Show command
|
||||
odoo_version_input = ""
|
||||
while odoo_version_input not in install_commands:
|
||||
if odoo_version_input:
|
||||
print(
|
||||
f"{t('Error, cannot understand value')} '{odoo_version_input}'"
|
||||
)
|
||||
str_input_dyn_odoo_version = (
|
||||
f"💬 {t('Choose a version:')}\n\t"
|
||||
+ "\n\t".join([a[1] for a in install_commands.values()])
|
||||
+ f"\n{t('Select: ')}"
|
||||
)
|
||||
odoo_version_input = (
|
||||
input(str_input_dyn_odoo_version).strip().lower()
|
||||
)
|
||||
|
||||
if odoo_version_input == "0":
|
||||
return
|
||||
|
||||
cmd_intern = install_commands.get(odoo_version_input)[2]
|
||||
|
||||
# For numbered version selections, offer extra modules sub-menu
|
||||
if odoo_version_input.isdigit():
|
||||
extra_choices = {
|
||||
"1": (
|
||||
"1",
|
||||
f"1: {t('Standard install (without extra modules)')}",
|
||||
),
|
||||
"2": (
|
||||
"2",
|
||||
f"2: {t('Install with extra modules (CybroOdoo - large, slow)')}",
|
||||
),
|
||||
"0": ("0", f"0: {t('Back')}"),
|
||||
}
|
||||
extra_input = ""
|
||||
while extra_input not in extra_choices:
|
||||
if extra_input:
|
||||
print(
|
||||
f"{t('Error, cannot understand value')} '{extra_input}'"
|
||||
)
|
||||
str_extra = (
|
||||
f"💬 {t('Install type:')}\n\t"
|
||||
+ "\n\t".join([a[1] for a in extra_choices.values()])
|
||||
+ f"\n{t('Select: ')}"
|
||||
)
|
||||
extra_input = input(str_extra).strip()
|
||||
if extra_input == "0":
|
||||
return
|
||||
if extra_input == "2":
|
||||
cmd_intern = cmd_intern + " --with_extra"
|
||||
|
||||
print(f"{t('Will execute:')}\n{cmd_intern}")
|
||||
|
||||
# TODO use external script to detect terminal to use on system
|
||||
# TODO check script open_terminal_code_generator.sh
|
||||
# cmd_extern = f"gnome-terminal -- bash -c '{cmd_intern};bash'"
|
||||
try:
|
||||
subprocess.run(
|
||||
cmd_intern, shell=True, executable="/bin/bash", check=True
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(
|
||||
f"{t('The Bash script failed with return code')} {e.returncode}."
|
||||
)
|
||||
print("Wait after installation and open projects by terminal.")
|
||||
print("make open_terminal")
|
||||
self.restart_script(str(e))
|
||||
|
||||
def execute_from_configuration(
|
||||
self, instance, exec_run_db=False, ignore_makefile=False
|
||||
):
|
||||
|
|
@ -5750,6 +5957,76 @@ class TODO:
|
|||
cmd, source_erplibre=False, single_source_erplibre=True
|
||||
)
|
||||
|
||||
def prompt_execute_code(self):
|
||||
print(f"🤖 {t('What do you need for development?')}")
|
||||
# help_info = """Commande :
|
||||
# [1] Status Git local et distant
|
||||
# [2] Démarrer le générateur de code
|
||||
# [3] Format - Formatage automatique selon changement [ou manuelle]
|
||||
# [4] Qualité - Qualité logiciel, détecter les fichiers qui manquent les licences AGPLv3
|
||||
# [0] Retour
|
||||
# """
|
||||
# help_info = """Commande :
|
||||
# [1] Status Git local et distant
|
||||
# [0] Retour
|
||||
# """
|
||||
|
||||
choices = self.config_file.get_config("code_from_makefile")
|
||||
|
||||
menu_entry = {
|
||||
"prompt_description": t("Open SHELL"),
|
||||
}
|
||||
choices.append(menu_entry)
|
||||
|
||||
menu_entry = {
|
||||
"prompt_description": t("Upgrade Module"),
|
||||
}
|
||||
choices.append(menu_entry)
|
||||
|
||||
choices.append(
|
||||
{
|
||||
"prompt_description": t("Debug"),
|
||||
}
|
||||
)
|
||||
|
||||
# Déplacé depuis le menu Execute : mise à jour de tout le code source
|
||||
# de dev en staging (sous-menu de mise à jour).
|
||||
choices.append(
|
||||
{
|
||||
"prompt_description": t(
|
||||
"Update - Update all developed staging source code"
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
help_info = self.fill_help_info(choices)
|
||||
|
||||
while True:
|
||||
status = click.prompt(help_info)
|
||||
print()
|
||||
if status == "0":
|
||||
return False
|
||||
elif status == str(len(choices)):
|
||||
self.prompt_execute_update()
|
||||
elif status == str(len(choices) - 1):
|
||||
self.debug_ide()
|
||||
elif status == str(len(choices) - 2):
|
||||
self.upgrade_module()
|
||||
elif status == str(len(choices) - 3):
|
||||
self.open_shell_on_database()
|
||||
else:
|
||||
cmd_no_found = True
|
||||
try:
|
||||
int_cmd = int(status)
|
||||
if 0 < int_cmd <= len(choices):
|
||||
cmd_no_found = False
|
||||
instance = choices[int_cmd - 1]
|
||||
self.execute_from_configuration(instance)
|
||||
except ValueError:
|
||||
pass
|
||||
if cmd_no_found:
|
||||
print(t("Command not found !"))
|
||||
|
||||
def prompt_execute_git(self):
|
||||
print(f"🤖 {t('Git management tools!')}")
|
||||
choices = [
|
||||
|
|
@ -5987,6 +6264,44 @@ class TODO:
|
|||
print("-" * 50)
|
||||
print(f"{t('Total:')}" f" {len(files)}")
|
||||
|
||||
def _setup_claude_command(
|
||||
self, command_name, template_filename, personalize=False
|
||||
):
|
||||
dest_dir = os.path.expanduser("~/.claude/commands")
|
||||
dest_file = os.path.join(dest_dir, f"{command_name}.md")
|
||||
|
||||
if os.path.exists(dest_file):
|
||||
print(f"{t('File already exists: ')}{dest_file}")
|
||||
overwrite = input(t("Do you want to overwrite the file? (y/Y): "))
|
||||
if not self._is_yes(overwrite):
|
||||
print(t("Nothing to do."))
|
||||
return
|
||||
|
||||
template_path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
"..",
|
||||
"..",
|
||||
"conf",
|
||||
template_filename,
|
||||
)
|
||||
try:
|
||||
with open(template_path) as f:
|
||||
content = f.read()
|
||||
|
||||
if personalize:
|
||||
name = input(t("Enter your full name: ")).strip()
|
||||
email = input(t("Enter your email: ")).strip()
|
||||
content = content.replace("your@email.com", email)
|
||||
content = content.replace("Your Name", name)
|
||||
|
||||
os.makedirs(dest_dir, exist_ok=True)
|
||||
with open(dest_file, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
print(f"{t('File created successfully: ')}{dest_file}")
|
||||
except Exception as e:
|
||||
print(f"{t('Error creating file: ')}{e}")
|
||||
|
||||
def _claude_add_automation(self):
|
||||
description = input(t("Description of the command to add: ")).strip()
|
||||
if not description:
|
||||
|
|
@ -6371,6 +6686,95 @@ class TODO:
|
|||
else:
|
||||
print(t("Command not found !"))
|
||||
|
||||
def execute_test_module(self, coverage=False):
|
||||
# Module name
|
||||
module_name = input(t("Module name to test: ")).strip()
|
||||
if not module_name:
|
||||
print(t("Module name is required!"))
|
||||
return
|
||||
|
||||
# Database name
|
||||
db_name = input(
|
||||
t("Temporary database name (default: test_todo_tmp): ")
|
||||
).strip()
|
||||
if not db_name:
|
||||
db_name = "test_todo_tmp"
|
||||
|
||||
# Extra modules
|
||||
extra_modules = input(
|
||||
t("Extra modules to install (comma-separated, empty for none): ")
|
||||
).strip()
|
||||
|
||||
# Log level
|
||||
log_level = input(t("Log level (default: test): ")).strip()
|
||||
if not log_level:
|
||||
log_level = "test"
|
||||
|
||||
# Build module list
|
||||
modules_to_install = module_name
|
||||
if extra_modules:
|
||||
modules_to_install += f",{extra_modules}"
|
||||
|
||||
# Step 1: Create temp DB
|
||||
print(f"\n--- {t('Creating temporary database')} '{db_name}' ---")
|
||||
cmd_restore = f"./script/database/db_restore.py --database {db_name}"
|
||||
self.execute.exec_command_live(
|
||||
cmd_restore,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=True,
|
||||
)
|
||||
|
||||
# Step 2: Install modules
|
||||
print(f"\n--- {t('Installing modules')}: {modules_to_install} ---")
|
||||
cmd_install = (
|
||||
f"./script/addons/install_addons.sh"
|
||||
f" {db_name} {modules_to_install}"
|
||||
)
|
||||
self.execute.exec_command_live(
|
||||
cmd_install,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=True,
|
||||
)
|
||||
|
||||
# Step 3: Run tests
|
||||
print(f"\n--- {t('Running tests')}: {module_name} ---")
|
||||
cmd_test = (
|
||||
f"ODOO_MODE_TEST=true"
|
||||
f" ./run.sh"
|
||||
f" -d {db_name}"
|
||||
f" -u {module_name}"
|
||||
f" --log-level={log_level}"
|
||||
)
|
||||
if coverage:
|
||||
cmd_test = f"ODOO_MODE_COVERAGE=true {cmd_test}"
|
||||
status_code, output = self.execute.exec_command_live(
|
||||
cmd_test,
|
||||
return_status_and_output=True,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=True,
|
||||
)
|
||||
|
||||
if status_code == 0:
|
||||
print(f"\n✅ {t('Tests completed successfully!')}")
|
||||
else:
|
||||
print(f"\n❌ {t('Tests failed with return code')} {status_code}")
|
||||
|
||||
# Step 4: Cleanup
|
||||
keep_input = input(t("Keep the temporary database? (y/N): "))
|
||||
keep = self._is_yes(keep_input)
|
||||
if keep:
|
||||
print(f"{t('Database kept')}: {db_name}")
|
||||
else:
|
||||
print(
|
||||
f"\n--- {t('Cleaning up temporary database')} '{db_name}' ---"
|
||||
)
|
||||
cmd_drop = f"./odoo_bin.sh db --drop --database {db_name}"
|
||||
self.execute.exec_command_live(
|
||||
cmd_drop,
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=True,
|
||||
)
|
||||
|
||||
def execute_unit_tests(self):
|
||||
print(f"\n--- {t('Running unit tests')} ---")
|
||||
cmd = (
|
||||
|
|
@ -6672,6 +7076,50 @@ class TODO:
|
|||
upgrade = todo_upgrade.TodoUpgrade(self)
|
||||
upgrade.execute_module_upgrade()
|
||||
|
||||
def upgrade_poetry(self):
|
||||
# Only show the version to the user
|
||||
status = self.execute.exec_command_live(
|
||||
f"make version",
|
||||
source_erplibre=False,
|
||||
)
|
||||
# TODO maybe autodetect to update it
|
||||
git_repo_update_input = input(
|
||||
"💬 Would you like to fetch all your git repositories, you need it (y/Y) : "
|
||||
)
|
||||
if self._is_yes(git_repo_update_input):
|
||||
status = self.execute.exec_command_live(
|
||||
f"./script/manifest/update_manifest_local_dev.sh",
|
||||
source_erplibre=False,
|
||||
)
|
||||
|
||||
poetry_lock = "./poetry.lock"
|
||||
try:
|
||||
os.remove(poetry_lock)
|
||||
except Exception as e:
|
||||
pass
|
||||
odoo_long_version = ""
|
||||
if os.path.exists("./.erplibre-version"):
|
||||
with open("./.erplibre-version") as f:
|
||||
odoo_long_version = f.read()
|
||||
path_file_odoo_lock = f"./requirement/poetry.{odoo_long_version}.lock"
|
||||
if odoo_long_version:
|
||||
try:
|
||||
os.remove(path_file_odoo_lock)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
status = self.execute.exec_command_live(
|
||||
f"pip install -r requirement/erplibre_require-ments-poetry.txt && "
|
||||
f"./script/poetry/poetry_update.py -f",
|
||||
source_erplibre=False,
|
||||
single_source_erplibre=False,
|
||||
single_source_odoo=True,
|
||||
source_odoo=odoo_long_version,
|
||||
)
|
||||
|
||||
if os.path.exists(poetry_lock):
|
||||
shutil.copy2(poetry_lock, path_file_odoo_lock)
|
||||
|
||||
def callback_execute_custom_database(self, config):
|
||||
database_name = self.db_manager.select_database()
|
||||
self.prompt_execute_selenium_and_run_db(database_name)
|
||||
|
|
@ -6719,6 +7167,128 @@ class TODO:
|
|||
self.dir_path = dir_path
|
||||
todo_file_browser.exit_program()
|
||||
|
||||
def callback_make_mobile_home(self, config):
|
||||
# Read file
|
||||
default_project_name = "ERPLibre"
|
||||
default_package_name = "ca.erplibre.home"
|
||||
# Read default information
|
||||
if os.path.exists(STRINGS_FILE):
|
||||
tree = ET.parse(STRINGS_FILE)
|
||||
root = tree.getroot()
|
||||
for elem in root.findall("string"):
|
||||
if elem.get("name") == "app_name":
|
||||
default_project_name = elem.text
|
||||
if elem.get("name") == "package_name":
|
||||
default_package_name = elem.text
|
||||
|
||||
default_project_url_name = "https://erplibre.ca"
|
||||
# Read default information
|
||||
dotenv_file = dotenv.find_dotenv(
|
||||
filename=os.path.join(MOBILE_HOME_PATH, "src", ".env.production")
|
||||
)
|
||||
default_project_url_name = dotenv.get_key(
|
||||
dotenv_file, "VITE_WEBSITE_URL"
|
||||
)
|
||||
default_project_note_subject = dotenv.get_key(
|
||||
dotenv_file, "VITE_LABEL_NOTE"
|
||||
)
|
||||
|
||||
default_debug = False
|
||||
project_name = default_project_name
|
||||
project_url_name = default_project_url_name
|
||||
project_principal_subject = default_project_note_subject
|
||||
package_name = default_package_name
|
||||
do_debug = default_debug
|
||||
do_change_picture_menu = False
|
||||
|
||||
do_personalize = input(
|
||||
"Do you want to personalize the mobile application (Y) : "
|
||||
)
|
||||
if self._is_yes(do_personalize):
|
||||
project_name = (
|
||||
input(
|
||||
f'Your project name (Separate by space in title), default "{default_project_name}" : '
|
||||
).strip()
|
||||
or default_project_name
|
||||
)
|
||||
package_name = (
|
||||
input(
|
||||
f'Your package name (separate by . lower case, 3 works like DOMAIN.NAME.OBJECT), default "{default_package_name}" : '
|
||||
).strip()
|
||||
or default_package_name
|
||||
)
|
||||
project_url_name = (
|
||||
input(
|
||||
f'Your project url website, default "{default_project_url_name}" : '
|
||||
).strip()
|
||||
or default_project_url_name
|
||||
)
|
||||
project_principal_subject = (
|
||||
input(
|
||||
f'Your project subject, default "{default_project_note_subject}" : '
|
||||
).strip()
|
||||
or default_project_note_subject
|
||||
)
|
||||
do_debug = self._is_yes(
|
||||
input("Compilation with debug information, default No (Y) : ")
|
||||
)
|
||||
do_change_picture_menu = self._is_yes(
|
||||
input(
|
||||
"Want to change picture from menu, you need"
|
||||
" android-studio (Y) : "
|
||||
)
|
||||
)
|
||||
|
||||
# Rename with script bash
|
||||
cmd_client = f'cd {MOBILE_HOME_PATH} && npx cap init "{project_name}" "{package_name}" && ./rename_android.sh "{project_name}" "{package_name}" && npx cap sync android'
|
||||
self.execute.exec_command_live(cmd_client, source_erplibre=False)
|
||||
|
||||
# dotenv_mobile = dotenv.dotenv_values(dotenv_file)
|
||||
# dotenv_mobile["VITE_TITLE"] = project_name
|
||||
# dotenv_mobile["VITE_WEBSITE_URL"] = project_url_name
|
||||
dotenv.set_key(
|
||||
dotenv_file, "VITE_TITLE", project_name, quote_mode="always"
|
||||
)
|
||||
dotenv.set_key(
|
||||
dotenv_file,
|
||||
"VITE_WEBSITE_URL",
|
||||
project_url_name,
|
||||
quote_mode="always",
|
||||
)
|
||||
dotenv.set_key(
|
||||
dotenv_file,
|
||||
"VITE_LABEL_NOTE",
|
||||
project_principal_subject,
|
||||
quote_mode="always",
|
||||
)
|
||||
dotenv.set_key(
|
||||
dotenv_file,
|
||||
"VITE_DEBUG_DEV",
|
||||
"true" if do_debug else "false",
|
||||
quote_mode="never",
|
||||
)
|
||||
|
||||
if do_change_picture_menu:
|
||||
status = self.execute.exec_command_live(
|
||||
f"cd {MOBILE_HOME_PATH} && npx cap open android;bash",
|
||||
source_erplibre=False,
|
||||
new_window=True,
|
||||
)
|
||||
print(
|
||||
"Guide for Android-Studio, wait loading is finish. Right-click to app/New/Image Asset and load your image."
|
||||
)
|
||||
input(
|
||||
"Did you finish to update image with Android-Studio ? Press to continue ..."
|
||||
)
|
||||
cmd_client = "cp ./mobile/erplibre_home_mobile/android/app/src/main/ic_launcher-playstore.png ./mobile/erplibre_home_mobile/src/assets/company_logo.png"
|
||||
self.execute.exec_command_live(cmd_client, source_erplibre=False)
|
||||
cmd_client = "cp ./mobile/erplibre_home_mobile/android/app/src/main/ic_launcher-playstore.png ./mobile/erplibre_home_mobile/src/assets/imgs/logo.png"
|
||||
self.execute.exec_command_live(cmd_client, source_erplibre=False)
|
||||
|
||||
status = self.execute.exec_command_live(
|
||||
"./mobile/compile_and_run.sh", source_erplibre=False
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = time.time()
|
||||
|
|
|
|||
|
|
@ -51,10 +51,64 @@ TRANSLATIONS = {
|
|||
"fr": "Commande non trouvée !",
|
||||
"en": "Command not found !",
|
||||
},
|
||||
"Back": {
|
||||
"fr": "🔙 Retour",
|
||||
"en": "🔙 Back",
|
||||
},
|
||||
# Execute submenu
|
||||
"Run - Execute and install an instance": {
|
||||
"fr": "🏃 Run - Exécuter et installer une instance",
|
||||
"en": "🏃 Run - Execute and install an instance",
|
||||
},
|
||||
"Automation - Demonstration of developed features": {
|
||||
"fr": "🦾 Automatisation - Demonstration des fonctions développées",
|
||||
"en": "🦾 Automation - Demonstration of developed features",
|
||||
},
|
||||
"Update - Update all developed staging source code": {
|
||||
"fr": "🔃 Mise à jour - Update all developed staging source code",
|
||||
"en": "🔃 Update - Update all developed staging source code",
|
||||
},
|
||||
"Code - Developer tools": {
|
||||
"fr": "💻 Code - Outil pour développeur",
|
||||
"en": "💻 Code - Developer tools",
|
||||
},
|
||||
"Doc - Documentation search": {
|
||||
"fr": "📖 Doc - Recherche de documentation",
|
||||
"en": "📖 Doc - Documentation search",
|
||||
},
|
||||
"Database - Database tools": {
|
||||
"fr": "💾 Database - Outils sur les bases de données",
|
||||
"en": "💾 Database - Database tools",
|
||||
},
|
||||
"Process - Execution tools": {
|
||||
"fr": "📟 Process - Outils sur les executions",
|
||||
"en": "📟 Process - Execution tools",
|
||||
},
|
||||
"Config - Configuration file management": {
|
||||
"fr": "🔧 Config - Traitement du fichier de configuration",
|
||||
"en": "🔧 Config - Configuration file management",
|
||||
},
|
||||
"Network - Network tools": {
|
||||
"fr": "📡 Réseau - Outil réseautique",
|
||||
"en": "📡 Network - Network tools",
|
||||
},
|
||||
"Security - Dependency security audit": {
|
||||
"fr": "🔒 Sécurité - Audit de sécurité des dépendances",
|
||||
"en": "🔒 Security - Dependency security audit",
|
||||
},
|
||||
"RTK - CLI proxy to reduce LLM token consumption": {
|
||||
"fr": "RTK - Proxy CLI pour réduire la consommation de tokens LLM",
|
||||
"en": "RTK - CLI proxy to reduce LLM token consumption",
|
||||
},
|
||||
"Language - Change language / Changer la langue": {
|
||||
"fr": "🌍 Langue - Changer la langue / Change language",
|
||||
"en": "🌍 Language - Change language / Changer la langue",
|
||||
},
|
||||
# Deploy section
|
||||
"Deploy - Deploy ERPLibre locally": {
|
||||
"fr": "🚀 Déploiement - Déployer ERPLibre localement",
|
||||
"en": "🚀 Deploy - Deploy ERPLibre locally",
|
||||
},
|
||||
"Deploy ERPLibre to a local directory!": {
|
||||
"fr": "Déployer ERPLibre dans un répertoire local!",
|
||||
"en": "Deploy ERPLibre to a local directory!",
|
||||
|
|
@ -533,11 +587,47 @@ TRANSLATIONS = {
|
|||
"fr": "Ouvrir ERPLibre avec TODO 🤖",
|
||||
"en": "Open ERPLibre with TODO 🤖",
|
||||
},
|
||||
"Update all erplibre_base on database test": {
|
||||
"fr": "🔄 Mise à jour de tous les erplibre_base sur la base de données test",
|
||||
"en": "🔄 Update all erplibre_base on database test",
|
||||
},
|
||||
"Show code status": {
|
||||
"fr": "🔍 Afficher le statut du code",
|
||||
"en": "🔍 Show code status",
|
||||
},
|
||||
"Stash all code": {
|
||||
"fr": "📦 Remiser tout le code",
|
||||
"en": "📦 Stash all code",
|
||||
},
|
||||
"Format modified code": {
|
||||
"fr": "🎨 Formater le code modifié",
|
||||
"en": "🎨 Format modified code",
|
||||
},
|
||||
# todo.py hardcoded prompt_descriptions
|
||||
"Mobile - Compile and run software": {
|
||||
"fr": "Mobile - Compiler et exécuter le logiciel",
|
||||
"en": "Mobile - Compile and run software",
|
||||
},
|
||||
"Upgrade Odoo - Migration Database": {
|
||||
"fr": "🚚 Mise à jour Odoo - Migration de base de données",
|
||||
"en": "🚚 Upgrade Odoo - Migration Database",
|
||||
},
|
||||
"Upgrade Poetry - Dependency of Odoo": {
|
||||
"fr": "📦 Mise à jour Poetry - Dépendances d'Odoo",
|
||||
"en": "📦 Upgrade Poetry - Dependency of Odoo",
|
||||
},
|
||||
"Open SHELL": {
|
||||
"fr": "🐚 Ouvrir le SHELL",
|
||||
"en": "🐚 Open SHELL",
|
||||
},
|
||||
"Upgrade Module": {
|
||||
"fr": "🧩 Mise à jour de module",
|
||||
"en": "🧩 Upgrade Module",
|
||||
},
|
||||
"Debug": {
|
||||
"fr": "🐛 Débogage",
|
||||
"en": "🐛 Debug",
|
||||
},
|
||||
"Migration module coverage": {
|
||||
"fr": "Couverture de migration des modules",
|
||||
"en": "Migration module coverage",
|
||||
|
|
@ -614,6 +704,11 @@ TRANSLATIONS = {
|
|||
"fr": "Débogage todo.py",
|
||||
"en": "Debug todo.py",
|
||||
},
|
||||
# Test section
|
||||
"Test - Test an Odoo module": {
|
||||
"fr": "🧪 Test - Tester un module Odoo",
|
||||
"en": "🧪 Test - Test an Odoo module",
|
||||
},
|
||||
"Test an Odoo module on a temporary database!": {
|
||||
"fr": "Tester un module Odoo sur une base de données temporaire!",
|
||||
"en": "Test an Odoo module on a temporary database!",
|
||||
|
|
@ -674,6 +769,10 @@ TRANSLATIONS = {
|
|||
"fr": "Suppression de la base de données temporaire",
|
||||
"en": "Cleaning up temporary database",
|
||||
},
|
||||
"Keep the temporary database? (y/N): ": {
|
||||
"fr": "Conserver la base de données temporaire? (o/N, défaut : non) : ",
|
||||
"en": "Keep the temporary database? (y/N, default: no): ",
|
||||
},
|
||||
"Database kept": {
|
||||
"fr": "Base de données conservée",
|
||||
"en": "Database kept",
|
||||
|
|
@ -690,6 +789,11 @@ TRANSLATIONS = {
|
|||
"fr": "Le nom du module est requis!",
|
||||
"en": "Module name is required!",
|
||||
},
|
||||
# Git section
|
||||
"Git - Git tools": {
|
||||
"fr": "🌿 Git - Outils Git",
|
||||
"en": "🌿 Git - Git tools",
|
||||
},
|
||||
"Git management tools!": {
|
||||
"fr": "Outils de gestion Git!",
|
||||
"en": "Git management tools!",
|
||||
|
|
@ -923,6 +1027,11 @@ TRANSLATIONS = {
|
|||
"fr": "Interruption clavier",
|
||||
"en": "Keyboard interrupt",
|
||||
},
|
||||
# GPT code section
|
||||
"GPT code - AI assistant tools": {
|
||||
"fr": "🤖 GPT code - Outils d'assistant IA",
|
||||
"en": "🤖 GPT code - AI assistant tools",
|
||||
},
|
||||
"AI assistant tools for development!": {
|
||||
"fr": "Outils d'assistant IA pour le développement!",
|
||||
"en": "AI assistant tools for development!",
|
||||
|
|
|
|||
Loading…
Reference in a new issue