ts-glitter 16.0.3 → 16.0.5

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 (87) hide show
  1. package/lowcode/Entry.js +1 -1
  2. package/lowcode/Entry.ts +1 -1
  3. package/lowcode/backend-manager/bg-line.js +1 -1
  4. package/lowcode/backend-manager/bg-line.ts +1 -1
  5. package/lowcode/backend-manager/bg-list-component.js +56 -49
  6. package/lowcode/backend-manager/bg-list-component.ts +57 -50
  7. package/lowcode/backend-manager/bg-notify.js +1 -1
  8. package/lowcode/backend-manager/bg-notify.ts +1 -1
  9. package/lowcode/backend-manager/bg-recommend.js +1 -1
  10. package/lowcode/backend-manager/bg-recommend.ts +1 -1
  11. package/lowcode/backend-manager/bg-sns.js +1 -1
  12. package/lowcode/backend-manager/bg-sns.ts +1 -1
  13. package/lowcode/backend-manager/bg-widget.js +3 -0
  14. package/lowcode/backend-manager/bg-widget.ts +3 -0
  15. package/lowcode/cms-plugin/filter-options.js +8 -0
  16. package/lowcode/cms-plugin/filter-options.ts +20 -0
  17. package/lowcode/cms-plugin/module/delivery-html.js +217 -93
  18. package/lowcode/cms-plugin/module/delivery-html.ts +232 -96
  19. package/lowcode/cms-plugin/module/product-excel.js +5 -1
  20. package/lowcode/cms-plugin/module/product-excel.ts +270 -266
  21. package/lowcode/cms-plugin/permission-setting.js +3 -2
  22. package/lowcode/cms-plugin/permission-setting.ts +2 -2
  23. package/lowcode/cms-plugin/shopping-allowance-manager.js +3 -2
  24. package/lowcode/cms-plugin/shopping-allowance-manager.ts +2 -2
  25. package/lowcode/cms-plugin/shopping-invoice-manager.js +3 -2
  26. package/lowcode/cms-plugin/shopping-invoice-manager.ts +2 -2
  27. package/lowcode/cms-plugin/shopping-order-manager.js +83 -6
  28. package/lowcode/cms-plugin/shopping-order-manager.ts +81 -6
  29. package/lowcode/cms-plugin/shopping-product-setting.js +2 -1
  30. package/lowcode/cms-plugin/shopping-product-setting.ts +1 -1
  31. package/lowcode/cms-plugin/shopping-product-stock.js +3 -2
  32. package/lowcode/cms-plugin/shopping-product-stock.ts +2 -2
  33. package/lowcode/cms-plugin/shopping-product-v2.js +3 -2
  34. package/lowcode/cms-plugin/shopping-product-v2.ts +2 -2
  35. package/lowcode/cms-plugin/stock-stores.js +379 -0
  36. package/lowcode/cms-plugin/stock-stores.ts +468 -0
  37. package/lowcode/cms-plugin/stock-vendors.js +349 -0
  38. package/lowcode/cms-plugin/stock-vendors.ts +433 -0
  39. package/lowcode/cms-plugin/user-list.js +6 -4
  40. package/lowcode/cms-plugin/user-list.ts +4 -4
  41. package/lowcode/editor-config.js +6 -1
  42. package/lowcode/editor-config.ts +5 -1
  43. package/lowcode/jspage/function-page/setting_editor.js +105 -113
  44. package/lowcode/jspage/function-page/setting_editor.ts +319 -331
  45. package/lowcode/public-components/checkout/index.js +3 -0
  46. package/lowcode/public-components/checkout/index.ts +16 -0
  47. package/package.json +1 -1
  48. package/src/api-public/controllers/ai-chat.js +2 -0
  49. package/src/api-public/controllers/ai-chat.js.map +1 -1
  50. package/src/api-public/controllers/ai-chat.ts +3 -1
  51. package/src/api-public/controllers/ai-points.js.map +1 -1
  52. package/src/api-public/controllers/article.js.map +1 -5
  53. package/src/api-public/controllers/fcm.js.map +1 -1
  54. package/src/api-public/controllers/index.js.map +1 -1
  55. package/src/api-public/controllers/rebate.js.map +1 -1
  56. package/src/api-public/controllers/shop.js +2 -0
  57. package/src/api-public/controllers/shop.js.map +1 -1
  58. package/src/api-public/controllers/shop.ts +2 -0
  59. package/src/api-public/controllers/sms-points.js.map +1 -1
  60. package/src/api-public/controllers/user.js.map +1 -1
  61. package/src/api-public/controllers/wallet.js.map +1 -1
  62. package/src/api-public/services/ai-pointes.js.map +1 -1
  63. package/src/api-public/services/ai-robot.js.map +1 -1
  64. package/src/api-public/services/auto-send-email.js.map +1 -1
  65. package/src/api-public/services/custom-code.js.map +1 -1
  66. package/src/api-public/services/fb-message.js.map +1 -1
  67. package/src/api-public/services/financial-service.d.ts +31 -1
  68. package/src/api-public/services/financial-service.js +71 -2
  69. package/src/api-public/services/financial-service.js.map +1 -1
  70. package/src/api-public/services/financial-service.ts +100 -1
  71. package/src/api-public/services/invoice.js.map +1 -1
  72. package/src/api-public/services/language-setting.js.map +1 -1
  73. package/src/api-public/services/rebate.js.map +1 -1
  74. package/src/api-public/services/recommend.js.map +1 -1
  75. package/src/api-public/services/share-permission.js.map +1 -1
  76. package/src/api-public/services/shopping.js +1 -0
  77. package/src/api-public/services/shopping.js.map +1 -1
  78. package/src/api-public/services/shopping.ts +2 -0
  79. package/src/api-public/services/sms-pointes.js.map +1 -1
  80. package/src/api-public/services/user.js.map +1 -5
  81. package/src/api-public/services/wallet.js.map +1 -1
  82. package/src/config.d.ts +1 -1
  83. package/src/config.js.map +1 -1
  84. package/src/index.js +3 -3
  85. package/src/index.js.map +5 -1
  86. package/src/services/app.js.map +1 -1
  87. package/src/services/saas-table-check.js.map +1 -1
package/lowcode/Entry.js CHANGED
@@ -79,7 +79,7 @@ export class Entry {
79
79
  }
80
80
  window.renderClock = (_a = window.renderClock) !== null && _a !== void 0 ? _a : clockF();
81
81
  console.log(`Entry-time:`, window.renderClock.stop());
82
- glitter.share.editerVersion = 'V_16.0.3';
82
+ glitter.share.editerVersion = 'V_16.0.5';
83
83
  glitter.share.start = new Date();
84
84
  const vm = {
85
85
  appConfig: [],
package/lowcode/Entry.ts CHANGED
@@ -81,7 +81,7 @@ export class Entry {
81
81
 
82
82
  (window as any).renderClock = (window as any).renderClock ?? clockF();
83
83
  console.log(`Entry-time:`, (window as any).renderClock.stop());
84
- glitter.share.editerVersion = 'V_16.0.3';
84
+ glitter.share.editerVersion = 'V_16.0.5';
85
85
  glitter.share.start = new Date();
86
86
  const vm: {
87
87
  appConfig: any;
@@ -309,7 +309,7 @@ export class BgLine {
309
309
  return html ` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
310
310
  <div>${filterList[0]}</div>
311
311
  <div style="display: flex;">
312
- <div class="me-2">${filterList[2]}</div>
312
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
313
313
  </div>
314
314
  </div>
315
315
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -385,7 +385,7 @@ export class BgLine {
385
385
  return html` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
386
386
  <div>${filterList[0]}</div>
387
387
  <div style="display: flex;">
388
- <div class="me-2">${filterList[2]}</div>
388
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
389
389
  </div>
390
390
  </div>
391
391
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -97,55 +97,62 @@ export class BgListComponent {
97
97
  view: () => {
98
98
  return html `<!-- Accordion: 篩選 -->
99
99
  <div class="accordion" id="accordion${vmShow.id}">
100
- ${gvc.map(items.map((item) => {
101
- let contentHTML = '';
102
- switch (item.type) {
103
- case 'during':
104
- contentHTML +=
105
- item.data && item.data.list.length > 0
106
- ? BgWidget.duringInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
107
- this.vm.filter[item.key] = value;
108
- })
109
- : '';
110
- break;
111
- case 'multi_checkbox':
112
- contentHTML +=
113
- item.data.length > 0
114
- ? BgWidget.multiCheckboxContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
115
- this.vm.filter[item.key] = value;
116
- })
117
- : '';
118
- break;
119
- case 'radio_and_input':
120
- contentHTML +=
121
- item.data.length > 0
122
- ? BgWidget.radioInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
123
- this.vm.filter[item.key] = value;
124
- })
125
- : '';
126
- break;
127
- }
128
- return contentHTML.length > 0
129
- ? html `<!-- Item -->
130
- <div class="accordion-item border-0 rounded-3 mb-3">
131
- <h3 class="accordion-header" id="heading${item.key}">
132
- <button
133
- class="accordion-button shadow-none rounded-3 p-0 collapsed"
134
- type="button"
135
- data-bs-toggle="collapse"
136
- data-bs-target="#collapse${item.key}"
137
- aria-expanded="false"
138
- aria-controls="collapse${item.key}"
139
- >
140
- ${item.name}
141
- </button>
142
- </h3>
143
- <div class="accordion-collapse collapse" id="collapse${item.key}" aria-labelledby="heading${item.key}" data-bs-parent="#accordion${vmShow.id}">
144
- <div class="accordion-body p-0 pt-1">${contentHTML}</div>
145
- </div>
146
- </div> `
147
- : '';
148
- }))}
100
+ ${gvc.map(items.length > 0
101
+ ? items.map((item) => {
102
+ let contentHTML = '';
103
+ switch (item.type) {
104
+ case 'during':
105
+ contentHTML +=
106
+ item.data && item.data.list.length > 0
107
+ ? BgWidget.duringInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
108
+ this.vm.filter[item.key] = value;
109
+ })
110
+ : '';
111
+ break;
112
+ case 'multi_checkbox':
113
+ contentHTML +=
114
+ item.data.length > 0
115
+ ? BgWidget.multiCheckboxContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
116
+ this.vm.filter[item.key] = value;
117
+ })
118
+ : '';
119
+ break;
120
+ case 'radio_and_input':
121
+ contentHTML +=
122
+ item.data.length > 0
123
+ ? BgWidget.radioInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
124
+ this.vm.filter[item.key] = value;
125
+ })
126
+ : '';
127
+ break;
128
+ }
129
+ return contentHTML.length > 0
130
+ ? html `<!-- Item -->
131
+ <div class="accordion-item border-0 rounded-3 mb-3">
132
+ <h3 class="accordion-header" id="heading${item.key}">
133
+ <button
134
+ class="accordion-button shadow-none rounded-3 p-0 collapsed"
135
+ type="button"
136
+ data-bs-toggle="collapse"
137
+ data-bs-target="#collapse${item.key}"
138
+ aria-expanded="false"
139
+ aria-controls="collapse${item.key}"
140
+ >
141
+ ${item.name}
142
+ </button>
143
+ </h3>
144
+ <div
145
+ class="accordion-collapse collapse"
146
+ id="collapse${item.key}"
147
+ aria-labelledby="heading${item.key}"
148
+ data-bs-parent="#accordion${vmShow.id}"
149
+ >
150
+ <div class="accordion-body p-0 pt-1">${contentHTML}</div>
151
+ </div>
152
+ </div> `
153
+ : '';
154
+ })
155
+ : ['無篩選項目'])}
149
156
  </div>
150
157
  <div class="position-absolute bottom-0 left-0 w-100 d-flex align-items-center justify-content-end p-3 border-top pe-4" style="gap:10px;">
151
158
  ${BgWidget.cancel(gvc.event(() => {
@@ -108,7 +108,7 @@ export class BgListComponent {
108
108
 
109
109
  showRightMenu(items: FilterItem[]) {
110
110
  const glitter = (window.parent as any).glitter;
111
- const gvc: GVC = glitter.pageConfig[glitter.pageConfig.length-1].gvc;
111
+ const gvc: GVC = glitter.pageConfig[glitter.pageConfig.length - 1].gvc;
112
112
  const menu = glitter.share.NormalPageEditor;
113
113
  const vmShow = { id: gvc.glitter.getUUID() };
114
114
  menu.closeEvent = () => gvc.notifyDataChange(this.vm.id);
@@ -122,57 +122,64 @@ export class BgListComponent {
122
122
  return html`<!-- Accordion: 篩選 -->
123
123
  <div class="accordion" id="accordion${vmShow.id}">
124
124
  ${gvc.map(
125
- items.map((item: any) => {
126
- let contentHTML = '';
127
- switch (item.type) {
128
- case 'during':
129
- contentHTML +=
130
- item.data && item.data.list.length > 0
131
- ? BgWidget.duringInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
132
- this.vm.filter[item.key] = value;
133
- })
134
- : '';
135
- break;
136
- case 'multi_checkbox':
137
- contentHTML +=
138
- item.data.length > 0
139
- ? BgWidget.multiCheckboxContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
140
- this.vm.filter[item.key] = value;
141
- })
142
- : '';
125
+ items.length > 0
126
+ ? items.map((item: any) => {
127
+ let contentHTML = '';
128
+ switch (item.type) {
129
+ case 'during':
130
+ contentHTML +=
131
+ item.data && item.data.list.length > 0
132
+ ? BgWidget.duringInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
133
+ this.vm.filter[item.key] = value;
134
+ })
135
+ : '';
136
+ break;
137
+ case 'multi_checkbox':
138
+ contentHTML +=
139
+ item.data.length > 0
140
+ ? BgWidget.multiCheckboxContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
141
+ this.vm.filter[item.key] = value;
142
+ })
143
+ : '';
143
144
 
144
- break;
145
- case 'radio_and_input':
146
- contentHTML +=
147
- item.data.length > 0
148
- ? BgWidget.radioInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
149
- this.vm.filter[item.key] = value;
150
- })
151
- : '';
152
- break;
153
- }
145
+ break;
146
+ case 'radio_and_input':
147
+ contentHTML +=
148
+ item.data.length > 0
149
+ ? BgWidget.radioInputContainer(gvc, item.data, this.vm.filter[item.key], (value) => {
150
+ this.vm.filter[item.key] = value;
151
+ })
152
+ : '';
153
+ break;
154
+ }
154
155
 
155
- return contentHTML.length > 0
156
- ? html`<!-- Item -->
157
- <div class="accordion-item border-0 rounded-3 mb-3">
158
- <h3 class="accordion-header" id="heading${item.key}">
159
- <button
160
- class="accordion-button shadow-none rounded-3 p-0 collapsed"
161
- type="button"
162
- data-bs-toggle="collapse"
163
- data-bs-target="#collapse${item.key}"
164
- aria-expanded="false"
165
- aria-controls="collapse${item.key}"
166
- >
167
- ${item.name}
168
- </button>
169
- </h3>
170
- <div class="accordion-collapse collapse" id="collapse${item.key}" aria-labelledby="heading${item.key}" data-bs-parent="#accordion${vmShow.id}">
171
- <div class="accordion-body p-0 pt-1">${contentHTML}</div>
172
- </div>
173
- </div> `
174
- : '';
175
- })
156
+ return contentHTML.length > 0
157
+ ? html`<!-- Item -->
158
+ <div class="accordion-item border-0 rounded-3 mb-3">
159
+ <h3 class="accordion-header" id="heading${item.key}">
160
+ <button
161
+ class="accordion-button shadow-none rounded-3 p-0 collapsed"
162
+ type="button"
163
+ data-bs-toggle="collapse"
164
+ data-bs-target="#collapse${item.key}"
165
+ aria-expanded="false"
166
+ aria-controls="collapse${item.key}"
167
+ >
168
+ ${item.name}
169
+ </button>
170
+ </h3>
171
+ <div
172
+ class="accordion-collapse collapse"
173
+ id="collapse${item.key}"
174
+ aria-labelledby="heading${item.key}"
175
+ data-bs-parent="#accordion${vmShow.id}"
176
+ >
177
+ <div class="accordion-body p-0 pt-1">${contentHTML}</div>
178
+ </div>
179
+ </div> `
180
+ : '';
181
+ })
182
+ : ['無篩選項目']
176
183
  )}
177
184
  </div>
178
185
  <div class="position-absolute bottom-0 left-0 w-100 d-flex align-items-center justify-content-end p-3 border-top pe-4" style="gap:10px;">
@@ -309,7 +309,7 @@ export class BgNotify {
309
309
  return html `<div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
310
310
  <div>${filterList[0]}</div>
311
311
  <div style="display: flex;">
312
- <div class="me-2">${filterList[2]}</div>
312
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
313
313
  </div>
314
314
  </div>
315
315
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -380,7 +380,7 @@ export class BgNotify {
380
380
  return html`<div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
381
381
  <div>${filterList[0]}</div>
382
382
  <div style="display: flex;">
383
- <div class="me-2">${filterList[2]}</div>
383
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
384
384
  </div>
385
385
  </div>
386
386
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -369,7 +369,7 @@ export class BgRecommend {
369
369
  return html ` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
370
370
  <div>${filterList[0]}</div>
371
371
  <div style="display: flex;">
372
- <div class="me-2">${filterList[2]}</div>
372
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
373
373
  </div>
374
374
  </div>
375
375
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>`;
@@ -465,7 +465,7 @@ export class BgRecommend {
465
465
  return html` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
466
466
  <div>${filterList[0]}</div>
467
467
  <div style="display: flex;">
468
- <div class="me-2">${filterList[2]}</div>
468
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
469
469
  </div>
470
470
  </div>
471
471
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>`;
@@ -311,7 +311,7 @@ export class BgSNS {
311
311
  return html ` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
312
312
  <div>${filterList[0]}</div>
313
313
  <div style="display: flex;">
314
- <div class="me-2">${filterList[2]}</div>
314
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
315
315
  </div>
316
316
  </div>
317
317
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -387,7 +387,7 @@ export class BgSNS {
387
387
  return html` <div style="display: flex; align-items: center; gap: 10px; width: 100%; justify-content: space-between">
388
388
  <div>${filterList[0]}</div>
389
389
  <div style="display: flex;">
390
- <div class="me-2">${filterList[2]}</div>
390
+ ${filterList[2] ? `<div class="me-2">${filterList[2]}</div>` : ''}
391
391
  </div>
392
392
  </div>
393
393
  <div style="display: flex; margin-top: 8px;">${filterList[1]}</div>
@@ -2051,6 +2051,9 @@ ${(_c = obj.default) !== null && _c !== void 0 ? _c : ''}</textarea
2051
2051
  bind: vm.id,
2052
2052
  view: () => {
2053
2053
  if (vm.show) {
2054
+ if (obj.options.length === 0) {
2055
+ return '';
2056
+ }
2054
2057
  return html ` <div class="c_absolute" style="top: 20px; right: 20px;">
2055
2058
  <div class="form-check d-flex flex-column" style="gap: 16px">
2056
2059
  ${obj.gvc.map(obj.options.map((opt) => {
@@ -2429,6 +2429,9 @@ ${obj.default ?? ''}</textarea
2429
2429
  bind: vm.id,
2430
2430
  view: () => {
2431
2431
  if (vm.show) {
2432
+ if (obj.options.length === 0) {
2433
+ return '';
2434
+ }
2432
2435
  return html` <div class="c_absolute" style="top: 20px; right: 20px;">
2433
2436
  <div class="form-check d-flex flex-column" style="gap: 16px">
2434
2437
  ${obj.gvc.map(
@@ -506,3 +506,11 @@ FilterOptions.permissionOrderBy = [
506
506
  { key: 'online_time_asc', value: '最後登入時間早 > 晚' },
507
507
  { key: 'online_time_desc', value: '最後登入時間晚 > 早' },
508
508
  ];
509
+ FilterOptions.storesFilterFrame = {};
510
+ FilterOptions.storesSelect = [{ key: 'name', value: '庫存點名稱' }];
511
+ FilterOptions.storesFunnel = [];
512
+ FilterOptions.storesOrderBy = [];
513
+ FilterOptions.vendorsFilterFrame = {};
514
+ FilterOptions.vendorsSelect = [{ key: 'name', value: '庫存點名稱' }];
515
+ FilterOptions.vendorsFunnel = [];
516
+ FilterOptions.vendorsOrderBy = [];
@@ -203,6 +203,7 @@ export class FilterOptions {
203
203
  },
204
204
  },
205
205
  ];
206
+
206
207
  static invoiceFunnel = [
207
208
  {
208
209
  key: 'invoice_type',
@@ -244,6 +245,7 @@ export class FilterOptions {
244
245
  },
245
246
  },
246
247
  ];
248
+
247
249
  static allowanceFunnel = [
248
250
  {
249
251
  key: 'status',
@@ -287,6 +289,7 @@ export class FilterOptions {
287
289
  { key: 'order_total_desc', value: '發票金額高 > 低' },
288
290
  { key: 'order_total_asc', value: '發票金額低 > 高' },
289
291
  ];
292
+
290
293
  static allowanceOrderBy = [
291
294
  { key: 'created_time_desc', value: '發票時間新 > 舊' },
292
295
  { key: 'created_time_asc', value: '發票時間舊 > 新' },
@@ -319,6 +322,7 @@ export class FilterOptions {
319
322
  { key: 'product_name', value: '商品名稱' },
320
323
  { key: 'product_number', value: '商品編號' },
321
324
  ];
325
+
322
326
  static allowanceSelect = [
323
327
  { key: 'allowance_no', value: '折讓單編號' },
324
328
  { key: 'invoice_no', value: '原發票編號' },
@@ -565,4 +569,20 @@ export class FilterOptions {
565
569
  { key: 'online_time_asc', value: '最後登入時間早 > 晚' },
566
570
  { key: 'online_time_desc', value: '最後登入時間晚 > 早' },
567
571
  ];
572
+
573
+ static storesFilterFrame = {};
574
+
575
+ static storesSelect = [{ key: 'name', value: '庫存點名稱' }];
576
+
577
+ static storesFunnel = [];
578
+
579
+ static storesOrderBy = [];
580
+
581
+ static vendorsFilterFrame = {};
582
+
583
+ static vendorsSelect = [{ key: 'name', value: '庫存點名稱' }];
584
+
585
+ static vendorsFunnel = [];
586
+
587
+ static vendorsOrderBy = [];
568
588
  }