Commit 79305bf74d3bb28210125c8f6866d0ea2486ff88

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

add adm

Showing 27 changed files with 393 additions and 16 deletions Inline Diff

__pycache__/routes.cpython-310.pyc
No preview for this file type
components/adm/README.md
File was created 1 # main.py
2
3 from components.adm.adm.views import adm
4 from components.test.test.views import test
5
6 app.register_blueprint(adm, url_prefix='/adm')
7
8 cd components/adm
9 pip install -r requirements.txt
10
11
12 endpoint "http://127.0.0.1:5000/adm/register"
13 dictionary to register in such way
14 {
15 "login": "xxx",
16 "password": "xxx",
17 "name": "xxx",
18 "email": "xxx"
19 }
20
21
22 endpoint "http://127.0.0.1:5000/adm/login"
23 dictionary to login in such way
24 {
25 "login":"xxx",
26 "password":"xxx"
27 }
28
29 endpoint http://127.0.0.1:5000/adm/changePassword
30 dictionary to changePassword in such way
31 {
32 "old_password":"xxx",
33 "new_password": "xxx",
34 "re_new_password": "xxx"
35 }
36 endpoint http://127.0.0.1:5000/adm/newUser
37 {
38 "login": "xxx",
39 "password": "xxx",
40 "name": "xxx",
41 "email": "xxx",
42 "phone": "xxx",
43 "repassword": "xxx"
44
45 }
components/adm/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/adm/adm/.idea/.gitignore
File was created 1 # Default ignored files
2 /shelf/
3 /workspace.xml
4 # Editor-based HTTP Client requests
5 /httpRequests/
6 # Datasource local storage ignored files
7 /dataSources/
8 /dataSources.local.xml
9
components/adm/adm/.idea/adm.iml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <module type="PYTHON_MODULE" version="4">
3 <component name="NewModuleRootManager">
4 <content url="file://$MODULE_DIR$" />
5 <orderEntry type="inheritedJdk" />
6 <orderEntry type="sourceFolder" forTests="false" />
7 </component>
8 <component name="TemplatesService">
9 <option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
10 <option name="TEMPLATE_FOLDERS">
11 <list>
12 <option value="$MODULE_DIR$/templates" />
13 </list>
14 </option>
15 </component>
16 </module>
components/adm/adm/.idea/inspectionProfiles/Project_Default.xml
File was created 1 <component name="InspectionProjectProfileManager">
2 <profile version="1.0">
3 <option name="myName" value="Project Default" />
4 <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5 <inspection_tool class="JSHint" enabled="true" level="ERROR" enabled_by_default="true" />
6 <inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
7 <option name="ignoredPackages">
8 <value>
9 <list size="13">
10 <item index="0" class="java.lang.String" itemvalue="blinker" />
11 <item index="1" class="java.lang.String" itemvalue="greenlet" />
12 <item index="2" class="java.lang.String" itemvalue="Werkzeug" />
13 <item index="3" class="java.lang.String" itemvalue="Flask-WTF" />
14 <item index="4" class="java.lang.String" itemvalue="SQLAlchemy" />
15 <item index="5" class="java.lang.String" itemvalue="MarkupSafe" />
16 <item index="6" class="java.lang.String" itemvalue="click" />
17 <item index="7" class="java.lang.String" itemvalue="Flask-SQLAlchemy" />
18 <item index="8" class="java.lang.String" itemvalue="Jinja2" />
19 <item index="9" class="java.lang.String" itemvalue="Flask-Login" />
20 <item index="10" class="java.lang.String" itemvalue="WTForms" />
21 <item index="11" class="java.lang.String" itemvalue="itsdangerous" />
22 <item index="12" class="java.lang.String" itemvalue="Flask" />
23 </list>
24 </value>
25 </option>
26 </inspection_tool>
27 </profile>
28 </component>
components/adm/adm/.idea/inspectionProfiles/profiles_settings.xml
File was created 1 <component name="InspectionProjectProfileManager">
2 <settings>
3 <option name="USE_PROJECT_PROFILE" value="false" />
4 <version value="1.0" />
5 </settings>
6 </component>
components/adm/adm/.idea/misc.xml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
4 </project>
components/adm/adm/.idea/modules.xml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="ProjectModuleManager">
4 <modules>
5 <module fileurl="file://$PROJECT_DIR$/.idea/adm.iml" filepath="$PROJECT_DIR$/.idea/adm.iml" />
6 </modules>
7 </component>
8 </project>
components/adm/adm/.idea/vcs.xml
File was created 1 <?xml version="1.0" encoding="UTF-8"?>
2 <project version="4">
3 <component name="VcsDirectoryMappings">
4 <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5 </component>
6 </project>
components/adm/adm/__pycache__/__init__.cpython-310.pyc
No preview for this file type
components/adm/adm/__pycache__/__init__.cpython-311.pyc
No preview for this file type
components/adm/adm/__pycache__/models.cpython-310.pyc
No preview for this file type
components/adm/adm/__pycache__/views.cpython-310.pyc
No preview for this file type
components/adm/adm/__pycache__/views.cpython-311.pyc
No preview for this file type
components/adm/adm/models.py
File was created 1 import uuid
2 from sqlalchemy import Column, Integer, String
3 from sqlalchemy.ext.declarative import declarative_base
4 from flask_jwt_extended import create_access_token
5 from datetime import timedelta
6 import hashlib
7 from flask import current_app as k2
8
9
10 Base = declarative_base()
11
12 class k2users(Base):
13 __tablename__ = 'k2users'
14 user_id = Column(Integer, primary_key=True)
15 login = Column(String(50))
16 name = Column(String(50))
17 email = Column(String(150))
18 password = Column(String(50))
19 phone = Column(String(20))
20
21 def __init__(self, **kwargs):
22 self.user_id = hashlib.md5(str(uuid.uuid4()).encode()).hexdigest()
23 self.login = kwargs.get('login')
24 self.password = hashlib.md5(kwargs.get('password').encode()).hexdigest()
25 self.name = kwargs.get('name')
26 self.email = kwargs.get('email')
27 self.phone = kwargs.get('phone')
28
29 def get_token(self, expire_time=24):
30 expires_delta = timedelta(expire_time)
31 token = create_access_token(identity=self.user_id, expires_delta=expires_delta)
32 return token
33
34 @classmethod
35 def authenticate(cls, login, password):
36 session = k2.extensions['sqlalchemy'].db.session
37 user = ''
38 try:
39 user = session.query(cls).filter(cls.login == login).filter(cls.password == hashlib.md5(password.encode()).hexdigest()).one()
40 except:
41 user = None
42
43 return user
components/adm/adm/views.py
File was created 1 import hashlib
2 import uuid
3 from flask import Blueprint, request, jsonify
4 from flask import current_app as k2
5 from flask_jwt_extended import jwt_required, get_jwt_identity
6 # from flask_sqlalchemy import session
7 # from sqlalchemy.orm import sessionmaker
8 # from k2.k2inst import Component
9
10 from .models import k2users
11
12
13 adm = Blueprint('adm', __name__, template_folder='templates', static_folder='static', static_url_path='/adm')
14
15
16 @adm.route('/register', methods=["POST"])
17 def register():
18 params = request.json
19 session = k2.extensions['sqlalchemy'].db.session
20 exist = session.query(k2users).filter_by(login=request.json['login']).first()
21 if not exist:
22 user = k2users(**params)
23 session.add(user)
24 session.commit()
25 token = user.get_token()
26 return {'access_token': token}
27 else:
28 return jsonify({'error': 'User exist'}), 401
29
30
31 @adm.route('/login', methods=["POST"])
32 def login():
33 params = request.json
34 login = params.get('login')
35 password = params.get('password')
36 user = k2users.authenticate(login, password)
37 if user:
38 token = user.get_token()
39 return {'access_token': token}
40 else:
41 return jsonify({'error': 'Unauthorized'}), 401
42
43
44 @adm.route('/logout', methods=["GET"])
45 @jwt_required()
46 def logout():
47 response = {
48 'message': 'Logged out successfully'
49 }
50 return jsonify(response)
51
52
53 @adm.route('/users', methods=["GET"])
54 @jwt_required()
55 def grid_users():
56 return jsonify({"data": "users"})
57
58
59 @adm.route('/roles', methods=["GET"])
60 @jwt_required()
61 def grid_roles():
62 return jsonify({"data": "roles"})
63
64
65 @adm.route('/usersclients', methods=["GET"])
66 @jwt_required()
67 def users_clients():
68 return jsonify({"data": "roles"})
69
70 @adm.route('/menuaaccess', methods=["GET"])
71 @jwt_required()
72 def menu_aaccess():
73 return jsonify({"data": "roles"})
74
75
76 @adm.route('/newUser', methods=["GET", "POST"])
77 @jwt_required()
78 def newUser():
79 session = k2.extensions['sqlalchemy'].db.session
80 exist = session.query(k2users).filter_by(login=request.json['login']).first()
81 if not exist:
82 res = k2users(
83 user_id=hashlib.md5(str(uuid.uuid4()).encode()).hexdigest(),
84 login=request.json['login'],
85 name=request.json['name'],
86 email=request.json['email'],
87 password=hashlib.md5(request.json['password'].encode()).hexdigest(),
88 phone=request.json['phone'])
89 if res:
90 session.add(res)
91 session.commit()
92 return jsonify({'status': 'ok'})
93 else:
94 return jsonify({'error': 'Such user exist'}), 404
95
96
97 @adm.route('/changePassword', methods=["POST"])
98 @jwt_required()
99 def changePassword():
100 session = k2.extensions['sqlalchemy'].db.session
101 current_user = get_jwt_identity()
102 user = session.query(k2users).filter_by(user_id=current_user).first()
103 if user.password == hashlib.md5(request.json['old_password'].encode()).hexdigest():
104 if request.json['new_password'] == request.json['re_new_password']:
105 user.password = hashlib.md5(request.json['new_password'].encode()).hexdigest()
106 session.commit()
107 else:
108 return jsonify({'error': 'Пароль не найден в базе'}), 404
109 else:
110 return jsonify({'error': 'Пароль не совпвдает'}), 404
111 return jsonify({'status': 'ok'})
112
113
114 @adm.route('/menu-items')
115 def menu_items():
116 menu = [
117 {
118 "title": 'Адміністрування сайту',
119 "icon": {"icon": 'mdi mdi-database'},
120 "children": [
121 {'title': 'Зміна паролю', 'to': 'adm-changePassword'},
122 {'title': 'Новий користувач', 'to': 'adm-newUser'},
123 {'title': 'Користувачі', 'to': 'adm-users'},
124 {'title': 'Користувачі клієнти', 'to': 'adm-usersclients'},
125 {'title': 'Права', 'to': 'adm-roles'},
126 {'title': 'Доступ до меню', 'to': 'adm-menuaaccess'},
127 ],
128 }]
129
130 return menu
131
132
133
134
135
136
components/adm/requirements.txt
File was created 1 alembic==1.11.1
2 Babel==2.12.1
3 bcrypt==4.0.1
4 bidict==0.22.1
5 blinker==1.6.2
6 certifi==2023.5.7
7 charset-normalizer==3.1.0
8 click==8.1.3
9 colorama==0.4.6
10 dnspython==2.3.0
11 email-validator==2.0.0.post2
12 Flask==2.3.2
13 flask-babel==3.1.0
14 Flask-Bcrypt==1.0.1
15 Flask-Cors==3.0.10
16 Flask-JWT-Extended==4.5.2
17 Flask-Login==0.6.2
18 Flask-Migrate==4.0.4
19 Flask-MySQLdb==1.0.1
20 Flask-SQLAlchemy==3.0.3
21 flask-staticdirs==1.0.1
22 Flask-WTF==1.1.1
23 greenlet==2.0.2
24 idna==3.4
25 itsdangerous==2.1.2
26 Jinja2==3.1.2
27 jsonify==0.5
28 Mako==1.2.4
29 MarkupSafe==2.1.2
30 mysql==0.0.3
31 mysql-connector==2.2.9
32 mysql-connector-python==8.0.33
33 mysqlclient==2.1.1
34 peppercorn==0.6
35 protobuf==3.20.3
36 PyJWT==2.7.0
37 python-engineio==4.4.1
38 python-socketio==5.8.0
39 pytz==2023.3
40 PyYAML==6.0
41 requests==2.31.0
42 six==1.16.0
43 SQLAlchemy==2.0.15
44 typing_extensions==4.6.2
45 urllib3==2.0.2
46 Werkzeug==2.3.4
47 WTForms==3.0.1
48
components/adm/setup.py
File was created 1 from setuptools import setup
2
3 setup(
4 name='adm',
5 version='1.0.0',
6 description='Description of my project',
7 author='Your Name',
8 author_email='yourname@example.com',
9 keywords="adm, k2",
10 python_requires=">=3.7, <=3.11.2",
11 packages=['adm'],
12 package_data={ # Optional
13 },
14 install_requires=[""],
15 )
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, jsonify
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 jsonify({'data': 'page new3'})
31 31
32 @k2test.route('/new4') 32 @k2test.route('/new4')
33 def new_component4(): 33 def new_component4():
34 return 'сторінка 4' 34 return jsonify({'data': 'page new4'})
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
42 'title': 'Тестова компонента', 41 'title': 'Тестова компонента',
43 'category': 'Тест',
44 'icon': {'icon': 'mdi-chart-timeline-variant'}, 42 'icon': {'icon': 'mdi-chart-timeline-variant'},
45 'children': [ 43 'children': [
46 {'title': 'Тест 3', 'to': 'k2test-new3'}, 44 {'title': 'Тест 3', 'to': 'k2test-new3'},
47 {'title': 'Тест 3', 'to': 'k2test-new4'}, 45 {'title': 'Тест 3', 'to': 'k2test-new4'},
48 ], 46 ],
49 } 47 }
50 48
51 ] 49 ]
52 return data 50 return data
1 - category: "\u0422\u0435\u0441\u0442" 1 - heading: APPS & PAGES
2 children: 2 - children:
3 - title: "\u0422\u0435\u0441\u0442 3" 3 - title: "\u0422\u0435\u0441\u0442 3"
4 to: k2test-new3 4 to: k2test-new3
5 - title: "\u0422\u0435\u0441\u0442 3" 5 - title: "\u0422\u0435\u0441\u0442 3"
6 to: k2test-new4 6 to: k2test-new4
7 component_name: k2test 7 component_name: k2test
8 icon: 8 icon:
9 icon: mdi-chart-timeline-variant 9 icon: mdi-chart-timeline-variant
10 id: 2 10 id: 2
11 title: "\u0422\u0435\u0441\u0442\u043E\u0432\u0430 \u043A\u043E\u043C\u043F\u043E\ 11 title: "\u0422\u0435\u0441\u0442\u043E\u0432\u0430 \u043A\u043E\u043C\u043F\u043E\
12 \u043D\u0435\u043D\u0442\u0430" 12 \u043D\u0435\u043D\u0442\u0430"
13 - children:
14 - title: "\u0417\u043C\u0456\u043D\u0430 \u043F\u0430\u0440\u043E\u043B\u044E"
15 to: adm-changePassword
16 - title: "\u041D\u043E\u0432\u0438\u0439 \u043A\u043E\u0440\u0438\u0441\u0442\u0443\
17 \u0432\u0430\u0447"
18 to: adm-newUser
19 - title: "\u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456"
20 to: adm-users
21 - title: "\u041A\u043E\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0456 \u043A\
22 \u043B\u0456\u0454\u043D\u0442\u0438"
23 to: adm-usersclients
24 - title: "\u041F\u0440\u0430\u0432\u0430"
25 to: adm-roles
26 - title: "\u0414\u043E\u0441\u0442\u0443\u043F \u0434\u043E \u043C\u0435\u043D\u044E"
27 to: adm-menuaaccess
28 component_name: adm
29 icon:
30 icon: mdi mdi-database
31 id: 3
32 title: "\u0410\u0434\u043C\u0456\u043D\u0456\u0441\u0442\u0440\u0443\u0432\u0430\
33 \u043D\u043D\u044F \u0441\u0430\u0439\u0442\u0443"
13 34
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 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 print(k2.domain) 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
341 else: 341 else:
342 data = [{ 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 343 # add component_name key for menu items
349 for item in data: 344 for item in data:
350 item['component_name'] = selected_component_name 345 item['component_name'] = selected_component_name
351 file_path = 'components/menu.yml' 346 file_path = 'components/menu.yml'
352 append_to_yaml_file(file_path, data) 347 append_to_yaml_file(file_path, data)
353 k2.get_menu_elenents() 348 k2.get_menu_elenents()
354 349
355 #install requirements 350 #install requirements
356 requirements_file = os.path.join('components', selected_component_name, "requirements.txt") 351 requirements_file = os.path.join('components', selected_component_name, "requirements.txt")
357 if os.path.isfile(requirements_file): 352 if os.path.isfile(requirements_file):
358 pip_command = f"{k2.venv_bin_path}/python -m pip install -r {requirements_file}" 353 pip_command = f"{k2.venv_bin_path}/python -m pip install -r {requirements_file}"
359 subprocess.run(pip_command, shell=True, check=True) 354 subprocess.run(pip_command, shell=True, check=True)
360 return f'''Requirements installed successfully 355 return f'''Requirements installed successfully
361 \n \n please wait installing requirments components... 356 \n \n please wait installing requirments components...
362 <meta http-equiv="refresh" content="1;url=/install-requirments-components" />''' 357 <meta http-equiv="refresh" content="1;url=/install-requirments-components" />'''
363 358
364 @components_bp.route('/install-requirments-components') 359 @components_bp.route('/install-requirments-components')
365 def install_requirements_components(): 360 def install_requirements_components():
366 # Откриття файлу requirements_components.txt 361 # Откриття файлу requirements_components.txt
367 requirements_file = 'requirements_components.txt' 362 requirements_file = 'requirements_components.txt'
368 component_ids = None 363 component_ids = None
369 if os.path.isfile(requirements_file): 364 if os.path.isfile(requirements_file):
370 with open('requirements_components.txt', 'r') as file: 365 with open('requirements_components.txt', 'r') as file:
371 component_ids = file.read().splitlines() 366 component_ids = file.read().splitlines()
372 if component_ids: 367 if component_ids:
373 for component_id in component_ids: 368 for component_id in component_ids:
374 # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти 369 # Виклик роуту '/install_components/<string:component_name>' для кожної назви компоненти
375 response = requests.get( 370 response = requests.get(
376 f'/install_components/{component_id}') 371 f'/install_components/{component_id}')
377 return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' 372 return f'Requirements components installed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
378 else: 373 else:
379 return f'<meta http-equiv="refresh" content="1;url=/dashboard" />' 374 return f'<meta http-equiv="refresh" content="1;url=/dashboard" />'
380 # Опрацювання відповіді (за потреби) 375 # Опрацювання відповіді (за потреби)
381 376
382 377
383 @components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET']) 378 @components_bp.route('/remove_dependencies/<string:component_id>', methods=['GET'])
384 def remove_dependencies(component_id): 379 def remove_dependencies(component_id):
385 # Знаходимо компоненту за її ID 380 # Знаходимо компоненту за її ID
386 component = Component.query.get(component_id) 381 component = Component.query.get(component_id)
387 if not component: 382 if not component:
388 return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' 383 return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
389 #remove menu items 384 #remove menu items
390 component_name = component.name 385 component_name = component.name
391 file_path = "components/menu.yml" 386 file_path = "components/menu.yml"
392 remove_from_yaml_file(file_path, component_name) 387 remove_from_yaml_file(file_path, component_name)
393 388
394 # remove routes 389 # remove routes
395 file_path = 'routes.py' 390 file_path = 'routes.py'
396 with open(file_path, 'r') as file: 391 with open(file_path, 'r') as file:
397 lines = file.readlines() 392 lines = file.readlines()
398 393
399 updated_lines = [line for line in lines if line.strip() not in component.dependencies] 394 updated_lines = [line for line in lines if line.strip() not in component.dependencies]
400 with open(file_path, 'w') as file: 395 with open(file_path, 'w') as file:
401 file.writelines(updated_lines) 396 file.writelines(updated_lines)
402 397
403 component.installed = False 398 component.installed = False
404 db.session.commit() 399 db.session.commit()
405 400
406 return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />' 401 return 'Component successfully turn off <meta http-equiv="refresh" content="1;url=/dashboard" />'
407 402
408 @components_bp.route('/add_dependencies/<string:component_id>', methods=['GET']) 403 @components_bp.route('/add_dependencies/<string:component_id>', methods=['GET'])
409 def add_dependencies(component_id): 404 def add_dependencies(component_id):
410 405
411 # Знаходимо компоненту за її ID 406 # Знаходимо компоненту за її ID
412 component = Component.query.get(component_id) 407 component = Component.query.get(component_id)
413 if not component: 408 if not component:
414 return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />' 409 return 'Component not found <meta http-equiv="refresh" content="1;url=/dashboard" />'
415 410
416 # Шлях до файлу, з якого потрібно видалити залежності 411 # Шлях до файлу, з якого потрібно видалити залежності
417 file_path = 'routes.py' 412 file_path = 'routes.py'
418 code = component.dependencies 413 code = component.dependencies
419 # Відкриття файлу у режимі дозапису 414 # Відкриття файлу у режимі дозапису
420 with open(file_path, 'a') as file: 415 with open(file_path, 'a') as file:
421 # Запис нового коду у файл 416 # Запис нового коду у файл
422 file.write(code) 417 file.write(code)
423 418
424 # Оновлюємо статус компоненти 419 # Оновлюємо статус компоненти
425 component.installed = True 420 component.installed = True
426 db.session.commit() 421 db.session.commit()
427 return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' 422 return 'Dependencies added successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
428 423
429 @components_bp.route('/remove-component/<string:component_id>') 424 @components_bp.route('/remove-component/<string:component_id>')
430 def remove_component(component_id): 425 def remove_component(component_id):
431 # Шлях до головної папки проекту 426 # Шлях до головної папки проекту
432 project_folder = 'components' 427 project_folder = 'components'
433 component = Component.query.get(component_id) 428 component = Component.query.get(component_id)
434 # Назва репозиторія 429 # Назва репозиторія
435 repository_name = component.name 430 repository_name = component.name
436 # Шлях до папки репозиторія в межах проекту 431 # Шлях до папки репозиторія в межах проекту
437 repository_folder = os.path.join(project_folder, repository_name) 432 repository_folder = os.path.join(project_folder, repository_name)
438 try: 433 try:
439 # Перевірка наявності папки репозиторія 434 # Перевірка наявності папки репозиторія
440 if os.path.exists(repository_folder): 435 if os.path.exists(repository_folder):
441 # Видалення папки репозиторія 436 # Видалення папки репозиторія
442 shutil.rmtree(repository_folder) 437 shutil.rmtree(repository_folder)
443 # Видаляємо компоненту з бази 438 # Видаляємо компоненту з бази
444 if component: 439 if component:
445 db.session.delete(component) 440 db.session.delete(component)
446 db.session.commit() 441 db.session.commit()
447 442
448 # Повертаємо повідомлення про успішне видалення 443 # Повертаємо повідомлення про успішне видалення
449 return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />' 444 return 'Component removed successfully <meta http-equiv="refresh" content="1;url=/dashboard" />'
450 except Exception as e: 445 except Exception as e:
451 # Повертаємо повідомлення про помилку видалення 446 # Повертаємо повідомлення про помилку видалення
452 return 'Error removing component: ' + str(e) 447 return 'Error removing component: ' + str(e)
453 448
454 @components_bp.route('/api/main-menu/') 449 @components_bp.route('/api/main-menu/')
455 def project_menu(): 450 def project_menu():
456 return k2.menu 451 return k2.menu
457 452
languages/babel_translation_directories.yml
1 babel_translation_directories: languages;components/k2test/k2test/languages 1 babel_translation_directories: languages;components/k2test/k2test/languages;components/adm/adm/languages
2 2
1 from flask import Flask 1 from flask import Flask
2 #app = Flask(__name__) 2 #app = Flask(__name__)
3 from main import app, babel 3 from main import app, babel
4 from k2.k2inst import components_bp 4 from k2.k2inst import components_bp
5 app.register_blueprint(components_bp) 5 app.register_blueprint(components_bp)
6
7 from components.k2test.k2test.views import k2test 6 from components.k2test.k2test.views import k2test
8 app.register_blueprint(k2test, url_prefix='/k2test') 7 app.register_blueprint(k2test, url_prefix='/k2test')
8
9 from components.adm.adm.views import adm
10 app.register_blueprint(adm, url_prefix='/adm')