@mixd-id/web-scaffold 0.1.230406001

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/package.json +71 -0
  4. package/public/images/mixd-logo2.png +0 -0
  5. package/src/App.vue +17 -0
  6. package/src/components/Ahref.vue +34 -0
  7. package/src/components/Alert.vue +160 -0
  8. package/src/components/Button.vue +253 -0
  9. package/src/components/ButtonGroup.vue +101 -0
  10. package/src/components/Carousel.vue +293 -0
  11. package/src/components/ChatTyping.vue +69 -0
  12. package/src/components/Checkbox.vue +152 -0
  13. package/src/components/ContextMenu.vue +261 -0
  14. package/src/components/CopyToClipboard.vue +59 -0
  15. package/src/components/Countdown.vue +213 -0
  16. package/src/components/Datepicker.vue +312 -0
  17. package/src/components/Dropdown.vue +198 -0
  18. package/src/components/DynamicTemplate.vue +44 -0
  19. package/src/components/ErrorText.vue +36 -0
  20. package/src/components/Feed.vue +118 -0
  21. package/src/components/Gmaps.vue +227 -0
  22. package/src/components/Grid.vue +29 -0
  23. package/src/components/GridColumn.vue +31 -0
  24. package/src/components/HTMLEditor.vue +396 -0
  25. package/src/components/Image.vue +207 -0
  26. package/src/components/Image360.vue +140 -0
  27. package/src/components/ImageFullScreen.vue +101 -0
  28. package/src/components/ImagePreview.vue +71 -0
  29. package/src/components/ImportModal.vue +247 -0
  30. package/src/components/ListItem.vue +147 -0
  31. package/src/components/ListPage1.vue +1331 -0
  32. package/src/components/ListPage1Filter.vue +170 -0
  33. package/src/components/Modal.vue +253 -0
  34. package/src/components/OTPField.vue +126 -0
  35. package/src/components/Radio.vue +134 -0
  36. package/src/components/SearchButton.vue +57 -0
  37. package/src/components/Slider.vue +285 -0
  38. package/src/components/SplitPane.vue +129 -0
  39. package/src/components/Switch.vue +89 -0
  40. package/src/components/TabView.vue +106 -0
  41. package/src/components/TableView.vue +201 -0
  42. package/src/components/TableViewHead.vue +159 -0
  43. package/src/components/Tabs.vue +74 -0
  44. package/src/components/TextEditor.vue +85 -0
  45. package/src/components/Textarea.vue +184 -0
  46. package/src/components/Textbox.vue +200 -0
  47. package/src/components/Timepicker.vue +108 -0
  48. package/src/components/Toast.vue +93 -0
  49. package/src/components/VirtualScroll.vue +215 -0
  50. package/src/components/VirtualTable.vue +497 -0
  51. package/src/entry-client.js +27 -0
  52. package/src/entry-server.js +73 -0
  53. package/src/index.css +3 -0
  54. package/src/index.js +255 -0
  55. package/src/main.js +38 -0
  56. package/src/router.js +57 -0
  57. package/src/themes/default/index.js +200 -0
  58. package/src/utils/helpers.js +185 -0
  59. package/src/utils/helpers.mjs +197 -0
  60. package/src/utils/importer.js +156 -0
  61. package/src/utils/listpage1.js +1371 -0
  62. package/src/utils/selection.js +64 -0
@@ -0,0 +1,247 @@
1
+ <template>
2
+ <Modal :state="isOpen" width="480" height="560">
3
+ <template v-slot:head>
4
+ <div class="relative p-5">
5
+ <div v-if="step !== 3">
6
+ <h3>{{ title }}</h3>
7
+ <p v-if="step === 1" class="mt-1 text-text-400" v-html="description"></p>
8
+ <p v-else-if="step === 2" class="mt-1 text-text-400" v-html="description2"></p>
9
+ </div>
10
+ <div class="absolute top-0 right-0 p-2">
11
+ <button type="button" class="p-2" @click="isOpen = false">
12
+ <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">
13
+ <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"/>
14
+ </svg>
15
+ </button>
16
+ </div>
17
+ </div>
18
+ </template>
19
+ <template v-slot:foot>
20
+ <div class="p-5 flex flex-row gap-3" v-if="step === 2">
21
+ <Button class="w-[120px]" :disabled="!canImport" :state="isLoading ? 2 : 1" @click="proceedImport">Import</Button>
22
+ <Button variant="secondary" class="w-[80px]" @click="step = 1">Back</Button>
23
+ </div>
24
+ </template>
25
+
26
+ <div class="flex-1 p-5 flex flex-col items-center justify-center" v-if="step === 1">
27
+ <button type="button" @click="$refs.uploader.click()" class="rounded-3xl w-[200px] bg-base-300 px-6 aspect-square flex items-center justify-center text-center border-dashed border-[3px] border-text-100">
28
+ <div class="text-xl" v-if="!isLoading">
29
+ Click to <br />
30
+ <span class="text-primary text-lg">Upload</span>
31
+ file
32
+ </div>
33
+ <div v-else class="flex items-center justify-center">
34
+ <svg class="animate-spin aspect-square w-[48px] text-primary" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
35
+ </div>
36
+ </button>
37
+ <input type="file" :accept="accept" ref="uploader" class="hidden" @change="onFileUploaded"/>
38
+ <br />
39
+ <br />
40
+ <br />
41
+ <br />
42
+ <div v-if="templateFiles.length > 0" class="flex flex-col gap-2">
43
+ <a v-for="(file, index) in templateFiles" :href="file" class="text-primary">
44
+ Download Sample {{ templateFiles.length > 1 ? index + 1 : '' }}
45
+ </a>
46
+ </div>
47
+ </div>
48
+
49
+ <div class="flex-1 p-5 flex flex-col gap-3" v-else-if="step === 2">
50
+ <div v-for="(key, index) in importData.keys" class="flex flex-row items-center gap-2">
51
+ <div class="w-[120px]">
52
+ <strong v-if="key.required">{{ key.text }}*</strong>
53
+ <label v-else>{{ key.text }}</label>
54
+ </div>
55
+ <div class="flex-1">
56
+ <Dropdown v-model="importData.keys[index].value">
57
+ <option disabled selected>Pilih Kolom</option>
58
+ <option v-for="column in importData.columns" :value="column">{{ column }}</option>
59
+ </Dropdown>
60
+ </div>
61
+ </div>
62
+ <slot name="mapping-opt" :import-data="importData"></slot>
63
+ </div>
64
+
65
+ <div class="flex-1 flex items-center justify-center" v-else-if="step === 3">
66
+ <div class="flex flex-col items-center justify-center gap-1">
67
+ <svg width="96" height="96" viewBox="0 0 24 24" class="fill-green-600" xmlns="http://www.w3.org/2000/svg">
68
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM20.5 12C20.5 16.6944 16.6944 20.5 12 20.5C7.30558 20.5 3.5 16.6944 3.5 12C3.5 7.30558 7.30558 3.5 12 3.5C14.5863 3.5 16.9028 4.65509 18.4618 6.47753L11.1768 13.7626C11.0791 13.8602 10.9209 13.8602 10.8232 13.7626L8.03033 10.9697C7.73744 10.6768 7.26256 10.6768 6.96967 10.9697C6.67678 11.2626 6.67678 11.7374 6.96967 12.0303L9.76256 14.8232C10.446 15.5066 11.554 15.5066 12.2374 14.8232L19.3437 7.717C20.0787 8.97466 20.5 10.4381 20.5 12Z" />
69
+ </svg>
70
+ <h3>{{ importData.result.title ?? 'Data berhasil diimport' }}</h3>
71
+ <p class="mb-4 text-text-400 text-center" v-html="importData.result.description"></p>
72
+ <div class="p-2 text-sm text-green-500 border-green-500 border-[1px] rounded-lg">
73
+ Total Data: {{ importData.result.count }}
74
+ </div>
75
+ <div class="px-6 my-4">
76
+ <VirtualTable v-if="warnings.length > 0" :columns="warningColumns" :items="warnings" class="h-[200px]"></VirtualTable>
77
+ </div>
78
+
79
+ <div class="flex flex-row gap-3">
80
+ <Button class="font-bold w-[160px]" @click="close">OK</Button>
81
+ <Button v-if="warnings.length > 0" variant="outline" class="font-bold w-[60px]" @click="downloadWarning">
82
+ <svg width="21" height="21" viewBox="0 0 24 24" class="fill-text-300 mr-1" xmlns="http://www.w3.org/2000/svg">
83
+ <path d="M12.7519 4.99959C12.7519 4.58537 12.4161 4.24959 12.0019 4.24959C11.5877 4.24959 11.2519 4.58537 11.2519 4.99959V13.6894L8.03216 10.4697C7.73927 10.1768 7.26439 10.1768 6.9715 10.4697C6.67861 10.7626 6.67861 11.2374 6.9715 11.5303L10.7644 15.3233C11.4479 16.0067 12.5559 16.0067 13.2393 15.3233L17.0303 11.5323C17.3232 11.2394 17.3232 10.7645 17.0303 10.4716C16.7374 10.1787 16.2625 10.1787 15.9696 10.4716L12.7519 13.6893V4.99959Z" />
84
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M4 14.25C4.41421 14.25 4.75 14.5858 4.75 15V17C4.75 17.6904 5.30964 18.25 6 18.25H18C18.6904 18.25 19.25 17.6904 19.25 17V15C19.25 14.5858 19.5858 14.25 20 14.25C20.4142 14.25 20.75 14.5858 20.75 15V17C20.75 18.5188 19.5188 19.75 18 19.75H6C4.48122 19.75 3.25 18.5188 3.25 17V15C3.25 14.5858 3.58579 14.25 4 14.25Z" />
85
+ </svg>
86
+ </Button>
87
+ </div>
88
+ </div>
89
+ </div>
90
+
91
+ </Modal>
92
+ </template>
93
+
94
+ <script>
95
+
96
+ import axios from "axios";
97
+
98
+ export default{
99
+
100
+ emit: [ 'complete' ],
101
+
102
+ inject: [ 'socketEmit', 'socket', 'toast' ],
103
+
104
+ props: {
105
+
106
+ accept: { type: String, default: ".csv,.xlsx" },
107
+
108
+ title: { type: String, default: "Untitled Import" },
109
+
110
+ description: { type: String, default: "Import csv or xlsx file" },
111
+
112
+ description2: { type: String, default: "Map column to fields" },
113
+
114
+ urlAnalyse: { type: String },
115
+
116
+ urlImport: { type: String },
117
+
118
+ completeDescription: { type: String, default: "" },
119
+
120
+ warningFile: { type: String, default: "warning.txt" },
121
+
122
+ templateFile: String
123
+
124
+ },
125
+
126
+ computed: {
127
+
128
+ canImport(){
129
+ return (this.importData.keys ?? []).filter((_) => _.required && !_.value).length < 1
130
+ },
131
+
132
+ warnings(){
133
+ return (this.importData.result ?? {}).warnings ?? []
134
+ },
135
+
136
+ templateFiles(){
137
+ return (this.templateFile ?? '').split(',')
138
+ }
139
+
140
+ },
141
+
142
+ data(){
143
+ return {
144
+ isOpen: false,
145
+ isLoading: false,
146
+ step: 1,
147
+ importData: null,
148
+ warningColumns: [
149
+ { key:"text", label:"Warning", width:"420px", visible:true }
150
+ ]
151
+ }
152
+ },
153
+
154
+ methods: {
155
+
156
+ onFileUploaded(){
157
+
158
+ const data = new FormData()
159
+ data.append('file', this.$refs.uploader.files[0])
160
+ data.append('filename', this.$refs.uploader.files[0].name)
161
+
162
+ this.isLoading = true
163
+ axios({
164
+ url: import.meta.env.VITE_API_HOST + this.urlAnalyse,
165
+ method: 'POST',
166
+ data
167
+ })
168
+ .then(({ data:res }) => {
169
+
170
+ this.step = 2
171
+ this.importData = res
172
+
173
+ this.importData.keys.forEach((key) => {
174
+
175
+ const labels = [
176
+ ...(key.labels ?? []),
177
+ key.text
178
+ ]
179
+
180
+ const value = res.columns.filter((_) => labels.includes(_)).pop()
181
+ if(value) key.value = value
182
+ })
183
+ })
184
+ .catch((e) => {
185
+ this.toast(e.response.data)
186
+ })
187
+ .finally(() => {
188
+ this.isLoading = false
189
+ })
190
+ },
191
+
192
+ open(){
193
+ this.reset()
194
+ this.isOpen = true
195
+ },
196
+
197
+ close(){
198
+ this.isOpen = false
199
+ this.$emit('dismiss')
200
+ if(this.step === 3){
201
+ this.$emit('complete')
202
+ }
203
+ },
204
+
205
+ reset(){
206
+ this.step = 1
207
+ this.importData = {}
208
+ },
209
+
210
+ proceedImport(){
211
+
212
+ this.isLoading = true
213
+ axios({
214
+ url: import.meta.env.VITE_API_HOST + this.urlImport,
215
+ method: 'POST',
216
+ data: this.importData
217
+ })
218
+ .then(({ data:res }) => {
219
+ this.importData.result = res
220
+ this.step = 3
221
+ })
222
+ .catch((e) => {
223
+ this.toast(e.response.data)
224
+ })
225
+ .finally(() => {
226
+ this.isLoading = false
227
+ })
228
+ },
229
+
230
+ downloadWarning(){
231
+ const warningText = this.importData.result.warnings.map((_) => _.text).join("\n")
232
+ this.$download("data:attachment/text," + encodeURI(warningText), this.warningFile)
233
+ }
234
+
235
+ }
236
+
237
+ }
238
+
239
+ </script>
240
+
241
+ <style module>
242
+
243
+ .comp{
244
+
245
+ }
246
+
247
+ </style>
@@ -0,0 +1,147 @@
1
+ <template>
2
+ <div :class="$style.comp">
3
+ <div :class="headerClass">
4
+ <slot name="header"></slot>
5
+ </div>
6
+ <div :class="bodyClass">
7
+ <slot v-if="items && items.length > 0" name="default" v-for="(item, index) in items" :item="item" :index="index"></slot>
8
+ <slot v-else name="empty"></slot>
9
+ </div>
10
+ <div :class="footerClass">
11
+ <slot name="footer"></slot>
12
+ </div>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+
18
+ export default{
19
+
20
+ props: {
21
+ items: [ Array, Object ],
22
+ headerClass: String,
23
+ bodyClass: String,
24
+ footerClass: String,
25
+ },
26
+
27
+ emits: [ 'reorder' ],
28
+
29
+ mounted() {
30
+ this.attachReorder()
31
+ },
32
+
33
+ data(){
34
+ return {
35
+ lastDragOver: null,
36
+ startIdx: null,
37
+ targetIdx: null,
38
+ dragItem: null
39
+ }
40
+ },
41
+
42
+ methods: {
43
+
44
+ dragOver(e){
45
+ e.preventDefault();
46
+
47
+ let targetItem = e.target
48
+ while(targetItem.parentNode.parentNode){
49
+ if(targetItem.parentNode.parentNode === this.$el){
50
+ break
51
+ }
52
+ targetItem = targetItem.parentNode
53
+ }
54
+ if(targetItem === this.dragItem) return
55
+
56
+ this.targetIdx = [ ...this.$el.children[1].children ].indexOf(targetItem)
57
+
58
+ if(this.lastDragOver){
59
+ this.lastDragOver.classList.remove(this.$style.dragover)
60
+ }
61
+ targetItem.classList.add(this.$style.dragover)
62
+ this.lastDragOver = targetItem
63
+ },
64
+
65
+ dragEnd(e){
66
+
67
+ e.preventDefault()
68
+ window.removeEventListener('dragover', this.dragOver)
69
+ window.removeEventListener('dragend', this.dragEnd)
70
+ this.dragItem.removeAttribute('draggable')
71
+ if(this.lastDragOver){
72
+ this.lastDragOver.classList.remove(this.$style.dragover)
73
+ }
74
+
75
+ if(this.targetIdx >= 0 && this.targetIdx !== this.startIdx){
76
+
77
+ /*if(this.items instanceof Array){
78
+ this.items.splice(targetIdx, 0, this.items.splice(startIdx, 1)[0])
79
+ }*/
80
+
81
+ /*this.$nextTick(() => {
82
+ this.attachReorder()
83
+ })*/
84
+
85
+ this.$emit('reorder', this.startIdx, this.targetIdx)
86
+ }
87
+ },
88
+
89
+ onDragStart(){
90
+ window.addEventListener('dragover', this.dragOver)
91
+ window.addEventListener('dragend', this.dragEnd)
92
+ },
93
+
94
+ onDrag(e){
95
+
96
+ this.dragItem = e.target
97
+ while(this.dragItem.parentNode.parentNode){
98
+ if(this.dragItem.parentNode.parentNode === this.$el){
99
+ break
100
+ }
101
+ this.dragItem = this.dragItem.parentNode
102
+ }
103
+
104
+ this.startIdx = [ ...this.$el.children[1].children ].indexOf(this.dragItem)
105
+ this.targetIdx = -1
106
+
107
+ this.dragItem.setAttribute('draggable', true)
108
+ this.dragItem.addEventListener('dragstart', this.onDragStart)
109
+ },
110
+
111
+ attachReorder(){
112
+ this.$el.querySelectorAll('[data-reorder]').forEach((comp) => {
113
+ comp.addEventListener('mousedown', this.onDrag)
114
+ comp.addEventListener('touchstart', this.onDrag)
115
+ })
116
+ }
117
+
118
+ },
119
+
120
+ watch: {
121
+
122
+ items: {
123
+ handler(to){
124
+ this.$nextTick(() => {
125
+ this.attachReorder()
126
+ })
127
+ },
128
+ deep: true
129
+ }
130
+
131
+ }
132
+
133
+ }
134
+
135
+ </script>
136
+
137
+ <style module>
138
+
139
+ .comp{
140
+
141
+ }
142
+
143
+ .comp .dragover{
144
+ @apply opacity-50
145
+ }
146
+
147
+ </style>