@mixd-id/web-scaffold 0.2.240706 → 0.2.250801009

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 (220) hide show
  1. package/docs/components/Dashboard.md +56 -0
  2. package/log.txt +7 -0
  3. package/package.json +27 -19
  4. package/src/components/404.vue +61 -0
  5. package/src/components/AccountIcon.vue +19 -0
  6. package/src/components/Ahref.vue +1 -1
  7. package/src/components/Alert.vue +4 -13
  8. package/src/components/ArrayList.vue +49 -0
  9. package/src/components/Article.vue +24 -30
  10. package/src/components/Button.vue +79 -167
  11. package/src/components/Card.vue +235 -0
  12. package/src/components/Carousel.vue +61 -60
  13. package/src/components/Cart.vue +192 -0
  14. package/src/components/CartIcon.vue +89 -0
  15. package/src/components/ChartBar.vue +2 -3
  16. package/src/components/Checkbox.vue +20 -11
  17. package/src/components/Checkout.vue +373 -0
  18. package/src/components/CheckoutDelivery.vue +267 -0
  19. package/src/components/CodeEditor.vue +5 -16
  20. package/src/components/CollapsiblePanel.vue +70 -0
  21. package/src/components/ColorPicker.vue +8 -3
  22. package/src/components/ColorPicker2.vue +41 -19
  23. package/src/components/ColorPicker3.vue +100 -0
  24. package/src/components/Confirm.vue +9 -7
  25. package/src/components/ContextMenu.vue +122 -206
  26. package/src/components/ContextMenuItem.vue +53 -0
  27. package/src/components/Dashboard.vue +243 -0
  28. package/src/components/Dashboard2.vue +118 -0
  29. package/src/components/DashboardComponentSelector.vue +96 -0
  30. package/src/components/DashboardConfigs.vue +202 -0
  31. package/src/components/Datepicker.vue +102 -41
  32. package/src/components/DayTimeRange.vue +3 -2
  33. package/src/components/Dropdown.vue +7 -4
  34. package/src/components/Flex.vue +14 -40
  35. package/src/components/GHeatMaps.vue +2 -2
  36. package/src/components/Grid.vue +6 -6
  37. package/src/components/HTMLEditor.vue +27 -14
  38. package/src/components/Image.vue +62 -108
  39. package/src/components/ImagePreview.vue +14 -4
  40. package/src/components/ImageUploader.vue +114 -0
  41. package/src/components/ImportModal.vue +3 -3
  42. package/src/components/Link.vue +62 -6
  43. package/src/components/List.vue +524 -403
  44. package/src/components/ListContextMenu.vue +88 -0
  45. package/src/components/ListItem.vue +5 -3
  46. package/src/components/ListPage1.vue +14 -15
  47. package/src/components/ListView.vue +5 -6
  48. package/src/components/ListViewSettings.vue +2 -2
  49. package/src/components/LogViewerItem.vue +1 -1
  50. package/src/components/MarkdownEdit.vue +128 -0
  51. package/src/components/MarkdownPreview.vue +102 -0
  52. package/src/components/MenuItem1.vue +36 -0
  53. package/src/components/Modal.vue +95 -43
  54. package/src/components/MultiDropdown.vue +124 -0
  55. package/src/components/MultilineText.vue +1 -4
  56. package/src/components/OTPField.vue +11 -17
  57. package/src/components/ObjectTree.vue +1 -1
  58. package/src/components/PageBuilder.vue +3 -3
  59. package/src/components/Paragraph.vue +1 -2
  60. package/src/components/PresetSelectorFilterItem.vue +107 -95
  61. package/src/components/Radio.vue +1 -1
  62. package/src/components/SearchModal.vue +153 -0
  63. package/src/components/Slider.vue +1 -1
  64. package/src/components/Svg.vue +1 -1
  65. package/src/components/SvgEditor.vue +173 -0
  66. package/src/components/Switch.vue +4 -5
  67. package/src/components/Table.vue +2 -2
  68. package/src/components/TableView.vue +2 -3
  69. package/src/components/TableViewHead.vue +2 -2
  70. package/src/components/Tabs.vue +1 -1
  71. package/src/components/Testimonial.vue +2 -2
  72. package/src/components/Text.vue +7 -22
  73. package/src/components/TextEditor.vue +3 -3
  74. package/src/components/TextWithTag.vue +61 -30
  75. package/src/components/Textarea.vue +11 -16
  76. package/src/components/Textbox.vue +9 -19
  77. package/src/components/Timepicker.vue +25 -15
  78. package/src/components/Toast.vue +5 -3
  79. package/src/components/TreeMenu.vue +122 -0
  80. package/src/components/TreeView.vue +15 -10
  81. package/src/components/TreeView2.vue +38 -0
  82. package/src/components/TreeViewItem.vue +58 -29
  83. package/src/components/TreeViewItem2.vue +55 -0
  84. package/src/components/Uploader.vue +45 -0
  85. package/src/components/Video.vue +119 -0
  86. package/src/components/VirtualGrid.vue +24 -7
  87. package/src/components/VirtualTable.vue +363 -128
  88. package/src/configs/dashboard/data-table.js +9 -0
  89. package/src/configs/web-page-builder.js +118 -0
  90. package/src/directives/intersect.js +26 -0
  91. package/src/hooks/device.js +14 -0
  92. package/src/index.js +62 -107
  93. package/src/mixin/component.js +147 -67
  94. package/src/themes/default/index.js +83 -155
  95. package/src/utils/dashboard.js +22 -962
  96. package/src/utils/helpers.cjs +635 -0
  97. package/src/utils/helpers.js +91 -60
  98. package/src/utils/helpers.mjs +245 -12
  99. package/src/utils/importer.js +22 -3
  100. package/src/utils/list.mjs +1509 -0
  101. package/src/utils/preset-selector.cjs +1455 -0
  102. package/src/utils/preset-selector.js +489 -95
  103. package/src/utils/preset-selector.mjs +59 -20
  104. package/src/utils/queue.js +63 -0
  105. package/src/utils/web.mjs +120 -0
  106. package/src/utils/wss.js +37 -29
  107. package/src/utils/wss.mjs +24 -19
  108. package/src/widgets/AhrefSetting.vue +16 -13
  109. package/src/widgets/ArticleSetting.vue +15 -27
  110. package/src/widgets/BackgroundColorSetting.vue +153 -0
  111. package/src/widgets/BorderColorSetting.vue +57 -0
  112. package/src/widgets/BotEditor/BotEditorActions.vue +3 -2
  113. package/src/widgets/BotEditor/BotEditorSettings.vue +21 -0
  114. package/src/widgets/BotEditor.vue +35 -15
  115. package/src/widgets/ButtonSetting.vue +12 -13
  116. package/src/widgets/CarouselSetting.vue +33 -45
  117. package/src/widgets/CartSetting.vue +46 -0
  118. package/src/widgets/CheckoutSetting.vue +46 -0
  119. package/src/widgets/CollapsiblePanelSetting.vue +46 -0
  120. package/src/widgets/ColumnSelector.vue +29 -5
  121. package/src/widgets/ComponentSetting.vue +1 -1
  122. package/src/widgets/ComponentSetting2.vue +112 -234
  123. package/src/widgets/ComponentSetting3.vue +1 -1
  124. package/src/widgets/ContactForm.vue +3 -3
  125. package/src/widgets/ContactFormSetting.vue +41 -30
  126. package/src/widgets/Dashboard/BarChart.vue +47 -11
  127. package/src/widgets/Dashboard/BarChartSetting.vue +1 -1
  128. package/src/widgets/Dashboard/DataTable.vue +125 -0
  129. package/src/widgets/Dashboard/DataTableSetting.vue +243 -0
  130. package/src/widgets/Dashboard/DatasourceSelector.vue +1 -1
  131. package/src/widgets/Dashboard/Doughnut.vue +49 -7
  132. package/src/widgets/Dashboard/DoughnutSetting.vue +2 -2
  133. package/src/widgets/Dashboard/Metric.vue +78 -19
  134. package/src/widgets/Dashboard/MetricSetting.vue +81 -28
  135. package/src/widgets/Dashboard/Pie.vue +55 -6
  136. package/src/widgets/Dashboard/PieSetting.vue +1 -1
  137. package/src/widgets/Dashboard/PolarArea.vue +49 -7
  138. package/src/widgets/Dashboard/PolarAreaSetting.vue +1 -1
  139. package/src/widgets/Dashboard/SharingModal.vue +4 -5
  140. package/src/widgets/Dashboard/ViewSelector.vue +2 -2
  141. package/src/widgets/Dashboard/VirtualTableSetting.vue +121 -184
  142. package/src/widgets/{Dashboard.vue → Dashboard0.vue} +426 -343
  143. package/src/widgets/EmbeddedVideoSetting.vue +7 -5
  144. package/src/widgets/FAQ.vue +16 -3
  145. package/src/widgets/FAQSetting.vue +53 -47
  146. package/src/widgets/FeatureList.vue +3 -0
  147. package/src/widgets/FeatureListSetting.vue +112 -102
  148. package/src/widgets/FlexSetting.vue +83 -106
  149. package/src/widgets/GridSetting.vue +71 -196
  150. package/src/widgets/Header2.vue +34 -71
  151. package/src/widgets/Header2Setting.vue +95 -179
  152. package/src/widgets/HeaderSetting.vue +16 -18
  153. package/src/widgets/IconListSetting.vue +69 -65
  154. package/src/widgets/ImageSetting.vue +33 -60
  155. package/src/widgets/LinkSetting.vue +60 -37
  156. package/src/widgets/LinkSettingModal.vue +173 -0
  157. package/src/widgets/LogViewer.vue +1 -1
  158. package/src/widgets/MarginSetting.vue +2 -2
  159. package/src/widgets/MenuEditor.vue +1 -1
  160. package/src/widgets/MenuItem1Setting.vue +78 -0
  161. package/src/widgets/ModalSetting.vue +42 -44
  162. package/src/widgets/MultiValueSetting.vue +2 -2
  163. package/src/widgets/MultiValueSetting2.vue +78 -45
  164. package/src/widgets/OGSettingModal.vue +103 -0
  165. package/src/widgets/PaddingSetting.vue +2 -2
  166. package/src/widgets/ParagraphSetting.vue +16 -13
  167. package/src/widgets/PositionSetting.vue +209 -0
  168. package/src/widgets/PresetBar.vue +359 -210
  169. package/src/widgets/PresetBarPivot.vue +31 -19
  170. package/src/widgets/PresetSelector.vue +29 -17
  171. package/src/widgets/SearchModalSetting.vue +70 -0
  172. package/src/widgets/Share.vue +1 -2
  173. package/src/widgets/ShareSetting.vue +67 -60
  174. package/src/widgets/StyleSetting.vue +227 -116
  175. package/src/widgets/TestimonialSetting.vue +97 -88
  176. package/src/widgets/TextBlockSetting.vue +16 -13
  177. package/src/widgets/UserActionBuilder/UserActionConsole.vue +30 -10
  178. package/src/widgets/UserActionBuilder/UserActionOutput.vue +2 -2
  179. package/src/widgets/UserActionBuilder/UserActionOutputReply.vue +64 -87
  180. package/src/widgets/UserActionBuilder/UserActionProps.vue +3 -3
  181. package/src/widgets/UserActionBuilder.vue +4 -16
  182. package/src/widgets/WebComponentSelector.vue +15 -11
  183. package/src/widgets/WebLayoutSelector.vue +41 -270
  184. package/src/widgets/WebPageBuilder.vue +693 -704
  185. package/src/widgets/WebPageBuilder2.vue +7 -7
  186. package/src/widgets/WebPageBuilder4/ButtonSetting.vue +0 -8
  187. package/src/widgets/WebPageBuilder4/CarouselSetting.vue +63 -7
  188. package/src/widgets/WebPageBuilder4/FlexAlignSetting.vue +3 -3
  189. package/src/widgets/WebPageBuilder4/FlexSetting.vue +1 -10
  190. package/src/widgets/WebPageBuilder4/MultiValueSetting.vue +2 -2
  191. package/src/widgets/WebPageBuilder4/PropertySetting.vue +0 -7
  192. package/src/widgets/WebPageBuilder4/WebPageComponentSelector.vue +1 -7
  193. package/src/widgets/WebPageBuilder4.vue +289 -575
  194. package/src/widgets/WebPageSelector.vue +1 -1
  195. package/src/widgets/YoutubeVideoSetting.vue +16 -13
  196. package/tailwind.config.js +3 -35
  197. package/docs/schema/user-action.json +0 -266
  198. package/src/App.vue +0 -25
  199. package/src/components/SearchButton.vue +0 -57
  200. package/src/entry-client.js +0 -27
  201. package/src/entry-server.js +0 -73
  202. package/src/events/event.js +0 -2
  203. package/src/main.js +0 -29
  204. package/src/mixin/website.js +0 -121
  205. package/src/router.js +0 -57
  206. package/src/widgets/MobileMenu.vue +0 -182
  207. package/src/widgets/WebPageBuilder4/ActionSetting.vue +0 -158
  208. package/src/widgets/WebPageBuilder4/ColorSetting.vue +0 -63
  209. package/src/widgets/WebPageBuilder4/DataSetting.vue +0 -92
  210. package/src/widgets/WebPageBuilder4/FontSizeSetting.vue +0 -76
  211. package/src/widgets/WebPageBuilder4/LinkSetting.vue +0 -68
  212. package/src/widgets/WebPageBuilder4/MobileMenuSetting.vue +0 -106
  213. package/src/widgets/WebPageBuilder4/Setting.vue +0 -73
  214. package/src/widgets/WebPageBuilder4/StyleSetting.vue +0 -77
  215. package/src/widgets/WebPageBuilder4/SvgSetting.vue +0 -207
  216. package/src/widgets/WebPageBuilder4/TextTransformSetting.vue +0 -70
  217. package/src/widgets/WebPageBuilder4/WebPageDataEdit.vue +0 -121
  218. package/test.json +0 -22
  219. /package/src/widgets/{Header1.vue → Header0.vue} +0 -0
  220. /package/src/widgets/{Header1Setting.vue → Header0Setting.vue} +0 -0
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div :class="$style.comp" v-if="config">
2
+ <div v-if="config" :class="$style.comp">
3
3
 
4
4
  <TransitionGroup name="openltr" tag="div" class="flex-1 flex">
5
5
 
@@ -8,102 +8,139 @@
8
8
  <div class="flex flex-row items-center gap-2 p-3">
9
9
  <slot name="start"></slot>
10
10
  <div class="flex-1">
11
- <h5 class="px-3">{{ config.name ?? 'Config' }}</h5>
11
+ <h5 class="px-3" @click="log(config)">{{ config.name ?? 'Config' }}</h5>
12
12
  </div>
13
13
  <slot name="toolbar" :edit="false"></slot>
14
14
  </div>
15
15
 
16
- <div class="p-3">
16
+ <div class="p-5">
17
17
  <div class="px-2">
18
18
  <label class="text-text-300">Presets</label>
19
19
  </div>
20
20
 
21
- <div class="mt-1 flex flex-col divide-y divide-text-50 bg-base-500 border-[1px] border-text-50 overflow-hidden rounded-lg">
22
- <div v-for="(_preset, idx) in presets" type="button"
23
- class="px-3 p-2 text-left hover:bg-primary-100 flex flex-row gap-2 items-center group">
24
- <Radio :checked="config.presetIdx === _preset.uid"
25
- @click="config.presetIdx = _preset.uid" />
26
- <button type="button"
27
- class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
28
- @click="config.presetIdx = _preset.uid"
29
- @click.shift="select(_preset.uid)">
30
- {{ _preset.name }}
31
- </button>
32
- <button type="button"
33
- class="pl-2 hidden group-hover:block"
34
- ref="btn"
35
- @click="$refs.contextMenu.open($refs.btn[idx], { preset:_preset, idx })">
36
- <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
37
- </button>
38
- </div>
39
- </div>
21
+ <ListItem :items="config.presets"
22
+ class="mt-1 rounded-lg overflow-hidden bg-base-300 border-border-50 border-[1px]"
23
+ container-class="divide-y divide-border-50"
24
+ @reorder="(from, to) => { config.presets.splice(to, 0, config.presets.splice(from, 1)[0]); apply() }">
25
+ <template v-slot="{ item }">
26
+ <div :class="$style.presetBtn">
27
+ <div data-reorder>
28
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
29
+ </div>
30
+ <Radio v-model="configParams.presetIdx" :value="item.uid" @change="apply()" />
31
+ <button type="button" class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
32
+ @click="configParams.presetIdx = item.uid; apply()">
33
+ {{ item.name }}
34
+ </button>
35
+ <button type="button"
36
+ :class="$style.presetOptBtn"
37
+ :ref="`presetbtn${item.uid}`"
38
+ @click="$refs.contextMenu.open($refs[`presetbtn${item.uid}`], { item })">
39
+ <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
40
+ </button>
41
+ </div>
42
+ </template>
43
+ </ListItem>
44
+
45
+ <ContextMenu ref="contextMenu" position="bottom-right">
46
+ <template #default="{ context }">
47
+ <div class="flex flex-col min-w-[200px] divide-y divide-border-50">
48
+
49
+ <button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
50
+ @click="select(context.item)">
51
+ <div class="w-[24px]">
52
+ <svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.3 344.9l32-32c5-5 13.7-1.5 13.7 5.7V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h273.5c7.1 0 10.7 8.6 5.7 13.7l-32 32c-1.5 1.5-3.5 2.3-5.7 2.3H48v352h352V350.5c0-2.1.8-4.1 2.3-5.6zm156.6-201.8L296.3 405.7l-90.4 10c-26.2 2.9-48.5-19.2-45.6-45.6l10-90.4L432.9 17.1c22.9-22.9 59.9-22.9 82.7 0l43.2 43.2c22.9 22.9 22.9 60 .1 82.8zM460.1 174L402 115.9 216.2 301.8l-7.3 65.3 65.3-7.3L460.1 174zm64.8-79.7l-43.2-43.2c-4.1-4.1-10.8-4.1-14.8 0L436 82l58.1 58.1 30.9-30.9c4-4.2 4-10.8-.1-14.9z"/></svg>
53
+ </div>
54
+ Edit
55
+ </button>
56
+
57
+ <button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
58
+ @click="duplicate(context.item)">
59
+ <div class="w-[24px]">
60
+ <svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>
61
+ </div>
62
+ Duplicate
63
+ </button>
64
+
65
+ <button v-if="config.presets.length > 1" class="w-full p-3 text-left flex flex-row gap-3 text-red-500" :class="appStyle.menuItem"
66
+ @click="remove(context.item)">
67
+ <div class="w-[24px]">
68
+ <svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
69
+ </div>
70
+ Remove
71
+ </button>
72
+
73
+ </div>
74
+ </template>
75
+ </ContextMenu>
40
76
  </div>
41
77
 
42
- <div v-if="sharedPresets?.length > 0" class="p-3">
78
+ <div v-if="(config.sharedPresets ?? []).length > 0" class="p-5">
43
79
  <div class="px-2">
44
80
  <label class="text-text-300">Shared Presets</label>
45
81
  </div>
46
82
 
47
- <div class="mt-1 flex flex-col divide-y divide-text-50 bg-base-500 border-[1px] border-text-50 overflow-hidden rounded-lg">
48
- <div v-for="(_preset, idx) in sharedPresets" type="button"
49
- class="px-3 p-2 text-left hover:bg-primary-100 flex flex-row gap-2 items-center group">
50
- <Radio :checked="config.presetIdx === _preset.uid"
51
- @click="config.presetIdx = _preset.uid" />
52
- <button type="button"
53
- class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
54
- @click="config.presetIdx = _preset.uid"
55
- @click.shift="select(_preset.uid)">
56
- {{ _preset.name }}
57
- </button>
58
- <button type="button"
59
- class="pl-2 hidden group-hover:block"
60
- ref="sharedBtn"
61
- @click="$refs.contextMenu.open($refs.sharedBtn[idx], { preset:_preset, idx, sharing:true })">
62
- <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
63
- </button>
64
- </div>
65
- </div>
66
- </div>
67
-
68
- <ContextMenu ref="contextMenu" position="bottom-right">
69
- <template #default="{ context }">
70
- <div class="flex flex-col min-w-[200px] divide-y divide-text-50">
83
+ <ListItem :items="config.sharedPresets"
84
+ class="mt-1 rounded-lg overflow-hidden"
85
+ container-class="divide-y divide-border-50">
86
+ <template v-slot="{ item, index }">
87
+ <div :class="$style.presetBtn">
88
+ <Radio v-model="configParams.presetIdx" :value="item.uid" @change="apply()" />
89
+ <button type="button" class="flex-1 py-1 text-left overflow-hidden text-ellipsis whitespace-nowrap"
90
+ @click="configParams.presetIdx = item.uid; apply()">
91
+ {{ item.name }}
92
+ </button>
93
+ <button type="button"
94
+ :class="$style.presetOptBtn"
95
+ :ref="`presetsbtn${item.uid}`"
96
+ @click="$refs.contextMenu2.open($refs[`presetsbtn${item.uid}`], { item, index })">
97
+ <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 512"><path d="M64 208c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zM16 104c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48zm0 304c0 26.5 21.5 48 48 48s48-21.5 48-48-21.5-48-48-48-48 21.5-48 48z"/></svg>
98
+ </button>
99
+ </div>
100
+ </template>
101
+ </ListItem>
71
102
 
72
- <button v-if="!context.sharing" class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
73
- @click="select(context.preset.uid)">
74
- <div class="w-[24px]">
75
- <svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.3 344.9l32-32c5-5 13.7-1.5 13.7 5.7V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h273.5c7.1 0 10.7 8.6 5.7 13.7l-32 32c-1.5 1.5-3.5 2.3-5.7 2.3H48v352h352V350.5c0-2.1.8-4.1 2.3-5.6zm156.6-201.8L296.3 405.7l-90.4 10c-26.2 2.9-48.5-19.2-45.6-45.6l10-90.4L432.9 17.1c22.9-22.9 59.9-22.9 82.7 0l43.2 43.2c22.9 22.9 22.9 60 .1 82.8zM460.1 174L402 115.9 216.2 301.8l-7.3 65.3 65.3-7.3L460.1 174zm64.8-79.7l-43.2-43.2c-4.1-4.1-10.8-4.1-14.8 0L436 82l58.1 58.1 30.9-30.9c4-4.2 4-10.8-.1-14.9z"/></svg>
76
- </div>
77
- Edit
78
- </button>
103
+ <ContextMenu ref="contextMenu2" position="bottom-right">
104
+ <template #default="{ context }">
105
+ <div class="flex flex-col min-w-[200px] divide-y divide-border-50">
79
106
 
80
- <button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
81
- @click="duplicate(context.preset)">
82
- <div class="w-[24px]">
83
- <svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>
84
- </div>
85
- Duplicate
86
- </button>
107
+ <button class="w-full p-3 text-left flex flex-row gap-3" :class="appStyle.menuItem"
108
+ @click="duplicate(context.item)">
109
+ <div class="w-[24px]">
110
+ <svg width="16" height="16" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"/></svg>
111
+ </div>
112
+ Duplicate
113
+ </button>
87
114
 
88
- <button v-if="presets.length > 1 && !context.sharing" class="w-full p-3 text-left flex flex-row gap-3 text-red-500" :class="appStyle.menuItem"
89
- @click="remove(context.preset.uid)">
90
- <div class="w-[24px]">
91
- <svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
92
- </div>
93
- Remove
94
- </button>
115
+ <button class="w-full p-3 text-left flex flex-row gap-3 text-red-500"
116
+ :class="appStyle.menuItem"
117
+ @click="removeShared(context.item, context.index)">
118
+ <div class="w-[24px]">
119
+ <svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
120
+ </div>
121
+ Remove
122
+ </button>
95
123
 
96
- <button v-else class="w-full p-3 text-left flex flex-row gap-3 text-red-500" :class="appStyle.menuItem"
97
- @click="removeShared(context.preset.uid)">
98
- <div class="w-[24px]">
99
- <svg width="19" height="19" class="mx-auto fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M469.65 181.65l-11.31-11.31c-6.25-6.25-16.38-6.25-22.63 0L384 222.06l-51.72-51.72c-6.25-6.25-16.38-6.25-22.63 0l-11.31 11.31c-6.25 6.25-6.25 16.38 0 22.63L350.06 256l-51.72 51.72c-6.25 6.25-6.25 16.38 0 22.63l11.31 11.31c6.25 6.25 16.38 6.25 22.63 0L384 289.94l51.72 51.72c6.25 6.25 16.38 6.25 22.63 0l11.31-11.31c6.25-6.25 6.25-16.38 0-22.63L417.94 256l51.72-51.72c6.24-6.25 6.24-16.38-.01-22.63zM576 64H205.26C188.28 64 172 70.74 160 82.74L9.37 233.37c-12.5 12.5-12.5 32.76 0 45.25L160 429.25c12 12 28.28 18.75 45.25 18.75H576c35.35 0 64-28.65 64-64V128c0-35.35-28.65-64-64-64zm16 320c0 8.82-7.18 16-16 16H205.26c-4.27 0-8.29-1.66-11.31-4.69L54.63 256l139.31-139.31c3.02-3.02 7.04-4.69 11.31-4.69H576c8.82 0 16 7.18 16 16v256z"/></svg>
100
- </div>
101
- Remove
102
- </button>
124
+ </div>
125
+ </template>
126
+ </ContextMenu>
127
+ </div>
103
128
 
129
+ <div class="p-5" v-if="['true', 1, true].includes(useAssistant)">
130
+ <div class="px-2 flex flex-col gap-1">
131
+ <div class="flex flex-row gap-2">
132
+ <div class="flex-1">
133
+ <label class="text-text-300">AI Assistant</label>
134
+ </div>
135
+ <div v-if="$isDebugMode" class="flex flex-row gap-2">
136
+ <button type="button" class="text-primary text-sm" @click="log(config)">Config</button>
137
+ <button type="button" class="text-primary text-sm" @click="log(preset)">Preset</button>
138
+ </div>
104
139
  </div>
105
- </template>
106
- </ContextMenu>
140
+ <Textarea rows="6" placeholder="Generate preset based on text" v-model="generateText" />
141
+ <Button ref="generateBtn" class="w-[100px] mt-2" :state="canGenerate ? 1 : -1" @click="generatePreset">Generate</Button>
142
+ </div>
143
+ </div>
107
144
 
108
145
  </div>
109
146
 
@@ -121,36 +158,61 @@
121
158
  <slot name="toolbar" :edit="true"></slot>
122
159
  </div>
123
160
 
124
- <div class="flex items-center justify-center border-b-[1px] border-text-100 px-3">
125
- <Tabs :items="tabItems[config.type ?? 'list']" v-model="config.presetBarTabIndex" />
161
+ <div class="flex items-center justify-center border-b-[1px] border-border-50 px-3">
162
+ <Tabs :items="tabItems[config.type ?? 'list']" v-model="configParams.presetBarTabIndex" />
126
163
  </div>
127
164
 
128
- <div class="flex-1 overflow-y-auto">
129
-
130
- <div v-if="config.presetBarTabIndex === 1" class="flex-1 flex flex-col p-5">
131
- <ListItem :items="presetColumns"
132
- body-class="divide-y divide-text-50 rounded-lg border-[1px] border-text-50 bg-base-300"
133
- @reorder="(from, to) => { presetColumns.splice(to, 0, presetColumns.splice(from, 1)[0]); }">
134
- <template v-slot="{ item }">
135
- <div v-if="!item.key.startsWith('_') || (item.key.startsWith('_') && (preset.pivot && preset.pivot.enabled))"
136
- class="flex flex-row items-center gap-3 px-3 p-1 hover:bg-primary-100">
137
- <div data-reorder>
138
- <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
165
+ <div class="flex-1 flex">
166
+
167
+ <div v-if="configParams.presetBarTabIndex === 1" class="flex-1 flex flex-col gap-5 py-5">
168
+ <div class="px-5">
169
+ <Textbox placeholder="Search..."
170
+ v-model="configParams.columnSearchKey"
171
+ :clearable="true"
172
+ class="border-none"
173
+ @clear="delete configParams.columnSearchKey">
174
+ <template #start>
175
+ <div class="pl-3">
176
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z"/></svg>
139
177
  </div>
140
- <div class="flex-1 flex flex-row gap-2 items-center">
141
- <div>
142
- <Checkbox v-model="item.visible" default="true" />
178
+ </template>
179
+ <template #end>
180
+ <div class="pr-3 hidden">
181
+ <button type="button" @click="configParams.activeColumnOnly = !configParams.activeColumnOnly">
182
+ <svg width="14" height="14" :class="configParams.activeColumnOnly ? 'fill-primary' : 'fill-text-200 hover:fill-primary'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M384 32H64C28.65 32 0 60.65 0 96v320c0 35.35 28.65 64 64 64h320c35.35 0 64-28.65 64-64V96C448 60.65 419.3 32 384 32zM339.8 211.8l-128 128C206.3 345.3 199.2 348 192 348s-14.34-2.719-19.81-8.188l-64-64c-10.91-10.94-10.91-28.69 0-39.63c10.94-10.94 28.69-10.94 39.63 0L192 280.4l108.2-108.2c10.94-10.94 28.69-10.94 39.63 0C350.7 183.1 350.7 200.9 339.8 211.8z"/></svg>
183
+ </button>
184
+ </div>
185
+ </template>
186
+ </Textbox>
187
+ </div>
188
+
189
+ <div class="flex-1 overflow-y-auto px-5">
190
+ <ListItem v-if="presetColumns.length > 0"
191
+ :items="presetColumns"
192
+ class="flex-1 bg-transparent"
193
+ body-class="divide-y divide-border-50 rounded-lg border-[1px] border-border-50 bg-base-300"
194
+ @reorder="(from, to) => { presetColumns.splice(to, 0, presetColumns.splice(from, 1)[0]); }">
195
+ <template v-slot="{ item }">
196
+ <div v-if="(!item.key.startsWith('_') || (item.key.startsWith('_') && (preset.pivot && preset.pivot.enabled)))"
197
+ class="flex flex-row items-center gap-2 pr-3 p-1 hover:bg-primary-100">
198
+ <div data-reorder v-if="!configParams.columnSearchKey">
199
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M496 288H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16zm0-128H16c-8.8 0-16 7.2-16 16v32c0 8.8 7.2 16 16 16h480c8.8 0 16-7.2 16-16v-32c0-8.8-7.2-16-16-16z"/></svg>
200
+ </div>
201
+ <div class="flex-1 flex flex-row gap-2 items-center">
202
+ <div>
203
+ <Checkbox v-model="item.visible" default="true" />
204
+ </div>
205
+ <Textbox v-model="item.label2" :placeholder="item.label"
206
+ class="border-none bg-transparent" :class="$style.columnTextbox"
207
+ item-class="p-1 px-0" />
143
208
  </div>
144
- <Textbox v-model="item.label2" :placeholder="item.label"
145
- class="border-none bg-transparent" :class="$style.columnTextbox"
146
- item-class="p-1 px-0" />
147
209
  </div>
148
- </div>
149
- </template>
150
- </ListItem>
210
+ </template>
211
+ </ListItem>
212
+ </div>
151
213
  </div>
152
214
 
153
- <div v-else-if="config.presetBarTabIndex === 2" class="flex-1 flex flex-col p-5">
215
+ <div v-else-if="configParams.presetBarTabIndex === 2" class="flex-1 flex flex-col p-5 overflow-y-auto">
154
216
 
155
217
  <div class="flex-1 flex flex-col gap-6">
156
218
 
@@ -159,20 +221,22 @@
159
221
  <div class="flex flex-row items-start">
160
222
  <Checkbox v-model="filter.enabled" :default="true" @change="apply" />
161
223
  <div class="flex-1 flex flex-col gap-3">
162
- <div class="flex-1 flex flex-row gap-2">
163
- <strong class="flex-1 cursor-pointer" @click="filter._collapsed = !filter._collapsed">
224
+ <div class="flex-1 flex flex-row items-center gap-2">
225
+ <strong class="flex-1 cursor-pointer whitespace-nowrap overflow-hidden text-ellipsis" @click="filter._collapsed = !filter._collapsed">
164
226
  <svg class="inline fill-text transition-transform relative top-[-1px]"
165
227
  :class="filter._collapsed === true ? `` : `rotate-90`"
166
228
  width="11" height="11" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M118.6 105.4l128 127.1C252.9 239.6 256 247.8 256 255.1s-3.125 16.38-9.375 22.63l-128 127.1c-9.156 9.156-22.91 11.9-34.88 6.943S64 396.9 64 383.1V128c0-12.94 7.781-24.62 19.75-29.58S109.5 96.23 118.6 105.4z"/></svg>
167
229
  {{ column(filter.key).label ?? filter.key }}
168
230
  </strong>
169
- <select v-if="filter.value.length > 1"
170
- v-model="filter.modifier"
171
- class="appearance-none bg-text-50 min-w-[60px] text-text-400 px-2 outline-none"
172
- @change="apply()">
173
- <option value="and">And</option>
174
- <option value="or">Or</option>
175
- </select>
231
+ <div>
232
+ <select v-if="filter.value.length > 1"
233
+ v-model="filter.modifier"
234
+ class="appearance-none bg-text-50 min-w-[40px] text-text-400 px-2 outline-none"
235
+ @change="apply()">
236
+ <option value="and">And</option>
237
+ <option value="or">Or</option>
238
+ </select>
239
+ </div>
176
240
  <button v-if="typeOf(column(filter.key).type) !== 'enum' && filter._collapsed !== true" type="button" @click="filter.value.push({})">
177
241
  <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M432 256C432 269.3 421.3 280 408 280h-160v160c0 13.25-10.75 24.01-24 24.01S200 453.3 200 440v-160h-160c-13.25 0-24-10.74-24-23.99C16 242.8 26.75 232 40 232h160v-160c0-13.25 10.75-23.99 24-23.99S248 58.75 248 72v160h160C421.3 232 432 242.8 432 256z"/></svg>
178
242
  </button>
@@ -180,11 +244,12 @@
180
244
  <svg width="14" height="14" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M193.94 256L296.5 153.44l21.15-21.15c3.12-3.12 3.12-8.19 0-11.31l-22.63-22.63c-3.12-3.12-8.19-3.12-11.31 0L160 222.06 36.29 98.34c-3.12-3.12-8.19-3.12-11.31 0L2.34 120.97c-3.12 3.12-3.12 8.19 0 11.31L126.06 256 2.34 379.71c-3.12 3.12-3.12 8.19 0 11.31l22.63 22.63c3.12 3.12 8.19 3.12 11.31 0L160 289.94 262.56 392.5l21.15 21.15c3.12 3.12 8.19 3.12 11.31 0l22.63-22.63c3.12-3.12 3.12-8.19 0-11.31L193.94 256z"/></svg>
181
245
  </button>
182
246
  </div>
183
- <div v-if="filter._collapsed !== true">
247
+ <div v-if="filter._collapsed !== true" class="flex flex-col">
184
248
  <div v-if="Array.isArray(filter.value)" class="flex flex-col gap-2">
185
249
  <div class="flex flex-row" v-for="(filterVal, filterIdx) in filter.value">
186
250
  <PresetSelectorFilterItem
187
251
  class="flex-1"
252
+ :enabled="filter.enabled"
188
253
  :column="column(filter.key)"
189
254
  :type="typeOf(column(filter.key).type)"
190
255
  :typeParams="typeParamsOf(column(filter.key))"
@@ -200,12 +265,6 @@
200
265
  </button>
201
266
  </div>
202
267
  </div>
203
- <PresetSelectorFilterItem v-else
204
- :column="column(filter.key)"
205
- :type="typeOf(column(filter.key).type)"
206
- :value="filter"
207
- :enumCache="enumCache"
208
- @change="apply()" />
209
268
  </div>
210
269
  </div>
211
270
  </div>
@@ -223,12 +282,12 @@
223
282
 
224
283
  </div>
225
284
 
226
- <div v-else-if="config.presetBarTabIndex === 3" class="flex-1 flex flex-col p-5">
285
+ <div v-else-if="configParams.presetBarTabIndex === 3" class="flex-1 flex flex-col p-5 overflow-y-auto">
227
286
 
228
287
  <ListItem v-if="Array.isArray(preset.sorts) && preset.sorts.length > 0"
229
288
  :items="preset.sorts"
230
289
  @reorder="(from, to) => { preset.sorts.splice(to, 0, preset.sorts.splice(from, 1)[0]); apply() }"
231
- container-class="flex flex-col rounded-lg border-[1px] border-text-50 bg-base-300 divide-y divide-text-50">
290
+ container-class="flex flex-col rounded-lg">
232
291
  <template v-slot="{ item, index }">
233
292
  <div class="flex flex-row items-center gap-3 p-1">
234
293
  <div data-reorder>
@@ -274,7 +333,7 @@
274
333
 
275
334
  </div>
276
335
 
277
- <div v-else-if="config.presetBarTabIndex === 4" class="flex-1 flex flex-col gap-6 p-6">
336
+ <div v-else-if="configParams.presetBarTabIndex === 4" class="flex-1 flex flex-col gap-6 p-6 overflow-y-auto">
278
337
 
279
338
  <div>
280
339
  <label>Select Type:</label>
@@ -309,7 +368,7 @@
309
368
  </button>
310
369
  </div>
311
370
  <ListItem :items="xAxis"
312
- class="mt-2 h-[90px] border-[1px] border-text-200 bg-base-400 rounded-lg p-1"
371
+ class="mt-2 h-[90px] border-[1px] border-border-200 bg-base-400 rounded-lg p-1"
313
372
  body-class="flex flex-col gap-1"
314
373
  @reorder="(from, to) => { xAxis.splice(to, 0, xAxis.splice(from, 1)[0]); }">
315
374
  <template v-slot="{ item, index }">
@@ -350,7 +409,7 @@
350
409
  </button>
351
410
  </div>
352
411
  <ListItem :items="yAxis"
353
- class="mt-2 h-[90px] border-[1px] border-text-200 bg-base-400 rounded-lg p-1"
412
+ class="mt-2 h-[90px] border-[1px] border-border-200 bg-base-400 rounded-lg p-1"
354
413
  body-class="flex flex-col gap-1"
355
414
  @reorder="(from, to) => { yAxis.splice(to, 0, yAxis.splice(from, 1)[0]); }">
356
415
  <template v-slot="{ item, index }">
@@ -401,7 +460,7 @@
401
460
  </button>
402
461
  </div>
403
462
  <ListItem :items="yAxis"
404
- class="mt-2 h-[90px] border-[1px] border-text-200 bg-base-400 rounded-lg p-0.5"
463
+ class="mt-2 h-[90px] border-[1px] border-border-200 bg-base-400 rounded-lg p-0.5"
405
464
  body-class="flex flex-col gap-1"
406
465
  @reorder="(from, to) => { yAxis.splice(to, 0, yAxis.splice(from, 1)[0]); }">
407
466
  <template v-slot="{ item, index }">
@@ -433,7 +492,7 @@
433
492
  </button>
434
493
  </div>
435
494
  <ListItem :items="xAxis"
436
- class="mt-2 h-[90px] border-[1px] border-text-200 bg-base-400 rounded-lg p-0.5"
495
+ class="mt-2 h-[90px] border-[1px] border-border-200 bg-base-400 rounded-lg p-0.5"
437
496
  body-class="flex flex-col gap-1"
438
497
  @reorder="(from, to) => { xAxis.splice(to, 0, xAxis.splice(from, 1)[0]); }">
439
498
  <template v-slot="{ item, index }">
@@ -491,37 +550,46 @@
491
550
 
492
551
  </div>
493
552
 
494
- <div v-else-if="config.presetBarTabIndex === 5" class="flex-1 p-6">
553
+ <div v-else-if="configParams.presetBarTabIndex === 5" class="flex-1 p-6 flex overflow-y-auto">
495
554
 
496
- <PresetBarPivot :pivot="presetPivot" :columns="pivotColumns" @apply="apply"/>
555
+ <PresetBarPivot :pivot="presetPivot" :columns="pivotColumns" class="flex-1" @apply="apply"/>
497
556
 
498
557
  </div>
499
558
 
500
- <div v-else-if="config.presetBarTabIndex === 6" class="flex-1 p-6">
559
+ <div v-else-if="configParams.presetBarTabIndex === 6" class="flex-1 p-6">
560
+
561
+ <div class="flex flex-row gap-2">
562
+ <label class="flex-1">Sharing</label>
563
+ <button class="text-primary" type="button"
564
+ @click="$refs.sharingModal.open([], { callback:addSharing })">
565
+ Share
566
+ </button>
501
567
 
568
+ <SharingModal ref="sharingModal" :src="sharingSrc"/>
569
+ </div>
502
570
  <div class="flex flex-col gap-1 mt-2">
503
- <div v-for="(user, index) in preset.sharing"
571
+ <div v-for="(item, index) in preset.shared"
504
572
  class="bg-base-500 hover:bg-text-50 p-3 rounded-lg flex flex-row gap-2 items-center gap-1">
505
573
  <div class="flex-1 flex flex-row items-center cursor-default gap-2">
506
- <svg width="14" height="14" class="fill-text-200" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M224 256c70.7 0 128-57.31 128-128s-57.3-128-128-128C153.3 0 96 57.31 96 128S153.3 256 224 256zM274.7 304H173.3C77.61 304 0 381.6 0 477.3c0 19.14 15.52 34.67 34.66 34.67h378.7C432.5 512 448 496.5 448 477.3C448 381.6 370.4 304 274.7 304z"/></svg>
507
- {{ user.name }}
574
+ <svg class="fill-text-200" height="14" viewBox="0 0 448 512" width="14"
575
+ xmlns="http://www.w3.org/2000/svg">
576
+ <!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
577
+ <path
578
+ d="M224 256c70.7 0 128-57.31 128-128s-57.3-128-128-128C153.3 0 96 57.31 96 128S153.3 256 224 256zM274.7 304H173.3C77.61 304 0 381.6 0 477.3c0 19.14 15.52 34.67 34.66 34.67h378.7C432.5 512 448 496.5 448 477.3C448 381.6 370.4 304 274.7 304z"/>
579
+ </svg>
580
+ {{ item.user?.name ?? item.userId }}
508
581
  </div>
509
- <button type="button" @click="removeSharing(index)">
510
- <svg width="14" height="14" class="fill-text-300 hover:fill-red-600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>
582
+ <button type="button" @click="removeSharing(item, index)">
583
+ <svg class="fill-text-300 hover:fill-red-600" height="14" viewBox="0 0 320 512"
584
+ width="14" xmlns="http://www.w3.org/2000/svg">
585
+ <!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
586
+ <path
587
+ d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/>
588
+ </svg>
511
589
  </button>
512
590
  </div>
513
591
  </div>
514
592
 
515
- <div class="flex justify-center p-5">
516
- <button type="button" class="text-primary flex flex-row items-center"
517
- @click="$refs.sharingModal.open([], { callback:addSharing })">
518
- <svg width="14" height="14" class="fill-primary inline mr-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M432 256c0 17.69-14.33 32.01-32 32.01H256v144c0 17.69-14.33 31.99-32 31.99s-32-14.3-32-31.99v-144H48c-17.67 0-32-14.32-32-32.01s14.33-31.99 32-31.99H192v-144c0-17.69 14.33-32.01 32-32.01s32 14.32 32 32.01v144h144C417.7 224 432 238.3 432 256z"/></svg>
519
- Share...
520
- </button>
521
- </div>
522
-
523
- <SharingModal ref="sharingModal" :src="sharingSrc" />
524
-
525
593
  </div>
526
594
 
527
595
  </div>
@@ -539,31 +607,31 @@
539
607
 
540
608
  import PresetSelectorFilterItem from "../components/PresetSelectorFilterItem.vue";
541
609
  import PresetBarPivot from "./PresetBarPivot.vue";
542
- import {getPresetUid} from "../utils/preset-selector.mjs";
543
610
  import SharingModal from "./Dashboard/SharingModal.vue";
611
+ import {getPresetUid} from "../utils/preset-selector.mjs";
544
612
 
545
613
  export default{
546
614
 
547
615
  components: {SharingModal, PresetBarPivot, PresetSelectorFilterItem},
548
616
 
549
- emits: [ 'apply', 'duplicate', 'remove', 'remove-shared' ],
617
+ emits: [ 'apply' ],
550
618
 
551
- inject: [ 'appStyle', 'confirm' ],
619
+ inject: [ 'alert', 'appStyle', 'confirm', 'load', 'socket' ],
552
620
 
553
621
  props: {
554
622
 
555
- canShare: Boolean,
556
-
557
623
  config: Object,
558
624
 
559
- presets: Array,
625
+ controller: String,
560
626
 
561
- sharedPresets: Array,
627
+ presetKey: String,
562
628
 
563
- sharingSrc: String,
564
- removeSharingSrc: String,
629
+ enumCache: Object,
565
630
 
566
- enumCache: Object
631
+ useAssistant: {
632
+ type: undefined,
633
+ default: false
634
+ }
567
635
 
568
636
  },
569
637
 
@@ -576,6 +644,40 @@ export default{
576
644
  this.apply()
577
645
  },
578
646
 
647
+ addSharing(item) {
648
+ const obj = {
649
+ key: this.presetKey,
650
+ presetUid: this.preset.uid,
651
+ userId: item.id
652
+ }
653
+
654
+ this.socket.send(`${this.controller}.add-sharing`, obj)
655
+ .then(newItem => {
656
+ if (!Array.isArray(this.preset.shared))
657
+ this.preset.shared = []
658
+ this.$util.push(this.preset.shared, newItem, {key: "presetUid"})
659
+ })
660
+ },
661
+
662
+ removeSharing(item, index) {
663
+ this.confirm('Remove shared?', () => {
664
+ this.socket.send(`${this.controller}.remove-sharing`, item)
665
+ .then(_ => {
666
+ this.preset.shared.splice(index, 1)
667
+ })
668
+ })
669
+ },
670
+
671
+ removeShared(item, index) {
672
+ this.confirm('Remove shared?', () => {
673
+ this.socket.send(`${this.controller}.remove-sharing`, item.UserConfigPresetShared)
674
+ .then(_ => {
675
+ this.config.sharedPresets.splice(index, 1)
676
+ this.configParams.presetIdx = this.config.presets[0].uid
677
+ })
678
+ })
679
+ },
680
+
579
681
  addSort(obj){
580
682
  if(!Array.isArray(this.preset.sorts))
581
683
  this.preset.sorts = []
@@ -592,7 +694,7 @@ export default{
592
694
  canApply(){
593
695
 
594
696
  if(this.preset){
595
- if(this.config.presetBarTabIndex === 2){
697
+ if(this.configParams.presetBarTabIndex === 2){
596
698
  return true
597
699
  /*if(Array.isArray(this.preset.filters)){
598
700
  if(this.preset.filters.filter(_ => !_.key).length > 0){
@@ -600,14 +702,14 @@ export default{
600
702
  }
601
703
  }*/
602
704
  }
603
- else if(this.config.presetBarTabIndex === 3){
705
+ else if(this.configParams.presetBarTabIndex === 3){
604
706
  if(Array.isArray(this.preset.sorts)){
605
707
  if(this.preset.sorts.filter(_ => !_.key).length > 0){
606
708
  return false
607
709
  }
608
710
  }
609
711
  }
610
- else if(this.config.presetBarTabIndex === 4){
712
+ else if(this.configParams.presetBarTabIndex === 4){
611
713
  if(Array.isArray(this.chartOpt.xAxis)){
612
714
  if(this.chartOpt.xAxis.filter(_ => !_.key).length > 0){
613
715
  return false
@@ -629,67 +731,76 @@ export default{
629
731
  return this.preset.columns.filter(_ => _.key === key).pop() ?? {}
630
732
  },
631
733
 
632
- duplicate(preset){
633
- const uid = getPresetUid()
734
+ generatePreset(){
735
+ if(!this.generateText) return
634
736
 
635
- let name = preset.name.substring(0, preset.name.indexOf(' (Copy') > -1 ? preset.name.indexOf(' (Copy') : preset.name.length)
636
- for(let i = 1 ; i < 100 ; i++){
637
- const curName = `${name} (Copy${i > 1 ? ' ' + i : ''})`
638
- if(this.presets.findIndex(_ => _.name === curName) < 0){
639
- name = curName
640
- break
641
- }
642
- }
737
+ this.$refs.generateBtn.setState(2)
738
+ this.socket.send(`${this.controller}.prompt-ai-assistance`, {
739
+ text: this.generateText
740
+ })
741
+ .then(preset => {
742
+
743
+ /*preset = {
744
+ columns: [
745
+ { key: 'code', label: 'Kode' },
746
+ { key: 'loginCode', label: 'NIP' },
747
+ { key: 'bertemuDengan', label: 'Bertemu Dengan' }
748
+ ],
749
+ filters: [
750
+ {
751
+ key: 'createdAt',
752
+ value: [ { operator: '=', value: [ '2024-07-05' ] } ]
753
+ }
754
+ ]
755
+ }*/
756
+
757
+ preset.uid = 'ai-assistant'
758
+ preset.name = !preset.name ? 'AI Assistant' : preset.name
759
+
760
+ let index = this.config.presets.findIndex(_ => _.uid === preset.uid)
761
+ if(index < 0){
762
+ this.config.presets.push(preset)
763
+ }
764
+ else {
765
+ Object.assign(this.config.presets[index], preset)
766
+ this.load()
767
+ }
643
768
 
644
- const newPreset = {
645
- ...JSON.parse(JSON.stringify(preset)),
646
- name,
647
- uid
648
- }
769
+ this.configParams.presetIdx = preset.uid
649
770
 
650
- this.presets.push(newPreset)
771
+ })
772
+ .catch(err => this.alert(err))
773
+ .finally(_ => this.$refs.generateBtn?.resetState())
774
+ },
651
775
 
652
- this.$emit('duplicate', preset)
776
+ duplicate(item){
777
+ const newItem = JSON.parse(JSON.stringify(item))
778
+ newItem.name = `${item.name} (Copy)`
779
+ newItem.uid = getPresetUid()
653
780
 
654
- this.$nextTick(() => this.select(newPreset.uid))
781
+ this.config.presets.push(newItem)
782
+ this.configParams.presetIdx = newItem.uid
655
783
  },
656
784
 
657
- remove(uid){
658
- if(this.presets.length > 1){
785
+ remove(item){
786
+ if(this.config.presets.length > 1){
659
787
  this.confirm('Remove this preset?', () => {
660
- const index = this.presets.findIndex(_ => _.uid === uid)
661
- const [ removed ] = this.presets.splice(index, 1)
662
- this.$emit('remove', removed)
663
-
664
- const nextIndex = index - 1 >= 0 ? index - 1 : 0
665
- this.config.presetIdx = this.presets[nextIndex].uid
788
+ this.config.presets.splice(this.config.presets.findIndex(_ => _.uid === item.uid), 1)
666
789
  })
667
790
  }
668
791
  },
669
792
 
670
- removeShared(uid){
671
- this.$emit('remove-shared', uid)
672
- },
673
-
674
- addSharing(item){
675
- if(!Array.isArray(this.preset.sharing))
676
- this.preset.sharing = []
677
-
678
- this.$util.push(this.preset.sharing, item, { key:"id" })
679
- },
680
-
681
- removeSharing(index){
682
- this.preset.sharing.splice(index, 1)
683
- },
684
-
685
- select(uid){
686
- this.config.presetIdx = uid
793
+ select(item){
687
794
  this.presetBar.view = 2
688
- this.apply()
795
+
796
+ if(this.configParams.presetIdx !== item.uid){
797
+ this.configParams.presetIdx = item.uid
798
+ this.apply()
799
+ }
689
800
  },
690
801
 
691
802
  deselect(){
692
- this.config.presetBar.view = 1
803
+ this.presetBar.view = 1
693
804
  },
694
805
 
695
806
  filterColumnAdded(column){
@@ -701,7 +812,7 @@ export default{
701
812
  return 'boolean'
702
813
  else if([ 'date' ].includes(type))
703
814
  return 'date'
704
- else if([ 'number' ].includes(type))
815
+ else if([ 'number', 'currency', 'decimal', 'double', 'float', 'integer' ].includes(type))
705
816
  return 'number'
706
817
  else if([ 'enum' ].includes(type))
707
818
  return 'enum'
@@ -732,6 +843,18 @@ export default{
732
843
  return this.presetChart[this.chartType]
733
844
  },
734
845
 
846
+ configParams(){
847
+ if(!this.config.params)
848
+ this.config.params = {}
849
+
850
+ if(this.config.presets.length > 0 &&
851
+ (!this.config.params.presetIdx ||
852
+ !this.config.presets.find(_ => _.uid === this.config.params.presetIdx)))
853
+ this.config.params.presetIdx = this.config.presets[0].uid
854
+
855
+ return this.config.params
856
+ },
857
+
735
858
  filterColumns(){
736
859
  return this.config.columns.filter(_ => {
737
860
  return _.filterable !== false
@@ -745,7 +868,8 @@ export default{
745
868
  },
746
869
 
747
870
  preset(){
748
- return this.presets.find(_ => _.uid === this.config.presetIdx)
871
+ return this.config.presets.find(_ => _.uid === this.configParams.presetIdx) ??
872
+ this.config.sharedPresets.find(_ => _.uid === this.configParams.presetIdx)
749
873
  },
750
874
 
751
875
  presetChart(){
@@ -761,6 +885,12 @@ export default{
761
885
  this.preset.columns = JSON.parse(JSON.stringify(this.config.columns))
762
886
  }
763
887
 
888
+ if(this.configParams.columnSearchKey){
889
+ return this.preset.columns.filter(_ => {
890
+ return _.label.toLowerCase().includes(this.configParams.columnSearchKey.toLowerCase()) ||
891
+ _.key.toLowerCase().includes(this.configParams.columnSearchKey.toLowerCase())
892
+ })
893
+ }
764
894
  return this.preset.columns
765
895
  },
766
896
 
@@ -771,8 +901,10 @@ export default{
771
901
  return this.preset.pivot
772
902
  },
773
903
 
904
+ sharingSrc(){ return `${this.controller}.load-sharing` },
905
+
774
906
  sortColumns(){
775
- return this.presetColumns.filter(_ => _.key && !_.key.startsWith('_'))
907
+ return this.presetColumns.filter(_ => _.key && !_.key.startsWith('_') && (_.sortable ?? false) !== false)
776
908
  },
777
909
 
778
910
  xAxis(){
@@ -790,12 +922,16 @@ export default{
790
922
  },
791
923
 
792
924
  presetBar(){
793
- if(!this.config.presetBar || !this.config.presetBar.view)
794
- this.config.presetBar = {
925
+ if(!this.configParams.presetBar || !this.configParams.presetBar.view)
926
+ this.configParams.presetBar = {
795
927
  view: 2
796
928
  }
797
929
 
798
- return this.config.presetBar
930
+ return this.configParams.presetBar
931
+ },
932
+
933
+ canGenerate(){
934
+ return this.generateText.length > 0
799
935
  }
800
936
 
801
937
  },
@@ -808,19 +944,20 @@ export default{
808
944
  ...((this.config ?? {}).filters !== false ? [{ text:'Filters', value:2 }] : []),
809
945
  ...((this.config ?? {}).sorts !== false ? [{ text:'Sorts', value:3 }] : []),
810
946
  ...((this.config ?? {}).pivot !== false ? [{ text:'Pivot', value:5 }] : []),
811
- ...(this.canShare ? [{ text:'Sharing', value:6 }] : [])
947
+ ...(this.controller && (this.config ?? {}).sharing !== false ? [{ text:'Sharing', value:6 }] : []),
812
948
  ],
813
949
  chart: [
814
950
  ...((this.config ?? {}).filters !== false ? [{ text:'Filters', value:2 }] : []),
815
951
  ...((this.config ?? {}).chart !== false ? [{ text:'Chart', value:4 }] : []),
816
952
  ]
817
953
  },
954
+ generateText: 'List kunjungan tgl 5 juli, hanya kolom kode, nip kolektor dan bertemu dengan'
818
955
  }
819
956
  },
820
957
 
821
958
  mounted() {
822
- if(!this.config.presetBarTabIndex){
823
- this.config.presetBarTabIndex = this.config.type === 'chart' ? 4 : 1
959
+ if(!this.configParams.presetBarTabIndex){
960
+ this.configParams.presetBarTabIndex = this.config.type === 'chart' ? 4 : 1
824
961
  }
825
962
  }
826
963
 
@@ -831,11 +968,23 @@ export default{
831
968
  <style module>
832
969
 
833
970
  .comp{
834
- @apply flex flex-col relative;
971
+ @apply flex flex-col relative bg-base-400;
972
+ }
973
+
974
+ .presetBtn{
975
+ @apply flex flex-row items-center gap-3 px-3 p-2 hover:bg-text-50;
976
+ }
977
+
978
+ .presetOptBtn{
979
+ @apply pl-2 hidden
980
+ }
981
+ .presetBtn:hover .presetOptBtn{
982
+ @apply flex;
835
983
  }
836
984
 
837
985
  .columnTextbox input::placeholder{
838
- @apply text-text;
986
+ @apply text-text-500;
839
987
  }
840
988
 
989
+
841
990
  </style>