@mongoosejs/studio 0.0.128 → 0.0.130

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.
@@ -618,6 +618,15 @@ video {
618
618
  inset: 0px;
619
619
  }
620
620
 
621
+ .inset-y-0 {
622
+ top: 0px;
623
+ bottom: 0px;
624
+ }
625
+
626
+ .left-0 {
627
+ left: 0px;
628
+ }
629
+
621
630
  .right-0 {
622
631
  right: 0px;
623
632
  }
@@ -662,6 +671,10 @@ video {
662
671
  z-index: 50;
663
672
  }
664
673
 
674
+ .z-\[100\] {
675
+ z-index: 100;
676
+ }
677
+
665
678
  .z-\[9999\] {
666
679
  z-index: 9999;
667
680
  }
@@ -727,10 +740,18 @@ video {
727
740
  margin-bottom: 0.5rem;
728
741
  }
729
742
 
743
+ .mb-3 {
744
+ margin-bottom: 0.75rem;
745
+ }
746
+
730
747
  .mb-4 {
731
748
  margin-bottom: 1rem;
732
749
  }
733
750
 
751
+ .mb-6 {
752
+ margin-bottom: 1.5rem;
753
+ }
754
+
734
755
  .ml-1 {
735
756
  margin-left: 0.25rem;
736
757
  }
@@ -962,6 +983,10 @@ video {
962
983
  width: 1.25rem;
963
984
  }
964
985
 
986
+ .w-52 {
987
+ width: 13rem;
988
+ }
989
+
965
990
  .w-6 {
966
991
  width: 1.5rem;
967
992
  }
@@ -986,6 +1011,10 @@ video {
986
1011
  min-width: 0px;
987
1012
  }
988
1013
 
1014
+ .min-w-\[140px\] {
1015
+ min-width: 140px;
1016
+ }
1017
+
989
1018
  .min-w-full {
990
1019
  min-width: 100%;
991
1020
  }
@@ -1052,6 +1081,21 @@ video {
1052
1081
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1053
1082
  }
1054
1083
 
1084
+ .rotate-0 {
1085
+ --tw-rotate: 0deg;
1086
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1087
+ }
1088
+
1089
+ .rotate-180 {
1090
+ --tw-rotate: 180deg;
1091
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1092
+ }
1093
+
1094
+ .rotate-90 {
1095
+ --tw-rotate: 90deg;
1096
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1097
+ }
1098
+
1055
1099
  .transform {
1056
1100
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
1057
1101
  }
@@ -1104,6 +1148,10 @@ video {
1104
1148
  flex-direction: column;
1105
1149
  }
1106
1150
 
1151
+ .flex-wrap {
1152
+ flex-wrap: wrap;
1153
+ }
1154
+
1107
1155
  .items-start {
1108
1156
  align-items: flex-start;
1109
1157
  }
@@ -1253,10 +1301,18 @@ video {
1253
1301
  white-space: nowrap;
1254
1302
  }
1255
1303
 
1304
+ .whitespace-pre {
1305
+ white-space: pre;
1306
+ }
1307
+
1256
1308
  .whitespace-pre-wrap {
1257
1309
  white-space: pre-wrap;
1258
1310
  }
1259
1311
 
1312
+ .break-words {
1313
+ overflow-wrap: break-word;
1314
+ }
1315
+
1260
1316
  .rounded {
1261
1317
  border-radius: 0.25rem;
1262
1318
  }
@@ -1281,16 +1337,36 @@ video {
1281
1337
  border-radius: 0.125rem;
1282
1338
  }
1283
1339
 
1340
+ .rounded-l-lg {
1341
+ border-top-left-radius: 0.5rem;
1342
+ border-bottom-left-radius: 0.5rem;
1343
+ }
1344
+
1284
1345
  .rounded-l-md {
1285
1346
  border-top-left-radius: 0.375rem;
1286
1347
  border-bottom-left-radius: 0.375rem;
1287
1348
  }
1288
1349
 
1350
+ .rounded-l-none {
1351
+ border-top-left-radius: 0px;
1352
+ border-bottom-left-radius: 0px;
1353
+ }
1354
+
1355
+ .rounded-r-lg {
1356
+ border-top-right-radius: 0.5rem;
1357
+ border-bottom-right-radius: 0.5rem;
1358
+ }
1359
+
1289
1360
  .rounded-r-md {
1290
1361
  border-top-right-radius: 0.375rem;
1291
1362
  border-bottom-right-radius: 0.375rem;
1292
1363
  }
1293
1364
 
1365
+ .rounded-r-none {
1366
+ border-top-right-radius: 0px;
1367
+ border-bottom-right-radius: 0px;
1368
+ }
1369
+
1294
1370
  .border {
1295
1371
  border-width: 1px;
1296
1372
  }
@@ -1311,6 +1387,10 @@ video {
1311
1387
  border-right-width: 1px;
1312
1388
  }
1313
1389
 
1390
+ .border-r-0 {
1391
+ border-right-width: 0px;
1392
+ }
1393
+
1314
1394
  .border-t {
1315
1395
  border-top-width: 1px;
1316
1396
  }
@@ -1319,6 +1399,11 @@ video {
1319
1399
  border-style: none;
1320
1400
  }
1321
1401
 
1402
+ .border-blue-300 {
1403
+ --tw-border-opacity: 1;
1404
+ border-color: rgb(147 197 253 / var(--tw-border-opacity));
1405
+ }
1406
+
1322
1407
  .border-gray-100 {
1323
1408
  --tw-border-opacity: 1;
1324
1409
  border-color: rgb(243 244 246 / var(--tw-border-opacity));
@@ -1334,6 +1419,11 @@ video {
1334
1419
  border-color: rgb(209 213 219 / var(--tw-border-opacity));
1335
1420
  }
1336
1421
 
1422
+ .border-red-500 {
1423
+ --tw-border-opacity: 1;
1424
+ border-color: rgb(239 68 68 / var(--tw-border-opacity));
1425
+ }
1426
+
1337
1427
  .border-transparent {
1338
1428
  border-color: transparent;
1339
1429
  }
@@ -1348,11 +1438,21 @@ video {
1348
1438
  background-color: rgb(0 0 0 / var(--tw-bg-opacity));
1349
1439
  }
1350
1440
 
1441
+ .bg-blue-100 {
1442
+ --tw-bg-opacity: 1;
1443
+ background-color: rgb(219 234 254 / var(--tw-bg-opacity));
1444
+ }
1445
+
1351
1446
  .bg-blue-200 {
1352
1447
  --tw-bg-opacity: 1;
1353
1448
  background-color: rgb(191 219 254 / var(--tw-bg-opacity));
1354
1449
  }
1355
1450
 
1451
+ .bg-blue-50 {
1452
+ --tw-bg-opacity: 1;
1453
+ background-color: rgb(239 246 255 / var(--tw-bg-opacity));
1454
+ }
1455
+
1356
1456
  .bg-blue-500 {
1357
1457
  --tw-bg-opacity: 1;
1358
1458
  background-color: rgb(59 130 246 / var(--tw-bg-opacity));
@@ -1453,9 +1553,9 @@ video {
1453
1553
  background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1454
1554
  }
1455
1555
 
1456
- .bg-slate-100 {
1556
+ .bg-slate-50 {
1457
1557
  --tw-bg-opacity: 1;
1458
- background-color: rgb(241 245 249 / var(--tw-bg-opacity));
1558
+ background-color: rgb(248 250 252 / var(--tw-bg-opacity));
1459
1559
  }
1460
1560
 
1461
1561
  .bg-slate-500 {
@@ -1560,6 +1660,16 @@ video {
1560
1660
  padding-right: 1rem;
1561
1661
  }
1562
1662
 
1663
+ .py-0 {
1664
+ padding-top: 0px;
1665
+ padding-bottom: 0px;
1666
+ }
1667
+
1668
+ .py-0\.5 {
1669
+ padding-top: 0.125rem;
1670
+ padding-bottom: 0.125rem;
1671
+ }
1672
+
1563
1673
  .py-1 {
1564
1674
  padding-top: 0.25rem;
1565
1675
  padding-bottom: 0.25rem;
@@ -1613,6 +1723,10 @@ video {
1613
1723
  padding-left: 0.25rem;
1614
1724
  }
1615
1725
 
1726
+ .pl-10 {
1727
+ padding-left: 2.5rem;
1728
+ }
1729
+
1616
1730
  .pl-2 {
1617
1731
  padding-left: 0.5rem;
1618
1732
  }
@@ -1649,6 +1763,10 @@ video {
1649
1763
  padding-top: 0.25rem;
1650
1764
  }
1651
1765
 
1766
+ .pt-4 {
1767
+ padding-top: 1rem;
1768
+ }
1769
+
1652
1770
  .pt-\[1px\] {
1653
1771
  padding-top: 1px;
1654
1772
  }
@@ -1741,6 +1859,16 @@ video {
1741
1859
  color: rgb(0 0 0 / var(--tw-text-opacity));
1742
1860
  }
1743
1861
 
1862
+ .text-blue-600 {
1863
+ --tw-text-opacity: 1;
1864
+ color: rgb(37 99 235 / var(--tw-text-opacity));
1865
+ }
1866
+
1867
+ .text-blue-800 {
1868
+ --tw-text-opacity: 1;
1869
+ color: rgb(30 64 175 / var(--tw-text-opacity));
1870
+ }
1871
+
1744
1872
  .text-forest-green-500 {
1745
1873
  --tw-text-opacity: 1;
1746
1874
  color: rgb(0 242 58 / var(--tw-text-opacity));
@@ -1761,11 +1889,21 @@ video {
1761
1889
  color: rgb(107 114 128 / var(--tw-text-opacity));
1762
1890
  }
1763
1891
 
1892
+ .text-gray-600 {
1893
+ --tw-text-opacity: 1;
1894
+ color: rgb(75 85 99 / var(--tw-text-opacity));
1895
+ }
1896
+
1764
1897
  .text-gray-700 {
1765
1898
  --tw-text-opacity: 1;
1766
1899
  color: rgb(55 65 81 / var(--tw-text-opacity));
1767
1900
  }
1768
1901
 
1902
+ .text-gray-800 {
1903
+ --tw-text-opacity: 1;
1904
+ color: rgb(31 41 55 / var(--tw-text-opacity));
1905
+ }
1906
+
1769
1907
  .text-gray-900 {
1770
1908
  --tw-text-opacity: 1;
1771
1909
  color: rgb(17 24 39 / var(--tw-text-opacity));
@@ -1776,11 +1914,21 @@ video {
1776
1914
  color: rgb(21 128 61 / var(--tw-text-opacity));
1777
1915
  }
1778
1916
 
1917
+ .text-purple-600 {
1918
+ --tw-text-opacity: 1;
1919
+ color: rgb(147 51 234 / var(--tw-text-opacity));
1920
+ }
1921
+
1779
1922
  .text-red-400 {
1780
1923
  --tw-text-opacity: 1;
1781
1924
  color: rgb(248 113 113 / var(--tw-text-opacity));
1782
1925
  }
1783
1926
 
1927
+ .text-red-600 {
1928
+ --tw-text-opacity: 1;
1929
+ color: rgb(220 38 38 / var(--tw-text-opacity));
1930
+ }
1931
+
1784
1932
  .text-red-700 {
1785
1933
  --tw-text-opacity: 1;
1786
1934
  color: rgb(185 28 28 / var(--tw-text-opacity));
@@ -1896,6 +2044,11 @@ video {
1896
2044
  --tw-ring-inset: inset;
1897
2045
  }
1898
2046
 
2047
+ .ring-black {
2048
+ --tw-ring-opacity: 1;
2049
+ --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity));
2050
+ }
2051
+
1899
2052
  .ring-black\/5 {
1900
2053
  --tw-ring-color: rgb(0 0 0 / 0.05);
1901
2054
  }
@@ -1917,6 +2070,10 @@ video {
1917
2070
  --tw-ring-color: rgb(22 163 74 / 0.2);
1918
2071
  }
1919
2072
 
2073
+ .ring-opacity-5 {
2074
+ --tw-ring-opacity: 0.05;
2075
+ }
2076
+
1920
2077
  .filter {
1921
2078
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1922
2079
  }
@@ -2034,6 +2191,11 @@ video {
2034
2191
  background-color: rgb(75 85 99 / var(--tw-bg-opacity));
2035
2192
  }
2036
2193
 
2194
+ .hover\:bg-green-100:hover {
2195
+ --tw-bg-opacity: 1;
2196
+ background-color: rgb(220 252 231 / var(--tw-bg-opacity));
2197
+ }
2198
+
2037
2199
  .hover\:bg-green-300:hover {
2038
2200
  --tw-bg-opacity: 1;
2039
2201
  background-color: rgb(134 239 172 / var(--tw-bg-opacity));
@@ -2049,6 +2211,21 @@ video {
2049
2211
  background-color: rgb(22 163 74 / var(--tw-bg-opacity));
2050
2212
  }
2051
2213
 
2214
+ .hover\:bg-green-700:hover {
2215
+ --tw-bg-opacity: 1;
2216
+ background-color: rgb(21 128 61 / var(--tw-bg-opacity));
2217
+ }
2218
+
2219
+ .hover\:bg-pink-100:hover {
2220
+ --tw-bg-opacity: 1;
2221
+ background-color: rgb(252 231 243 / var(--tw-bg-opacity));
2222
+ }
2223
+
2224
+ .hover\:bg-red-100:hover {
2225
+ --tw-bg-opacity: 1;
2226
+ background-color: rgb(254 226 226 / var(--tw-bg-opacity));
2227
+ }
2228
+
2052
2229
  .hover\:bg-red-500:hover {
2053
2230
  --tw-bg-opacity: 1;
2054
2231
  background-color: rgb(239 68 68 / var(--tw-bg-opacity));
@@ -2059,6 +2236,11 @@ video {
2059
2236
  background-color: rgb(220 38 38 / var(--tw-bg-opacity));
2060
2237
  }
2061
2238
 
2239
+ .hover\:bg-slate-100:hover {
2240
+ --tw-bg-opacity: 1;
2241
+ background-color: rgb(241 245 249 / var(--tw-bg-opacity));
2242
+ }
2243
+
2062
2244
  .hover\:bg-slate-400:hover {
2063
2245
  --tw-bg-opacity: 1;
2064
2246
  background-color: rgb(148 163 184 / var(--tw-bg-opacity));
@@ -2099,6 +2281,11 @@ video {
2099
2281
  background-color: rgb(220 73 73 / var(--tw-bg-opacity));
2100
2282
  }
2101
2283
 
2284
+ .hover\:text-blue-800:hover {
2285
+ --tw-text-opacity: 1;
2286
+ color: rgb(30 64 175 / var(--tw-text-opacity));
2287
+ }
2288
+
2102
2289
  .hover\:text-gray-700:hover {
2103
2290
  --tw-text-opacity: 1;
2104
2291
  color: rgb(55 65 81 / var(--tw-text-opacity));
@@ -2113,6 +2300,10 @@ video {
2113
2300
  z-index: 10;
2114
2301
  }
2115
2302
 
2303
+ .focus\:border-transparent:focus {
2304
+ border-color: transparent;
2305
+ }
2306
+
2116
2307
  .focus\:outline-none:focus {
2117
2308
  outline: 2px solid transparent;
2118
2309
  outline-offset: 2px;
@@ -2176,6 +2367,11 @@ video {
2176
2367
  --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
2177
2368
  }
2178
2369
 
2370
+ .focus\:ring-green-500:focus {
2371
+ --tw-ring-opacity: 1;
2372
+ --tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity));
2373
+ }
2374
+
2179
2375
  .focus\:ring-red-500:focus {
2180
2376
  --tw-ring-opacity: 1;
2181
2377
  --tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
@@ -2261,6 +2457,10 @@ video {
2261
2457
  outline-color: #00a8a5;
2262
2458
  }
2263
2459
 
2460
+ .focus-visible\:outline-ultramarine-500:focus-visible {
2461
+ outline-color: #3f53ff;
2462
+ }
2463
+
2264
2464
  .focus-visible\:outline-ultramarine-600:focus-visible {
2265
2465
  outline-color: #1823ff;
2266
2466
  }
@@ -2289,6 +2489,10 @@ video {
2289
2489
  color: rgb(209 213 219 / var(--tw-text-opacity));
2290
2490
  }
2291
2491
 
2492
+ .disabled\:opacity-50:disabled {
2493
+ opacity: 0.5;
2494
+ }
2495
+
2292
2496
  @media (min-width: 640px) {
2293
2497
  .sm\:-mx-6 {
2294
2498
  margin-left: -1.5rem;
@@ -2383,9 +2587,22 @@ video {
2383
2587
  display: block;
2384
2588
  }
2385
2589
 
2590
+ .md\:flex {
2591
+ display: flex;
2592
+ }
2593
+
2386
2594
  .md\:hidden {
2387
2595
  display: none;
2388
2596
  }
2597
+
2598
+ .md\:gap-3 {
2599
+ gap: 0.75rem;
2600
+ }
2601
+
2602
+ .md\:px-0 {
2603
+ padding-left: 0px;
2604
+ padding-right: 0px;
2605
+ }
2389
2606
  }
2390
2607
 
2391
2608
  @media (min-width: 1024px) {
@@ -69,6 +69,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
69
69
  }
70
70
  };
71
71
  exports.Model = {
72
+ addField(params) {
73
+ return client.post('', { action: 'Model.addField', ...params }).then(res => res.data);
74
+ },
72
75
  createChart(params) {
73
76
  return client.post('', { action: 'Model.createChart', ...params }).then(res => res.data);
74
77
  },
@@ -182,6 +185,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
182
185
  }
183
186
  };
184
187
  exports.Model = {
188
+ addField(params) {
189
+ return client.post('/Model/addField', params).then(res => res.data);
190
+ },
185
191
  createChart: function(params) {
186
192
  return client.post('/Model/createChart', params).then(res => res.data);
187
193
  },
@@ -7,6 +7,14 @@
7
7
 
8
8
  .document .document-menu {
9
9
  display: flex;
10
+ position: sticky;
11
+ top: 0;
12
+ z-index: 100;
13
+ background-color: white;
14
+ border-radius: 5px;
15
+ padding: 15px 15px;
16
+ margin: -15px 0 15px 0;
17
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
10
18
  }
11
19
 
12
20
  .document .document-menu .left {
@@ -1,19 +1,43 @@
1
- <div class="document">
2
- <div class="document-menu">
3
- <div class="left">
1
+ <div class="document px-1 md:px-0">
2
+ <div class="flex justify-between">
3
+ <div class="flex">
4
4
  <button
5
5
  @click="$router.push('/model/' + this.model)"
6
- class="rounded-md bg-gray-400 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600">
6
+ class="mr-2 rounded-md bg-gray-400 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600">
7
7
  &lsaquo; Back
8
8
  </button>
9
+ <button
10
+ @click="viewMode = 'fields'"
11
+ :class="viewMode === 'fields'
12
+ ? 'bg-blue-600 text-white z-10'
13
+ : 'bg-gray-200 text-gray-700 hover:bg-gray-300'"
14
+ class="px-4 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 flex items-center gap-2 border border-gray-300 border-r-0 rounded-l-lg rounded-r-none"
15
+ >
16
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
17
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16"></path>
18
+ </svg>
19
+ Fields
20
+ </button>
21
+ <button
22
+ @click="viewMode = 'json'"
23
+ :class="viewMode === 'json'
24
+ ? 'bg-blue-600 text-white z-10'
25
+ : 'bg-gray-200 text-gray-700 hover:bg-gray-300'"
26
+ class="px-4 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-blue-500 flex items-center gap-2 border border-gray-300 rounded-r-lg rounded-l-none"
27
+ >
28
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
29
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"></path>
30
+ </svg>
31
+ JSON
32
+ </button>
9
33
  </div>
10
34
 
11
- <div class="right">
35
+ <div class="gap-2 hidden md:flex">
12
36
  <button
13
37
  v-if="!editting"
14
38
  @click="editting = true"
15
- :disabled="!canManipulate"
16
- :class="{'cursor-not-allowed opacity-50': !canManipulate}"
39
+ :disabled="!canEdit"
40
+ :class="{'cursor-not-allowed opacity-50': !canEdit}"
17
41
  type="button"
18
42
  class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">
19
43
  <img src="images/edit.svg" class="inline" /> Edit
@@ -51,14 +75,84 @@
51
75
  <img src="images/duplicate.svg" class="inline" /> Clone
52
76
  </button>
53
77
  </div>
78
+ <div class="md:hidden flex items-center">
79
+ <div class="relative">
80
+ <button
81
+ @click="mobileMenuOpen = !mobileMenuOpen"
82
+ type="button"
83
+ class="inline-flex items-center justify-center rounded-md bg-gray-200 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
84
+ aria-expanded="mobileMenuOpen"
85
+ aria-label="Open menu"
86
+ >
87
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
88
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
89
+ d="M4 6h16M4 12h16M4 18h16"></path>
90
+ </svg>
91
+ </button>
92
+ <div
93
+ v-show="mobileMenuOpen"
94
+ @click.away="mobileMenuOpen = false"
95
+ class="origin-top-right absolute right-0 mt-2 w-52 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-50"
96
+ >
97
+ <div class="py-1 flex flex-col">
98
+ <button
99
+ v-if="!editting"
100
+ @click="editting = true; mobileMenuOpen = false"
101
+ :disabled="!canEdit"
102
+ :class="['flex items-center px-4 py-2 text-sm text-gray-700', !canEdit ? 'cursor-not-allowed opacity-50' : 'hover:bg-ultramarine-100']"
103
+ type="button"
104
+ >
105
+ <img src="images/edit.svg" class="inline mr-2" /> Edit
106
+ </button>
107
+ <button
108
+ v-if="editting"
109
+ @click="editting = false; mobileMenuOpen = false"
110
+ type="button"
111
+ class="flex items-center px-4 py-2 text-sm text-gray-700 hover:bg-slate-100"
112
+ >
113
+ &times; Cancel
114
+ </button>
115
+ <button
116
+ v-if="editting"
117
+ :disabled="!canManipulate"
118
+ :class="['flex items-center px-4 py-2 text-sm text-gray-700', !canManipulate ? 'cursor-not-allowed opacity-50' : 'hover:bg-green-100']"
119
+ @click="shouldShowConfirmModal=true; mobileMenuOpen = false"
120
+ type="button"
121
+ >
122
+ <img src="images/save.svg" class="inline mr-2" /> Save
123
+ </button>
124
+ <button
125
+ @click="shouldShowDeleteModal=true; mobileMenuOpen = false"
126
+ :disabled="!canManipulate"
127
+ :class="['flex items-center px-4 py-2 text-sm text-gray-700', !canManipulate ? 'cursor-not-allowed opacity-50' : 'hover:bg-red-100']"
128
+ type="button"
129
+ >
130
+ <img src="images/delete.svg" class="inline mr-2" /> Delete
131
+ </button>
132
+ <button
133
+ @click="shouldShowCloneModal=true; mobileMenuOpen = false"
134
+ :disabled="!canManipulate"
135
+ :class="['flex items-center px-4 py-2 text-sm text-gray-700', !canManipulate ? 'cursor-not-allowed opacity-50' : 'hover:bg-pink-100']"
136
+ type="button"
137
+ >
138
+ <img src="images/duplicate.svg" class="inline mr-2" /> Clone
139
+ </button>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
54
144
  </div>
55
145
  <div v-if="status === 'loaded'">
56
146
  <document-details
57
147
  :document="document"
58
148
  :schemaPaths="schemaPaths"
149
+ :virtualPaths="virtualPaths"
59
150
  :editting="editting"
60
151
  :changes="changes"
61
- :invalid="invalid"></document-details>
152
+ :invalid="invalid"
153
+ :viewMode="viewMode"
154
+ @add-field="addField"
155
+ @view-mode-change="updateViewMode"></document-details>
62
156
  <modal v-if="shouldShowConfirmModal">
63
157
  <template v-slot:body>
64
158
  <div class="modal-exit" @click="shouldShowConfirmModal = false;">&times;</div>
@@ -20,13 +20,16 @@ module.exports = app => app.component('document', {
20
20
  invalid: {},
21
21
  editting: false,
22
22
  virtuals: [],
23
+ virtualPaths: [],
24
+ mobileMenuOpen: false,
25
+ viewMode: 'fields',
23
26
  shouldShowConfirmModal: false,
24
27
  shouldShowDeleteModal: false,
25
28
  shouldShowCloneModal: false
26
29
  }),
27
30
  async mounted() {
28
31
  window.pageState = this;
29
- const { doc, schemaPaths } = await api.Model.getDocument({ model: this.model, documentId: this.documentId });
32
+ const { doc, schemaPaths, virtualPaths } = await api.Model.getDocument({ model: this.model, documentId: this.documentId });
30
33
  window.doc = doc;
31
34
  this.document = doc;
32
35
  this.schemaPaths = Object.keys(schemaPaths).sort((k1, k2) => {
@@ -38,6 +41,7 @@ module.exports = app => app.component('document', {
38
41
  }
39
42
  return 0;
40
43
  }).map(key => schemaPaths[key]);
44
+ this.virtualPaths = virtualPaths || [];
41
45
  this.status = 'loaded';
42
46
  },
43
47
  computed: {
@@ -49,6 +53,9 @@ module.exports = app => app.component('document', {
49
53
  return false;
50
54
  }
51
55
  return !this.roles.includes('readonly');
56
+ },
57
+ canEdit() {
58
+ return this.canManipulate && this.viewMode === 'fields';
52
59
  }
53
60
  },
54
61
  methods: {
@@ -89,6 +96,32 @@ module.exports = app => app.component('document', {
89
96
  },
90
97
  showClonedDocument(doc) {
91
98
  this.$router.push({ path: `/model/${this.model}/document/${doc._id}` });
99
+ },
100
+ async addField(fieldData) {
101
+ const { doc } = await api.Model.addField({
102
+ model: this.model,
103
+ _id: this.document._id,
104
+ fieldName: fieldData.name,
105
+ fieldValue: fieldData.value
106
+ });
107
+ this.document = doc;
108
+
109
+ // Show success message
110
+ vanillatoast.create({
111
+ title: 'Field Added!',
112
+ text: `Field "${fieldData.name}" has been added to the document`,
113
+ type: 'success',
114
+ timeout: 3000,
115
+ positionClass: 'bottomRight'
116
+ });
117
+ },
118
+ updateViewMode(mode) {
119
+ this.viewMode = mode;
120
+ // Exit edit mode when switching to JSON view
121
+ if (mode === 'json' && this.editting) {
122
+ this.editting = false;
123
+ this.changes = {};
124
+ }
92
125
  }
93
126
  }
94
127
  });