Commit 821570955a9bcc49053ed16df3d4b7d1da58c785

Authored by Василь Свідрик
1 parent 0fd7982778
Exists in master

add get menu-items

Showing 14 changed files with 120 additions and 18 deletions Inline Diff

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