Compare View

switch
from
...
to
 
Commits (7)

Changes

Showing 14 changed files Inline Diff

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