supervisely 6.73.431__py3-none-any.whl → 6.73.432__py3-none-any.whl
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.
- supervisely/app/widgets/dataset_thumbnail/dataset_thumbnail.py +11 -2
- supervisely/app/widgets/dataset_thumbnail/template.html +3 -1
- supervisely/app/widgets/fast_table/fast_table.py +156 -21
- supervisely/app/widgets/fast_table/script.js +165 -36
- supervisely/app/widgets/fast_table/style.css +32 -2
- supervisely/app/widgets/fast_table/template.html +1 -1
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/METADATA +1 -1
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/RECORD +12 -12
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/LICENSE +0 -0
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/WHEEL +0 -0
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.431.dist-info → supervisely-6.73.432.dist-info}/top_level.txt +0 -0
|
@@ -19,6 +19,10 @@ class DatasetThumbnail(Widget):
|
|
|
19
19
|
:type dataset_info: Optional[DatasetInfo]
|
|
20
20
|
:param show_project_name: if True, project name will be shown
|
|
21
21
|
:type show_project_name: Optional[bool]
|
|
22
|
+
:param remove_margins: if True, removes margins around the widget
|
|
23
|
+
:type remove_margins: bool, optional
|
|
24
|
+
:param custom_name: custom name for the dataset (if None, actual dataset name will be used)
|
|
25
|
+
:type custom_name: str, optional
|
|
22
26
|
:param widget_id: An identifier of the widget.
|
|
23
27
|
:type widget_id: str, optional
|
|
24
28
|
|
|
@@ -38,18 +42,21 @@ class DatasetThumbnail(Widget):
|
|
|
38
42
|
project_info: Optional[ProjectInfo] = None,
|
|
39
43
|
dataset_info: Optional[DatasetInfo] = None,
|
|
40
44
|
show_project_name: Optional[bool] = True,
|
|
45
|
+
remove_margins: bool = False,
|
|
46
|
+
custom_name: str = None,
|
|
41
47
|
widget_id: Optional[str] = None,
|
|
42
48
|
):
|
|
43
49
|
self._project_info: ProjectInfo = None
|
|
44
50
|
self._dataset_info: DatasetInfo = None
|
|
45
51
|
self._id: int = None
|
|
46
|
-
self._name: str =
|
|
52
|
+
self._name: str = custom_name
|
|
47
53
|
self._description: str = None
|
|
48
54
|
self._url: str = None
|
|
49
55
|
self._image_preview_url: str = None
|
|
50
56
|
self._show_project_name: bool = show_project_name
|
|
51
57
|
self._project_name: str = None
|
|
52
58
|
self._project_url: str = None
|
|
59
|
+
self._remove_margins: bool = remove_margins
|
|
53
60
|
self._set_info(project_info, dataset_info, show_project_name)
|
|
54
61
|
|
|
55
62
|
super().__init__(widget_id=widget_id, file_path=__file__)
|
|
@@ -79,6 +86,7 @@ class DatasetThumbnail(Widget):
|
|
|
79
86
|
"show_project_name": self._show_project_name,
|
|
80
87
|
"project_name": self._project_name,
|
|
81
88
|
"project_url": self._project_url,
|
|
89
|
+
"removeMargins": self._remove_margins,
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
def get_json_state(self) -> None:
|
|
@@ -96,7 +104,8 @@ class DatasetThumbnail(Widget):
|
|
|
96
104
|
self._project_info = project_info
|
|
97
105
|
self._dataset_info = dataset_info
|
|
98
106
|
self._id = dataset_info.id
|
|
99
|
-
self._name
|
|
107
|
+
if self._name is None:
|
|
108
|
+
self._name = dataset_info.name
|
|
100
109
|
self._description = f"{self._dataset_info.items_count} {self._project_info.type} in dataset"
|
|
101
110
|
self._url = Dataset.get_url(project_id=project_info.id, dataset_id=dataset_info.id)
|
|
102
111
|
self._image_preview_url = dataset_info.image_preview_url
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
<
|
|
1
|
+
<link rel="stylesheet" href="./sly/css/app/widgets/project_thumbnail/style.css" />
|
|
2
|
+
|
|
3
|
+
<sly-field {% if widget._remove_margins %} class="remove-margins" {% endif %} title="" :description="data.{{{widget.widget_id}}}.description">
|
|
2
4
|
<span slot="title">
|
|
3
5
|
<span v-if="data.{{{widget.widget_id}}}.show_project_name">
|
|
4
6
|
<a target="_blank" :href="data.{{{widget.widget_id}}}.project_url">
|
|
@@ -46,6 +46,21 @@ class FastTable(Widget):
|
|
|
46
46
|
:type width: str, optional
|
|
47
47
|
:param widget_id: Unique widget identifier.
|
|
48
48
|
:type widget_id: str, optional
|
|
49
|
+
:param show_header: Whether to show table header
|
|
50
|
+
:type show_header: bool, optional
|
|
51
|
+
:param is_radio: Enable radio button selection mode (single row selection)
|
|
52
|
+
:type is_radio: bool, optional
|
|
53
|
+
:param is_selectable: Enable multiple row selection
|
|
54
|
+
:type is_selectable: bool, optional
|
|
55
|
+
:param header_left_content: Widget to display in the left side of the header
|
|
56
|
+
:type header_left_content: Widget, optional
|
|
57
|
+
:param header_right_content: Widget to display in the right side of the header
|
|
58
|
+
:type header_right_content: Widget, optional
|
|
59
|
+
:param max_selected_rows: Maximum number of rows that can be selected
|
|
60
|
+
:type max_selected_rows: int, optional
|
|
61
|
+
:param search_position: Position of the search input ("left" or "right")
|
|
62
|
+
:type search_position: Literal["left", "right"], optional
|
|
63
|
+
|
|
49
64
|
|
|
50
65
|
:Usage example:
|
|
51
66
|
.. code-block:: python
|
|
@@ -141,6 +156,8 @@ class FastTable(Widget):
|
|
|
141
156
|
is_selectable: bool = False,
|
|
142
157
|
header_left_content: Optional[Widget] = None,
|
|
143
158
|
header_right_content: Optional[Widget] = None,
|
|
159
|
+
max_selected_rows: Optional[int] = None,
|
|
160
|
+
search_position: Optional[Literal["left", "right"]] = None,
|
|
144
161
|
):
|
|
145
162
|
self._supported_types = tuple([pd.DataFrame, list, type(None)])
|
|
146
163
|
self._row_click_handled = False
|
|
@@ -170,8 +187,9 @@ class FastTable(Widget):
|
|
|
170
187
|
self._searched_data = None
|
|
171
188
|
self._active_page = 1
|
|
172
189
|
self._width = width
|
|
173
|
-
self._selected_rows =
|
|
190
|
+
self._selected_rows = []
|
|
174
191
|
self._selected_cell = None
|
|
192
|
+
self._clicked_row = None
|
|
175
193
|
self._is_row_clickable = False
|
|
176
194
|
self._is_cell_clickable = False
|
|
177
195
|
self._search_str = ""
|
|
@@ -179,6 +197,9 @@ class FastTable(Widget):
|
|
|
179
197
|
self._project_meta = self._unpack_project_meta(project_meta)
|
|
180
198
|
self._header_left_content = header_left_content
|
|
181
199
|
self._header_right_content = header_right_content
|
|
200
|
+
self._max_selected_rows = max_selected_rows
|
|
201
|
+
acceptable_search_positions = ["left", "right"]
|
|
202
|
+
self._search_position = search_position if search_position in acceptable_search_positions else "left"
|
|
182
203
|
|
|
183
204
|
# table_options
|
|
184
205
|
self._page_size = page_size
|
|
@@ -234,7 +255,9 @@ class FastTable(Widget):
|
|
|
234
255
|
self._searched_data = self._search(search_value)
|
|
235
256
|
self._rows_total = len(self._searched_data)
|
|
236
257
|
|
|
237
|
-
if
|
|
258
|
+
# if active page is greater than the number of pages (e.g. after filtering)
|
|
259
|
+
max_page = (self._rows_total - 1) // self._page_size + 1
|
|
260
|
+
if (self._rows_total > 0 and self._active_page == 0) or self._active_page > max_page:
|
|
238
261
|
self._active_page = 1
|
|
239
262
|
StateJson()[self.widget_id]["page"] = self._active_page
|
|
240
263
|
|
|
@@ -260,7 +283,13 @@ class FastTable(Widget):
|
|
|
260
283
|
- isRowClickable: whether rows are clickable
|
|
261
284
|
- isCellClickable: whether cells are clickable
|
|
262
285
|
- fixColumns: number of fixed columns
|
|
286
|
+
- isRadio: whether radio button selection mode is enabled
|
|
287
|
+
- isRowSelectable: whether multiple row selection is enabled
|
|
288
|
+
- maxSelectedRows: maximum number of rows that can be selected
|
|
289
|
+
- searchPosition: position of the search input ("left" or "right")
|
|
263
290
|
- pageSize: number of rows per page
|
|
291
|
+
- showHeader: whether to show table header
|
|
292
|
+
- selectionChangedHandled: whether selection changed event listener is set
|
|
264
293
|
|
|
265
294
|
:return: Dictionary with widget data
|
|
266
295
|
:rtype: Dict[str, Any]
|
|
@@ -276,6 +305,9 @@ class FastTable(Widget):
|
|
|
276
305
|
"isCellClickable": self._is_cell_clickable,
|
|
277
306
|
"fixColumns": self._fix_columns,
|
|
278
307
|
"isRadio": self._is_radio,
|
|
308
|
+
"isRowSelectable": self._is_selectable,
|
|
309
|
+
"maxSelectedRows": self._max_selected_rows,
|
|
310
|
+
"searchPosition": self._search_position
|
|
279
311
|
},
|
|
280
312
|
"pageSize": self._page_size,
|
|
281
313
|
"showHeader": self._show_header,
|
|
@@ -286,8 +318,9 @@ class FastTable(Widget):
|
|
|
286
318
|
"""Returns dictionary with widget state.
|
|
287
319
|
Dictionary contains the following fields:
|
|
288
320
|
- search: search string
|
|
289
|
-
-
|
|
321
|
+
- selectedRows: selected rows
|
|
290
322
|
- selectedCell: selected cell
|
|
323
|
+
- clickedRow: clicked row
|
|
291
324
|
- page: active page
|
|
292
325
|
- sort: sorting options with the following fields:
|
|
293
326
|
- column: index of the column to sort by
|
|
@@ -300,6 +333,7 @@ class FastTable(Widget):
|
|
|
300
333
|
"search": self._search_str,
|
|
301
334
|
"selectedRows": self._selected_rows,
|
|
302
335
|
"selectedCell": self._selected_cell,
|
|
336
|
+
"clickedRow": self._clicked_row,
|
|
303
337
|
"page": self._active_page,
|
|
304
338
|
"sort": {
|
|
305
339
|
"column": self._sort_column_idx,
|
|
@@ -383,38 +417,95 @@ class FastTable(Widget):
|
|
|
383
417
|
filter_function = self._default_filter_function
|
|
384
418
|
self._filter_function = filter_function
|
|
385
419
|
|
|
386
|
-
def read_json(self, data: Dict, meta: Dict = None) -> None:
|
|
420
|
+
def read_json(self, data: Dict, meta: Dict = None, custom_columns: Optional[List[Union[str, tuple]]] = None) -> None:
|
|
387
421
|
"""Replace table data with options and project meta in the widget
|
|
388
422
|
|
|
389
|
-
:param data: Table data with options
|
|
423
|
+
:param data: Table data with options:
|
|
424
|
+
- data: table data
|
|
425
|
+
- columns: list of column names
|
|
426
|
+
- projectMeta: project meta information - if provided
|
|
427
|
+
- columnsOptions: list of dicts with options for each column
|
|
428
|
+
- total: total number of rows
|
|
429
|
+
- options: table options with the following fields:
|
|
430
|
+
- isRowClickable: whether rows are clickable
|
|
431
|
+
- isCellClickable: whether cells are clickable
|
|
432
|
+
- fixColumns: number of fixed columns
|
|
433
|
+
- isRadio: whether radio button selection mode is enabled
|
|
434
|
+
- isRowSelectable: whether multiple row selection is enabled
|
|
435
|
+
- maxSelectedRows: maximum number of rows that can be selected
|
|
436
|
+
- searchPosition: position of the search input ("left" or "right")
|
|
437
|
+
- pageSize: number of rows per page
|
|
438
|
+
- showHeader: whether to show table header
|
|
439
|
+
- selectionChangedHandled: whether selection changed event listener is set
|
|
440
|
+
|
|
390
441
|
:type data: dict
|
|
391
442
|
:param meta: Project meta information
|
|
392
443
|
:type meta: dict
|
|
444
|
+
:param custom_columns: List of column names. Can include widgets as tuples (column_name, widget)
|
|
445
|
+
:type custom_columns: List[Union[str, tuple]], optional
|
|
446
|
+
|
|
447
|
+
Example of data dict:
|
|
448
|
+
.. code-block:: python
|
|
449
|
+
|
|
450
|
+
data = {
|
|
451
|
+
"data": [["apple", "21"], ["banana", "15"]],
|
|
452
|
+
"columns": ["Class", "Items"],
|
|
453
|
+
"columnsOptions": [
|
|
454
|
+
{ "type": "class"},
|
|
455
|
+
{ "maxValue": 21, "postfix": "pcs", "tooltip": "description text", "subtitle": "boxes" }
|
|
456
|
+
],
|
|
457
|
+
"options": {
|
|
458
|
+
"isRowClickable": True,
|
|
459
|
+
"isCellClickable": True,
|
|
460
|
+
"fixColumns": 1,
|
|
461
|
+
"isRadio": False,
|
|
462
|
+
"isRowSelectable": True,
|
|
463
|
+
"maxSelectedRows": 5,
|
|
464
|
+
"searchPosition": "right",
|
|
465
|
+
"sort": {"column": 0, "order": "asc"},
|
|
466
|
+
},
|
|
467
|
+
}
|
|
393
468
|
"""
|
|
394
|
-
self._columns_first_idx = self._prepare_json_data(data, "columns")
|
|
395
469
|
self._columns_options = self._prepare_json_data(data, "columnsOptions")
|
|
470
|
+
self._read_custom_columns(custom_columns)
|
|
471
|
+
if not self._columns_first_idx:
|
|
472
|
+
self._columns_first_idx = self._prepare_json_data(data, "columns")
|
|
396
473
|
self._table_options = self._prepare_json_data(data, "options")
|
|
397
474
|
self._project_meta = self._unpack_project_meta(meta)
|
|
398
|
-
|
|
399
|
-
self.
|
|
400
|
-
self.
|
|
401
|
-
|
|
475
|
+
table_data = data.get("data", None)
|
|
476
|
+
self._validate_input_data(table_data)
|
|
477
|
+
self._source_data = self._prepare_input_data(table_data)
|
|
478
|
+
(
|
|
479
|
+
self._parsed_source_data,
|
|
480
|
+
self._sliced_data,
|
|
481
|
+
self._parsed_active_data,
|
|
482
|
+
) = self._prepare_working_data()
|
|
402
483
|
self._rows_total = len(self._parsed_source_data["data"])
|
|
403
484
|
init_options = DataJson()[self.widget_id]["options"]
|
|
404
485
|
init_options.update(self._table_options)
|
|
405
486
|
sort = init_options.pop("sort", {"column": None, "order": None})
|
|
406
|
-
|
|
487
|
+
self._active_page = 1
|
|
488
|
+
self._sort_column_idx = sort.get("column", None)
|
|
489
|
+
if self._sort_column_idx is not None and self._sort_column_idx > len(self._columns_first_idx) - 1:
|
|
490
|
+
self._sort_column_idx = None
|
|
491
|
+
self._sort_order = sort.get("order", None)
|
|
492
|
+
self._page_size = init_options.pop("pageSize", 10)
|
|
407
493
|
DataJson()[self.widget_id]["data"] = self._parsed_active_data["data"]
|
|
408
494
|
DataJson()[self.widget_id]["columns"] = self._parsed_active_data["columns"]
|
|
409
495
|
DataJson()[self.widget_id]["columnsOptions"] = self._columns_options
|
|
410
496
|
DataJson()[self.widget_id]["options"] = init_options
|
|
411
497
|
DataJson()[self.widget_id]["total"] = len(self._source_data)
|
|
412
|
-
DataJson()[self.widget_id]["pageSize"] =
|
|
498
|
+
DataJson()[self.widget_id]["pageSize"] = self._page_size
|
|
413
499
|
DataJson()[self.widget_id]["projectMeta"] = self._project_meta
|
|
414
|
-
StateJson()[self.widget_id]["sort"] =
|
|
500
|
+
StateJson()[self.widget_id]["sort"]["column"] = self._sort_column_idx
|
|
501
|
+
StateJson()[self.widget_id]["sort"]["order"] = self._sort_order
|
|
502
|
+
StateJson()[self.widget_id]["page"] = self._active_page
|
|
503
|
+
StateJson()[self.widget_id]["selectedRows"] = []
|
|
504
|
+
StateJson()[self.widget_id]["selectedCell"] = None
|
|
505
|
+
self._maybe_update_selected_row()
|
|
506
|
+
self._validate_sort_attrs()
|
|
415
507
|
DataJson().send_changes()
|
|
416
508
|
StateJson().send_changes()
|
|
417
|
-
self.clear_selection()
|
|
418
509
|
|
|
419
510
|
def read_pandas(self, data: pd.DataFrame) -> None:
|
|
420
511
|
"""Replace table data (rows and columns) in the widget.
|
|
@@ -440,6 +531,24 @@ class FastTable(Widget):
|
|
|
440
531
|
def to_json(self, active_page: Optional[bool] = False) -> Dict[str, Any]:
|
|
441
532
|
"""Export table data with current options as dict.
|
|
442
533
|
|
|
534
|
+
Dictionary contains the following fields:
|
|
535
|
+
- data: table data
|
|
536
|
+
- columns: list of column names
|
|
537
|
+
- projectMeta: project meta information - if provided
|
|
538
|
+
- columnsOptions: list of dicts with options for each column
|
|
539
|
+
- total: total number of rows
|
|
540
|
+
- options: table options with the following fields:
|
|
541
|
+
- isRowClickable: whether rows are clickable
|
|
542
|
+
- isCellClickable: whether cells are clickable
|
|
543
|
+
- fixColumns: number of fixed columns
|
|
544
|
+
- isRadio: whether radio button selection mode is enabled
|
|
545
|
+
- isRowSelectable: whether multiple row selection is enabled
|
|
546
|
+
- maxSelectedRows: maximum number of rows that can be selected
|
|
547
|
+
- searchPosition: position of the search input ("left" or "right")
|
|
548
|
+
- pageSize: number of rows per page
|
|
549
|
+
- showHeader: whether to show table header
|
|
550
|
+
- selectionChangedHandled: whether selection changed event listener is set
|
|
551
|
+
|
|
443
552
|
:param active_page: Specifies the size of the data to be exported. If True - returns only the active page of the table
|
|
444
553
|
:type active_page: Optional[bool]
|
|
445
554
|
:return: Table data with current options
|
|
@@ -477,7 +586,7 @@ class FastTable(Widget):
|
|
|
477
586
|
|
|
478
587
|
def clear_selection(self) -> None:
|
|
479
588
|
"""Clears the selection of the table."""
|
|
480
|
-
StateJson()[self.widget_id]["selectedRows"] =
|
|
589
|
+
StateJson()[self.widget_id]["selectedRows"] = []
|
|
481
590
|
StateJson()[self.widget_id]["selectedCell"] = None
|
|
482
591
|
StateJson().send_changes()
|
|
483
592
|
self._maybe_update_selected_row()
|
|
@@ -558,15 +667,15 @@ class FastTable(Widget):
|
|
|
558
667
|
if self._rows_total != 0:
|
|
559
668
|
self.select_row(0)
|
|
560
669
|
else:
|
|
561
|
-
self._selected_rows =
|
|
562
|
-
StateJson()[self.widget_id]["selectedRows"] =
|
|
670
|
+
self._selected_rows = []
|
|
671
|
+
StateJson()[self.widget_id]["selectedRows"] = self._selected_rows
|
|
563
672
|
StateJson().send_changes()
|
|
564
673
|
return
|
|
565
674
|
if not self._selected_rows:
|
|
566
675
|
return
|
|
567
676
|
if self._rows_total == 0:
|
|
568
|
-
self._selected_rows =
|
|
569
|
-
StateJson()[self.widget_id]["selectedRows"] =
|
|
677
|
+
self._selected_rows = []
|
|
678
|
+
StateJson()[self.widget_id]["selectedRows"] = self._selected_rows
|
|
570
679
|
StateJson().send_changes()
|
|
571
680
|
return
|
|
572
681
|
if self._is_selectable:
|
|
@@ -1115,8 +1224,12 @@ class FastTable(Widget):
|
|
|
1115
1224
|
|
|
1116
1225
|
@server.post(selection_changed_route_path)
|
|
1117
1226
|
def _selection_changed():
|
|
1118
|
-
|
|
1119
|
-
|
|
1227
|
+
if self._is_radio:
|
|
1228
|
+
selected_row = self.get_selected_row()
|
|
1229
|
+
func(selected_row)
|
|
1230
|
+
elif self._is_selectable:
|
|
1231
|
+
selected_rows = self.get_selected_rows()
|
|
1232
|
+
func(selected_rows)
|
|
1120
1233
|
|
|
1121
1234
|
self._selection_changed_handled = True
|
|
1122
1235
|
DataJson()[self.widget_id]["selectionChangedHandled"] = True
|
|
@@ -1201,3 +1314,25 @@ class FastTable(Widget):
|
|
|
1201
1314
|
|
|
1202
1315
|
idxs = self._source_data[self._source_data[column].isin(values)].index.tolist()
|
|
1203
1316
|
self.select_rows(idxs)
|
|
1317
|
+
|
|
1318
|
+
def _read_custom_columns(self, columns: List[Union[str, tuple]]) -> None:
|
|
1319
|
+
if not columns:
|
|
1320
|
+
return
|
|
1321
|
+
self._columns = columns
|
|
1322
|
+
self._columns_options = self._columns_options or [{} for _ in columns]
|
|
1323
|
+
self._columns_data = []
|
|
1324
|
+
self._columns_first_idx = []
|
|
1325
|
+
for i, col in enumerate(columns):
|
|
1326
|
+
if isinstance(col, str):
|
|
1327
|
+
self._columns_first_idx.append(col)
|
|
1328
|
+
self._columns_data.append(self.ColumnData(name=col))
|
|
1329
|
+
elif isinstance(col, tuple):
|
|
1330
|
+
self._columns_first_idx.append(col[0])
|
|
1331
|
+
self._columns_data.append(
|
|
1332
|
+
self.ColumnData(name=col[0], is_widget=True, widget=col[1])
|
|
1333
|
+
)
|
|
1334
|
+
self._columns_options[i]["customCell"] = True
|
|
1335
|
+
else:
|
|
1336
|
+
raise TypeError(f"Column name must be a string or a tuple, got {type(col)}")
|
|
1337
|
+
|
|
1338
|
+
self._validate_sort_attrs()
|
|
@@ -17,7 +17,7 @@ Vue.component('fast-table', {
|
|
|
17
17
|
style="flex-grow: 1"
|
|
18
18
|
>
|
|
19
19
|
<slot name="header-left-side-start" />
|
|
20
|
-
<div class="relative w-full md:max-w-[14rem]">
|
|
20
|
+
<div v-if="settings.searchPosition !== 'right'" class="relative w-full md:max-w-[14rem]">
|
|
21
21
|
<i class="zmdi zmdi-search h-4 absolute top-2 left-2.5 opacity-50" />
|
|
22
22
|
<i
|
|
23
23
|
v-if="search"
|
|
@@ -35,6 +35,22 @@ Vue.component('fast-table', {
|
|
|
35
35
|
</div>
|
|
36
36
|
<slot name="header-left-side-end" />
|
|
37
37
|
</div>
|
|
38
|
+
<div v-if="settings.searchPosition === 'right'" class="relative w-full md:max-w-[14rem]">
|
|
39
|
+
<i class="zmdi zmdi-search h-4 absolute top-2 left-2.5 opacity-50" />
|
|
40
|
+
<i
|
|
41
|
+
v-if="search"
|
|
42
|
+
class="zmdi zmdi-close h-4 absolute top-2.5 right-3 opacity-50 cursor-pointer"
|
|
43
|
+
@click="searchChanged('')"
|
|
44
|
+
/>
|
|
45
|
+
<input
|
|
46
|
+
:value="search"
|
|
47
|
+
type="text"
|
|
48
|
+
:placeholder="\`\${name ? \`Search for \${name}...\` : 'Search'}\`"
|
|
49
|
+
class="text-sm rounded-md px-3 py-1.5 text-gray-900 shadow-sm placeholder:text-gray-400 border border-slate-200 w-full pl-8 bg-slate-50"
|
|
50
|
+
@input="searchChanged($event.target.value)"
|
|
51
|
+
@keydown.esc="searchChanged('')"
|
|
52
|
+
>
|
|
53
|
+
</div>
|
|
38
54
|
<div
|
|
39
55
|
v-if="data && data.length"
|
|
40
56
|
class="text-[.9rem] text-slate-500 flex items-center gap-0 w-full md:w-auto whitespace-nowrap"
|
|
@@ -73,6 +89,7 @@ Vue.component('fast-table', {
|
|
|
73
89
|
<table
|
|
74
90
|
ref="tableBox"
|
|
75
91
|
class="w-full text-[.8rem] md:text-[.9rem] mb-1"
|
|
92
|
+
:key="'table-' + page"
|
|
76
93
|
>
|
|
77
94
|
<thead>
|
|
78
95
|
<tr>
|
|
@@ -84,17 +101,25 @@ Vue.component('fast-table', {
|
|
|
84
101
|
>
|
|
85
102
|
</th>
|
|
86
103
|
<th
|
|
87
|
-
v-
|
|
104
|
+
v-if="settings.isRowSelectable && (!settings.maxSelectedRows || settings.maxSelectedRows > 1)"
|
|
88
105
|
class="px-2 md:px-3 py-2.5 whitespace-nowrap first:pl-3 last:pr-3 md:last:pr-6 first:text-left cursor-pointer sticky top-0 bg-slate-50 box-content shadow-[inset_0_-2px_0_#dfe6ec] group"
|
|
89
106
|
:class="{ 'first:sticky first:left-0 first:z-20 first:shadow-[inset_-2px_-2px_0_#dfe6ec]': fixColumns }"
|
|
90
107
|
>
|
|
91
108
|
<el-checkbox
|
|
92
|
-
v-if="settings.isRowSelectable"
|
|
109
|
+
v-if="settings.isRowSelectable && (!settings.maxSelectedRows || settings.maxSelectedRows > 1)"
|
|
93
110
|
size="small"
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
v-model="headerCheckboxModel"
|
|
112
|
+
:indeterminate="isSomeOnPageSelected && !isAllOnPageSelected"
|
|
113
|
+
:key="'headercb-' + page + '-' + (data && data.map(r => r.idx).join(',')) + '-' + (selectedRows && selectedRows.map(r => r.idx).join(',')) + '-' + (isAllOnPageSelected?1:0) + '-' + (isSomeOnPageSelected?1:0)"
|
|
114
|
+
style="transform: scale(1.2);"
|
|
96
115
|
/>
|
|
97
116
|
</th>
|
|
117
|
+
<th
|
|
118
|
+
v-if="settings.isRowSelectable && settings.maxSelectedRows === 1"
|
|
119
|
+
class="px-2 md:px-3 py-2.5 whitespace-nowrap first:pl-3 last:pr-3 md:last:pr-6 first:text-left cursor-pointer sticky top-0 bg-slate-50 box-content shadow-[inset_0_-2px_0_#dfe6ec] group"
|
|
120
|
+
:class="{ 'first:sticky first:left-0 first:z-20 first:shadow-[inset_-2px_-2px_0_#dfe6ec]': fixColumns }"
|
|
121
|
+
>
|
|
122
|
+
</th>
|
|
98
123
|
<th
|
|
99
124
|
v-for="(c,idx) in columns.slice(0, columnNumberLimit)"
|
|
100
125
|
class="px-2 md:px-3 py-2.5 whitespace-nowrap first:pl-3 last:pr-3 md:first:pl-6 md:last:pr-6 first:text-left cursor-pointer sticky top-0 bg-slate-50 box-content shadow-[inset_0_-2px_0_#dfe6ec] group"
|
|
@@ -140,12 +165,13 @@ Vue.component('fast-table', {
|
|
|
140
165
|
</th>
|
|
141
166
|
</tr>
|
|
142
167
|
</thead>
|
|
143
|
-
<tbody>
|
|
168
|
+
<tbody :key="'page-' + page">
|
|
144
169
|
<tr
|
|
145
170
|
v-for="row in data"
|
|
171
|
+
:key="'row-' + rowKeyValue(row)"
|
|
146
172
|
class="border-b border-gray-200 last:border-0 group"
|
|
147
173
|
:class="{ 'cursor-pointer': settings.isRowClickable }"
|
|
148
|
-
@click="settings.isRowClickable && $emit('row-click', { idx: row
|
|
174
|
+
@click="settings.isRowClickable && $emit('row-click', { idx: rowKeyValue(row), row: row.items, columnsSettings })"
|
|
149
175
|
>
|
|
150
176
|
<td
|
|
151
177
|
v-if="settings.isRadio"
|
|
@@ -169,8 +195,11 @@ Vue.component('fast-table', {
|
|
|
169
195
|
>
|
|
170
196
|
<el-checkbox
|
|
171
197
|
size="small"
|
|
172
|
-
|
|
173
|
-
@
|
|
198
|
+
v-model="rowCheckboxModel[rowKeyValue(row)]"
|
|
199
|
+
@change="onRowCheckboxChange(row, rowCheckboxModel[rowKeyValue(row)])"
|
|
200
|
+
@click.stop
|
|
201
|
+
:key="'rowcb-' + page + '-' + rowKeyValue(row)"
|
|
202
|
+
style="transform: scale(1.2);"
|
|
174
203
|
/>
|
|
175
204
|
</td>
|
|
176
205
|
|
|
@@ -314,11 +343,16 @@ Vue.component('fast-table', {
|
|
|
314
343
|
type: Boolean,
|
|
315
344
|
default: false,
|
|
316
345
|
},
|
|
346
|
+
rowKey: {
|
|
347
|
+
type: String,
|
|
348
|
+
default: 'idx',
|
|
349
|
+
},
|
|
317
350
|
},
|
|
318
351
|
|
|
319
352
|
data() {
|
|
320
353
|
return {
|
|
321
354
|
columnNumberLimit: 50,
|
|
355
|
+
rowCheckboxModel: {},
|
|
322
356
|
};
|
|
323
357
|
},
|
|
324
358
|
|
|
@@ -342,6 +376,7 @@ Vue.component('fast-table', {
|
|
|
342
376
|
settings() {
|
|
343
377
|
const defaultSettings = {
|
|
344
378
|
showHeaderControls: true,
|
|
379
|
+
searchPosition: 'left',
|
|
345
380
|
};
|
|
346
381
|
return {
|
|
347
382
|
...defaultSettings,
|
|
@@ -353,10 +388,6 @@ Vue.component('fast-table', {
|
|
|
353
388
|
return this.pageSize || 50;
|
|
354
389
|
},
|
|
355
390
|
|
|
356
|
-
selectedRowsById() {
|
|
357
|
-
return _.keyBy(this.selectedRows, 'id');
|
|
358
|
-
},
|
|
359
|
-
|
|
360
391
|
classesMap() {
|
|
361
392
|
return this.projectMeta ? _.keyBy(this.projectMeta.classes, 'title') : {};
|
|
362
393
|
},
|
|
@@ -373,15 +404,53 @@ Vue.component('fast-table', {
|
|
|
373
404
|
return this.columnsSettings.find(i => i?.subtitle);
|
|
374
405
|
},
|
|
375
406
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
407
|
+
isAllOnPageSelected() {
|
|
408
|
+
const rows = this.data || [];
|
|
409
|
+
if (rows.length === 0) return false;
|
|
410
|
+
const selectedIdx = new Set((this.selectedRows || []).map(r => this.rowKeyValue(r)));
|
|
411
|
+
return rows.every(r => selectedIdx.has(this.rowKeyValue(r)));
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
isSomeOnPageSelected() {
|
|
415
|
+
const rows = this.data || [];
|
|
416
|
+
if (rows.length === 0) return false;
|
|
417
|
+
const selectedIdx = new Set((this.selectedRows || []).map(r => this.rowKeyValue(r)));
|
|
418
|
+
const count = rows.filter(r => selectedIdx.has(this.rowKeyValue(r))).length;
|
|
419
|
+
return count > 0 && count < rows.length;
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
selectedIdxSet() {
|
|
423
|
+
return new Set((this.selectedRows || []).map(r => this.rowKeyValue(r)));
|
|
379
424
|
},
|
|
425
|
+
|
|
426
|
+
headerCheckboxModel: {
|
|
427
|
+
get() {
|
|
428
|
+
return this.isAllOnPageSelected;
|
|
429
|
+
},
|
|
430
|
+
set(val) {
|
|
431
|
+
this.selectAllRows(val);
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
|
|
436
|
+
watch: {
|
|
437
|
+
data: {
|
|
438
|
+
immediate: true,
|
|
439
|
+
handler() {
|
|
440
|
+
this.syncRowCheckboxModel();
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
selectedRows: {
|
|
444
|
+
immediate: true,
|
|
445
|
+
handler() {
|
|
446
|
+
this.syncRowCheckboxModel();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
380
449
|
},
|
|
381
450
|
|
|
382
451
|
methods: {
|
|
383
452
|
_updateData() {
|
|
384
|
-
this.$emit('filters-changed')
|
|
453
|
+
this.$emit('filters-changed')
|
|
385
454
|
},
|
|
386
455
|
|
|
387
456
|
searchChanged(val) {
|
|
@@ -409,31 +478,85 @@ Vue.component('fast-table', {
|
|
|
409
478
|
this.updateData();
|
|
410
479
|
},
|
|
411
480
|
|
|
412
|
-
selectAllRows() {
|
|
413
|
-
if (this.
|
|
414
|
-
|
|
415
|
-
|
|
481
|
+
selectAllRows(checked) {
|
|
482
|
+
if (!this.data || this.data.length === 0) return;
|
|
483
|
+
|
|
484
|
+
const current = Array.isArray(this.selectedRows) ? [...this.selectedRows] : [];
|
|
485
|
+
const max = this.settings && this.settings.maxSelectedRows ? this.settings.maxSelectedRows : 0;
|
|
486
|
+
|
|
487
|
+
if (checked) {
|
|
488
|
+
const selectedIdx = new Set(current.map(r => this.rowKeyValue(r)));
|
|
489
|
+
const result = [...current];
|
|
490
|
+
|
|
491
|
+
if (max && max > 0) {
|
|
492
|
+
let quota = Math.max(0, max - result.length);
|
|
493
|
+
for (const r of this.data) {
|
|
494
|
+
const key = this.rowKeyValue(r);
|
|
495
|
+
if (!selectedIdx.has(key)) {
|
|
496
|
+
if (quota <= 0) break;
|
|
497
|
+
result.push(_.cloneDeep(r));
|
|
498
|
+
selectedIdx.add(key);
|
|
499
|
+
quota -= 1;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
this.$emit('update:selected-rows', result);
|
|
503
|
+
} else {
|
|
504
|
+
for (const r of this.data) {
|
|
505
|
+
const key = this.rowKeyValue(r);
|
|
506
|
+
if (!selectedIdx.has(key)) {
|
|
507
|
+
result.push(_.cloneDeep(r));
|
|
508
|
+
selectedIdx.add(key);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
this.$emit('update:selected-rows', result);
|
|
512
|
+
}
|
|
416
513
|
} else {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
this
|
|
420
|
-
if (this.selectedRowsById[row.id]) return;
|
|
421
|
-
|
|
422
|
-
selected.push(row);
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
this.$emit('update:selected-rows', selected);
|
|
514
|
+
const pageIdx = new Set(this.data.map(r => this.rowKeyValue(r)));
|
|
515
|
+
const result = current.filter(r => !pageIdx.has(this.rowKeyValue(r)));
|
|
516
|
+
this.$emit('update:selected-rows', result);
|
|
426
517
|
}
|
|
427
518
|
},
|
|
428
519
|
|
|
429
|
-
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
520
|
+
syncRowCheckboxModel() {
|
|
521
|
+
const map = {};
|
|
522
|
+
const selected = new Set((this.selectedRows || []).map(r => this.rowKeyValue(r)));
|
|
523
|
+
for (const r of (this.data || [])) {
|
|
524
|
+
const key = this.rowKeyValue(r);
|
|
525
|
+
map[key] = selected.has(key);
|
|
526
|
+
}
|
|
527
|
+
this.rowCheckboxModel = map;
|
|
528
|
+
},
|
|
529
|
+
|
|
530
|
+
onRowCheckboxChange(row, checked) {
|
|
531
|
+
this.updateSelectedRows(row, checked);
|
|
532
|
+
},
|
|
533
|
+
|
|
534
|
+
updateSelectedRows(row, checked) {
|
|
535
|
+
checked = typeof checked === 'boolean' ? checked : !!checked;
|
|
536
|
+
const current = Array.isArray(this.selectedRows) ? [...this.selectedRows] : [];
|
|
537
|
+
const key = this.rowKeyValue(row);
|
|
538
|
+
const exists = current.some(r => this.rowKeyValue(r) === key);
|
|
539
|
+
const max = this.settings && this.settings.maxSelectedRows ? this.settings.maxSelectedRows : 0;
|
|
540
|
+
|
|
541
|
+
let result = current;
|
|
542
|
+
if (checked) {
|
|
543
|
+
if (max && max > 0) {
|
|
544
|
+
if (max === 1) {
|
|
545
|
+
result = [_.cloneDeep(row)];
|
|
546
|
+
this.$emit('update:selected-rows', result);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
if (!exists && current.length >= max) {
|
|
550
|
+
// revert checkbox state if over the limit
|
|
551
|
+
this.$nextTick(() => { this.$set(this.rowCheckboxModel, key, false); });
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (!exists) result = [...current, _.cloneDeep(row)];
|
|
434
556
|
} else {
|
|
435
|
-
|
|
557
|
+
if (exists) result = current.filter(r => this.rowKeyValue(r) !== key);
|
|
436
558
|
}
|
|
559
|
+
this.$emit('update:selected-rows', result);
|
|
437
560
|
},
|
|
438
561
|
|
|
439
562
|
updateSelectedRadio(row) {
|
|
@@ -453,6 +576,12 @@ Vue.component('fast-table', {
|
|
|
453
576
|
if (!this.search) return text;
|
|
454
577
|
return text.toString().replace(new RegExp(this.search, 'gi'), match => '<span class="bg-yellow-400">'+match+'</span>');
|
|
455
578
|
},
|
|
579
|
+
|
|
580
|
+
rowKeyValue(row) {
|
|
581
|
+
if (!row) return undefined;
|
|
582
|
+
const keyName = this.rowKey || 'idx';
|
|
583
|
+
return row[keyName] != null ? row[keyName] : row.idx;
|
|
584
|
+
},
|
|
456
585
|
},
|
|
457
586
|
|
|
458
587
|
mounted() {
|
|
@@ -704,8 +704,38 @@
|
|
|
704
704
|
border-width: 1px;
|
|
705
705
|
}
|
|
706
706
|
|
|
707
|
-
.
|
|
708
|
-
|
|
707
|
+
.tailwind .el-checkbox__inner {
|
|
708
|
+
--tw-border-opacity: 1;
|
|
709
|
+
border-width: 1px;
|
|
710
|
+
border-color: rgb(226 232 240 / var(--tw-border-opacity));
|
|
711
|
+
}
|
|
712
|
+
.tailwind .el-checkbox__input.is-checked .el-checkbox__inner,
|
|
713
|
+
.tailwind .el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
|
714
|
+
--tw-bg-opacity: 1;
|
|
715
|
+
background-color: rgb(14 165 233 / var(--tw-bg-opacity));
|
|
716
|
+
border-color: rgb(14 165 233 / var(--tw-bg-opacity));
|
|
717
|
+
}
|
|
718
|
+
/* refine the checkmark so it's thinner and not a full box */
|
|
719
|
+
.tailwind .el-checkbox__inner::after {
|
|
720
|
+
border-left: 0 !important;
|
|
721
|
+
border-top: 0 !important;
|
|
722
|
+
}
|
|
723
|
+
.tailwind .el-checkbox__input.is-checked .el-checkbox__inner::after {
|
|
724
|
+
border-right: 1.5px solid #fff;
|
|
725
|
+
border-bottom: 1.5px solid #fff;
|
|
726
|
+
border-left: 0 !important;
|
|
727
|
+
border-top: 0 !important;
|
|
728
|
+
}
|
|
729
|
+
.tailwind .el-checkbox__input.is-indeterminate .el-checkbox__inner::before {
|
|
730
|
+
background-color: #fff;
|
|
731
|
+
height: 2px;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.tailwind .el-checkbox__inner::after {
|
|
735
|
+
left: 4px;
|
|
736
|
+
top: 1px;
|
|
737
|
+
width: 4px;
|
|
738
|
+
height: 8px;
|
|
709
739
|
}
|
|
710
740
|
|
|
711
741
|
.sly-fast-table-disable-overlay {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
if
|
|
25
25
|
widget._row_click_handled
|
|
26
26
|
%}
|
|
27
|
-
@row-click="state.{{{widget.widget_id}}}.
|
|
27
|
+
@row-click="state.{{{widget.widget_id}}}.clickedRow = $event; post('/{{{widget.widget_id}}}/row_clicked_cb')"
|
|
28
28
|
{%
|
|
29
29
|
endif
|
|
30
30
|
%}
|
|
@@ -216,8 +216,8 @@ supervisely/app/widgets/custom_models_selector/custom_models_selector.py,sha256=
|
|
|
216
216
|
supervisely/app/widgets/custom_models_selector/style.css,sha256=-zPPXHnJvatYj_xVVAb7T8uoSsUTyhm5xCKWkkFQ78E,548
|
|
217
217
|
supervisely/app/widgets/custom_models_selector/template.html,sha256=Ot7dluekJEUtBWYezAVmcg6PbcEtb2_MRaTBhEnvRjk,2888
|
|
218
218
|
supervisely/app/widgets/dataset_thumbnail/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
219
|
-
supervisely/app/widgets/dataset_thumbnail/dataset_thumbnail.py,sha256=
|
|
220
|
-
supervisely/app/widgets/dataset_thumbnail/template.html,sha256=
|
|
219
|
+
supervisely/app/widgets/dataset_thumbnail/dataset_thumbnail.py,sha256=C-PaA9TYTs_AEC-rZr789ww6NMNkBOgZOSKkXHqgs1k,5106
|
|
220
|
+
supervisely/app/widgets/dataset_thumbnail/template.html,sha256=zQZrSLeqbUGR3W0XxuztvEgS1ndnzxvhAhC1JbgmVtk,828
|
|
221
221
|
supervisely/app/widgets/date_picker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
222
222
|
supervisely/app/widgets/date_picker/date_picker.py,sha256=76tXh9OamTk7lz7aQJvKli7T-vbadULs8DpkndlvbeM,8213
|
|
223
223
|
supervisely/app/widgets/date_picker/template.html,sha256=bQ8y6W7ZIXxQ3xRH6SlARBSAhHMOjDZqMddbdOZ69YM,699
|
|
@@ -266,10 +266,10 @@ supervisely/app/widgets/empty/template.html,sha256=aDBKkin5aLuqByzNN517-rTYCGIg5
|
|
|
266
266
|
supervisely/app/widgets/experiment_selector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
267
267
|
supervisely/app/widgets/experiment_selector/experiment_selector.py,sha256=9UseS99hb0ln4QLSeSIfXM7-pIpqLyWsyWoYQsELlnM,28402
|
|
268
268
|
supervisely/app/widgets/fast_table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
269
|
-
supervisely/app/widgets/fast_table/fast_table.py,sha256=
|
|
270
|
-
supervisely/app/widgets/fast_table/script.js,sha256=
|
|
271
|
-
supervisely/app/widgets/fast_table/style.css,sha256=
|
|
272
|
-
supervisely/app/widgets/fast_table/template.html,sha256=
|
|
269
|
+
supervisely/app/widgets/fast_table/fast_table.py,sha256=OlClGdTcERueYBNR8uITYQa-8mwNT53NeIlJokebRN0,56293
|
|
270
|
+
supervisely/app/widgets/fast_table/script.js,sha256=V0l3hlRjejsVM6lSYDF6b79NZgegSdLKH0RBrhumnPU,22728
|
|
271
|
+
supervisely/app/widgets/fast_table/style.css,sha256=DwVGIX4Hap_rG7D570pfyFRAUSMtfHUZEQYs9C6JrAY,16685
|
|
272
|
+
supervisely/app/widgets/fast_table/template.html,sha256=KTeZs6F8bUYOVZ58D7C4yrDTXKB9wvqEVT4RgRZr4sk,2787
|
|
273
273
|
supervisely/app/widgets/field/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
274
274
|
supervisely/app/widgets/field/field.py,sha256=FqBqfIEcUK7R3va30YS_zijWTUSD5QT3-kpLKJNPq7o,6258
|
|
275
275
|
supervisely/app/widgets/field/style.css,sha256=sLMbqxS4EDPykcQZNMXeYdR4v1y1OP6iqcX0tRz7C68,56
|
|
@@ -1127,9 +1127,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1127
1127
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1128
1128
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1129
1129
|
supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
|
|
1130
|
-
supervisely-6.73.
|
|
1131
|
-
supervisely-6.73.
|
|
1132
|
-
supervisely-6.73.
|
|
1133
|
-
supervisely-6.73.
|
|
1134
|
-
supervisely-6.73.
|
|
1135
|
-
supervisely-6.73.
|
|
1130
|
+
supervisely-6.73.432.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1131
|
+
supervisely-6.73.432.dist-info/METADATA,sha256=mJQpgFJG362uNb35ChhLMbHqErpjRc-bx5KHRkaut_c,35433
|
|
1132
|
+
supervisely-6.73.432.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
1133
|
+
supervisely-6.73.432.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1134
|
+
supervisely-6.73.432.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1135
|
+
supervisely-6.73.432.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|