Commit 7285fe209e8a9db38cd2eecac6a709b0e4990cda

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

add remove menu items function

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