k96beni commited on
Commit
db39613
·
verified ·
1 Parent(s): 127d456

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +321 -179
app.py CHANGED
@@ -545,253 +545,358 @@ scheduler_thread.start()
545
  # --- Gradio UI ---
546
  initial_chat = [{"role": "assistant", "content": "Detta är ChargeNode's AI bot. Hur kan jag hjälpa dig idag?"}]
547
 
 
548
  custom_css = """
 
 
 
 
 
549
  body, html {
550
- background-color: #f7f7f7;
551
- font-family: Arial, sans-serif;
552
  margin: 0;
553
  padding: 0;
 
 
554
  height: 100%;
 
555
  }
556
 
557
- /* --- Default styles (Desktop - Floating Widget) --- */
558
  .gradio-container {
559
- max-width: 450px;
560
- margin: 0;
561
- padding: 0;
562
- position: fixed;
563
- bottom: 20px;
564
- right: 20px;
565
- box-shadow: 0px 0px 15px rgba(0, 0, 0, 0.15);
566
- border-radius: 12px;
567
- background-color: #fff;
568
- display: flex;
569
  flex-direction: column;
570
- height: clamp(70vh, 550px, 85vh);
571
- overflow: hidden;
572
  }
573
 
574
- #chat_interface_main_group, #support_interface_group, #success_interface_group {
 
 
 
575
  display: flex;
576
  flex-direction: column;
577
- flex-grow: 1;
578
- padding: 15px;
579
- overflow-y: hidden;
580
- }
581
- #support_interface_group, #success_interface_group {
582
- justify-content: center; /* Centrera innehåll i support/success-vyerna */
583
  }
584
 
 
 
 
 
 
 
 
585
 
 
586
  #chatbot_conversation {
587
- flex-grow: 1;
 
 
 
 
 
588
  overflow-y: auto;
589
- min-height: 100px;
590
- margin-bottom: 15px;
591
- border: 1px solid #e0e0e0;
 
 
 
 
 
 
 
 
 
 
592
  border-radius: 8px;
593
- padding: 10px;
594
- background-color: #ffffff; /* Ensure background for chat messages */
 
 
 
595
  }
596
 
597
- .gr-textbox textarea {
598
- border-radius: 6px;
599
- padding: 10px;
600
- border: 1px solid #ccc;
601
- box-sizing: border-box; /* Include padding and border in the element's total width and height */
602
- width: 100%; /* Make textarea take full width of its container */
603
  }
604
 
605
- .flex-row {
 
606
  display: flex;
607
- flex-direction: row;
608
- gap: 10px;
609
- align-items: center;
610
- margin-top: 10px; /* Space above button row */
611
  }
612
 
613
  .gr-button {
614
- background-color: #2a9d8f;
615
- color: #fff;
 
616
  border: none;
617
- border-radius: 4px;
618
- padding: 10px 16px;
619
- margin: 0;
620
- flex-grow: 1;
621
- text-align: center;
622
  cursor: pointer;
 
 
 
623
  }
624
 
625
  .gr-button:hover {
626
- background-color: #264653;
 
627
  }
628
 
629
- .support-btn {
630
- background-color: #000000;
631
- color: #ffffff;
632
  }
633
- .support-btn:hover {
634
- background-color: #333333;
 
635
  }
636
 
637
- #support_interface_group .gr-form {
638
- padding: 10px;
639
- border: 1px solid #eee;
640
- border-radius: 4px;
641
- margin-bottom: 10px;
642
- background-color: #f9f9f9;
 
 
 
 
 
 
643
  }
644
- #support_interface_group .gr-form label { /* Style labels in support form */
645
- margin-bottom: 5px;
 
 
 
 
 
 
 
646
  display: block;
647
- font-weight: bold;
648
- font-size: 0.9em;
649
  }
650
 
 
 
 
 
 
 
 
651
 
 
652
  .chat-preview {
653
- max-height: 150px;
654
  overflow-y: auto;
655
- border: 1px solid #eee;
656
- padding: 8px;
657
- margin-top: 10px;
658
- font-size: 0.9em;
659
- background-color: #f0f0f0; /* Slightly different background for preview */
660
  border-radius: 4px;
 
 
 
 
661
  }
662
 
663
- .success-message {
664
- font-size: 1.1em;
665
- font-weight: normal;
 
666
  text-align: center;
667
- padding: 20px;
668
- }
669
- .success_interface_group .gr-button { /* Button in success message */
670
- flex-grow: 0; /* Don't let it grow unnecessarily */
671
- align-self: center; /* Center button */
672
  }
673
 
 
 
 
 
 
 
 
 
 
674
 
675
- /* Dölj Gradio-footer */
676
  footer, .footer, .gr-footer, .gradio-footer {
677
  display: none !important;
678
  }
679
- .gradio-container > .footer {
680
- display: none !important;
681
- }
682
-
683
 
684
- /* --- Mobilanpassade stilar --- */
685
  @media (max-width: 768px) {
686
- body, html {
687
- overflow: hidden;
688
- }
689
-
690
  .gradio-container {
691
- width: 100%;
692
- max-width: 100%;
693
- height: 100vh;
694
- height: 100dvh;
695
- position: static;
696
- border-radius: 0;
697
- box-shadow: none;
698
- bottom: auto;
699
- right: auto;
700
  }
701
-
702
- #chat_interface_main_group, #support_interface_group, #success_interface_group {
703
- padding: 10px;
704
- height: 100%; /* Ensure groups fill the container height */
705
- box-sizing: border-box; /* Padding included in height */
706
  }
707
-
708
  #chatbot_conversation {
709
- margin-bottom: 10px;
 
 
710
  }
711
-
712
- .flex-row { /* For buttons */
 
 
 
 
 
713
  flex-direction: column;
714
  gap: 8px;
715
- width: 100%; /* Make the column take full width */
716
  }
717
-
718
- .flex-row .gr-button {
719
- width: 100%;
720
- flex-grow: 0;
 
 
721
  }
722
 
723
- /* For message input row on mobile if it also needs stacking (not typical) */
724
- /* Example: if msg textbox was also in a .flex-row */
725
- /* #chat_interface_main_group > .gr-row:has(> .gr-textbox) { flex-direction: column; } */
726
-
 
 
 
 
 
 
 
 
 
 
 
 
727
 
728
- .gradio-app {
729
- height: 100%;
730
- min-height: 100%;
 
 
 
731
  }
732
 
733
- /* Adjust main markdown text for mobile if needed */
734
- .gradio-container > .gr-markdown { /* Targets the first markdown element if it's a direct child */
735
- padding-left: 10px;
736
- padding-right: 10px;
737
- font-size: 0.95em;
 
 
738
  }
739
  }
 
 
 
 
 
 
 
 
 
 
740
  """
741
 
742
- with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
743
- gr.Markdown("Ställ din fråga om ChargeNodes produkter och tjänster nedan. Om du inte gillar botten, så ring oss gärna på 010 – 205 10 55")
 
744
 
 
 
 
745
  with gr.Group(visible=True, elem_id="chat_interface_main_group") as chat_interface:
746
- chatbot = gr.Chatbot(value=initial_chat, type="messages", elem_id="chatbot_conversation", bubble_full_width=False)
 
 
 
 
 
 
747
  chatbot.like(vote, None, None)
748
 
749
- with gr.Row(): # Row for message input
750
- msg = gr.Textbox(label=None, placeholder="Ange din fråga...", scale=1, show_label=False)
751
- # Removed scale to let CSS handle width with .gr-textbox textarea { width: 100%; }
 
 
 
 
 
752
 
753
- with gr.Row(elem_classes="flex-row"): # Row for buttons
754
- clear = gr.Button("Rensa")
755
- support_btn = gr.Button("Behöver du mer hjälp?", elem_classes="support-btn")
756
 
 
757
  with gr.Group(visible=False, elem_id="support_interface_group") as support_interface:
758
  gr.Markdown("### Vänligen fyll i din områdeskod, uttagsnummer och din email adress")
759
- with gr.Group(elem_classes="gr-form"):
760
- områdeskod = gr.Textbox(label="Områdeskod", placeholder="Områdeskod (valfritt)", info="Numeriskt värde")
761
- uttagsnummer = gr.Textbox(label="Uttagsnummer", placeholder="Uttagsnummer (valfritt)", info="Numeriskt värde")
762
- email = gr.Textbox(label="Din email adress", placeholder="din@email.se", info="Email adress krävs")
 
 
 
 
 
 
 
 
 
 
 
 
 
763
 
764
  gr.Markdown("### Chat som skickas till support:")
765
- chat_preview = gr.Markdown(elem_classes="chat-preview")
766
 
767
- with gr.Row(elem_classes="flex-row"): # Buttons in support form
768
- back_btn = gr.Button("Tillbaka")
769
- send_support_btn = gr.Button("Skicka")
770
 
 
771
  with gr.Group(visible=False, elem_id="success_interface_group") as success_interface:
772
- gr.Markdown("Tack för att du kontaktar support@chargenode.eu. Vi återkommer inom kort", elem_classes="success-message")
773
- back_to_chat_btn = gr.Button("Tillbaka till chatten")
774
 
775
  def respond(message, chat_history, request: gr.Request):
776
  global last_log
777
- if not message.strip(): # Do not respond to empty messages
778
  return "", chat_history
779
 
780
- start_time = time.time() # Renamed for clarity
781
- response_text = generate_answer(message) # Renamed for clarity
782
- elapsed_time = round(time.time() - start_time, 2) # Renamed for clarity
783
 
784
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
785
 
786
- # Session ID logic: try to reuse from last_log if it exists and is recent enough (e.g., within 30 mins)
787
- current_session_id = str(uuid.uuid4()) # Default new session_id
788
  if last_log and 'session_id' in last_log and 'timestamp' in last_log:
789
  try:
790
  last_log_time = datetime.strptime(last_log['timestamp'], "%Y-%m-%d %H:%M:%S")
791
  if (datetime.now() - last_log_time) < timedelta(minutes=30):
792
  current_session_id = last_log['session_id']
793
- except ValueError: # If timestamp format is unexpected
794
- pass # Keep new session_id
795
 
796
  user_id = request.client.host if request else "unknown_client"
797
  ua_str = request.headers.get("user-agent", "") if request else ""
@@ -805,7 +910,7 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
805
  platform = "web"
806
  if "chargenode.eu" in ref: platform = "chargenode.eu"
807
  elif "localhost" in ref: platform = "test"
808
- elif "app" in ref: platform = "app" # Assuming 'app' in referer indicates your app environment
809
 
810
  log_data = {
811
  "timestamp": timestamp, "user_id": user_id, "session_id": current_session_id,
@@ -813,9 +918,8 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
813
  "ip": ip, "browser": browser, "os": osys, "platform": platform
814
  }
815
  safe_append_to_log(log_data)
816
- last_log = log_data # Update last_log with the current log
817
 
818
- # Slack notification for new conversation (asynchronously)
819
  try:
820
  convo_subject = f"Ny konversation ({platform})"
821
  convo_content = f"""
@@ -830,47 +934,53 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
830
 
831
  chat_history.append({"role": "user", "content": message})
832
  chat_history.append({"role": "assistant", "content": response_text})
833
- return "", chat_history # Clear input field, update chat history
834
 
835
- def format_chat_preview(chat_history_messages): # Parameter renamed for clarity
836
- if not chat_history_messages: return "Ingen chatthistorik att visa."
 
837
  preview = ""
838
  for msg in chat_history_messages:
839
- sender = "Användare" if msg.get("role") == "user" else "Bot"
840
  content = msg.get("content", "")
841
- preview += f"**{sender}:** {content[:100]}{'...' if len(content) > 100 else ''}\n\n"
842
  return preview
843
 
844
- def show_support_form(chat_history_messages):
845
  preview_md = format_chat_preview(chat_history_messages)
846
  return {
847
  chat_interface: gr.Group(visible=False),
848
  support_interface: gr.Group(visible=True),
849
  success_interface: gr.Group(visible=False),
850
- chat_preview: preview_md # Update the markdown component directly
 
851
  }
852
 
853
- def back_to_chat():
854
  return {
855
  chat_interface: gr.Group(visible=True),
856
  support_interface: gr.Group(visible=False),
857
- success_interface: gr.Group(visible=False)
 
858
  }
859
 
860
- def submit_support_form(area_code, outlet_number, user_email, chat_history_messages):
861
  validation_errors = []
862
- if area_code and not area_code.isdigit(): validation_errors.append("Områdeskod måste vara numerisk.")
863
- if outlet_number and not outlet_number.isdigit(): validation_errors.append("Uttagsnummer måste vara numerisk.")
 
 
864
  if not user_email or '@' not in user_email or '.' not in user_email.split('@')[-1]:
865
  validation_errors.append("En giltig e-postadress krävs.")
866
 
867
  if validation_errors:
868
  error_md = "**Valideringsfel:**\n" + "\n".join(f"- {err}" for err in validation_errors)
869
- return { # Return updates for all relevant components
870
  chat_interface: gr.Group(visible=False),
871
- support_interface: gr.Group(visible=True), # Keep support form visible
872
  success_interface: gr.Group(visible=False),
873
- chat_preview: error_md # Show errors in the preview area
 
874
  }
875
 
876
  slack_sent = send_support_to_slack(area_code, outlet_number, user_email, chat_history_messages)
@@ -878,28 +988,56 @@ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst") as app:
878
  return {
879
  chat_interface: gr.Group(visible=False),
880
  support_interface: gr.Group(visible=False),
881
- success_interface: gr.Group(visible=True) # Show success
 
882
  }
883
  else:
884
  error_md = "**Ett tekniskt fel uppstod när meddelandet skulle skickas. Vänligen försök igen senare eller kontakta support direkt.**"
885
  return {
886
  chat_interface: gr.Group(visible=False),
887
- support_interface: gr.Group(visible=True), # Keep support form visible
888
  success_interface: gr.Group(visible=False),
889
- chat_preview: error_md # Show submission error
 
890
  }
891
 
892
- # Event handlers
893
- msg.submit(respond, [msg, chatbot], [msg, chatbot], api_name="respond") # Added api_name
894
- clear.click(lambda: (None, initial_chat[:]), None, [msg, chatbot], queue=False) # Reset chat to initial state
 
 
 
 
 
 
 
 
 
 
 
895
 
896
- support_btn.click(show_support_form, [chatbot], [chat_interface, support_interface, success_interface, chat_preview])
897
- back_btn.click(back_to_chat, None, [chat_interface, support_interface, success_interface])
898
- back_to_chat_btn.click(back_to_chat, None, [chat_interface, support_interface, success_interface])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
899
  send_support_btn.click(
900
  submit_support_form,
901
- [områdeskod, uttagsnummer, email, chatbot],
902
- [chat_interface, support_interface, success_interface, chat_preview]
903
  )
904
 
905
  # Initialisera embeddings vid uppstart
@@ -908,5 +1046,9 @@ initialize_embeddings()
908
  print("Embedding-modell och index redo!")
909
 
910
  if __name__ == "__main__":
911
- app.launch(share=IS_HUGGINGFACE) # Share only if IS_HUGGINGFACE is True, otherwise local
912
- # For local development, you might want app.launch() or app.launch(share=False)
 
 
 
 
 
545
  # --- Gradio UI ---
546
  initial_chat = [{"role": "assistant", "content": "Detta är ChargeNode's AI bot. Hur kan jag hjälpa dig idag?"}]
547
 
548
+ # FÖRBÄTTRAD CSS MED KORREKT VISIBILITY OCH MOBILSUPPORT
549
  custom_css = """
550
+ /* Reset och grundläggande stilar */
551
+ * {
552
+ box-sizing: border-box;
553
+ }
554
+
555
  body, html {
 
 
556
  margin: 0;
557
  padding: 0;
558
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
559
+ background-color: #f8f9fa;
560
  height: 100%;
561
+ overflow: hidden;
562
  }
563
 
564
+ /* Huvudcontainer - anpassar sig efter iframe */
565
  .gradio-container {
566
+ width: 100% !important;
567
+ height: 100vh !important;
568
+ max-width: none !important;
569
+ margin: 0 !important;
570
+ padding: 0 !important;
571
+ border-radius: 0 !important;
572
+ box-shadow: none !important;
573
+ position: relative;
574
+ display: flex;
 
575
  flex-direction: column;
576
+ background-color: #ffffff;
 
577
  }
578
 
579
+ /* Huvud-grupper */
580
+ #chat_interface_main_group,
581
+ #support_interface_group,
582
+ #success_interface_group {
583
  display: flex;
584
  flex-direction: column;
585
+ height: 100%;
586
+ padding: 16px;
587
+ overflow: hidden;
 
 
 
588
  }
589
 
590
+ /* KORREKT HANTERING AV VISIBILITY */
591
+ #chat_interface_main_group.hidden,
592
+ #support_interface_group.hidden,
593
+ #success_interface_group.hidden {
594
+ display: none !important;
595
+ visibility: hidden !important;
596
+ }
597
 
598
+ /* Chatbot-område */
599
  #chatbot_conversation {
600
+ flex: 1;
601
+ min-height: 300px;
602
+ margin-bottom: 16px;
603
+ border: 1px solid #e9ecef;
604
+ border-radius: 8px;
605
+ background-color: #ffffff;
606
  overflow-y: auto;
607
+ padding: 12px;
608
+ }
609
+
610
+ /* Meddelande-input */
611
+ .message-input-container {
612
+ margin-bottom: 12px;
613
+ }
614
+
615
+ .message-input-container .gr-textbox {
616
+ margin: 0;
617
+ }
618
+
619
+ .message-input-container .gr-textbox textarea {
620
  border-radius: 8px;
621
+ border: 2px solid #e9ecef;
622
+ padding: 12px;
623
+ font-size: 14px;
624
+ resize: none;
625
+ transition: border-color 0.2s ease;
626
  }
627
 
628
+ .message-input-container .gr-textbox textarea:focus {
629
+ border-color: #2a9d8f;
630
+ outline: none;
631
+ box-shadow: 0 0 0 3px rgba(42, 157, 143, 0.1);
 
 
632
  }
633
 
634
+ /* Knappar */
635
+ .button-row {
636
  display: flex;
637
+ gap: 8px;
638
+ flex-wrap: wrap;
 
 
639
  }
640
 
641
  .gr-button {
642
+ flex: 1;
643
+ min-width: 120px;
644
+ padding: 12px 16px;
645
  border: none;
646
+ border-radius: 6px;
647
+ font-weight: 500;
648
+ font-size: 14px;
 
 
649
  cursor: pointer;
650
+ transition: all 0.2s ease;
651
+ background-color: #2a9d8f;
652
+ color: white;
653
  }
654
 
655
  .gr-button:hover {
656
+ background-color: #238277;
657
+ transform: translateY(-1px);
658
  }
659
 
660
+ .gr-button.support-btn {
661
+ background-color: #495057;
 
662
  }
663
+
664
+ .gr-button.support-btn:hover {
665
+ background-color: #343a40;
666
  }
667
 
668
+ /* Support-formulär */
669
+ #support_interface_group {
670
+ justify-content: flex-start;
671
+ padding-top: 20px;
672
+ }
673
+
674
+ .support-form {
675
+ background-color: #f8f9fa;
676
+ padding: 20px;
677
+ border-radius: 8px;
678
+ border: 1px solid #dee2e6;
679
+ margin-bottom: 16px;
680
  }
681
+
682
+ .support-form .gr-textbox {
683
+ margin-bottom: 12px;
684
+ }
685
+
686
+ .support-form .gr-textbox label {
687
+ font-weight: 600;
688
+ color: #495057;
689
+ margin-bottom: 4px;
690
  display: block;
 
 
691
  }
692
 
693
+ .support-form .gr-textbox textarea,
694
+ .support-form .gr-textbox input {
695
+ border: 1px solid #ced4da;
696
+ border-radius: 4px;
697
+ padding: 8px 12px;
698
+ width: 100%;
699
+ }
700
 
701
+ /* Chat-förhandsvisning */
702
  .chat-preview {
703
+ max-height: 200px;
704
  overflow-y: auto;
705
+ background-color: #f8f9fa;
706
+ border: 1px solid #dee2e6;
 
 
 
707
  border-radius: 4px;
708
+ padding: 12px;
709
+ font-size: 13px;
710
+ line-height: 1.4;
711
+ margin-top: 12px;
712
  }
713
 
714
+ /* Success-meddelande */
715
+ #success_interface_group {
716
+ justify-content: center;
717
+ align-items: center;
718
  text-align: center;
 
 
 
 
 
719
  }
720
 
721
+ .success-message {
722
+ font-size: 18px;
723
+ color: #198754;
724
+ margin-bottom: 24px;
725
+ padding: 20px;
726
+ background-color: #d1e7dd;
727
+ border: 1px solid #badbcc;
728
+ border-radius: 8px;
729
+ }
730
 
731
+ /* Dölj Gradio footer */
732
  footer, .footer, .gr-footer, .gradio-footer {
733
  display: none !important;
734
  }
 
 
 
 
735
 
736
+ /* --- MOBILANPASSNINGAR --- */
737
  @media (max-width: 768px) {
 
 
 
 
738
  .gradio-container {
739
+ height: 100vh !important;
740
+ height: 100dvh !important;
 
 
 
 
 
 
 
741
  }
742
+
743
+ #chat_interface_main_group,
744
+ #support_interface_group,
745
+ #success_interface_group {
746
+ padding: 12px;
747
  }
748
+
749
  #chatbot_conversation {
750
+ min-height: 250px;
751
+ margin-bottom: 12px;
752
+ padding: 8px;
753
  }
754
+
755
+ .message-input-container .gr-textbox textarea {
756
+ font-size: 16px; /* Förhindrar zoom på iOS */
757
+ padding: 12px;
758
+ }
759
+
760
+ .button-row {
761
  flex-direction: column;
762
  gap: 8px;
 
763
  }
764
+
765
+ .gr-button {
766
+ width: 100%;
767
+ min-width: unset;
768
+ padding: 14px 16px;
769
+ font-size: 16px;
770
  }
771
 
772
+ .support-form {
773
+ padding: 16px;
774
+ margin-bottom: 12px;
775
+ }
776
+
777
+ .chat-preview {
778
+ max-height: 150px;
779
+ font-size: 12px;
780
+ }
781
+
782
+ .success-message {
783
+ font-size: 16px;
784
+ padding: 16px;
785
+ margin-bottom: 20px;
786
+ }
787
+ }
788
 
789
+ /* --- EXTRA SMÅ SKÄRMAR --- */
790
+ @media (max-width: 480px) {
791
+ #chat_interface_main_group,
792
+ #support_interface_group,
793
+ #success_interface_group {
794
+ padding: 8px;
795
  }
796
 
797
+ #chatbot_conversation {
798
+ margin-bottom: 8px;
799
+ padding: 6px;
800
+ }
801
+
802
+ .support-form {
803
+ padding: 12px;
804
  }
805
  }
806
+
807
+ /* IFRAME-SPECIFIKA JUSTERINGAR */
808
+ body.iframe-embedded {
809
+ overflow: hidden;
810
+ }
811
+
812
+ body.iframe-embedded .gradio-container {
813
+ border: none;
814
+ border-radius: 0;
815
+ }
816
  """
817
 
818
+ with gr.Blocks(css=custom_css, title="ChargeNode Kundtjänst", theme=gr.themes.Soft()) as app:
819
+ # State för att hantera aktuell vy
820
+ current_view = gr.State("chat") # "chat", "support", "success"
821
 
822
+ gr.Markdown("**Ställ din fråga om ChargeNodes produkter och tjänster nedan. Om du inte gillar botten, så ring oss gärna på 010 – 205 10 55**", elem_classes=["header-text"])
823
+
824
+ # Chat Interface
825
  with gr.Group(visible=True, elem_id="chat_interface_main_group") as chat_interface:
826
+ chatbot = gr.Chatbot(
827
+ value=initial_chat,
828
+ type="messages",
829
+ elem_id="chatbot_conversation",
830
+ bubble_full_width=False,
831
+ show_copy_button=True
832
+ )
833
  chatbot.like(vote, None, None)
834
 
835
+ with gr.Group(elem_classes=["message-input-container"]):
836
+ msg = gr.Textbox(
837
+ label=None,
838
+ placeholder="Ange din fråga...",
839
+ show_label=False,
840
+ lines=2,
841
+ max_lines=4
842
+ )
843
 
844
+ with gr.Group(elem_classes=["button-row"]):
845
+ clear = gr.Button("Rensa chat", variant="secondary")
846
+ support_btn = gr.Button("Behöver du mer hjälp?", elem_classes=["support-btn"])
847
 
848
+ # Support Interface
849
  with gr.Group(visible=False, elem_id="support_interface_group") as support_interface:
850
  gr.Markdown("### Vänligen fyll i din områdeskod, uttagsnummer och din email adress")
851
+
852
+ with gr.Group(elem_classes=["support-form"]):
853
+ områdeskod = gr.Textbox(
854
+ label="Områdeskod (valfritt)",
855
+ placeholder="Områdeskod",
856
+ info="Numeriskt värde"
857
+ )
858
+ uttagsnummer = gr.Textbox(
859
+ label="Uttagsnummer (valfritt)",
860
+ placeholder="Uttagsnummer",
861
+ info="Numeriskt värde"
862
+ )
863
+ email = gr.Textbox(
864
+ label="Din email adress",
865
+ placeholder="din@email.se",
866
+ info="Email adress krävs"
867
+ )
868
 
869
  gr.Markdown("### Chat som skickas till support:")
870
+ chat_preview = gr.Markdown("", elem_classes=["chat-preview"])
871
 
872
+ with gr.Group(elem_classes=["button-row"]):
873
+ back_btn = gr.Button("Tillbaka", variant="secondary")
874
+ send_support_btn = gr.Button("Skicka till support", variant="primary")
875
 
876
+ # Success Interface
877
  with gr.Group(visible=False, elem_id="success_interface_group") as success_interface:
878
+ gr.Markdown("**Tack för att du kontaktar support@chargenode.eu. Vi återkommer inom kort**", elem_classes=["success-message"])
879
+ back_to_chat_btn = gr.Button("Tillbaka till chatten", variant="primary")
880
 
881
  def respond(message, chat_history, request: gr.Request):
882
  global last_log
883
+ if not message.strip():
884
  return "", chat_history
885
 
886
+ start_time = time.time()
887
+ response_text = generate_answer(message)
888
+ elapsed_time = round(time.time() - start_time, 2)
889
 
890
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
891
 
892
+ current_session_id = str(uuid.uuid4())
 
893
  if last_log and 'session_id' in last_log and 'timestamp' in last_log:
894
  try:
895
  last_log_time = datetime.strptime(last_log['timestamp'], "%Y-%m-%d %H:%M:%S")
896
  if (datetime.now() - last_log_time) < timedelta(minutes=30):
897
  current_session_id = last_log['session_id']
898
+ except ValueError:
899
+ pass
900
 
901
  user_id = request.client.host if request else "unknown_client"
902
  ua_str = request.headers.get("user-agent", "") if request else ""
 
910
  platform = "web"
911
  if "chargenode.eu" in ref: platform = "chargenode.eu"
912
  elif "localhost" in ref: platform = "test"
913
+ elif "app" in ref: platform = "app"
914
 
915
  log_data = {
916
  "timestamp": timestamp, "user_id": user_id, "session_id": current_session_id,
 
918
  "ip": ip, "browser": browser, "os": osys, "platform": platform
919
  }
920
  safe_append_to_log(log_data)
921
+ last_log = log_data
922
 
 
923
  try:
924
  convo_subject = f"Ny konversation ({platform})"
925
  convo_content = f"""
 
934
 
935
  chat_history.append({"role": "user", "content": message})
936
  chat_history.append({"role": "assistant", "content": response_text})
937
+ return "", chat_history
938
 
939
+ def format_chat_preview(chat_history_messages):
940
+ if not chat_history_messages:
941
+ return "Ingen chatthistorik att visa."
942
  preview = ""
943
  for msg in chat_history_messages:
944
+ sender = "**Användare**" if msg.get("role") == "user" else "**Bot**"
945
  content = msg.get("content", "")
946
+ preview += f"{sender}: {content[:100]}{'...' if len(content) > 100 else ''}\n\n"
947
  return preview
948
 
949
+ def show_support_form(chat_history_messages, current_view_state):
950
  preview_md = format_chat_preview(chat_history_messages)
951
  return {
952
  chat_interface: gr.Group(visible=False),
953
  support_interface: gr.Group(visible=True),
954
  success_interface: gr.Group(visible=False),
955
+ chat_preview: preview_md,
956
+ current_view: "support"
957
  }
958
 
959
+ def back_to_chat(current_view_state):
960
  return {
961
  chat_interface: gr.Group(visible=True),
962
  support_interface: gr.Group(visible=False),
963
+ success_interface: gr.Group(visible=False),
964
+ current_view: "chat"
965
  }
966
 
967
+ def submit_support_form(area_code, outlet_number, user_email, chat_history_messages, current_view_state):
968
  validation_errors = []
969
+ if area_code and not area_code.isdigit():
970
+ validation_errors.append("Områdeskod måste vara numerisk.")
971
+ if outlet_number and not outlet_number.isdigit():
972
+ validation_errors.append("Uttagsnummer måste vara numerisk.")
973
  if not user_email or '@' not in user_email or '.' not in user_email.split('@')[-1]:
974
  validation_errors.append("En giltig e-postadress krävs.")
975
 
976
  if validation_errors:
977
  error_md = "**Valideringsfel:**\n" + "\n".join(f"- {err}" for err in validation_errors)
978
+ return {
979
  chat_interface: gr.Group(visible=False),
980
+ support_interface: gr.Group(visible=True),
981
  success_interface: gr.Group(visible=False),
982
+ chat_preview: error_md,
983
+ current_view: "support"
984
  }
985
 
986
  slack_sent = send_support_to_slack(area_code, outlet_number, user_email, chat_history_messages)
 
988
  return {
989
  chat_interface: gr.Group(visible=False),
990
  support_interface: gr.Group(visible=False),
991
+ success_interface: gr.Group(visible=True),
992
+ current_view: "success"
993
  }
994
  else:
995
  error_md = "**Ett tekniskt fel uppstod när meddelandet skulle skickas. Vänligen försök igen senare eller kontakta support direkt.**"
996
  return {
997
  chat_interface: gr.Group(visible=False),
998
+ support_interface: gr.Group(visible=True),
999
  success_interface: gr.Group(visible=False),
1000
+ chat_preview: error_md,
1001
+ current_view: "support"
1002
  }
1003
 
1004
+ # Event handlers med korrekt state management
1005
+ msg.submit(
1006
+ respond,
1007
+ [msg, chatbot],
1008
+ [msg, chatbot],
1009
+ api_name="respond"
1010
+ )
1011
+
1012
+ clear.click(
1013
+ lambda: (None, initial_chat[:]),
1014
+ None,
1015
+ [msg, chatbot],
1016
+ queue=False
1017
+ )
1018
 
1019
+ support_btn.click(
1020
+ show_support_form,
1021
+ [chatbot, current_view],
1022
+ [chat_interface, support_interface, success_interface, chat_preview, current_view]
1023
+ )
1024
+
1025
+ back_btn.click(
1026
+ back_to_chat,
1027
+ [current_view],
1028
+ [chat_interface, support_interface, success_interface, current_view]
1029
+ )
1030
+
1031
+ back_to_chat_btn.click(
1032
+ back_to_chat,
1033
+ [current_view],
1034
+ [chat_interface, support_interface, success_interface, current_view]
1035
+ )
1036
+
1037
  send_support_btn.click(
1038
  submit_support_form,
1039
+ [områdeskod, uttagsnummer, email, chatbot, current_view],
1040
+ [chat_interface, support_interface, success_interface, chat_preview, current_view]
1041
  )
1042
 
1043
  # Initialisera embeddings vid uppstart
 
1046
  print("Embedding-modell och index redo!")
1047
 
1048
  if __name__ == "__main__":
1049
+ app.launch(
1050
+ share=IS_HUGGINGFACE,
1051
+ server_name="0.0.0.0" if IS_HUGGINGFACE else "127.0.0.1",
1052
+ show_error=True,
1053
+ show_api=False
1054
+ )