Commit a2bb956ac6582cd5509f97c59deded1cfd8cfad7

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

change get menu

Showing 12 changed files with 26 additions and 65 deletions Inline Diff

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