sample-ui-component-library 0.0.48-dev → 0.0.50-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sample-ui-component-library",
3
- "version": "0.0.48-dev",
3
+ "version": "0.0.50-dev",
4
4
  "description": "A library which contains sample UI elements that can be used for populating layouts.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -46,7 +46,7 @@
46
46
  "@storybook/test": "^8.6.11",
47
47
  "@storybook/theming": "^8.6.11",
48
48
  "css-loader": "^7.1.2",
49
- "dal-engine-core-js-lib-dev": "^0.0.4",
49
+ "dal-engine-core-js-lib-dev": "^0.0.15-dev",
50
50
  "gh-pages": "^6.3.0",
51
51
  "prop-types": "^15.8.1",
52
52
  "raw-loader": "^4.0.2",
@@ -0,0 +1,7 @@
1
+ let EDITOR_MODES = {
2
+ DESIGN: 1,
3
+ MAPPING: 2
4
+ };
5
+ EDITOR_MODES = Object.freeze(EDITOR_MODES);
6
+
7
+ export default EDITOR_MODES;
@@ -54,6 +54,10 @@ export const Editor = forwardRef(({ }, ref) => {
54
54
  const setMapping = useCallback((fileName, mapping) => {
55
55
  dispatch({ type: "SET_MAPPING", payload: { fileName, mapping } });
56
56
  }, []);
57
+
58
+ const setMode = useCallback((mode) => {
59
+ dispatch({ type: "SET_MODE", payload: mode });
60
+ }, []);
57
61
 
58
62
  const api = useMemo(() => {
59
63
  return {
@@ -63,9 +67,10 @@ export const Editor = forwardRef(({ }, ref) => {
63
67
  selectTab,
64
68
  closeTab,
65
69
  moveTab,
66
- setMapping
70
+ setMapping,
71
+ setMode
67
72
  };
68
- }, [state, addTab, selectTab, closeTab, moveTab, setTabGroupId, setMapping]);
73
+ }, [state, addTab, selectTab, closeTab, moveTab, setTabGroupId, setMapping, setMode]);
69
74
 
70
75
  useImperativeHandle(ref, () => api, [api]);
71
76
 
@@ -1,7 +1,11 @@
1
+ import EDITOR_MODES from "./EDITOR_MODES";
2
+
1
3
  export const initialState = {
2
4
  uid: crypto.randomUUID(),
3
5
  tabs: [],
4
6
  activeTab: null,
7
+ mode: EDITOR_MODES.DESIGN,
8
+ mapping: new Map(),
5
9
  parentTabGroupId: null
6
10
  };
7
11
 
@@ -102,23 +106,21 @@ export const editorReducer = (state, action) => {
102
106
 
103
107
  case "SET_MAPPING": {
104
108
  const { mapping, fileName } = action.payload;
105
- console.log(state);
106
- for (let i = 0; i < state.tabs.length; i++) {
107
- const tab = state.tabs[i];
108
- if (tab.name === fileName) {
109
- const updatedTab = { ...tab, mapping: mapping };
110
- const newTabs = [...state.tabs];
111
- newTabs[i] = updatedTab;
112
- return {
113
- ...state,
114
- tabs: newTabs,
115
- activeTab: updatedTab
116
- };
117
- }
118
- }
119
- return state;
109
+ const newMapping = new Map(state.mapping);
110
+ newMapping.set(fileName, mapping);
111
+ return {
112
+ ...state,
113
+ mapping: newMapping
114
+ };
120
115
  }
121
-
116
+
117
+ case "SET_MODE": {
118
+ return {
119
+ ...state,
120
+ mode: action.payload
121
+ };
122
+ }
123
+
122
124
  case "RESET_STATE": {
123
125
  return initialState;
124
126
  }
@@ -1,6 +1,8 @@
1
1
  import React, { useCallback, useLayoutEffect, useEffect, useRef, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
+ import EDITOR_MODES from '../EDITOR_MODES';
5
+
4
6
  import Editor from '@monaco-editor/react';
5
7
 
6
8
  import "./MonacoInstance.scss"
@@ -18,17 +20,12 @@ export const MonacoInstance = ({ }) => {
18
20
  const frameRef = useRef(0);
19
21
 
20
22
  const [overlayDivs, setOverlayDivs] = useState();
21
- const [overlayRanges, setOverlayRanges] = useState();
22
23
 
23
24
  useLayoutEffect(() => {
24
25
  if (state.activeTab) {
25
26
  setEditorContent(state.activeTab.content);
26
27
  setShowEditor(true);
27
- if (state.activeTab.mapping) {
28
- addOverlays(state.activeTab.mapping);
29
- } else {
30
- setOverlayDivs([]);
31
- }
28
+ addOverlays();
32
29
  } else {
33
30
  setShowEditor(false);
34
31
  }
@@ -52,21 +49,23 @@ export const MonacoInstance = ({ }) => {
52
49
  editorRef.current.setValue(content.current);
53
50
  }
54
51
  editorRef.current.layout();
55
- if (state.activeTab?.mapping) {
56
- addOverlays(state.activeTab.mapping);
57
- } else {
58
- setOverlayDivs([]);
59
- }
52
+ addOverlays();
60
53
  }, [state.activeTab]);
61
54
 
62
55
  // Add overlays to editor for the given line ranges.
63
- const addOverlays = useCallback((ranges) => {
56
+ const addOverlays = useCallback(() => {
64
57
  if (!editorRef.current) return;
65
58
 
59
+ if (state.mode !== EDITOR_MODES.MAPPING || !state.mapping.get(state.activeTab?.name)) {
60
+ setOverlayDivs([]);
61
+ return;
62
+ }
63
+
64
+ const ranges = state.mapping.get(state.activeTab?.name);
66
65
  const lineCount = editorRef.current.getModel().getLineCount();
67
- const lineHeight = editorRef.current.getOption(monaco.editor.EditorOption.lineHeight);
68
-
66
+ const lineHeight = editorRef.current.getOption(monaco.editor.EditorOption.lineHeight);
69
67
  const divs = [];
68
+
70
69
  ranges.forEach((entry) => {
71
70
  const top = editorRef.current.getTopForLineNumber(entry.start_line) - editorRef.current.getScrollTop();
72
71
  let bottom = editorRef.current.getTopForLineNumber(entry.end_line + 1) - editorRef.current.getScrollTop();
@@ -77,7 +76,7 @@ export const MonacoInstance = ({ }) => {
77
76
  divs.push(overlayDiv);
78
77
  });
79
78
  setOverlayDivs(divs);
80
- }, [editorRef?.current]);
79
+ }, [editorRef?.current, state]);
81
80
 
82
81
  // Scroll the editor and update overlays on wheel event.
83
82
  const handleWheel = useCallback((e) => {
@@ -85,14 +84,8 @@ export const MonacoInstance = ({ }) => {
85
84
  const deltaY = e.deltaY;
86
85
  const currentScrollTop = editorRef.current.getScrollTop();
87
86
  editorRef.current.setScrollTop(currentScrollTop + deltaY);
88
- if (state.activeTab?.mapping) {
89
- addOverlays(state.activeTab.mapping);
90
- } else {
91
- setOverlayDivs([]);
92
- }
93
- }, [overlayRanges, state.activeTab]);
94
-
95
-
87
+ addOverlays();
88
+ }, [state.activeTab, addOverlays]);
96
89
 
97
90
  // Editor options for Monaco Editor.
98
91
  const editorOptions = {
@@ -118,7 +111,7 @@ export const MonacoInstance = ({ }) => {
118
111
  cancelAnimationFrame(frameRef.current);
119
112
  frameRef.current = requestAnimationFrame(() => {
120
113
  editorRef.current?.layout();
121
- addOverlays(state.activeTab.mapping);
114
+ addOverlays();
122
115
  });
123
116
  });
124
117
 
@@ -153,9 +146,12 @@ export const MonacoInstance = ({ }) => {
153
146
  return (
154
147
  <div className="editor-container" ref={containerRef}>
155
148
  {renderEditor()}
156
- <div className="overlay-layer" onWheel={handleWheel}>
157
- {overlayDivs}
158
- </div>
149
+ {
150
+ state.mode === EDITOR_MODES.MAPPING &&
151
+ <div className="overlay-layer" onWheel={handleWheel}>
152
+ {overlayDivs}
153
+ </div>
154
+ }
159
155
  </div>
160
156
  )
161
157
  }
@@ -1 +1,2 @@
1
- export * from "./Editor.jsx"
1
+ export * from "./Editor.jsx"
2
+ export * from "./EDITOR_MODES.js"
@@ -1,6 +1,7 @@
1
- import { useEffect, useState, useRef, useLayoutEffect } from "react";
1
+ import { useEffect, useState, useRef, useLayoutEffect, useCallback } from "react";
2
2
  import { Editor } from "../components/Editor";
3
3
  import { useArgs } from "@storybook/preview-api";
4
+ import EDITOR_MODES from "../components/Editor/EDITOR_MODES";
4
5
  import { action } from "@storybook/addon-actions";
5
6
  import {
6
7
  DndContext,
@@ -12,7 +13,8 @@ import {
12
13
 
13
14
  import WorkspaceSampleTree from "./data/FileBrowser/workspace_sample.json"
14
15
  import transactiondb_mapping from "./data/Mapping/TransactionDB_mapping.json"
15
- import mapping from "./data/Mapping/mapping.json"
16
+ import { ToolBarEditor } from "./components/ToolBarEditor/ToolBarEditor";
17
+ import translator_mapping from "./data/Mapping/FrenchTranslator_mapping.json"
16
18
 
17
19
  import "./EditorStories.scss"
18
20
 
@@ -43,6 +45,7 @@ const Template = (args) => {
43
45
  const [, updateArgs] = useArgs();
44
46
 
45
47
  const [dragPreviewLabel, setDragPreviewLabel] = useState(<></>);
48
+ const [selectTool, setSelectTool] = useState("select");
46
49
 
47
50
  const editorRef = useRef();
48
51
 
@@ -57,12 +60,12 @@ const Template = (args) => {
57
60
  const result = flattenTree(WorkspaceSampleTree.tree).find(
58
61
  (obj) => obj.name === "TransactionDB.py"
59
62
  );
60
- editorRef.current.addTab(result);
61
- // editorRef.current.setMapping("FrenchTranslator.py", mapping);
63
+ editorRef.current.addTab(result);translator_mapping
62
64
  editorRef.current.setMapping("TransactionDB.py", transactiondb_mapping);
65
+ editorRef.current.setMapping("FrenchTranslator.py", translator_mapping);
63
66
  }, []);
64
67
 
65
- const [dragging, setDragging] = useState(false);
68
+ const [dragging, setDragging] = useState(false);
66
69
 
67
70
  /**
68
71
  * Callback for when drag ends.
@@ -104,10 +107,21 @@ const [dragging, setDragging] = useState(false);
104
107
 
105
108
  window.addEventListener("pointermove", handleMove);
106
109
 
110
+ const handleKeyDown = (event) => {
111
+ console.log("KEY DOWN");
112
+ if (event.code === "KeyA") {
113
+ editorRef.current.setMode(EDITOR_MODES.DESIGN);
114
+ } else if (event.code === "KeyB") {
115
+ editorRef.current.setMode(EDITOR_MODES.MAPPING);
116
+ }
117
+ };
118
+ document.addEventListener("keydown", handleKeyDown);
119
+
107
120
  return () => {
121
+ document.removeEventListener("keydown", handleKeyDown);
108
122
  window.removeEventListener("pointermove", handleMove);
109
123
  };
110
- }, [dragging]);
124
+ }, [dragging, editorRef]);
111
125
 
112
126
  const sensors = useSensors(
113
127
  useSensor(PointerSensor, {
@@ -117,23 +131,38 @@ const [dragging, setDragging] = useState(false);
117
131
  })
118
132
  );
119
133
 
134
+ const onSelectTool = useCallback((tool) => {
135
+ if (tool === "mapping-mode") {
136
+ editorRef.current.setMode(EDITOR_MODES.MAPPING);
137
+ } else if (tool === "implementation-mode") {
138
+ editorRef.current.setMode(EDITOR_MODES.DESIGN);
139
+ }
140
+ }, [editorRef]);
141
+
120
142
  return (
121
143
  <DndContext sensors={sensors} onDragStart={onDragStart} onDragEnd={handleDragEnd}>
122
- <div className="editorStoryWrapper">
123
- <Editor ref={editorRef}{...args} />
124
- </div>
125
- {dragging && (
126
- <div
127
- style={{
128
- position: "fixed",
129
- left: pos.x,
130
- top: pos.y,
131
- pointerEvents: "none",
132
- zIndex: 9999,
133
- }}>
134
- {dragPreviewLabel}
144
+
145
+ <div className="editorRootContainer">
146
+ <div className="toolbar">
147
+ <ToolBarEditor onSelectTool={onSelectTool} />
135
148
  </div>
136
- )}
149
+ <div className="flow">
150
+ <Editor ref={editorRef}{...args} />
151
+ {dragging && (
152
+ <div
153
+ style={{
154
+ position: "fixed",
155
+ left: pos.x,
156
+ top: pos.y,
157
+ pointerEvents: "none",
158
+ zIndex: 9999,
159
+ }}>
160
+ {dragPreviewLabel}
161
+ </div>
162
+ )}
163
+ </div>
164
+ </div>
165
+
137
166
  </DndContext>
138
167
  )
139
168
  }
@@ -1,7 +1,22 @@
1
- .editorStoryWrapper{
1
+
2
+
3
+ .editorRootContainer {
2
4
  position: absolute;
3
5
  top:0;
4
6
  bottom:0;
5
7
  left:0;
6
8
  right:0;
7
- }
9
+ display:flex;
10
+ flex-direction: row;
11
+ }
12
+
13
+ .toolbar {
14
+ width:40px;
15
+ }
16
+
17
+ .flow {
18
+ display: flex;
19
+ flex-grow: 1;
20
+ flex-direction: column;
21
+ overflow:hidden;
22
+ }
@@ -0,0 +1,38 @@
1
+ import React, { useState } from "react";
2
+
3
+ import { Alt, Crosshair } from "react-bootstrap-icons";
4
+
5
+ import "./ToolBarEditor.scss";
6
+
7
+ ToolBarEditor.propTypes = {};
8
+
9
+ /**
10
+ * ToolBarEditor Component
11
+ * @return {JSX.Element}
12
+ */
13
+ export function ToolBarEditor({ onSelectTool }) {
14
+ const [selectedTool, setSelectedTool] = useState("select");
15
+
16
+ const selectTool = (tool) => {
17
+ setSelectedTool(tool);
18
+ onSelectTool(tool);
19
+ };
20
+
21
+ return (
22
+ <div className="toolbarWrapper">
23
+ <div className="toolbarContainer">
24
+ <Alt
25
+ onClick={(e) => selectTool("implementation-mode")}
26
+ title="Implementation Mode"
27
+ className="icon"
28
+ />
29
+ <Crosshair
30
+ onClick={(e) => selectTool("mapping-mode")}
31
+ title="Mapping Mode"
32
+ className="icon"
33
+ />
34
+ </div>
35
+ <div className="toolbarContainer bottom"></div>
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1,29 @@
1
+ .toolbarWrapper {
2
+ display:flex;
3
+ flex-direction: column;
4
+ justify-content:space-around;
5
+ height: 100%;
6
+ background-color: #333333;
7
+ }
8
+
9
+ .toolbarContainer {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: 15px;
13
+ width:100%;
14
+ align-items: center;
15
+ padding: 10px 0;
16
+ }
17
+
18
+ .toolbarWrapper > .bottom {
19
+ margin-top: auto;
20
+ }
21
+
22
+ .toolbarContainer > .icon {
23
+ color:grey;
24
+ }
25
+
26
+ .toolbarContainer > .icon:hover {
27
+ color:white;
28
+ cursor:pointer;
29
+ }
@@ -1,147 +1,147 @@
1
1
  [
2
2
  {
3
3
  "type": "Import",
4
- "uid": "41375952-c2b0-4d81-9833-f7e38afe5130",
4
+ "uid": "3379cd52-2d8c-4e8a-9b1d-bc232f60576b",
5
5
  "start_line": 1,
6
6
  "end_line": 1,
7
7
  "source": "import sqlite3"
8
8
  },
9
9
  {
10
10
  "type": "Import",
11
- "uid": "a8ceb80a-390d-4d0e-a3b4-db9f299a067b",
11
+ "uid": "e5d628dc-f651-4245-a200-79d1873c3386",
12
12
  "start_line": 2,
13
13
  "end_line": 2,
14
14
  "source": "import atexit"
15
15
  },
16
16
  {
17
17
  "type": "Import",
18
- "uid": "eccfad0c-1487-4d39-84e2-24107925be66",
18
+ "uid": "c85d079d-1268-421d-a4bb-fc1f5792d63b",
19
19
  "start_line": 3,
20
20
  "end_line": 3,
21
21
  "source": "import uuid"
22
22
  },
23
23
  {
24
24
  "type": "Expr",
25
- "uid": "b13d053d-b448-42cf-adce-2720d7026c28",
25
+ "uid": "8bf2605a-1940-49de-9b2f-0efa22bf658c",
26
26
  "start_line": 8,
27
27
  "end_line": 8,
28
28
  "source": "atexit.register(self.cleanup_function)"
29
29
  },
30
30
  {
31
31
  "type": "Expr",
32
- "uid": "d735f8a9-b2d9-4af7-b8d0-021bbb8a8945",
32
+ "uid": "595db236-990c-4aea-bae0-d46f17e89729",
33
33
  "start_line": 9,
34
34
  "end_line": 9,
35
35
  "source": "self.initializeDB()"
36
36
  },
37
37
  {
38
38
  "type": "Expr",
39
- "uid": "f96705c3-5afb-4ad2-ad3b-66e0f8c1fa44",
39
+ "uid": "df540a11-0f67-41ce-a9f7-02aafb9996f0",
40
40
  "start_line": 12,
41
41
  "end_line": 12,
42
42
  "source": "self.conn.close()"
43
43
  },
44
44
  {
45
45
  "type": "Assign",
46
- "uid": "3597725d-8fba-486f-9788-4f346ba91be9",
46
+ "uid": "720ce1a8-58d8-4dfc-aaeb-11865bc5311f",
47
47
  "start_line": 16,
48
48
  "end_line": 16,
49
49
  "source": "self.conn = sqlite3.connect(\"translations.db\")"
50
50
  },
51
51
  {
52
52
  "type": "Assign",
53
- "uid": "8e34543e-d1a8-4f0b-9945-9fc61b192e88",
53
+ "uid": "41f3eec1-71eb-4272-941b-c5209befe90d",
54
54
  "start_line": 17,
55
55
  "end_line": 17,
56
56
  "source": "self.cursor = self.conn.cursor()"
57
57
  },
58
58
  {
59
59
  "type": "Expr",
60
- "uid": "3071e179-638f-428c-9afc-e7c92997cec8",
60
+ "uid": "df8a04d5-3b90-445a-8d2f-8a6278cde108",
61
61
  "start_line": 19,
62
62
  "end_line": 29,
63
63
  "source": "self.cursor.execute(\"\"\"\n CREATE TABLE IF NOT EXISTS translation_jobs (\n job_id INTEGER PRIMARY KEY AUTOINCREMENT,\n uid TEXT NOT NULL UNIQUE,\n english TEXT NOT NULL,\n french TEXT,\n spanish TEXT,\n tamil TEXT,\n done INTEGER NOT NULL DEFAULT 0\n );\n \"\"\")"
64
64
  },
65
65
  {
66
66
  "type": "Expr",
67
- "uid": "053a69cc-9959-4011-83b9-9cd01948d560",
67
+ "uid": "0297ec2d-e27c-483a-97ac-a82d4f185a45",
68
68
  "start_line": 30,
69
69
  "end_line": 30,
70
70
  "source": "self.conn.commit()"
71
71
  },
72
72
  {
73
73
  "type": "Assign",
74
- "uid": "c0c88646-99fc-45de-b441-1efbfb617467",
74
+ "uid": "12d3fdc6-44f3-4526-b461-a1037636dc33",
75
75
  "start_line": 33,
76
76
  "end_line": 33,
77
77
  "source": "uid = str(uuid.uuid4())"
78
78
  },
79
79
  {
80
80
  "type": "Expr",
81
- "uid": "a0dc4483-bf8d-4790-b6ee-11d4c3ff6747",
81
+ "uid": "7e3e96ad-99c5-43e1-9e60-2ec7593692e9",
82
82
  "start_line": 34,
83
83
  "end_line": 40,
84
84
  "source": "self.conn.execute(\n \"\"\"\n INSERT INTO translation_jobs (uid, english)\n VALUES (?, ?)\n \"\"\",\n (uid, data)\n )"
85
85
  },
86
86
  {
87
87
  "type": "Expr",
88
- "uid": "5daf0842-9da2-473f-906f-177b2297e42a",
88
+ "uid": "33aaf4bc-2c5c-44d7-aa23-ed4c00dc9850",
89
89
  "start_line": 41,
90
90
  "end_line": 41,
91
91
  "source": "self.conn.commit()"
92
92
  },
93
93
  {
94
94
  "type": "Return",
95
- "uid": "e5507376-e78c-49a8-953f-a50f7d534e91",
95
+ "uid": "91b23b1a-6dbc-4be4-a5c9-3c25bb7e4d31",
96
96
  "start_line": 43,
97
97
  "end_line": 46,
98
98
  "source": "return {\n \"uid\": uid,\n \"value\": {\"data\": data}\n }"
99
99
  },
100
100
  {
101
101
  "type": "Expr",
102
- "uid": "5c91cc00-0bab-45f4-8c44-52b9cbba0033",
102
+ "uid": "9283152d-497a-4adf-ae94-bd36ddfa7ec3",
103
103
  "start_line": 49,
104
104
  "end_line": 56,
105
105
  "source": "self.conn.execute(\n f\"\"\"\n UPDATE translation_jobs\n SET {msg[\"value\"][\"language\"]} = ?\n WHERE uid = ?\n \"\"\",\n (msg[\"value\"][\"translated\"], msg[\"uid\"])\n )"
106
106
  },
107
107
  {
108
108
  "type": "Expr",
109
- "uid": "50dbde63-e2af-4788-bba3-72ce9aa6cd4b",
109
+ "uid": "9e49a0c5-d0f2-41f9-bea7-42db302ba180",
110
110
  "start_line": 57,
111
111
  "end_line": 57,
112
112
  "source": "self.conn.commit()"
113
113
  },
114
114
  {
115
115
  "type": "Assign",
116
- "uid": "709389e7-985b-433e-b2cb-e77d5a4b8b54",
116
+ "uid": "b0885662-490e-4679-84f9-636be9b68198",
117
117
  "start_line": 61,
118
118
  "end_line": 71,
119
119
  "source": "cur = self.conn.execute(\n \"\"\"\n SELECT\n french IS NOT NULL\n AND spanish IS NOT NULL\n AND tamil IS NOT NULL\n FROM translation_jobs\n WHERE uid = ?\n \"\"\",\n (uid,)\n )"
120
120
  },
121
121
  {
122
122
  "type": "Assign",
123
- "uid": "31c90fb9-89a3-45d9-a2cf-ab0941b26668",
123
+ "uid": "9185886f-b795-45fb-9676-aa65e0e54fb5",
124
124
  "start_line": 72,
125
125
  "end_line": 72,
126
126
  "source": "row = cur.fetchone()"
127
127
  },
128
128
  {
129
129
  "type": "Return",
130
- "uid": "2273d6fc-aa36-4abf-9f98-8259a9d3fd0b",
130
+ "uid": "8bdd4fd1-2678-4fd2-943c-016cc601bfe5",
131
131
  "start_line": 73,
132
132
  "end_line": 73,
133
133
  "source": "return bool(row[0]) if row else False"
134
134
  },
135
135
  {
136
136
  "type": "Expr",
137
- "uid": "695d4481-ba24-458d-80db-0e600296cf2b",
137
+ "uid": "c4f43010-71ef-46e6-bf38-0548d3a34012",
138
138
  "start_line": 76,
139
139
  "end_line": 83,
140
140
  "source": "self.conn.execute(\n \"\"\"\n UPDATE translation_jobs\n SET done = 1\n WHERE uid = ?\n \"\"\",\n (uid,)\n )"
141
141
  },
142
142
  {
143
143
  "type": "Expr",
144
- "uid": "7d6571df-d51f-461a-8a2f-59ce793a3444",
144
+ "uid": "d1678a59-0a81-4126-8ca9-befbafbd8986",
145
145
  "start_line": 84,
146
146
  "end_line": 84,
147
147
  "source": "self.conn.commit()"