@platforma-sdk/ui-vue 1.84.10 → 1.84.14

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.
Files changed (185) hide show
  1. package/.turbo/turbo-build.log +68 -68
  2. package/.turbo/turbo-formatter$colon$check.log +2 -2
  3. package/.turbo/turbo-linter$colon$check.log +2 -2
  4. package/.turbo/turbo-types$colon$check.log +1 -1
  5. package/CHANGELOG.md +8 -0
  6. package/dist/components/BlockLayout.js.map +1 -1
  7. package/dist/components/BlockLayout.style.js.map +1 -1
  8. package/dist/components/BlockLayout.vue.d.ts.map +1 -1
  9. package/dist/components/BlockLayout.vue2.js +5 -1
  10. package/dist/components/BlockLayout.vue2.js.map +1 -1
  11. package/dist/components/BlockLoader.js.map +1 -1
  12. package/dist/components/BlockLoader.vue.d.ts.map +1 -1
  13. package/dist/components/BlockLoader.vue2.js +2 -0
  14. package/dist/components/BlockLoader.vue2.js.map +1 -1
  15. package/dist/components/LoaderPage.js +4 -1
  16. package/dist/components/LoaderPage.js.map +1 -1
  17. package/dist/components/LoaderPage.vue.d.ts.map +1 -1
  18. package/dist/components/NotFound.js.map +1 -1
  19. package/dist/components/NotFound.vue.d.ts.map +1 -1
  20. package/dist/components/NotFound.vue2.js +11 -5
  21. package/dist/components/NotFound.vue2.js.map +1 -1
  22. package/dist/components/PlAdvancedFilter/FilterEditor.js.map +1 -1
  23. package/dist/components/PlAdvancedFilter/FilterEditor.style.js.map +1 -1
  24. package/dist/components/PlAdvancedFilter/FilterEditor.vue.d.ts.map +1 -1
  25. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +26 -2
  26. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js.map +1 -1
  27. package/dist/components/PlAdvancedFilter/OperandButton.js.map +1 -1
  28. package/dist/components/PlAdvancedFilter/OperandButton.style.js.map +1 -1
  29. package/dist/components/PlAdvancedFilter/OperandButton.vue.d.ts.map +1 -1
  30. package/dist/components/PlAdvancedFilter/OperandButton.vue2.js +2 -1
  31. package/dist/components/PlAdvancedFilter/OperandButton.vue2.js.map +1 -1
  32. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.js.map +1 -1
  33. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.style.js.map +1 -1
  34. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts.map +1 -1
  35. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +70 -61
  36. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
  37. package/dist/components/PlAgCellFile/PlAgCellFile.js.map +1 -1
  38. package/dist/components/PlAgCellFile/PlAgCellFile.vue.d.ts.map +1 -1
  39. package/dist/components/PlAgCellFile/PlAgCellFile.vue2.js +5 -1
  40. package/dist/components/PlAgCellFile/PlAgCellFile.vue2.js.map +1 -1
  41. package/dist/components/PlAgCellProgress/PlAgCellProgress.js.map +1 -1
  42. package/dist/components/PlAgCellProgress/PlAgCellProgress.vue.d.ts.map +1 -1
  43. package/dist/components/PlAgCellProgress/PlAgCellProgress.vue2.js +6 -6
  44. package/dist/components/PlAgCellProgress/PlAgCellProgress.vue2.js.map +1 -1
  45. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.js.map +1 -1
  46. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.d.ts.map +1 -1
  47. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue2.js +8 -2
  48. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue2.js.map +1 -1
  49. package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.js.map +1 -1
  50. package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.d.ts.map +1 -1
  51. package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue2.js +4 -1
  52. package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue2.js.map +1 -1
  53. package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.js.map +1 -1
  54. package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.d.ts.map +1 -1
  55. package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue2.js +7 -2
  56. package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue2.js.map +1 -1
  57. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.js.map +1 -1
  58. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.d.ts.map +1 -1
  59. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js +28 -20
  60. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue2.js.map +1 -1
  61. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.js.map +1 -1
  62. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.d.ts.map +1 -1
  63. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js +1 -0
  64. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue2.js.map +1 -1
  65. package/dist/components/PlAgDataTable/PlAgDataTableSheets.js.map +1 -1
  66. package/dist/components/PlAgDataTable/PlAgDataTableSheets.style.js.map +1 -1
  67. package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue.d.ts.map +1 -1
  68. package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.js +2 -0
  69. package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.js.map +1 -1
  70. package/dist/components/PlAgDataTable/PlAgDataTableV2.js.map +1 -1
  71. package/dist/components/PlAgDataTable/PlAgDataTableV2.style.js.map +1 -1
  72. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
  73. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +5 -1
  74. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
  75. package/dist/components/PlAgDataTable/PlAgOverlayLoading.js.map +1 -1
  76. package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue.d.ts.map +1 -1
  77. package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue2.js +12 -2
  78. package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue2.js.map +1 -1
  79. package/dist/components/PlAgDataTable/PlAgOverlayNoRows.js.map +1 -1
  80. package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue.d.ts.map +1 -1
  81. package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue2.js +7 -1
  82. package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue2.js.map +1 -1
  83. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.js.map +1 -1
  84. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js.map +1 -1
  85. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.d.ts.map +1 -1
  86. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +35 -27
  87. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
  88. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.js.map +1 -1
  89. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.d.ts.map +1 -1
  90. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue2.js +12 -7
  91. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue2.js.map +1 -1
  92. package/dist/components/PlAgRowNumHeader.js.map +1 -1
  93. package/dist/components/PlAgRowNumHeader.vue.d.ts.map +1 -1
  94. package/dist/components/PlAgRowNumHeader.vue2.js +14 -7
  95. package/dist/components/PlAgRowNumHeader.vue2.js.map +1 -1
  96. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.js.map +1 -1
  97. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.d.ts.map +1 -1
  98. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue2.js +8 -1
  99. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue2.js.map +1 -1
  100. package/dist/components/PlAnnotations/components/AnnotationsSidebar.js.map +1 -1
  101. package/dist/components/PlAnnotations/components/AnnotationsSidebar.style.js.map +1 -1
  102. package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue.d.ts.map +1 -1
  103. package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js +14 -3
  104. package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js.map +1 -1
  105. package/dist/components/PlAnnotations/components/FilterSidebar.js.map +1 -1
  106. package/dist/components/PlAnnotations/components/FilterSidebar.style.js.map +1 -1
  107. package/dist/components/PlAnnotations/components/FilterSidebar.vue.d.ts.map +1 -1
  108. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +11 -2
  109. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
  110. package/dist/components/PlAnnotations/components/PlAnnotations.js.map +1 -1
  111. package/dist/components/PlAnnotations/components/PlAnnotations.style.js.map +1 -1
  112. package/dist/components/PlAnnotations/components/PlAnnotations.vue.d.ts.map +1 -1
  113. package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js +1 -1
  114. package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
  115. package/dist/components/PlAnnotations/components/PlAnnotationsModal.js.map +1 -1
  116. package/dist/components/PlAnnotations/components/PlAnnotationsModal.style.js.map +1 -1
  117. package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue.d.ts.map +1 -1
  118. package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js +1 -0
  119. package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js.map +1 -1
  120. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.js.map +1 -1
  121. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.d.ts.map +1 -1
  122. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue2.js +16 -2
  123. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue2.js.map +1 -1
  124. package/dist/components/PlBtnExportArchive/Item.js.map +1 -1
  125. package/dist/components/PlBtnExportArchive/Item.style.js.map +1 -1
  126. package/dist/components/PlBtnExportArchive/Item.vue.d.ts.map +1 -1
  127. package/dist/components/PlBtnExportArchive/Item.vue2.js +12 -2
  128. package/dist/components/PlBtnExportArchive/Item.vue2.js.map +1 -1
  129. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.js.map +1 -1
  130. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.style.js.map +1 -1
  131. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue.d.ts.map +1 -1
  132. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js +7 -1
  133. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js.map +1 -1
  134. package/dist/components/PlBtnExportArchive/Summary.js.map +1 -1
  135. package/dist/components/PlBtnExportArchive/Summary.style.js.map +1 -1
  136. package/dist/components/PlBtnExportArchive/Summary.vue.d.ts.map +1 -1
  137. package/dist/components/PlBtnExportArchive/Summary.vue2.js +11 -2
  138. package/dist/components/PlBtnExportArchive/Summary.vue2.js.map +1 -1
  139. package/dist/components/PlDatasetSelector/PlDatasetSelector.js.map +1 -1
  140. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts.map +1 -1
  141. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js +1 -0
  142. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js.map +1 -1
  143. package/dist/components/PlTableFastSearch/PlTableFastSearch.js.map +1 -1
  144. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue.d.ts.map +1 -1
  145. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js +1 -0
  146. package/dist/components/PlTableFastSearch/PlTableFastSearch.vue2.js.map +1 -1
  147. package/dist/components/PlTableFilters/PlTableFiltersV2.js.map +1 -1
  148. package/dist/components/PlTableFilters/PlTableFiltersV2.style.js.map +1 -1
  149. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts.map +1 -1
  150. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +12 -2
  151. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
  152. package/package.json +5 -5
  153. package/src/components/BlockLayout.vue +4 -2
  154. package/src/components/BlockLoader.vue +2 -1
  155. package/src/components/LoaderPage.vue +1 -1
  156. package/src/components/NotFound.vue +7 -3
  157. package/src/components/PlAdvancedFilter/FilterEditor.vue +36 -6
  158. package/src/components/PlAdvancedFilter/OperandButton.vue +2 -1
  159. package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +20 -4
  160. package/src/components/PlAgCellFile/PlAgCellFile.vue +2 -1
  161. package/src/components/PlAgCellProgress/PlAgCellProgress.vue +1 -1
  162. package/src/components/PlAgCellStatusTag/PlAgCellStatusTag.vue +2 -2
  163. package/src/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue +13 -3
  164. package/src/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue +13 -3
  165. package/src/components/PlAgColumnHeader/PlAgColumnHeader.vue +24 -6
  166. package/src/components/PlAgCsvExporter/PlAgCsvExporter.vue +6 -1
  167. package/src/components/PlAgDataTable/PlAgDataTableSheets.vue +6 -1
  168. package/src/components/PlAgDataTable/PlAgDataTableV2.vue +2 -1
  169. package/src/components/PlAgDataTable/PlAgOverlayLoading.vue +10 -3
  170. package/src/components/PlAgDataTable/PlAgOverlayNoRows.vue +4 -2
  171. package/src/components/PlAgGridColumnManager/PlAgGridColumnManager.vue +18 -5
  172. package/src/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue +5 -1
  173. package/src/components/PlAgRowNumHeader.vue +3 -1
  174. package/src/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue +3 -2
  175. package/src/components/PlAnnotations/components/AnnotationsSidebar.vue +13 -4
  176. package/src/components/PlAnnotations/components/FilterSidebar.vue +11 -3
  177. package/src/components/PlAnnotations/components/PlAnnotations.vue +1 -1
  178. package/src/components/PlAnnotations/components/PlAnnotationsModal.vue +1 -0
  179. package/src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue +34 -7
  180. package/src/components/PlBtnExportArchive/Item.vue +22 -6
  181. package/src/components/PlBtnExportArchive/PlBtnExportArchive.vue +18 -3
  182. package/src/components/PlBtnExportArchive/Summary.vue +15 -5
  183. package/src/components/PlDatasetSelector/PlDatasetSelector.vue +1 -0
  184. package/src/components/PlTableFastSearch/PlTableFastSearch.vue +6 -1
  185. package/src/components/PlTableFilters/PlTableFiltersV2.vue +14 -4
@@ -1 +1 @@
1
- {"version":3,"file":"FilterSidebar.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div :class=\"$style.actions\">\n <PlBtnSecondary icon=\"add\" @click=\"addFilterPlaceholder\"> Add Filter </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"FilterSidebar.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\" data-testid=\"pl-annotations-step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n data-testid=\"pl-annotations-step-label\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div data-testid=\"pl-annotations-filter-actions\" :class=\"$style.actions\">\n <PlBtnSecondary\n data-testid=\"pl-annotations-add-filter\"\n icon=\"add\"\n @click=\"addFilterPlaceholder\"\n >\n Add Filter\n </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n data-testid=\"pl-annotations-add-from-selection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterSidebar.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div :class=\"$style.actions\">\n <PlBtnSecondary icon=\"add\" @click=\"addFilterPlaceholder\"> Add Filter </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"FilterSidebar.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\" data-testid=\"pl-annotations-step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n data-testid=\"pl-annotations-step-label\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div data-testid=\"pl-annotations-filter-actions\" :class=\"$style.actions\">\n <PlBtnSecondary\n data-testid=\"pl-annotations-add-filter\"\n icon=\"add\"\n @click=\"addFilterPlaceholder\"\n >\n Add Filter\n </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n data-testid=\"pl-annotations-add-from-selection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"FilterSidebar.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"names":[],"mappings":"AA8LA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAG3F,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EAGzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMvC,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAEhC,iBAAiB,EAAE,CAAC,MAAM,EAAE;QAC1B,QAAQ,EAAE,wBAAwB,CAAC;QACnC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;KAC/B,KAAK,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAErF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,OAAO,CACzC,SAAS,GAAG;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CACtD,CAAC;CACH,CAAC;wBACmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;UAER,MAAM;kBACE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;UAD9B,MAAM;kBACE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;iGA+QpC,CAAC"}
1
+ {"version":3,"file":"FilterSidebar.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"names":[],"mappings":"AAsMA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAuB,MAAM,sBAAsB,CAAC;AAG3F,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EAGzB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAMvC,MAAM,MAAM,KAAK,GAAG;IAClB,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAEhC,iBAAiB,EAAE,CAAC,MAAM,EAAE;QAC1B,QAAQ,EAAE,wBAAwB,CAAC;QACnC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC;KAC/B,KAAK,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IAErF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B,CAAC,EAAE,MAAM,OAAO,CACzC,SAAS,GAAG;QAAE,QAAQ,EAAE,SAAS,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CACtD,CAAC;CACH,CAAC;wBACmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;UAER,MAAM;kBACE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;;UAD9B,MAAM;kBACE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI;iGAwRpC,CAAC"}
@@ -83,9 +83,13 @@ var y = /* @__PURE__ */ d({
83
83
  "topN",
84
84
  "bottomN"
85
85
  ];
86
- return (e, i) => y.step ? (p(), o(m(v), { key: 0 }, {
86
+ return (e, i) => y.step ? (p(), o(m(v), {
87
+ key: 0,
88
+ "data-testid": "pl-annotations-step"
89
+ }, {
87
90
  "header-content": h(() => [(p(), o(m(_), {
88
91
  key: y.step.id,
92
+ "data-testid": "pl-annotations-step-label",
89
93
  "model-value": y.step.label,
90
94
  class: f({ [m(n).flashing]: y.step.label.length === 0 }),
91
95
  "max-length": 40,
@@ -110,7 +114,11 @@ var y = /* @__PURE__ */ d({
110
114
  "enable-dnd": !1,
111
115
  "enable-add-group-button": !0
112
116
  }, {
113
- "add-group-buttons": h(() => [c("div", { class: f(e.$style.actions) }, [u(m(g), {
117
+ "add-group-buttons": h(() => [c("div", {
118
+ "data-testid": "pl-annotations-filter-actions",
119
+ class: f(e.$style.actions)
120
+ }, [u(m(g), {
121
+ "data-testid": "pl-annotations-add-filter",
114
122
  icon: "add",
115
123
  onClick: w
116
124
  }, {
@@ -118,6 +126,7 @@ var y = /* @__PURE__ */ d({
118
126
  _: 1
119
127
  }), b.value ? (p(), o(m(g), {
120
128
  key: 0,
129
+ "data-testid": "pl-annotations-add-from-selection",
121
130
  icon: "add",
122
131
  disabled: y.hasSelectedColumns !== !0,
123
132
  onClick: T
@@ -1 +1 @@
1
- {"version":3,"file":"FilterSidebar.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div :class=\"$style.actions\">\n <PlBtnSecondary icon=\"add\" @click=\"addFilterPlaceholder\"> Add Filter </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAoCA,IAAM,IAAQ,GAOR,IAAgB,QACb,EAAM,uBAAuB,KAAA,KAAa,EAAM,gCAAgC,KAAA,EACvF;EAEF,SAAS,EAAkB,GAAkC;AAC3D,KAAM,aAAa,EAAQ,EAAM,MAAM,EAAQ,CAAC;;EAGlD,SAAS,EAAY,GAA2B;AAC9C,MAAmB,MAAU;AAC3B,MAAM,QAAQ,KAAS;KACvB;;EAGJ,SAAS,EAAa,GAA0B;AAC9C,MAAmB,MAAU;AAC3B,MAAM,SAAS;KACf;;EAGJ,SAAS,IAAuB;AAC1B,KAAM,QAAQ,WAAW,KAC7B,GAAmB,MAAU;AAC3B,MAAM,OAAO,QAAQ,KAAK;KACxB,IAAI,GAAW;KACf,YAAY;KACZ,MAAM;KACN,SAAS,CACP;MACE,IAAI,GAAW;MACf,MAAM;MACN,QAAQ,EAAM,QAAQ,GAAG;MAC1B,CACF;KACF,CAAC;KACF;;EAGJ,eAAe,IAAwB;AACrC,OAAI,EAAM,uBAAuB,KAAA,KAAa,EAAM,gCAAgC,KAAA,EAClF;GAEF,IAAM,IAAO,MAAM,EAAM,6BAA6B;AACtD,OAAI,CAAC,KAAQ,EAAK,OAAO,WAAW,EAAG;GAEvC,IAAM,EAAE,aAAU,cAAW,GACvB,IACJ,EAAO,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,IAAI,EAAO,SAAS,IAAI,QAAQ,EAAO,SAAS,EAAE,SAAS;AAE1F,MAAmB,MAAU;AAC3B,MAAM,OAAO,QAAQ,KAAK;KACxB,IAAI,GAAW;KACf,MAAM,kBAAkB,EAAc;KACtC,YAAY;KACZ,MAAM;KACN,SAAS,EAAO,KAAK,GAAO,OAAO;MACjC,IAAI;MACJ,MAAM;MACN,QAAQ;MACR;MACD,EAAE;KACJ,CAAC;KACF;;EAGJ,IAAM,IAAmB;GACvB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;mBAIsB,EAAM,QAAA,GAAA,EAA3B,EAwCgB,EAAA,EAAA,EAAA,EAAA,KAAA,GAAA,EAAA;GAvCH,kBAAc,QAWrB,EAAA,GAAA,EAVF,EAUE,EAAA,EAAA,EAAA;IATC,KAAK,EAAM,KAAK;IAChB,eAAa,EAAM,KAAK;IACxB,OAAK,EAAA,GAAK,EAAA,EAAY,CAAC,WAAW,EAAM,KAAK,MAAM,WAAM,GAAA,CAAA;IACzD,cAAY;IACb,aAAU;IACV,aAAY;IACX,WAAW,EAAM,KAAK,MAAM,WAAM;IAClC,UAAU,EAAA,EAAa;IACvB,uBAAoB;;;;;;;GAGd,gBAAY,QAwBO,CAvB5B,EAuB4B,EAAA,EAAA,EAAA;IAtBzB,OAAK,EAAA,CAAGA,EAAAA,OAAO,MAAI,GAAK,EAAA,EAAY,CAAC,WAAW,EAAM,KAAK,MAAM,WAAM,GAAA,CAAA,CAAA;IACvE,SAAS,EAAM;IACf,SAAS,EAAM,KAAK;IACpB,qBAAmB;IACnB,qBAAmB;IACnB,uBAAqB,EAAM;IAC3B,cAAY;IACZ,2BAAyB;;IAEf,qBAAiB,QAWpB,CAVN,EAUM,OAAA,EAVA,OAAK,EAAEA,EAAAA,OAAO,QAAO,EAAA,EAAA,CACzB,EAAsF,EAAA,EAAA,EAAA;KAAtE,MAAK;KAAO,SAAO;;sBAAkC,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAZ,gBAAY,GAAA,CAAA,CAAA,CAAA;;QAE7D,EAAA,SAAA,GAAA,EADR,EAOiB,EAAA,EAAA,EAAA;;KALf,MAAK;KACJ,UAAU,EAAM,uBAAkB;KAClC,SAAO;;sBAGV,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAFC,oBAED,GAAA,CAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"FilterSidebar.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/FilterSidebar.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type Props = {\n columns: PlAdvancedFilterItem[];\n\n getSuggestOptions: (params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;\n\n hasSelectedColumns?: boolean;\n getValuesForSelectedColumns?: () => Promise<\n undefined | { columnId: PObjectId; values: string[] }\n >;\n};\n</script>\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { produce } from \"immer\";\nimport { randomInt } from \"@milaboratories/helpers\";\nimport { PlBtnSecondary, PlEditableTitle, PlSidebarItem } from \"@milaboratories/uikit\";\nimport type { ListOptionBase, PObjectId, SUniversalPColumnId } from \"@platforma-sdk/model\";\n\nimport { PlAdvancedFilterComponent } from \"../../PlAdvancedFilter\";\nimport type {\n PlAdvancedFilterItem,\n PlAdvancedFilterColumnId,\n PlAdvancedFilterSupportedFilters,\n PlAdvancedFilter,\n} from \"../../PlAdvancedFilter\";\nimport type { Filter } from \"../types\";\nimport { validateTitle } from \"../utils\";\n\nimport $commonStyle from \"./style.module.css\";\n\nconst props = defineProps<\n Props & {\n step: Filter;\n onUpdateStep: (step: Filter) => void;\n }\n>();\n\nconst withSelection = computed(() => {\n return props.hasSelectedColumns !== undefined && props.getValuesForSelectedColumns !== undefined;\n});\n\nfunction produceStepUpdate(updater: (draft: Filter) => void) {\n props.onUpdateStep(produce(props.step, updater));\n}\n\nfunction updateLabel(label: string | undefined) {\n produceStepUpdate((draft) => {\n draft.label = label ?? \"\";\n });\n}\n\nfunction updateFilter(filter: PlAdvancedFilter) {\n produceStepUpdate((draft) => {\n draft.filter = filter as typeof draft.filter;\n });\n}\n\nfunction addFilterPlaceholder() {\n if (props.columns.length === 0) return;\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n isExpanded: true,\n type: \"or\",\n filters: [\n {\n id: randomInt(),\n type: \"isNA\",\n column: props.columns[0].id as SUniversalPColumnId,\n },\n ],\n });\n });\n}\n\nasync function addFilterFromSelected() {\n if (props.hasSelectedColumns === undefined || props.getValuesForSelectedColumns === undefined)\n return;\n\n const data = await props.getValuesForSelectedColumns();\n if (!data || data.values.length === 0) return;\n\n const { columnId, values } = data;\n const shortReminder =\n values.slice(0, 3).join(\", \") + (values.length > 3 ? ` and ${values.length - 3} more` : \"\");\n\n produceStepUpdate((draft) => {\n draft.filter.filters.push({\n id: randomInt(),\n name: `Selected list (${shortReminder})`,\n isExpanded: false,\n type: \"or\",\n filters: values.map((value, i) => ({\n id: i,\n type: \"patternEquals\",\n column: columnId as SUniversalPColumnId,\n value,\n })),\n });\n });\n}\n\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"equal\",\n \"notEqual\",\n \"topN\",\n \"bottomN\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n</script>\n\n<template>\n <PlSidebarItem v-if=\"props.step\" data-testid=\"pl-annotations-step\">\n <template #header-content>\n <PlEditableTitle\n :key=\"props.step.id\"\n data-testid=\"pl-annotations-step-label\"\n :model-value=\"props.step.label\"\n :class=\"{ [$commonStyle.flashing]: props.step.label.length === 0 }\"\n :max-length=\"40\"\n max-width=\"600px\"\n placeholder=\"Label\"\n :autofocus=\"props.step.label.length === 0\"\n :validate=\"validateTitle\"\n @update:model-value=\"updateLabel\"\n />\n </template>\n <template #body-content>\n <PlAdvancedFilterComponent\n :class=\"[$style.root, { [$commonStyle.disabled]: props.step.label.length === 0 }]\"\n :options=\"props.columns\"\n :filters=\"props.step.filter as PlAdvancedFilter\"\n :on-update-filters=\"updateFilter\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :enable-dnd=\"false\"\n :enable-add-group-button=\"true\"\n >\n <template #add-group-buttons>\n <div data-testid=\"pl-annotations-filter-actions\" :class=\"$style.actions\">\n <PlBtnSecondary\n data-testid=\"pl-annotations-add-filter\"\n icon=\"add\"\n @click=\"addFilterPlaceholder\"\n >\n Add Filter\n </PlBtnSecondary>\n <PlBtnSecondary\n v-if=\"withSelection\"\n data-testid=\"pl-annotations-add-from-selection\"\n icon=\"add\"\n :disabled=\"props.hasSelectedColumns !== true\"\n @click=\"addFilterFromSelected\"\n >\n From selection\n </PlBtnSecondary>\n </div>\n </template>\n </PlAdvancedFilterComponent>\n </template>\n </PlSidebarItem>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.actions {\n display: flex;\n flex-direction: row;\n gap: 12px;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAoCA,IAAM,IAAQ,GAOR,IAAgB,QACb,EAAM,uBAAuB,KAAA,KAAa,EAAM,gCAAgC,KAAA,EACvF;EAEF,SAAS,EAAkB,GAAkC;AAC3D,KAAM,aAAa,EAAQ,EAAM,MAAM,EAAQ,CAAC;;EAGlD,SAAS,EAAY,GAA2B;AAC9C,MAAmB,MAAU;AAC3B,MAAM,QAAQ,KAAS;KACvB;;EAGJ,SAAS,EAAa,GAA0B;AAC9C,MAAmB,MAAU;AAC3B,MAAM,SAAS;KACf;;EAGJ,SAAS,IAAuB;AAC1B,KAAM,QAAQ,WAAW,KAC7B,GAAmB,MAAU;AAC3B,MAAM,OAAO,QAAQ,KAAK;KACxB,IAAI,GAAW;KACf,YAAY;KACZ,MAAM;KACN,SAAS,CACP;MACE,IAAI,GAAW;MACf,MAAM;MACN,QAAQ,EAAM,QAAQ,GAAG;MAC1B,CACF;KACF,CAAC;KACF;;EAGJ,eAAe,IAAwB;AACrC,OAAI,EAAM,uBAAuB,KAAA,KAAa,EAAM,gCAAgC,KAAA,EAClF;GAEF,IAAM,IAAO,MAAM,EAAM,6BAA6B;AACtD,OAAI,CAAC,KAAQ,EAAK,OAAO,WAAW,EAAG;GAEvC,IAAM,EAAE,aAAU,cAAW,GACvB,IACJ,EAAO,MAAM,GAAG,EAAE,CAAC,KAAK,KAAK,IAAI,EAAO,SAAS,IAAI,QAAQ,EAAO,SAAS,EAAE,SAAS;AAE1F,MAAmB,MAAU;AAC3B,MAAM,OAAO,QAAQ,KAAK;KACxB,IAAI,GAAW;KACf,MAAM,kBAAkB,EAAc;KACtC,YAAY;KACZ,MAAM;KACN,SAAS,EAAO,KAAK,GAAO,OAAO;MACjC,IAAI;MACJ,MAAM;MACN,QAAQ;MACR;MACD,EAAE;KACJ,CAAC;KACF;;EAGJ,IAAM,IAAmB;GACvB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;mBAIsB,EAAM,QAAA,GAAA,EAA3B,EAgDgB,EAAA,EAAA,EAAA;;GAhDiB,eAAY;;GAChC,kBAAc,QAYrB,EAAA,GAAA,EAXF,EAWE,EAAA,EAAA,EAAA;IAVC,KAAK,EAAM,KAAK;IACjB,eAAY;IACX,eAAa,EAAM,KAAK;IACxB,OAAK,EAAA,GAAK,EAAA,EAAY,CAAC,WAAW,EAAM,KAAK,MAAM,WAAM,GAAA,CAAA;IACzD,cAAY;IACb,aAAU;IACV,aAAY;IACX,WAAW,EAAM,KAAK,MAAM,WAAM;IAClC,UAAU,EAAA,EAAa;IACvB,uBAAoB;;;;;;;GAGd,gBAAY,QA+BO,CA9B5B,EA8B4B,EAAA,EAAA,EAAA;IA7BzB,OAAK,EAAA,CAAGA,EAAAA,OAAO,MAAI,GAAK,EAAA,EAAY,CAAC,WAAW,EAAM,KAAK,MAAM,WAAM,GAAA,CAAA,CAAA;IACvE,SAAS,EAAM;IACf,SAAS,EAAM,KAAK;IACpB,qBAAmB;IACnB,qBAAmB;IACnB,uBAAqB,EAAM;IAC3B,cAAY;IACZ,2BAAyB;;IAEf,qBAAiB,QAkBpB,CAjBN,EAiBM,OAAA;KAjBD,eAAY;KAAiC,OAAK,EAAEA,EAAAA,OAAO,QAAO;QACrE,EAMiB,EAAA,EAAA,EAAA;KALf,eAAY;KACZ,MAAK;KACJ,SAAO;;sBAGV,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAFC,gBAED,GAAA,CAAA,CAAA,CAAA;;QAEQ,EAAA,SAAA,GAAA,EADR,EAQiB,EAAA,EAAA,EAAA;;KANf,eAAY;KACZ,MAAK;KACJ,UAAU,EAAM,uBAAkB;KAClC,SAAO;;sBAGV,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAFC,oBAED,GAAA,CAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotations.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAnnotations.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup data-testid=\"pl-annotations\">\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotations.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAnnotations.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup data-testid=\"pl-annotations\">\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotations.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"names":[],"mappings":"AA4GA,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,UAAU,CAAC;AAKnD,OAAO,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC9D,MAAM,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAAC,GAAG;IAC7D,UAAU,EAAE,UAAU,CAAC;IACvB,kBAAkB,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACrD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;wBACmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY,sRAuJd,CAAC"}
1
+ {"version":3,"file":"PlAnnotations.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"names":[],"mappings":"AA4GA,OAAO,KAAK,EAAE,UAAU,EAAU,MAAM,UAAU,CAAC;AAKnD,OAAO,KAAK,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC9D,MAAM,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,CAAC,GAAG;IAC7D,UAAU,EAAE,UAAU,CAAC;IACvB,kBAAkB,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACrD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,CAAC;wBACmB,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY,sRAyJd,CAAC"}
@@ -40,7 +40,7 @@ var _ = /* @__PURE__ */ c({
40
40
  n !== -1 && (t.steps[n] = e);
41
41
  }));
42
42
  }
43
- return (e, r) => (d(), a(p(h), null, {
43
+ return (e, r) => (d(), a(p(h), { "data-testid": "pl-annotations" }, {
44
44
  "item-0": m(() => [s(t, {
45
45
  annotation: _.annotation,
46
46
  "selected-step-id": v.value,
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup>\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAoBA,IAAM,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAE1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAM,WAAU,GACxD,KAAA,IACA,EAAM,WAAW,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAEF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAM,WAAW,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAM,WAAW,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;EAI5B,SAAS,EAAqB,GAAwB;AACpD,KAAe,QAAQ;;EAGzB,SAAS,EAAmB,GAAc;AACxC,KAAM,mBACJ,EAAQ,EAAM,aAAa,MAAU;IACnC,IAAM,IAAM,EAAM,MAAM,WAAW,MAAM,EAAE,OAAO,EAAK,GAAG;AAC1D,IAAI,MAAQ,OACV,EAAM,MAAM,KAAO;KAErB,CACH;;yBAKD,EAuBiB,EAAA,EAAA,EAAA,MAAA;GAtBJ,UAAM,QAQb,CAPF,EAOE,GAAA;IANC,YAAY,EAAM;IAClB,oBAAkB,EAAA;IAClB,wBAAsB,EAAM;IAC5B,8BAA4B;IAC5B,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,gBAAe;;;;;;;GAGT,UAAM,QAgBP,CAdA,EAAA,SAAA,GAAA,EADR,EASE,GAAA;;IAPC,MAAM,EAAA;IACN,kBAAgB;IAChB,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,uBAAqB,EAAM;IAC3B,oBAAoB,EAAM;IAC1B,6BAA6B,EAAM"}
1
+ {"version":3,"file":"PlAnnotations.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotations.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { Props as BaseProps } from \"./FilterSidebar.vue\";\nexport type Props = Omit<BaseProps, \"step\" | \"onUpdateStep\"> & {\n annotation: Annotation;\n onUpdateAnnotation: (annotation: Annotation) => void;\n onDeleteSchema?: () => void;\n};\n</script>\n\n<script setup lang=\"ts\">\nimport { computed, effect, shallowRef } from \"vue\";\n\nimport { isNil } from \"@milaboratories/helpers\";\nimport { produce } from \"immer\";\nimport { PlSidebarGroup, useConfirm } from \"@milaboratories/uikit\";\n\nimport type { Annotation, Filter } from \"../types\";\nimport AnnotationsSidebar from \"./AnnotationsSidebar.vue\";\nimport FilterSidebar from \"./FilterSidebar.vue\";\n\nconst props = defineProps<Props>();\n\nconst selectedStepId = shallowRef<undefined | number>(undefined);\n\nconst selectedStep = computed(() => {\n return isNil(selectedStepId.value) || isNil(props.annotation)\n ? undefined\n : props.annotation.steps.find((step) => step.id === selectedStepId.value);\n});\n\neffect(function setDefaultStepId() {\n if (selectedStepId.value === undefined && props.annotation.steps.length > 0) {\n selectedStepId.value = props.annotation.steps[0].id;\n }\n});\n\nconst confirmResetSchema = useConfirm({\n title: \"Reset Schema\",\n message: \"Are you sure you want to reset the schema? This action cannot be undone.\",\n confirmLabel: \"Yes, reset\",\n cancelLabel: \"No, cancel\",\n});\n\nasync function handleDeleteSchema() {\n if (await confirmResetSchema()) {\n selectedStepId.value = undefined;\n props.onDeleteSchema?.();\n }\n}\n\nfunction updateSelectedStepId(id: undefined | number) {\n selectedStepId.value = id;\n}\n\nfunction updateSelectedStep(step: Filter) {\n props.onUpdateAnnotation(\n produce(props.annotation, (draft) => {\n const idx = draft.steps.findIndex((s) => s.id === step.id);\n if (idx !== -1) {\n draft.steps[idx] = step;\n }\n }),\n );\n}\n</script>\n\n<template>\n <PlSidebarGroup data-testid=\"pl-annotations\">\n <template #item-0>\n <AnnotationsSidebar\n :annotation=\"props.annotation\"\n :selected-step-id=\"selectedStepId\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-update-selected-step-id=\"updateSelectedStepId\"\n :class=\"$style.sidebarItem\"\n @delete-schema=\"handleDeleteSchema\"\n />\n </template>\n <template #item-1>\n <FilterSidebar\n v-if=\"selectedStep\"\n :step=\"selectedStep\"\n :on-update-step=\"updateSelectedStep\"\n :class=\"$style.sidebarItem\"\n :columns=\"props.columns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :hasSelectedColumns=\"props.hasSelectedColumns\"\n :getValuesForSelectedColumns=\"props.getValuesForSelectedColumns\"\n />\n </template>\n </PlSidebarGroup>\n</template>\n\n<style module>\n.sidebarItem {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAoBA,IAAM,IAAQ,GAER,IAAiB,EAA+B,KAAA,EAAU,EAE1D,IAAe,QACZ,EAAM,EAAe,MAAM,IAAI,EAAM,EAAM,WAAU,GACxD,KAAA,IACA,EAAM,WAAW,MAAM,MAAM,MAAS,EAAK,OAAO,EAAe,MAAM,CAC3E;AAEF,IAAO,WAA4B;AACjC,GAAI,EAAe,UAAU,KAAA,KAAa,EAAM,WAAW,MAAM,SAAS,MACxE,EAAe,QAAQ,EAAM,WAAW,MAAM,GAAG;IAEnD;EAEF,IAAM,IAAqB,EAAW;GACpC,OAAO;GACP,SAAS;GACT,cAAc;GACd,aAAa;GACd,CAAC;EAEF,eAAe,IAAqB;AAClC,GAAI,MAAM,GAAoB,KAC5B,EAAe,QAAQ,KAAA,GACvB,EAAM,kBAAkB;;EAI5B,SAAS,EAAqB,GAAwB;AACpD,KAAe,QAAQ;;EAGzB,SAAS,EAAmB,GAAc;AACxC,KAAM,mBACJ,EAAQ,EAAM,aAAa,MAAU;IACnC,IAAM,IAAM,EAAM,MAAM,WAAW,MAAM,EAAE,OAAO,EAAK,GAAG;AAC1D,IAAI,MAAQ,OACV,EAAM,MAAM,KAAO;KAErB,CACH;;yBAKD,EAuBiB,EAAA,EAAA,EAAA,EAvBD,eAAY,kBAAgB,EAAA;GAC/B,UAAM,QAQb,CAPF,EAOE,GAAA;IANC,YAAY,EAAM;IAClB,oBAAkB,EAAA;IAClB,wBAAsB,EAAM;IAC5B,8BAA4B;IAC5B,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,gBAAe;;;;;;;GAGT,UAAM,QAUb,CARM,EAAA,SAAA,GAAA,EADR,EASE,GAAA;;IAPC,MAAM,EAAA;IACN,kBAAgB;IAChB,OAAK,EAAEA,EAAAA,OAAO,YAAW;IACzB,SAAS,EAAM;IACf,uBAAqB,EAAM;IAC3B,oBAAoB,EAAM;IAC1B,6BAA6B,EAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotationsModal.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAnnotationsModal.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n data-testid=\"pl-annotations-modal\"\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotationsModal.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAnnotationsModal.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n data-testid=\"pl-annotations-modal\"\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotationsModal.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"names":[],"mappings":"AAsDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,KAAK,WAAW,GAAG,KAAK,GAAG;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3C,CAAC;AAuFJ,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"PlAnnotationsModal.vue.d.ts","sourceRoot":"","sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"names":[],"mappings":"AAuDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD,KAAK,WAAW,GAAG,KAAK,GAAG;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3C,CAAC;AAyFJ,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -21,6 +21,7 @@ var l = /* @__PURE__ */ r({
21
21
  l.onUpdateOpened(!1), l.onDeleteSchema?.();
22
22
  }
23
23
  return (r, d) => (a(), t(o(c), {
24
+ "data-testid": "pl-annotations-modal",
24
25
  "model-value": l.opened,
25
26
  class: i(r.$style.modal),
26
27
  width: "768px",
@@ -1 +1 @@
1
- {"version":3,"file":"PlAnnotationsModal.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAMA,IAAM,IAAQ;EAOd,eAAe,IAAqB;AAElC,GADA,EAAM,eAAe,GAAM,EAC3B,EAAM,kBAAkB;;yBAKxB,EAgBmB,EAAA,EAAA,EAAA;GAfhB,eAAa,EAAM;GACnB,OAAK,EAAEA,EAAAA,OAAO,MAAK;GACpB,OAAM;GACL,uBAAoB,EAAM;;oBAWzB,CATF,EASE,GAAA;IARC,OAAK,EAAEA,EAAAA,OAAO,QAAO;IACrB,SAAS,EAAM;IACf,YAAY,EAAM;IAClB,wBAAsB,EAAM;IAC5B,oBAAkB;IAClB,wBAAsB,EAAM;IAC5B,uBAAqB,EAAM;IAC3B,mCAAiC,EAAM"}
1
+ {"version":3,"file":"PlAnnotationsModal.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../../src/components/PlAnnotations/components/PlAnnotationsModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlPureSlideModal } from \"@milaboratories/uikit\";\n\nimport type { Props } from \"./PlAnnotations.vue\";\nimport PlAnnotations from \"./PlAnnotations.vue\";\n\nconst props = defineProps<\n Props & {\n opened: boolean;\n onUpdateOpened: (opened: boolean) => void;\n }\n>();\n\nasync function handleDeleteSchema() {\n props.onUpdateOpened(false);\n props.onDeleteSchema?.();\n}\n</script>\n\n<template>\n <PlPureSlideModal\n data-testid=\"pl-annotations-modal\"\n :model-value=\"props.opened\"\n :class=\"$style.modal\"\n width=\"768px\"\n @update:model-value=\"props.onUpdateOpened\"\n >\n <PlAnnotations\n :class=\"$style.content\"\n :columns=\"props.columns\"\n :annotation=\"props.annotation\"\n :on-update-annotation=\"props.onUpdateAnnotation\"\n :on-delete-schema=\"handleDeleteSchema\"\n :has-selected-columns=\"props.hasSelectedColumns\"\n :get-suggest-options=\"props.getSuggestOptions\"\n :get-values-for-selected-columns=\"props.getValuesForSelectedColumns\"\n />\n </PlPureSlideModal>\n</template>\n\n<style module>\n.modal {\n display: flex;\n}\n\n.content {\n width: 100%;\n height: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAMA,IAAM,IAAQ;EAOd,eAAe,IAAqB;AAElC,GADA,EAAM,eAAe,GAAM,EAC3B,EAAM,kBAAkB;;yBAKxB,EAiBmB,EAAA,EAAA,EAAA;GAhBjB,eAAY;GACX,eAAa,EAAM;GACnB,OAAK,EAAEA,EAAAA,OAAO,MAAK;GACpB,OAAM;GACL,uBAAoB,EAAM;;oBAWzB,CATF,EASE,GAAA;IARC,OAAK,EAAEA,EAAAA,OAAO,QAAO;IACrB,SAAS,EAAM;IACf,YAAY,EAAM;IAClB,wBAAsB,EAAM;IAC5B,oBAAkB;IAClB,wBAAsB,EAAM;IAC5B,uBAAqB,EAAM;IAC3B,mCAAiC,EAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAppErrorNotificationAlert.js","names":[],"sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BlockOutputsBase } from \"@platforma-sdk/model\";\nimport type { OutputErrors } from \"../../types\";\n// @TODO module\nimport \"./pl-app-error-notification-alert.scss\";\nimport {\n PlBtnPrimary,\n PlDialogModal,\n PlNotificationAlert,\n PlSpacer,\n PlLogView,\n} from \"@milaboratories/uikit\";\nimport { computed, ref, watch } from \"vue\";\n\nexport type FullMessage = { fullMessage: string };\n\nconst props = defineProps<{ errors: OutputErrors<BlockOutputsBase> }>();\n\nconst isModalOpen = ref(false);\n\nconst isAlertOpen = ref(true);\n\nconst existingErrors = computed(() => Object.entries(props.errors).filter((item) => !!item[1]));\n\nfunction showErrors() {\n isModalOpen.value = true;\n}\n\n// @TODO (temp)\nwatch(\n () => props.errors,\n (errors) => {\n isAlertOpen.value = Object.values(errors).some((v) => !!v);\n },\n { immediate: true, deep: true },\n);\n</script>\n<template>\n <div class=\"pl-app-notification-alert\">\n <PlDialogModal v-model=\"isModalOpen\" width=\"720px\" style=\"max-height: 100vh\">\n <template #title> Errors </template>\n <div class=\"pl-app-notification-alert__content\">\n <template v-for=\"item in existingErrors\" :key=\"item[0]\">\n <div class=\"pl-app-notification-alert__item\">\n <div class=\"pl-app-notification-alert__title\">Block output: {{ item[0] }}</div>\n <PlLogView\n :value=\"item[1]?.message\"\n :valueToCopy=\"\n 'fullMessage' in (item[1] ?? {})\n ? (item[1] as unknown as FullMessage).fullMessage\n : item[1]?.message\n \"\n :download-filename=\"`output-${item[0]}-error.txt`\"\n />\n </div>\n </template>\n </div>\n </PlDialogModal>\n\n <PlNotificationAlert v-model=\"isAlertOpen\" type=\"error\" closable>\n Some outputs have errors.\n <template #actions>\n <PlBtnPrimary icon=\"arrow-right\" @click=\"showErrors\">See errors</PlBtnPrimary>\n <PlSpacer />\n </template>\n </PlNotificationAlert>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"PlAppErrorNotificationAlert.js","names":[],"sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BlockOutputsBase } from \"@platforma-sdk/model\";\nimport type { OutputErrors } from \"../../types\";\n// @TODO module\nimport \"./pl-app-error-notification-alert.scss\";\nimport {\n PlBtnPrimary,\n PlDialogModal,\n PlNotificationAlert,\n PlSpacer,\n PlLogView,\n} from \"@milaboratories/uikit\";\nimport { computed, ref, watch } from \"vue\";\n\nexport type FullMessage = { fullMessage: string };\n\nconst props = defineProps<{ errors: OutputErrors<BlockOutputsBase> }>();\n\nconst isModalOpen = ref(false);\n\nconst isAlertOpen = ref(true);\n\nconst existingErrors = computed(() => Object.entries(props.errors).filter((item) => !!item[1]));\n\nfunction showErrors() {\n isModalOpen.value = true;\n}\n\n// @TODO (temp)\nwatch(\n () => props.errors,\n (errors) => {\n isAlertOpen.value = Object.values(errors).some((v) => !!v);\n },\n { immediate: true, deep: true },\n);\n</script>\n<template>\n <div data-testid=\"pl-app-error-notification-alert\" class=\"pl-app-notification-alert\">\n <PlDialogModal\n v-model=\"isModalOpen\"\n data-testid=\"pl-app-error-notification-alert-modal\"\n width=\"720px\"\n style=\"max-height: 100vh\"\n >\n <template #title> Errors </template>\n <div\n data-testid=\"pl-app-error-notification-alert-content\"\n class=\"pl-app-notification-alert__content\"\n >\n <template v-for=\"item in existingErrors\" :key=\"item[0]\">\n <div\n data-testid=\"pl-app-error-notification-alert-item\"\n class=\"pl-app-notification-alert__item\"\n >\n <div\n data-testid=\"pl-app-error-notification-alert-item-title\"\n class=\"pl-app-notification-alert__title\"\n >\n Block output: {{ item[0] }}\n </div>\n <PlLogView\n data-testid=\"pl-app-error-notification-alert-log\"\n :value=\"item[1]?.message\"\n :valueToCopy=\"\n 'fullMessage' in (item[1] ?? {})\n ? (item[1] as unknown as FullMessage).fullMessage\n : item[1]?.message\n \"\n :download-filename=\"`output-${item[0]}-error.txt`\"\n />\n </div>\n </template>\n </div>\n </PlDialogModal>\n\n <PlNotificationAlert\n v-model=\"isAlertOpen\"\n data-testid=\"pl-app-error-notification-alert-message\"\n type=\"error\"\n closable\n >\n Some outputs have errors.\n <template #actions>\n <PlBtnPrimary\n data-testid=\"pl-app-error-notification-alert-show-errors\"\n icon=\"arrow-right\"\n @click=\"showErrors\"\n >See errors</PlBtnPrimary\n >\n <PlSpacer />\n </template>\n </PlNotificationAlert>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlAppErrorNotificationAlert.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"names":[],"mappings":"AAuEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,wCAAwC,CAAC;AAUhD,MAAM,MAAM,WAAW,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAA;CAAE,CAAC;AA6K9D,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"PlAppErrorNotificationAlert.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"names":[],"mappings":"AAkGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,wCAAwC,CAAC;AAUhD,MAAM,MAAM,WAAW,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,KAAK,WAAW,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC,gBAAgB,CAAC,CAAA;CAAE,CAAC;AAyL9D,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -2,7 +2,16 @@ import './pl-app-error-notification-alert.css';/* empty css
2
2
  import { Fragment as e, computed as t, createElementBlock as n, createElementVNode as r, createTextVNode as i, createVNode as a, defineComponent as o, openBlock as s, ref as c, renderList as l, toDisplayString as u, unref as d, watch as f, withCtx as p } from "vue";
3
3
  import { PlBtnPrimary as m, PlDialogModal as h, PlLogView as g, PlNotificationAlert as _, PlSpacer as v } from "@milaboratories/uikit";
4
4
  //#region src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue?vue&type=script&setup=true&lang.ts
5
- var y = { class: "pl-app-notification-alert" }, b = { class: "pl-app-notification-alert__content" }, x = { class: "pl-app-notification-alert__title" }, S = /* @__PURE__ */ o({
5
+ var y = {
6
+ "data-testid": "pl-app-error-notification-alert",
7
+ class: "pl-app-notification-alert"
8
+ }, b = {
9
+ "data-testid": "pl-app-error-notification-alert-content",
10
+ class: "pl-app-notification-alert__content"
11
+ }, x = {
12
+ "data-testid": "pl-app-error-notification-alert-item-title",
13
+ class: "pl-app-notification-alert__title"
14
+ }, S = /* @__PURE__ */ o({
6
15
  __name: "PlAppErrorNotificationAlert",
7
16
  props: { errors: {} },
8
17
  setup(o) {
@@ -18,14 +27,17 @@ var y = { class: "pl-app-notification-alert" }, b = { class: "pl-app-notificatio
18
27
  }), (t, o) => (s(), n("div", y, [a(d(h), {
19
28
  modelValue: C.value,
20
29
  "onUpdate:modelValue": o[0] ||= (e) => C.value = e,
30
+ "data-testid": "pl-app-error-notification-alert-modal",
21
31
  width: "720px",
22
32
  style: { "max-height": "100vh" }
23
33
  }, {
24
34
  title: p(() => [...o[2] ||= [i(" Errors ", -1)]]),
25
35
  default: p(() => [r("div", b, [(s(!0), n(e, null, l(T.value, (e) => (s(), n("div", {
26
36
  key: e[0],
37
+ "data-testid": "pl-app-error-notification-alert-item",
27
38
  class: "pl-app-notification-alert__item"
28
- }, [r("div", x, "Block output: " + u(e[0]), 1), a(d(g), {
39
+ }, [r("div", x, " Block output: " + u(e[0]), 1), a(d(g), {
40
+ "data-testid": "pl-app-error-notification-alert-log",
29
41
  value: e[1]?.message,
30
42
  valueToCopy: "fullMessage" in (e[1] ?? {}) ? e[1].fullMessage : e[1]?.message,
31
43
  "download-filename": `output-${e[0]}-error.txt`
@@ -38,10 +50,12 @@ var y = { class: "pl-app-notification-alert" }, b = { class: "pl-app-notificatio
38
50
  }, 8, ["modelValue"]), a(d(_), {
39
51
  modelValue: w.value,
40
52
  "onUpdate:modelValue": o[1] ||= (e) => w.value = e,
53
+ "data-testid": "pl-app-error-notification-alert-message",
41
54
  type: "error",
42
55
  closable: ""
43
56
  }, {
44
57
  actions: p(() => [a(d(m), {
58
+ "data-testid": "pl-app-error-notification-alert-show-errors",
45
59
  icon: "arrow-right",
46
60
  onClick: E
47
61
  }, {
@@ -1 +1 @@
1
- {"version":3,"file":"PlAppErrorNotificationAlert.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BlockOutputsBase } from \"@platforma-sdk/model\";\nimport type { OutputErrors } from \"../../types\";\n// @TODO module\nimport \"./pl-app-error-notification-alert.scss\";\nimport {\n PlBtnPrimary,\n PlDialogModal,\n PlNotificationAlert,\n PlSpacer,\n PlLogView,\n} from \"@milaboratories/uikit\";\nimport { computed, ref, watch } from \"vue\";\n\nexport type FullMessage = { fullMessage: string };\n\nconst props = defineProps<{ errors: OutputErrors<BlockOutputsBase> }>();\n\nconst isModalOpen = ref(false);\n\nconst isAlertOpen = ref(true);\n\nconst existingErrors = computed(() => Object.entries(props.errors).filter((item) => !!item[1]));\n\nfunction showErrors() {\n isModalOpen.value = true;\n}\n\n// @TODO (temp)\nwatch(\n () => props.errors,\n (errors) => {\n isAlertOpen.value = Object.values(errors).some((v) => !!v);\n },\n { immediate: true, deep: true },\n);\n</script>\n<template>\n <div class=\"pl-app-notification-alert\">\n <PlDialogModal v-model=\"isModalOpen\" width=\"720px\" style=\"max-height: 100vh\">\n <template #title> Errors </template>\n <div class=\"pl-app-notification-alert__content\">\n <template v-for=\"item in existingErrors\" :key=\"item[0]\">\n <div class=\"pl-app-notification-alert__item\">\n <div class=\"pl-app-notification-alert__title\">Block output: {{ item[0] }}</div>\n <PlLogView\n :value=\"item[1]?.message\"\n :valueToCopy=\"\n 'fullMessage' in (item[1] ?? {})\n ? (item[1] as unknown as FullMessage).fullMessage\n : item[1]?.message\n \"\n :download-filename=\"`output-${item[0]}-error.txt`\"\n />\n </div>\n </template>\n </div>\n </PlDialogModal>\n\n <PlNotificationAlert v-model=\"isAlertOpen\" type=\"error\" closable>\n Some outputs have errors.\n <template #actions>\n <PlBtnPrimary icon=\"arrow-right\" @click=\"showErrors\">See errors</PlBtnPrimary>\n <PlSpacer />\n </template>\n </PlNotificationAlert>\n </div>\n</template>\n"],"mappings":";;;;;;;;EAgBA,IAAM,IAAQ,GAER,IAAc,EAAI,GAAM,EAExB,IAAc,EAAI,GAAK,EAEvB,IAAiB,QAAe,OAAO,QAAQ,EAAM,OAAO,CAAC,QAAQ,MAAS,CAAC,CAAC,EAAK,GAAG,CAAC;EAE/F,SAAS,IAAa;AACpB,KAAY,QAAQ;;SAItB,QACQ,EAAM,SACX,MAAW;AACV,KAAY,QAAQ,OAAO,OAAO,EAAO,CAAC,MAAM,MAAM,CAAC,CAAC,EAAE;KAE5D;GAAE,WAAW;GAAM,MAAM;GAAM,CAChC,kBAGC,EA4BM,OA5BN,GA4BM,CA3BJ,EAkBgB,EAAA,EAAA,EAAA;eAlBQ,EAAA;4CAAW,QAAA;GAAE,OAAM;GAAQ,OAAA,EAAA,cAAA,SAAyB;;GAC/D,OAAK,QAAS,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAR,YAAQ,GAAA,CAAA,CAAA,CAAA;oBAgBnB,CAfN,EAeM,OAfN,GAeM,EAAA,EAAA,GAAA,EAdJ,EAaW,GAAA,MAAA,EAbc,EAAA,QAAR,YACf,EAWM,OAAA;SAZuC,EAAI;IAC5C,OAAM;OACT,EAA+E,OAA/E,GAA8C,mBAAc,EAAG,EAAI,GAAA,EAAA,EAAA,EACnE,EAQE,EAAA,EAAA,EAAA;IAPC,OAAO,EAAI,IAAK;IAChB,aAAA,kBAAgD,EAAI,MAAA,EAAA,IAAgC,EAAI,GAA+B,cAAgC,EAAI,IAAK;IAKhK,qBAAiB,UAAY,EAAI,GAAA;;;;;;;yBAO5C,EAMsB,EAAA,EAAA,EAAA;eANQ,EAAA;4CAAW,QAAA;GAAE,MAAK;GAAQ,UAAA;;GAE3C,SAAO,QAC8D,CAA9E,EAA8E,EAAA,EAAA,EAAA;IAAhE,MAAK;IAAe,SAAO;;qBAAsB,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAV,cAAU,GAAA,CAAA,CAAA,CAAA;;OAC/D,EAAY,EAAA,EAAA,CAAA,CAAA,CAAA;oBAFd,CAAA,AAAA,EAAA,OAAA,EAF+D,+BAE/D,GAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"PlAppErrorNotificationAlert.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { BlockOutputsBase } from \"@platforma-sdk/model\";\nimport type { OutputErrors } from \"../../types\";\n// @TODO module\nimport \"./pl-app-error-notification-alert.scss\";\nimport {\n PlBtnPrimary,\n PlDialogModal,\n PlNotificationAlert,\n PlSpacer,\n PlLogView,\n} from \"@milaboratories/uikit\";\nimport { computed, ref, watch } from \"vue\";\n\nexport type FullMessage = { fullMessage: string };\n\nconst props = defineProps<{ errors: OutputErrors<BlockOutputsBase> }>();\n\nconst isModalOpen = ref(false);\n\nconst isAlertOpen = ref(true);\n\nconst existingErrors = computed(() => Object.entries(props.errors).filter((item) => !!item[1]));\n\nfunction showErrors() {\n isModalOpen.value = true;\n}\n\n// @TODO (temp)\nwatch(\n () => props.errors,\n (errors) => {\n isAlertOpen.value = Object.values(errors).some((v) => !!v);\n },\n { immediate: true, deep: true },\n);\n</script>\n<template>\n <div data-testid=\"pl-app-error-notification-alert\" class=\"pl-app-notification-alert\">\n <PlDialogModal\n v-model=\"isModalOpen\"\n data-testid=\"pl-app-error-notification-alert-modal\"\n width=\"720px\"\n style=\"max-height: 100vh\"\n >\n <template #title> Errors </template>\n <div\n data-testid=\"pl-app-error-notification-alert-content\"\n class=\"pl-app-notification-alert__content\"\n >\n <template v-for=\"item in existingErrors\" :key=\"item[0]\">\n <div\n data-testid=\"pl-app-error-notification-alert-item\"\n class=\"pl-app-notification-alert__item\"\n >\n <div\n data-testid=\"pl-app-error-notification-alert-item-title\"\n class=\"pl-app-notification-alert__title\"\n >\n Block output: {{ item[0] }}\n </div>\n <PlLogView\n data-testid=\"pl-app-error-notification-alert-log\"\n :value=\"item[1]?.message\"\n :valueToCopy=\"\n 'fullMessage' in (item[1] ?? {})\n ? (item[1] as unknown as FullMessage).fullMessage\n : item[1]?.message\n \"\n :download-filename=\"`output-${item[0]}-error.txt`\"\n />\n </div>\n </template>\n </div>\n </PlDialogModal>\n\n <PlNotificationAlert\n v-model=\"isAlertOpen\"\n data-testid=\"pl-app-error-notification-alert-message\"\n type=\"error\"\n closable\n >\n Some outputs have errors.\n <template #actions>\n <PlBtnPrimary\n data-testid=\"pl-app-error-notification-alert-show-errors\"\n icon=\"arrow-right\"\n @click=\"showErrors\"\n >See errors</PlBtnPrimary\n >\n <PlSpacer />\n </template>\n </PlNotificationAlert>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;EAgBA,IAAM,IAAQ,GAER,IAAc,EAAI,GAAM,EAExB,IAAc,EAAI,GAAK,EAEvB,IAAiB,QAAe,OAAO,QAAQ,EAAM,OAAO,CAAC,QAAQ,MAAS,CAAC,CAAC,EAAK,GAAG,CAAC;EAE/F,SAAS,IAAa;AACpB,KAAY,QAAQ;;SAItB,QACQ,EAAM,SACX,MAAW;AACV,KAAY,QAAQ,OAAO,OAAO,EAAO,CAAC,MAAM,MAAM,CAAC,CAAC,EAAE;KAE5D;GAAE,WAAW;GAAM,MAAM;GAAM,CAChC,kBAGC,EAuDM,OAvDN,GAuDM,CAtDJ,EAmCgB,EAAA,EAAA,EAAA;eAlCL,EAAA;4CAAW,QAAA;GACpB,eAAY;GACZ,OAAM;GACN,OAAA,EAAA,cAAA,SAAyB;;GAEd,OAAK,QAAS,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAR,YAAQ,GAAA,CAAA,CAAA,CAAA;oBA4BnB,CA3BN,EA2BM,OA3BN,GA2BM,EAAA,EAAA,GAAA,EAvBJ,EAsBW,GAAA,MAAA,EAtBc,EAAA,QAAR,YACf,EAoBM,OAAA;SArBuC,EAAI;IAE/C,eAAY;IACZ,OAAM;OAEN,EAKM,OALN,GAGC,oBACe,EAAG,EAAI,GAAA,EAAA,EAAA,EAEvB,EASE,EAAA,EAAA,EAAA;IARA,eAAY;IACX,OAAO,EAAI,IAAK;IAChB,aAAA,kBAAgD,EAAI,MAAA,EAAA,IAAgC,EAAI,GAA+B,cAAgC,EAAI,IAAK;IAKhK,qBAAiB,UAAY,EAAI,GAAA;;;;;;;yBAO5C,EAgBsB,EAAA,EAAA,EAAA;eAfX,EAAA;4CAAW,QAAA;GACpB,eAAY;GACZ,MAAK;GACL,UAAA;;GAGW,SAAO,QAMf,CALD,EAKC,EAAA,EAAA,EAAA;IAJC,eAAY;IACZ,MAAK;IACJ,SAAO;;qBACG,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAV,cAAU,GAAA,CAAA,CAAA,CAAA;;OAEb,EAAY,EAAA,EAAA,CAAA,CAAA,CAAA;oBAPd,CAAA,AAAA,EAAA,OAAA,EAFD,+BAEC,GAAA,CAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Item.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div :class=\"$style.item\">\n <div :class=\"$style.name\">{{ item.fileName }}</div>\n <div v-if=\"item.status === 'in-progress'\" :class=\"$style.details\">\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'completed'\" :class=\"$style.details\">\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'error'\" :class=\"$style.error\">\n <span>{{ item.error }}</span>\n </div>\n <div v-else :class=\"$style.details\">Pending</div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"Item.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div data-testid=\"pl-btn-export-archive-item\" :class=\"$style.item\">\n <div data-testid=\"pl-btn-export-archive-item-name\" :class=\"$style.name\">\n {{ item.fileName }}\n </div>\n <div\n v-if=\"item.status === 'in-progress'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'completed'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'error'\"\n data-testid=\"pl-btn-export-archive-item-error\"\n :class=\"$style.error\"\n >\n <span>{{ item.error }}</span>\n </div>\n <div v-else data-testid=\"pl-btn-export-archive-item-status\" :class=\"$style.details\">\n Pending\n </div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Item.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div :class=\"$style.item\">\n <div :class=\"$style.name\">{{ item.fileName }}</div>\n <div v-if=\"item.status === 'in-progress'\" :class=\"$style.details\">\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'completed'\" :class=\"$style.details\">\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'error'\" :class=\"$style.error\">\n <span>{{ item.error }}</span>\n </div>\n <div v-else :class=\"$style.details\">Pending</div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"Item.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div data-testid=\"pl-btn-export-archive-item\" :class=\"$style.item\">\n <div data-testid=\"pl-btn-export-archive-item-name\" :class=\"$style.name\">\n {{ item.fileName }}\n </div>\n <div\n v-if=\"item.status === 'in-progress'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'completed'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'error'\"\n data-testid=\"pl-btn-export-archive-item-error\"\n :class=\"$style.error\"\n >\n <span>{{ item.error }}</span>\n </div>\n <div v-else data-testid=\"pl-btn-export-archive-item-status\" :class=\"$style.details\">\n Pending\n </div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"Item.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"names":[],"mappings":"AAiEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAyEF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
1
+ {"version":3,"file":"Item.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"names":[],"mappings":"AAiFA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AA+EF,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
@@ -6,8 +6,15 @@ var l = /* @__PURE__ */ i({
6
6
  __name: "Item",
7
7
  props: { item: {} },
8
8
  setup(i) {
9
- return (l, u) => (o(), t("div", { class: a(l.$style.item) }, [n("div", { class: a(l.$style.name) }, s(i.item.fileName), 3), i.item.status === "in-progress" ? (o(), t("div", {
9
+ return (l, u) => (o(), t("div", {
10
+ "data-testid": "pl-btn-export-archive-item",
11
+ class: a(l.$style.item)
12
+ }, [n("div", {
13
+ "data-testid": "pl-btn-export-archive-item-name",
14
+ class: a(l.$style.name)
15
+ }, s(i.item.fileName), 3), i.item.status === "in-progress" ? (o(), t("div", {
10
16
  key: 0,
17
+ "data-testid": "pl-btn-export-archive-item-status",
11
18
  class: a(l.$style.details)
12
19
  }, [
13
20
  n("span", null, s(c(e)(i.item.current, {})), 1),
@@ -15,14 +22,17 @@ var l = /* @__PURE__ */ i({
15
22
  n("span", null, s(c(e)(i.item.size, {})), 1)
16
23
  ], 2)) : i.item.status === "completed" ? (o(), t("div", {
17
24
  key: 1,
25
+ "data-testid": "pl-btn-export-archive-item-status",
18
26
  class: a(l.$style.details)
19
27
  }, [u[1] ||= r(" Done ", -1), n("span", null, s(c(e)(i.item.size, {})), 1)], 2)) : i.item.status === "error" ? (o(), t("div", {
20
28
  key: 2,
29
+ "data-testid": "pl-btn-export-archive-item-error",
21
30
  class: a(l.$style.error)
22
31
  }, [n("span", null, s(i.item.error), 1)], 2)) : (o(), t("div", {
23
32
  key: 3,
33
+ "data-testid": "pl-btn-export-archive-item-status",
24
34
  class: a(l.$style.details)
25
- }, "Pending", 2))], 2));
35
+ }, " Pending ", 2))], 2));
26
36
  }
27
37
  });
28
38
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Item.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div :class=\"$style.item\">\n <div :class=\"$style.name\">{{ item.fileName }}</div>\n <div v-if=\"item.status === 'in-progress'\" :class=\"$style.details\">\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'completed'\" :class=\"$style.details\">\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div v-else-if=\"item.status === 'error'\" :class=\"$style.error\">\n <span>{{ item.error }}</span>\n </div>\n <div v-else :class=\"$style.details\">Pending</div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":";;;;;;;;yBAUE,EAcM,OAAA,EAdA,OAAK,EAAEA,EAAAA,OAAO,KAAI,EAAA,EAAA,CACtB,EAAmD,OAAA,EAA7C,OAAK,EAAEA,EAAAA,OAAO,KAAI,EAAA,EAAA,EAAK,EAAA,KAAK,SAAQ,EAAA,EAAA,EAC/B,EAAA,KAAK,WAAM,iBAAA,GAAA,EAAtB,EAIM,OAAA;;GAJqC,OAAK,EAAEA,EAAAA,OAAO,QAAO;;GAC9D,EAAgD,QAAA,MAAA,EAAvC,EAAA,EAAW,CAAC,EAAA,KAAK,SAAO,EAAA,CAAA,CAAA,EAAA,EAAA;YACjC,EAAc,QAAA,MAAR,KAAC,GAAA;GACP,EAA6C,QAAA,MAAA,EAApC,EAAA,EAAW,CAAC,EAAA,KAAK,MAAI,EAAA,CAAA,CAAA,EAAA,EAAA;WAEhB,EAAA,KAAK,WAAM,eAAA,GAAA,EAA3B,EAEM,OAAA;;GAFwC,OAAK,EAAEA,EAAAA,OAAO,QAAO;iBAAE,UAC9D,GAAA,EAAA,EAA6C,QAAA,MAAA,EAApC,EAAA,EAAW,CAAC,EAAA,KAAK,MAAI,EAAA,CAAA,CAAA,EAAA,EAAA,CAAA,EAAA,EAAA,IAErB,EAAA,KAAK,WAAM,WAAA,GAAA,EAA3B,EAEM,OAAA;;GAFoC,OAAK,EAAEA,EAAAA,OAAO,MAAK;MAC3D,EAA6B,QAAA,MAAA,EAApB,EAAA,KAAK,MAAK,EAAA,EAAA,CAAA,EAAA,EAAA,KAAA,GAAA,EAErB,EAAiD,OAAA;;GAApC,OAAK,EAAEA,EAAAA,OAAO,QAAO;KAAE,WAAO,EAAA,EAAA,EAAA,EAAA"}
1
+ {"version":3,"file":"Item.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlBtnExportArchive/Item.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ExportItem } from \"./types\";\nimport { prettyBytes } from \"@milaboratories/helpers\";\n\ndefineProps<{\n item: ExportItem;\n}>();\n</script>\n\n<template>\n <div data-testid=\"pl-btn-export-archive-item\" :class=\"$style.item\">\n <div data-testid=\"pl-btn-export-archive-item-name\" :class=\"$style.name\">\n {{ item.fileName }}\n </div>\n <div\n v-if=\"item.status === 'in-progress'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n <span>{{ prettyBytes(item.current, {}) }}</span>\n <span>/</span>\n <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'completed'\"\n data-testid=\"pl-btn-export-archive-item-status\"\n :class=\"$style.details\"\n >\n Done <span>{{ prettyBytes(item.size, {}) }}</span>\n </div>\n <div\n v-else-if=\"item.status === 'error'\"\n data-testid=\"pl-btn-export-archive-item-error\"\n :class=\"$style.error\"\n >\n <span>{{ item.error }}</span>\n </div>\n <div v-else data-testid=\"pl-btn-export-archive-item-status\" :class=\"$style.details\">\n Pending\n </div>\n </div>\n</template>\n\n<style module>\n.item {\n display: flex;\n flex-direction: column;\n margin-bottom: 8px;\n overflow: hidden;\n --name-font-size: 12px;\n --details-font-size: 10px;\n}\n.name {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-size: var(--name-font-size);\n font-weight: 600;\n}\n\n.details {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: rgba(255, 255, 255, 0.6);\n}\n\n.error {\n font-size: var(--details-font-size);\n font-weight: 400;\n color: var(--txt-error);\n span {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 100%;\n }\n}\n</style>\n"],"mappings":";;;;;;;;yBAUE,EA8BM,OAAA;GA9BD,eAAY;GAA8B,OAAK,EAAEA,EAAAA,OAAO,KAAI;MAC/D,EAEM,OAAA;GAFD,eAAY;GAAmC,OAAK,EAAEA,EAAAA,OAAO,KAAI;OACjE,EAAA,KAAK,SAAQ,EAAA,EAAA,EAGV,EAAA,KAAK,WAAM,iBAAA,GAAA,EADnB,EAQM,OAAA;;GANJ,eAAY;GACX,OAAK,EAAEA,EAAAA,OAAO,QAAO;;GAEtB,EAAgD,QAAA,MAAA,EAAvC,EAAA,EAAW,CAAC,EAAA,KAAK,SAAO,EAAA,CAAA,CAAA,EAAA,EAAA;YACjC,EAAc,QAAA,MAAR,KAAC,GAAA;GACP,EAA6C,QAAA,MAAA,EAApC,EAAA,EAAW,CAAC,EAAA,KAAK,MAAI,EAAA,CAAA,CAAA,EAAA,EAAA;WAGnB,EAAA,KAAK,WAAM,eAAA,GAAA,EADxB,EAMM,OAAA;;GAJJ,eAAY;GACX,OAAK,EAAEA,EAAAA,OAAO,QAAO;iBACvB,UACM,GAAA,EAAA,EAA6C,QAAA,MAAA,EAApC,EAAA,EAAW,CAAC,EAAA,KAAK,MAAI,EAAA,CAAA,CAAA,EAAA,EAAA,CAAA,EAAA,EAAA,IAGxB,EAAA,KAAK,WAAM,WAAA,GAAA,EADxB,EAMM,OAAA;;GAJJ,eAAY;GACX,OAAK,EAAEA,EAAAA,OAAO,MAAK;MAEpB,EAA6B,QAAA,MAAA,EAApB,EAAA,KAAK,MAAK,EAAA,EAAA,CAAA,EAAA,EAAA,KAAA,GAAA,EAErB,EAEM,OAAA;;GAFM,eAAY;GAAqC,OAAK,EAAEA,EAAAA,OAAO,QAAO;KAAE,aAEpF,EAAA,EAAA,EAAA,EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"PlBtnExportArchive.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlBtnGhost, PlIcon16, PlIcon24, useClickOutside } from \"@milaboratories/uikit\";\nimport { ZipWriter } from \"@zip.js/zip.js\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { ExportItem, ExportsMap, FileExportEntry } from \"./types\";\nimport Item from \"./Item.vue\";\nimport { getFileNameFromHandle, ChunkedStreamReader } from \"@platforma-sdk/model\";\nimport { getRawPlatformaInstance } from \"@platforma-sdk/model\";\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport Summary from \"./Summary.vue\";\n\ntype FilePickerAcceptType = {\n description?: string;\n accept?: Record<string, string[]>;\n};\n\nconst props = defineProps<{\n fileExports?: FileExportEntry[];\n suggestedFileName?: string;\n disabled?: boolean;\n filePickerTypes?: FilePickerAcceptType[];\n strategy?: \"parallel\"; // default is sequential\n debugFn?: (fileName: string) => Promise<void>;\n}>();\n\nconst defaultData = () => ({\n loading: false,\n name: \"\",\n exports: undefined as ExportsMap | undefined,\n showExports: false,\n});\n\nconst data = reactive(defaultData());\n\nconst updateExportsItem = (id: string, partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n};\n\nconst isReadyToExport = computed(() => {\n return props.fileExports !== undefined && !props.disabled;\n});\n\nconst items = computed(() => {\n return Array.from(data.exports?.values() ?? []);\n});\n\nconst archive = computed<ExportItem>(() => {\n return {\n fileName: data.name,\n current: items.value.reduce((acc, item) => acc + item.current, 0),\n size: items.value.reduce((acc, item) => acc + item.size, 0),\n status: items.value.some((item) => item.status === \"in-progress\")\n ? \"in-progress\"\n : items.value.every((item) => item.status === \"completed\")\n ? \"completed\"\n : \"pending\",\n hasErrors: items.value.some((item) => item.status === \"error\"),\n };\n});\n\ntype ZipRequest = {\n id: string;\n fileName: string;\n size: number;\n stream: ReadableStream<Uint8Array>;\n};\n\nconst exportRawTsvs = async () => {\n if (data.loading) {\n data.showExports = true;\n return;\n }\n\n if (!isReadyToExport.value || !props.fileExports) {\n return;\n }\n\n const defaultFileName = `${new Date().toISOString().split(\"T\")[0]}_Export.zip`;\n const defaultTypes = [\n {\n description: \"ZIP files\",\n accept: {\n \"application/zip\": [\".zip\"],\n },\n },\n ];\n\n // @ts-expect-error - type definition issue TODO: fix this\n const newHandle = await window.showSaveFilePicker({\n types: props.filePickerTypes || defaultTypes,\n suggestedName: props.suggestedFileName || defaultFileName,\n });\n\n data.loading = true;\n data.name = newHandle.name;\n data.showExports = true;\n data.exports = new Map();\n\n try {\n const writableStream = await newHandle.createWritable();\n const zip = new ZipWriter(writableStream, {\n keepOrder: true,\n zip64: true,\n bufferedWrite: false,\n });\n try {\n const requests = [] as ZipRequest[];\n\n for (const entry of props.fileExports) {\n const { importHandle, blobHandle, fileName: customFileName } = entry;\n const fileName = customFileName ?? getFileNameFromHandle(importHandle);\n const { handle, size } = blobHandle;\n\n const id = uniqueId();\n\n data.exports?.set(id, { fileName, current: 0, size, status: \"pending\" });\n\n const stream = ChunkedStreamReader.create({\n fetchChunk: async ({ from, to }) => {\n if (props.debugFn) {\n await props.debugFn(fileName);\n }\n\n return await getRawPlatformaInstance().blobDriver.getContent(handle, { from, to });\n },\n totalSize: size,\n onError: async (error) => {\n updateExportsItem(id, { status: \"error\", error });\n await new Promise((resolve) => setTimeout(resolve, 1000)); // primitive for now\n return \"continue\";\n },\n });\n\n // Create a chunked stream reader for efficient streaming\n requests.push({ id, fileName, size, stream });\n }\n\n const processRequest = async (request: ZipRequest) => {\n const { id, fileName, size, stream } = request;\n const update = (partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n };\n await zip.add(fileName, stream, {\n bufferedWrite: true,\n onstart: () => {\n update({ status: \"in-progress\" });\n return undefined;\n },\n onprogress: (current: number) => {\n update({ current, status: \"in-progress\" });\n return undefined;\n },\n onend() {\n update({ current: size, status: \"completed\" });\n return undefined;\n },\n });\n };\n\n if (props.strategy === \"parallel\") {\n await Promise.all(requests.map(processRequest));\n } else {\n for (const request of requests) {\n await processRequest(request);\n }\n }\n } finally {\n await zip.close().catch((error) => {\n console.error(\"Error closing zip\", error);\n });\n }\n } finally {\n data.loading = false;\n }\n};\n\nconst progressesRef = ref();\n\nuseClickOutside([progressesRef], () => {\n data.showExports = false;\n});\n</script>\n\n<template>\n <PlBtnGhost\n :disabled=\"!isReadyToExport\"\n :loading=\"data.loading\"\n :class=\"{ [$style['has-exports']]: data.exports }\"\n @click.stop=\"exportRawTsvs\"\n >\n <slot />\n <template #append>\n <PlIcon24 :class=\"$style.icon\" name=\"download\" />\n </template>\n </PlBtnGhost>\n <Teleport to=\"body\">\n <div v-if=\"data.exports && data.showExports\" ref=\"progressesRef\" :class=\"$style.progresses\">\n <PlIcon16 :class=\"$style.close\" name=\"close\" @click.stop=\"data.showExports = false\" />\n <Summary :item=\"archive\" />\n <div :class=\"$style.itemsContainer\" class=\"pl-scrollable-y\">\n <Item v-for=\"item in data.exports?.values()\" :key=\"item.fileName\" :item=\"item\" />\n </div>\n </div>\n </Teleport>\n</template>\n\n<style module>\n.progresses {\n position: fixed;\n top: 8px;\n right: 8px;\n width: 350px;\n height: auto;\n max-height: 400px;\n overflow: auto;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 8px;\n padding: 20px 8px 8px 20px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n z-index: 1000;\n\n .itemsContainer {\n max-height: 300px;\n }\n\n .close {\n position: absolute;\n top: 8px;\n right: 8px;\n cursor: pointer;\n --icon-color: white;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlBtnExportArchive.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlBtnGhost, PlIcon16, PlIcon24, useClickOutside } from \"@milaboratories/uikit\";\nimport { ZipWriter } from \"@zip.js/zip.js\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { ExportItem, ExportsMap, FileExportEntry } from \"./types\";\nimport Item from \"./Item.vue\";\nimport { getFileNameFromHandle, ChunkedStreamReader } from \"@platforma-sdk/model\";\nimport { getRawPlatformaInstance } from \"@platforma-sdk/model\";\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport Summary from \"./Summary.vue\";\n\ntype FilePickerAcceptType = {\n description?: string;\n accept?: Record<string, string[]>;\n};\n\nconst props = defineProps<{\n fileExports?: FileExportEntry[];\n suggestedFileName?: string;\n disabled?: boolean;\n filePickerTypes?: FilePickerAcceptType[];\n strategy?: \"parallel\"; // default is sequential\n debugFn?: (fileName: string) => Promise<void>;\n}>();\n\nconst defaultData = () => ({\n loading: false,\n name: \"\",\n exports: undefined as ExportsMap | undefined,\n showExports: false,\n});\n\nconst data = reactive(defaultData());\n\nconst updateExportsItem = (id: string, partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n};\n\nconst isReadyToExport = computed(() => {\n return props.fileExports !== undefined && !props.disabled;\n});\n\nconst items = computed(() => {\n return Array.from(data.exports?.values() ?? []);\n});\n\nconst archive = computed<ExportItem>(() => {\n return {\n fileName: data.name,\n current: items.value.reduce((acc, item) => acc + item.current, 0),\n size: items.value.reduce((acc, item) => acc + item.size, 0),\n status: items.value.some((item) => item.status === \"in-progress\")\n ? \"in-progress\"\n : items.value.every((item) => item.status === \"completed\")\n ? \"completed\"\n : \"pending\",\n hasErrors: items.value.some((item) => item.status === \"error\"),\n };\n});\n\ntype ZipRequest = {\n id: string;\n fileName: string;\n size: number;\n stream: ReadableStream<Uint8Array>;\n};\n\nconst exportRawTsvs = async () => {\n if (data.loading) {\n data.showExports = true;\n return;\n }\n\n if (!isReadyToExport.value || !props.fileExports) {\n return;\n }\n\n const defaultFileName = `${new Date().toISOString().split(\"T\")[0]}_Export.zip`;\n const defaultTypes = [\n {\n description: \"ZIP files\",\n accept: {\n \"application/zip\": [\".zip\"],\n },\n },\n ];\n\n // @ts-expect-error - type definition issue TODO: fix this\n const newHandle = await window.showSaveFilePicker({\n types: props.filePickerTypes || defaultTypes,\n suggestedName: props.suggestedFileName || defaultFileName,\n });\n\n data.loading = true;\n data.name = newHandle.name;\n data.showExports = true;\n data.exports = new Map();\n\n try {\n const writableStream = await newHandle.createWritable();\n const zip = new ZipWriter(writableStream, {\n keepOrder: true,\n zip64: true,\n bufferedWrite: false,\n });\n try {\n const requests = [] as ZipRequest[];\n\n for (const entry of props.fileExports) {\n const { importHandle, blobHandle, fileName: customFileName } = entry;\n const fileName = customFileName ?? getFileNameFromHandle(importHandle);\n const { handle, size } = blobHandle;\n\n const id = uniqueId();\n\n data.exports?.set(id, { fileName, current: 0, size, status: \"pending\" });\n\n const stream = ChunkedStreamReader.create({\n fetchChunk: async ({ from, to }) => {\n if (props.debugFn) {\n await props.debugFn(fileName);\n }\n\n return await getRawPlatformaInstance().blobDriver.getContent(handle, { from, to });\n },\n totalSize: size,\n onError: async (error) => {\n updateExportsItem(id, { status: \"error\", error });\n await new Promise((resolve) => setTimeout(resolve, 1000)); // primitive for now\n return \"continue\";\n },\n });\n\n // Create a chunked stream reader for efficient streaming\n requests.push({ id, fileName, size, stream });\n }\n\n const processRequest = async (request: ZipRequest) => {\n const { id, fileName, size, stream } = request;\n const update = (partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n };\n await zip.add(fileName, stream, {\n bufferedWrite: true,\n onstart: () => {\n update({ status: \"in-progress\" });\n return undefined;\n },\n onprogress: (current: number) => {\n update({ current, status: \"in-progress\" });\n return undefined;\n },\n onend() {\n update({ current: size, status: \"completed\" });\n return undefined;\n },\n });\n };\n\n if (props.strategy === \"parallel\") {\n await Promise.all(requests.map(processRequest));\n } else {\n for (const request of requests) {\n await processRequest(request);\n }\n }\n } finally {\n await zip.close().catch((error) => {\n console.error(\"Error closing zip\", error);\n });\n }\n } finally {\n data.loading = false;\n }\n};\n\nconst progressesRef = ref();\n\nuseClickOutside([progressesRef], () => {\n data.showExports = false;\n});\n</script>\n\n<template>\n <PlBtnGhost\n data-testid=\"pl-btn-export-archive\"\n :disabled=\"!isReadyToExport\"\n :loading=\"data.loading\"\n :class=\"{ [$style['has-exports']]: data.exports }\"\n @click.stop=\"exportRawTsvs\"\n >\n <slot />\n <template #append>\n <PlIcon24 :class=\"$style.icon\" name=\"download\" />\n </template>\n </PlBtnGhost>\n <Teleport to=\"body\">\n <div\n v-if=\"data.exports && data.showExports\"\n ref=\"progressesRef\"\n data-testid=\"pl-btn-export-archive-progress\"\n :class=\"$style.progresses\"\n >\n <PlIcon16\n data-testid=\"pl-btn-export-archive-progress-close\"\n :class=\"$style.close\"\n name=\"close\"\n @click.stop=\"data.showExports = false\"\n />\n <Summary :item=\"archive\" />\n <div\n data-testid=\"pl-btn-export-archive-items\"\n :class=\"$style.itemsContainer\"\n class=\"pl-scrollable-y\"\n >\n <Item v-for=\"item in data.exports?.values()\" :key=\"item.fileName\" :item=\"item\" />\n </div>\n </div>\n </Teleport>\n</template>\n\n<style module>\n.progresses {\n position: fixed;\n top: 8px;\n right: 8px;\n width: 350px;\n height: auto;\n max-height: 400px;\n overflow: auto;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 8px;\n padding: 20px 8px 8px 20px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n z-index: 1000;\n\n .itemsContainer {\n max-height: 300px;\n }\n\n .close {\n position: absolute;\n top: 8px;\n right: 8px;\n cursor: pointer;\n --icon-color: white;\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlBtnExportArchive.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlBtnGhost, PlIcon16, PlIcon24, useClickOutside } from \"@milaboratories/uikit\";\nimport { ZipWriter } from \"@zip.js/zip.js\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { ExportItem, ExportsMap, FileExportEntry } from \"./types\";\nimport Item from \"./Item.vue\";\nimport { getFileNameFromHandle, ChunkedStreamReader } from \"@platforma-sdk/model\";\nimport { getRawPlatformaInstance } from \"@platforma-sdk/model\";\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport Summary from \"./Summary.vue\";\n\ntype FilePickerAcceptType = {\n description?: string;\n accept?: Record<string, string[]>;\n};\n\nconst props = defineProps<{\n fileExports?: FileExportEntry[];\n suggestedFileName?: string;\n disabled?: boolean;\n filePickerTypes?: FilePickerAcceptType[];\n strategy?: \"parallel\"; // default is sequential\n debugFn?: (fileName: string) => Promise<void>;\n}>();\n\nconst defaultData = () => ({\n loading: false,\n name: \"\",\n exports: undefined as ExportsMap | undefined,\n showExports: false,\n});\n\nconst data = reactive(defaultData());\n\nconst updateExportsItem = (id: string, partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n};\n\nconst isReadyToExport = computed(() => {\n return props.fileExports !== undefined && !props.disabled;\n});\n\nconst items = computed(() => {\n return Array.from(data.exports?.values() ?? []);\n});\n\nconst archive = computed<ExportItem>(() => {\n return {\n fileName: data.name,\n current: items.value.reduce((acc, item) => acc + item.current, 0),\n size: items.value.reduce((acc, item) => acc + item.size, 0),\n status: items.value.some((item) => item.status === \"in-progress\")\n ? \"in-progress\"\n : items.value.every((item) => item.status === \"completed\")\n ? \"completed\"\n : \"pending\",\n hasErrors: items.value.some((item) => item.status === \"error\"),\n };\n});\n\ntype ZipRequest = {\n id: string;\n fileName: string;\n size: number;\n stream: ReadableStream<Uint8Array>;\n};\n\nconst exportRawTsvs = async () => {\n if (data.loading) {\n data.showExports = true;\n return;\n }\n\n if (!isReadyToExport.value || !props.fileExports) {\n return;\n }\n\n const defaultFileName = `${new Date().toISOString().split(\"T\")[0]}_Export.zip`;\n const defaultTypes = [\n {\n description: \"ZIP files\",\n accept: {\n \"application/zip\": [\".zip\"],\n },\n },\n ];\n\n // @ts-expect-error - type definition issue TODO: fix this\n const newHandle = await window.showSaveFilePicker({\n types: props.filePickerTypes || defaultTypes,\n suggestedName: props.suggestedFileName || defaultFileName,\n });\n\n data.loading = true;\n data.name = newHandle.name;\n data.showExports = true;\n data.exports = new Map();\n\n try {\n const writableStream = await newHandle.createWritable();\n const zip = new ZipWriter(writableStream, {\n keepOrder: true,\n zip64: true,\n bufferedWrite: false,\n });\n try {\n const requests = [] as ZipRequest[];\n\n for (const entry of props.fileExports) {\n const { importHandle, blobHandle, fileName: customFileName } = entry;\n const fileName = customFileName ?? getFileNameFromHandle(importHandle);\n const { handle, size } = blobHandle;\n\n const id = uniqueId();\n\n data.exports?.set(id, { fileName, current: 0, size, status: \"pending\" });\n\n const stream = ChunkedStreamReader.create({\n fetchChunk: async ({ from, to }) => {\n if (props.debugFn) {\n await props.debugFn(fileName);\n }\n\n return await getRawPlatformaInstance().blobDriver.getContent(handle, { from, to });\n },\n totalSize: size,\n onError: async (error) => {\n updateExportsItem(id, { status: \"error\", error });\n await new Promise((resolve) => setTimeout(resolve, 1000)); // primitive for now\n return \"continue\";\n },\n });\n\n // Create a chunked stream reader for efficient streaming\n requests.push({ id, fileName, size, stream });\n }\n\n const processRequest = async (request: ZipRequest) => {\n const { id, fileName, size, stream } = request;\n const update = (partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n };\n await zip.add(fileName, stream, {\n bufferedWrite: true,\n onstart: () => {\n update({ status: \"in-progress\" });\n return undefined;\n },\n onprogress: (current: number) => {\n update({ current, status: \"in-progress\" });\n return undefined;\n },\n onend() {\n update({ current: size, status: \"completed\" });\n return undefined;\n },\n });\n };\n\n if (props.strategy === \"parallel\") {\n await Promise.all(requests.map(processRequest));\n } else {\n for (const request of requests) {\n await processRequest(request);\n }\n }\n } finally {\n await zip.close().catch((error) => {\n console.error(\"Error closing zip\", error);\n });\n }\n } finally {\n data.loading = false;\n }\n};\n\nconst progressesRef = ref();\n\nuseClickOutside([progressesRef], () => {\n data.showExports = false;\n});\n</script>\n\n<template>\n <PlBtnGhost\n :disabled=\"!isReadyToExport\"\n :loading=\"data.loading\"\n :class=\"{ [$style['has-exports']]: data.exports }\"\n @click.stop=\"exportRawTsvs\"\n >\n <slot />\n <template #append>\n <PlIcon24 :class=\"$style.icon\" name=\"download\" />\n </template>\n </PlBtnGhost>\n <Teleport to=\"body\">\n <div v-if=\"data.exports && data.showExports\" ref=\"progressesRef\" :class=\"$style.progresses\">\n <PlIcon16 :class=\"$style.close\" name=\"close\" @click.stop=\"data.showExports = false\" />\n <Summary :item=\"archive\" />\n <div :class=\"$style.itemsContainer\" class=\"pl-scrollable-y\">\n <Item v-for=\"item in data.exports?.values()\" :key=\"item.fileName\" :item=\"item\" />\n </div>\n </div>\n </Teleport>\n</template>\n\n<style module>\n.progresses {\n position: fixed;\n top: 8px;\n right: 8px;\n width: 350px;\n height: auto;\n max-height: 400px;\n overflow: auto;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 8px;\n padding: 20px 8px 8px 20px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n z-index: 1000;\n\n .itemsContainer {\n max-height: 300px;\n }\n\n .close {\n position: absolute;\n top: 8px;\n right: 8px;\n cursor: pointer;\n --icon-color: white;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"PlBtnExportArchive.vue_vue_type_style_index_0_lang.module.js","names":[],"sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { PlBtnGhost, PlIcon16, PlIcon24, useClickOutside } from \"@milaboratories/uikit\";\nimport { ZipWriter } from \"@zip.js/zip.js\";\nimport { reactive, computed, ref } from \"vue\";\nimport type { ExportItem, ExportsMap, FileExportEntry } from \"./types\";\nimport Item from \"./Item.vue\";\nimport { getFileNameFromHandle, ChunkedStreamReader } from \"@platforma-sdk/model\";\nimport { getRawPlatformaInstance } from \"@platforma-sdk/model\";\nimport { uniqueId } from \"@milaboratories/helpers\";\nimport Summary from \"./Summary.vue\";\n\ntype FilePickerAcceptType = {\n description?: string;\n accept?: Record<string, string[]>;\n};\n\nconst props = defineProps<{\n fileExports?: FileExportEntry[];\n suggestedFileName?: string;\n disabled?: boolean;\n filePickerTypes?: FilePickerAcceptType[];\n strategy?: \"parallel\"; // default is sequential\n debugFn?: (fileName: string) => Promise<void>;\n}>();\n\nconst defaultData = () => ({\n loading: false,\n name: \"\",\n exports: undefined as ExportsMap | undefined,\n showExports: false,\n});\n\nconst data = reactive(defaultData());\n\nconst updateExportsItem = (id: string, partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n};\n\nconst isReadyToExport = computed(() => {\n return props.fileExports !== undefined && !props.disabled;\n});\n\nconst items = computed(() => {\n return Array.from(data.exports?.values() ?? []);\n});\n\nconst archive = computed<ExportItem>(() => {\n return {\n fileName: data.name,\n current: items.value.reduce((acc, item) => acc + item.current, 0),\n size: items.value.reduce((acc, item) => acc + item.size, 0),\n status: items.value.some((item) => item.status === \"in-progress\")\n ? \"in-progress\"\n : items.value.every((item) => item.status === \"completed\")\n ? \"completed\"\n : \"pending\",\n hasErrors: items.value.some((item) => item.status === \"error\"),\n };\n});\n\ntype ZipRequest = {\n id: string;\n fileName: string;\n size: number;\n stream: ReadableStream<Uint8Array>;\n};\n\nconst exportRawTsvs = async () => {\n if (data.loading) {\n data.showExports = true;\n return;\n }\n\n if (!isReadyToExport.value || !props.fileExports) {\n return;\n }\n\n const defaultFileName = `${new Date().toISOString().split(\"T\")[0]}_Export.zip`;\n const defaultTypes = [\n {\n description: \"ZIP files\",\n accept: {\n \"application/zip\": [\".zip\"],\n },\n },\n ];\n\n // @ts-expect-error - type definition issue TODO: fix this\n const newHandle = await window.showSaveFilePicker({\n types: props.filePickerTypes || defaultTypes,\n suggestedName: props.suggestedFileName || defaultFileName,\n });\n\n data.loading = true;\n data.name = newHandle.name;\n data.showExports = true;\n data.exports = new Map();\n\n try {\n const writableStream = await newHandle.createWritable();\n const zip = new ZipWriter(writableStream, {\n keepOrder: true,\n zip64: true,\n bufferedWrite: false,\n });\n try {\n const requests = [] as ZipRequest[];\n\n for (const entry of props.fileExports) {\n const { importHandle, blobHandle, fileName: customFileName } = entry;\n const fileName = customFileName ?? getFileNameFromHandle(importHandle);\n const { handle, size } = blobHandle;\n\n const id = uniqueId();\n\n data.exports?.set(id, { fileName, current: 0, size, status: \"pending\" });\n\n const stream = ChunkedStreamReader.create({\n fetchChunk: async ({ from, to }) => {\n if (props.debugFn) {\n await props.debugFn(fileName);\n }\n\n return await getRawPlatformaInstance().blobDriver.getContent(handle, { from, to });\n },\n totalSize: size,\n onError: async (error) => {\n updateExportsItem(id, { status: \"error\", error });\n await new Promise((resolve) => setTimeout(resolve, 1000)); // primitive for now\n return \"continue\";\n },\n });\n\n // Create a chunked stream reader for efficient streaming\n requests.push({ id, fileName, size, stream });\n }\n\n const processRequest = async (request: ZipRequest) => {\n const { id, fileName, size, stream } = request;\n const update = (partial: Partial<ExportItem>) => {\n const it = data.exports?.get(id);\n if (it) {\n data.exports?.set(id, { ...it, ...partial });\n }\n };\n await zip.add(fileName, stream, {\n bufferedWrite: true,\n onstart: () => {\n update({ status: \"in-progress\" });\n return undefined;\n },\n onprogress: (current: number) => {\n update({ current, status: \"in-progress\" });\n return undefined;\n },\n onend() {\n update({ current: size, status: \"completed\" });\n return undefined;\n },\n });\n };\n\n if (props.strategy === \"parallel\") {\n await Promise.all(requests.map(processRequest));\n } else {\n for (const request of requests) {\n await processRequest(request);\n }\n }\n } finally {\n await zip.close().catch((error) => {\n console.error(\"Error closing zip\", error);\n });\n }\n } finally {\n data.loading = false;\n }\n};\n\nconst progressesRef = ref();\n\nuseClickOutside([progressesRef], () => {\n data.showExports = false;\n});\n</script>\n\n<template>\n <PlBtnGhost\n data-testid=\"pl-btn-export-archive\"\n :disabled=\"!isReadyToExport\"\n :loading=\"data.loading\"\n :class=\"{ [$style['has-exports']]: data.exports }\"\n @click.stop=\"exportRawTsvs\"\n >\n <slot />\n <template #append>\n <PlIcon24 :class=\"$style.icon\" name=\"download\" />\n </template>\n </PlBtnGhost>\n <Teleport to=\"body\">\n <div\n v-if=\"data.exports && data.showExports\"\n ref=\"progressesRef\"\n data-testid=\"pl-btn-export-archive-progress\"\n :class=\"$style.progresses\"\n >\n <PlIcon16\n data-testid=\"pl-btn-export-archive-progress-close\"\n :class=\"$style.close\"\n name=\"close\"\n @click.stop=\"data.showExports = false\"\n />\n <Summary :item=\"archive\" />\n <div\n data-testid=\"pl-btn-export-archive-items\"\n :class=\"$style.itemsContainer\"\n class=\"pl-scrollable-y\"\n >\n <Item v-for=\"item in data.exports?.values()\" :key=\"item.fileName\" :item=\"item\" />\n </div>\n </div>\n </Teleport>\n</template>\n\n<style module>\n.progresses {\n position: fixed;\n top: 8px;\n right: 8px;\n width: 350px;\n height: auto;\n max-height: 400px;\n overflow: auto;\n background: rgba(0, 0, 0, 0.85);\n border-radius: 8px;\n padding: 20px 8px 8px 20px;\n color: white;\n font-size: 12px;\n font-weight: 600;\n z-index: 1000;\n\n .itemsContainer {\n max-height: 300px;\n }\n\n .close {\n position: absolute;\n top: 8px;\n right: 8px;\n cursor: pointer;\n --icon-color: white;\n }\n}\n</style>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"PlBtnExportArchive.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"names":[],"mappings":"AAwPA,OAAO,KAAK,EAA0B,eAAe,EAAE,MAAM,SAAS,CAAC;AAOvE,KAAK,oBAAoB,GAAG;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACzC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C,CAAC;AA2TF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK/C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"PlBtnExportArchive.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlBtnExportArchive/PlBtnExportArchive.vue"],"names":[],"mappings":"AAuQA,OAAO,KAAK,EAA0B,eAAe,EAAE,MAAM,SAAS,CAAC;AAOvE,KAAK,oBAAoB,GAAG;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACzC,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C,CAAC;AAiUF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK/C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}