Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import dash
|
2 |
+
from dash import dcc, html, Input, Output, State, callback
|
3 |
+
import dash_bootstrap_components as dbc
|
4 |
+
import base64
|
5 |
+
import io
|
6 |
+
import pandas as pd
|
7 |
+
import openai
|
8 |
+
import os
|
9 |
+
import time
|
10 |
+
from dash.exceptions import PreventUpdate
|
11 |
+
|
12 |
+
# Initialize the Dash app
|
13 |
+
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
14 |
+
|
15 |
+
# Get OpenAI API key from Hugging Face Spaces environment variable
|
16 |
+
openai.api_key = os.environ.get('OPENAI_API_KEY')
|
17 |
+
|
18 |
+
# Global variables
|
19 |
+
uploaded_files = []
|
20 |
+
current_matrix = None
|
21 |
+
matrix_type = None
|
22 |
+
|
23 |
+
# Matrix types and their descriptions
|
24 |
+
matrix_types = {
|
25 |
+
"Communications Plan Matrix": "Create a matrix showing stakeholders, communication methods, frequency, and responsibilities.",
|
26 |
+
"Project Kick-off Matrix": "Generate a matrix outlining key project details, goals, team roles, and initial timelines.",
|
27 |
+
"Decision Matrix": "Develop a matrix for evaluating options against criteria, with weighted scores.",
|
28 |
+
"Lessons Learned Matrix": "Create a matrix capturing project experiences, challenges, solutions, and recommendations.",
|
29 |
+
"Key Performance Indicator Matrix": "Generate a matrix of KPIs, their targets, actual performance, and status.",
|
30 |
+
"Prioritization Matrix": "Develop a matrix for ranking tasks or features based on importance and urgency.",
|
31 |
+
"Risk Matrix": "Create a matrix assessing potential risks, their likelihood, impact, and mitigation strategies.",
|
32 |
+
"RACI Matrix": "Generate a matrix showing team members and their roles (Responsible, Accountable, Consulted, Informed) for each task.",
|
33 |
+
"Project Schedule Matrix": "Develop a matrix showing project phases, tasks, durations, and dependencies.",
|
34 |
+
"Quality Control Matrix": "Create a matrix outlining quality standards, testing methods, and acceptance criteria.",
|
35 |
+
"Requirements Traceability Matrix": "Generate a matrix linking requirements to their sources, test cases, and status.",
|
36 |
+
"Sprint Planning Matrix": "Develop a matrix for sprint tasks, story points, assignees, and status.",
|
37 |
+
"Test Traceability Matrix": "Create a matrix linking test cases to requirements, execution status, and results.",
|
38 |
+
"Sprint Backlog": "Generate a matrix of user stories, tasks, estimates, and priorities for the sprint.",
|
39 |
+
"Sprint Retrospective": "Develop a matrix capturing what went well, what didn't, and action items from the sprint.",
|
40 |
+
"SWOT Matrix": "Create a matrix analyzing Strengths, Weaknesses, Opportunities, and Threats."
|
41 |
+
}
|
42 |
+
|
43 |
+
# Layout
|
44 |
+
app.layout = dbc.Container([
|
45 |
+
dbc.Row([
|
46 |
+
dbc.Col([
|
47 |
+
html.H4("Project Artifacts", className="mt-3 mb-4"),
|
48 |
+
dcc.Upload(
|
49 |
+
id='upload-files',
|
50 |
+
children=html.Div([
|
51 |
+
'Drag and Drop or ',
|
52 |
+
html.A('Select Files')
|
53 |
+
]),
|
54 |
+
style={
|
55 |
+
'width': '100%',
|
56 |
+
'height': '60px',
|
57 |
+
'lineHeight': '60px',
|
58 |
+
'borderWidth': '1px',
|
59 |
+
'borderStyle': 'dashed',
|
60 |
+
'borderRadius': '5px',
|
61 |
+
'textAlign': 'center',
|
62 |
+
'margin': '10px 0'
|
63 |
+
},
|
64 |
+
multiple=True
|
65 |
+
),
|
66 |
+
html.Div(id='file-list'),
|
67 |
+
html.Hr(),
|
68 |
+
html.Div([
|
69 |
+
dbc.Button(
|
70 |
+
matrix_type,
|
71 |
+
id=f'btn-{matrix_type.lower().replace(" ", "-")}',
|
72 |
+
color="primary",
|
73 |
+
className="mb-2 w-100",
|
74 |
+
style={'overflow': 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap'}
|
75 |
+
) for matrix_type in matrix_types.keys()
|
76 |
+
])
|
77 |
+
], width=3),
|
78 |
+
dbc.Col([
|
79 |
+
html.Div(id='matrix-preview', className="border p-3 mb-3"),
|
80 |
+
dcc.Loading(
|
81 |
+
id="loading-indicator",
|
82 |
+
type="dot",
|
83 |
+
children=[html.Div(id="loading-output")]
|
84 |
+
),
|
85 |
+
dbc.Button("Download Matrix", id="btn-download", color="success", className="mt-3"),
|
86 |
+
dcc.Download(id="download-matrix"),
|
87 |
+
html.Hr(),
|
88 |
+
dbc.Input(id="chat-input", type="text", placeholder="Chat with GPT to update matrix...", className="mb-2"),
|
89 |
+
dbc.Button("Send", id="btn-send-chat", color="primary", className="mb-3"),
|
90 |
+
html.Div(id="chat-output")
|
91 |
+
], width=9)
|
92 |
+
])
|
93 |
+
], fluid=True)
|
94 |
+
|
95 |
+
@app.callback(
|
96 |
+
Output('file-list', 'children'),
|
97 |
+
Input('upload-files', 'contents'),
|
98 |
+
State('upload-files', 'filename'),
|
99 |
+
State('file-list', 'children')
|
100 |
+
)
|
101 |
+
def update_output(list_of_contents, list_of_names, existing_files):
|
102 |
+
if list_of_contents is not None:
|
103 |
+
new_files = [
|
104 |
+
html.Div([
|
105 |
+
html.Button('×', id={'type': 'remove-file', 'index': i}, style={'marginRight': '5px', 'fontSize': '10px'}),
|
106 |
+
html.Span(filename)
|
107 |
+
]) for i, filename in enumerate(list_of_names)
|
108 |
+
]
|
109 |
+
if existing_files is None:
|
110 |
+
existing_files = []
|
111 |
+
return existing_files + new_files
|
112 |
+
return existing_files
|
113 |
+
|
114 |
+
@app.callback(
|
115 |
+
Output('matrix-preview', 'children'),
|
116 |
+
Output('loading-output', 'children'),
|
117 |
+
[Input(f'btn-{matrix_type.lower().replace(" ", "-")}', 'n_clicks') for matrix_type in matrix_types.keys()],
|
118 |
+
prevent_initial_call=True
|
119 |
+
)
|
120 |
+
def generate_matrix(*args):
|
121 |
+
global current_matrix, matrix_type
|
122 |
+
ctx = dash.callback_context
|
123 |
+
if not ctx.triggered:
|
124 |
+
raise PreventUpdate
|
125 |
+
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
126 |
+
matrix_type = button_id.replace('btn-', '').replace('-', ' ').title()
|
127 |
+
|
128 |
+
# Simulate matrix generation (replace with actual OpenAI call)
|
129 |
+
time.sleep(2) # Simulating API call delay
|
130 |
+
current_matrix = pd.DataFrame({
|
131 |
+
'Column 1': ['Row 1', 'Row 2', 'Row 3'],
|
132 |
+
'Column 2': ['Data 1', 'Data 2', 'Data 3'],
|
133 |
+
'Column 3': ['Info 1', 'Info 2', 'Info 3']
|
134 |
+
})
|
135 |
+
|
136 |
+
return dbc.Table.from_dataframe(current_matrix, striped=True, bordered=True, hover=True), f"{matrix_type} generated"
|
137 |
+
|
138 |
+
@app.callback(
|
139 |
+
Output('chat-output', 'children'),
|
140 |
+
Output('matrix-preview', 'children', allow_duplicate=True),
|
141 |
+
Input('btn-send-chat', 'n_clicks'),
|
142 |
+
State('chat-input', 'value'),
|
143 |
+
prevent_initial_call=True
|
144 |
+
)
|
145 |
+
def update_matrix_via_chat(n_clicks, chat_input):
|
146 |
+
global current_matrix
|
147 |
+
if not chat_input:
|
148 |
+
raise PreventUpdate
|
149 |
+
|
150 |
+
# Simulate chat interaction and matrix update (replace with actual OpenAI call)
|
151 |
+
time.sleep(1) # Simulating API call delay
|
152 |
+
chat_response = f"Updated the matrix based on: {chat_input}"
|
153 |
+
current_matrix = current_matrix.append({'Column 1': 'New Row', 'Column 2': 'New Data', 'Column 3': 'New Info'}, ignore_index=True)
|
154 |
+
|
155 |
+
return chat_response, dbc.Table.from_dataframe(current_matrix, striped=True, bordered=True, hover=True)
|
156 |
+
|
157 |
+
@app.callback(
|
158 |
+
Output("download-matrix", "data"),
|
159 |
+
Input("btn-download", "n_clicks"),
|
160 |
+
prevent_initial_call=True
|
161 |
+
)
|
162 |
+
def download_matrix(n_clicks):
|
163 |
+
global current_matrix, matrix_type
|
164 |
+
if current_matrix is None:
|
165 |
+
raise PreventUpdate
|
166 |
+
|
167 |
+
# Create an in-memory Excel file
|
168 |
+
output = io.BytesIO()
|
169 |
+
with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
|
170 |
+
current_matrix.to_excel(writer, sheet_name='Sheet1', index=False)
|
171 |
+
|
172 |
+
return dcc.send_bytes(output.getvalue(), f"{matrix_type}.xlsx")
|
173 |
+
|
174 |
+
if __name__ == '__main__':
|
175 |
+
print("Starting the Dash application...")
|
176 |
+
app.run(debug=True, host='0.0.0.0', port=7860)
|
177 |
+
print("Dash application has finished running.")
|