@mixd-id/web-scaffold 0.1.230406043 → 0.1.230406044

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mixd-id/web-scaffold",
3
3
  "private": false,
4
- "version": "0.1.230406043",
4
+ "version": "0.1.230406044",
5
5
  "scripts": {
6
6
  "dev": "vite serve",
7
7
  "build": "vite build",
@@ -1,57 +1,71 @@
1
1
  <template>
2
- <div :class="$style.comp" v-if="true || configLoaded">
2
+ <div :class="$style.comp" v-if="configLoaded">
3
3
 
4
4
  <slot v-if="$slots.head" name="head"></slot>
5
5
  <div v-else class="flex flex-row items-center gap-4">
6
- <div class="flex flex-row gap-1">
7
- <button type="button" class="flex flex-row gap-1 items-center">
8
- <h3>{{ title }}</h3>
9
- <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"/></svg>
10
- </button>
11
- <button type="button" @click="$refs.setting.open()">
12
- <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M452.515 237l31.843-18.382c9.426-5.441 13.996-16.542 11.177-27.054-11.404-42.531-33.842-80.547-64.058-110.797-7.68-7.688-19.575-9.246-28.985-3.811l-31.785 18.358a196.276 196.276 0 0 0-32.899-19.02V39.541a24.016 24.016 0 0 0-17.842-23.206c-41.761-11.107-86.117-11.121-127.93-.001-10.519 2.798-17.844 12.321-17.844 23.206v36.753a196.276 196.276 0 0 0-32.899 19.02l-31.785-18.358c-9.41-5.435-21.305-3.877-28.985 3.811-30.216 30.25-52.654 68.265-64.058 110.797-2.819 10.512 1.751 21.613 11.177 27.054L59.485 237a197.715 197.715 0 0 0 0 37.999l-31.843 18.382c-9.426 5.441-13.996 16.542-11.177 27.054 11.404 42.531 33.842 80.547 64.058 110.797 7.68 7.688 19.575 9.246 28.985 3.811l31.785-18.358a196.202 196.202 0 0 0 32.899 19.019v36.753a24.016 24.016 0 0 0 17.842 23.206c41.761 11.107 86.117 11.122 127.93.001 10.519-2.798 17.844-12.321 17.844-23.206v-36.753a196.34 196.34 0 0 0 32.899-19.019l31.785 18.358c9.41 5.435 21.305 3.877 28.985-3.811 30.216-30.25 52.654-68.266 64.058-110.797 2.819-10.512-1.751-21.613-11.177-27.054L452.515 275c1.22-12.65 1.22-25.35 0-38zm-52.679 63.019l43.819 25.289a200.138 200.138 0 0 1-33.849 58.528l-43.829-25.309c-31.984 27.397-36.659 30.077-76.168 44.029v50.599a200.917 200.917 0 0 1-67.618 0v-50.599c-39.504-13.95-44.196-16.642-76.168-44.029l-43.829 25.309a200.15 200.15 0 0 1-33.849-58.528l43.819-25.289c-7.63-41.299-7.634-46.719 0-88.038l-43.819-25.289c7.85-21.229 19.31-41.049 33.849-58.529l43.829 25.309c31.984-27.397 36.66-30.078 76.168-44.029V58.845a200.917 200.917 0 0 1 67.618 0v50.599c39.504 13.95 44.196 16.642 76.168 44.029l43.829-25.309a200.143 200.143 0 0 1 33.849 58.529l-43.819 25.289c7.631 41.3 7.634 46.718 0 88.037zM256 160c-52.935 0-96 43.065-96 96s43.065 96 96 96 96-43.065 96-96-43.065-96-96-96zm0 144c-26.468 0-48-21.532-48-48 0-26.467 21.532-48 48-48s48 21.533 48 48c0 26.468-21.532 48-48 48z"/></svg>
13
- </button>
14
-
15
- <Modal ref="setting" width="680" height="560">
16
- <template #head>
17
- <div class="relative">
18
- <div class="absolute top-0 right-0 p-2">
19
- <button type="button" class="p-2" @click="$refs.setting.close()">
20
- <svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
21
- <path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
22
- </svg>
23
- </button>
24
- </div>
25
- </div>
26
- </template>
27
- <ListViewSettings class="flex-1"
28
- :config="config"
29
- @change="load" />
30
- </Modal>
6
+ <div class="flex-1 flex flex-row gap-4">
7
+ <button type="button" ref="presetSelectorBtn"
8
+ class="flex flex-row gap-1 items-center"
9
+ @click="$refs.presetSelector.open($refs.presetSelectorBtn)">
10
+ <h3>{{ preset.name }}</h3>
11
+ <svg width="16" height="16" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"/></svg>
12
+ </button>
13
+ <button type="button" @click="openPreset()">
14
+ <svg width="19" height="19" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M452.515 237l31.843-18.382c9.426-5.441 13.996-16.542 11.177-27.054-11.404-42.531-33.842-80.547-64.058-110.797-7.68-7.688-19.575-9.246-28.985-3.811l-31.785 18.358a196.276 196.276 0 0 0-32.899-19.02V39.541a24.016 24.016 0 0 0-17.842-23.206c-41.761-11.107-86.117-11.121-127.93-.001-10.519 2.798-17.844 12.321-17.844 23.206v36.753a196.276 196.276 0 0 0-32.899 19.02l-31.785-18.358c-9.41-5.435-21.305-3.877-28.985 3.811-30.216 30.25-52.654 68.265-64.058 110.797-2.819 10.512 1.751 21.613 11.177 27.054L59.485 237a197.715 197.715 0 0 0 0 37.999l-31.843 18.382c-9.426 5.441-13.996 16.542-11.177 27.054 11.404 42.531 33.842 80.547 64.058 110.797 7.68 7.688 19.575 9.246 28.985 3.811l31.785-18.358a196.202 196.202 0 0 0 32.899 19.019v36.753a24.016 24.016 0 0 0 17.842 23.206c41.761 11.107 86.117 11.122 127.93.001 10.519-2.798 17.844-12.321 17.844-23.206v-36.753a196.34 196.34 0 0 0 32.899-19.019l31.785 18.358c9.41 5.435 21.305 3.877 28.985-3.811 30.216-30.25 52.654-68.266 64.058-110.797 2.819-10.512-1.751-21.613-11.177-27.054L452.515 275c1.22-12.65 1.22-25.35 0-38zm-52.679 63.019l43.819 25.289a200.138 200.138 0 0 1-33.849 58.528l-43.829-25.309c-31.984 27.397-36.659 30.077-76.168 44.029v50.599a200.917 200.917 0 0 1-67.618 0v-50.599c-39.504-13.95-44.196-16.642-76.168-44.029l-43.829 25.309a200.15 200.15 0 0 1-33.849-58.528l43.819-25.289c-7.63-41.299-7.634-46.719 0-88.038l-43.819-25.289c7.85-21.229 19.31-41.049 33.849-58.529l43.829 25.309c31.984-27.397 36.66-30.078 76.168-44.029V58.845a200.917 200.917 0 0 1 67.618 0v50.599c39.504 13.95 44.196 16.642 76.168 44.029l43.829-25.309a200.143 200.143 0 0 1 33.849 58.529l-43.819 25.289c7.631 41.3 7.634 46.718 0 88.037zM256 160c-52.935 0-96 43.065-96 96s43.065 96 96 96 96-43.065 96-96-43.065-96-96-96zm0 144c-26.468 0-48-21.532-48-48 0-26.467 21.532-48 48-48s48 21.533 48 48c0 26.468-21.532 48-48 48z"/></svg>
15
+ </button>
16
+
17
+ <ContextMenu ref="presetSelector">
18
+ <div class="flex-1 flex flex-col w-[270px]">
19
+ <button type="button" v-for="(preset, idx) in config.presets"
20
+ class="p-3 text-left hover:bg-primary hover:text-white"
21
+ @click="config.presetIdx = idx">
22
+ {{ preset.name }}
23
+ </button>
24
+ </div>
25
+ </ContextMenu>
26
+
27
+ <Modal ref="setting" width="680" height="560">
28
+ <template #head>
29
+ <div class="relative">
30
+ <div class="absolute top-0 right-0 p-2">
31
+ <button type="button" class="p-2" @click="$refs.setting.close()">
32
+ <svg width="24" height="24" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
33
+ <path d="M6.53034 5.46965C6.23745 5.17676 5.76257 5.17676 5.46968 5.46965C5.17679 5.76255 5.17679 6.23742 5.46968 6.53031L10.9393 12L5.46967 17.4697C5.17678 17.7626 5.17678 18.2374 5.46967 18.5303C5.76256 18.8232 6.23744 18.8232 6.53033 18.5303L12 13.0606L17.4697 18.5303C17.7626 18.8232 18.2375 18.8232 18.5303 18.5303C18.8232 18.2374 18.8232 17.7626 18.5303 17.4697L13.0607 12L18.5303 6.53032C18.8232 6.23743 18.8232 5.76256 18.5303 5.46966C18.2374 5.17677 17.7626 5.17677 17.4697 5.46966L12 10.9393L6.53034 5.46965Z"/>
34
+ </svg>
35
+ </button>
36
+ </div>
37
+ </div>
38
+ </template>
39
+ <template #foot>
40
+ <div class="p-6 py-4 border-t-[1px] border-text-50">
41
+ <Button class="w-[90px]" @click="applyPreset">Apply</Button>
42
+ </div>
43
+ </template>
44
+ <ListViewSettings ref="listviewSettings" class="flex-1"
45
+ :config="copiedConfig" />
46
+ </Modal>
31
47
  </div>
32
48
 
33
- <div class="flex-1">
34
- <slot name="headerOpt"></slot>
35
- </div>
49
+ <slot name="headerOpt"></slot>
36
50
 
37
51
  <Textbox :placeholder="$t('Search...')" :clearable="true" @clear="clearSearch" v-model="preset.search"
38
- @keyup.enter="load" :class="$style.searchBox">
39
- <template #start>
40
- <div class="pl-2">
41
- <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M508.5 481.6l-129-129c-2.3-2.3-5.3-3.5-8.5-3.5h-10.3C395 312 416 262.5 416 208 416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c54.5 0 104-21 141.1-55.2V371c0 3.2 1.3 6.2 3.5 8.5l129 129c4.7 4.7 12.3 4.7 17 0l9.9-9.9c4.7-4.7 4.7-12.3 0-17zM208 384c-97.3 0-176-78.7-176-176S110.7 32 208 32s176 78.7 176 176-78.7 176-176 176z"/></svg>
42
- </div>
43
- </template>
52
+ @keyup.enter="load" :class="$style.searchBox">
53
+ <template #start>
54
+ <div class="pl-2">
55
+ <svg width="14" height="14" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M508.5 481.6l-129-129c-2.3-2.3-5.3-3.5-8.5-3.5h-10.3C395 312 416 262.5 416 208 416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c54.5 0 104-21 141.1-55.2V371c0 3.2 1.3 6.2 3.5 8.5l129 129c4.7 4.7 12.3 4.7 17 0l9.9-9.9c4.7-4.7 4.7-12.3 0-17zM208 384c-97.3 0-176-78.7-176-176S110.7 32 208 32s176 78.7 176 176-78.7 176-176 176z"/></svg>
56
+ </div>
57
+ </template>
44
58
  </Textbox>
45
59
  </div>
46
60
 
47
61
  <VirtualTable ref="table1" :columns="presetColumns" :items="items" class="flex-1"
48
- @scroll-end="loadNext">
62
+ @scroll-end="loadNext">
49
63
  <template v-for="column in presetColumns" #[colOf(column.key)]="{}">
50
64
  <div :class="getHeader(column)" @click="openColumnOptions(column.key, $event.target.closest('.' + $style.header))">
51
65
  <div>
52
66
  {{ column.label ?? column.key }}
53
67
  </div>
54
- <div class="absolute top-0 right-0 p-2 bg-base-500" v-if="false">
68
+ <div class="absolute top-0 right-0 p-2 bg-base-500" v-if="presetSortedColumns[column.key] === 'asc'">
55
69
  <svg width="19" height="19" viewBox="0 0 24 24" class="fill-text-400" xmlns="http://www.w3.org/2000/svg">
56
70
  <path d="M6.75 5C6.75 4.58579 6.41421 4.25 6 4.25C5.58579 4.25 5.25 4.58579 5.25 5V17.6893L3.53033 15.9697C3.23744 15.6768 2.76256 15.6768 2.46967 15.9697C2.17678 16.2626 2.17678 16.7374 2.46967 17.0303L4.76256 19.3232C5.44598 20.0066 6.55402 20.0066 7.23744 19.3232L9.53033 17.0303C9.82322 16.7374 9.82322 16.2626 9.53033 15.9697C9.23744 15.6768 8.76256 15.6768 8.46967 15.9697L6.75 17.6893V5Z"/>
57
71
  <path fill-rule="evenodd" clip-rule="evenodd" d="M12.25 17C12.25 17.4142 12.5858 17.75 13 17.75H21C21.4142 17.75 21.75 17.4142 21.75 17C21.75 16.5858 21.4142 16.25 21 16.25H13C12.5858 16.25 12.25 16.5858 12.25 17Z"/>
@@ -59,7 +73,7 @@
59
73
  <path fill-rule="evenodd" clip-rule="evenodd" d="M12.25 7C12.25 6.58579 12.5858 6.25 13 6.25H15C15.4142 6.25 15.75 6.58579 15.75 7C15.75 7.41421 15.4142 7.75 15 7.75H13C12.5858 7.75 12.25 7.41421 12.25 7Z"/>
60
74
  </svg>
61
75
  </div>
62
- <div class="absolute top-0 right-0 p-2 bg-base-500" v-else-if="false">
76
+ <div class="absolute top-0 right-0 p-2 bg-base-500" v-else-if="presetSortedColumns[column.key] === 'desc'">
63
77
  <svg width="19" height="19" viewBox="0 0 24 24" class="fill-text-400" xmlns="http://www.w3.org/2000/svg">
64
78
  <path d="M6.75 5C6.75 4.58579 6.41421 4.25 6 4.25C5.58579 4.25 5.25 4.58579 5.25 5V17.6893L3.53033 15.9697C3.23744 15.6768 2.76256 15.6768 2.46967 15.9697C2.17678 16.2626 2.17678 16.7374 2.46967 17.0303L4.76256 19.3232C5.44598 20.0066 6.55402 20.0066 7.23744 19.3232L9.53033 17.0303C9.82322 16.7374 9.82322 16.2626 9.53033 15.9697C9.23744 15.6768 8.76256 15.6768 8.46967 15.9697L6.75 17.6893V5Z"/>
65
79
  <path fill-rule="evenodd" clip-rule="evenodd" d="M12.25 7C12.25 6.58579 12.5858 6.25 13 6.25H21C21.4142 6.25 21.75 6.58579 21.75 7C21.75 7.41421 21.4142 7.75 21 7.75H13C12.5858 7.75 12.25 7.41421 12.25 7Z"/>
@@ -79,38 +93,38 @@
79
93
  </template>
80
94
  </VirtualTable>
81
95
 
82
- <ContextMenu ref="columnMenu" :dismiss="false">
83
- <div class="flex-1 flex flex-col w-[270px] p-3">
84
- <div class="flex flex-col">
85
- <div class="flex flex-row gap-2 items-center">
86
- <div class="p-2 text-text-300 flex-1">Sort By</div>
87
- <div class="text-primary cursor-pointer text-sm" @click="openPreset('sort');$refs.columnMenu.close()">Sort Options</div>
88
- </div>
89
- <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="setSortCurrent(1)">Sort Ascending</div>
90
- <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="setSortCurrent(2)">Sort Descending</div>
91
- </div>
92
- <div class="h-[1px] bg-text-50 my-2"></div>
93
- <div class="flex flex-col">
94
- <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="hide">Hide</div>
95
- <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="openPreset();$refs.columnMenu.close()">Column Options</div>
96
- </div>
97
- <div class="h-[1px] bg-text-50 my-2"></div>
98
- <div class="flex flex-col">
99
- <div class="flex flex-row gap-2 items-center">
100
- <div class="p-2 text-text-300 flex-1">Filters</div>
101
- <div class="text-primary cursor-pointer text-sm" @click="openPreset('filter');$refs.columnMenu.close()">Filter Options</div>
102
- </div>
103
- <div v-if="presetCurrentFilters.length > 0">
104
- <ListPage1Filter v-if="preset.filters" v-for="filter in presetCurrentFilters"
105
- :filter="filter" :column="config.columns[filter.key]"
106
- @remove="removeFilter(filter)" @change="load" />
107
- </div>
108
- <div v-else>
109
- <div class="p-2 cursor-pointer" :class="$style.hoverable" @click.stop="addCurrentFilter">Add Filter</div>
110
- </div>
111
- </div>
112
- </div>
113
- </ContextMenu>
96
+ <ContextMenu ref="columnMenu" :dismiss="false">
97
+ <div class="flex-1 flex flex-col w-[270px] p-3">
98
+ <div class="flex flex-col">
99
+ <div class="flex flex-row gap-2 items-center">
100
+ <div class="p-2 text-text-300 flex-1">Sort By</div>
101
+ <div class="text-primary cursor-pointer text-sm" @click="openPreset('sort');$refs.columnMenu.close()">Sort Options</div>
102
+ </div>
103
+ <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="setSortCurrent(1)">Sort Ascending</div>
104
+ <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="setSortCurrent(2)">Sort Descending</div>
105
+ </div>
106
+ <div class="h-[1px] bg-text-50 my-2"></div>
107
+ <div class="flex flex-col">
108
+ <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="hide">Hide</div>
109
+ <div class="p-2 cursor-pointer" :class="$style.hoverable" @click="openPreset();$refs.columnMenu.close()">Column Options</div>
110
+ </div>
111
+ <div class="h-[1px] bg-text-50 my-2"></div>
112
+ <div class="flex flex-col">
113
+ <div class="flex flex-row gap-2 items-center">
114
+ <div class="p-2 text-text-300 flex-1">Filters</div>
115
+ <div class="text-primary cursor-pointer text-sm" @click="openPreset('filter');$refs.columnMenu.close()">Filter Options</div>
116
+ </div>
117
+ <div v-if="presetCurrentFilters.length > 0">
118
+ <ListPage1Filter v-if="preset.filters" v-for="filter in presetCurrentFilters"
119
+ :filter="filter" :column="config.columns[filter.key]"
120
+ @remove="removeFilter(filter)" @change="load" />
121
+ </div>
122
+ <div v-else>
123
+ <div class="p-2 cursor-pointer" :class="$style.hoverable" @click.stop="addCurrentFilter">Add Filter</div>
124
+ </div>
125
+ </div>
126
+ </div>
127
+ </ContextMenu>
114
128
 
115
129
  </div>
116
130
  </template>
@@ -153,7 +167,7 @@ export default{
153
167
 
154
168
  addFilter(key){
155
169
 
156
- const column = this.config.columns[key]
170
+ const column = this.presetColumns.find((_) => _.key === key)
157
171
 
158
172
  if(!this.preset.filters){
159
173
  this.preset.filters = []
@@ -223,7 +237,6 @@ export default{
223
237
  .then((res) => {
224
238
  this.items.push(...res.items)
225
239
  this.hasNext = res.hasNext
226
- console.log('loadNext', this.$data)
227
240
  })
228
241
  .catch((err) => {
229
242
  this.toast(err)
@@ -245,8 +258,23 @@ export default{
245
258
  }
246
259
  },
247
260
 
261
+ loadSummary(){
262
+
263
+ if(!this.presetSummary) return
264
+
265
+ this.socketEmit2(`${this.computedDataSource}.load-summary`, {
266
+ preset: this.preset
267
+ })
268
+ .then((res) => {
269
+ const data = res && res.data ? res.data : res
270
+ this.summary = data
271
+ })
272
+ .catch((err) => {
273
+ this.toast(err)
274
+ })
275
+ },
276
+
248
277
  onHooks(model, event, items){
249
- console.log('onHooks', model, event, items)
250
278
  if(model === this.subscriptionObj.model){
251
279
  switch(event){
252
280
 
@@ -276,9 +304,23 @@ export default{
276
304
  },
277
305
 
278
306
  openPreset(tab){
307
+ if(!this.config.presetTab) this.config.presetTab = 'column'
308
+
309
+ this.copiedConfig = {
310
+ ...JSON.parse(JSON.stringify(this.config)),
311
+ presetTab: tab ?? this.config.presetTab
312
+ }
279
313
  this.$refs.setting.open()
280
314
  },
281
315
 
316
+ applyPreset(){
317
+ if(JSON.stringify(this.copiedConfig) !== JSON.stringify(this.config)){
318
+ Object.assign(this.config, this.copiedConfig)
319
+ this.load()
320
+ }
321
+ this.$refs.setting.close()
322
+ },
323
+
282
324
  removeFilter(filter){
283
325
  this.preset.filters.splice(this.preset.filters.indexOf(filter), 1)
284
326
  this.load()
@@ -288,7 +330,7 @@ export default{
288
330
  this.preset.sorts = [
289
331
  {
290
332
  key: this.selectedColumn,
291
- label: this.config.columns[this.selectedColumn].label,
333
+ label: this.presetColumns.find((_) => _.key === this.selectedColumn).label,
292
334
  type: sortType === 2 ? 'desc' : 'asc'
293
335
  }
294
336
  ]
@@ -371,17 +413,38 @@ export default{
371
413
  },
372
414
 
373
415
  presetColumns(){
374
- if(!this.preset.columns) return
375
-
376
- for(let i = 0 ; i < (this.preset.columns).length ; i++){
377
- const presetColumn = this.preset.columns[i]
378
- const column = this.config.columns[presetColumn.key] ?? {}
379
- for(let key in column){
380
- if(!presetColumn[key]){
381
- this.preset.columns[i][key] = column[key]
382
- }
416
+ if(!this.preset || !this.preset.columns) return []
417
+
418
+ const presetColumns = {}
419
+ this.preset.columns.forEach((column, _index) => {
420
+ presetColumns[column.key] = {
421
+ ...column,
422
+ _index
383
423
  }
384
- }
424
+ })
425
+
426
+ this.preset.columns = this.config.columns.map((column, index) => {
427
+ const _sort = {
428
+ index: presetColumns[column.key] ? presetColumns[column.key]._index : index,
429
+ isUser: !!presetColumns[column.key]
430
+ }
431
+
432
+ return {
433
+ ...column,
434
+ ...(presetColumns[column.key] ?? {}),
435
+ _sort
436
+ }
437
+ })
438
+ .sort((a, b) => {
439
+ if(a._sort.index < b._sort.index) return -1
440
+ if(a._sort.index > b._sort.index) return 1
441
+ return a._sort.isUser ? 1 : -1
442
+ })
443
+ .map((column) => {
444
+ delete column._sort
445
+ delete column._index
446
+ return column
447
+ })
385
448
 
386
449
  return this.preset.columns
387
450
  },
@@ -391,6 +454,12 @@ export default{
391
454
  return this.preset.filters.filter((_) => _.key === this.selectedColumn)
392
455
  },
393
456
 
457
+ presetSortedColumns(){
458
+ const c = {};
459
+ (this.preset.sorts ?? []).forEach((_) => c[_.key] = _.type);
460
+ return c
461
+ },
462
+
394
463
  },
395
464
 
396
465
  data(){
@@ -399,7 +468,8 @@ export default{
399
468
  hasNext: false,
400
469
  count: null,
401
470
  configLoaded: false,
402
- selectedColumn: null
471
+ selectedColumn: null,
472
+ copiedConfig: null
403
473
  }
404
474
  },
405
475
 
@@ -448,6 +518,10 @@ export default{
448
518
  @apply text-ellipsis whitespace-nowrap overflow-x-hidden;
449
519
  }
450
520
 
521
+ .headerSelected{
522
+ @apply border-primary;
523
+ }
524
+
451
525
  .searchBox{
452
526
  @apply w-[300px] max-w-[30%];
453
527
  }
@@ -2,21 +2,21 @@
2
2
  <div :class="styleComp">
3
3
  <div class="border-r-[1px] border-text-50 bg-base-400">
4
4
 
5
- <div class="p-6">
6
- <h3>Presets</h3>
7
- <br />
5
+ <div class="p-6 flex flex-row">
6
+ <h3 class="flex-1">Presets</h3>
7
+ <button type="button" @click="addPreset">
8
+ <svg width="21" height="21" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M376 232H216V72c0-4.42-3.58-8-8-8h-32c-4.42 0-8 3.58-8 8v160H8c-4.42 0-8 3.58-8 8v32c0 4.42 3.58 8 8 8h160v160c0 4.42 3.58 8 8 8h32c4.42 0 8-3.58 8-8V280h160c4.42 0 8-3.58 8-8v-32c0-4.42-3.58-8-8-8z"/></svg>
9
+ </button>
8
10
  </div>
9
11
 
10
12
  <div class="flex-1 overflow-y-auto">
11
13
  <div v-for="(preset, idx) in config.presets"
12
- class="px-6 py-3 flex flex-row gap-2 items-center hover:bg-text-50 cursor-pointer">
13
- <div class="px-2">
14
- <Checkbox :checked="idx === config.presetIdx" @change="selectPreset(preset)" />
15
- </div>
16
- <div @click="presetOpenIdx = idx" class="flex-1">
14
+ class="p-2 flex flex-row gap-2 items-center hover:bg-primary-50 cursor-pointer"
15
+ :class="config.presetIdx === idx ? 'bg-primary-100' : ''">
16
+ <div @click="config.presetIdx = idx" class="flex-1 p-1 pl-4 overflow-x-hidden whitespace-nowrap text-ellipsis">
17
17
  <label>{{ preset.name }}</label>
18
18
  </div>
19
- <button class="px-2" v-if="config.presets.length > 1" @click="removePreset(idx)">
19
+ <button type="button" class="px-2" v-if="config.presets.length > 1" @click="removePreset(idx)">
20
20
  <svg width="16" height="16" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
21
21
  <path fill-rule="evenodd" clip-rule="evenodd" d="M10 10.25C10.4142 10.25 10.75 10.5858 10.75 11V16C10.75 16.4142 10.4142 16.75 10 16.75C9.58579 16.75 9.25 16.4142 9.25 16V11C9.25 10.5858 9.58579 10.25 10 10.25Z"/>
22
22
  <path fill-rule="evenodd" clip-rule="evenodd" d="M14 10.25C14.4142 10.25 14.75 10.5858 14.75 11V16C14.75 16.4142 14.4142 16.75 14 16.75C13.5858 16.75 13.25 16.4142 13.25 16V11C13.25 10.5858 13.5858 10.25 14 10.25Z"/>
@@ -24,37 +24,34 @@
24
24
  </svg>
25
25
  </button>
26
26
  </div>
27
- <div class="p-5 text-center">
28
- <button @click="addPreset">
29
- <svg width="21" height="21" viewBox="0 0 24 24" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg">
30
- <path d="M12.75 5C12.75 4.58579 12.4142 4.25 12 4.25C11.5858 4.25 11.25 4.58579 11.25 5V11.25H5C4.58579 11.25 4.25 11.5858 4.25 12C4.25 12.4142 4.58579 12.75 5 12.75H11.25V19C11.25 19.4142 11.5858 19.75 12 19.75C12.4142 19.75 12.75 19.4142 12.75 19V12.75H19C19.4142 12.75 19.75 12.4142 19.75 12C19.75 11.5858 19.4142 11.25 19 11.25H12.75V5Z"/>
31
- </svg>
32
- </button>
33
- </div>
34
27
  </div>
35
28
 
36
29
  </div>
37
30
 
38
31
  <div>
39
32
  <div class="p-6 pb-0">
40
- <div class="flex flex-row gap-4 mb-3">
41
- <button @click="presetOpenIdx = -1">
33
+ <div class="flex flex-row items-center gap-4 mb-3">
34
+ <button type="button" class="hidden" @click="presetOpenIdx = -1">
42
35
  <svg width="19" height="19" viewBox="0 0 24 24" class="fill-text-300 hover:fill-text-400" xmlns="http://www.w3.org/2000/svg">
43
36
  <path d="M10.5303 17.9697C10.8232 18.2626 10.8232 18.7374 10.5303 19.0303C10.2374 19.3232 9.76253 19.3232 9.46964 19.0303L3.67675 13.2374C2.99333 12.554 2.99333 11.446 3.67675 10.7626L9.46964 4.96967C9.76253 4.67678 10.2374 4.67678 10.5303 4.96967C10.8232 5.26256 10.8232 5.73744 10.5303 6.03033L5.31063 11.25H20C20.4142 11.25 20.75 11.5858 20.75 12C20.75 12.4142 20.4142 12.75 20 12.75H5.31063L10.5303 17.9697Z"/>
44
37
  </svg>
45
38
  </button>
46
- <input class="flex-1 text-xl bg-transparent outline-none" :value="preset.name" @blur="preset.name = $event.target.value"
47
- @keyup.enter="preset.name = $event.target.value" />
48
- </div>
39
+ <div class="flex-1 flex flex-row items-center gap-2">
40
+ <svg @click="$refs.title.select()" width="16" height="16" class="fill-text-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"/></svg>
41
+ <input ref="title" class="flex-1 text-xl bg-transparent outline-none" :value="preset.name" maxlength="30"
42
+ @blur="preset.name = $event.target.value"
43
+ @keyup.enter="preset.name = $event.target.value" />
44
+ </div>
45
+ </div>
49
46
 
50
47
  <div class="flex justify-center">
51
- <Tabs v-model="presetTab" :items="tabItems" @change="tabChanged"/>
48
+ <Tabs v-model="config.presetTab" :items="tabItems" @change="tabChanged"/>
52
49
  </div>
53
50
  </div>
54
51
 
55
52
  <div class="flex-1 overflow-y-auto px-6 mb-6">
56
53
 
57
- <div class="p-2 mt-6 flex flex-col" v-if="presetTab === 'column'">
54
+ <div class="p-2 mt-6 flex flex-col" v-if="!config.presetTab || config.presetTab === 'column'">
58
55
  <ListItem :items="presetColumns" @reorder="reorderColumns">
59
56
  <template v-slot="{ item }">
60
57
  <div class="flex flex-row items-center gap-2" :key="item">
@@ -72,7 +69,7 @@
72
69
  </ListItem>
73
70
  </div>
74
71
 
75
- <div class="flex flex-col" v-else-if="presetTab === 'filter'">
72
+ <div class="flex flex-col" v-else-if="config.presetTab === 'filter'">
76
73
  <div v-if="filterableColumns.length > 0">
77
74
  <ListPage1Filter v-if="preset.filters" v-for="filter in preset.filters"
78
75
  :filter="filter" :column="config.columns[filter.key]"
@@ -91,7 +88,7 @@
91
88
  </div>
92
89
  </div>
93
90
 
94
- <div class="flex flex-col" v-else-if="presetTab === 'sort'">
91
+ <div class="flex flex-col" v-else-if="config.presetTab === 'sort'">
95
92
  <div v-if="sortableColumns.length > 0" class="my-8">
96
93
  <div v-for="sort in preset.sorts" class="py-4">
97
94
  <div class="flex flex-row items-center gap-2">
@@ -107,7 +104,7 @@
107
104
  <option value="desc">Desc</option>
108
105
  </Dropdown>
109
106
  </div>
110
- <button @click="removeSort(sort)">
107
+ <button type="button" @click="removeSort(sort)">
111
108
  <svg width="21" height="21" class="fill-text-100 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
112
109
  <path class="secondary" fill-rule="evenodd" d="M15.78 14.36a1 1 0 0 1-1.42 1.42l-2.82-2.83-2.83 2.83a1 1 0 1 1-1.42-1.42l2.83-2.82L7.3 8.7a1 1 0 0 1 1.42-1.42l2.83 2.83 2.82-2.83a1 1 0 0 1 1.42 1.42l-2.83 2.83 2.83 2.82z"/>
113
110
  </svg>
@@ -129,7 +126,7 @@
129
126
  </div>
130
127
  </div>
131
128
 
132
- <div class="flex flex-col gap-3 py-8" v-else-if="presetTab === 'summary'">
129
+ <div class="flex flex-col gap-3 py-8" v-else-if="config.presetTab === 'summarys'">
133
130
 
134
131
  <div v-if="config.summaryOpenIdx === -1">
135
132
  <div v-for="(summary, idx) in preset.summaries">
@@ -140,7 +137,7 @@
140
137
  <div class="flex-1" @click="config.summaryOpenIdx = idx">
141
138
  <label>{{ summary.title }}</label>
142
139
  </div>
143
- <button class="px-2" v-if="preset.summaries.length > 1" @click="removeSummary(summary)">
140
+ <button type="button" class="px-2" v-if="preset.summaries.length > 1" @click="removeSummary(summary)">
144
141
  <svg width="16" height="16" viewBox="0 0 24 24" class="fill-text-300 hover:fill-red-500" xmlns="http://www.w3.org/2000/svg">
145
142
  <path fill-rule="evenodd" clip-rule="evenodd" d="M10 10.25C10.4142 10.25 10.75 10.5858 10.75 11V16C10.75 16.4142 10.4142 16.75 10 16.75C9.58579 16.75 9.25 16.4142 9.25 16V11C9.25 10.5858 9.58579 10.25 10 10.25Z"/>
146
143
  <path fill-rule="evenodd" clip-rule="evenodd" d="M14 10.25C14.4142 10.25 14.75 10.5858 14.75 11V16C14.75 16.4142 14.4142 16.75 14 16.75C13.5858 16.75 13.25 16.4142 13.25 16V11C13.25 10.5858 13.5858 10.25 14 10.25Z"/>
@@ -150,7 +147,7 @@
150
147
  </div>
151
148
  </div>
152
149
  <div class="p-2 text-center">
153
- <button @click="addSummary">
150
+ <button type="button" @click="addSummary">
154
151
  <svg width="21" height="21" viewBox="0 0 24 24" class="fill-text-300 hover:fill-primary" xmlns="http://www.w3.org/2000/svg">
155
152
  <path d="M12.75 5C12.75 4.58579 12.4142 4.25 12 4.25C11.5858 4.25 11.25 4.58579 11.25 5V11.25H5C4.58579 11.25 4.25 11.5858 4.25 12C4.25 12.4142 4.58579 12.75 5 12.75H11.25V19C11.25 19.4142 11.5858 19.75 12 19.75C12.4142 19.75 12.75 19.4142 12.75 19V12.75H19C19.4142 12.75 19.75 12.4142 19.75 12C19.75 11.5858 19.4142 11.25 19 11.25H12.75V5Z"/>
156
153
  </svg>
@@ -162,7 +159,7 @@
162
159
 
163
160
  <div class="flex flex-row items-center p-3 py-1">
164
161
  <label class="text-text-400 flex-1">Enabled</label>
165
- <Checkbox v-model="openedPresetSummary.enabled" @change="loadSummary"/>
162
+ <Checkbox v-model="openedPresetSummary.enabled"/>
166
163
  </div>
167
164
 
168
165
  <div class="h-[1px] bg-text-50 my-1"></div>
@@ -176,7 +173,7 @@
176
173
 
177
174
  <div class="flex flex-row items-center p-3 py-1">
178
175
  <label class="text-text-400 flex-1">Hide Details</label>
179
- <Checkbox v-model="openedPresetSummary.hideDetails" @change="loadSummary"/>
176
+ <Checkbox v-model="openedPresetSummary.hideDetails"/>
180
177
  </div>
181
178
 
182
179
  <div class="h-[1px] bg-text-50 my-1"></div>
@@ -184,7 +181,7 @@
184
181
  <div class="p-3">
185
182
  <label class="text-text-400 flex-1">Type</label>
186
183
  <div class="mt-2">
187
- <Dropdown v-model="openedPresetSummary.mode" class="flex-1" @change="loadSummary">
184
+ <Dropdown v-model="openedPresetSummary.mode" class="flex-1">
188
185
  <option value="table">{{ $t('Table') }}</option>
189
186
  <option value="bar">{{ $t('Bar Chart') }}</option>
190
187
  <option value="line">{{ $t('Line Chart') }}</option>
@@ -192,7 +189,7 @@
192
189
  </Dropdown>
193
190
  </div>
194
191
  <div v-if="[ 'bar', 'line' ].includes(openedPresetSummary.mode)" class="mt-1">
195
- <Checkbox v-model="openedPresetSummary.hideLegends" @change="loadSummary">Hide Legend</Checkbox>
192
+ <Checkbox v-model="openedPresetSummary.hideLegends">Hide Legend</Checkbox>
196
193
  </div>
197
194
  </div>
198
195
 
@@ -201,11 +198,11 @@
201
198
  <div class="p-3">
202
199
  <label class="text-text-400 flex-1">{{ $t('Row') }}</label>
203
200
  <div class="flex flex-row mt-2 gap-2">
204
- <Dropdown v-model="openedPresetSummary.table.rows[0].key" class="flex-1" @change="loadSummary">
201
+ <Dropdown v-model="openedPresetSummary.table.rows[0].key" class="flex-1">
205
202
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
206
203
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
207
204
  </Dropdown>
208
- <Dropdown v-model="openedPresetSummary.table.rows[0].format" class="w-[100px]" @change="loadSummary">
205
+ <Dropdown v-model="openedPresetSummary.table.rows[0].format" class="w-[100px]">
209
206
  <option value="">{{ $t('Default') }}</option>
210
207
  <option value="date">{{ $t('Date') }}</option>
211
208
  <option value="month">{{ $t('Month') }}</option>
@@ -221,7 +218,7 @@
221
218
  <div class="p-3">
222
219
  <label class="text-text-400 flex-1">{{$t('Column') }}</label>
223
220
  <div>
224
- <Dropdown v-model="openedPresetSummary.table.columns[0].key" class="flex-1" @change="loadSummary">
221
+ <Dropdown v-model="openedPresetSummary.table.columns[0].key" class="flex-1">
225
222
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
226
223
  <option value="(none)">{{ $t('(None)') }}</option>
227
224
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
@@ -235,7 +232,7 @@
235
232
  <div class="p-3">
236
233
  <label class="text-text-400 flex-1">Values</label>
237
234
  <div class="flex flex-row mt-2 gap-2">
238
- <Dropdown v-model="openedPresetSummary.table.values[0].aggregrate" class="flex-1" @change="loadSummary">
235
+ <Dropdown v-model="openedPresetSummary.table.values[0].aggregrate" class="flex-1">
239
236
  <option value="" disabled selected>{{ $t('Select') }}</option>
240
237
  <option value="count">{{ $t('Count') }}</option>
241
238
  <option value="max">{{ $t('Max') }}</option>
@@ -252,11 +249,11 @@
252
249
  <div class="p-3">
253
250
  <label class="text-text-400 flex-1">{{ $t('X-axis') }}</label>
254
251
  <div class="flex flex-row mt-2 gap-2">
255
- <Dropdown v-model="openedPresetSummary.bar.rows[0].key" class="flex-1" @change="loadSummary">
252
+ <Dropdown v-model="openedPresetSummary.bar.rows[0].key" class="flex-1">
256
253
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
257
254
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
258
255
  </Dropdown>
259
- <Dropdown v-model="openedPresetSummary.bar.rows[0].format" class="w-[100px]" @change="loadSummary">
256
+ <Dropdown v-model="openedPresetSummary.bar.rows[0].format" class="w-[100px]">
260
257
  <option value="">{{ $t('Default') }}</option>
261
258
  <option value="date">{{ $t('Date') }}</option>
262
259
  <option value="month">{{ $t('Month') }}</option>
@@ -269,12 +266,12 @@
269
266
  <div class="p-3">
270
267
  <label class="text-text-400 flex-1">{{ $t('Column') }}</label>
271
268
  <div class="flex flex-row mt-2 gap-2">
272
- <Dropdown v-model="openedPresetSummary.bar.columns[0].key" class="flex-1" @change="loadSummary">
269
+ <Dropdown v-model="openedPresetSummary.bar.columns[0].key" class="flex-1">
273
270
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
274
271
  <option value="(none)">{{ $t('None') }}</option>
275
272
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
276
273
  </Dropdown>
277
- <Dropdown v-model="openedPresetSummary.bar.columns[0].format" class="w-[100px]" @change="loadSummary">
274
+ <Dropdown v-model="openedPresetSummary.bar.columns[0].format" class="w-[100px]">
278
275
  <option value="">{{ $t('Default') }}</option>
279
276
  <option value="date">{{ $t('Date') }}</option>
280
277
  </Dropdown>
@@ -287,7 +284,7 @@
287
284
  <div class="p-3">
288
285
  <label class="text-text-400 flex-1">Values</label>
289
286
  <div class="flex flex-row mt-2 gap-2">
290
- <Dropdown v-model="openedPresetSummary.bar.values[0].aggregrate" class="flex-1" @change="loadSummary">
287
+ <Dropdown v-model="openedPresetSummary.bar.values[0].aggregrate" class="flex-1">
291
288
  <option value="" disabled selected>{{ $t('Select') }}</option>
292
289
  <option value="count">{{ $t('Count') }}</option>
293
290
  <option value="max">{{ $t('Max') }}</option>
@@ -304,11 +301,11 @@
304
301
  <div class="p-3">
305
302
  <label class="text-text-400 flex-1">{{ $t('X-axis') }}</label>
306
303
  <div class="flex flex-row mt-2 gap-2">
307
- <Dropdown v-model="openedPresetSummary.line.rows[0].key" class="flex-1" @change="loadSummary">
304
+ <Dropdown v-model="openedPresetSummary.line.rows[0].key" class="flex-1">
308
305
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
309
306
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
310
307
  </Dropdown>
311
- <Dropdown v-model="openedPresetSummary.line.rows[0].format" class="w-[100px]" @change="loadSummary">
308
+ <Dropdown v-model="openedPresetSummary.line.rows[0].format" class="w-[100px]">
312
309
  <option value="">{{ $t('Default') }}</option>
313
310
  <option value="date">{{ $t('Date') }}</option>
314
311
  <option value="month">{{ $t('Month') }}</option>
@@ -321,12 +318,12 @@
321
318
  <div class="p-3">
322
319
  <label class="text-text-400 flex-1">{{$t('Column') }}</label>
323
320
  <div class="flex flex-row mt-2 gap-2">
324
- <Dropdown v-model="openedPresetSummary.line.columns[0].key" class="flex-1" @change="loadSummary">
321
+ <Dropdown v-model="openedPresetSummary.line.columns[0].key" class="flex-1">
325
322
  <option value="" disabled selected>{{ $t('Add Column') }}</option>
326
323
  <option value="(none)">{{ $t('None') }}</option>
327
324
  <option v-for="column in filterableColumns" :value="column.key">{{ column.label ?? column.key }}</option>
328
325
  </Dropdown>
329
- <Dropdown v-model="openedPresetSummary.line.columns[0].format" class="w-[100px]" @change="loadSummary">
326
+ <Dropdown v-model="openedPresetSummary.line.columns[0].format" class="w-[100px]">
330
327
  <option value="">{{ $t('Default') }}</option>
331
328
  <option value="date">{{ $t('Date') }}</option>
332
329
  </Dropdown>
@@ -336,7 +333,7 @@
336
333
  <div class="p-3">
337
334
  <label class="text-text-400 flex-1">Values</label>
338
335
  <div class="flex flex-row mt-2 gap-2">
339
- <Dropdown v-model="openedPresetSummary.line.values[0].aggregrate" class="flex-1" @change="loadSummary">
336
+ <Dropdown v-model="openedPresetSummary.line.values[0].aggregrate" class="flex-1">
340
337
  <option value="" disabled selected>{{ $t('Select') }}</option>
341
338
  <option value="count">{{ $t('Count') }}</option>
342
339
  <option value="max">{{ $t('Max') }}</option>
@@ -353,7 +350,7 @@
353
350
  <div class="p-3 flex flex-row gap-3">
354
351
  <div class="flex-1">
355
352
  <label class="text-text-400 flex-1">Map Type</label>
356
- <Dropdown class="mt-2" v-model="openedPresetSummary.map.mapType" @change="loadSummary">
353
+ <Dropdown class="mt-2" v-model="openedPresetSummary.map.mapType">
357
354
  <option value="" disabled selected>(Default)</option>
358
355
  <option value="heatmap">Heatmap</option>
359
356
  </Dropdown>
@@ -361,7 +358,7 @@
361
358
  <div>
362
359
  <label class="text-text-400 flex-1">Radius</label>
363
360
  <div class="flex flex-row mt-2 gap-2">
364
- <Textbox v-model="openedPresetSummary.map.mapRadius" class="w-[60px]" @blur="loadSummary" @keyup.enter="loadSummary" />
361
+ <Textbox v-model="openedPresetSummary.map.mapRadius" class="w-[60px]" />
365
362
  </div>
366
363
  </div>
367
364
  </div>
@@ -369,7 +366,7 @@
369
366
  <div class="p-3">
370
367
  <label class="text-text-400 flex-1">{{$t('Property') }}</label>
371
368
  <div>
372
- <Dropdown v-model="openedPresetSummary.map.key" class="flex-1" @change="loadSummary">
369
+ <Dropdown v-model="openedPresetSummary.map.key" class="flex-1">
373
370
  <option value="" disabled selected>{{ $t('Select Column') }}</option>
374
371
  <option v-for="column in coordinateColumns" :value="column.key">{{ column.label ?? column.key }}</option>
375
372
  </Dropdown>
@@ -400,9 +397,22 @@ export default{
400
397
 
401
398
  methods: {
402
399
 
400
+ addPreset(){
401
+ this.config.presets.push({
402
+ name: "Untitled",
403
+ columns: []
404
+ })
405
+ },
406
+
407
+ removePreset(index){
408
+ if(this.config.presets.length <= 1) return
409
+ this.config.presets.splice(index, 1)
410
+ this.config.presetIdx = this.config.presets[index] ? index : this.config.presets.length - 1
411
+ },
412
+
403
413
  addFilter(key){
404
414
 
405
- const column = this.config.columns[key]
415
+ const column = this.presetColumns.find((_) => _.key === key)
406
416
 
407
417
  if(!this.preset.filters){
408
418
  this.preset.filters = []
@@ -471,6 +481,22 @@ export default{
471
481
  }
472
482
  },
473
483
 
484
+ addSummary(){
485
+
486
+ if(!this.preset.summaries)
487
+ this.preset.summaries = []
488
+
489
+ this.preset.summaries.push({
490
+ title: "New Summary",
491
+ table: { rows: [{}], columns:[{}], values:[{}] },
492
+ bar: { rows: [{}], columns:[{}], values:[{}] },
493
+ line: { rows: [{}], columns:[{}], values:[{}] },
494
+ map: {}
495
+ })
496
+
497
+ this.configs.summaryOpenIdx = this.preset.summaries.length - 1
498
+ },
499
+
474
500
  },
475
501
 
476
502
 
@@ -500,19 +526,40 @@ export default{
500
526
  },
501
527
 
502
528
  presetColumns(){
503
- if(!this.preset.columns) return
504
-
505
- for(let i = 0 ; i < (this.preset.columns).length ; i++){
506
- const presetColumn = this.preset.columns[i]
507
- const column = this.config.columns[presetColumn.key] ?? {}
508
- for(let key in column){
509
- if(!presetColumn[key]){
510
- this.preset.columns[i][key] = column[key]
511
- }
512
- }
513
- }
514
-
515
- return this.preset.columns
529
+ if(!this.preset.columns) return []
530
+
531
+ const presetColumns = {}
532
+ this.preset.columns.forEach((column, _index) => {
533
+ presetColumns[column.key] = {
534
+ ...column,
535
+ _index
536
+ }
537
+ })
538
+
539
+ this.preset.columns = this.config.columns.map((column, index) => {
540
+ const _sort = {
541
+ index: presetColumns[column.key] ? presetColumns[column.key]._index : index,
542
+ isUser: !!presetColumns[column.key]
543
+ }
544
+
545
+ return {
546
+ ...column,
547
+ ...(presetColumns[column.key] ?? {}),
548
+ _sort
549
+ }
550
+ })
551
+ .sort((a, b) => {
552
+ if(a._sort.index < b._sort.index) return -1
553
+ if(a._sort.index > b._sort.index) return 1
554
+ return a._sort.isUser ? 1 : -1
555
+ })
556
+ .map((column) => {
557
+ delete column._sort
558
+ delete column._index
559
+ return column
560
+ })
561
+
562
+ return this.preset.columns
516
563
  },
517
564
 
518
565
  presetAppearances(){
@@ -544,7 +591,6 @@ export default{
544
591
  { text:'Sorts', value:'sort' },
545
592
  { text:'Summary', value:'summary' },
546
593
  ],
547
- presetTab: 'column',
548
594
  presetFilterSelector: null,
549
595
  presetSortSelector: null,
550
596
  viewMode: null,
@@ -558,6 +604,14 @@ export default{
558
604
 
559
605
  watch: {
560
606
 
607
+ config: {
608
+ immediate: true,
609
+ handler(to){
610
+ if(!this.config.presetTab){
611
+ this.config.presetTab = 'column'
612
+ }
613
+ }
614
+ }
561
615
 
562
616
  }
563
617
 
@@ -3,7 +3,7 @@
3
3
  <Teleport to=".bW9k">
4
4
  <Transition :name="transition" @after-leave="onAfterLeave" @after-enter="$emit('show')">
5
5
  <div v-if="computedState" :class="computedClass" ref="modal" :style="computedStyle">
6
- <form @submit.prevent="$emit('submit')">
6
+ <form v-if="useForm" @submit.prevent="$emit('submit')">
7
7
  <div class="modal-head">
8
8
  <slot name="head"></slot>
9
9
  </div>
@@ -15,6 +15,18 @@
15
15
  </div>
16
16
  <div v-if="isDisabled" :class="$style.overlay"></div>
17
17
  </form>
18
+ <div v-else class="flex-1 min-h-0 flex flex-col relative">
19
+ <div class="modal-head">
20
+ <slot name="head"></slot>
21
+ </div>
22
+ <div :class="modalBodyClass">
23
+ <slot></slot>
24
+ </div>
25
+ <div class="modal-foot">
26
+ <slot name="foot"></slot>
27
+ </div>
28
+ <div v-if="isDisabled" :class="$style.overlay"></div>
29
+ </div>
18
30
  </div>
19
31
  </Transition>
20
32
  </Teleport>
@@ -54,7 +66,11 @@ export default{
54
66
  position: String,
55
67
  state: [ Number, Boolean, String ],
56
68
  transition: { type: String, default: 'slideup' },
57
- width: String
69
+ width: String,
70
+ useForm: {
71
+ type: Boolean,
72
+ default: false
73
+ }
58
74
  },
59
75
 
60
76
  computed:{
@@ -250,4 +266,4 @@ html[data-theme='dark'] .overlay{
250
266
  transform: translate3d(0, 10px, 0);
251
267
  }
252
268
 
253
- </style>
269
+ </style>
@@ -171,8 +171,7 @@ export default{
171
171
  },
172
172
 
173
173
  visibleColumns(){
174
- const columns = (this.columns ?? []).filter(_ => _.visible)
175
- return columns
174
+ return (this.columns ?? []).filter(_ => _.visible)
176
175
  }
177
176
 
178
177
  },