AnnasBlackHat commited on
Commit
1fea92e
1 Parent(s): 816058d

edit, add, login

Browse files
.streamlit/config.toml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ [client]
2
+ showSidebarNavigation = false
Pipfile CHANGED
@@ -7,6 +7,10 @@ name = "pypi"
7
  streamlit = "*"
8
  pymongo = {extras = ["srv"], version = "*"}
9
  firebase-admin = "*"
 
 
 
 
10
 
11
  [dev-packages]
12
 
 
7
  streamlit = "*"
8
  pymongo = {extras = ["srv"], version = "*"}
9
  firebase-admin = "*"
10
+ extra-streamlit-components = "*"
11
+ passlib = "*"
12
+ install = "*"
13
+ bcrypt = "*"
14
 
15
  [dev-packages]
16
 
Pipfile.lock CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "_meta": {
3
  "hash": {
4
- "sha256": "0785ab991784d23d32014c16541fe6e40bfbc07e215073ce9ccfd519297a5bb6"
5
  },
6
  "pipfile-spec": 6,
7
  "requires": {
@@ -32,6 +32,40 @@
32
  "markers": "python_version >= '3.7'",
33
  "version": "==23.2.0"
34
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  "blinker": {
36
  "hashes": [
37
  "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9",
@@ -271,6 +305,15 @@
271
  "markers": "python_version >= '3.8'",
272
  "version": "==2.6.1"
273
  },
 
 
 
 
 
 
 
 
 
274
  "firebase-admin": {
275
  "hashes": [
276
  "sha256:e716dde1447f0a1cd1523be76ff872df33c4e1a3c079564ace033b2ad60bcc4f",
@@ -526,6 +569,15 @@
526
  "markers": "python_version >= '3.5'",
527
  "version": "==3.6"
528
  },
 
 
 
 
 
 
 
 
 
529
  "jinja2": {
530
  "hashes": [
531
  "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa",
@@ -779,6 +831,14 @@
779
  "markers": "python_version >= '3.9'",
780
  "version": "==2.2.1"
781
  },
 
 
 
 
 
 
 
 
782
  "pillow": {
783
  "hashes": [
784
  "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8",
 
1
  {
2
  "_meta": {
3
  "hash": {
4
+ "sha256": "880bfa861bc27021017018af7ae02f48b9834c97963dedfab3021569c5ce5a32"
5
  },
6
  "pipfile-spec": 6,
7
  "requires": {
 
32
  "markers": "python_version >= '3.7'",
33
  "version": "==23.2.0"
34
  },
35
+ "bcrypt": {
36
+ "hashes": [
37
+ "sha256:02d9ef8915f72dd6daaef40e0baeef8a017ce624369f09754baf32bb32dba25f",
38
+ "sha256:1c28973decf4e0e69cee78c68e30a523be441972c826703bb93099868a8ff5b5",
39
+ "sha256:2a298db2a8ab20056120b45e86c00a0a5eb50ec4075b6142db35f593b97cb3fb",
40
+ "sha256:33313a1200a3ae90b75587ceac502b048b840fc69e7f7a0905b5f87fac7a1258",
41
+ "sha256:3566a88234e8de2ccae31968127b0ecccbb4cddb629da744165db72b58d88ca4",
42
+ "sha256:387e7e1af9a4dd636b9505a465032f2f5cb8e61ba1120e79a0e1cd0b512f3dfc",
43
+ "sha256:44290ccc827d3a24604f2c8bcd00d0da349e336e6503656cb8192133e27335e2",
44
+ "sha256:57fa9442758da926ed33a91644649d3e340a71e2d0a5a8de064fb621fd5a3326",
45
+ "sha256:68e3c6642077b0c8092580c819c1684161262b2e30c4f45deb000c38947bf483",
46
+ "sha256:69057b9fc5093ea1ab00dd24ede891f3e5e65bee040395fb1e66ee196f9c9b4a",
47
+ "sha256:6cad43d8c63f34b26aef462b6f5e44fdcf9860b723d2453b5d391258c4c8e966",
48
+ "sha256:71b8be82bc46cedd61a9f4ccb6c1a493211d031415a34adde3669ee1b0afbb63",
49
+ "sha256:732b3920a08eacf12f93e6b04ea276c489f1c8fb49344f564cca2adb663b3e4c",
50
+ "sha256:9800ae5bd5077b13725e2e3934aa3c9c37e49d3ea3d06318010aa40f54c63551",
51
+ "sha256:a97e07e83e3262599434816f631cc4c7ca2aa8e9c072c1b1a7fec2ae809a1d2d",
52
+ "sha256:ac621c093edb28200728a9cca214d7e838529e557027ef0581685909acd28b5e",
53
+ "sha256:b8df79979c5bae07f1db22dcc49cc5bccf08a0380ca5c6f391cbb5790355c0b0",
54
+ "sha256:b90e216dc36864ae7132cb151ffe95155a37a14e0de3a8f64b49655dd959ff9c",
55
+ "sha256:ba4e4cc26610581a6329b3937e02d319f5ad4b85b074846bf4fef8a8cf51e7bb",
56
+ "sha256:ba55e40de38a24e2d78d34c2d36d6e864f93e0d79d0b6ce915e4335aa81d01b1",
57
+ "sha256:be3ab1071662f6065899fe08428e45c16aa36e28bc42921c4901a191fda6ee42",
58
+ "sha256:d75fc8cd0ba23f97bae88a6ec04e9e5351ff3c6ad06f38fe32ba50cbd0d11946",
59
+ "sha256:e51c42750b7585cee7892c2614be0d14107fad9581d1738d954a262556dd1aab",
60
+ "sha256:ea505c97a5c465ab8c3ba75c0805a102ce526695cd6818c6de3b1a38f6f60da1",
61
+ "sha256:eb3bd3321517916696233b5e0c67fd7d6281f0ef48e66812db35fc963a422a1c",
62
+ "sha256:f70d9c61f9c4ca7d57f3bfe88a5ccf62546ffbadf3681bb1e268d9d2e41c91a7",
63
+ "sha256:fbe188b878313d01b7718390f31528be4010fed1faa798c5a1d0469c9c48c369"
64
+ ],
65
+ "index": "pypi",
66
+ "markers": "python_version >= '3.7'",
67
+ "version": "==4.1.2"
68
+ },
69
  "blinker": {
70
  "hashes": [
71
  "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9",
 
305
  "markers": "python_version >= '3.8'",
306
  "version": "==2.6.1"
307
  },
308
+ "extra-streamlit-components": {
309
+ "hashes": [
310
+ "sha256:c8e6f98446adecd3002756362e50d0669693b7673afaa89cebfced6415cc6bd3",
311
+ "sha256:d18314cf2ed009f95641882b50aa3bdb11b6a0eb6403fb43dbc8af1722419617"
312
+ ],
313
+ "index": "pypi",
314
+ "markers": "python_version >= '3.6'",
315
+ "version": "==0.1.71"
316
+ },
317
  "firebase-admin": {
318
  "hashes": [
319
  "sha256:e716dde1447f0a1cd1523be76ff872df33c4e1a3c079564ace033b2ad60bcc4f",
 
569
  "markers": "python_version >= '3.5'",
570
  "version": "==3.6"
571
  },
572
+ "install": {
573
+ "hashes": [
574
+ "sha256:0d3fadf4aa62c95efe8d34757c8507eb46177f86c016c21c6551eafc6a53d5a9",
575
+ "sha256:e67c8a0be5ccf8cb4ffa17d090f3a61b6e820e6a7e21cd1d2c0f7bc59b18e647"
576
+ ],
577
+ "index": "pypi",
578
+ "markers": "python_version >= '2.7'",
579
+ "version": "==1.3.5"
580
+ },
581
  "jinja2": {
582
  "hashes": [
583
  "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa",
 
831
  "markers": "python_version >= '3.9'",
832
  "version": "==2.2.1"
833
  },
834
+ "passlib": {
835
+ "hashes": [
836
+ "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1",
837
+ "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"
838
+ ],
839
+ "index": "pypi",
840
+ "version": "==1.7.4"
841
+ },
842
  "pillow": {
843
  "hashes": [
844
  "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8",
app.py CHANGED
@@ -1,10 +1,9 @@
1
  import streamlit as st
2
 
3
- st.set_page_config(page_title="FAQ and Chat App")
4
  st.title("FAQ and Chat App")
5
  st.write("Welcome to the FAQ and Chat App! Navigate using the sidebar.")
6
 
7
-
8
- (st.page_link("pages/faq_page.py", label="FAQ"))
9
- (st.page_link("pages/chat_page.py", label="Chat"))
10
 
 
1
  import streamlit as st
2
 
3
+ # st.set_page_config(page_title="FAQ and Chat App")
4
  st.title("FAQ and Chat App")
5
  st.write("Welcome to the FAQ and Chat App! Navigate using the sidebar.")
6
 
7
+ st.page_link("pages/faq.py", label="FAQ")
8
+ st.page_link("pages/chat.py", label="Chat")
 
9
 
dependency.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from pymongo import MongoClient
3
+ import os
4
+ import extra_streamlit_components as stx
5
+
6
+ @st.cache_resource
7
+ def load_db():
8
+ db_user = os.environ['DB_USER']
9
+ db_pass = os.environ['DB_PASS']
10
+ db_uri = f"mongodb+srv://{db_user}:{db_pass}@cluster0.firly.gcp.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
11
+ client = MongoClient(db_uri)
12
+ return client
13
+
14
+ @st.cache_resource(experimental_allow_widgets=True)
15
+ def get_manager():
16
+ return stx.CookieManager()
17
+
18
+
19
+ client = load_db()
20
+ db = client["chat_support"]
21
+ faq_collection = db["faq"]
pages/{chat_page.py → chat.py} RENAMED
File without changes
pages/{faq_page.py → faq.py} RENAMED
@@ -1,14 +1,11 @@
1
  import streamlit as st
2
  import pandas as pd
3
  from pymongo import MongoClient
 
4
  import os
5
 
6
- #uri = "mongodb+srv://<username>:<password>@cluster0.firly.gcp.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
7
- db_user = os.environ['DB_USER']
8
- db_pass = os.environ['DB_PASS']
9
- db_uri = f"mongodb+srv://{db_user}:{db_pass}@cluster0.firly.gcp.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0"
10
- # Connect to MongoDB
11
- client = MongoClient(db_uri)
12
  db = client["chat_support"]
13
  faq_collection = db["faq"]
14
 
 
1
  import streamlit as st
2
  import pandas as pd
3
  from pymongo import MongoClient
4
+ from dependency import load_db
5
  import os
6
 
7
+
8
+ client = load_db()
 
 
 
 
9
  db = client["chat_support"]
10
  faq_collection = db["faq"]
11
 
pages/login.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import extra_streamlit_components as stx
3
+ from dependency import get_manager
4
+ from dependency import db
5
+ from passlib.hash import pbkdf2_sha256
6
+ import bcrypt
7
+
8
+ admin_collection = db['admin']
9
+
10
+ # Replace this with your actual authentication logic
11
+ def authenticate(email, password):
12
+ # Query the admin_collection with the provided email
13
+ admin = admin_collection.find_one({"email": email})
14
+
15
+ # If the email is not found, return False
16
+ if not admin:
17
+ return False
18
+
19
+ if bcrypt.checkpw(password.encode('utf-8'), admin["password"].encode('utf-8')):
20
+ return True
21
+ else:
22
+ return False
23
+
24
+ # Verify the provided password against the hashed password in the database
25
+ if pbkdf2_sha256.verify(password, admin["password"]):
26
+ return True
27
+ else:
28
+ return False
29
+
30
+ cookie_manager = get_manager()
31
+ auth_state = cookie_manager.get(cookie='auth_state')
32
+
33
+ def login():
34
+ st.title("Login")
35
+ username = st.text_input("Username")
36
+ password = st.text_input("Password", type="password")
37
+ if st.button("Login"):
38
+ if authenticate(username, password):
39
+ st.success("Login successful!")
40
+ cookie_manager.set('auth_state', 'authenticated')
41
+ st.switch_page('pages/manage_faqs.py')
42
+ else:
43
+ st.error("Invalid username or password")
44
+
45
+ if not auth_state == "authenticated":
46
+ login()
47
+ else:
48
+ st.warning("You are already logged in. Redirecting to FAQ management page.")
49
+ st.experimental_set_query_params(page="manage_faqs")
pages/manage_faqs.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ from pymongo import MongoClient
4
+ from dependency import get_manager, load_db
5
+ from bson.objectid import ObjectId
6
+
7
+ cookie_manager = get_manager()
8
+ auth_state = cookie_manager.get(cookie='auth_state')
9
+ st.write(auth_state)
10
+
11
+ if not auth_state == "authenticated":
12
+ st.warning("You are not authorized to access this page. Please login.")
13
+ st.stop()
14
+
15
+ # Connect to MongoDB
16
+ client = load_db()
17
+ db = client["chat_support"]
18
+ faq_collection = db["faq"]
19
+ st.title("Manage FAQs")
20
+ print('load faqs...')
21
+
22
+ # Display existing FAQs
23
+ faq_all = pd.DataFrame(list(faq_collection.find()))
24
+
25
+ with st.sidebar:
26
+ st.subheader("Add New FAQ")
27
+ with st.form("new_faq_form", clear_on_submit=True):
28
+ new_title = st.text_input("Title")
29
+ new_questions = st.text_area("Questions (one per line)")
30
+ new_answer = st.text_area("Answer")
31
+ add_faq = st.form_submit_button("Add FAQ")
32
+ if add_faq:
33
+ print('add new faq...')
34
+ new_questions_list = new_questions.split("\n")
35
+ faq_collection.insert_one({
36
+ "title": new_title,
37
+ "questions": new_questions_list,
38
+ "answer": new_answer,
39
+ "time_updated": pd.Timestamp.now().value
40
+ })
41
+ st.success("New FAQ added successfully!")
42
+
43
+ # Search functionality
44
+ search_term = st.text_input("Search FAQs", "")
45
+ if search_term:
46
+ faq_data = faq_all[faq_all['questions'].apply(lambda x: any(search_term.lower() in q.lower() for q in x))]
47
+ else:
48
+ faq_data = faq_all
49
+
50
+ # id = ObjectId('5e26c9f62da44968cc46444c')
51
+ # result = faq_collection.update_one(
52
+ # {"_id": id},
53
+ # {"$set": {
54
+ # "title": 'cara menambahkan produks',
55
+ # }}
56
+ # )
57
+ # print('updated: ', result.modified_count, 'id: ', type(id))
58
+
59
+ def edit_faq(index):
60
+ row = faq_data.loc[index]
61
+ with st.form(f"edit_form_{index}", clear_on_submit=True):
62
+ st.write("Edit FAQ Form")
63
+ new_title = st.text_input("Title", value=row['title'], key=f"title_{index}")
64
+ new_questions = st.text_area("Questions (one per line)", value="\n".join(row['questions']), key=f"questions_{index}")
65
+ new_answer = st.text_area("Answer", value=row['answer'], key=f"answer_{index}")
66
+ confirm_edit = st.form_submit_button("Confirm Edit", on_click=save_edit, args=(index,))
67
+
68
+
69
+ def save_edit(index):
70
+ print('save at index: ', index)
71
+ row = faq_data.loc[index]
72
+ faq_id = row['_id']
73
+ # print('save....', row['_id'], faq_id['$oid'])
74
+ print('typeOf faq_id ',type(faq_id))
75
+
76
+ # Get the current state of the input fields
77
+ edit_form = st.form(f"edit_form_{index}")
78
+ print('form: ', edit_form)
79
+ new_title = st.session_state.get(f"title_{index}", row['title'])
80
+ new_questions = st.session_state.get(f"questions_{index}", "\n".join(row['questions']))
81
+ new_answer = st.session_state.get(f"answer_{index}", row['answer'])
82
+ # new_title = edit_form.form_state.widget_states['title'].value
83
+ # new_questions = edit_form.form_state.widget_states['questions'].value.split("\n")
84
+ # new_answer = edit_form.form_state.widget_states['answer'].value
85
+
86
+ # Convert the _id to ObjectId
87
+ # if isinstance(faq_id, ObjectId):
88
+ # faq_id = faq_id
89
+ # print('isinstance')
90
+ # else:
91
+ # faq_id = ObjectId(faq_id['$oid'])
92
+ # print('isnot isinstance')
93
+
94
+ result = faq_collection.update_one(
95
+ {"_id": faq_id},
96
+ {"$set": {
97
+ "title": new_title,
98
+ "questions": new_questions.split("\n"),
99
+ "answer": new_answer,
100
+ "time_updated": pd.Timestamp.now().value
101
+ }}
102
+ )
103
+ print('updated: ', result.modified_count, new_title)
104
+ st.success("FAQ updated successfully!")
105
+
106
+ # Add new FAQ
107
+
108
+ # with st.form("new_faq_form"):
109
+ # new_title = st.text_input("Title")
110
+ # new_questions = st.text_area("Questions (one per line)")
111
+ # new_answer = st.text_area("Answer")
112
+ # add_faq = st.form_submit_button("Add FAQ")
113
+
114
+ # if add_faq:
115
+ # new_questions_list = new_questions.split("\n")
116
+ # faq_collection.insert_one({
117
+ # "title": new_title,
118
+ # "questions": new_questions_list,
119
+ # "answer": new_answer,
120
+ # "time_updated": pd.Timestamp.now().value
121
+ # })
122
+ # st.success("New FAQ added successfully!")
123
+
124
+ for index, row in faq_data.iterrows():
125
+ with st.expander(row['title']):
126
+ st.write("**Questions:**")
127
+ for question in row['questions']:
128
+ st.write(f"- {question}")
129
+ st.write(f"\n**Answer:** {row['answer']}")
130
+ # edit_faq_button = st.button("Edit FAQ", key=f"edit_{index}", on_click=edit_faq, args=(index,))
131
+ edit_faq_button = st.button("Edit FAQ", key=f"edit_{index}")
132
+ if edit_faq_button:
133
+ with st.form(f"edit_form_{index}", clear_on_submit=True):
134
+ st.write("Edit FAQ Form")
135
+ new_title = st.text_input("Title", value=row['title'], key=f"title_{index}")
136
+ new_questions = st.text_area("Questions (one per line)", value="\n".join(row['questions']), key=f"questions_{index}")
137
+ new_answer = st.text_area("Answer", value=row['answer'], key=f"answer_{index}")
138
+ confirm_edit = st.form_submit_button("Confirm Edit", on_click=save_edit, args=(index,))
139
+ # Add code to create a new FAQ entry
sync.py CHANGED
@@ -4,6 +4,7 @@ import pymongo
4
  from datetime import datetime
5
  import os
6
 
 
7
  # Initialize the Firebase app
8
  cred = credentials.Certificate('serviceAccountKey.json')
9
  firebase_admin.initialize_app(cred)
 
4
  from datetime import datetime
5
  import os
6
 
7
+
8
  # Initialize the Firebase app
9
  cred = credentials.Certificate('serviceAccountKey.json')
10
  firebase_admin.initialize_app(cred)