@edgedev/create-edge-app 1.1.23 → 1.1.26

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 (116) hide show
  1. package/.env +1 -0
  2. package/.env.dev +1 -0
  3. package/README.md +55 -20
  4. package/{agent.md → agents.md} +2 -0
  5. package/bin/cli.js +6 -6
  6. package/edge/components/auth/login.vue +384 -0
  7. package/edge/components/auth/register.vue +396 -0
  8. package/edge/components/auth.vue +108 -0
  9. package/edge/components/autoFileUpload.vue +215 -0
  10. package/edge/components/billing.vue +8 -0
  11. package/edge/components/buttonDivider.vue +14 -0
  12. package/edge/components/chip.vue +34 -0
  13. package/edge/components/clipboardButton.vue +42 -0
  14. package/edge/components/cms/block.vue +529 -0
  15. package/edge/components/cms/blockApi.vue +212 -0
  16. package/edge/components/cms/blockEditor.vue +725 -0
  17. package/edge/components/cms/blockInput.vue +66 -0
  18. package/edge/components/cms/blockPicker.vue +486 -0
  19. package/edge/components/cms/blockRender.vue +78 -0
  20. package/edge/components/cms/blockSheetContent.vue +28 -0
  21. package/edge/components/cms/codeEditor.vue +466 -0
  22. package/edge/components/cms/fontUpload.vue +327 -0
  23. package/edge/components/cms/htmlContent.vue +807 -0
  24. package/edge/components/cms/init_blocks/api_with_subarrays.html +17 -0
  25. package/edge/components/cms/init_blocks/array_with_collection.html +7 -0
  26. package/edge/components/cms/init_blocks/array_with_objects.html +7 -0
  27. package/edge/components/cms/init_blocks/carousel.html +103 -0
  28. package/edge/components/cms/init_blocks/contact_us.html +69 -0
  29. package/edge/components/cms/init_blocks/content_with_left_image.html +27 -0
  30. package/edge/components/cms/init_blocks/footer.html +24 -0
  31. package/edge/components/cms/init_blocks/header_divider.html +7 -0
  32. package/edge/components/cms/init_blocks/hero.html +35 -0
  33. package/edge/components/cms/init_blocks/hero_carousel.html +52 -0
  34. package/edge/components/cms/init_blocks/newsletter.html +117 -0
  35. package/edge/components/cms/init_blocks/post_content.html +7 -0
  36. package/edge/components/cms/init_blocks/post_title_header.html +21 -0
  37. package/edge/components/cms/init_blocks/posts_list.html +20 -0
  38. package/edge/components/cms/init_blocks/properties_showcase.html +100 -0
  39. package/edge/components/cms/init_blocks/property_carousel.html +59 -0
  40. package/edge/components/cms/init_blocks/property_detail.html +112 -0
  41. package/edge/components/cms/init_blocks/property_detail_header.html +34 -0
  42. package/edge/components/cms/init_blocks/property_results.html +137 -0
  43. package/edge/components/cms/init_blocks/property_search.html +75 -0
  44. package/edge/components/cms/init_blocks/simple_array.html +7 -0
  45. package/edge/components/cms/mediaCard.vue +116 -0
  46. package/edge/components/cms/mediaManager.vue +386 -0
  47. package/edge/components/cms/menu.vue +1103 -0
  48. package/edge/components/cms/optionsSelect.vue +107 -0
  49. package/edge/components/cms/page.vue +1785 -0
  50. package/edge/components/cms/posts.vue +1083 -0
  51. package/edge/components/cms/site.vue +1298 -0
  52. package/edge/components/cms/themeDefaultMenu.vue +548 -0
  53. package/edge/components/cms/themeEditor.vue +426 -0
  54. package/edge/components/dashboard.vue +776 -0
  55. package/edge/components/editor.vue +671 -0
  56. package/edge/components/fileTree.vue +72 -0
  57. package/edge/components/files.vue +89 -0
  58. package/edge/components/formSubtypes/myOrgs.vue +214 -0
  59. package/edge/components/formSubtypes/users.vue +336 -0
  60. package/edge/components/functionChips.vue +57 -0
  61. package/edge/components/gError.vue +98 -0
  62. package/edge/components/gHelper.vue +67 -0
  63. package/edge/components/gInput.vue +1331 -0
  64. package/edge/components/loggingIn.vue +41 -0
  65. package/edge/components/menu.vue +137 -0
  66. package/edge/components/menuContent.vue +132 -0
  67. package/edge/components/myAccount.vue +317 -0
  68. package/edge/components/myOrganizations.vue +75 -0
  69. package/edge/components/myProfile.vue +122 -0
  70. package/edge/components/orgSwitcher.vue +25 -0
  71. package/edge/components/organizationMembers.vue +522 -0
  72. package/edge/components/organizationSettings.vue +271 -0
  73. package/edge/components/shad/breadcrumbs.vue +35 -0
  74. package/edge/components/shad/button.vue +43 -0
  75. package/edge/components/shad/checkbox.vue +73 -0
  76. package/edge/components/shad/combobox.vue +238 -0
  77. package/edge/components/shad/datepicker.vue +184 -0
  78. package/edge/components/shad/dialog.vue +32 -0
  79. package/edge/components/shad/dropdownMenu.vue +54 -0
  80. package/edge/components/shad/dropdownMenuItem.vue +21 -0
  81. package/edge/components/shad/form.vue +59 -0
  82. package/edge/components/shad/html.vue +877 -0
  83. package/edge/components/shad/input.vue +139 -0
  84. package/edge/components/shad/number.vue +109 -0
  85. package/edge/components/shad/select.vue +151 -0
  86. package/edge/components/shad/selectTags.vue +278 -0
  87. package/edge/components/shad/switch.vue +67 -0
  88. package/edge/components/shad/tags.vue +137 -0
  89. package/edge/components/shad/textarea.vue +102 -0
  90. package/edge/components/shad/typeMoney.vue +167 -0
  91. package/edge/components/sideBar.vue +288 -0
  92. package/edge/components/sideBarContent.vue +268 -0
  93. package/edge/components/sidebarProvider.vue +33 -0
  94. package/edge/components/tooltip.vue +16 -0
  95. package/edge/components/userMenu.vue +148 -0
  96. package/edge/components/v/alert.vue +59 -0
  97. package/edge/components/v/alertTitle.vue +18 -0
  98. package/edge/components/v/card.vue +53 -0
  99. package/edge/components/v/cardActions.vue +18 -0
  100. package/edge/components/v/cardText.vue +18 -0
  101. package/edge/components/v/cardTitle.vue +20 -0
  102. package/edge/components/v/col.vue +56 -0
  103. package/edge/components/v/list.vue +46 -0
  104. package/edge/components/v/listItem.vue +26 -0
  105. package/edge/components/v/listItemTitle.vue +18 -0
  106. package/edge/components/v/row.vue +42 -0
  107. package/edge/components/v/toolbar.vue +24 -0
  108. package/edge/composables/global.ts +519 -0
  109. package/edge-pull.sh +2 -0
  110. package/edge-push.sh +1 -0
  111. package/edge-status.sh +14 -0
  112. package/firebase.json +5 -2
  113. package/firebase_init.sh +21 -6
  114. package/package.json +1 -1
  115. package/plugins/firebase.client.ts +1 -0
  116. package/edge-components-install.sh +0 -1
@@ -0,0 +1,1331 @@
1
+ <script setup>
2
+ // TODO: ADD HELPERS TO THE SCHEMA PARAMS
3
+ // TODO: START SHAD CONVERSION AT
4
+ import { computed, defineProps, inject, nextTick, onBeforeMount, onMounted, reactive, ref, watch } from 'vue'
5
+
6
+ const props = defineProps({
7
+ disableTracking: {
8
+ type: Boolean,
9
+ default: false,
10
+ },
11
+ parentTrackerId: {
12
+ type: String,
13
+ default: '',
14
+ },
15
+ helper: {
16
+ type: String,
17
+ default: '',
18
+ },
19
+ items: {
20
+ type: Array,
21
+ default: () => [],
22
+ },
23
+ fieldType: {
24
+ type: String,
25
+ default: 'text',
26
+ },
27
+ fieldTypes: {
28
+ type: Array,
29
+ default: () => ['string', 'boolean', 'array', 'object', 'number', 'integer'],
30
+ },
31
+ subFieldType: {
32
+ type: String,
33
+ default: '',
34
+ },
35
+ collectionPath: {
36
+ type: String,
37
+ default: '',
38
+ },
39
+ collectionTitleField: {
40
+ type: String,
41
+ default: 'name',
42
+ },
43
+ collectionValueField: {
44
+ type: String,
45
+ default: 'docId',
46
+ },
47
+ titleField: {
48
+ type: String,
49
+ default: 'title',
50
+ },
51
+ valueField: {
52
+ type: String,
53
+ default: 'value',
54
+ },
55
+ modelValue: {
56
+ type: [Number, String, Array, Object, Boolean],
57
+ },
58
+ rules: {
59
+ type: Array,
60
+ default: () => [],
61
+ },
62
+ label: {
63
+ type: String,
64
+ default: '',
65
+ },
66
+ description: {
67
+ type: String,
68
+ default: '',
69
+ },
70
+ rows: {
71
+ type: String,
72
+ default: '1',
73
+ },
74
+ hint: {
75
+ type: String,
76
+ default: '',
77
+ },
78
+ persistentHint: {
79
+ type: Boolean,
80
+ default: false,
81
+ },
82
+ disabled: {
83
+ type: Boolean,
84
+ default: false,
85
+ },
86
+ passThroughProps: {
87
+ type: [Number, String, Array, Object, Boolean],
88
+ required: false,
89
+ default: null,
90
+ },
91
+ maskOptions: {
92
+ type: [Object],
93
+ required: false,
94
+ default: null,
95
+ },
96
+ bindings: {
97
+ type: [Object],
98
+ required: false,
99
+ default: () => ({}),
100
+ },
101
+ forFunctions: {
102
+ type: Boolean,
103
+ default: false,
104
+ },
105
+ name: {
106
+ type: String,
107
+ required: true,
108
+ },
109
+ staticObject: {
110
+ type: Boolean,
111
+ default: false,
112
+ },
113
+ errors: {
114
+ type: String,
115
+ default: '',
116
+ },
117
+ })
118
+ const emit = defineEmits(['update:modelValue'])
119
+
120
+ const generateShortId = () => {
121
+ return Math.random().toString(36).substr(2, 6)
122
+ }
123
+
124
+ const jsonSchemaStringFormats = [
125
+ '',
126
+ 'date-time',
127
+ 'date',
128
+ 'time',
129
+ 'email',
130
+ 'hostname',
131
+ 'ipv4',
132
+ 'ipv6',
133
+ 'uri',
134
+ 'uri-reference',
135
+ 'uri-template',
136
+ 'json-pointer',
137
+ 'relative-json-pointer',
138
+ 'regex',
139
+ ]
140
+ // const edgeGlobal = inject('edgeGlobal')
141
+ const edgeFirebase = inject('edgeFirebase')
142
+ const state = reactive({
143
+ loaded: false,
144
+ afterMount: false,
145
+ trackerKey: '',
146
+ helper: false,
147
+ fieldsTypes: ['string', 'boolean', 'array', 'object', 'number', 'integer'],
148
+ fieldInsert: { key: '', type: 'string' },
149
+ fieldInsertKeyRequired: false,
150
+ fieldInsertDialog: false,
151
+ removeField: null,
152
+ fieldErrorMessage: '',
153
+ keyMenu: false,
154
+ newKey: null,
155
+ currentKey: null,
156
+ order: [],
157
+ orderUpdateFromWatcher: false,
158
+ objectListOriginalOrder: {},
159
+ arrayAdd: null,
160
+ isEditing: false,
161
+ removeFieldDialogShow: false,
162
+ })
163
+
164
+ const returnObject = computed(() => {
165
+ if (props.bindings && props.bindings['return-object']) {
166
+ return props.bindings['return-object']
167
+ }
168
+ return false
169
+ })
170
+
171
+ const fieldTypes = computed(() => {
172
+ if (props.fieldTypes.length > 0) {
173
+ return props.fieldTypes
174
+ }
175
+ return state.fieldsTypes
176
+ })
177
+
178
+ // {
179
+ // "type": "string", // Declares the data type as string
180
+ // "description": "A text value", // Describes the property
181
+ // "minLength": 1, // Minimum length of the string
182
+ // "maxLength": 100, // Maximum length of the string
183
+ // "pattern": "^[a-zA-Z0-9]+$", // Regular expression pattern for string validation
184
+ // "format": "email", // Specific format of the string, e.g., email, date-time, uri
185
+ // "enum": ["option1", "option2", "option3"], // Enumerates allowable values for the string
186
+ // "default": "defaultText", // Default value for the string
187
+ // "examples": ["exampleText1", "exampleText2"] // Examples of valid strings
188
+ // }
189
+
190
+ const extraTypeFields = {
191
+ string: {
192
+ enum: { default: [], bindings: { 'field-type': 'stringArray', 'label': 'Enum' } },
193
+ minLength: { default: 0, bindings: { 'field-type': 'integer', 'label': 'Minimum Length' } },
194
+ maxLength: { default: 100, bindings: { 'field-type': 'integer', 'label': 'Maximum Length' } },
195
+ pattern: { default: '', bindings: { 'field-type': 'text', 'label': 'Pattern' } },
196
+ format: { default: '', bindings: { 'field-type': 'select', 'label': 'Format', 'items': jsonSchemaStringFormats } },
197
+ default: { default: '', bindings: { 'field-type': 'text', 'label': 'Default' } },
198
+ examples: { default: [], bindings: { 'field-type': 'stringArray', 'label': 'Examples' } },
199
+ },
200
+ boolean: {
201
+ default: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Default' } },
202
+ },
203
+ number: {
204
+ enum: { default: [], bindings: { 'field-type': 'numberArray', 'label': 'Enum' } },
205
+ minimum: { default: 0, bindings: { 'field-type': 'number', 'label': 'Minimum' } },
206
+ maximum: { default: 10, bindings: { 'field-type': 'number', 'label': 'Maximum' } },
207
+ exclusiveMinimum: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Exclusive Minimum' } },
208
+ exclusiveMaximum: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Exclusive Maximum' } },
209
+ multipleOf: { default: 0.5, bindings: { 'field-type': 'number', 'label': 'Multiple Of' } },
210
+ default: { default: 5, bindings: { 'field-type': 'number', 'label': 'Default' } },
211
+ examples: { default: [], bindings: { 'field-type': 'numberArray', 'label': 'Examples' } },
212
+ },
213
+ integer: {
214
+ enum: { default: [], bindings: { 'field-type': 'integerArray', 'label': 'Enum' } },
215
+ minimum: { default: 0, bindings: { 'field-type': 'integer', 'label': 'Minimum' } },
216
+ maximum: { default: 10, bindings: { 'field-type': 'integer', 'label': 'Maximum' } },
217
+ exclusiveMinimum: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Exclusive Minimum' } },
218
+ exclusiveMaximum: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Exclusive Maximum' } },
219
+ multipleOf: { default: 1, bindings: { 'field-type': 'integer', 'label': 'Multiple Of' } },
220
+ default: { default: 5, bindings: { 'field-type': 'integer', 'label': 'Default' } },
221
+ examples: { default: [], bindings: { 'field-type': 'integerArray', 'label': 'Examples' } },
222
+ },
223
+ array: {
224
+ minItems: { default: 0, bindings: { 'field-type': 'integer', 'label': 'Minimum Items' } },
225
+ maxItems: { default: 10, bindings: { 'field-type': 'integer', 'label': 'Maximum Items' } },
226
+ uniqueItems: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Unique Items' } },
227
+ additionalItems: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Additional Items' } },
228
+ items: { default: [], bindings: { 'field-type': 'array', 'label': 'Items' } },
229
+ default: { default: [], bindings: { 'field-type': 'array', 'label': 'Default' } },
230
+ examples: { default: [], bindings: { 'field-type': 'array', 'label': 'Examples' } },
231
+ },
232
+ object: {
233
+ required: { default: [], bindings: { 'field-type': 'stringArray', 'label': 'Required' } },
234
+ additionalProperties: { default: false, bindings: { 'field-type': 'boolean', 'label': 'Additional Properties' } },
235
+ minProperties: { default: 0, bindings: { 'field-type': 'integer', 'label': 'Minimum Properties' } },
236
+ maxProperties: { default: 10, bindings: { 'field-type': 'integer', 'label': 'Maximum Properties' } },
237
+ },
238
+ }
239
+
240
+ const clearExtraFields = () => {
241
+ if (!props.forFunctions) {
242
+ return
243
+ }
244
+ state.fieldInsert = {
245
+ key: state.fieldInsert.key,
246
+ type: state.fieldInsert.type,
247
+ description: state.fieldInsert.description,
248
+ required: state.fieldInsert.required,
249
+ }
250
+ // const extraFields = extraTypeFields[state.fieldInsert.type]
251
+ // Object.keys(extraFields).forEach((field) => {
252
+ // state.fieldInsert[field] = extraFields[field].default
253
+ // })
254
+ }
255
+
256
+ // eslint-disable-next-line vue/no-dupe-keys
257
+ const modelValue = ref(null)
258
+
259
+ const refreshArray = ref(true)
260
+ const addArray = () => {
261
+ if (state.arrayAdd === null || state.arrayAdd === '') {
262
+ return
263
+ }
264
+ if (typeof state.arrayAdd !== 'string' && isNaN(state.arrayAdd)) {
265
+ return
266
+ }
267
+ if (modelValue.value.includes(state.arrayAdd)) {
268
+ return
269
+ }
270
+ modelValue.value.push(state.arrayAdd)
271
+ state.arrayAdd = null
272
+ refreshArray.value = false
273
+ nextTick(() => {
274
+ refreshArray.value = true
275
+ })
276
+ }
277
+
278
+ const editField = (item) => {
279
+ state.isEditing = true
280
+ state.fieldInsert = edgeGlobal.dupObject(modelValue.value[item.key])
281
+ state.fieldInsertDialog = true
282
+ }
283
+
284
+ const addField = async () => {
285
+ let fieldId = generateShortId()
286
+ if (state.fieldInsert?.fieldId) {
287
+ fieldId = state.fieldInsert.fieldId
288
+ }
289
+ if (props.fieldType === 'object') {
290
+ if (!state.fieldInsert.key) {
291
+ state.fieldInsertKeyRequired = true
292
+ state.fieldErrorMessage = 'Key is required'
293
+ return
294
+ }
295
+ if (!state.isEditing) {
296
+ if (Object.keys(modelValue.value).some((k) => {
297
+ return k.toLowerCase() === state.fieldInsert.key.toLowerCase()
298
+ })) {
299
+ state.fieldInsertKeyRequired = true
300
+ state.fieldErrorMessage = 'Key already exists'
301
+ return
302
+ }
303
+ state.order.push({ key: state.fieldInsert.key })
304
+ }
305
+ }
306
+ if (props.fieldType === 'array') {
307
+ let value = null
308
+ if (state.fieldInsert.type === 'string') {
309
+ value = ''
310
+ }
311
+ else if (state.fieldInsert.type === 'boolean') {
312
+ value = false
313
+ }
314
+ else if (state.fieldInsert.type === 'array') {
315
+ value = []
316
+ }
317
+ else if (state.fieldInsert.type === 'object') {
318
+ value = {}
319
+ }
320
+ else if (state.fieldInsert.type === 'number') {
321
+ value = 0
322
+ }
323
+ else if (state.fieldInsert.type === 'integer') {
324
+ value = 0
325
+ }
326
+ let finalValue = null
327
+ if (props.forFunctions) {
328
+ finalValue = {
329
+ fieldId,
330
+ gptGenerated: true,
331
+ value,
332
+ ...state.fieldInsert,
333
+ }
334
+ }
335
+ else {
336
+ finalValue = value
337
+ }
338
+ console.log(state.isEditing)
339
+ if (state.isEditing) {
340
+ modelValue.value[0] = finalValue
341
+ }
342
+ else {
343
+ modelValue.value.push(finalValue)
344
+ }
345
+ state.order = modelValue.value.map((value, index) => {
346
+ return {
347
+ key: index,
348
+ value,
349
+ }
350
+ })
351
+ // state.order.push({ key: state.order.length, value: arrayValue })
352
+
353
+ state.fieldInsert.key = ''
354
+ state.fieldInsert.description = ''
355
+ state.fieldInsert.type = 'string'
356
+ if (props.forFunctions) {
357
+ state.fieldInsert.required = false
358
+ clearExtraFields()
359
+ }
360
+ state.fieldInsertKeyRequired = false
361
+ state.fieldErrorMessage = ''
362
+ state.isEditing = false
363
+ state.fieldInsertDialog = false
364
+ return
365
+ }
366
+ if (!state.fieldInsert.key) {
367
+ state.fieldInsertKeyRequired = true
368
+ state.fieldErrorMessage = 'Key is required'
369
+ return
370
+ }
371
+ if (!state.isEditing) {
372
+ if (Object.keys(modelValue.value).some((k) => {
373
+ return k.toLowerCase() === state.fieldInsert.key.toLowerCase()
374
+ })) {
375
+ state.fieldInsertKeyRequired = true
376
+ state.fieldErrorMessage = 'Key already exists'
377
+ return
378
+ }
379
+ }
380
+ let value = null
381
+ if (state.fieldInsert.type === 'string') {
382
+ value = ''
383
+ }
384
+ else if (state.fieldInsert.type === 'boolean') {
385
+ value = false
386
+ }
387
+ else if (state.fieldInsert.type === 'array') {
388
+ value = []
389
+ }
390
+ else if (state.fieldInsert.type === 'object') {
391
+ value = {}
392
+ }
393
+ else if (state.fieldInsert.type === 'number') {
394
+ value = 0
395
+ }
396
+ else if (state.fieldInsert.type === 'integer') {
397
+ value = 0
398
+ }
399
+ let finalValue = null
400
+ if (props.forFunctions) {
401
+ finalValue = {
402
+ fieldId,
403
+ gptGenerated: true,
404
+ value,
405
+ ...state.fieldInsert,
406
+ }
407
+ }
408
+ else {
409
+ finalValue = value
410
+ }
411
+ const existingFieldIndex = Object.values(modelValue.value).findIndex(item => item.fieldId === fieldId)
412
+
413
+ if (existingFieldIndex !== -1) {
414
+ if (modelValue.value[existingFieldIndex]?.value) {
415
+ finalValue.value = modelValue.value[existingFieldIndex].value
416
+ }
417
+ const oldKey = Object.keys(modelValue.value)[existingFieldIndex]
418
+ delete modelValue.value[oldKey]
419
+ modelValue.value[state.fieldInsert.key] = finalValue
420
+ const orderIndex = state.order.findIndex(item => item.key === oldKey)
421
+ if (orderIndex !== -1) {
422
+ state.order[orderIndex].key = state.fieldInsert.key
423
+ }
424
+ }
425
+ else {
426
+ modelValue.value[state.fieldInsert.key] = finalValue
427
+ }
428
+ modelValue.value[state.fieldInsert.key] = finalValue
429
+ state.fieldInsert.key = ''
430
+ state.fieldInsert.description = ''
431
+ state.isEditing = false
432
+ if (props.forFunctions) {
433
+ state.fieldInsert.required = false
434
+ clearExtraFields()
435
+ }
436
+ state.fieldInsertDialog = false
437
+ state.fieldInsertKeyRequired = false
438
+ state.fieldErrorMessage = ''
439
+ }
440
+
441
+ const typeColor = (fieldType) => {
442
+ console.log('typeColor')
443
+ console.log(fieldType)
444
+ if (fieldType === 'string') {
445
+ return '#0d47a1' // dark blue
446
+ }
447
+ if (fieldType === 'boolean') {
448
+ return '#2e7d32' // dark green
449
+ }
450
+ if (fieldType === 'array') {
451
+ return '#424242' // dark grey
452
+ }
453
+ if (fieldType === 'object') {
454
+ return '#1565c0' // darker light blue
455
+ }
456
+ if (fieldType === 'number' || fieldType === 'integer') {
457
+ return '#000000' // black
458
+ }
459
+ return '#0d47a1' // dark blue
460
+ }
461
+
462
+ const removeField = (key) => {
463
+ if (props.fieldType === 'array') {
464
+ modelValue.value.splice(key, 1)
465
+ if (modelValue.value.length === 0) {
466
+ modelValue.value = []
467
+ state.order = []
468
+ }
469
+ else {
470
+ state.order = modelValue.value.map((value, index) => {
471
+ return {
472
+ key: index,
473
+ value,
474
+ }
475
+ })
476
+ }
477
+ state.removeField = null
478
+ return
479
+ }
480
+ delete modelValue.value[key]
481
+ state.order = state.order.filter((k) => {
482
+ return k.key !== key
483
+ })
484
+ state.removeField = null
485
+ }
486
+
487
+ const undo = async () => {
488
+ modelValue.value = edgeGlobal.dupObject(edgeGlobal.edgeState.changeTracker[state.trackerKey])
489
+ if (props.fieldType === 'array') {
490
+ if (modelValue.value === null) {
491
+ state.order = []
492
+ }
493
+ else {
494
+ state.order = modelValue.value.map((value, index) => {
495
+ return {
496
+ key: index,
497
+ value,
498
+ }
499
+ })
500
+ }
501
+ }
502
+ if (props.fieldType === 'object') {
503
+ if (!edgeGlobal.objHas(modelValue.value, 'flingKeyOrder')) {
504
+ state.order = Object.entries(modelValue.value).map(([key, value]) => {
505
+ return {
506
+ key,
507
+ }
508
+ }).filter((k) => {
509
+ return k.key !== 'flingKeyOrder'
510
+ })
511
+ }
512
+ else {
513
+ state.order = edgeGlobal.dupObject(modelValue.value.flingKeyOrder)
514
+ }
515
+ }
516
+ state.loaded = false
517
+ await nextTick()
518
+ state.loaded = true
519
+ }
520
+
521
+ onBeforeMount(async () => {
522
+ if (props.forFunctions) {
523
+ state.fieldInsert.required = false
524
+ state.fieldInsert.description = ''
525
+ }
526
+ modelValue.value = edgeGlobal.dupObject(props.modelValue)
527
+ if (props.fieldType === 'objectList') {
528
+ props.modelValue.forEach((item, index) => {
529
+ state.objectListOriginalOrder[item.id] = index
530
+ })
531
+ }
532
+ if (props.fieldType === 'object') {
533
+ if (!edgeGlobal.objHas(props.modelValue, 'flingKeyOrder')) {
534
+ if (props.modelValue === null) {
535
+ state.order = []
536
+ }
537
+ else {
538
+ state.order = Object.entries(props.modelValue).map(([key, value]) => {
539
+ return {
540
+ key,
541
+ }
542
+ }).filter((k) => {
543
+ return k.key !== 'flingKeyOrder'
544
+ })
545
+ }
546
+ }
547
+ else {
548
+ state.order = edgeGlobal.dupObject(props.modelValue.flingKeyOrder)
549
+ }
550
+ }
551
+ if (props.fieldType === 'array') {
552
+ if (props.modelValue === null) {
553
+ state.order = []
554
+ }
555
+ else {
556
+ state.order = props.modelValue.map((value, index) => {
557
+ return {
558
+ key: index,
559
+ value,
560
+ }
561
+ })
562
+ }
563
+ }
564
+ if (props.fieldType === 'collection') {
565
+ if (props.collectionPath) {
566
+ // only if startSnapshot is not already running
567
+ if (edgeGlobal.objHas(edgeFirebase.data, props.collectionPath) === false) {
568
+ console.log('startSnapshot')
569
+ await edgeFirebase.startSnapshot(props.collectionPath)
570
+ console.log(edgeFirebase.data[props.collectionPath])
571
+ }
572
+ }
573
+ }
574
+ state.loaded = true
575
+ })
576
+
577
+ const collectionItems = computed(() => {
578
+ if (!props.collectionPath || !props.collectionTitleField) {
579
+ return []
580
+ }
581
+ if (edgeGlobal.objHas(edgeFirebase.data, props.collectionPath) === false) {
582
+ return []
583
+ }
584
+ // if collection props.collectionValueField is the same as props.collectionTitleField return an a array of vaules of the title field
585
+ if (props.collectionValueField === props.collectionTitleField) {
586
+ return Object.values(edgeFirebase.data[props.collectionPath]).map(item => item[props.collectionTitleField])
587
+ }
588
+ return Object.values(edgeFirebase.data[props.collectionPath]).map(item => ({
589
+ title: item[props.collectionTitleField],
590
+ value: item.docId,
591
+ }))
592
+ })
593
+
594
+ watch (() => state.removeField, () => {
595
+ if (state.removeField !== null) {
596
+ state.removeFieldDialogShow = true
597
+ }
598
+ else {
599
+ state.removeFieldDialogShow = false
600
+ }
601
+ })
602
+
603
+ const originalCompare = computed(() => {
604
+ if (props.fieldType === 'objectList' || props.fieldType === 'object' || props.fieldType === 'array' || returnObject) {
605
+ return JSON.stringify(edgeGlobal.edgeState.changeTracker[state.trackerKey])
606
+ }
607
+ else {
608
+ return edgeGlobal.edgeState.changeTracker[state.trackerKey]
609
+ }
610
+ })
611
+
612
+ const isTracked = computed(() => {
613
+ return edgeGlobal.objHas(edgeGlobal.edgeState.changeTracker, state.trackerKey)
614
+ })
615
+
616
+ const modelCompare = computed(() => {
617
+ if (props.fieldType === 'objectList' || props.fieldType === 'object' || props.fieldType === 'array' || returnObject) {
618
+ return JSON.stringify(modelValue.value)
619
+ }
620
+ else {
621
+ return modelValue.value
622
+ }
623
+ })
624
+
625
+ const getArrayObjectLabel = (key) => {
626
+ if (props.fieldType === 'object') {
627
+ return key
628
+ }
629
+ else {
630
+ if (props.forFunctions) {
631
+ return 'Array Item Params'
632
+ }
633
+ return `Array Item #${key + 1}`
634
+ }
635
+ }
636
+
637
+ const openKeyMenu = (key) => {
638
+ state.keyMenu = true
639
+ state.currentKey = key
640
+ state.newKey = key
641
+ }
642
+
643
+ const updateKey = async () => {
644
+ const keyArray = Object.keys(modelValue.value)
645
+ const keyIndex = keyArray.findIndex(k => k === state.currentKey)
646
+ keyArray[keyIndex] = state.newKey
647
+
648
+ const value = modelValue.value[state.currentKey]
649
+ delete modelValue.value[state.currentKey]
650
+
651
+ const newObject = {}
652
+ keyArray.forEach((k) => {
653
+ if (k === state.newKey) {
654
+ newObject[k] = value
655
+ }
656
+ else {
657
+ newObject[k] = modelValue.value[k]
658
+ }
659
+ })
660
+
661
+ const newItem = { key: state.newKey }
662
+ const index = state.order.findIndex(item => item.key === state.currentKey)
663
+ if (index !== -1) {
664
+ state.order.splice(index, 1, newItem)
665
+ }
666
+ modelValue.value = newObject
667
+ state.keyMenu = false
668
+ }
669
+
670
+ const isNumber = (value) => {
671
+ return !isNaN(parseFloat(value)) && isFinite(value)
672
+ }
673
+
674
+ onMounted(() => {
675
+ state.trackerKey = (`${props.parentTrackerId}-${props.label.replaceAll(' ', '-')}`).toLowerCase()
676
+ if (!edgeGlobal.objHas(edgeGlobal.edgeState.changeTracker, state.trackerKey)) {
677
+ if (!props.disableTracking) {
678
+ edgeGlobal.edgeState.changeTracker[state.trackerKey] = edgeGlobal.dupObject(modelValue.value)
679
+ }
680
+ }
681
+ state.afterMount = true
682
+ })
683
+
684
+ const userItem = (id) => {
685
+ if (!edgeGlobal.objHas(edgeFirebase.state.users, id)) {
686
+ return ''
687
+ }
688
+ if (!edgeGlobal.objHas(edgeFirebase.state.users[id], 'meta')) {
689
+ return ''
690
+ }
691
+ if (!edgeGlobal.objHas(edgeFirebase.state.users[id].meta, 'name')) {
692
+ return ''
693
+ }
694
+ return edgeFirebase.state.users[id].meta.name
695
+ }
696
+
697
+ const collectionItem = (id) => {
698
+ if (!props.collectionPath || !props.collectionTitleField) {
699
+ return ''
700
+ }
701
+ if (!edgeGlobal.objHas(edgeFirebase.data, props.collectionPath)) {
702
+ return ''
703
+ }
704
+ if (!edgeGlobal.objHas(edgeFirebase.data[props.collectionPath], id)) {
705
+ return ''
706
+ }
707
+ if (!edgeGlobal.objHas(edgeFirebase.data[props.collectionPath][id], props.collectionTitleField)) {
708
+ return ''
709
+ }
710
+ return edgeFirebase.data[props.collectionPath][id][props.collectionTitleField]
711
+ }
712
+
713
+ const validateInput = (event) => {
714
+ // Allow keys that don't result in character input.
715
+ if (['Backspace', 'Delete', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Tab'].includes(event.key)) {
716
+ return
717
+ }
718
+
719
+ // Create a copy of the value that would result from this keypress.
720
+ const proposedValue = event.target.value + event.key
721
+
722
+ // Create a regex that matches valid inputs: up to one decimal point, and up to two digits after the decimal point.
723
+ const regex = /^\d*\.?\d{0,2}$/
724
+
725
+ // If the proposed value doesn't match the regex, prevent the keypress.
726
+ if (!regex.test(proposedValue)) {
727
+ event.preventDefault()
728
+ }
729
+ }
730
+ watch(() => props.modelValue, (newValue) => {
731
+ if (state.afterMount) {
732
+ if (props.fieldType === 'objectList') {
733
+ // Only update if the objects are different and newValue is not undefined
734
+ if (newValue !== undefined && JSON.stringify(modelValue.value) !== JSON.stringify(newValue)) {
735
+ modelValue.value = edgeGlobal.dupObject(newValue)
736
+ }
737
+ }
738
+ }
739
+ // console.log('order changed')
740
+ })
741
+
742
+ watch(() => state.order, () => {
743
+ if (props.fieldType === 'object') {
744
+ modelValue.value.flingKeyOrder = edgeGlobal.dupObject(state.order)
745
+ }
746
+ if (props.fromFunctions) {
747
+ return
748
+ }
749
+ console.log('order changed')
750
+ if (props.fieldType === 'array') {
751
+ if (!state.orderUpdateFromWatcher) {
752
+ if (state.order.length > 0) {
753
+ const currentValues = edgeGlobal.dupObject(modelValue.value)
754
+ modelValue.value = state.order.map((item) => {
755
+ return currentValues[item.key]
756
+ })
757
+
758
+ state.orderUpdateFromWatcher = true
759
+ if (modelValue.value.some(item => typeof item !== 'object' || item === null)) {
760
+ state.order = modelValue.value.map((value, index) => {
761
+ return {
762
+ key: index,
763
+ value,
764
+ }
765
+ })
766
+ }
767
+ }
768
+ }
769
+ }
770
+ },
771
+ { deep: true })
772
+
773
+ const fieldInsertType = computed(() => {
774
+ return state.fieldInsert.type
775
+ })
776
+
777
+ watch(fieldInsertType, (newValue, oldValue) => {
778
+ if (state.isEditing) {
779
+ return
780
+ }
781
+ if (oldValue !== newValue) {
782
+ console.log('fieldInsertType changed')
783
+ clearExtraFields()
784
+ }
785
+ })
786
+
787
+ watch(() => state.fieldInsertDialog, () => {
788
+ if (!state.fieldInsertDialog) {
789
+ state.isEditing = false
790
+ }
791
+ if (state.isEditing) {
792
+ return
793
+ }
794
+ if (state.fieldInsertDialog) {
795
+ if (props.fieldType === 'array') {
796
+ if (!props.forFunctions) {
797
+ // addField()
798
+ }
799
+ }
800
+ }
801
+ else {
802
+ state.fieldInsert.key = ''
803
+ if (props.forFunctions) {
804
+ state.fieldInsert.required = false
805
+ clearExtraFields()
806
+ }
807
+ state.fieldInsertKeyRequired = false
808
+ state.fieldErrorMessage = ''
809
+ }
810
+ },
811
+ { deep: true })
812
+
813
+ watch(modelValue, () => {
814
+ if (state.afterMount) {
815
+ emit('update:modelValue', modelValue.value)
816
+ }
817
+ if (props.fieldType === 'array') {
818
+ state.orderUpdateFromWatcher = false
819
+ }
820
+ }, { deep: true })
821
+ </script>
822
+
823
+ <template>
824
+ <div v-if="state.loaded">
825
+ <edge-shad-combobox
826
+ v-if="props.fieldType === 'collection'" v-model="modelValue" :label="props.label"
827
+ :items="collectionItems" v-bind="props.bindings" :disabled="props.disabled" :name="props.name" item-value="value"
828
+ item-title="title" :placeholder="`${props.label}...`"
829
+ class="w-full"
830
+ >
831
+ <template v-if="props.helper" #append>
832
+ <edge-g-helper :title="props.label" :helper="props.helper" />
833
+ </template>
834
+ </edge-shad-combobox>
835
+ <Card
836
+ v-if="props.fieldType === 'stringArray' || props.fieldType === 'numberArray' || props.fieldType === 'intArray'"
837
+ class="p-1"
838
+ >
839
+ <CardHeader class="px-3 py-2">
840
+ <CardTitle class="text-md">
841
+ <div class="flex items-center">
842
+ <div class="grow">
843
+ {{ props.label }}
844
+ </div>
845
+ <div v-if="props.helper">
846
+ <edge-g-helper :title="props.label" :helper="props.helper" />
847
+ </div>
848
+ </div>
849
+ </CardTitle>
850
+ <CardDescription v-if="props?.description">
851
+ {{ props.description }}
852
+ </CardDescription>
853
+ </CardHeader>
854
+ <CardContent>
855
+ <div v-if="refreshArray" class="flex items-center w-full">
856
+ <div class="grow">
857
+ <edge-shad-number
858
+ v-if="props.fieldType === 'numberArray'" v-model="state.arrayAdd" :step=".1"
859
+ :name="`${props.name}Input`" v-bind="props.bindings" class="w-full"
860
+ />
861
+ <edge-shad-number
862
+ v-else-if="props.fieldType === 'intArray'" v-model="state.arrayAdd" :step="1"
863
+ :name="`${props.name}Input`" :format-options="{ maximumFractionDigits: 0 }" v-bind="props.bindings"
864
+ />
865
+ <edge-shad-input v-else v-model="state.arrayAdd" :name="`${props.name}Input`" />
866
+ </div>
867
+ <edge-shad-button
868
+ variant="ghost" size="icon" class="text-slate-800 hover:bg-slate-400"
869
+ @click.stop.prevent="addArray"
870
+ >
871
+ <ListPlus width="16" height="16" />
872
+ </edge-shad-button>
873
+ </div>
874
+
875
+ <div>
876
+ <draggable v-model="modelValue" handle=".handle" item-key="key">
877
+ <template #item="{ element }">
878
+ <div :key="element" class="flex items-center w-full py-1 odd:bg-slate-100 even:bg-slate-200">
879
+ <div class="px-2 text-left">
880
+ <Grip class="handle pointer" />
881
+ </div>
882
+ <div class="px-2 grow">
883
+ {{ element }}
884
+ </div>
885
+ <div class="pr-1">
886
+ <edge-shad-button class="text-white bg-slate-800 hover:bg-slate-400" size="icon" @click="modelValue.splice(modelValue.indexOf(element), 1)">
887
+ <Trash width="16" height="16" />
888
+ </edge-shad-button>
889
+ </div>
890
+ </div>
891
+ </template>
892
+ </draggable>
893
+ </div>
894
+ </CardContent>
895
+ </Card>
896
+ <edge-shad-select
897
+ v-if="props.fieldType === 'users'" v-model="modelValue" :label="props.label"
898
+ v-bind="props.bindings" :items="Object.values(edgeFirebase.state.users).filter(user => user.uid !== '')"
899
+ item-title="meta.name" item-value="uid" :disabled="props.disabled" :name="props.name" :description="props.hint"
900
+ >
901
+ <template v-if="props.helper" #icon>
902
+ <edge-g-helper :title="props.label" :helper="props.helper" />
903
+ </template>
904
+ </edge-shad-select>
905
+ <edge-shad-number
906
+ v-if="props.fieldType === 'number'" v-model="modelValue" :step=".1" :name="props.name"
907
+ :disabled="props.disabled" v-bind="props.bindings" :label="props.label" :description="props.hint"
908
+ >
909
+ <template v-if="props.helper">
910
+ <edge-g-helper :title="props.label" :helper="props.helper" />
911
+ </template>
912
+ </edge-shad-number>
913
+ <edge-shad-number
914
+ v-if="props.fieldType === 'integer'" v-model="modelValue" :step="1" :name="props.name"
915
+ :disabled="props.disabled" v-bind="props.bindings" :label="props.label" :description="props.hint"
916
+ :format-options="{ maximumFractionDigits: 0 }"
917
+ >
918
+ <template v-if="props.helper">
919
+ <edge-g-helper :title="props.label" :helper="props.helper" />
920
+ </template>
921
+ </edge-shad-number>
922
+ <edge-shad-type-money
923
+ v-if="props.fieldType === 'money'" v-model="modelValue" :step=".1" :name="props.name"
924
+ :disabled="props.disabled" v-bind="props.bindings" :label="props.label" :description="props.hint" :format-options="{
925
+ style: 'currency',
926
+ currency: 'USD',
927
+ currencyDisplay: 'symbol',
928
+ currencySign: 'accounting',
929
+ }"
930
+ >
931
+ <template v-if="props.helper">
932
+ <edge-g-helper :title="props.label" :helper="props.helper" />
933
+ </template>
934
+ </edge-shad-type-money>
935
+ <edge-shad-input
936
+ v-if="props.fieldType === 'text'" v-model="modelValue" v-maska:[props.maskOptions] type="text"
937
+ :name="props.name" v-bind="props.bindings" :label="props.label" :disabled="props.disabled"
938
+ :description="props.hint"
939
+ >
940
+ <template #icon>
941
+ <edge-g-helper v-if="props.helper" :title="props.label" :helper="props.helper" />
942
+ </template>
943
+ </edge-shad-input>
944
+ <edge-shad-checkbox
945
+ v-if="props.fieldType === 'boolean'" v-model="modelValue" :name="props.name"
946
+ v-bind="props.bindings"
947
+ >
948
+ {{ props.label }}
949
+ <template #icon>
950
+ <edge-g-helper v-if="props.helper" :title="props.label" :helper="props.helper" />
951
+ </template>
952
+ </edge-shad-checkbox>
953
+ <edge-shad-combobox
954
+ v-if="props.fieldType === 'combobox'" v-model="modelValue" :label="props.label"
955
+ :items="props.items" v-bind="props.bindings" :disabled="props.disabled" :name="props.name"
956
+ :item-value="props.valueField" :item-title="props.titleField" :placeholder="`${props.label}...`"
957
+ >
958
+ <template v-if="props.helper" #append>
959
+ <edge-g-helper :title="props.label" :helper="props.helper" />
960
+ </template>
961
+ </edge-shad-combobox>
962
+ <edge-shad-select
963
+ v-if="props.fieldType === 'select'" v-model="modelValue" :label="props.label" :items="props.items"
964
+ v-bind="props.bindings" :disabled="props.disabled" :name="props.name"
965
+ >
966
+ <template v-if="props.helper" #icon>
967
+ <edge-g-helper :title="props.label" :helper="props.helper" />
968
+ </template>
969
+ </edge-shad-select>
970
+ <edge-shad-textarea
971
+ v-if="props.fieldType === 'textarea'" v-model="modelValue" v-maska:[props.maskOptions]
972
+ type="text" :name="props.name" v-bind="props.bindings" :label="props.label" :disabled="props.disabled"
973
+ >
974
+ <template v-if="props.helper" #icon>
975
+ <edge-g-helper :title="props.label" :helper="props.helper" />
976
+ </template>
977
+ </edge-shad-textarea>
978
+ <edge-shad-tags
979
+ v-if="props.fieldType === 'tags'" v-model="modelValue" type="text" :name="props.name"
980
+ v-bind="props.bindings" :label="props.label" :disabled="props.disabled" :value-as="props.bindings['value-as']"
981
+ >
982
+ <template v-if="props.helper" #icon>
983
+ <edge-g-helper :title="props.label" :helper="props.helper" />
984
+ </template>
985
+ </edge-shad-tags>
986
+ <template v-if="props.fieldType === 'object' || props.fieldType === 'array'">
987
+ <edge-shad-dialog v-model="state.keyMenu">
988
+ <DialogContent>
989
+ <DialogHeader>
990
+ <DialogTitle>
991
+ <span v-if="props.fieldType === 'object'">
992
+ Update Key
993
+ </span>
994
+ <span v-else>
995
+ Add Item
996
+ </span>
997
+ </DialogTitle>
998
+ </DialogHeader>
999
+ <DialogDescription />
1000
+ <edge-shad-input v-model="state.newKey" name="key" class="mb-1" label="Key" v-bind="props.bindings" />
1001
+ <DialogFooter class="flex justify-between pt-6">
1002
+ <edge-shad-button variant="destructive" @click="state.keyMenu = false">
1003
+ Cancel
1004
+ </edge-shad-button>
1005
+ <edge-shad-button class="w-full text-white bg-slate-800 hover:bg-slate-400" @click="updateKey">
1006
+ Submit
1007
+ </edge-shad-button>
1008
+ </DialogFooter>
1009
+ </DialogContent>
1010
+ </edge-shad-dialog>
1011
+ <Card
1012
+ v-if="!(props.forFunctions && modelValue.length >= 1)" class="p-0"
1013
+ :class="state.forFunctions ? '' : 'bg-transparent mb-1'"
1014
+ >
1015
+ <CardHeader class="p-2" :class="state.forFunctions ? '' : 'bg-transparent'">
1016
+ <div class="flex justify-between w-full">
1017
+ <div v-if="!props.forFunctions" class="flex items-center">
1018
+ <Braces v-if="props.fieldType === 'object'" class="mx-2" />
1019
+
1020
+ <Brackets v-else class="mx-2" />
1021
+
1022
+ <div>
1023
+ {{ props.label }}
1024
+ </div>
1025
+ </div>
1026
+ <div class="flex items-center">
1027
+ <edge-shad-button
1028
+ v-if="!props.staticObject" class="h-6 mx-2 text-xs bg-slate-500"
1029
+ @click.stop.prevent="state.fieldInsertDialog = true"
1030
+ >
1031
+ <template v-if="props.fieldType === 'object'">
1032
+ Add Field
1033
+ </template>
1034
+ <template v-else>
1035
+ <template v-if="props.forFunctions">
1036
+ Array Item Params
1037
+ </template>
1038
+ <template v-else>
1039
+ Add Item
1040
+ </template>
1041
+ </template>
1042
+ </edge-shad-button>
1043
+ <edge-g-helper v-if="props.helper" :title="props.label" :helper="props.helper" />
1044
+ </div>
1045
+ </div>
1046
+ </CardHeader>
1047
+ <CardContent class="px-2 py-0">
1048
+ <draggable v-model="state.order" handle=".handle" item-key="key">
1049
+ <template #item="{ element }">
1050
+ <div :key="element.key" class="w-full">
1051
+ <div class="flex items-center justify-between w-full py-1">
1052
+ <div v-if="!staticObject" class="px-2 text-left">
1053
+ <Grip class="handle pointer" />
1054
+ </div>
1055
+ <div v-show="props.fieldType !== 'array'" class="w-1/6 mr-2 text-left">
1056
+ <template v-if="modelValue[element.key].gptGenerated">
1057
+ <edge-shad-button class="h-6 mx-2 text-xs bg-slate-500" @click.prevent.stop="editField(element)">
1058
+ {{ element.key }}
1059
+ </edge-shad-button>
1060
+ </template>
1061
+ <edge-shad-button
1062
+ v-else-if="!props.staticObject" class="h-6 mx-2 text-xs bg-slate-500"
1063
+ @click.prevent.stop="openKeyMenu(element.key)"
1064
+ >
1065
+ {{ element.key }}
1066
+ </edge-shad-button>
1067
+ </div>
1068
+ <div v-if="props.fieldType === 'array'">
1069
+ <edge-shad-button
1070
+ v-if="props.forFunctions" class="h-6 mx-2 text-xs bg-slate-500"
1071
+ @click.prevent.stop="editField(element)"
1072
+ >
1073
+ <Pencil width="16" height="16" />
1074
+ {{ element.value.type }}
1075
+ </edge-shad-button>
1076
+ </div>
1077
+ <div class="py-0 text-right grow">
1078
+ <template v-if="modelValue[element.key].gptGenerated || props.forFunctions">
1079
+ <edge-function-chips class="mt-5" :field="modelValue[element.key]" />
1080
+ </template>
1081
+ <template v-else-if="typeof modelValue[element.key] !== 'object'">
1082
+ <edge-shad-input
1083
+ v-if="typeof modelValue[element.key] === 'string'"
1084
+ v-model="modelValue[element.key]" v-bind="props.bindings" placeholder="Enter value here"
1085
+ :label="!props.staticObject ? '' : element.key" :name="`${props.name}.${element.key}`"
1086
+ />
1087
+ <edge-shad-checkbox
1088
+ v-else-if="typeof modelValue[element.key] === 'boolean'"
1089
+ v-model="modelValue[element.key]" class="mb-1" v-bind="props.bindings"
1090
+ :name="`${props.name}.${element.key}`"
1091
+ >
1092
+ {{ getArrayObjectLabel(element.key) }}
1093
+ </edge-shad-checkbox>
1094
+ <edge-shad-number
1095
+ v-else-if="typeof modelValue[element.key] === 'number'"
1096
+ v-model="modelValue[element.key]" :step=".1" :name="`${props.name}.${element.key}`"
1097
+ v-bind="props.bindings"
1098
+ />
1099
+ </template>
1100
+ <template v-else>
1101
+ <Separator class="dark:bg-slate-600" />
1102
+ </template>
1103
+ </div>
1104
+ <edge-shad-button
1105
+ v-if="!props.staticObject" variant="text" size="icon"
1106
+ @click.prevent.stop="state.removeField = element.key"
1107
+ >
1108
+ <Trash width="18" height="18" />
1109
+ </edge-shad-button>
1110
+ </div>
1111
+ <div v-if="typeof modelValue[element.key] === 'object'" class="w-full py-1">
1112
+ <edge-g-input
1113
+ v-model="modelValue[element.key]" :name="element.key"
1114
+ :for-functions="props.forFunctions" :bindings="props.bindings"
1115
+ :label="getArrayObjectLabel(element.key)" :disable-tracking="true"
1116
+ :field-type="Array.isArray(modelValue[element.key]) ? 'array' : 'object'"
1117
+ />
1118
+ </div>
1119
+ </div>
1120
+ </template>
1121
+ </draggable>
1122
+ <edge-shad-dialog v-model="state.removeFieldDialogShow">
1123
+ <DialogContent>
1124
+ <DialogHeader>
1125
+ <DialogTitle>
1126
+ Delete "{{ getArrayObjectLabel (state.removeField) }}"
1127
+ </DialogTitle>
1128
+ <DialogDescription class="mt-3">
1129
+ Are you sure you want to delete "{{ getArrayObjectLabel(state.removeField) }}"?
1130
+ </DialogDescription>
1131
+ </DialogHeader>
1132
+ <DialogFooter class="flex justify-between pt-6">
1133
+ <edge-shad-button class="text-white bg-slate-800 hover:bg-slate-400" @click="state.removeField = null">
1134
+ Cancel
1135
+ </edge-shad-button>
1136
+ <edge-shad-button variant="destructive" class="w-full" @click="removeField(state.removeField)">
1137
+ Delete
1138
+ </edge-shad-button>
1139
+ </DialogFooter>
1140
+ </DialogContent>
1141
+ </edge-shad-dialog>
1142
+ </CardContent>
1143
+ </Card>
1144
+ </template>
1145
+ <template v-if="props.fieldType === 'objectList'">
1146
+ <Card class="px-0 bg-transparent border-0 shadow-none">
1147
+ <CardHeader class="px-0 pt-3 pb-2">
1148
+ <CardTitle class="flex items-center text-lg">
1149
+ <div :class="{ 'text-red-500': props.errors.length > 0 }">
1150
+ {{ props.label }}
1151
+ </div>
1152
+ <div class="text-right grow">
1153
+ <component
1154
+ :is="resolveComponent(`edge-form-subtypes-${props.subFieldType}`)" v-model:items="modelValue"
1155
+ :pass-through-props="passThroughProps"
1156
+ />
1157
+ </div>
1158
+ <edge-g-helper v-if="props.helper" :title="props.label" :helper="props.helper" />
1159
+ </CardTitle>
1160
+ <CardDescription>
1161
+ <span v-if="props.errors" class="text-red-500">
1162
+ {{ props.errors }}
1163
+ </span>
1164
+ <Separator />
1165
+ </CardDescription>
1166
+ </CardHeader>
1167
+ <CardContent class="px-0 mt-0">
1168
+ <draggable v-model="modelValue" handle=".handle" item-key="id">
1169
+ <template #item="{ element, index }">
1170
+ <div>
1171
+ <component
1172
+ :is="resolveComponent(`edge-form-subtypes-${props.subFieldType}`)" v-model:items="modelValue"
1173
+ :item="element" :pass-through-props="passThroughProps"
1174
+ />
1175
+ <Alert
1176
+ v-if="isTracked && state.afterMount && (JSON.stringify(modelValue[index]) !== JSON.stringify(edgeGlobal.edgeState.changeTracker[state.trackerKey][state.objectListOriginalOrder[element.id]]))"
1177
+ class="px-1 py-2 mt-0 mb-3 bg-warning"
1178
+ >
1179
+ <div class="flex flex-wrap items-center justify-center py-0">
1180
+ <div v-if="props.fieldType === 'objectList'" class="flex flex-wrap justify-center grow">
1181
+ This item has been modified
1182
+ </div>
1183
+ <div v-else class="flex flex-wrap justify-center grow">
1184
+ Modified from "{{ originalCompare }}"
1185
+ </div>
1186
+ <div class="text-right">
1187
+ <edge-shad-button
1188
+ class="h-6 mx-2 text-xs text-white bg-slate-700"
1189
+ @click="modelValue[index] = edgeGlobal.edgeState.changeTracker[state.trackerKey][state.objectListOriginalOrder[element.id]]"
1190
+ >
1191
+ Undo
1192
+ </edge-shad-button>
1193
+ </div>
1194
+ </div>
1195
+ </Alert>
1196
+ <Separator class="dark:bg-slate-600" />
1197
+ </div>
1198
+ </template>
1199
+ </draggable>
1200
+ </CardContent>
1201
+ </Card>
1202
+ </template>
1203
+ <Alert
1204
+ v-if="isTracked && state.afterMount && (modelCompare !== originalCompare)"
1205
+ class="px-1 py-2 mt-0 mb-3 bg-warning"
1206
+ >
1207
+ <div class="flex flex-wrap items-center justify-center py-0">
1208
+ <template
1209
+ v-if="props.fieldType === 'objectList' || props.fieldType === 'object' || props.fieldType === 'array' || returnObject"
1210
+ >
1211
+ <div class="justify-center text-center grow">
1212
+ {{ props.label }} has been modified
1213
+ </div>
1214
+ <div class="text-right">
1215
+ <edge-shad-button class="h-6 mx-2 text-xs text-white bg-slate-700" @click="undo()">
1216
+ Undo All
1217
+ </edge-shad-button>
1218
+ </div>
1219
+ </template>
1220
+
1221
+ <template v-else>
1222
+ <div v-if="props.fieldType === 'collection'" class="flex flex-wrap justify-center grow">
1223
+ <template v-if="props.collectionTitleField !== props.collectionValueField">
1224
+ Modified to "{{ collectionItem(modelValue) }}"
1225
+ </template>
1226
+ <template v-else>
1227
+ Modified from "{{ originalCompare }}" to "{{ modelValue }}"
1228
+ </template>
1229
+ </div>
1230
+ <div v-else-if="props.fieldType === 'users'" class="flex flex-wrap justify-center grow">
1231
+ Modified to "{{ userItem(modelValue) }}"
1232
+ </div>
1233
+ <div v-else class="flex flex-wrap justify-center grow">
1234
+ Modified from "{{ originalCompare }}" to "{{ modelValue }}"
1235
+ </div>
1236
+ <div class="text-right">
1237
+ <edge-shad-button class="h-6 mx-2 text-xs text-white bg-slate-700" @click="undo()">
1238
+ Undo
1239
+ </edge-shad-button>
1240
+ </div>
1241
+ </template>
1242
+ </div>
1243
+ </Alert>
1244
+ </div>
1245
+ <edge-shad-dialog v-model="state.fieldInsertDialog">
1246
+ <DialogContent>
1247
+ <DialogHeader>
1248
+ <DialogTitle>
1249
+ <template v-if="!state.isEditing">
1250
+ Add Field
1251
+ </template>
1252
+ <template v-else>
1253
+ Update Field
1254
+ </template>
1255
+ </DialogTitle>
1256
+ </DialogHeader>
1257
+ <DialogDescription />
1258
+ <edge-shad-input
1259
+ v-if="props.fieldType === 'object'" v-model="state.fieldInsert.key" v-bind="props.bindings"
1260
+ label="Field Key" name="key" class="mb-0"
1261
+ />
1262
+ <Alert v-if="state.fieldInsertKeyRequired" class="px-1 py-2 mt-0 mb-3 bg-error">
1263
+ <div class="flex flex-wrap items-center justify-center py-0">
1264
+ <div class="justify-center pl-2 grow text-bold">
1265
+ {{ state.fieldErrorMessage }}
1266
+ </div>
1267
+ </div>
1268
+ </Alert>
1269
+ <edge-shad-select
1270
+ v-if="(fieldTypes.length > 1) || props.forFunctions" v-model="state.fieldInsert.type"
1271
+ :disabled="state.isEditing" v-bind="props.bindings" :items="fieldTypes" label="Type" name="type"
1272
+ />
1273
+ <edge-shad-textarea
1274
+ v-if="props.forFunctions" v-model="state.fieldInsert.description" label="Description"
1275
+ name="description"
1276
+ />
1277
+ <edge-shad-checkbox
1278
+ v-if="props.forFunctions && props.fieldType !== 'array'" v-model="state.fieldInsert.required"
1279
+ label="Field Required" name="required"
1280
+ />
1281
+ <DropdownMenu v-if="props.forFunctions">
1282
+ <DropdownMenuTrigger as-child>
1283
+ <Button variant="outline" class="">
1284
+ Add JSON Schema Params
1285
+ </Button>
1286
+ </DropdownMenuTrigger>
1287
+ <DropdownMenuContent class="w-56">
1288
+ <DropdownMenuGroup>
1289
+ <template v-for="(item, i) in extraTypeFields[state.fieldInsert.type]" :key="i">
1290
+ <DropdownMenuItem
1291
+ v-if="!state.fieldInsert.hasOwnProperty(i)" :key="i" :value="item" color="primary"
1292
+ class="cursor-pointer" @click="state.fieldInsert[i] = item.default"
1293
+ >
1294
+ <span>{{ item.bindings.label }}</span>
1295
+ </DropdownMenuItem>
1296
+ </template>
1297
+ </DropdownMenuGroup>
1298
+ </DropdownMenuContent>
1299
+ </DropdownMenu>
1300
+ <template v-for="(value, key) in state.fieldInsert" :key="key">
1301
+ <edge-g-input
1302
+ v-if="!['type', 'key', 'description', 'required', 'gptGenerated', 'value', 'fieldId'].includes(key)"
1303
+ v-model="state.fieldInsert[key]" :name="key" :disable-tracking="true"
1304
+ v-bind="extraTypeFields[state.fieldInsert.type][key].bindings"
1305
+ />
1306
+ </template>
1307
+ <DialogFooter class="flex justify-between pt-6">
1308
+ <edge-shad-button variant="destructive" @click="state.fieldInsertDialog = false">
1309
+ Cancel
1310
+ </edge-shad-button>
1311
+ <edge-shad-button class="w-full text-white bg-slate-800 hover:bg-slate-400" @click="addField">
1312
+ <template v-if="!state.isEditing">
1313
+ Insert
1314
+ </template>
1315
+ <template v-else>
1316
+ Update
1317
+ </template>
1318
+ </edge-shad-button>
1319
+ </DialogFooter>
1320
+ </DialogContent>
1321
+ </edge-shad-dialog>
1322
+ </template>
1323
+
1324
+ <style lang="scss">
1325
+ .vue-number-input input {
1326
+ background-color: transparent !important;
1327
+ }
1328
+ .pointer {
1329
+ cursor: grab;
1330
+ }
1331
+ </style>