Update app.py
Browse files
app.py
CHANGED
@@ -397,29 +397,26 @@ def update_session_list():
|
|
397 |
print(f"Error updating session list: {e}")
|
398 |
return gr.update(choices=[])
|
399 |
|
400 |
-
|
|
|
401 |
try:
|
402 |
-
|
403 |
-
return
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
conn = sqlite3.connect('chat_history.db')
|
408 |
-
c = conn.cursor()
|
409 |
-
c.execute("""
|
410 |
-
SELECT prompt, response, timestamp
|
411 |
-
FROM chat_history
|
412 |
-
WHERE session_id = ?
|
413 |
-
ORDER BY timestamp DESC
|
414 |
-
""", (session_id,))
|
415 |
-
history = c.fetchall()
|
416 |
-
conn.close()
|
417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
html_content = """
|
419 |
<style>
|
420 |
.prompt-grid {
|
421 |
display: grid;
|
422 |
-
grid-template-columns: repeat(
|
423 |
gap: 20px;
|
424 |
padding: 20px;
|
425 |
}
|
@@ -436,37 +433,43 @@ def load_session_history(selected_session):
|
|
436 |
transform: translateY(-2px);
|
437 |
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
|
438 |
}
|
439 |
-
.
|
440 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
441 |
color: #666;
|
442 |
-
|
|
|
|
|
|
|
443 |
}
|
444 |
</style>
|
445 |
"""
|
446 |
|
447 |
-
# jQuery 추가
|
448 |
html_content += """
|
449 |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
|
450 |
"""
|
451 |
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
short_prompt = prompt[:100] + "..." if len(prompt) > 100 else prompt
|
457 |
-
formatted_time = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S.%f').strftime('%Y-%m-%d %H:%M')
|
458 |
-
|
459 |
-
# HTML 이스케이프 처리
|
460 |
-
escaped_prompt = html.escape(prompt).replace('"', '"')
|
461 |
-
escaped_response = html.escape(response).replace('"', '"')
|
462 |
|
463 |
html_content += f"""
|
464 |
-
<div class="prompt-card"
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
<div>{html.escape(short_prompt)}</div>
|
469 |
-
<div class="timestamp">{formatted_time}</div>
|
470 |
</div>
|
471 |
"""
|
472 |
|
@@ -474,69 +477,24 @@ def load_session_history(selected_session):
|
|
474 |
</div>
|
475 |
<script>
|
476 |
function handleCardClick(card) {
|
477 |
-
console.log('Card clicked');
|
478 |
-
|
479 |
-
// 프롬프트와 응답 데이터 가져오기
|
480 |
const prompt = card.getAttribute('data-prompt');
|
481 |
-
const response = card.getAttribute('data-response');
|
482 |
-
|
483 |
-
console.log('Prompt:', prompt);
|
484 |
-
console.log('Response:', response);
|
485 |
-
|
486 |
-
// 텍스트 영역 찾기 및 업데이트
|
487 |
const textarea = document.querySelector('textarea');
|
488 |
if (textarea) {
|
489 |
-
console.log('Found textarea');
|
490 |
textarea.value = prompt;
|
491 |
|
492 |
-
// 코드 추출
|
493 |
-
let code = response;
|
494 |
-
if (response.includes('```html')) {
|
495 |
-
const match = response.match(/```html\\n([\\s\\S]*?)\\n```/);
|
496 |
-
if (match) {
|
497 |
-
code = match[1];
|
498 |
-
}
|
499 |
-
}
|
500 |
-
|
501 |
-
console.log('Extracted code:', code);
|
502 |
-
|
503 |
-
// Base64 인코딩
|
504 |
-
const encodedHtml = btoa(unescape(encodeURIComponent(code.trim())));
|
505 |
-
const dataUri = `data:text/html;charset=utf-8;base64,${encodedHtml}`;
|
506 |
-
|
507 |
-
// iframe 업데이트
|
508 |
-
const iframe = document.querySelector('.html_content iframe');
|
509 |
-
if (iframe) {
|
510 |
-
console.log('Found iframe');
|
511 |
-
iframe.src = dataUri;
|
512 |
-
}
|
513 |
-
|
514 |
-
// Code 실행 버튼 찾기 및 클릭
|
515 |
setTimeout(() => {
|
516 |
const executeButton = $('button:contains("Code 실행")');
|
517 |
if (executeButton.length) {
|
518 |
-
console.log('Found execute button');
|
519 |
executeButton[0].click();
|
520 |
-
} else {
|
521 |
-
console.log('Execute button not found');
|
522 |
}
|
523 |
}, 100);
|
524 |
|
525 |
-
// 드로어 닫기
|
526 |
const drawer = document.querySelector('.session-drawer');
|
527 |
if (drawer) {
|
528 |
-
console.log('Closing drawer');
|
529 |
drawer.style.display = 'none';
|
530 |
}
|
531 |
-
} else {
|
532 |
-
console.log('Textarea not found');
|
533 |
}
|
534 |
}
|
535 |
-
|
536 |
-
// 페이지 로드 완료 후 실행
|
537 |
-
$(document).ready(function() {
|
538 |
-
console.log('Session history loaded');
|
539 |
-
});
|
540 |
</script>
|
541 |
"""
|
542 |
|
@@ -620,39 +578,34 @@ with gr.Blocks(css_paths="app.css",theme=theme) as demo:
|
|
620 |
with ms.Application() as app:
|
621 |
with antd.ConfigProvider():
|
622 |
# Drawer 컴포넌트들
|
|
|
|
|
|
|
623 |
with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer:
|
624 |
code_output = legacy.Markdown()
|
625 |
|
626 |
with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer:
|
627 |
history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot")
|
628 |
|
629 |
-
|
630 |
with antd.Drawer(
|
631 |
open=False,
|
632 |
-
title="
|
633 |
placement="right",
|
634 |
width="900px",
|
635 |
elem_classes="session-drawer"
|
636 |
) as session_drawer:
|
637 |
with antd.Flex(vertical=True, gap="middle"):
|
638 |
-
gr.Markdown("### Previous Sessions")
|
639 |
-
session_list = gr.Dropdown(
|
640 |
-
label="Select a session to view history",
|
641 |
-
choices=[],
|
642 |
-
elem_classes="session-list"
|
643 |
-
)
|
644 |
-
|
645 |
session_history = gr.HTML(
|
646 |
elem_classes="session-history"
|
647 |
)
|
648 |
-
|
649 |
-
|
650 |
close_btn = antd.Button(
|
651 |
"Close",
|
652 |
type="default",
|
653 |
elem_classes="close-btn"
|
654 |
)
|
655 |
|
|
|
656 |
# 세션 드로어에서 카드 클릭 시 실행할 함수 (Drawer 컴포넌트들 다음에 위치)
|
657 |
def execute_history_item(evt: gr.SelectData): # gr.SelectData로 이벤트 데이터 받기
|
658 |
try:
|
@@ -681,12 +634,6 @@ with gr.Blocks(css_paths="app.css",theme=theme) as demo:
|
|
681 |
outputs=[session_history]
|
682 |
)
|
683 |
|
684 |
-
# session_history.click(
|
685 |
-
# fn=execute_history_item,
|
686 |
-
# inputs=[],
|
687 |
-
# outputs=[input, sandbox, state_tab, session_drawer]
|
688 |
-
# )
|
689 |
-
|
690 |
|
691 |
# 메인 컨텐츠를 위한 Row
|
692 |
with antd.Row(gutter=[32, 12]) as layout:
|
@@ -883,25 +830,24 @@ with gr.Blocks(css_paths="app.css",theme=theme) as demo:
|
|
883 |
outputs=[history_drawer]
|
884 |
)
|
885 |
|
886 |
-
|
|
|
887 |
sessionBtn.click(
|
888 |
-
lambda: (gr.update(open=True),
|
889 |
inputs=[],
|
890 |
-
outputs=[session_drawer,
|
891 |
)
|
892 |
|
893 |
-
# 세션 드로어 닫기 이벤트 수정
|
894 |
session_drawer.close(
|
895 |
-
lambda: (gr.update(open=False), gr.
|
896 |
-
outputs=[session_drawer,
|
897 |
)
|
898 |
|
899 |
close_btn.click(
|
900 |
-
lambda: (gr.update(open=False), gr.
|
901 |
-
outputs=[session_drawer,
|
902 |
-
)
|
903 |
-
|
904 |
-
|
905 |
|
906 |
|
907 |
session_list.change(
|
|
|
397 |
print(f"Error updating session list: {e}")
|
398 |
return gr.update(choices=[])
|
399 |
|
400 |
+
# db.json 파일 읽기 함수 추가
|
401 |
+
def load_json_data():
|
402 |
try:
|
403 |
+
with open('db.json', 'r', encoding='utf-8') as f:
|
404 |
+
return json.load(f)
|
405 |
+
except Exception as e:
|
406 |
+
print(f"Error loading db.json: {e}")
|
407 |
+
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
408 |
|
409 |
+
# 세션 히스토리 로드 함수 수정
|
410 |
+
def load_session_history(selected_session=None):
|
411 |
+
try:
|
412 |
+
# db.json 데이터 로드
|
413 |
+
json_data = load_json_data()
|
414 |
+
|
415 |
html_content = """
|
416 |
<style>
|
417 |
.prompt-grid {
|
418 |
display: grid;
|
419 |
+
grid-template-columns: repeat(3, 1fr);
|
420 |
gap: 20px;
|
421 |
padding: 20px;
|
422 |
}
|
|
|
433 |
transform: translateY(-2px);
|
434 |
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
|
435 |
}
|
436 |
+
.card-image {
|
437 |
+
width: 100%;
|
438 |
+
height: 200px;
|
439 |
+
object-fit: cover;
|
440 |
+
border-radius: 4px;
|
441 |
+
margin-bottom: 10px;
|
442 |
+
}
|
443 |
+
.card-name {
|
444 |
+
font-weight: bold;
|
445 |
+
margin-bottom: 8px;
|
446 |
+
}
|
447 |
+
.card-prompt {
|
448 |
+
font-size: 0.9em;
|
449 |
color: #666;
|
450 |
+
display: -webkit-box;
|
451 |
+
-webkit-line-clamp: 3;
|
452 |
+
-webkit-box-orient: vertical;
|
453 |
+
overflow: hidden;
|
454 |
}
|
455 |
</style>
|
456 |
"""
|
457 |
|
|
|
458 |
html_content += """
|
459 |
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
460 |
+
<div class="prompt-grid">
|
461 |
"""
|
462 |
|
463 |
+
for item in json_data:
|
464 |
+
name = html.escape(item.get('name', ''))
|
465 |
+
image_url = html.escape(item.get('image_url', ''))
|
466 |
+
prompt = html.escape(item.get('prompt', ''))
|
|
|
|
|
|
|
|
|
|
|
|
|
467 |
|
468 |
html_content += f"""
|
469 |
+
<div class="prompt-card" data-prompt="{prompt}" onclick="handleCardClick(this)">
|
470 |
+
<img src="{image_url}" class="card-image" alt="{name}">
|
471 |
+
<div class="card-name">{name}</div>
|
472 |
+
<div class="card-prompt">{prompt}</div>
|
|
|
|
|
473 |
</div>
|
474 |
"""
|
475 |
|
|
|
477 |
</div>
|
478 |
<script>
|
479 |
function handleCardClick(card) {
|
|
|
|
|
|
|
480 |
const prompt = card.getAttribute('data-prompt');
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
const textarea = document.querySelector('textarea');
|
482 |
if (textarea) {
|
|
|
483 |
textarea.value = prompt;
|
484 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
485 |
setTimeout(() => {
|
486 |
const executeButton = $('button:contains("Code 실행")');
|
487 |
if (executeButton.length) {
|
|
|
488 |
executeButton[0].click();
|
|
|
|
|
489 |
}
|
490 |
}, 100);
|
491 |
|
|
|
492 |
const drawer = document.querySelector('.session-drawer');
|
493 |
if (drawer) {
|
|
|
494 |
drawer.style.display = 'none';
|
495 |
}
|
|
|
|
|
496 |
}
|
497 |
}
|
|
|
|
|
|
|
|
|
|
|
498 |
</script>
|
499 |
"""
|
500 |
|
|
|
578 |
with ms.Application() as app:
|
579 |
with antd.ConfigProvider():
|
580 |
# Drawer 컴포넌트들
|
581 |
+
|
582 |
+
|
583 |
+
|
584 |
with antd.Drawer(open=False, title="code", placement="left", width="750px") as code_drawer:
|
585 |
code_output = legacy.Markdown()
|
586 |
|
587 |
with antd.Drawer(open=False, title="history", placement="left", width="900px") as history_drawer:
|
588 |
history_output = legacy.Chatbot(show_label=False, flushing=False, height=960, elem_classes="history_chatbot")
|
589 |
|
590 |
+
# 세션 관련 UI 수정
|
591 |
with antd.Drawer(
|
592 |
open=False,
|
593 |
+
title="Templates",
|
594 |
placement="right",
|
595 |
width="900px",
|
596 |
elem_classes="session-drawer"
|
597 |
) as session_drawer:
|
598 |
with antd.Flex(vertical=True, gap="middle"):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
session_history = gr.HTML(
|
600 |
elem_classes="session-history"
|
601 |
)
|
|
|
|
|
602 |
close_btn = antd.Button(
|
603 |
"Close",
|
604 |
type="default",
|
605 |
elem_classes="close-btn"
|
606 |
)
|
607 |
|
608 |
+
|
609 |
# 세션 드로어에서 카드 클릭 시 실행할 함수 (Drawer 컴포넌트들 다음에 위치)
|
610 |
def execute_history_item(evt: gr.SelectData): # gr.SelectData로 이벤트 데이터 받기
|
611 |
try:
|
|
|
634 |
outputs=[session_history]
|
635 |
)
|
636 |
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
|
638 |
# 메인 컨텐츠를 위한 Row
|
639 |
with antd.Row(gutter=[32, 12]) as layout:
|
|
|
830 |
outputs=[history_drawer]
|
831 |
)
|
832 |
|
833 |
+
|
834 |
+
# 세션 버튼 클릭 이벤트 수정
|
835 |
sessionBtn.click(
|
836 |
+
lambda: (gr.update(open=True), load_session_history()),
|
837 |
inputs=[],
|
838 |
+
outputs=[session_drawer, session_history]
|
839 |
)
|
840 |
|
841 |
+
# 세션 드로어 닫기 이벤트 수정
|
842 |
session_drawer.close(
|
843 |
+
lambda: (gr.update(open=False), gr.HTML("")),
|
844 |
+
outputs=[session_drawer, session_history]
|
845 |
)
|
846 |
|
847 |
close_btn.click(
|
848 |
+
lambda: (gr.update(open=False), gr.HTML("")),
|
849 |
+
outputs=[session_drawer, session_history]
|
850 |
+
)
|
|
|
|
|
851 |
|
852 |
|
853 |
session_list.change(
|