File size: 9,982 Bytes
e62655f
82ac72c
 
 
 
e62655f
a436d5d
82ac72c
b08141b
5346976
7b3d690
 
e62655f
a793c10
e62655f
 
82ac72c
 
a793c10
82ac72c
 
 
 
a793c10
 
e62655f
a793c10
 
82ac72c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e62655f
82ac72c
 
 
 
e62655f
 
 
 
f23ce56
 
 
 
 
 
 
 
 
 
 
 
 
82ac72c
e62655f
82ac72c
e62655f
 
 
 
 
 
7e479fc
 
 
 
 
 
f23ce56
7e479fc
 
 
 
e62655f
 
82ac72c
e62655f
82ac72c
e62655f
 
 
 
7e479fc
 
 
 
 
 
 
e62655f
 
82ac72c
e62655f
 
 
 
 
 
7e479fc
f23ce56
 
 
7e479fc
 
82ac72c
e62655f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82ac72c
e62655f
 
 
 
 
 
 
 
7e479fc
 
 
 
e62655f
 
 
 
 
 
 
82ac72c
e62655f
 
 
 
7e479fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82ac72c
e62655f
82ac72c
e62655f
 
 
 
 
 
 
7e479fc
 
 
 
e62655f
82ac72c
e62655f
82ac72c
7e479fc
 
 
 
e62655f
 
82ac72c
e62655f
 
 
b08141b
f23ce56
e62655f
 
1849515
e62655f
 
 
 
1849515
e62655f
 
 
 
 
4405acb
e62655f
f23ce56
 
 
 
 
 
 
 
 
 
 
e62655f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f23ce56
 
000722b
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import streamlit as st
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_mail import Mail, Message
import openai
from flask import Flask
import os

#print(os.getenv('OPEN_AI_KEY'))

open_ai_api_key = os.getenv('OPEN_AI_KEY')

# Streamlit Configuration
st.set_page_config(page_title="WDWT?")

# Flask Configuration for Database and Mail
app = Flask(__name__)
app.secret_key = 's3cr3t'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///wdwt.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)

# Configuring Flask-Mail
app.config['MAIL_SERVER'] = 'smtp.freesmtpservers.com'
app.config['MAIL_PORT'] = 25
app.config['MAIL_USERNAME'] = '[email protected]'
app.config['MAIL_PASSWORD'] = ''
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = False
mail = Mail(app)

# User model
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)

# Issue model
class Issue(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    description = db.Column(db.Text, nullable=False)
    created_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

# Solution model
class Solution(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.Text, nullable=False)
    issue_id = db.Column(db.Integer, db.ForeignKey('issue.id'), nullable=False)
    created_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

# Collaborator model
class Collaborator(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    issue_id = db.Column(db.Integer, db.ForeignKey('issue.id'), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)

# Streamlit Pages
st.sidebar.title("Navigation")
page = st.sidebar.radio("Go to", ["Register", "Login", "Dashboard", "Create Issue", "Invite Collaborators", "Submit Solution", "Decide", "Settings"])

# Header for Notifications and User Info
if 'user_id' in st.session_state and st.session_state['user_id'] is not None:
    with app.app_context():
        user = User.query.get(st.session_state['user_id'])
        if user:
            st.sidebar.markdown(f"**Hello, {user.username}**")
            notification_icon = "πŸ””"
            if Issue.query.join(Collaborator).filter(Collaborator.user_id == user.id).count() > 0:
                notification_icon = "πŸ”” (New)"
            st.sidebar.write(f"[{notification_icon} Notifications](#)")
            st.sidebar.write("[βš™οΈ Settings](#)")

# Register Page
def register():
    st.title("Register")
    username = st.text_input("Username")
    email = st.text_input("Email")
    password = st.text_input("Password", type="password")
    if st.button("Register"):
        if username and email and password:
            with app.app_context():
                hashed_pw = bcrypt.generate_password_hash(password).decode('utf-8')
                new_user = User(username=username, email=email, password=hashed_pw)
                db.session.add(new_user)
                db.session.commit()
                st.success("Registration successful! Please check your email for further instructions.")

                # Send registration email
                msg = Message('Welcome to Sociocracy App', sender='[email protected]', recipients=[email])
                msg.body = "Thank you for registering. You can now log in and start collaborating."
                mail.send(msg)
        else:
            st.error("Please fill all fields.")

# Login Page
def login():
    st.title("Login")
    username = st.text_input("Username")
    password = st.text_input("Password", type="password")
    if st.button("Login"):
        with app.app_context():
            user = User.query.filter_by(username=username).first()
            if user and bcrypt.check_password_hash(user.password, password):
                st.session_state['user_id'] = user.id
                st.success("Login successful!")
            else:
                st.error("Invalid username or password.")

# Dashboard Page
def dashboard():
    if 'user_id' not in st.session_state:
        st.warning("You need to log in first.")
        return

    st.title("Dashboard")
    user_id = st.session_state['user_id']
    with app.app_context():
        user = User.query.get(user_id)
        st.header(f"Hello, {user.username}")

        user_issues = Issue.query.filter_by(created_by=user_id).all()
        collaboration_issues = Issue.query.join(Collaborator).filter(Collaborator.user_id == user_id).all()

    st.header("Your Issues")
    for issue in user_issues:
        st.write(f"Title: {issue.title}")
        if st.button(f"Submit Solution for {issue.title}"):
            submit_solution(issue.id)
        if st.button(f"Decide on {issue.title}"):
            decide(issue.id)

    st.header("Issues You Are Collaborating On")
    for issue in collaboration_issues:
        st.write(f"Title: {issue.title}")
        if st.button(f"Submit Solution for {issue.title}"):
            submit_solution(issue.id)
        if st.button(f"Decide on {issue.title}"):
            decide(issue.id)

# Create Issue Page
def create_issue():
    if 'user_id' not in st.session_state:
        st.warning("You need to log in first.")
        return

    st.title("Create Issue")
    title = st.text_input("Issue Title")
    description = st.text_area("Issue Description")
    if st.button("Create Issue"):
        with app.app_context():
            new_issue = Issue(title=title, description=description, created_by=st.session_state['user_id'])
            db.session.add(new_issue)
            db.session.commit()
        st.success("Issue created successfully!")

# Invite Collaborators Page
def invite_collaborators():
    if 'user_id' not in st.session_state:
        st.warning("You need to log in first.")
        return

    st.title("Invite Collaborators")
    issue_id = st.number_input("Issue ID", min_value=1, step=1)
    emails = st.text_input("Collaborator Emails (comma-separated)")
    if st.button("Send Invites"):
        with app.app_context():
            issue = Issue.query.get(issue_id)
            if issue:
                for email in emails.split(','):
                    email = email.strip()
                    user = User.query.filter_by(email=email).first()
                    if user:
                        new_collaborator = Collaborator(issue_id=issue_id, user_id=user.id)
                        db.session.add(new_collaborator)
                    msg = Message('Collaboration Invite', sender='[email protected]', recipients=[email])
                    msg.body = f"You have been invited to collaborate on the issue: {issue.title}."
                    mail.send(msg)
                db.session.commit()
                st.success("Invitations sent successfully!")
            else:
                st.error("Issue not found.")

# Submit Solution Page
def submit_solution(issue_id):
    if 'user_id' not in st.session_state:
        st.warning("You need to log in first.")
        return

    st.title(f"Submit Solution for Issue {issue_id}")
    solution_content = st.text_area("Your Solution")
    if st.button("Submit Solution"):
        with app.app_context():
            new_solution = Solution(content=solution_content, issue_id=issue_id, created_by=st.session_state['user_id'])
            db.session.add(new_solution)
            db.session.commit()
        st.success("Solution submitted successfully!")

# Decide Page
def decide(issue_id):
    with app.app_context():
        issue = Issue.query.get(issue_id)
        solutions = Solution.query.filter_by(issue_id=issue_id).all()
    
    if issue:
        st.title(f"Decide on Issue: {issue.title}")
        for solution in solutions:
            st.write(f"- {solution.content}")

        if st.button("Get AI Decision"):
            openai.api_key = open_ai_api_key
            prompt = f"Given the following solutions for the issue '{issue.title}', which one is the most socio-democratic decision?\n"
            for solution in solutions:
                prompt += f"- {solution.content}\n"
            prompt += "Please consider socio-democratic values and provide a summary on the best decision. Do not use the term socio-democratic in any reply."

            response = openai.ChatCompletion.create(
                model="gpt-3.5-turbo",
                messages=[
                    {"role": "system", "content": "You are an assistant helping to make socio-democratic decisions. Do not use the term socio-democratic in any reply."},
                    {"role": "user", "content": prompt}
                ],
                max_tokens=150
            )
            decision = response.choices[0].message['content'].strip()
            st.write(f"WDWT? AI Decision: {decision}")

# Settings Page
def settings():
    if 'user_id' not in st.session_state:
        st.warning("You need to log in first.")
        return

    st.title("Settings")
    st.write("Update your general information here.")
    # Add settings fields as needed

# Main Flow
if 'user_id' not in st.session_state:
    st.session_state['user_id'] = None

if page == "Register":
    register()
elif page == "Login":
    login()
elif page == "Dashboard":
    dashboard()
elif page == "Create Issue":
    create_issue()
elif page == "Invite Collaborators":
    invite_collaborators()
elif page == "Submit Solution":
    issue_id = st.number_input("Issue ID", min_value=1, step=1)
    submit_solution(issue_id)
elif page == "Decide":
    issue_id = st.number_input("Issue ID", min_value=1, step=1)
    decide(issue_id)
elif page == "Settings":
    settings()

# Ensure tables are created
if __name__ == '__main__':
    with app.app_context():
        db.create_all()