@fleetbase/storefront-engine 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/components/context-panel.hbs +5 -0
- package/addon/components/context-panel.js +6 -0
- package/addon/components/customer-panel/details.hbs +34 -0
- package/addon/components/customer-panel/details.js +3 -0
- package/addon/components/customer-panel/orders.hbs +140 -0
- package/addon/components/customer-panel/orders.js +78 -0
- package/addon/components/customer-panel.hbs +70 -0
- package/addon/components/customer-panel.js +171 -0
- package/addon/components/display-place.hbs +52 -0
- package/addon/components/display-place.js +11 -0
- package/addon/components/modals/manage-addons.hbs +15 -52
- package/addon/components/modals/manage-addons.js +93 -43
- package/addon/components/modals/select-addon-category.hbs +1 -1
- package/addon/components/order-panel/details.hbs +245 -0
- package/addon/components/order-panel/details.js +189 -0
- package/addon/components/order-panel.hbs +1 -0
- package/addon/components/order-panel.js +38 -0
- package/addon/components/storefront-order-summary.hbs +9 -2
- package/addon/components/widget/customers.hbs +3 -1
- package/addon/components/widget/customers.js +5 -0
- package/addon/components/widget/orders.js +8 -146
- package/addon/controllers/customers/index/view.js +43 -0
- package/addon/controllers/customers/index.js +10 -6
- package/addon/controllers/networks/index/network/customers.js +68 -2
- package/addon/controllers/networks/index/network/orders.js +324 -1
- package/addon/controllers/networks/index/network/stores.js +0 -2
- package/addon/controllers/orders/index/view.js +13 -0
- package/addon/controllers/orders/index.js +10 -7
- package/addon/controllers/products/index/category/edit.js +12 -16
- package/addon/controllers/products/index/category/new.js +40 -45
- package/addon/controllers/products/index.js +8 -2
- package/addon/helpers/avatar-url.js +9 -0
- package/addon/models/product-variant-option.js +8 -1
- package/addon/models/product-variant.js +12 -2
- package/addon/models/product.js +62 -0
- package/addon/routes/customers/index/view.js +14 -0
- package/addon/routes/networks/index/network/customers.js +29 -0
- package/addon/routes/networks/index/network/orders.js +5 -0
- package/addon/routes/networks/index.js +1 -1
- package/addon/routes/orders/index/view.js +22 -1
- package/addon/routes/products/index/category/edit.js +6 -0
- package/addon/routes/products/index/category/new.js +3 -1
- package/addon/routes.js +1 -0
- package/addon/serializers/product-variant-option.js +14 -0
- package/addon/serializers/product-variant.js +27 -0
- package/addon/serializers/product.js +26 -4
- package/addon/services/context-panel.js +210 -0
- package/addon/styles/storefront-engine.css +6 -0
- package/addon/templates/application.hbs +3 -1
- package/addon/templates/customers/index/view.hbs +1 -0
- package/addon/templates/networks/index/network/customers.hbs +18 -1
- package/addon/templates/networks/index/network/orders.hbs +18 -1
- package/addon/templates/networks/index/network.hbs +1 -1
- package/addon/templates/orders/index/view.hbs +1 -1
- package/addon/templates/products/index/category/new.hbs +12 -67
- package/app/components/context-panel.js +1 -0
- package/app/components/customer-panel/details.js +1 -0
- package/app/components/customer-panel/orders.js +1 -0
- package/app/components/customer-panel.js +1 -0
- package/app/components/display-place.js +1 -0
- package/app/components/order-panel/details.js +1 -0
- package/app/components/order-panel.js +1 -0
- package/app/controllers/customers/index/view.js +1 -0
- package/app/controllers/orders/index/view.js +1 -0
- package/app/helpers/avatar-url.js +1 -0
- package/app/routes/customers/index/view.js +1 -0
- package/app/serializers/product-variant-option.js +1 -0
- package/app/services/context-panel.js +1 -0
- package/app/templates/customers/index/view.js +1 -0
- package/composer.json +4 -4
- package/extension.json +1 -1
- package/package.json +9 -3
- package/server/seeders/OrderConfigSeeder.php +2 -249
- package/server/src/Http/Controllers/AddonCategoryController.php +90 -0
- package/server/src/Http/Controllers/v1/ReviewController.php +43 -52
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +7 -9
- package/server/src/Http/Resources/Network.php +34 -32
- package/server/src/Http/Resources/NotificationChannel.php +32 -0
- package/server/src/Http/Resources/Product.php +10 -8
- package/server/src/Models/AddonCategory.php +37 -0
- package/server/src/Models/Product.php +6 -7
- package/server/src/Models/ProductAddon.php +3 -0
- package/server/src/Models/ProductAddonCategory.php +12 -2
- package/server/src/Observers/CompanyObserver.php +20 -0
- package/server/src/Providers/StorefrontServiceProvider.php +2 -1
- package/server/src/Support/Storefront.php +249 -0
- package/translations/en-us.yaml +101 -39
- package/server/src/Support/OrderConfig.php +0 -14
|
@@ -1,3 +1,326 @@
|
|
|
1
1
|
import Controller from '@ember/controller';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { tracked } from '@glimmer/tracking';
|
|
4
|
+
import { isBlank } from '@ember/utils';
|
|
5
|
+
import { timeout } from 'ember-concurrency';
|
|
6
|
+
import { task } from 'ember-concurrency-decorators';
|
|
7
|
+
import { action } from '@ember/object';
|
|
2
8
|
|
|
3
|
-
export default class NetworksIndexNetworkOrdersController extends Controller {
|
|
9
|
+
export default class NetworksIndexNetworkOrdersController extends Controller {
|
|
10
|
+
/**
|
|
11
|
+
* Inject the `notifications` service
|
|
12
|
+
*
|
|
13
|
+
* @var {Service}
|
|
14
|
+
*/
|
|
15
|
+
@service notifications;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Inject the `intl` service
|
|
19
|
+
*
|
|
20
|
+
* @var {Service}
|
|
21
|
+
*/
|
|
22
|
+
@service intl;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Inject the `modals-manager` service
|
|
26
|
+
*
|
|
27
|
+
* @var {Service}
|
|
28
|
+
*/
|
|
29
|
+
@service modalsManager;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Inject the `crud` service
|
|
33
|
+
*
|
|
34
|
+
* @var {Service}
|
|
35
|
+
*/
|
|
36
|
+
@service crud;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Inject the `fetch` service
|
|
40
|
+
*
|
|
41
|
+
* @var {Service}
|
|
42
|
+
*/
|
|
43
|
+
@service fetch;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Inject the `filters` service
|
|
47
|
+
*
|
|
48
|
+
* @var {Service}
|
|
49
|
+
*/
|
|
50
|
+
@service filters;
|
|
51
|
+
|
|
52
|
+
@service contextPanel;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Queryable parameters for this controller's model
|
|
56
|
+
*
|
|
57
|
+
* @var {Array}
|
|
58
|
+
*/
|
|
59
|
+
queryParams = [];
|
|
60
|
+
|
|
61
|
+
@tracked page = 1;
|
|
62
|
+
@tracked limit;
|
|
63
|
+
@tracked query;
|
|
64
|
+
@tracked sort = '-created_at';
|
|
65
|
+
@tracked public_id;
|
|
66
|
+
@tracked internal_id;
|
|
67
|
+
@tracked tracking;
|
|
68
|
+
@tracked facilitator;
|
|
69
|
+
@tracked customer;
|
|
70
|
+
@tracked driver;
|
|
71
|
+
@tracked payload;
|
|
72
|
+
@tracked pickup;
|
|
73
|
+
@tracked dropoff;
|
|
74
|
+
@tracked updated_by;
|
|
75
|
+
@tracked created_by;
|
|
76
|
+
@tracked status;
|
|
77
|
+
|
|
78
|
+
@tracked columns = [
|
|
79
|
+
{
|
|
80
|
+
label: this.intl.t('storefront.common.id'),
|
|
81
|
+
valuePath: 'public_id',
|
|
82
|
+
width: '150px',
|
|
83
|
+
cellComponent: 'table/cell/anchor',
|
|
84
|
+
action: this.viewOrder,
|
|
85
|
+
resizable: true,
|
|
86
|
+
sortable: true,
|
|
87
|
+
filterable: true,
|
|
88
|
+
filterComponent: 'filter/string',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
label: this.intl.t('storefront.orders.index.internal-id'),
|
|
92
|
+
valuePath: 'internal_id',
|
|
93
|
+
width: '125px',
|
|
94
|
+
resizable: true,
|
|
95
|
+
sortable: true,
|
|
96
|
+
filterable: true,
|
|
97
|
+
filterComponent: 'filter/string',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
label: this.intl.t('storefront.orders.index.customer'),
|
|
101
|
+
valuePath: 'customer.name',
|
|
102
|
+
cellComponent: 'table/cell/base',
|
|
103
|
+
width: '125px',
|
|
104
|
+
resizable: true,
|
|
105
|
+
sortable: true,
|
|
106
|
+
hidden: true,
|
|
107
|
+
filterable: true,
|
|
108
|
+
filterComponent: 'filter/model',
|
|
109
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-order-customer'),
|
|
110
|
+
filterParam: 'customer',
|
|
111
|
+
model: 'customer',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
label: this.intl.t('storefront.common.pickup'),
|
|
115
|
+
valuePath: 'pickupName',
|
|
116
|
+
cellComponent: 'table/cell/base',
|
|
117
|
+
width: '160px',
|
|
118
|
+
resizable: true,
|
|
119
|
+
sortable: true,
|
|
120
|
+
filterable: true,
|
|
121
|
+
filterComponent: 'filter/model',
|
|
122
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-order-pickup-location'),
|
|
123
|
+
filterParam: 'pickup',
|
|
124
|
+
model: 'place',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
label: this.intl.t('storefront.common.dropoff'),
|
|
128
|
+
valuePath: 'dropoffName',
|
|
129
|
+
cellComponent: 'table/cell/base',
|
|
130
|
+
width: '160px',
|
|
131
|
+
resizable: true,
|
|
132
|
+
sortable: true,
|
|
133
|
+
filterable: true,
|
|
134
|
+
filterComponent: 'filter/model',
|
|
135
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-order-dropoff-location'),
|
|
136
|
+
filterParam: 'dropoff',
|
|
137
|
+
model: 'place',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
label: this.intl.t('storefront.orders.index.scheduled-at'),
|
|
141
|
+
valuePath: 'scheduledAt',
|
|
142
|
+
sortParam: 'scheduled_at',
|
|
143
|
+
filterParam: 'scheduled_at',
|
|
144
|
+
width: '150px',
|
|
145
|
+
resizable: true,
|
|
146
|
+
sortable: true,
|
|
147
|
+
filterable: true,
|
|
148
|
+
filterComponent: 'filter/date',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
label: '# Items',
|
|
152
|
+
cellComponent: 'table/cell/base',
|
|
153
|
+
valuePath: 'item_count',
|
|
154
|
+
resizable: true,
|
|
155
|
+
hidden: true,
|
|
156
|
+
width: '50px',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
label: this.intl.t('storefront.orders.index.transaction-total'),
|
|
160
|
+
cellComponent: 'table/cell/base',
|
|
161
|
+
valuePath: 'transaction_amount',
|
|
162
|
+
width: '50px',
|
|
163
|
+
resizable: true,
|
|
164
|
+
hidden: true,
|
|
165
|
+
sortable: true,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
label: this.intl.t('storefront.orders.index.tracking-number'),
|
|
169
|
+
cellComponent: 'table/cell/base',
|
|
170
|
+
valuePath: 'tracking_number.tracking_number',
|
|
171
|
+
width: '170px',
|
|
172
|
+
resizable: true,
|
|
173
|
+
sortable: true,
|
|
174
|
+
filterable: true,
|
|
175
|
+
filterComponent: 'filter/string',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
label: this.intl.t('storefront.orders.index.driver-assigned'),
|
|
179
|
+
cellComponent: 'table/cell/driver-name',
|
|
180
|
+
valuePath: 'driver_assigned',
|
|
181
|
+
modelPath: 'driver_assigned',
|
|
182
|
+
width: '170px',
|
|
183
|
+
resizable: true,
|
|
184
|
+
sortable: true,
|
|
185
|
+
filterable: true,
|
|
186
|
+
filterComponent: 'filter/model',
|
|
187
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-driver-for-order'),
|
|
188
|
+
filterParam: 'driver',
|
|
189
|
+
model: 'driver',
|
|
190
|
+
query: {
|
|
191
|
+
// no model, serializer, adapter for relations
|
|
192
|
+
without: ['fleets', 'vendor', 'vehicle', 'currentJob'],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
label: this.intl.t('storefront.common.type'),
|
|
197
|
+
cellComponent: 'cell/humanize',
|
|
198
|
+
valuePath: 'type',
|
|
199
|
+
width: '100px',
|
|
200
|
+
resizable: true,
|
|
201
|
+
hidden: true,
|
|
202
|
+
sortable: true,
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
label: this.intl.t('storefront.common.status'),
|
|
206
|
+
valuePath: 'status',
|
|
207
|
+
cellComponent: 'table/cell/status',
|
|
208
|
+
width: '120px',
|
|
209
|
+
resizable: true,
|
|
210
|
+
sortable: true,
|
|
211
|
+
filterable: true,
|
|
212
|
+
filterComponent: 'filter/multi-option',
|
|
213
|
+
// filterOptions: this.statusOptions,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
label: this.intl.t('storefront.orders.index.created-at'),
|
|
217
|
+
valuePath: 'createdAt',
|
|
218
|
+
sortParam: 'created_at',
|
|
219
|
+
filterParam: 'created_at',
|
|
220
|
+
width: '140px',
|
|
221
|
+
resizable: true,
|
|
222
|
+
sortable: true,
|
|
223
|
+
filterable: true,
|
|
224
|
+
filterComponent: 'filter/date',
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
label: this.intl.t('storefront.orders.index.updated-at'),
|
|
228
|
+
valuePath: 'updatedAt',
|
|
229
|
+
sortParam: 'updated_at',
|
|
230
|
+
filterParam: 'updated_at',
|
|
231
|
+
width: '125px',
|
|
232
|
+
resizable: true,
|
|
233
|
+
sortable: true,
|
|
234
|
+
hidden: true,
|
|
235
|
+
filterable: true,
|
|
236
|
+
filterComponent: 'filter/date',
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
label: this.intl.t('storefront.orders.index.created-by'),
|
|
240
|
+
valuePath: 'created_by_name',
|
|
241
|
+
width: '125px',
|
|
242
|
+
resizable: true,
|
|
243
|
+
hidden: true,
|
|
244
|
+
filterable: true,
|
|
245
|
+
filterComponent: 'filter/model',
|
|
246
|
+
filterComponentPlaceholder: 'Select user',
|
|
247
|
+
filterParam: 'created_by',
|
|
248
|
+
model: 'user',
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
label: this.intl.t('storefront.orders.index.updated-by'),
|
|
252
|
+
valuePath: 'updated_by_name',
|
|
253
|
+
width: '125px',
|
|
254
|
+
resizable: true,
|
|
255
|
+
hidden: true,
|
|
256
|
+
filterable: true,
|
|
257
|
+
filterComponent: 'filter/model',
|
|
258
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-user'),
|
|
259
|
+
filterParam: 'updated_by',
|
|
260
|
+
model: 'user',
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
label: '',
|
|
264
|
+
cellComponent: 'table/cell/dropdown',
|
|
265
|
+
ddButtonText: false,
|
|
266
|
+
ddButtonIcon: 'ellipsis-h',
|
|
267
|
+
ddButtonIconPrefix: 'fas',
|
|
268
|
+
ddMenuLabel: 'Order Actions',
|
|
269
|
+
cellClassNames: 'overflow-visible',
|
|
270
|
+
wrapperClass: 'flex items-center justify-end mx-2',
|
|
271
|
+
width: '12%',
|
|
272
|
+
actions: [
|
|
273
|
+
{
|
|
274
|
+
label: this.intl.t('storefront.orders.index.view-order'),
|
|
275
|
+
icon: 'eye',
|
|
276
|
+
fn: this.viewOrder,
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
label: this.intl.t('storefront.orders.index.cancel-order'),
|
|
280
|
+
icon: 'ban',
|
|
281
|
+
fn: this.cancelOrder,
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
separator: true,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
label: this.intl.t('storefront.orders.index.delete-order'),
|
|
288
|
+
icon: 'trash',
|
|
289
|
+
fn: this.deleteOrder,
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
sortable: false,
|
|
293
|
+
filterable: false,
|
|
294
|
+
resizable: false,
|
|
295
|
+
searchable: false,
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* The search task.
|
|
301
|
+
*
|
|
302
|
+
* @void
|
|
303
|
+
*/
|
|
304
|
+
@task({ restartable: true }) *search({ target: { value } }) {
|
|
305
|
+
// if no query don't search
|
|
306
|
+
if (isBlank(value)) {
|
|
307
|
+
this.query = null;
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// timeout for typing
|
|
312
|
+
yield timeout(250);
|
|
313
|
+
|
|
314
|
+
// reset page for results
|
|
315
|
+
if (this.page > 1) {
|
|
316
|
+
this.page = 1;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// update the query param
|
|
320
|
+
this.query = value;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@action viewOrder(order) {
|
|
324
|
+
this.contextPanel.focus(order, 'viewing');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
|
+
import BaseController from '../../base-controller';
|
|
3
|
+
|
|
4
|
+
export default class OrdersIndexViewController extends BaseController {
|
|
5
|
+
/**
|
|
6
|
+
* Uses router service to transition back to `orders.index`
|
|
7
|
+
*
|
|
8
|
+
* @void
|
|
9
|
+
*/
|
|
10
|
+
@action transitionBack() {
|
|
11
|
+
return this.transitionToRoute('orders.index');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { action } from '@ember/object';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
-
import { tracked } from '@glimmer/tracking';
|
|
4
3
|
import { isBlank } from '@ember/utils';
|
|
4
|
+
import BaseController from '@fleetbase/storefront-engine/controllers/base-controller';
|
|
5
|
+
import { tracked } from '@glimmer/tracking';
|
|
5
6
|
import { timeout } from 'ember-concurrency';
|
|
6
7
|
import { task } from 'ember-concurrency-decorators';
|
|
7
8
|
|
|
8
|
-
export default class OrdersIndexController extends
|
|
9
|
+
export default class OrdersIndexController extends BaseController {
|
|
9
10
|
/**
|
|
10
11
|
* Inject the `notifications` service
|
|
11
12
|
*
|
|
@@ -94,13 +95,11 @@ export default class OrdersIndexController extends Controller {
|
|
|
94
95
|
label: this.intl.t('storefront.common.id'),
|
|
95
96
|
valuePath: 'public_id',
|
|
96
97
|
width: '150px',
|
|
97
|
-
cellComponent: 'table/cell/
|
|
98
|
-
|
|
99
|
-
// onLinkClick: this.viewOrder,
|
|
98
|
+
cellComponent: 'table/cell/anchor',
|
|
99
|
+
onClick: this.viewOrder,
|
|
100
100
|
resizable: true,
|
|
101
101
|
sortable: true,
|
|
102
102
|
filterable: true,
|
|
103
|
-
filterComponent: 'filter/string',
|
|
104
103
|
},
|
|
105
104
|
{
|
|
106
105
|
label: this.intl.t('storefront.orders.index.internal-id'),
|
|
@@ -334,4 +333,8 @@ export default class OrdersIndexController extends Controller {
|
|
|
334
333
|
// update the query param
|
|
335
334
|
this.query = value;
|
|
336
335
|
}
|
|
336
|
+
|
|
337
|
+
@action viewOrder(order) {
|
|
338
|
+
return this.transitionToRoute('orders.index.view', order);
|
|
339
|
+
}
|
|
337
340
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import ProductsIndexCategoryNewController from './new';
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
|
-
import { alias } from '@ember/object/computed';
|
|
4
3
|
import { action } from '@ember/object';
|
|
5
4
|
import { inject as service } from '@ember/service';
|
|
5
|
+
import { task } from 'ember-concurrency';
|
|
6
|
+
import { filterHasManyForNewRecords } from '../../../../serializers/product';
|
|
6
7
|
|
|
7
8
|
export default class ProductsIndexCategoryEditController extends ProductsIndexCategoryNewController {
|
|
8
|
-
@alias('model') product;
|
|
9
9
|
@service intl;
|
|
10
|
+
@tracked product;
|
|
10
11
|
@tracked overlayActionButtonTitle = 'Save Changes';
|
|
11
12
|
@tracked overlayActionButtonIcon = 'save';
|
|
12
13
|
@tracked overlayExitButtonTitle = 'Done';
|
|
@@ -15,20 +16,15 @@ export default class ProductsIndexCategoryEditController extends ProductsIndexCa
|
|
|
15
16
|
return `Edit ${this.product.name}`;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
@
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
28
|
-
.catch((error) => {
|
|
29
|
-
this.isSaving = false;
|
|
30
|
-
this.notifications.serverError(error);
|
|
31
|
-
});
|
|
19
|
+
@task *saveProduct() {
|
|
20
|
+
let savedProduct;
|
|
21
|
+
try {
|
|
22
|
+
savedProduct = yield this.product.serializeMeta().save();
|
|
23
|
+
} catch (error) {
|
|
24
|
+
return this.notifications.serverError(error);
|
|
25
|
+
}
|
|
26
|
+
this.product = filterHasManyForNewRecords(savedProduct, ['variants', 'addon_categories', 'hours']);
|
|
27
|
+
this.notifications.success(this.intl.t('storefront.products.index.edit.changes-saved'));
|
|
32
28
|
}
|
|
33
29
|
|
|
34
30
|
@action transitionBack({ closeOverlay }) {
|
|
@@ -6,6 +6,7 @@ import { action } from '@ember/object';
|
|
|
6
6
|
import { alias } from '@ember/object/computed';
|
|
7
7
|
import { underscore } from '@ember/string';
|
|
8
8
|
import { inject as service } from '@ember/service';
|
|
9
|
+
import { task } from 'ember-concurrency';
|
|
9
10
|
|
|
10
11
|
export default class ProductsIndexCategoryNewController extends BaseController {
|
|
11
12
|
@controller('products.index.category') productsIndexCategoryController;
|
|
@@ -40,6 +41,7 @@ export default class ProductsIndexCategoryNewController extends BaseController {
|
|
|
40
41
|
onClick: this.addMetaField,
|
|
41
42
|
},
|
|
42
43
|
];
|
|
44
|
+
|
|
43
45
|
@tracked acceptedFileTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'video/mp4', 'video/quicktime', 'video/x-msvideo', 'video/x-flv', 'video/x-ms-wmv'];
|
|
44
46
|
|
|
45
47
|
@action reset() {
|
|
@@ -48,32 +50,24 @@ export default class ProductsIndexCategoryNewController extends BaseController {
|
|
|
48
50
|
this.uploadedFiles = [];
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
@
|
|
52
|
-
const { category } = this.productsIndexCategoryController;
|
|
53
|
+
@task *saveProduct() {
|
|
53
54
|
const loader = this.loader.showLoader('body', { loadingMessage: 'Creating new product...' });
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const { category } = this.productsIndexCategoryController;
|
|
56
56
|
if (category) {
|
|
57
57
|
this.product.set('category_uuid', category.id);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
.serializeMeta()
|
|
62
|
-
|
|
63
|
-
.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
})
|
|
72
|
-
.catch((error) => {
|
|
73
|
-
this.loader.removeLoader(loader);
|
|
74
|
-
this.isSaving = false;
|
|
75
|
-
this.notifications.serverError(error);
|
|
76
|
-
});
|
|
60
|
+
try {
|
|
61
|
+
yield this.product.serializeMeta().save();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
this.loader.removeLoader(loader);
|
|
64
|
+
return this.notifications.serverError(error);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.loader.removeLoader(loader);
|
|
68
|
+
this.notifications.success(this.intl.t('storefront.products.index.new.new-product-created-success'));
|
|
69
|
+
yield this.transitionToRoute('products.index.category', category.slug);
|
|
70
|
+
this.reset();
|
|
77
71
|
}
|
|
78
72
|
|
|
79
73
|
@action addTag(tag) {
|
|
@@ -166,7 +160,6 @@ export default class ProductsIndexCategoryNewController extends BaseController {
|
|
|
166
160
|
}
|
|
167
161
|
|
|
168
162
|
@action exit(closeOverlay) {
|
|
169
|
-
console.log(closeOverlay, 'closeOverlay');
|
|
170
163
|
return closeOverlay(() => {
|
|
171
164
|
return this.transitionToRoute('products.index.category').then(() => {
|
|
172
165
|
this.reset();
|
|
@@ -174,32 +167,34 @@ export default class ProductsIndexCategoryNewController extends BaseController {
|
|
|
174
167
|
});
|
|
175
168
|
}
|
|
176
169
|
|
|
177
|
-
@
|
|
178
|
-
this.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
product,
|
|
188
|
-
updateProductAddonCategories: (categories) => {
|
|
189
|
-
this.product.addon_categories = categories.map((category) => {
|
|
190
|
-
return this.store.createRecord('product-addon-category', {
|
|
191
|
-
product_uuid: product.id,
|
|
192
|
-
category_uuid: category.id,
|
|
193
|
-
name: category.name,
|
|
194
|
-
excluded_addons: [],
|
|
195
|
-
category,
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
});
|
|
170
|
+
@task *promptSelectAddonCategories() {
|
|
171
|
+
const addonCategories = yield this.store.findAll('addon-category');
|
|
172
|
+
const selectedAddonCategories = this.product.addon_categories;
|
|
173
|
+
this.modalsManager.show('modals/select-addon-category', {
|
|
174
|
+
title: this.intl.t('storefront.products.index.new.select-addon-categories'),
|
|
175
|
+
selectedAddonCategories,
|
|
176
|
+
addonCategories,
|
|
177
|
+
updateProductAddonCategories: (addonCategories) => {
|
|
178
|
+
this.product.syncProductAddonCategories(addonCategories);
|
|
179
|
+
},
|
|
200
180
|
});
|
|
201
181
|
}
|
|
202
182
|
|
|
183
|
+
// @action selectAddonCategory() {
|
|
184
|
+
// this.store.findAll('addon-category')
|
|
185
|
+
// const addonCategories = await this.store.findAll('addon-category');
|
|
186
|
+
|
|
187
|
+
// await this.modalsManager.done();
|
|
188
|
+
// this.modalsManager.show('modals/select-addon-category', {
|
|
189
|
+
// title: this.intl.t('storefront.products.index.new.select-addon-categories'),
|
|
190
|
+
// addonCategories,
|
|
191
|
+
// selectedAddonCategories: this.product.addon_categories,
|
|
192
|
+
// updateProductAddonCategories: (addonCategories) => {
|
|
193
|
+
// this.product.syncProductAddonCategories(addonCategories);
|
|
194
|
+
// },
|
|
195
|
+
// });
|
|
196
|
+
// }
|
|
197
|
+
|
|
203
198
|
@action createProductVariant() {
|
|
204
199
|
const { product } = this;
|
|
205
200
|
const productVariant = this.store.createRecord('product-variant');
|
|
@@ -33,11 +33,17 @@ export default class ProductsIndexController extends BaseController {
|
|
|
33
33
|
return this.transitionToRoute('products.index.category.new');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Toggles a dialog which allows user to manage addon categories and options.
|
|
38
|
+
*
|
|
39
|
+
* @memberof ProductsIndexController
|
|
40
|
+
*/
|
|
36
41
|
@action manageAddons() {
|
|
37
42
|
this.modalsManager.show('modals/manage-addons', {
|
|
38
|
-
title: this.intl.t('storefront.products.index.
|
|
43
|
+
title: this.intl.t('storefront.products.index.manage-addons-dialog.manage-addons-title'),
|
|
44
|
+
acceptButtonText: this.intl.t('storefront.products.index.manage-addons-dialog.manage-addons-accept-button'),
|
|
45
|
+
acceptButtonIcon: 'save',
|
|
39
46
|
modalClass: 'modal-lg',
|
|
40
|
-
acceptButtonText: this.intl.t('storefront.products.index.done'),
|
|
41
47
|
store: this.activeStore,
|
|
42
48
|
});
|
|
43
49
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { helper } from '@ember/component/helper';
|
|
2
|
+
|
|
3
|
+
export default helper(function avatarUrl([url, defaultUrl = 'https://s3.ap-southeast-1.amazonaws.com/flb-assets/static/no-avatar.png']) {
|
|
4
|
+
if (typeof url === 'string') {
|
|
5
|
+
return url;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
return defaultUrl;
|
|
9
|
+
});
|
|
@@ -17,7 +17,14 @@ export default class ProductVariantOptionModel extends Model {
|
|
|
17
17
|
|
|
18
18
|
/** @methods */
|
|
19
19
|
toJSON() {
|
|
20
|
-
return
|
|
20
|
+
return {
|
|
21
|
+
uuid: this.id,
|
|
22
|
+
product_variant_uuid: this.product_variant_uuid,
|
|
23
|
+
name: this.name,
|
|
24
|
+
description: this.description,
|
|
25
|
+
additional_cost: this.additional_cost,
|
|
26
|
+
translations: this.additional_cost,
|
|
27
|
+
};
|
|
21
28
|
}
|
|
22
29
|
|
|
23
30
|
/** @computed */
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import Model, { attr, hasMany } from '@ember-data/model';
|
|
2
2
|
import { format, formatDistanceToNow } from 'date-fns';
|
|
3
|
+
import { isArray } from '@ember/array';
|
|
3
4
|
|
|
4
5
|
export default class ProductVariantModel extends Model {
|
|
5
6
|
/** @ids */
|
|
6
7
|
@attr('string') product_uuid;
|
|
7
8
|
|
|
8
9
|
/** @relationships */
|
|
9
|
-
@hasMany('product-variant-option') options;
|
|
10
|
+
@hasMany('product-variant-option', { async: false }) options;
|
|
10
11
|
|
|
11
12
|
/** @attributes */
|
|
12
13
|
@attr('string', { defaultValue: '' }) name;
|
|
@@ -21,7 +22,16 @@ export default class ProductVariantModel extends Model {
|
|
|
21
22
|
|
|
22
23
|
/** @methods */
|
|
23
24
|
toJSON() {
|
|
24
|
-
return
|
|
25
|
+
return {
|
|
26
|
+
uuid: this.id,
|
|
27
|
+
product_uuid: this.product_uuid,
|
|
28
|
+
name: this.name,
|
|
29
|
+
description: this.description,
|
|
30
|
+
is_multiselect: this.is_multiselect,
|
|
31
|
+
is_required: this.is_required,
|
|
32
|
+
translations: this.translations,
|
|
33
|
+
options: isArray(this.options) ? Array.from(this.options) : [],
|
|
34
|
+
};
|
|
25
35
|
}
|
|
26
36
|
|
|
27
37
|
/** @computed */
|