Commit 0fd79827789847350a22a18ec18d78471d7bc0cf
1 parent
282a39ee6f
Exists in
master
add k2, k2obj class, other
Showing 38 changed files with 618 additions and 464 deletions Side-by-side Diff
- __pycache__/main.cpython-310.pyc
- __pycache__/routes.cpython-310.pyc
- components/k2test/.idea/.gitignore
- components/k2test/.idea/gittest.iml
- components/k2test/.idea/inspectionProfiles/profiles_settings.xml
- components/k2test/.idea/misc.xml
- components/k2test/.idea/modules.xml
- components/k2test/.idea/vcs.xml
- components/k2test/__pycache__/__init__.cpython-310.pyc
- components/k2test/k2test/__pycache__/__init__.cpython-310.pyc
- components/k2test/k2test/__pycache__/views.cpython-310.pyc
- components/k2test/k2test/languages/en/LC_MESSAGES/messages.mo
- components/k2test/k2test/languages/en/LC_MESSAGES/messages.po
- components/k2test/k2test/languages/uk/LC_MESSAGES/messages.mo
- components/k2test/k2test/languages/uk/LC_MESSAGES/messages.po
- components/k2test/k2test/templates/login.html
- components/k2test/k2test/templates/new2.html
- components/k2test/k2test/views.py
- components/k2test/requirements.txt
- db/__pycache__/database.cpython-310.pyc
- db/database.db
- db/database.py
- k2/__pycache__/k2cfg.cpython-310.pyc
- k2/__pycache__/k2inst.cpython-310.pyc
- k2/__pycache__/k2obj.cpython-310.pyc
- k2/__pycache__/root.cpython-310.pyc
- k2/k2cfg.py
- k2/k2inst.py
- k2/k2obj.py
- k2/root.py
- languages/__pycache__/find_language.cpython-310.pyc
- languages/__pycache__/views.cpython-310.pyc
- languages/babel_translation_directories.yml
- languages/find_language.py
- languages/views.py
- main.py
- routes.py
- templates/dashboard.html
__pycache__/main.cpython-310.pyc
No preview for this file type
__pycache__/routes.cpython-310.pyc
No preview for this file type
components/k2test/.idea/.gitignore
components/k2test/.idea/gittest.iml
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<module type="PYTHON_MODULE" version="4"> | |
| 3 | + <component name="NewModuleRootManager"> | |
| 4 | + <content url="file://$MODULE_DIR$"> | |
| 5 | + <excludeFolder url="file://$MODULE_DIR$/venv" /> | |
| 6 | + </content> | |
| 7 | + <orderEntry type="inheritedJdk" /> | |
| 8 | + <orderEntry type="sourceFolder" forTests="false" /> | |
| 9 | + </component> | |
| 10 | +</module> |
components/k2test/.idea/inspectionProfiles/profiles_settings.xml
components/k2test/.idea/misc.xml
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<project version="4"> | |
| 3 | + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (gittest)" project-jdk-type="Python SDK" /> | |
| 4 | + <component name="PyCharmProfessionalAdvertiser"> | |
| 5 | + <option name="shown" value="true" /> | |
| 6 | + </component> | |
| 7 | +</project> |
components/k2test/.idea/modules.xml
components/k2test/.idea/vcs.xml
components/k2test/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/k2test/k2test/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/k2test/k2test/__pycache__/views.cpython-310.pyc
No preview for this file type
components/k2test/k2test/languages/en/LC_MESSAGES/messages.mo
No preview for this file type
components/k2test/k2test/languages/en/LC_MESSAGES/messages.po
| 1 | +msgid "Installed components" | |
| 2 | +msgstr "Installed components" | |
| 3 | + | |
| 4 | +msgid "Name" | |
| 5 | +msgstr "Name" | |
| 6 | + | |
| 7 | +msgid "Description" | |
| 8 | +msgstr "Description" | |
| 9 | + | |
| 10 | +msgid "Version" | |
| 11 | +msgstr "Version" | |
| 12 | + | |
| 13 | +msgid "Dependencies" | |
| 14 | +msgstr "Dependencies" | |
| 15 | + | |
| 16 | +msgid "Git Link" | |
| 17 | +msgstr "Git Link" | |
| 18 | + | |
| 19 | +msgid "Install At" | |
| 20 | +msgstr "Install At" | |
| 21 | + | |
| 22 | +msgid "Status" | |
| 23 | +msgstr "Status" | |
| 24 | + | |
| 25 | +msgid "Action" | |
| 26 | +msgstr "Action" | |
| 27 | + | |
| 28 | +msgid "Components Shop" | |
| 29 | +msgstr "Components Shop" | |
| 30 | + | |
| 31 | +msgid "New 2 page" | |
| 32 | +msgstr "New 2 page" |
components/k2test/k2test/languages/uk/LC_MESSAGES/messages.mo
No preview for this file type
components/k2test/k2test/languages/uk/LC_MESSAGES/messages.po
components/k2test/k2test/templates/login.html
| 1 | +login |
components/k2test/k2test/templates/new2.html
components/k2test/k2test/views.py
| 1 | +from flask import render_template, redirect, request | |
| 2 | +from flask_login import login_user, current_user, logout_user, login_required | |
| 3 | +from flask import current_app as k2 | |
| 4 | +from flask import Blueprint, json | |
| 5 | +from flask_sqlalchemy import SQLAlchemy | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | +k2test = Blueprint('k2test', __name__, template_folder='templates', static_folder='static',) | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | +@k2test.route('/new') | |
| 14 | +def new_component(): | |
| 15 | + db = k2.extensions['sqlalchemy'].db | |
| 16 | + connection = db.engine.connect() | |
| 17 | + query = db.text("SELECT email, login FROM k2users") | |
| 18 | + result = connection.execute(query).fetchall() | |
| 19 | + rows = [dict(email=row.email, login=row.login) for row in result] | |
| 20 | + # Перетворення результату на JSON | |
| 21 | + json_result = json.dumps(rows) | |
| 22 | + return json_result | |
| 23 | + | |
| 24 | +@k2test.route('/new2') | |
| 25 | +def new_component2(): | |
| 26 | + return render_template('new2.html') | |
| 27 | + | |
| 28 | +@k2test.route('/new3') | |
| 29 | +def new_component3(): | |
| 30 | + return 'сторінка 3' | |
| 31 | + | |
| 32 | +@k2test.route('/new4') | |
| 33 | +def new_component4(): | |
| 34 | + return 'сторінка 4' |
components/k2test/requirements.txt
| 1 | +Flask-Login==0.6.2 |
db/__pycache__/database.cpython-310.pyc
No preview for this file type
db/database.db
No preview for this file type
db/database.py
| 1 | -from flask_sqlalchemy import SQLAlchemy | |
| 2 | -from sqlalchemy import text | |
| 3 | -import yaml | |
| 4 | -import os | |
| 5 | -# load database settings from yml file | |
| 6 | -def init_db_uri(): | |
| 7 | - with open('db/db.yml', 'r') as f: | |
| 8 | - db_config = yaml.load(f, Loader=yaml.FullLoader) | |
| 9 | - return db_config | |
| 10 | -# creating a connection string | |
| 11 | -db = SQLAlchemy() | |
| 12 | - | |
| 13 | -def init_db(app): | |
| 14 | - db_config = init_db_uri() | |
| 15 | - db_uri = f"mysql+{db_config['driver']}://{db_config['user']}:{db_config['password']}@{db_config['host']}/{db_config['dbname']}" | |
| 16 | - app.config['SQLALCHEMY_DATABASE_URI'] = db_uri | |
| 17 | - basedir = os.path.abspath(os.path.dirname(__file__)) | |
| 18 | - db_path = os.path.join(basedir, '', '', 'database.db') | |
| 19 | - app.config['SQLALCHEMY_BINDS'] = {'db2': f'sqlite:///{db_path}'} | |
| 20 | - db.init_app(app) |
k2/__pycache__/k2cfg.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2inst.cpython-310.pyc
No preview for this file type
k2/__pycache__/k2obj.cpython-310.pyc
No preview for this file type
k2/__pycache__/root.cpython-310.pyc
No preview for this file type
k2/k2cfg.py
| 1 | +from flask_sqlalchemy import SQLAlchemy | |
| 2 | +from sqlalchemy import text | |
| 3 | +from .k2obj import k2obj | |
| 4 | +import yaml | |
| 5 | +import os | |
| 6 | +import requests | |
| 7 | +import pytz | |
| 8 | +import os | |
| 9 | +import sys | |
| 10 | +from flask import session | |
| 11 | + | |
| 12 | +class k2(k2obj): | |
| 13 | + | |
| 14 | + version = '2.5.1.27' | |
| 15 | + db = SQLAlchemy() | |
| 16 | + domain = 'http://127.0.0.1:5000/' | |
| 17 | + update_domain ='http://127.0.0.1:8001/' | |
| 18 | + venv_bin_path = os.path.join(os.path.dirname(sys.prefix), 'venv/Scripts') | |
| 19 | + json_sort_keys = False | |
| 20 | + timezone = pytz.timezone('Europe/Kiev') | |
| 21 | + secret_key = 'JH&INH987gFDHdsagh&8dwbjdw8ckw' | |
| 22 | + default_language = 'en' | |
| 23 | + current_language = '' | |
| 24 | + babel_translation_directories = '' | |
| 25 | + | |
| 26 | + def __init__(self): | |
| 27 | + super().__init__() | |
| 28 | + | |
| 29 | + @classmethod | |
| 30 | + def load_babel_translation_directories(cls): | |
| 31 | + with open('languages/babel_translation_directories.yml', 'r') as f: | |
| 32 | + data = yaml.safe_load(f) | |
| 33 | + cls.babel_translation_directories = data['babel_translation_directories'] | |
| 34 | + | |
| 35 | + @classmethod | |
| 36 | + def get_locale(cls): | |
| 37 | + if 'lang' in session: | |
| 38 | + # Отримати обрану мову з сеансу користувача | |
| 39 | + return session['lang'] | |
| 40 | + else: | |
| 41 | + # Повернути мову за замовчуванням з налаштувань додатку | |
| 42 | + return cls.default_language #app.config['DEFAULT_LANGUAGE'] | |
| 43 | + | |
| 44 | + @classmethod | |
| 45 | + def search_babel_translation_directories(cls): | |
| 46 | + response = requests.get(f'{cls.domain}api/languages') | |
| 47 | + if response.status_code == 200: | |
| 48 | + cls.babel_translation_directories = response.text | |
| 49 | + data = {'babel_translation_directories': response.text} | |
| 50 | + else: | |
| 51 | + cls.babel_translation_directories = 'languages' | |
| 52 | + data = {'babel_translation_directories': 'languages'} | |
| 53 | + | |
| 54 | + with open('languages/babel_translation_directories.yml', 'w') as f: | |
| 55 | + yaml.dump(data, f) | |
| 56 | + | |
| 57 | + # load database settings from yml file | |
| 58 | + def init_db_uri(self): | |
| 59 | + with open('db/db.yml', 'r') as f: | |
| 60 | + db_config = yaml.load(f, Loader=yaml.FullLoader) | |
| 61 | + return db_config | |
| 62 | + | |
| 63 | + # creating a connection string | |
| 64 | + | |
| 65 | + | |
| 66 | + def init_db(self, app): | |
| 67 | + db_config = self.init_db_uri() | |
| 68 | + db_uri = f"mysql+{db_config['driver']}://{db_config['user']}:{db_config['password']}@{db_config['host']}/{db_config['dbname']}" | |
| 69 | + app.config['SQLALCHEMY_DATABASE_URI'] = db_uri | |
| 70 | + db_path = '../db/database.db' | |
| 71 | + app.config['SQLALCHEMY_BINDS'] = {'db2': f'sqlite:///{db_path}'} | |
| 72 | + self.db.init_app(app) |
k2/k2inst.py
| 1 | +import zipfile | |
| 2 | +from flask import Flask, Blueprint, jsonify, render_template, redirect, url_for, session, g | |
| 3 | +import os | |
| 4 | +import shutil | |
| 5 | +from datetime import datetime | |
| 6 | +import uuid | |
| 7 | +from flask import request | |
| 8 | +from k2.k2cfg import k2 | |
| 9 | +from flask_migrate import Migrate | |
| 10 | +import requests | |
| 11 | +import subprocess | |
| 12 | +from flask import current_app | |
| 13 | +import yaml | |
| 14 | +from functools import wraps | |
| 15 | + | |
| 16 | +db = k2.db | |
| 17 | +#migrate = Migrate(app, db) | |
| 18 | +def generate_id(): | |
| 19 | + generated_id = uuid.uuid4().hex[:32] | |
| 20 | + return ''.join([generated_id[i:i + 4] for i in range(0, len(generated_id), 4)]) | |
| 21 | +class Component(db.Model): | |
| 22 | + __bind_key__ = 'db2' | |
| 23 | + __tablename__ = 'component' | |
| 24 | + __table_args__ = {'extend_existing': True} | |
| 25 | + id = db.Column(db.String(36), primary_key=True, default=generate_id) | |
| 26 | + name = db.Column(db.String(100), nullable=False) | |
| 27 | + description = db.Column(db.String(200)) | |
| 28 | + version = db.Column(db.String(20)) | |
| 29 | + git_link = db.Column(db.String(200)) | |
| 30 | + dependencies = db.Column(db.String) | |
| 31 | + date_installed = db.Column(db.DateTime, default=datetime.utcnow) | |
| 32 | + installed = db.Column(db.Boolean, default=False) | |
| 33 | + | |
| 34 | + def __init__(self, name, description, version, git_link, dependencies, installed): | |
| 35 | + self.name = name | |
| 36 | + self.description = description | |
| 37 | + self.version = version | |
| 38 | + self.git_link = git_link | |
| 39 | + self.dependencies = dependencies | |
| 40 | + self.installed = installed | |
| 41 | + def __repr__(self): | |
| 42 | + return f"Component('{self.name}', '{self.version}')" | |
| 43 | + @classmethod | |
| 44 | + def get_repository_by_id(self,rep_id): | |
| 45 | + component = db.session.query(Component).filter(Component.id == rep_id).first() | |
| 46 | + return component | |
| 47 | +components_bp = Blueprint('components', __name__, template_folder='templates') | |
| 48 | +config = yaml.safe_load(open("db/first-login.yml")) | |
| 49 | + | |
| 50 | +def first_login_required(view_func): | |
| 51 | + @wraps(view_func) | |
| 52 | + def decorated_view(*args, **kwargs): | |
| 53 | + if 'username' not in session: | |
| 54 | + return redirect(url_for('first_login')) | |
| 55 | + return view_func(*args, **kwargs) | |
| 56 | + | |
| 57 | + return decorated_view | |
| 58 | + | |
| 59 | + | |
| 60 | +@components_bp.route('/api/languages', methods=['GET']) | |
| 61 | +def find_language(): | |
| 62 | + components = Component.query.all() | |
| 63 | + languages_paths = [] | |
| 64 | + # Додаємо головну директорію languages | |
| 65 | + languages_paths.append('languages') | |
| 66 | + # Знаходимо шляхи до директорій languages всередині папки components | |
| 67 | + for component in components: | |
| 68 | + component_languages_directory = 'components/' + component.name + '/' + component.name + '/languages' | |
| 69 | + languages_paths.append(component_languages_directory) | |
| 70 | + result = ';'.join(languages_paths) | |
| 71 | + print(result) | |
| 72 | + return result | |
| 73 | + | |
| 74 | +@components_bp.route('/', methods=['GET', 'POST']) | |
| 75 | +@first_login_required | |
| 76 | +def home(): | |
| 77 | + return redirect('/dashboard') | |
| 78 | + | |
| 79 | +@components_bp.route('/login', methods=['GET', 'POST']) | |
| 80 | +def first_login(): | |
| 81 | + if request.method == "POST": | |
| 82 | + username = request.form.get("username") | |
| 83 | + password = request.form.get("password") | |
| 84 | + for user in config["users"]: | |
| 85 | + if user["username"] == username and user["password"] == password: | |
| 86 | + session['username'] = username # Збереження ім'я користувача в сесії | |
| 87 | + return redirect(url_for('components.dashboard')) | |
| 88 | + return "Невірне ім'я користувача або пароль." | |
| 89 | + return render_template('first-login.html') | |
| 90 | + | |
| 91 | +@components_bp.route('/logout') | |
| 92 | +def logout(): | |
| 93 | + session.pop('username', None) # Видалення ім'я користувача з сесії | |
| 94 | + return redirect(url_for('first_login')) | |
| 95 | + | |
| 96 | +@components_bp.route('/change_language/<lang>') | |
| 97 | +def change_language(lang): | |
| 98 | + session['lang'] = lang | |
| 99 | + k2.current_language = lang | |
| 100 | + return redirect(url_for('components.dashboard')) | |
| 101 | + | |
| 102 | +@components_bp.route('/dashboard') | |
| 103 | +@first_login_required | |
| 104 | +def dashboard(): | |
| 105 | + | |
| 106 | + # Компоненти доступні для встановлення | |
| 107 | + try: | |
| 108 | + # GET-запит до API | |
| 109 | + response = requests.get('http://127.0.0.1:8001/api/components') | |
| 110 | + json_data = response.json() | |
| 111 | + # Перетворення JSON-об'єкту на масив | |
| 112 | + component_server = [item for item in json_data] | |
| 113 | + except: | |
| 114 | + component_server = None | |
| 115 | + | |
| 116 | + # Встановлені компоненти | |
| 117 | + components = Component.query.all() | |
| 118 | + components_names = [component.name for component in components] | |
| 119 | + # Отримання значення пошукового запиту з параметрів URL | |
| 120 | + search_query = request.args.get('search_query') | |
| 121 | + #print(search_query) | |
| 122 | + filtered_components = [] | |
| 123 | + if search_query: | |
| 124 | + filtered_components = [component for component in component_server if | |
| 125 | + (search_query.lower() in component['name'].lower() if component['name'] else False) or | |
| 126 | + (search_query.lower() in component['description'].lower() if component[ | |
| 127 | + 'description'] else False)] | |
| 128 | + else: | |
| 129 | + filtered_components = component_server | |
| 130 | + current_language = k2.current_language | |
| 131 | + | |
| 132 | + return render_template('dashboard.html', components=components, | |
| 133 | + components_names=components_names, component_server=filtered_components, | |
| 134 | + search_query=search_query, language=current_language ) | |
| 135 | + | |
| 136 | +@components_bp.route('/show_components/<string:component_id>') | |
| 137 | +@first_login_required | |
| 138 | +def show_components(component_id): | |
| 139 | + response = requests.get('http://127.0.0.1:8001/api/components') | |
| 140 | + json_data = response.json() | |
| 141 | + selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 142 | + return render_template('component-info.html', selected_component=selected_component) | |
| 143 | + | |
| 144 | +@components_bp.route('/install_components_git/<string:component_id>') | |
| 145 | +@first_login_required | |
| 146 | +def install_components_git(component_id): | |
| 147 | + # Шлях до головної папки проекту | |
| 148 | + project_folder = 'components' | |
| 149 | + #component = Component.get_repository_by_id(component_id) | |
| 150 | + response = requests.get('http://127.0.0.1:8001/api/components') | |
| 151 | + json_data = response.json() | |
| 152 | + selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 153 | + # Назва репозиторія | |
| 154 | + repository_name = selected_component['name'] | |
| 155 | + # Шлях до папки репозиторія в межах проекту | |
| 156 | + repository_folder = os.path.join(project_folder, repository_name) | |
| 157 | + # URL репозиторія | |
| 158 | + | |
| 159 | + git_repo_url = selected_component['git_link'] | |
| 160 | + try: | |
| 161 | + # Перевірка наявності папки репозиторія | |
| 162 | + if not os.path.exists(repository_folder): | |
| 163 | + # Створення папки репозиторія | |
| 164 | + os.makedirs(repository_folder) | |
| 165 | + # Шлях до файлу __init__.py | |
| 166 | + init_file = os.path.join(repository_folder, '__init__.py') | |
| 167 | + # Перевірка наявності файлу __init__.py | |
| 168 | + if not os.path.exists(init_file): | |
| 169 | + # Створення пустого файлу __init__.py | |
| 170 | + open(init_file, 'a').close() | |
| 171 | + #підключення до приватного репозиторію | |
| 172 | + #os.environ['GITLAB_PRIVATE_TOKEN'] = '8xxTpxrKVDGoXD5ynjiW' | |
| 173 | + #git_repo_url_with_token = git_repo_url.replace('https://', | |
| 174 | + # f'https://oauth2:{os.environ["GITLAB_PRIVATE_TOKEN"]}@') | |
| 175 | + | |
| 176 | + # Команда для встановлення з використанням git_repo_url і повного шляху до папки репозиторія | |
| 177 | + command = ['venv/Scripts/python.exe', '-m', 'pip', 'install', '--use-pep517', 'git+' + git_repo_url, '--target=' + repository_folder] | |
| 178 | + # Виконуємо команду встановлення | |
| 179 | + subprocess.check_call(command) | |
| 180 | + | |
| 181 | + # Шлях до файлу, до якого потрібно додати код | |
| 182 | + file_path = 'routes.py' | |
| 183 | + # Код, який потрібно додати | |
| 184 | + code = selected_component['dependencies'] | |
| 185 | + # Відкриття файлу у режимі дозапису | |
| 186 | + with open(file_path, 'a') as file: | |
| 187 | + # Запис нового коду у файл | |
| 188 | + file.write('\n') | |
| 189 | + file.write(code) | |
| 190 | + file.write('\n') | |
| 191 | + component = Component.query.filter_by(name=selected_component['name']).first() | |
| 192 | + if not component: | |
| 193 | + new_component = Component( | |
| 194 | + name=selected_component['name'], | |
| 195 | + description=selected_component['description'], | |
| 196 | + version=selected_component['version'], | |
| 197 | + git_link=selected_component['git_link'], | |
| 198 | + dependencies=selected_component['dependencies'], | |
| 199 | + installed=True | |
| 200 | + ) | |
| 201 | + # Add the new component to the database | |
| 202 | + db.session.add(new_component) | |
| 203 | + db.session.commit() | |
| 204 | + | |
| 205 | + # Повертаємо повідомлення про успішне встановлення | |
| 206 | + return f'Installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 207 | + except subprocess.CalledProcessError as e: | |
| 208 | + return 'Error installing : ' + str(e) | |
| 209 | + | |
| 210 | +@components_bp.route('/install_components/<string:component_id>') | |
| 211 | +@first_login_required | |
| 212 | +def install_component_from_archive(component_id): | |
| 213 | + # Шлях до головної папки проекту | |
| 214 | + project_folder = 'components' | |
| 215 | + # Отримати відповідну компоненту зі списку компонент | |
| 216 | + response = requests.get('http://127.0.0.1:8001/api/components') | |
| 217 | + json_data = response.json() | |
| 218 | + selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 219 | + if selected_component is None: | |
| 220 | + return 'Component not found' | |
| 221 | + # Отримати посилання на архів компоненти та версію | |
| 222 | + archive_url = selected_component['latest_component_data'] | |
| 223 | + version = selected_component['latest_version'] | |
| 224 | + try: | |
| 225 | + # Створити шлях до папки компоненти згідно назви та версії | |
| 226 | + component_folder = os.path.join(project_folder) | |
| 227 | + os.makedirs(component_folder, exist_ok=True) | |
| 228 | + # Завантажити архів компоненти | |
| 229 | + response = requests.get(archive_url, stream=True) | |
| 230 | + response.raise_for_status() | |
| 231 | + # Шлях до завантаженого архіву | |
| 232 | + archive_path = os.path.join(component_folder, f"{selected_component['name']}.zip") | |
| 233 | + # Встановити залежності з файлу requirements.txt | |
| 234 | + | |
| 235 | + # Зберегти архів на диск | |
| 236 | + with open(archive_path, "wb") as file: | |
| 237 | + for chunk in response.iter_content(chunk_size=8192): | |
| 238 | + file.write(chunk) | |
| 239 | + # Розпакувати архів | |
| 240 | + with zipfile.ZipFile(archive_path, "r") as zip_ref: | |
| 241 | + zip_ref.extractall(component_folder) | |
| 242 | + | |
| 243 | + # Видалити архів | |
| 244 | + os.remove(archive_path) | |
| 245 | + | |
| 246 | + # Шлях до файлу, до якого потрібно додати код | |
| 247 | + file_path = 'routes.py' | |
| 248 | + # Код, який потрібно додати | |
| 249 | + code = f'''from components.{selected_component['name']}.{selected_component['name']}.views import {selected_component['name']}\napp.register_blueprint({selected_component['name']}, url_prefix='/{selected_component['name']}')''' | |
| 250 | + #selected_component['dependencies'] | |
| 251 | + | |
| 252 | + # Відкриття файлу у режимі дозапису | |
| 253 | + with open(file_path, 'a') as file: | |
| 254 | + # Запис нового коду у файл | |
| 255 | + file.write('\n') | |
| 256 | + file.write(code) | |
| 257 | + file.write('\n') | |
| 258 | + | |
| 259 | + # Оновити базу даних з встановленою компонентою | |
| 260 | + component = Component.query.filter_by(name=selected_component['name']).first() | |
| 261 | + if not component: | |
| 262 | + component = Component( | |
| 263 | + name=selected_component['name'], | |
| 264 | + description=selected_component['description'], | |
| 265 | + version=version, | |
| 266 | + git_link=selected_component['git_link'], | |
| 267 | + dependencies=code, | |
| 268 | + installed=True | |
| 269 | + ) | |
| 270 | + db.session.add(component) | |
| 271 | + else: | |
| 272 | + component.version = version | |
| 273 | + component.git_link = selected_component['git_link'] | |
| 274 | + component.dependencies = code | |
| 275 | + component.installed = True | |
| 276 | + | |
| 277 | + db.session.commit() | |
| 278 | + | |
| 279 | + | |
| 280 | + k2.search_babel_translation_directories() | |
| 281 | + | |
| 282 | + return f'''Component installed successfully: {selected_component["name"]} v{version} {k2.babel_translation_directories}, | |
| 283 | + \n \n please wait installing requirments... | |
| 284 | + <meta http-equiv="refresh" content="0;url=/install-requirments/{selected_component["name"]}" />''' | |
| 285 | + | |
| 286 | + except Exception as e: | |
| 287 | + return f'Error installing component: {str(e)}' | |
| 288 | + | |
| 289 | +@components_bp.route('/install-requirments/<string:selected_component_name>', methods=['GET']) | |
| 290 | +@first_login_required | |
| 291 | +def install_requirments(selected_component_name): | |
| 292 | + requirements_file = os.path.join('components', selected_component_name, "requirements.txt") | |
| 293 | + if os.path.isfile(requirements_file): | |
| 294 | + pip_command = f"{k2.venv_bin_path}/python -m pip install -r {requirements_file}" | |
| 295 | + subprocess.run(pip_command, shell=True, check=True) | |
| 296 | + return f'''Requirements installed successfully | |
| 297 | + \n \n please wait installing requirments components... | |
| 298 | + <meta http-equiv="refresh" content="1;url=/install-requirments-components" />''' | |
| 299 | + | |
| 300 | + | |
| 301 | +@components_bp.route('/install-requirments-components') | |
| 302 | +@first_login_required | |
| 303 | +def install_requirements_components(): | |
| 304 | + # Откриття файлу requirements_components.txt | |
| 305 | + requirements_file = 'requirements_components.txt' | |
| 306 | + component_ids = None | |
| 307 | + if os.path.isfile(requirements_file): | |
| 308 | + with open('requirements_components.txt', 'r') as file: | |
| 309 | + component_ids = file.read().splitlines() | |
| 310 | + if component_ids: | |
| 311 | + for component_id in component_ids: | |
| 312 | + # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти | |
| 313 | + response = requests.get( | |
| 314 | + f'/install_components/{component_id}') | |
| 315 | + return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 316 | + else: | |
| 317 | + return f'<meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 318 | + # Опрацювання відповіді (за потреби) | |
| 319 | + | |
| 320 | + | |
| 321 | +@components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET']) | |
| 322 | +@first_login_required | |
| 323 | +def remove_dependencies(component_id): | |
| 324 | + # Знаходимо компоненту за її ID | |
| 325 | + component = Component.query.get(component_id) | |
| 326 | + if not component: | |
| 327 | + return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 328 | + | |
| 329 | + # Шлях до файлу, з якого потрібно видалити залежності | |
| 330 | + file_path = 'routes.py' | |
| 331 | + | |
| 332 | + # Зчитуємо вміст файлу | |
| 333 | + with open(file_path, 'r') as file: | |
| 334 | + lines = file.readlines() | |
| 335 | + | |
| 336 | + # Видаляємо рядки, що містять залежності компоненти | |
| 337 | + updated_lines = [line for line in lines if line.strip() not in component.dependencies] | |
| 338 | + | |
| 339 | + # Записуємо оновлений вміст у файл | |
| 340 | + with open(file_path, 'w') as file: | |
| 341 | + file.writelines(updated_lines) | |
| 342 | + | |
| 343 | + # Оновлюємо статус компоненти | |
| 344 | + component.installed = False | |
| 345 | + db.session.commit() | |
| 346 | + | |
| 347 | + return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 348 | + | |
| 349 | +@components_bp.route('/add_dependencies/<string:component_id>', methods=['GET']) | |
| 350 | +@first_login_required | |
| 351 | +def add_dependencies(component_id): | |
| 352 | + | |
| 353 | + # Знаходимо компоненту за її ID | |
| 354 | + component = Component.query.get(component_id) | |
| 355 | + if not component: | |
| 356 | + return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 357 | + | |
| 358 | + # Шлях до файлу, з якого потрібно видалити залежності | |
| 359 | + file_path = 'routes.py' | |
| 360 | + code = component.dependencies | |
| 361 | + # Відкриття файлу у режимі дозапису | |
| 362 | + with open(file_path, 'a') as file: | |
| 363 | + # Запис нового коду у файл | |
| 364 | + file.write(code) | |
| 365 | + | |
| 366 | + # Оновлюємо статус компоненти | |
| 367 | + component.installed = True | |
| 368 | + db.session.commit() | |
| 369 | + return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 370 | + | |
| 371 | +@components_bp.route('/remove-component/<string:component_id>') | |
| 372 | +@first_login_required | |
| 373 | +def remove_component(component_id): | |
| 374 | + # Шлях до головної папки проекту | |
| 375 | + project_folder = 'components' | |
| 376 | + component = Component.query.get(component_id) | |
| 377 | + # Назва репозиторія | |
| 378 | + repository_name = component.name | |
| 379 | + # Шлях до папки репозиторія в межах проекту | |
| 380 | + repository_folder = os.path.join(project_folder, repository_name) | |
| 381 | + try: | |
| 382 | + # Перевірка наявності папки репозиторія | |
| 383 | + if os.path.exists(repository_folder): | |
| 384 | + # Видалення папки репозиторія | |
| 385 | + shutil.rmtree(repository_folder) | |
| 386 | + # Видаляємо компоненту з бази | |
| 387 | + if component: | |
| 388 | + db.session.delete(component) | |
| 389 | + db.session.commit() | |
| 390 | + | |
| 391 | + # Повертаємо повідомлення про успішне видалення | |
| 392 | + return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 393 | + except Exception as e: | |
| 394 | + # Повертаємо повідомлення про помилку видалення | |
| 395 | + return 'Error removing component: ' + str(e) |
k2/k2obj.py
k2/root.py
| 1 | -import zipfile | |
| 2 | -from flask import Flask, Blueprint, jsonify, render_template, redirect, url_for, session, g | |
| 3 | -import os | |
| 4 | -import shutil | |
| 5 | -from datetime import datetime | |
| 6 | -import uuid | |
| 7 | -from flask import request | |
| 8 | -from db.database import db | |
| 9 | -from flask_migrate import Migrate | |
| 10 | -from main import app | |
| 11 | -import requests | |
| 12 | -import subprocess | |
| 13 | -from flask import current_app | |
| 14 | -import yaml | |
| 15 | -from functools import wraps | |
| 16 | -from languages.views import get_locale | |
| 17 | - | |
| 18 | - | |
| 19 | -with app.app_context(): | |
| 20 | - | |
| 21 | - #migrate = Migrate(app, db) | |
| 22 | - def generate_id(): | |
| 23 | - generated_id = uuid.uuid4().hex[:32] | |
| 24 | - return ''.join([generated_id[i:i + 4] for i in range(0, len(generated_id), 4)]) | |
| 25 | - class Component(db.Model): | |
| 26 | - __bind_key__ = 'db2' | |
| 27 | - __tablename__ = 'component' | |
| 28 | - __table_args__ = {'extend_existing': True} | |
| 29 | - id = db.Column(db.String(36), primary_key=True, default=generate_id) | |
| 30 | - name = db.Column(db.String(100), nullable=False) | |
| 31 | - description = db.Column(db.String(200)) | |
| 32 | - version = db.Column(db.String(20)) | |
| 33 | - git_link = db.Column(db.String(200)) | |
| 34 | - dependencies = db.Column(db.String) | |
| 35 | - date_installed = db.Column(db.DateTime, default=datetime.utcnow) | |
| 36 | - installed = db.Column(db.Boolean, default=False) | |
| 37 | - | |
| 38 | - def __init__(self, name, description, version, git_link, dependencies, installed): | |
| 39 | - self.name = name | |
| 40 | - self.description = description | |
| 41 | - self.version = version | |
| 42 | - self.git_link = git_link | |
| 43 | - self.dependencies = dependencies | |
| 44 | - self.installed = installed | |
| 45 | - def __repr__(self): | |
| 46 | - return f"Component('{self.name}', '{self.version}')" | |
| 47 | - @classmethod | |
| 48 | - def get_repository_by_id(self,rep_id): | |
| 49 | - component = db.session.query(Component).filter(Component.id == rep_id).first() | |
| 50 | - return component | |
| 51 | - components_bp = Blueprint('components', __name__, template_folder='templates') | |
| 52 | - config = yaml.safe_load(open("db/first-login.yml")) | |
| 53 | - | |
| 54 | - | |
| 55 | - def first_login_required(view_func): | |
| 56 | - @wraps(view_func) | |
| 57 | - def decorated_view(*args, **kwargs): | |
| 58 | - if 'username' not in session: | |
| 59 | - return redirect(url_for('first_login')) | |
| 60 | - return view_func(*args, **kwargs) | |
| 61 | - | |
| 62 | - return decorated_view | |
| 63 | - | |
| 64 | - | |
| 65 | - def find_language(): | |
| 66 | - components = Component.query.all() | |
| 67 | - languages_paths = [] | |
| 68 | - # Додаємо головну директорію languages | |
| 69 | - languages_paths.append('languages') | |
| 70 | - # Знаходимо шляхи до директорій languages всередині папки components | |
| 71 | - for component in components: | |
| 72 | - component_languages_directory = 'components/' + component.name + '/languages' | |
| 73 | - languages_paths.append(component_languages_directory) | |
| 74 | - result = ';'.join(languages_paths) | |
| 75 | - return result | |
| 76 | - | |
| 77 | - @app.route('/', methods=['GET', 'POST']) | |
| 78 | - @first_login_required | |
| 79 | - def home(): | |
| 80 | - return redirect('/dashboard') | |
| 81 | - | |
| 82 | - | |
| 83 | - @app.route('/login', methods=['GET', 'POST']) | |
| 84 | - def first_login(): | |
| 85 | - if request.method == "POST": | |
| 86 | - username = request.form.get("username") | |
| 87 | - password = request.form.get("password") | |
| 88 | - for user in config["users"]: | |
| 89 | - if user["username"] == username and user["password"] == password: | |
| 90 | - session['username'] = username # Збереження ім'я користувача в сесії | |
| 91 | - return redirect(url_for('components.dashboard')) | |
| 92 | - return "Невірне ім'я користувача або пароль." | |
| 93 | - return render_template('first-login.html') | |
| 94 | - | |
| 95 | - | |
| 96 | - @app.route('/logout') | |
| 97 | - def logout(): | |
| 98 | - session.pop('username', None) # Видалення ім'я користувача з сесії | |
| 99 | - return redirect(url_for('login')) | |
| 100 | - | |
| 101 | - | |
| 102 | - @components_bp.route('/change_language/<lang>') | |
| 103 | - def change_language(lang): | |
| 104 | - session['lang'] = lang | |
| 105 | - app.config['CURRENT_LANGUAGE'] = lang | |
| 106 | - return redirect(url_for('components.dashboard')) | |
| 107 | - | |
| 108 | - @components_bp.route('/dashboard') | |
| 109 | - @first_login_required | |
| 110 | - def dashboard(): | |
| 111 | - | |
| 112 | - # Компоненти доступні для встановлення | |
| 113 | - try: | |
| 114 | - # GET-запит до API | |
| 115 | - response = requests.get('http://127.0.0.1:8001/api/components') | |
| 116 | - json_data = response.json() | |
| 117 | - # Перетворення JSON-об'єкту на масив | |
| 118 | - component_server = [item for item in json_data] | |
| 119 | - except: | |
| 120 | - component_server = None | |
| 121 | - | |
| 122 | - # Встановлені компоненти | |
| 123 | - components = Component.query.all() | |
| 124 | - components_names = [component.name for component in components] | |
| 125 | - # Отримання значення пошукового запиту з параметрів URL | |
| 126 | - search_query = request.args.get('search_query') | |
| 127 | - #print(search_query) | |
| 128 | - filtered_components = [] | |
| 129 | - if search_query: | |
| 130 | - filtered_components = [component for component in component_server if | |
| 131 | - (search_query.lower() in component['name'].lower() if component['name'] else False) or | |
| 132 | - (search_query.lower() in component['description'].lower() if component[ | |
| 133 | - 'description'] else False)] | |
| 134 | - else: | |
| 135 | - filtered_components = component_server | |
| 136 | - current_language = app.config['CURRENT_LANGUAGE'] #get_locale() | |
| 137 | - | |
| 138 | - return render_template('dashboard.html', components=components, | |
| 139 | - components_names=components_names, component_server=filtered_components, | |
| 140 | - search_query=search_query, language=current_language) | |
| 141 | - | |
| 142 | - @components_bp.route('/show_components/<string:component_id>') | |
| 143 | - @first_login_required | |
| 144 | - def show_components(component_id): | |
| 145 | - response = requests.get('http://127.0.0.1:8001/api/components') | |
| 146 | - json_data = response.json() | |
| 147 | - selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 148 | - return render_template('component-info.html', selected_component=selected_component) | |
| 149 | - | |
| 150 | - @components_bp.route('/install_components_git/<string:component_id>') | |
| 151 | - @first_login_required | |
| 152 | - def install_components_git(component_id): | |
| 153 | - # Шлях до головної папки проекту | |
| 154 | - project_folder = 'components' | |
| 155 | - #component = Component.get_repository_by_id(component_id) | |
| 156 | - response = requests.get('http://127.0.0.1:8001/api/components') | |
| 157 | - json_data = response.json() | |
| 158 | - selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 159 | - # Назва репозиторія | |
| 160 | - repository_name = selected_component['name'] | |
| 161 | - # Шлях до папки репозиторія в межах проекту | |
| 162 | - repository_folder = os.path.join(project_folder, repository_name) | |
| 163 | - # URL репозиторія | |
| 164 | - | |
| 165 | - git_repo_url = selected_component['git_link'] | |
| 166 | - try: | |
| 167 | - # Перевірка наявності папки репозиторія | |
| 168 | - if not os.path.exists(repository_folder): | |
| 169 | - # Створення папки репозиторія | |
| 170 | - os.makedirs(repository_folder) | |
| 171 | - # Шлях до файлу __init__.py | |
| 172 | - init_file = os.path.join(repository_folder, '__init__.py') | |
| 173 | - # Перевірка наявності файлу __init__.py | |
| 174 | - if not os.path.exists(init_file): | |
| 175 | - # Створення пустого файлу __init__.py | |
| 176 | - open(init_file, 'a').close() | |
| 177 | - #підключення до приватного репозиторію | |
| 178 | - #os.environ['GITLAB_PRIVATE_TOKEN'] = '8xxTpxrKVDGoXD5ynjiW' | |
| 179 | - #git_repo_url_with_token = git_repo_url.replace('https://', | |
| 180 | - # f'https://oauth2:{os.environ["GITLAB_PRIVATE_TOKEN"]}@') | |
| 181 | - | |
| 182 | - # Команда для встановлення з використанням git_repo_url і повного шляху до папки репозиторія | |
| 183 | - command = ['venv/Scripts/python.exe', '-m', 'pip', 'install', '--use-pep517', 'git+' + git_repo_url, '--target=' + repository_folder] | |
| 184 | - # Виконуємо команду встановлення | |
| 185 | - subprocess.check_call(command) | |
| 186 | - | |
| 187 | - # Шлях до файлу, до якого потрібно додати код | |
| 188 | - file_path = 'routes.py' | |
| 189 | - # Код, який потрібно додати | |
| 190 | - code = selected_component['dependencies'] | |
| 191 | - # Відкриття файлу у режимі дозапису | |
| 192 | - with open(file_path, 'a') as file: | |
| 193 | - # Запис нового коду у файл | |
| 194 | - file.write('\n') | |
| 195 | - file.write(code) | |
| 196 | - file.write('\n') | |
| 197 | - component = Component.query.filter_by(name=selected_component['name']).first() | |
| 198 | - if not component: | |
| 199 | - new_component = Component( | |
| 200 | - name=selected_component['name'], | |
| 201 | - description=selected_component['description'], | |
| 202 | - version=selected_component['version'], | |
| 203 | - git_link=selected_component['git_link'], | |
| 204 | - dependencies=selected_component['dependencies'], | |
| 205 | - installed=True | |
| 206 | - ) | |
| 207 | - # Add the new component to the database | |
| 208 | - db.session.add(new_component) | |
| 209 | - db.session.commit() | |
| 210 | - | |
| 211 | - # Повертаємо повідомлення про успішне встановлення | |
| 212 | - return f'Installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 213 | - except subprocess.CalledProcessError as e: | |
| 214 | - return 'Error installing : ' + str(e) | |
| 215 | - | |
| 216 | - @components_bp.route('/install_components/<string:component_id>') | |
| 217 | - @first_login_required | |
| 218 | - def install_component_from_archive(component_id): | |
| 219 | - # Шлях до головної папки проекту | |
| 220 | - project_folder = 'components' | |
| 221 | - # Отримати відповідну компоненту зі списку компонент | |
| 222 | - response = requests.get('http://127.0.0.1:8001/api/components') | |
| 223 | - json_data = response.json() | |
| 224 | - selected_component = next((component for component in json_data if component['id'] == component_id), None) | |
| 225 | - if selected_component is None: | |
| 226 | - return 'Component not found' | |
| 227 | - # Отримати посилання на архів компоненти та версію | |
| 228 | - archive_url = selected_component['latest_component_data'] | |
| 229 | - version = selected_component['latest_version'] | |
| 230 | - try: | |
| 231 | - # Створити шлях до папки компоненти згідно назви та версії | |
| 232 | - component_folder = os.path.join(project_folder) | |
| 233 | - os.makedirs(component_folder, exist_ok=True) | |
| 234 | - # Завантажити архів компоненти | |
| 235 | - response = requests.get(archive_url, stream=True) | |
| 236 | - response.raise_for_status() | |
| 237 | - # Шлях до завантаженого архіву | |
| 238 | - archive_path = os.path.join(component_folder, f"{selected_component['name']}.zip") | |
| 239 | - # Встановити залежності з файлу requirements.txt | |
| 240 | - | |
| 241 | - # Зберегти архів на диск | |
| 242 | - with open(archive_path, "wb") as file: | |
| 243 | - for chunk in response.iter_content(chunk_size=8192): | |
| 244 | - file.write(chunk) | |
| 245 | - # Розпакувати архів | |
| 246 | - with zipfile.ZipFile(archive_path, "r") as zip_ref: | |
| 247 | - zip_ref.extractall(component_folder) | |
| 248 | - | |
| 249 | - # Видалити архів | |
| 250 | - os.remove(archive_path) | |
| 251 | - | |
| 252 | - # Шлях до файлу, до якого потрібно додати код | |
| 253 | - file_path = 'routes.py' | |
| 254 | - # Код, який потрібно додати | |
| 255 | - code = f'''from components.{selected_component['name']}.{selected_component['name']}.views import {selected_component['name']}\napp.register_blueprint({selected_component['name']}, url_prefix='/{selected_component['name']}')''' | |
| 256 | - #selected_component['dependencies'] | |
| 257 | - | |
| 258 | - # Відкриття файлу у режимі дозапису | |
| 259 | - with open(file_path, 'a') as file: | |
| 260 | - # Запис нового коду у файл | |
| 261 | - file.write('\n') | |
| 262 | - file.write(code) | |
| 263 | - file.write('\n') | |
| 264 | - | |
| 265 | - # Оновити базу даних з встановленою компонентою | |
| 266 | - component = Component.query.filter_by(name=selected_component['name']).first() | |
| 267 | - if not component: | |
| 268 | - component = Component( | |
| 269 | - name=selected_component['name'], | |
| 270 | - description=selected_component['description'], | |
| 271 | - version=version, | |
| 272 | - git_link=selected_component['git_link'], | |
| 273 | - dependencies=code, | |
| 274 | - installed=True | |
| 275 | - ) | |
| 276 | - db.session.add(component) | |
| 277 | - else: | |
| 278 | - component.version = version | |
| 279 | - component.git_link = selected_component['git_link'] | |
| 280 | - component.dependencies = code | |
| 281 | - component.installed = True | |
| 282 | - | |
| 283 | - db.session.commit() | |
| 284 | - | |
| 285 | - return f'''Component installed successfully: {selected_component["name"]} v{version}, | |
| 286 | - \n \n please wait installing requirments... | |
| 287 | - <meta http-equiv="refresh" content="0;url=/install-requirments/{selected_component["name"]}" />''' | |
| 288 | - | |
| 289 | - except Exception as e: | |
| 290 | - return f'Error installing component: {str(e)}' | |
| 291 | - | |
| 292 | - @components_bp.route('/install-requirments/<string:selected_component_name>', methods=['GET']) | |
| 293 | - @first_login_required | |
| 294 | - def install_requirments(selected_component_name): | |
| 295 | - requirements_file = os.path.join('components', selected_component_name, "requirements.txt") | |
| 296 | - if os.path.isfile(requirements_file): | |
| 297 | - pip_command = f"{current_app.config['VENV_BIN_PATH']}/python -m pip install -r {requirements_file}" | |
| 298 | - subprocess.run(pip_command, shell=True, check=True) | |
| 299 | - return f'''Requirements installed successfully | |
| 300 | - \n \n please wait installing requirments components... | |
| 301 | - <meta http-equiv="refresh" content="1;url=/install-requirments-components" />''' | |
| 302 | - | |
| 303 | - | |
| 304 | - @components_bp.route('/install-requirments-components') | |
| 305 | - @first_login_required | |
| 306 | - def install_requirements_components(): | |
| 307 | - # Откриття файлу requirements_components.txt | |
| 308 | - requirements_file = 'requirements_components.txt' | |
| 309 | - component_ids = None | |
| 310 | - if os.path.isfile(requirements_file): | |
| 311 | - with open('requirements_components.txt', 'r') as file: | |
| 312 | - component_ids = file.read().splitlines() | |
| 313 | - if component_ids: | |
| 314 | - for component_id in component_ids: | |
| 315 | - # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти | |
| 316 | - response = requests.get( | |
| 317 | - f'/install_components/{component_id}') | |
| 318 | - return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 319 | - else: | |
| 320 | - return f'<meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 321 | - # Опрацювання відповіді (за потреби) | |
| 322 | - | |
| 323 | - | |
| 324 | - | |
| 325 | - | |
| 326 | - @components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET']) | |
| 327 | - @first_login_required | |
| 328 | - def remove_dependencies(component_id): | |
| 329 | - # Знаходимо компоненту за її ID | |
| 330 | - component = Component.query.get(component_id) | |
| 331 | - if not component: | |
| 332 | - return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 333 | - | |
| 334 | - # Шлях до файлу, з якого потрібно видалити залежності | |
| 335 | - file_path = 'routes.py' | |
| 336 | - | |
| 337 | - # Зчитуємо вміст файлу | |
| 338 | - with open(file_path, 'r') as file: | |
| 339 | - lines = file.readlines() | |
| 340 | - | |
| 341 | - # Видаляємо рядки, що містять залежності компоненти | |
| 342 | - updated_lines = [line for line in lines if line.strip() not in component.dependencies] | |
| 343 | - | |
| 344 | - # Записуємо оновлений вміст у файл | |
| 345 | - with open(file_path, 'w') as file: | |
| 346 | - file.writelines(updated_lines) | |
| 347 | - | |
| 348 | - # Оновлюємо статус компоненти | |
| 349 | - component.installed = False | |
| 350 | - db.session.commit() | |
| 351 | - | |
| 352 | - return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 353 | - | |
| 354 | - @components_bp.route('/add_dependencies/<string:component_id>', methods=['GET']) | |
| 355 | - @first_login_required | |
| 356 | - def add_dependencies(component_id): | |
| 357 | - | |
| 358 | - # Знаходимо компоненту за її ID | |
| 359 | - component = Component.query.get(component_id) | |
| 360 | - if not component: | |
| 361 | - return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 362 | - | |
| 363 | - # Шлях до файлу, з якого потрібно видалити залежності | |
| 364 | - file_path = 'routes.py' | |
| 365 | - code = component.dependencies | |
| 366 | - # Відкриття файлу у режимі дозапису | |
| 367 | - with open(file_path, 'a') as file: | |
| 368 | - # Запис нового коду у файл | |
| 369 | - file.write(code) | |
| 370 | - | |
| 371 | - # Оновлюємо статус компоненти | |
| 372 | - component.installed = True | |
| 373 | - db.session.commit() | |
| 374 | - return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 375 | - | |
| 376 | - @components_bp.route('/remove-component/<string:component_id>') | |
| 377 | - @first_login_required | |
| 378 | - def remove_component(component_id): | |
| 379 | - # Шлях до головної папки проекту | |
| 380 | - project_folder = 'components' | |
| 381 | - component = Component.query.get(component_id) | |
| 382 | - # Назва репозиторія | |
| 383 | - repository_name = component.name | |
| 384 | - # Шлях до папки репозиторія в межах проекту | |
| 385 | - repository_folder = os.path.join(project_folder, repository_name) | |
| 386 | - try: | |
| 387 | - # Перевірка наявності папки репозиторія | |
| 388 | - if os.path.exists(repository_folder): | |
| 389 | - # Видалення папки репозиторія | |
| 390 | - shutil.rmtree(repository_folder) | |
| 391 | - # Видаляємо компоненту з бази | |
| 392 | - if component: | |
| 393 | - db.session.delete(component) | |
| 394 | - db.session.commit() | |
| 395 | - | |
| 396 | - # Повертаємо повідомлення про успішне видалення | |
| 397 | - return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' | |
| 398 | - except Exception as e: | |
| 399 | - # Повертаємо повідомлення про помилку видалення | |
| 400 | - return 'Error removing component: ' + str(e) | |
| 401 | - app.register_blueprint(components_bp) |
languages/__pycache__/find_language.cpython-310.pyc
No preview for this file type
languages/__pycache__/views.cpython-310.pyc
No preview for this file type
languages/babel_translation_directories.yml
| 1 | +babel_translation_directories: languages;components/k2test/k2test/languages |
languages/find_language.py
| 1 | -from k2.root import Component |
languages/views.py
| 1 | -import yaml | |
| 2 | -from flask import session, g | |
| 3 | -from main import app, babel | |
| 4 | - | |
| 5 | -def load_languages(): | |
| 6 | - with open('languages/languages.yml', 'r') as file: | |
| 7 | - languages = yaml.safe_load(file) | |
| 8 | - return print(languages) | |
| 9 | - | |
| 10 | -def get_locale(): | |
| 11 | - if 'lang' in session: | |
| 12 | - # Отримати обрану мову з сеансу користувача | |
| 13 | - return session['lang'] | |
| 14 | - else: | |
| 15 | - # Повернути мову за замовчуванням з налаштувань додатку | |
| 16 | - return app.config['DEFAULT_LANGUAGE'] | |
| 17 | -babel.init_app(app, locale_selector=get_locale) |
main.py
| 1 | -import pytz | |
| 2 | -from flask import Flask | |
| 3 | 1 | from flask_cors import CORS |
| 4 | -from db.database import init_db | |
| 5 | -import os | |
| 6 | -import sys | |
| 7 | -from k2.root import * | |
| 8 | -from flask_login import LoginManager | |
| 9 | 2 | from flask_babel import Babel |
| 3 | +#from k2.k2inst import * | |
| 4 | +from flask import Flask | |
| 5 | +from k2.k2cfg import k2 | |
| 10 | 6 | |
| 11 | - | |
| 12 | 7 | # configure flask app |
| 13 | 8 | app = Flask(__name__) |
| 14 | -venv_path = os.path.join(os.path.dirname(sys.prefix), 'venv/Scripts') | |
| 15 | -app.config['VENV_BIN_PATH'] = venv_path | |
| 16 | -app.config['JSON_SORT_KEYS'] = False | |
| 17 | -app.config['TIMEZONE'] = pytz.timezone('Europe/Kiev') | |
| 18 | -app.config['SECRET_KEY'] = 'JH&INH987gFDHdsagh&8dwbjdw8ckw' | |
| 19 | -app.config['DOMAIN'] = 'http://127.0.0.1:5001/' | |
| 20 | -app.config['DEFAULT_LANGUAGE'] = 'en' | |
| 21 | -app.config['CURRENT_LANGUAGE'] = '' | |
| 22 | -app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'languages;components/k2test/k2test/languages' | |
| 9 | +app.config['SECRET_KEY'] = k2.secret_key | |
| 10 | +app.config.from_object(k2) | |
| 23 | 11 | |
| 24 | -# setting flask app | |
| 25 | -init_db(app) | |
| 12 | +# init db | |
| 13 | +k2().init_db(app) | |
| 26 | 14 | CORS(app) |
| 15 | + | |
| 16 | +#translate | |
| 17 | +k2.load_babel_translation_directories() | |
| 18 | +app.config['BABEL_TRANSLATION_DIRECTORIES'] = k2.babel_translation_directories | |
| 27 | 19 | babel = Babel(app) |
| 20 | +babel.init_app(app, locale_selector=k2.get_locale) | |
| 28 | 21 | |
| 29 | 22 | # flask routing |
| 30 | 23 | from routes import * |
| 24 | + | |
| 31 | 25 | if __name__ == '__main__': |
| 32 | 26 | app.run(debug=True, port=5000) |
routes.py
templates/dashboard.html
| ... | ... | @@ -32,6 +32,7 @@ |
| 32 | 32 | <p> <a href="/logout">вихід</a></p> |
| 33 | 33 | <p> <a href="{{ url_for('components.change_language', lang='en') }}">en</a> | <a href="{{ url_for('components.change_language', lang='uk') }}">uk</a></p> |
| 34 | 34 | {{language}} |
| 35 | +{{lang_d}} | |
| 35 | 36 | |
| 36 | 37 | <h2>{{ _('Installed components') }}</h2> |
| 37 | 38 | |
| ... | ... | @@ -130,7 +131,7 @@ |
| 130 | 131 | <div> |
| 131 | 132 | <h2>{{ component.name|title }}</h2> |
| 132 | 133 | <p>{{ component.description }}</p> |
| 133 | - <p>ВЕРСІЯ {{ component.version }}</p> | |
| 134 | + <p>ВЕРСІЯ {{ component.latest_version }}</p> | |
| 134 | 135 | {% if component.name in components_names %} |
| 135 | 136 | <button type="button" class="btn btn-success">Installed</button> |
| 136 | 137 | {% else %} |