jira-ai-assistant-docker / interface.py
DocUA's picture
Файл interface
26e822e
raw
history blame
10.4 kB
import gradio as gr
import os
from pathlib import Path
from datetime import datetime
import matplotlib.pyplot as plt
import logging
logger = logging.getLogger("jira_assistant_interface")
def launch_interface(app):
"""
Запуск інтерфейсу користувача Gradio
Args:
app: Екземпляр JiraAssistantApp
"""
# Функція для обробки завантаження та аналізу CSV
def analyze_csv(file_obj, inactive_days, include_ai):
if file_obj is None:
return "Помилка: файл не вибрано", None, None, None, None
try:
logger.info(f"Отримано файл: {file_obj.name}, тип: {type(file_obj)}")
# Створення тимчасового файлу
temp_file_path = os.path.join("temp", f"temp_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv")
# У Gradio 5.19.0 об'єкт файлу має різну структуру
# file_obj може бути шляхом до файлу або містити атрибут 'name'
if hasattr(file_obj, 'name'):
source_path = file_obj.name
# Копіювання файлу
import shutil
shutil.copy2(source_path, temp_file_path)
else:
# Якщо це не шлях до файлу, ймовірно це вже самі дані
with open(temp_file_path, "w", encoding="utf-8") as f:
f.write(str(file_obj))
# Аналіз даних
api_key = os.getenv("OPENAI_API_KEY") if include_ai else None
result = app.analyze_csv_file(
temp_file_path,
inactive_days=inactive_days,
include_ai=include_ai,
api_key=api_key
)
# Видалення тимчасового файлу
try:
os.remove(temp_file_path)
except:
pass
if result.get("error"):
return result.get("error"), None, None, None, None
return (
result.get("report", ""),
result.get("visualizations", {}).get("status"),
result.get("visualizations", {}).get("priority"),
result.get("visualizations", {}).get("created_timeline"),
result.get("ai_analysis", "AI аналіз буде доступний у наступних версіях додатку.")
)
except Exception as e:
import traceback
error_msg = f"Помилка аналізу: {str(e)}\n\n{traceback.format_exc()}"
logger.error(error_msg)
return error_msg, None, None, None, None
# Функція для збереження звіту
def save_report_handler(report_text, format_type, include_visualizations):
if not report_text:
return "Помилка: спочатку виконайте аналіз даних"
return app.save_report(
format_type=format_type,
include_visualizations=include_visualizations
)
# Функція для тестування підключення до Jira
def test_jira_connection_handler(url, username, api_token):
if not url or not username or not api_token:
return "Помилка: необхідно заповнити всі поля (URL, користувач, API токен)"
success = app.test_jira_connection(url, username, api_token)
if success:
return "✅ Успішне підключення до Jira API"
else:
return "❌ Помилка підключення до Jira. Перевірте введені дані."
# Створення інтерфейсу Gradio
with gr.Blocks(title="Jira AI Assistant") as interface:
gr.Markdown("# 🔍 Jira AI Assistant")
with gr.Tabs():
with gr.Tab("CSV Аналіз"):
with gr.Row():
with gr.Column(scale=1):
file_input = gr.File(label="Завантажити CSV файл Jira")
inactive_days = gr.Slider(minimum=1, maximum=90, value=14, step=1,
label="Кількість днів для визначення неактивних тікетів")
include_ai = gr.Checkbox(label="Включити AI аналіз", value=False)
analyze_btn = gr.Button("Аналізувати", variant="primary")
with gr.Accordion("Збереження звіту", open=False):
format_type = gr.Dropdown(
choices=["markdown", "html", "pdf"],
value="markdown",
label="Формат звіту"
)
include_visualizations = gr.Checkbox(
label="Включити візуалізації",
value=True
)
save_btn = gr.Button("Зберегти звіт")
save_output = gr.Textbox(label="Статус збереження")
with gr.Column(scale=2):
with gr.Tabs():
with gr.Tab("Звіт"):
report_output = gr.Markdown()
with gr.Tab("Візуалізації"):
with gr.Row():
status_plot = gr.Plot(label="Статуси тікетів")
priority_plot = gr.Plot(label="Пріоритети тікетів")
timeline_plot = gr.Plot(label="Часова шкала")
with gr.Tab("AI Аналіз"):
ai_output = gr.Markdown()
# Встановлюємо обробники подій
analyze_btn.click(
analyze_csv,
inputs=[file_input, inactive_days, include_ai],
outputs=[report_output, status_plot, priority_plot, timeline_plot, ai_output]
)
save_btn.click(
save_report_handler,
inputs=[report_output, format_type, include_visualizations],
outputs=[save_output]
)
with gr.Tab("Jira API"):
gr.Markdown("## Підключення до Jira API")
with gr.Row():
jira_url = gr.Textbox(
label="Jira URL",
placeholder="https://your-company.atlassian.net"
)
jira_username = gr.Textbox(
label="Ім'я користувача Jira",
placeholder="[email protected]"
)
jira_api_token = gr.Textbox(
label="Jira API Token",
type="password"
)
test_connection_btn = gr.Button("Тестувати з'єднання")
connection_status = gr.Textbox(label="Статус підключення")
test_connection_btn.click(
test_jira_connection_handler,
inputs=[jira_url, jira_username, jira_api_token],
outputs=[connection_status]
)
gr.Markdown("## ⚠️ Ця функція буде доступна у наступних версіях")
with gr.Tab("AI Асистенти"):
gr.Markdown("## AI Асистенти для Jira")
gr.Markdown("⚠️ Ця функція буде доступна у наступних версіях")
with gr.Accordion("Зразок інтерфейсу"):
question = gr.Textbox(
label="Запитання",
placeholder="Наприклад: Які тікети мають найвищий пріоритет?",
lines=2
)
answer = gr.Markdown(label="Відповідь")
with gr.Tab("Інтеграції"):
gr.Markdown("## Інтеграції з зовнішніми системами")
gr.Markdown("⚠️ Ця функція буде доступна у наступних версіях")
with gr.Accordion("Slack інтеграція"):
slack_channel = gr.Textbox(
label="Slack канал",
placeholder="#project-updates"
)
slack_message = gr.Textbox(
label="Повідомлення",
placeholder="Тижневий звіт по проекту",
lines=3
)
slack_send_btn = gr.Button("Надіслати у Slack", interactive=False)
# Запуск інтерфейсу
interface.launch()
# Можливість запустити інтерфейс самостійно (для тестування)
if __name__ == "__main__":
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app import JiraAssistantApp
app_instance = JiraAssistantApp()
launch_interface(app_instance)