Update app.py
Browse files
app.py
CHANGED
@@ -11,8 +11,6 @@ from dash.exceptions import PreventUpdate
|
|
11 |
import PyPDF2
|
12 |
import docx
|
13 |
import chardet
|
14 |
-
import json
|
15 |
-
from dash.exceptions import PreventUpdate
|
16 |
|
17 |
# Initialize the Dash app
|
18 |
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
@@ -68,48 +66,30 @@ app.layout = dbc.Container([
|
|
68 |
},
|
69 |
multiple=True
|
70 |
),
|
71 |
-
html.Div(
|
72 |
-
html.H5("Uploaded Files"),
|
73 |
-
dbc.ListGroup(id='file-list')
|
74 |
-
], className="mt-3"),
|
75 |
html.Hr(),
|
76 |
html.Div([
|
77 |
dbc.Button(
|
78 |
matrix_type,
|
79 |
-
id={
|
80 |
-
color="
|
81 |
-
className="mb-2 w-100
|
82 |
-
style={
|
83 |
-
'textAlign': 'left',
|
84 |
-
'textDecoration': 'none',
|
85 |
-
'padding': '0.375rem 0.75rem',
|
86 |
-
'transition': 'background-color 0.3s'
|
87 |
-
}
|
88 |
) for matrix_type in matrix_types.keys()
|
89 |
-
]
|
90 |
], width=3),
|
91 |
dbc.Col([
|
92 |
-
html.Div(style={"height": "20px"}), #
|
93 |
-
html.Div(id="loading-output"), # Text status box
|
94 |
-
html.Div([ # New row for progress indicator
|
95 |
-
dcc.Loading(
|
96 |
-
id="loading-indicator",
|
97 |
-
type="dot",
|
98 |
-
children=[html.Div(style={"height": "50px"})] # Increased height for visibility
|
99 |
-
),
|
100 |
-
], className="my-3"), # Add margin for separation
|
101 |
-
html.Div(id='matrix-preview', className="border p-3 mb-3"),
|
102 |
-
html.Div(id="loading-output"), # Text status box
|
103 |
dcc.Loading(
|
104 |
id="loading-indicator",
|
105 |
type="dot",
|
106 |
-
children=[html.Div()]
|
107 |
),
|
108 |
html.Div(id='matrix-preview', className="border p-3 mb-3"),
|
109 |
dbc.Button("Download Matrix", id="btn-download", color="success", className="mt-3"),
|
110 |
dcc.Download(id="download-matrix"),
|
111 |
html.Hr(),
|
112 |
-
html.Div(style={"height": "20px"}), #
|
113 |
dcc.Loading(
|
114 |
id="chat-loading",
|
115 |
type="dot",
|
@@ -120,10 +100,7 @@ app.layout = dbc.Container([
|
|
120 |
]
|
121 |
)
|
122 |
], width=9)
|
123 |
-
])
|
124 |
-
html.Div(id='uploaded-files-state', style={'display': 'none'}),
|
125 |
-
dcc.Store(id='matrix-type-store'),
|
126 |
-
html.Div(id='matrix-button-clicks', style={'display': 'none'})
|
127 |
], fluid=True)
|
128 |
|
129 |
def parse_file_content(contents, filename):
|
@@ -157,17 +134,17 @@ def update_output(list_of_contents, list_of_names, existing_files):
|
|
157 |
global uploaded_files
|
158 |
if list_of_contents is not None:
|
159 |
new_files = []
|
160 |
-
for content, name in zip(list_of_contents, list_of_names):
|
161 |
file_content = parse_file_content(content, name)
|
162 |
uploaded_files[name] = file_content
|
163 |
-
new_files.append(
|
164 |
-
|
165 |
-
color="danger", size="sm", className="me-2"),
|
166 |
html.Span(name)
|
167 |
]))
|
168 |
-
|
|
|
169 |
return existing_files + new_files
|
170 |
-
return existing_files
|
171 |
|
172 |
@app.callback(
|
173 |
Output('file-list', 'children', allow_duplicate=True),
|
@@ -180,25 +157,10 @@ def remove_file(n_clicks, existing_files):
|
|
180 |
ctx = dash.callback_context
|
181 |
if not ctx.triggered:
|
182 |
raise PreventUpdate
|
183 |
-
|
184 |
-
triggered_id = ctx.triggered[0]['prop_id']
|
185 |
-
removed_file = triggered_id.split('"index":')[1].split('}')[0].strip('"')
|
186 |
-
|
187 |
uploaded_files.pop(removed_file, None)
|
188 |
-
|
189 |
-
|
190 |
-
return [
|
191 |
-
file for file in existing_files
|
192 |
-
if isinstance(file, dict) and
|
193 |
-
'props' in file and
|
194 |
-
'children' in file['props'] and
|
195 |
-
isinstance(file['props']['children'], list) and
|
196 |
-
len(file['props']['children']) > 1 and
|
197 |
-
isinstance(file['props']['children'][1], dict) and
|
198 |
-
'children' in file['props']['children'][1] and
|
199 |
-
file['props']['children'][1]['children'] != removed_file
|
200 |
-
]
|
201 |
-
|
202 |
def generate_matrix_with_gpt(matrix_type, file_contents):
|
203 |
prompt = f"""Generate a {matrix_type} based on the following project artifacts:
|
204 |
{' '.join(file_contents)}
|
@@ -237,40 +199,27 @@ Now, generate the {matrix_type}:
|
|
237 |
|
238 |
return pd.DataFrame(data, columns=headers)
|
239 |
|
240 |
-
@app.callback(
|
241 |
-
Output('uploaded-files-state', 'children'),
|
242 |
-
Input('file-list', 'children')
|
243 |
-
)
|
244 |
-
def update_uploaded_files_state(file_list):
|
245 |
-
global uploaded_files
|
246 |
-
return json.dumps(list(uploaded_files.keys()))
|
247 |
-
|
248 |
@app.callback(
|
249 |
Output('matrix-preview', 'children'),
|
250 |
Output('loading-output', 'children'),
|
251 |
-
Input({
|
252 |
-
State('uploaded-files-state', 'children'),
|
253 |
prevent_initial_call=True
|
254 |
)
|
255 |
-
def generate_matrix(
|
256 |
global current_matrix, matrix_type
|
257 |
ctx = dash.callback_context
|
258 |
if not ctx.triggered:
|
259 |
raise PreventUpdate
|
|
|
|
|
260 |
|
261 |
-
|
262 |
-
matrix_type = json.loads(button_id.split('.')[0])['index']
|
263 |
-
|
264 |
-
if not uploaded_files_json:
|
265 |
return html.Div("Please upload project artifacts before generating a matrix."), ""
|
266 |
|
267 |
-
|
268 |
-
|
269 |
-
if not uploaded_files_list:
|
270 |
-
return html.Div("Please upload project artifacts before generating a matrix."), ""
|
271 |
|
272 |
try:
|
273 |
-
current_matrix = generate_matrix_with_gpt(matrix_type,
|
274 |
return dbc.Table.from_dataframe(current_matrix, striped=True, bordered=True, hover=True), f"{matrix_type} generated"
|
275 |
except Exception as e:
|
276 |
print(f"Error generating matrix: {str(e)}")
|
|
|
11 |
import PyPDF2
|
12 |
import docx
|
13 |
import chardet
|
|
|
|
|
14 |
|
15 |
# Initialize the Dash app
|
16 |
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
|
|
66 |
},
|
67 |
multiple=True
|
68 |
),
|
69 |
+
html.Div(id='file-list'),
|
|
|
|
|
|
|
70 |
html.Hr(),
|
71 |
html.Div([
|
72 |
dbc.Button(
|
73 |
matrix_type,
|
74 |
+
id=f'btn-{matrix_type.lower().replace(" ", "-")}',
|
75 |
+
color="primary",
|
76 |
+
className="mb-2 w-100",
|
77 |
+
style={'overflow': 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap'}
|
|
|
|
|
|
|
|
|
|
|
78 |
) for matrix_type in matrix_types.keys()
|
79 |
+
])
|
80 |
], width=3),
|
81 |
dbc.Col([
|
82 |
+
html.Div(style={"height": "20px"}), # Added small gap
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
dcc.Loading(
|
84 |
id="loading-indicator",
|
85 |
type="dot",
|
86 |
+
children=[html.Div(id="loading-output")]
|
87 |
),
|
88 |
html.Div(id='matrix-preview', className="border p-3 mb-3"),
|
89 |
dbc.Button("Download Matrix", id="btn-download", color="success", className="mt-3"),
|
90 |
dcc.Download(id="download-matrix"),
|
91 |
html.Hr(),
|
92 |
+
html.Div(style={"height": "20px"}), # Added small gap
|
93 |
dcc.Loading(
|
94 |
id="chat-loading",
|
95 |
type="dot",
|
|
|
100 |
]
|
101 |
)
|
102 |
], width=9)
|
103 |
+
])
|
|
|
|
|
|
|
104 |
], fluid=True)
|
105 |
|
106 |
def parse_file_content(contents, filename):
|
|
|
134 |
global uploaded_files
|
135 |
if list_of_contents is not None:
|
136 |
new_files = []
|
137 |
+
for i, (content, name) in enumerate(zip(list_of_contents, list_of_names)):
|
138 |
file_content = parse_file_content(content, name)
|
139 |
uploaded_files[name] = file_content
|
140 |
+
new_files.append(html.Div([
|
141 |
+
html.Button('×', id={'type': 'remove-file', 'index': name}, style={'marginRight': '5px', 'fontSize': '10px'}),
|
|
|
142 |
html.Span(name)
|
143 |
]))
|
144 |
+
if existing_files is None:
|
145 |
+
existing_files = []
|
146 |
return existing_files + new_files
|
147 |
+
return existing_files
|
148 |
|
149 |
@app.callback(
|
150 |
Output('file-list', 'children', allow_duplicate=True),
|
|
|
157 |
ctx = dash.callback_context
|
158 |
if not ctx.triggered:
|
159 |
raise PreventUpdate
|
160 |
+
removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
|
|
|
|
|
|
|
161 |
uploaded_files.pop(removed_file, None)
|
162 |
+
return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file]
|
163 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
def generate_matrix_with_gpt(matrix_type, file_contents):
|
165 |
prompt = f"""Generate a {matrix_type} based on the following project artifacts:
|
166 |
{' '.join(file_contents)}
|
|
|
199 |
|
200 |
return pd.DataFrame(data, columns=headers)
|
201 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
@app.callback(
|
203 |
Output('matrix-preview', 'children'),
|
204 |
Output('loading-output', 'children'),
|
205 |
+
[Input(f'btn-{matrix_type.lower().replace(" ", "-")}', 'n_clicks') for matrix_type in matrix_types.keys()],
|
|
|
206 |
prevent_initial_call=True
|
207 |
)
|
208 |
+
def generate_matrix(*args):
|
209 |
global current_matrix, matrix_type
|
210 |
ctx = dash.callback_context
|
211 |
if not ctx.triggered:
|
212 |
raise PreventUpdate
|
213 |
+
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
214 |
+
matrix_type = button_id.replace('btn-', '').replace('-', ' ').title()
|
215 |
|
216 |
+
if not uploaded_files:
|
|
|
|
|
|
|
217 |
return html.Div("Please upload project artifacts before generating a matrix."), ""
|
218 |
|
219 |
+
file_contents = list(uploaded_files.values())
|
|
|
|
|
|
|
220 |
|
221 |
try:
|
222 |
+
current_matrix = generate_matrix_with_gpt(matrix_type, file_contents)
|
223 |
return dbc.Table.from_dataframe(current_matrix, striped=True, bordered=True, hover=True), f"{matrix_type} generated"
|
224 |
except Exception as e:
|
225 |
print(f"Error generating matrix: {str(e)}")
|