Sathvika-Alla commited on
Commit
2660129
·
verified ·
1 Parent(s): 4478bc2

Upload 4 files

Browse files
converters_improved.json ADDED
The diff for this file is too large to render. See raw diff
 
converters_metadata.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "gugydydtdui86567": {
3
+ "created_at": "2025-05-26T09:37:28.110531",
4
+ "updated_at": "2025-05-26T09:37:28.110531",
5
+ "deleted_at": null,
6
+ "price_history": []
7
+ },
8
+ "390mA - 999999": {
9
+ "created_at": "2025-06-03T11:00:31.755818",
10
+ "updated_at": "2025-06-03T11:00:31.755818",
11
+ "deleted_at": null,
12
+ "price_history": []
13
+ }
14
+ }
converters_with_links_and_pricelist.json ADDED
The diff for this file is too large to render. See raw diff
 
data_syncing.py ADDED
@@ -0,0 +1,414 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import json
3
+ import gradio as gr
4
+ import pandas as pd
5
+ import datetime
6
+ import uuid
7
+ import re
8
+ from typing import Dict, Any
9
+ from collections import OrderedDict
10
+
11
+ # ======================
12
+ # Configuration
13
+ # ======================
14
+ MAIN_JSON_PATH = "/Users/alessiacolumban/TAL_Chatbot/DataPrep/converters_with_links_and_pricelist.json"
15
+ METADATA_JSON_PATH = "/Users/alessiacolumban/TAL_Chatbot/DataPrep/converters_metadata.json"
16
+ SECONDARY_JSON_PATH = "/Users/alessiacolumban/TAL_Chatbot/DataPrep/converters_improved.json"
17
+
18
+ # ======================
19
+ # Data Transformation Functions
20
+ # ======================
21
+ def rename_and_restructure_item_cosmos(item):
22
+ if "id" not in item:
23
+ item["id"] = str(uuid.uuid4())
24
+
25
+ key_mapping = {
26
+ "TYPE": "type",
27
+ "ARTNR": "artnr",
28
+ "CONVERTER DESCRIPTION": "converter_description",
29
+ "STRAIN RELIEF": "strain_relief",
30
+ "LOCATION": "location",
31
+ "DIMMABILITY": "dimmability",
32
+ "CCR (AMPLITUDE)": "ccr_amplitude",
33
+ "SIZE: L*B*H (mm)": "size",
34
+ "EFFICIENCY @full load": "efficiency_full_load",
35
+ "IP": "ip",
36
+ "CLASS": "class",
37
+ "NOM. INPUT VOLTAGE (V)": "nom_input_voltage_v",
38
+ "OUTPUT VOLTAGE (V)": "output_voltage_v",
39
+ "Barcode": "barcode",
40
+ "Name": "name",
41
+ "Listprice": "listprice",
42
+ "Unit": "unit",
43
+ "LifeCycle": "lifecycle",
44
+ "pdf_link": "pdf_link"
45
+ }
46
+
47
+ renamed_item = {}
48
+ for old_key, value in item.items():
49
+ new_key = key_mapping.get(old_key, old_key.lower())
50
+ renamed_item[new_key] = value
51
+
52
+ return renamed_item
53
+
54
+ def clean_keys(obj):
55
+ if isinstance(obj, dict):
56
+ new_obj = OrderedDict()
57
+ for k, v in obj.items():
58
+ if k == "lamps":
59
+ new_obj[k] = v
60
+ else:
61
+ cleaned_key = re.sub(r'[^a-zA-Z0-9_]', '', k)
62
+ new_obj[cleaned_key] = clean_keys(v)
63
+ return new_obj
64
+ elif isinstance(obj, list):
65
+ return [clean_keys(item) for item in obj]
66
+ else:
67
+ return obj
68
+
69
+ # ======================
70
+ # Core Sync Functionality
71
+ # ======================
72
+ def sync_secondary_json():
73
+ """Transforms and saves data to secondary JSON format"""
74
+ try:
75
+ with open(MAIN_JSON_PATH, "r", encoding="utf-8") as f:
76
+ main_data = json.load(f)
77
+ with open(METADATA_JSON_PATH, "r", encoding="utf-8") as f:
78
+ metadata = json.load(f)
79
+
80
+ transformed_list = []
81
+ for converter_id, value in main_data.items():
82
+ # Skip deleted items using metadata
83
+ if metadata.get(converter_id, {}).get("deleted_at"):
84
+ continue
85
+
86
+ # Apply transformations
87
+ item = rename_and_restructure_item_cosmos(value)
88
+ cleaned_item = clean_keys(item)
89
+
90
+ # Ensure required fields
91
+ if "id" not in cleaned_item:
92
+ cleaned_item["id"] = str(uuid.uuid4())
93
+ transformed_list.append(cleaned_item)
94
+
95
+ with open(SECONDARY_JSON_PATH, "w", encoding="utf-8") as f:
96
+ json.dump(transformed_list, f, indent=4, ensure_ascii=False)
97
+
98
+ print("✅ Successfully synced secondary JSON")
99
+ except Exception as e:
100
+ print(f"❌ Sync failed: {str(e)}")
101
+
102
+ # ======================
103
+ # CRUD Functions with Metadata Management
104
+ # ======================
105
+ def load_json() -> Dict[str, Any]:
106
+ with open(MAIN_JSON_PATH, "r", encoding="utf-8") as f:
107
+ return json.load(f)
108
+
109
+ def save_json(data: Dict[str, Any]):
110
+ with open(MAIN_JSON_PATH, "w", encoding="utf-8") as f:
111
+ json.dump(data, f, indent=4, ensure_ascii=False)
112
+ sync_secondary_json()
113
+
114
+ def load_metadata() -> Dict[str, Any]:
115
+ try:
116
+ with open(METADATA_JSON_PATH, "r", encoding="utf-8") as f:
117
+ return json.load(f)
118
+ except FileNotFoundError:
119
+ return {}
120
+
121
+ def save_metadata(data: Dict[str, Any]):
122
+ with open(METADATA_JSON_PATH, "w", encoding="utf-8") as f:
123
+ json.dump(data, f, indent=4, ensure_ascii=False)
124
+
125
+ def get_current_time():
126
+ return datetime.datetime.now().isoformat()
127
+
128
+ def add_converter(
129
+ converter_id, converter_type, artnr, description, strain_relief, location, dimmability,
130
+ ccr, size, efficiency, ip, class_, input_voltage, output_voltage, barcode, name,
131
+ price, unit, lifecycle, pdf_link
132
+ ):
133
+ converter_id = converter_id.strip()
134
+ data = load_json()
135
+ metadata = load_metadata()
136
+
137
+ if converter_id in data:
138
+ return f"Converter '{converter_id}' already exists."
139
+
140
+ now = get_current_time()
141
+
142
+ # Main data entry
143
+ data[converter_id] = {
144
+ "TYPE": converter_type,
145
+ "ARTNR": float(artnr) if artnr else None,
146
+ "CONVERTER DESCRIPTION:": description,
147
+ "STRAIN RELIEF": strain_relief,
148
+ "LOCATION": location,
149
+ "DIMMABILITY": dimmability,
150
+ "CCR (AMPLITUDE)": ccr,
151
+ "SIZE: L*B*H (mm)": size,
152
+ "EFFICIENCY @full load": float(efficiency) if efficiency else None,
153
+ "IP": float(ip) if ip else None,
154
+ "CLASS": float(class_) if class_ else None,
155
+ "NOM. INPUT VOLTAGE (V)": input_voltage,
156
+ "OUTPUT VOLTAGE (V)": output_voltage,
157
+ "Barcode": barcode,
158
+ "Name": name,
159
+ "Listprice": float(price) if price else None,
160
+ "Unit": unit,
161
+ "LifeCycle": lifecycle,
162
+ "pdf_link": pdf_link,
163
+ "lamps": {}
164
+ }
165
+
166
+ # Metadata entry
167
+ metadata[converter_id] = {
168
+ "created_at": now,
169
+ "updated_at": now,
170
+ "deleted_at": None,
171
+ "price_history": [{"timestamp": now, "price": float(price)}] if price else []
172
+ }
173
+
174
+ save_json(data)
175
+ save_metadata(metadata)
176
+ return f"Added converter '{converter_id}'."
177
+
178
+ def update_converter(
179
+ converter_id, converter_type, artnr, description, strain_relief, location, dimmability,
180
+ ccr, size, efficiency, ip, class_, input_voltage, output_voltage, barcode, name,
181
+ price, unit, lifecycle, pdf_link
182
+ ):
183
+ converter_id = converter_id.strip()
184
+ data = load_json()
185
+ metadata = load_metadata()
186
+
187
+ if converter_id not in data:
188
+ return f"Converter '{converter_id}' does not exist."
189
+
190
+ now = get_current_time()
191
+
192
+ # Update main data
193
+ info = data[converter_id]
194
+ update_fields = {
195
+ "TYPE": converter_type,
196
+ "ARTNR": float(artnr) if artnr else None,
197
+ "CONVERTER DESCRIPTION:": description,
198
+ "STRAIN RELIEF": strain_relief,
199
+ "LOCATION": location,
200
+ "DIMMABILITY": dimmability,
201
+ "CCR (AMPLITUDE)": ccr,
202
+ "SIZE: L*B*H (mm)": size,
203
+ "EFFICIENCY @full load": float(efficiency) if efficiency else None,
204
+ "IP": float(ip) if ip else None,
205
+ "CLASS": float(class_) if class_ else None,
206
+ "NOM. INPUT VOLTAGE (V)": input_voltage,
207
+ "OUTPUT VOLTAGE (V)": output_voltage,
208
+ "Barcode": barcode,
209
+ "Name": name,
210
+ "Unit": unit,
211
+ "LifeCycle": lifecycle,
212
+ "pdf_link": pdf_link
213
+ }
214
+
215
+ for key, value in update_fields.items():
216
+ if value:
217
+ info[key] = value
218
+
219
+ # Handle price changes in metadata
220
+ current_price = float(price) if price else None
221
+ if current_price:
222
+ if "Listprice" not in info or current_price != info.get("Listprice"):
223
+ metadata[converter_id]["price_history"].append({
224
+ "timestamp": now,
225
+ "price": current_price
226
+ })
227
+ info["Listprice"] = current_price
228
+
229
+ # Update metadata
230
+ metadata[converter_id]["updated_at"] = now
231
+
232
+ # Handle ID change
233
+ new_type = info.get("TYPE", "")
234
+ new_artnr = info.get("ARTNR", 0)
235
+ new_id = f"{new_type}mA - {int(new_artnr)}"
236
+
237
+ if new_id != converter_id:
238
+ data[new_id] = info
239
+ del data[converter_id]
240
+ metadata[new_id] = metadata.pop(converter_id)
241
+ save_json(data)
242
+ save_metadata(metadata)
243
+ return f"Updated converter. ID changed to '{new_id}'."
244
+ else:
245
+ save_json(data)
246
+ save_metadata(metadata)
247
+ return f"Updated converter '{converter_id}'."
248
+
249
+ def delete_converter(converter_id):
250
+ converter_id = converter_id.strip()
251
+ data = load_json()
252
+ metadata = load_metadata()
253
+
254
+ if converter_id not in data:
255
+ return f"Converter '{converter_id}' does not exist."
256
+
257
+ metadata[converter_id]["deleted_at"] = get_current_time()
258
+ save_metadata(metadata)
259
+ return f"Deleted converter '{converter_id}'."
260
+
261
+ def add_or_update_lamp(converter_id, lamp_name, min_val, max_val):
262
+ converter_id = converter_id.strip()
263
+ data = load_json()
264
+ if converter_id not in data:
265
+ return f"Converter '{converter_id}' does not exist."
266
+
267
+ lamps = data[converter_id].setdefault("lamps", {})
268
+ lamps[lamp_name.strip()] = {
269
+ "min": float(min_val),
270
+ "max": float(max_val)
271
+ }
272
+ save_json(data)
273
+ return f"Added/updated lamp '{lamp_name}' in converter '{converter_id}'."
274
+
275
+ def delete_lamp(converter_id, lamp_name):
276
+ converter_id = converter_id.strip()
277
+ data = load_json()
278
+ if converter_id not in data:
279
+ return f"Converter '{converter_id}' does not exist."
280
+
281
+ lamps = data[converter_id].get("lamps", {})
282
+ if lamp_name.strip() not in lamps:
283
+ return f"Lamp '{lamp_name}' not found."
284
+
285
+ del lamps[lamp_name.strip()]
286
+ save_json(data)
287
+ return f"Deleted lamp '{lamp_name}' from converter '{converter_id}'."
288
+
289
+ def get_converter(converter_id):
290
+ data = load_json()
291
+ return json.dumps(data.get(converter_id.strip(), {}), indent=2, ensure_ascii=False)
292
+
293
+ def filter_lamps(filter_type, n_latest):
294
+ data = load_json()
295
+ records = []
296
+
297
+ for cid, cinfo in data.items():
298
+ if cinfo.get("deleted_at") and filter_type != "Deleted":
299
+ continue
300
+
301
+ record = {
302
+ "Converter ID": cid,
303
+ "Created At": cinfo.get("created_at", ""),
304
+ "Updated At": cinfo.get("updated_at", ""),
305
+ "Price": cinfo.get("Listprice", ""),
306
+ "Lamps": ", ".join(cinfo.get("lamps", {}).keys())
307
+ }
308
+
309
+ if filter_type == "Deleted":
310
+ if cinfo.get("deleted_at"):
311
+ record["Deleted At"] = cinfo["deleted_at"]
312
+ records.append(record)
313
+ elif filter_type == "Price Change" and len(cinfo.get("price_history", [])) > 1:
314
+ record["Price History"] = str(cinfo["price_history"])
315
+ records.append(record)
316
+ else:
317
+ records.append(record)
318
+
319
+ if filter_type == "Latest Added":
320
+ records.sort(key=lambda x: x["Created At"], reverse=True)
321
+ elif filter_type == "Latest Updated":
322
+ records.sort(key=lambda x: x["Updated At"], reverse=True)
323
+
324
+ return pd.DataFrame(records[:n_latest])
325
+
326
+ # ======================
327
+ # Gradio Interface
328
+ # ======================
329
+ with gr.Blocks(title="TAL Converter JSON Editor") as demo:
330
+ gr.Markdown("# TAL Converter JSON Editor")
331
+
332
+ with gr.Tab("Add Converter"):
333
+ inputs = [
334
+ gr.Textbox(label=label) for label in [
335
+ "Converter ID (e.g. 350mA - 930537)", "TYPE", "ARTNR", "CONVERTER DESCRIPTION:",
336
+ "STRAIN RELIEF", "LOCATION", "DIMMABILITY", "CCR (AMPLITUDE)", "SIZE: L*B*H (mm)",
337
+ "EFFICIENCY @full load", "IP", "CLASS", "NOM. INPUT VOLTAGE (V)", "OUTPUT VOLTAGE (V)",
338
+ "Barcode", "Name", "Listprice", "Unit", "LifeCycle", "pdf_link"
339
+ ]
340
+ ]
341
+ add_btn = gr.Button("Add Converter")
342
+ add_output = gr.Textbox(label="Result")
343
+ add_btn.click(
344
+ add_converter,
345
+ inputs=inputs,
346
+ outputs=add_output
347
+ ).then(lambda: [gr.update(value="") for _ in inputs], outputs=inputs)
348
+
349
+ with gr.Tab("Update Converter"):
350
+ update_inputs = [gr.Textbox(label=f"{label} (update)") for label in [
351
+ "Converter ID", "TYPE", "ARTNR", "CONVERTER DESCRIPTION:", "STRAIN RELIEF",
352
+ "LOCATION", "DIMMABILITY", "CCR (AMPLITUDE)", "SIZE: L*B*H (mm)",
353
+ "EFFICIENCY @full load", "IP", "CLASS", "NOM. INPUT VOLTAGE (V)",
354
+ "OUTPUT VOLTAGE (V)", "Barcode", "Name", "Listprice", "Unit", "LifeCycle", "pdf_link"
355
+ ]]
356
+ update_btn = gr.Button("Update Converter")
357
+ update_output = gr.Textbox(label="Result")
358
+ update_btn.click(
359
+ update_converter,
360
+ inputs=update_inputs,
361
+ outputs=update_output
362
+ ).then(lambda: [gr.update(value="") for _ in update_inputs], outputs=update_inputs)
363
+
364
+ with gr.Tab("Delete Converter"):
365
+ converter_id_d = gr.Textbox(label="Converter ID")
366
+ delete_btn = gr.Button("Delete Converter")
367
+ delete_output = gr.Textbox(label="Result")
368
+ delete_btn.click(
369
+ delete_converter,
370
+ inputs=converter_id_d,
371
+ outputs=delete_output
372
+ ).then(lambda: gr.update(value=""), outputs=converter_id_d)
373
+
374
+ with gr.Tab("Lamp Management"):
375
+ lamp_inputs = [
376
+ gr.Textbox(label=label) for label in [
377
+ "Converter ID", "Lamp Name", "Min Value", "Max Value"
378
+ ]
379
+ ]
380
+ lamp_btns = [
381
+ gr.Button("Add/Update Lamp"),
382
+ gr.Button("Delete Lamp")
383
+ ]
384
+ lamp_output = gr.Textbox(label="Result")
385
+ lamp_btns[0].click(
386
+ add_or_update_lamp,
387
+ inputs=lamp_inputs,
388
+ outputs=lamp_output
389
+ ).then(lambda: [gr.update(value="") for _ in lamp_inputs], outputs=lamp_inputs)
390
+ lamp_btns[1].click(
391
+ delete_lamp,
392
+ inputs=lamp_inputs[:2],
393
+ outputs=lamp_output
394
+ ).then(lambda: [gr.update(value="") for _ in lamp_inputs[:2]], outputs=lamp_inputs[:2])
395
+
396
+ with gr.Tab("View Converter"):
397
+ converter_id_v = gr.Textbox(label="Converter ID")
398
+ view_btn = gr.Button("View Converter")
399
+ view_output = gr.Textbox(label="Converter Data", lines=10)
400
+ view_btn.click(get_converter, inputs=converter_id_v, outputs=view_output)
401
+
402
+ with gr.Tab("Converters Table"):
403
+ filter_type = gr.Dropdown(
404
+ choices=["Latest Added", "Latest Updated", "Deleted", "Price Change"],
405
+ value="Latest Added",
406
+ label="Filter Type"
407
+ )
408
+ n_latest = gr.Slider(1, 200, value=5, label="Number of Results")
409
+ filter_btn = gr.Button("Apply Filter")
410
+ lamp_table = gr.DataFrame(label="Converters")
411
+ filter_btn.click(filter_lamps, inputs=[filter_type, n_latest], outputs=lamp_table)
412
+
413
+ if __name__ == "__main__":
414
+ demo.launch()