@fleetbase/storefront-engine 0.3.5 → 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 +3 -3
- package/extension.json +1 -1
- package/package.json +9 -3
- package/server/src/Http/Controllers/AddonCategoryController.php +90 -0
- package/server/src/Http/Controllers/v1/ReviewController.php +43 -52
- 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/Providers/StorefrontServiceProvider.php +1 -1
- package/translations/en-us.yaml +101 -39
package/addon/models/product.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
|
|
2
|
+
import ProductAddonCategoryModel from './product-addon-category';
|
|
3
|
+
import AddonCategoryModel from './addon-category';
|
|
2
4
|
import { tracked } from '@glimmer/tracking';
|
|
3
5
|
import { getOwner } from '@ember/application';
|
|
4
6
|
import { setProperties } from '@ember/object';
|
|
@@ -237,4 +239,64 @@ export default class ProductModel extends Model {
|
|
|
237
239
|
});
|
|
238
240
|
});
|
|
239
241
|
}
|
|
242
|
+
|
|
243
|
+
createAddonCategory(category) {
|
|
244
|
+
const owner = getOwner(this);
|
|
245
|
+
const store = owner.lookup('service:store');
|
|
246
|
+
if (store) {
|
|
247
|
+
const productAddonCategory = store.createRecord('product-addon-category', {
|
|
248
|
+
product_uuid: this.id,
|
|
249
|
+
category_uuid: category.id,
|
|
250
|
+
name: category.name,
|
|
251
|
+
excluded_addons: [],
|
|
252
|
+
category,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
this.addon_categories.pushObject(productAddonCategory);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
doesProductAddonCategoryExist(category) {
|
|
260
|
+
const productAddonCategories = this.addon_categories;
|
|
261
|
+
return productAddonCategories.find((_) => _.category_uuid === category.id) !== undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
isProductAddonCategory(_) {
|
|
265
|
+
return _ instanceof ProductAddonCategoryModel;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
isAddonCategory(_) {
|
|
269
|
+
return _ instanceof AddonCategoryModel;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
incomingCategoriesIsMissingExistingAddonCategory(incomingAddonCategories = [], existingProductAddonCategory) {
|
|
273
|
+
const existingProductCategoryFromIncoming = incomingAddonCategories.find((addonCategory) => {
|
|
274
|
+
if (this.isAddonCategory(addonCategory)) {
|
|
275
|
+
return addonCategory.id === existingProductAddonCategory.category_uuid;
|
|
276
|
+
}
|
|
277
|
+
return addonCategory.category_uuid === existingProductAddonCategory.category_uuid;
|
|
278
|
+
});
|
|
279
|
+
return existingProductCategoryFromIncoming === undefined;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
syncProductAddonCategories(incomingAddonCategories = []) {
|
|
283
|
+
// remove old categories first
|
|
284
|
+
const productAddonCategories = this.addon_categories;
|
|
285
|
+
for (let i = 0; i < productAddonCategories.length; i++) {
|
|
286
|
+
const productAddonCategory = productAddonCategories[i];
|
|
287
|
+
if (this.incomingCategoriesIsMissingExistingAddonCategory(incomingAddonCategories, productAddonCategory)) {
|
|
288
|
+
this.addon_categories = productAddonCategories.filter((_) => _.id !== productAddonCategory.id);
|
|
289
|
+
productAddonCategory.destroyRecord();
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// add incoming non existing addon categories
|
|
294
|
+
for (let i = 0; i < incomingAddonCategories.length; i++) {
|
|
295
|
+
const incomingAddonCategory = incomingAddonCategories[i];
|
|
296
|
+
if (this.isProductAddonCategory(incomingAddonCategory) || this.doesProductAddonCategoryExist(incomingAddonCategory)) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
this.createAddonCategory(incomingAddonCategory);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
240
302
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Route from '@ember/routing/route';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
|
|
4
|
+
export default class CustomersIndexViewRoute extends Route {
|
|
5
|
+
@service store;
|
|
6
|
+
|
|
7
|
+
queryParams = {
|
|
8
|
+
view: { refreshModel: false },
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
model({ public_id }) {
|
|
12
|
+
return this.store.findRecord('contact', public_id);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
import Route from '@ember/routing/route';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
+
import { action, set } from '@ember/object';
|
|
4
|
+
import isNestedRouteTransition from '@fleetbase/ember-core/utils/is-nested-route-transition';
|
|
3
5
|
|
|
4
6
|
export default class NetworksIndexNetworkCustomersRoute extends Route {
|
|
5
7
|
@service store;
|
|
8
|
+
@service storefront;
|
|
9
|
+
|
|
10
|
+
queryParams = {
|
|
11
|
+
page: { refreshModel: true, as: 'n_page' },
|
|
12
|
+
limit: { refreshModel: true, as: 'n_limit' },
|
|
13
|
+
sort: { refreshModel: true, as: 'n_sort' },
|
|
14
|
+
query: { refreshModel: true, as: 'n_query' },
|
|
15
|
+
status: { refreshModel: true, as: 'n_status' },
|
|
16
|
+
phone: { refreshModel: true },
|
|
17
|
+
email: { refreshModel: true },
|
|
18
|
+
address: { refreshModel: true },
|
|
19
|
+
public_id: { refreshModel: true },
|
|
20
|
+
internal_id: { refreshModel: true },
|
|
21
|
+
created_at: { refreshModel: true, as: 'n_created_at' },
|
|
22
|
+
updated_at: { refreshModel: true, as: 'n_updated_at' },
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
@action willTransition(transition) {
|
|
26
|
+
if (isNestedRouteTransition(transition)) {
|
|
27
|
+
set(this.queryParams, 'page.refreshModel', false);
|
|
28
|
+
set(this.queryParams, 'sort.refreshModel', false);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
model(params) {
|
|
33
|
+
return this.store.query('customer', { ...params, storefront: this.storefront.getActiveStore('public_id') });
|
|
34
|
+
}
|
|
6
35
|
}
|
|
@@ -3,4 +3,9 @@ import { inject as service } from '@ember/service';
|
|
|
3
3
|
|
|
4
4
|
export default class NetworksIndexNetworkOrdersRoute extends Route {
|
|
5
5
|
@service store;
|
|
6
|
+
@service storefront;
|
|
7
|
+
|
|
8
|
+
model(params) {
|
|
9
|
+
return this.store.query('order', { ...params, storefront: this.storefront.getActiveStore('public_id') });
|
|
10
|
+
}
|
|
6
11
|
}
|
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
import Route from '@ember/routing/route';
|
|
2
|
+
import { inject as service } from '@ember/service';
|
|
3
|
+
import { action } from '@ember/object';
|
|
2
4
|
|
|
3
|
-
export default class OrdersIndexViewRoute extends Route {
|
|
5
|
+
export default class OrdersIndexViewRoute extends Route {
|
|
6
|
+
@service currentUser;
|
|
7
|
+
@service notifications;
|
|
8
|
+
@service store;
|
|
9
|
+
@service socket;
|
|
10
|
+
|
|
11
|
+
@action error(error) {
|
|
12
|
+
this.notifications.serverError(error);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
model({ public_id }) {
|
|
16
|
+
const order = this.store.queryRecord('order', {
|
|
17
|
+
public_id,
|
|
18
|
+
single: true,
|
|
19
|
+
with: ['payload', 'driverAssigned', 'orderConfig', 'customer', 'facilitator', 'trackingStatuses', 'trackingNumber', 'purchaseRate', 'comments', 'files'],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return order;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Route from '@ember/routing/route';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
+
import { filterHasManyForNewRecords } from '../../../../serializers/product';
|
|
3
4
|
|
|
4
5
|
export default class ProductsIndexCategoryEditRoute extends Route {
|
|
5
6
|
@service store;
|
|
@@ -12,4 +13,9 @@ export default class ProductsIndexCategoryEditRoute extends Route {
|
|
|
12
13
|
with: ['addonCategories', 'variants', 'files', 'hours'],
|
|
13
14
|
});
|
|
14
15
|
}
|
|
16
|
+
|
|
17
|
+
setupController(controller, model) {
|
|
18
|
+
super.setupController(...arguments);
|
|
19
|
+
controller.product = filterHasManyForNewRecords(model, ['variants', 'addon_categories', 'hours']);
|
|
20
|
+
}
|
|
15
21
|
}
|
package/addon/routes.js
CHANGED
|
@@ -16,6 +16,7 @@ export default buildRoutes(function () {
|
|
|
16
16
|
this.route('customers', function () {
|
|
17
17
|
this.route('index', { path: '/' }, function () {
|
|
18
18
|
this.route('edit', { path: '/:public_id' });
|
|
19
|
+
this.route('view', { path: '/:public_id' });
|
|
19
20
|
});
|
|
20
21
|
});
|
|
21
22
|
this.route('orders', function () {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
|
|
2
|
+
|
|
3
|
+
export default class ProductVariantOptionSerializer extends ApplicationSerializer {
|
|
4
|
+
serialize(snapshot) {
|
|
5
|
+
return {
|
|
6
|
+
uuid: snapshot.record.get('id'),
|
|
7
|
+
product_variant_uuid: snapshot.record.get('product_variant_uuid'),
|
|
8
|
+
name: snapshot.record.get('name'),
|
|
9
|
+
description: snapshot.record.get('description'),
|
|
10
|
+
additional_cost: snapshot.record.get('additional_cost'),
|
|
11
|
+
translations: snapshot.record.get('additional_cost'),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
|
|
2
2
|
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
|
|
3
|
+
import { isArray } from '@ember/array';
|
|
3
4
|
|
|
4
5
|
export default class ProductVariantSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
|
|
5
6
|
/**
|
|
@@ -12,4 +13,30 @@ export default class ProductVariantSerializer extends ApplicationSerializer.exte
|
|
|
12
13
|
options: { embedded: 'always' },
|
|
13
14
|
};
|
|
14
15
|
}
|
|
16
|
+
|
|
17
|
+
serialize(snapshot) {
|
|
18
|
+
const options = snapshot.record.get('options');
|
|
19
|
+
return {
|
|
20
|
+
uuid: snapshot.record.get('id'),
|
|
21
|
+
product_uuid: snapshot.record.get('product_uuid'),
|
|
22
|
+
name: snapshot.record.get('name'),
|
|
23
|
+
description: snapshot.record.get('description'),
|
|
24
|
+
is_multiselect: snapshot.record.get('is_multiselect'),
|
|
25
|
+
is_required: snapshot.record.get('is_required'),
|
|
26
|
+
translations: snapshot.record.get('translations'),
|
|
27
|
+
options: isArray(options) ? Array.from(options) : [],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
serializeHasMany(snapshot, json, relationship) {
|
|
32
|
+
let key = relationship.key;
|
|
33
|
+
|
|
34
|
+
if (key === 'options') {
|
|
35
|
+
const options = snapshot.record.get('options');
|
|
36
|
+
json.options = isArray(options) ? Array.from(options) : [];
|
|
37
|
+
console.log('[ProductVariantSerializer #json.options]', json.options);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return super.serializeHasMany(...arguments);
|
|
41
|
+
}
|
|
15
42
|
}
|
|
@@ -2,6 +2,27 @@ import ApplicationSerializer from '@fleetbase/ember-core/serializers/application
|
|
|
2
2
|
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
|
|
3
3
|
import { isArray } from '@ember/array';
|
|
4
4
|
|
|
5
|
+
export function filterHasManyForNewRecords(model, relations = []) {
|
|
6
|
+
for (let i = 0; i < relations.length; i++) {
|
|
7
|
+
let relationKey = relations[i];
|
|
8
|
+
let data = model[relationKey];
|
|
9
|
+
if (isArray(data)) {
|
|
10
|
+
data = data.filter((_) => {
|
|
11
|
+
if (relationKey === 'variants') {
|
|
12
|
+
_ = filterHasManyForNewRecords(_, ['options']);
|
|
13
|
+
}
|
|
14
|
+
return !_.isNew;
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
data = [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
model.set(relationKey, data);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return model;
|
|
24
|
+
}
|
|
25
|
+
|
|
5
26
|
export default class ProductSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
|
|
6
27
|
/**
|
|
7
28
|
* Embedded relationship attributes
|
|
@@ -24,11 +45,12 @@ export default class ProductSerializer extends ApplicationSerializer.extend(Embe
|
|
|
24
45
|
|
|
25
46
|
if (key === 'addon_categories') {
|
|
26
47
|
const addonCategories = snapshot.record.get('addon_categories');
|
|
48
|
+
json.addon_categories = isArray(addonCategories) ? Array.from(addonCategories) : [];
|
|
49
|
+
}
|
|
27
50
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return;
|
|
51
|
+
if (key === 'variants') {
|
|
52
|
+
const variants = snapshot.record.get('variants');
|
|
53
|
+
json.variants = isArray(variants) ? Array.from(variants) : [];
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
return super.serializeHasMany(...arguments);
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import Service from '@ember/service';
|
|
2
|
+
import { tracked } from '@glimmer/tracking';
|
|
3
|
+
import { action } from '@ember/object';
|
|
4
|
+
import { camelize } from '@ember/string';
|
|
5
|
+
import getModelName from '@fleetbase/ember-core/utils/get-model-name';
|
|
6
|
+
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
|
|
7
|
+
import isObject from '@fleetbase/ember-core/utils/is-object';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Service for managing the state and interactions of the context panel.
|
|
11
|
+
*
|
|
12
|
+
* @class ContextPanelService
|
|
13
|
+
* @memberof @fleetbase/storefront
|
|
14
|
+
* @extends Service
|
|
15
|
+
*/
|
|
16
|
+
export default class ContextPanelService extends Service {
|
|
17
|
+
/**
|
|
18
|
+
* Registry mapping model names to their corresponding component details.
|
|
19
|
+
* @type {Object}
|
|
20
|
+
*/
|
|
21
|
+
registry = {
|
|
22
|
+
customer: {
|
|
23
|
+
viewing: {
|
|
24
|
+
component: 'customer-panel',
|
|
25
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
order: {
|
|
29
|
+
viewing: {
|
|
30
|
+
component: 'order-panel',
|
|
31
|
+
componentArguments: [{ isResizable: true }, { width: '500px' }],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The current context or model object.
|
|
38
|
+
* @type {Object}
|
|
39
|
+
* @tracked
|
|
40
|
+
*/
|
|
41
|
+
@tracked currentContext;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The current registry configuration for the current context.
|
|
45
|
+
* @type {Object}
|
|
46
|
+
* @tracked
|
|
47
|
+
*/
|
|
48
|
+
@tracked currentContextRegistry;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Arguments for the current context component.
|
|
52
|
+
* @type {Object}
|
|
53
|
+
* @tracked
|
|
54
|
+
*/
|
|
55
|
+
@tracked currentContextComponentArguments = {};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Additional options for controlling the context.
|
|
59
|
+
* @type {Object}
|
|
60
|
+
* @tracked
|
|
61
|
+
*/
|
|
62
|
+
@tracked contextOptions = {};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Focuses on a given model and intent.
|
|
66
|
+
*
|
|
67
|
+
* @method
|
|
68
|
+
* @param {Object} model - The model to focus on.
|
|
69
|
+
* @param {String} [intent='viewing'] - The type of intent ('viewing' or 'editing').
|
|
70
|
+
* @action
|
|
71
|
+
*/
|
|
72
|
+
@action focus(model, intent = 'viewing', options = {}) {
|
|
73
|
+
// handle focus which is not based on a model resource
|
|
74
|
+
// this is purely intent
|
|
75
|
+
if (typeof model === 'string') {
|
|
76
|
+
if (isObject(intent)) {
|
|
77
|
+
options = intent;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const registry = this.registry[model];
|
|
81
|
+
const dynamicArgs = getWithDefault(options, 'args', {});
|
|
82
|
+
if (registry) {
|
|
83
|
+
this.currentContext = null;
|
|
84
|
+
this.currentContextRegistry = registry;
|
|
85
|
+
this.currentContextComponentArguments = this.createDynamicArgsFromRegistry(registry, model, dynamicArgs);
|
|
86
|
+
this.contextOptions = options;
|
|
87
|
+
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
throw new Error(`Unable to focus selected context: ${model}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const modelName = getModelName(model);
|
|
95
|
+
const registry = this.getRegistryFromModelName(modelName);
|
|
96
|
+
const dynamicArgs = getWithDefault(options, 'args', {});
|
|
97
|
+
if (registry && registry[intent]) {
|
|
98
|
+
this.currentContext = model;
|
|
99
|
+
this.currentContextRegistry = registry[intent];
|
|
100
|
+
this.currentContextComponentArguments = this.createDynamicArgsFromRegistry(registry[intent], model, dynamicArgs);
|
|
101
|
+
this.contextOptions = options;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the correct registry from the modelName provided.
|
|
108
|
+
*
|
|
109
|
+
* @param {string} modelName
|
|
110
|
+
* @return {object}
|
|
111
|
+
* @memberof ContextPanelService
|
|
112
|
+
*/
|
|
113
|
+
getRegistryFromModelName(modelName) {
|
|
114
|
+
if (typeof modelName === 'string' && modelName.includes('-')) {
|
|
115
|
+
modelName = camelize(modelName);
|
|
116
|
+
}
|
|
117
|
+
return this.registry[modelName];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Clears the current context and associated details.
|
|
122
|
+
*
|
|
123
|
+
* @method
|
|
124
|
+
* @action
|
|
125
|
+
*/
|
|
126
|
+
@action clear() {
|
|
127
|
+
this.currentContext = null;
|
|
128
|
+
this.currentContextRegistry = null;
|
|
129
|
+
this.currentContextComponentArguments = {};
|
|
130
|
+
this.contextOptions = {};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Changes the intent for the current context.
|
|
135
|
+
*
|
|
136
|
+
* @method
|
|
137
|
+
* @param {String} intent - The new intent.
|
|
138
|
+
* @action
|
|
139
|
+
*/
|
|
140
|
+
@action changeIntent(intent) {
|
|
141
|
+
if (this.currentContext) {
|
|
142
|
+
return this.focus(this.currentContext, intent);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Sets an option key-value pair.
|
|
148
|
+
*
|
|
149
|
+
* @method
|
|
150
|
+
* @param {String} key - The option key.
|
|
151
|
+
* @param {*} value - The option value.
|
|
152
|
+
*/
|
|
153
|
+
setOption(key, value) {
|
|
154
|
+
this.contextOptions = {
|
|
155
|
+
...this.contextOptions,
|
|
156
|
+
[key]: value,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Retrieves the value of an option key.
|
|
162
|
+
*
|
|
163
|
+
* @method
|
|
164
|
+
* @param {String} key - The option key.
|
|
165
|
+
* @param {*} [defaultValue=null] - The default value to return if the key is not found.
|
|
166
|
+
* @returns {*}
|
|
167
|
+
*/
|
|
168
|
+
getOption(key, defaultValue = null) {
|
|
169
|
+
const value = this.contextOptions[key];
|
|
170
|
+
|
|
171
|
+
if (value === undefined) {
|
|
172
|
+
return defaultValue;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Generates dynamic arguments for a given registry and model.
|
|
180
|
+
*
|
|
181
|
+
* @method
|
|
182
|
+
* @param {Object} registry - The registry details for a given model.
|
|
183
|
+
* @param {Object} model - The model object.
|
|
184
|
+
* @returns {Object} The dynamic arguments.
|
|
185
|
+
*/
|
|
186
|
+
createDynamicArgsFromRegistry(registry, model, additionalArgs = {}) {
|
|
187
|
+
// Generate dynamic arguments object
|
|
188
|
+
const dynamicArgs = {
|
|
189
|
+
[camelize(getModelName(model))]: model,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const componentArguments = registry.componentArguments || [];
|
|
193
|
+
|
|
194
|
+
componentArguments.forEach((arg, index) => {
|
|
195
|
+
if (typeof arg === 'string') {
|
|
196
|
+
dynamicArgs[arg] = model[arg]; // Map string arguments to model properties
|
|
197
|
+
} else if (typeof arg === 'object' && arg !== null) {
|
|
198
|
+
Object.assign(dynamicArgs, arg);
|
|
199
|
+
} else {
|
|
200
|
+
// Handle other types of arguments as needed
|
|
201
|
+
dynamicArgs[`arg${index}`] = arg;
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Merge additional args
|
|
206
|
+
Object.assign(dynamicArgs, additionalArgs);
|
|
207
|
+
|
|
208
|
+
return dynamicArgs;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
.ui-combo-box .options-list a.combo-box-option.selected,
|
|
2
|
+
.ui-combo-box .selected-list a.combo-box-option.selected,
|
|
3
|
+
.ui-combo-box .options-list a.combo-box-option.selected:hover,
|
|
4
|
+
.ui-combo-box .selected-list a.combo-box-option.selected:hover {
|
|
5
|
+
background-color: #76a9fa !important;
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<CustomerPanel @customer={{@model}} @tab={{this.view}} @onTabChanged={{this.onTabChanged}} @onPressCancel={{this.transitionBack}} @onEdit={{this.onEdit}} />
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
{{
|
|
1
|
+
<Layout::Section::Header @title={{t "storefront.common.customers"}} @searchQuery={{this.query}} @onSearch={{perform this.search}} />
|
|
2
|
+
|
|
3
|
+
<Layout::Section::Body>
|
|
4
|
+
<Table
|
|
5
|
+
@wrapperClass="overscroll-y-none"
|
|
6
|
+
@rows={{@model}}
|
|
7
|
+
@columns={{this.columns}}
|
|
8
|
+
@selectable={{false}}
|
|
9
|
+
@canSelectAll={{false}}
|
|
10
|
+
@onSetup={{fn (mut this.table)}}
|
|
11
|
+
@pagination={{true}}
|
|
12
|
+
@paginationMeta={{@model.meta}}
|
|
13
|
+
@page={{this.page}}
|
|
14
|
+
@onPageChange={{fn (mut this.page)}}
|
|
15
|
+
@tfootVerticalOffset="53"
|
|
16
|
+
@tfootVerticalOffsetElements=".next-view-section-subheader"
|
|
17
|
+
/>
|
|
18
|
+
</Layout::Section::Body>
|
|
@@ -1 +1,18 @@
|
|
|
1
|
-
{{
|
|
1
|
+
<Layout::Section::Header @title={{t "storefront.common.orders"}} @searchQuery={{this.query}} @onSearch={{perform this.search}} />
|
|
2
|
+
|
|
3
|
+
<Layout::Section::Body>
|
|
4
|
+
<Table
|
|
5
|
+
@wrapperClass="overscroll-y-none"
|
|
6
|
+
@rows={{@model}}
|
|
7
|
+
@columns={{this.columns}}
|
|
8
|
+
@selectable={{true}}
|
|
9
|
+
@canSelectAll={{true}}
|
|
10
|
+
@onSetup={{fn (mut this.table)}}
|
|
11
|
+
@pagination={{true}}
|
|
12
|
+
@paginationMeta={{@model.meta}}
|
|
13
|
+
@page={{this.page}}
|
|
14
|
+
@onPageChange={{fn (mut this.page)}}
|
|
15
|
+
@tfootVerticalOffset="53"
|
|
16
|
+
@tfootVerticalOffsetElements=".next-view-section-subheader"
|
|
17
|
+
/>
|
|
18
|
+
</Layout::Section::Body>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<Overlay @position="right" @isResizable={{true}} @noBackdrop={{true}} @width="
|
|
1
|
+
<Overlay @position="right" @isResizable={{true}} @noBackdrop={{true}} @width="900px" @minResizeWidth={{570}} @fullHeight={{true}}>
|
|
2
2
|
<Overlay::Header @title={{t "storefront.networks.index.network.manage-network"}} @onPressCancel={{this.transitionBack}} />
|
|
3
3
|
<Overlay::Body class="p-0i" @increaseInnerBodyHeightBy="0" @wrapperClass="space-y-4 pt-4">
|
|
4
4
|
<div class="flex flex-col">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{{
|
|
1
|
+
<OrderPanel::Details @order={{@model}} @onPressCancel={{this.transitionBack}} />
|