diff --git a/addon/templates/networks/index/network/customers.hbs b/addon/templates/networks/index/network/customers.hbs
index e2147ca..ae41eb1 100644
--- a/addon/templates/networks/index/network/customers.hbs
+++ b/addon/templates/networks/index/network/customers.hbs
@@ -1 +1,18 @@
-{{outlet}}
\ No newline at end of file
+
+
+
+
+
\ No newline at end of file
diff --git a/addon/templates/networks/index/network/orders.hbs b/addon/templates/networks/index/network/orders.hbs
index e2147ca..fe3c092 100644
--- a/addon/templates/networks/index/network/orders.hbs
+++ b/addon/templates/networks/index/network/orders.hbs
@@ -1 +1,18 @@
-{{outlet}}
\ No newline at end of file
+
+
+
+
+
\ No newline at end of file
diff --git a/addon/templates/orders/index/view.hbs b/addon/templates/orders/index/view.hbs
index e2147ca..0def9f9 100644
--- a/addon/templates/orders/index/view.hbs
+++ b/addon/templates/orders/index/view.hbs
@@ -1 +1 @@
-{{outlet}}
\ No newline at end of file
+
\ No newline at end of file
diff --git a/addon/templates/products/index/category/new.hbs b/addon/templates/products/index/category/new.hbs
index 84f92b2..0c79a0b 100644
--- a/addon/templates/products/index/category/new.hbs
+++ b/addon/templates/products/index/category/new.hbs
@@ -1,20 +1,6 @@
-
-
+
+
@@ -23,48 +9,21 @@
-
+
{{tag}}
-
+
-
+
-
+
{{#each this.product.meta_array as |metaField index|}}
{{#each this.product.addon_categories as |addonCategory index|}}
@@ -215,9 +169,7 @@
{{#if this.isUploading}}
-
+
@@ -276,14 +228,7 @@
{{#each this.product.files as |file|}}
-
+
{{/each}}
diff --git a/app/components/context-panel.js b/app/components/context-panel.js
new file mode 100644
index 0000000..c6f83b2
--- /dev/null
+++ b/app/components/context-panel.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/context-panel';
diff --git a/app/components/customer-panel.js b/app/components/customer-panel.js
new file mode 100644
index 0000000..728c15a
--- /dev/null
+++ b/app/components/customer-panel.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/customer-panel';
diff --git a/app/components/customer-panel/details.js b/app/components/customer-panel/details.js
new file mode 100644
index 0000000..8627445
--- /dev/null
+++ b/app/components/customer-panel/details.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/customer-panel/details';
diff --git a/app/components/customer-panel/orders.js b/app/components/customer-panel/orders.js
new file mode 100644
index 0000000..ac43c06
--- /dev/null
+++ b/app/components/customer-panel/orders.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/customer-panel/orders';
diff --git a/app/components/display-place.js b/app/components/display-place.js
new file mode 100644
index 0000000..0ad8b9b
--- /dev/null
+++ b/app/components/display-place.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/display-place';
diff --git a/app/components/order-panel.js b/app/components/order-panel.js
new file mode 100644
index 0000000..f33927a
--- /dev/null
+++ b/app/components/order-panel.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/order-panel';
diff --git a/app/components/order-panel/details.js b/app/components/order-panel/details.js
new file mode 100644
index 0000000..52ede46
--- /dev/null
+++ b/app/components/order-panel/details.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/components/order-panel/details';
diff --git a/app/controllers/customers/index/view.js b/app/controllers/customers/index/view.js
new file mode 100644
index 0000000..863db8c
--- /dev/null
+++ b/app/controllers/customers/index/view.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/controllers/customers/index/view';
diff --git a/app/controllers/orders/index/view.js b/app/controllers/orders/index/view.js
new file mode 100644
index 0000000..eb53c45
--- /dev/null
+++ b/app/controllers/orders/index/view.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/controllers/orders/index/view';
diff --git a/app/helpers/avatar-url.js b/app/helpers/avatar-url.js
new file mode 100644
index 0000000..6c6ff8e
--- /dev/null
+++ b/app/helpers/avatar-url.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/helpers/avatar-url';
diff --git a/app/routes/customers/index/view.js b/app/routes/customers/index/view.js
new file mode 100644
index 0000000..74e2c04
--- /dev/null
+++ b/app/routes/customers/index/view.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/routes/customers/index/view';
diff --git a/app/serializers/product-variant-option.js b/app/serializers/product-variant-option.js
new file mode 100644
index 0000000..8627122
--- /dev/null
+++ b/app/serializers/product-variant-option.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/serializers/product-variant-option';
diff --git a/app/services/context-panel.js b/app/services/context-panel.js
new file mode 100644
index 0000000..24f6e11
--- /dev/null
+++ b/app/services/context-panel.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/services/context-panel';
diff --git a/app/templates/customers/index/view.js b/app/templates/customers/index/view.js
new file mode 100644
index 0000000..60f8389
--- /dev/null
+++ b/app/templates/customers/index/view.js
@@ -0,0 +1 @@
+export { default } from '@fleetbase/storefront-engine/templates/customers/index/view';
diff --git a/composer.json b/composer.json
index 7df429a..1cf2bb1 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "fleetbase/storefront-api",
- "version": "0.3.5",
+ "version": "0.3.6",
"description": "Headless Commerce & Marketplace Extension for Fleetbase",
"keywords": [
"fleetbase-extension",
@@ -22,8 +22,8 @@
],
"require": {
"php": "^8.0",
- "fleetbase/core-api": "^1.4.12",
- "fleetbase/fleetops-api": "^0.4.18",
+ "fleetbase/core-api": "^1.4.15",
+ "fleetbase/fleetops-api": "^0.4.23",
"geocoder-php/google-maps-places-provider": "^1.4",
"laravel-notification-channels/apn": "^5.0",
"laravel-notification-channels/fcm": "^4.1",
diff --git a/extension.json b/extension.json
index 34c93ad..d2b5691 100644
--- a/extension.json
+++ b/extension.json
@@ -1,6 +1,6 @@
{
"name": "Storefront",
- "version": "0.3.5",
+ "version": "0.3.6",
"description": "Headless Commerce & Marketplace Extension for Fleetbase",
"repository": "https://github.com/fleetbase/storefront",
"license": "MIT",
diff --git a/package.json b/package.json
index 60e3c4d..be91272 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/storefront-engine",
- "version": "0.3.5",
+ "version": "0.3.6",
"description": "Headless Commerce & Marketplace Extension for Fleetbase",
"fleetbase": {
"route": "storefront",
@@ -43,9 +43,9 @@
"publish:github": "npm config set '@fleetbase:registry' https://npm.pkg.github.com/ && npm publish"
},
"dependencies": {
- "@fleetbase/ember-core": "^0.2.6",
+ "@fleetbase/ember-core": "^0.2.8",
"@fleetbase/ember-ui": "^0.2.11",
- "@fleetbase/fleetops-data": "^0.1.13",
+ "@fleetbase/fleetops-data": "^0.1.14",
"@babel/core": "^7.23.2",
"@fortawesome/ember-fontawesome": "^0.4.1",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
@@ -130,6 +130,12 @@
"options": {
"singleQuote": false
}
+ },
+ {
+ "files": "*.{yml,yaml}",
+ "options": {
+ "tabWidth": 2
+ }
}
]
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ae36e4e..74aa4fd 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,14 +5,14 @@ dependencies:
specifier: ^7.23.2
version: 7.23.2
'@fleetbase/ember-core':
- specifier: ^0.2.6
- version: 0.2.6(@ember/test-helpers@3.2.0)(ember-source@5.4.0)(webpack@5.89.0)
+ specifier: ^0.2.8
+ version: 0.2.8(@ember/test-helpers@3.2.0)(ember-source@5.4.0)(webpack@5.89.0)
'@fleetbase/ember-ui':
specifier: ^0.2.11
version: 0.2.11(@ember/test-helpers@3.2.0)(@glimmer/component@1.1.2)(@glimmer/tracking@1.1.2)(ember-source@5.4.0)(postcss@8.4.35)(rollup@4.12.0)(tracked-built-ins@3.3.0)(webpack@5.89.0)
'@fleetbase/fleetops-data':
- specifier: ^0.1.13
- version: 0.1.13
+ specifier: ^0.1.14
+ version: 0.1.14
'@fortawesome/ember-fontawesome':
specifier: ^0.4.1
version: 0.4.1(rollup@4.12.0)
@@ -2360,8 +2360,8 @@ packages:
- supports-color
dev: false
- /@fleetbase/ember-core@0.2.6(@ember/test-helpers@3.2.0)(ember-source@5.4.0)(webpack@5.89.0):
- resolution: {integrity: sha512-EHO47NM6XH/1bC6TL7cEbJQ//RCrdFb1+TsCIHvhPtP7KSGyam2gexiiNlwTm4fgVizxyvDCbCpGDMEs8ltZnA==}
+ /@fleetbase/ember-core@0.2.8(@ember/test-helpers@3.2.0)(ember-source@5.4.0)(webpack@5.89.0):
+ resolution: {integrity: sha512-9GGwjkp038UuMX4IHjw4NUqSinCOQWMisFG6XhQT8iyGlcOfSXJX8CxMyNutKpdwQ21VPbRoylVw0q4CmwjaNw==}
engines: {node: '>= 18'}
dependencies:
'@babel/core': 7.23.2
@@ -2476,8 +2476,8 @@ packages:
- webpack-command
dev: false
- /@fleetbase/fleetops-data@0.1.13:
- resolution: {integrity: sha512-+JgP0p15TxMOxfJCSPJt/2nTA8ZugukGuaFYQTLzD0TFFKXjZE9bmYKPf+Z5w9L4oJ4b1oLsvRv6BL5dFt11lw==}
+ /@fleetbase/fleetops-data@0.1.14:
+ resolution: {integrity: sha512-CNgr/De//I2+USYBhFvaRD4c1KBbNJUUmPy5oT07fkFbCGplYeVfPhYlCxj2JpeGbtBBqfGEujrViRVRfR2JKg==}
engines: {node: '>= 18'}
dependencies:
'@babel/core': 7.23.2
diff --git a/server/src/Http/Controllers/AddonCategoryController.php b/server/src/Http/Controllers/AddonCategoryController.php
index 4ef2517..e60c2bb 100644
--- a/server/src/Http/Controllers/AddonCategoryController.php
+++ b/server/src/Http/Controllers/AddonCategoryController.php
@@ -2,6 +2,10 @@
namespace Fleetbase\Storefront\Http\Controllers;
+use Fleetbase\Storefront\Models\AddonCategory;
+use Fleetbase\Support\Http;
+use Illuminate\Http\Request;
+
class AddonCategoryController extends StorefrontController
{
/**
@@ -10,4 +14,90 @@ class AddonCategoryController extends StorefrontController
* @var string
*/
public $resource = 'addon_category';
+
+ /**
+ * Creates a new record based on the provided request data.
+ *
+ * This method handles the creation of a new record using data from the request.
+ * It includes a validation step, creation of the record, and an optional closure
+ * to perform additional operations on the model and request data. The method
+ * returns an instance of a resource, which wraps the created record. Error handling
+ * is implemented to catch and respond to various exceptions that might occur during the process.
+ *
+ * @param Request $request the incoming HTTP request containing data for the new record
+ *
+ * @return mixed an instance of the resource class containing the created record, or an error response
+ *
+ * @throws \Exception general exceptions with a message
+ * @throws \Illuminate\Database\QueryException database query exceptions with a message
+ * @throws \Fleetbase\Exceptions\FleetbaseRequestValidationException custom validation exceptions with error details
+ */
+ public function createRecord(Request $request)
+ {
+ try {
+ $this->validateRequest($request);
+
+ $record = $this->model->createRecordFromRequest($request, null, function (&$request, AddonCategory &$addonCategory) {
+ $addons = $request->array('addonCategory.addons');
+ $addonCategory->setAddons($addons);
+ });
+
+ if (Http::isInternalRequest($request)) {
+ $this->resource::wrap($this->resourceSingularlName);
+
+ return new $this->resource($record);
+ }
+
+ return new $this->resource($record);
+ } catch (\Exception $e) {
+ return response()->error($e->getMessage());
+ } catch (\Illuminate\Database\QueryException $e) {
+ return response()->error($e->getMessage());
+ } catch (\Fleetbase\Exceptions\FleetbaseRequestValidationException $e) {
+ return response()->error($e->getErrors());
+ }
+ }
+
+ /**
+ * Updates an existing record based on the provided request data.
+ *
+ * This method updates a record identified by the provided ID using data from the request.
+ * It includes a validation step, updating of the record, and an optional closure
+ * to perform additional operations on the model and request data. The method returns
+ * an instance of a resource, which wraps the updated record. Error handling is implemented
+ * to catch and respond to various exceptions that might occur during the update process.
+ *
+ * @param Request $request the incoming HTTP request containing data for updating the record
+ * @param string $id the identifier of the record to be updated
+ *
+ * @return mixed an instance of the resource class containing the updated record, or an error response
+ *
+ * @throws \Exception general exceptions with a message
+ * @throws \Illuminate\Database\QueryException database query exceptions with a message
+ * @throws \Fleetbase\Exceptions\FleetbaseRequestValidationException custom validation exceptions with error details
+ */
+ public function updateRecord(Request $request, string $id)
+ {
+ try {
+ $this->validateRequest($request);
+ $record = $this->model->updateRecordFromRequest($request, $id, function (&$request, AddonCategory &$addonCategory) {
+ $addons = $request->array('addonCategory.addons');
+ $addonCategory->setAddons($addons);
+ });
+
+ if (Http::isInternalRequest($request)) {
+ $this->resource::wrap($this->resourceSingularlName);
+
+ return new $this->resource($record);
+ }
+
+ return new $this->resource($record);
+ } catch (\Exception $e) {
+ return response()->error($e->getMessage());
+ } catch (\Illuminate\Database\QueryException $e) {
+ return response()->error($e->getMessage());
+ } catch (\Fleetbase\Exceptions\FleetbaseRequestValidationException $e) {
+ return response()->error($e->getErrors());
+ }
+ }
}
diff --git a/server/src/Http/Controllers/v1/ReviewController.php b/server/src/Http/Controllers/v1/ReviewController.php
index 8fffd1a..c0fec38 100644
--- a/server/src/Http/Controllers/v1/ReviewController.php
+++ b/server/src/Http/Controllers/v1/ReviewController.php
@@ -28,40 +28,20 @@ public function query(Request $request)
$offset = $request->input('offset', false);
$sort = $request->input('sort');
+ if ($sort) {
+ $this->applySort($request, $sort);
+ }
+
if (session('storefront_store')) {
- $results = Review::queryWithRequest($request, function (&$query) use ($limit, $offset, $sort) {
- $query->where('subject_uuid', session('storefront_store'));
+ $results = Review::queryWithRequest($request, function (&$query) use ($store, $limit, $offset) {
+ $query->where('subject_uuid', $store->uuid);
if ($limit) {
$query->limit($limit);
}
if ($offset) {
- $query->limit($offset);
- }
-
- if ($sort) {
- switch ($sort) {
- case 'highest':
- case 'highest rated':
- $query->orderByDesc('rating');
- break;
-
- case 'lowest':
- case 'lowest rated':
- $query->orderBy('rating');
- break;
-
- case 'newest':
- case 'newest first':
- $query->orderByDesc('created_at');
- break;
-
- case 'oldest':
- case 'oldest first':
- $query->orderBy('created_at');
- break;
- }
+ $query->offset($offset);
}
});
}
@@ -79,7 +59,7 @@ public function query(Request $request)
return response()->json(['error' => 'Cannot find reviews for store'], 400);
}
- $results = Review::queryWithRequest($request, function (&$query) use ($store, $sort, $limit, $offset) {
+ $results = Review::queryWithRequest($request, function (&$query) use ($store, $limit, $offset) {
$query->where('subject_uuid', $store->uuid);
if ($limit) {
@@ -89,30 +69,6 @@ public function query(Request $request)
if ($offset) {
$query->limit($offset);
}
-
- if ($sort) {
- switch ($sort) {
- case 'highest':
- case 'highest rated':
- $query->orderByDesc('rating');
- break;
-
- case 'lowest':
- case 'lowest rated':
- $query->orderBy('rating');
- break;
-
- case 'newest':
- case 'newest first':
- $query->orderByDesc('created_at');
- break;
-
- case 'oldest':
- case 'oldest first':
- $query->orderBy('created_at');
- break;
- }
- }
});
}
}
@@ -120,6 +76,41 @@ public function query(Request $request)
return StorefrontReview::collection($results);
}
+ public function applySort($request, $sort)
+ {
+ if ($sort) {
+ switch ($sort) {
+ case 'highest':
+ case 'highest rated':
+ $request->merge(['sort' => 'rating', 'sort_direction' => 'desc']);
+
+ break;
+
+ case 'lowest':
+ case 'lowest rated':
+ $request->merge(['sort' => 'rating', 'sort_direction' => 'asc']);
+
+ break;
+
+ case 'newest':
+ case 'newest first':
+ $request->merge(['sort' => 'created_at', 'sort_direction' => 'desc']);
+
+ break;
+
+ case 'oldest':
+ case 'oldest first':
+ $request->merge(['sort' => 'created_at', 'sort_direction' => 'asc']);
+
+ break;
+
+ default:
+ // Handle unknown sorting criteria
+ break;
+ }
+ }
+ }
+
/**
* Coutns the number of ratings between 1-5 for a store.
*
diff --git a/server/src/Http/Resources/Network.php b/server/src/Http/Resources/Network.php
index fa72d98..7418b56 100644
--- a/server/src/Http/Resources/Network.php
+++ b/server/src/Http/Resources/Network.php
@@ -17,38 +17,40 @@ class Network extends FleetbaseResource
public function toArray($request)
{
return [
- 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
- 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
- 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
- 'key' => $this->when(Http::isInternalRequest(), $this->key),
- 'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
- 'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
- 'logo_uuid' => $this->when(Http::isInternalRequest(), $this->logo_uuid),
- 'backdrop_uuid' => $this->when(Http::isInternalRequest(), $this->backdrop_uuid),
- 'name' => $this->name,
- 'description' => $this->description,
- 'translations' => $this->translations ?? [],
- 'website' => $this->website,
- 'facebook' => $this->facebook,
- 'instagram' => $this->instagram,
- 'twitter' => $this->twitter,
- 'email' => $this->email,
- 'phone' => $this->phone,
- 'tags' => $this->tags ?? [],
- 'currency' => $this->currency ?? 'USD',
- 'options' => $this->options ?? [],
- 'alertable' => $this->alertable,
- 'logo_url' => $this->logo_url,
- 'backdrop_url' => $this->backdrop_url,
- 'rating' => $this->rating,
- 'online' => $this->online,
- 'stores' => $this->when($request->boolean('with_stores') || $request->inArray('with', 'stores'), Store::collection($this->stores)),
- 'categories' => $this->when($request->boolean('with_categories') || $request->inArray('with', 'categories'), Category::collection($this->categories)),
- 'is_network' => true,
- 'is_store' => false,
- 'slug' => $this->slug,
- 'created_at' => $this->created_at,
- 'updated_at' => $this->updated_at,
+ 'id' => $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
+ 'key' => $this->when(Http::isInternalRequest(), $this->key),
+ 'company_uuid' => $this->when(Http::isInternalRequest(), $this->company_uuid),
+ 'created_by_uuid' => $this->when(Http::isInternalRequest(), $this->created_by_uuid),
+ 'logo_uuid' => $this->when(Http::isInternalRequest(), $this->logo_uuid),
+ 'backdrop_uuid' => $this->when(Http::isInternalRequest(), $this->backdrop_uuid),
+ 'name' => $this->name,
+ 'description' => $this->description,
+ 'translations' => $this->translations ?? [],
+ 'website' => $this->website,
+ 'facebook' => $this->facebook,
+ 'instagram' => $this->instagram,
+ 'twitter' => $this->twitter,
+ 'email' => $this->email,
+ 'phone' => $this->phone,
+ 'tags' => $this->tags ?? [],
+ 'currency' => $this->currency ?? 'USD',
+ 'options' => $this->options ?? [],
+ 'alertable' => $this->alertable,
+ 'logo_url' => $this->logo_url,
+ 'backdrop_url' => $this->backdrop_url,
+ 'rating' => $this->rating,
+ 'online' => $this->online,
+ 'stores' => $this->when($request->boolean('with_stores') || $request->inArray('with', 'stores'), Store::collection($this->stores)),
+ 'categories' => $this->when($request->boolean('with_categories') || $request->inArray('with', 'categories'), Category::collection($this->categories)),
+ 'gateways' => $this->when($request->boolean('with_gateways') || $request->inArray('with', 'gateways'), Gateway::collection($this->gateways)),
+ 'notification_channels' => $this->when($request->boolean('with_notification_channels') || $request->inArray('with', 'notification_channels'), NotificationChannel::collection($this->notificationChannels)),
+ 'is_network' => true,
+ 'is_store' => false,
+ 'slug' => $this->slug,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
];
}
}
diff --git a/server/src/Http/Resources/NotificationChannel.php b/server/src/Http/Resources/NotificationChannel.php
new file mode 100644
index 0000000..859ced2
--- /dev/null
+++ b/server/src/Http/Resources/NotificationChannel.php
@@ -0,0 +1,32 @@
+ $this->when(Http::isInternalRequest(), $this->id, $this->public_id),
+ 'uuid' => $this->when(Http::isInternalRequest(), $this->uuid),
+ 'public_id' => $this->when(Http::isInternalRequest(), $this->public_id),
+ 'name' => $this->name,
+ 'scheme' => $this->scheme,
+ 'options' => $this->options,
+ 'is_apn_gateway' => $this->is_apn_gateway,
+ 'is_fcm_gateway' => $this->is_fcm_gateway,
+ 'created_at' => $this->created_at,
+ 'updated_at' => $this->updated_at,
+ ];
+ }
+}
diff --git a/server/src/Http/Resources/Product.php b/server/src/Http/Resources/Product.php
index 6b1cf9b..5c2e695 100644
--- a/server/src/Http/Resources/Product.php
+++ b/server/src/Http/Resources/Product.php
@@ -97,14 +97,16 @@ public function mapAddonCategories(\Illuminate\Database\Eloquent\Collection $add
if (Http::isInternalRequest()) {
return [
- 'uuid' => $addonCategory->uuid,
- 'public_id' => data_get($addonCategory, 'category.public_id'),
- 'id' => $addonCategory->id,
- 'name' => $addonCategory->name,
- 'excluded_addons' => $addonCategory->excluded_addons,
- 'category' => $addonCategory->category,
- 'created_at' => $addonCategory->created_at,
- 'updated_at' => $addonCategory->updated_at,
+ 'uuid' => $addonCategory->uuid,
+ 'product_uuid' => $addonCategory->product_uuid,
+ 'category_uuid' => $addonCategory->category_uuid,
+ 'public_id' => data_get($addonCategory, 'category.public_id'),
+ 'id' => $addonCategory->id,
+ 'name' => $addonCategory->name,
+ 'excluded_addons' => $addonCategory->excluded_addons,
+ 'category' => $addonCategory->category,
+ 'created_at' => $addonCategory->created_at,
+ 'updated_at' => $addonCategory->updated_at,
];
} else {
return [
diff --git a/server/src/Models/AddonCategory.php b/server/src/Models/AddonCategory.php
index de88bcf..e6e61d1 100644
--- a/server/src/Models/AddonCategory.php
+++ b/server/src/Models/AddonCategory.php
@@ -3,6 +3,8 @@
namespace Fleetbase\Storefront\Models;
use Fleetbase\Models\Category;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Str;
class AddonCategory extends Category
{
@@ -25,4 +27,39 @@ public function addons()
{
return $this->setConnection(config('storefront.connection.db'))->hasMany(ProductAddon::class, 'category_uuid');
}
+
+ public function setAddons(array $addons = []): AddonCategory
+ {
+ foreach ($addons as $addon) {
+ // get uuid if set
+ $id = data_get($addon, 'uuid');
+
+ // make sure the cateogry is set to this current
+ data_set($addon, 'category_uuid', $this->uuid);
+
+ // make sure sale price is 0 if null
+ if (data_get($addon, 'sale_price') === null) {
+ data_set($addon, 'sale_price', 0);
+ }
+
+ // update product addon category
+ if (Str::isUuid($id)) {
+ ProductAddon::where('uuid', $id)->update(Arr::except($addon, ['uuid', 'created_at', 'updated_at']));
+ continue;
+ }
+
+ // create new product addon category
+ ProductAddon::create([
+ 'category_uuid' => $this->uuid,
+ 'name' => data_get($addon, 'name'),
+ 'description' => data_get($addon, 'description'),
+ 'translations' => data_get($addon, 'translations', []),
+ 'price' => data_get($addon, 'price'),
+ 'sale_price' => data_get($addon, 'sale_price'),
+ 'is_on_sale' => data_get($addon, 'is_on_sale'),
+ ]);
+ }
+
+ return $this;
+ }
}
diff --git a/server/src/Models/Product.php b/server/src/Models/Product.php
index af13d31..6514465 100644
--- a/server/src/Models/Product.php
+++ b/server/src/Models/Product.php
@@ -304,18 +304,17 @@ public function setAddonCategories(array $addonCategories = []): Product
// get uuid if set
$id = data_get($addonCategory, 'uuid');
+ // Make sure product is set
+ data_set($addonCategory, 'product_uuid', $this->uuid);
+
// update product addon category
if (Str::isUuid($id)) {
- ProductAddonCategory::where('uuid', $id)->update([
- 'excluded_addons' => data_get($addonCategory, 'excluded_addons'),
- 'max_selectable' => data_get($addonCategory, 'max_selectable'),
- 'is_required' => data_get($addonCategory, 'is_required'),
- ]);
+ ProductAddonCategory::where('uuid', $id)->update(Arr::except($addonCategory, ['uuid', 'created_at', 'updated_at', 'name', 'category']));
continue;
}
// create new product addon category
- $productAddonCategory = ProductAddonCategory::create([
+ ProductAddonCategory::create([
'product_uuid' => $this->uuid,
'category_uuid' => data_get($addonCategory, 'category_uuid'),
'excluded_addons' => data_get($addonCategory, 'excluded_addons'),
@@ -369,7 +368,7 @@ public function setProductVariants(array $variants = []): Product
$option['additional_cost'] = Utils::numbersOnly($option['additional_cost']);
}
- $productVariantOptionInput = Arr::except($option, ['uuid']);
+ $productVariantOptionInput = Arr::except($option, ['uuid', 'created_at', 'updated_at']);
ProductVariantOption::where('uuid', $option['uuid'])->update($productVariantOptionInput);
continue;
}
diff --git a/server/src/Models/ProductAddon.php b/server/src/Models/ProductAddon.php
index 20a07a7..3d31578 100644
--- a/server/src/Models/ProductAddon.php
+++ b/server/src/Models/ProductAddon.php
@@ -3,6 +3,7 @@
namespace Fleetbase\Storefront\Models;
use Fleetbase\Casts\Json;
+use Fleetbase\Casts\Money;
use Fleetbase\FleetOps\Support\Utils;
use Fleetbase\Models\Category;
use Fleetbase\Models\User;
@@ -66,6 +67,8 @@ class ProductAddon extends StorefrontModel
protected $casts = [
'is_on_sale' => 'boolean',
'translations' => Json::class,
+ 'price' => Money::class,
+ 'sale_price' => Money::class,
];
/**
diff --git a/server/src/Models/ProductAddonCategory.php b/server/src/Models/ProductAddonCategory.php
index 11eb06d..58d3d35 100644
--- a/server/src/Models/ProductAddonCategory.php
+++ b/server/src/Models/ProductAddonCategory.php
@@ -84,8 +84,18 @@ public function getNameAttribute()
return static::attributeFromCache($this, 'category.name');
}
- public function getExcludedAddonsAttribute($excluded)
+ /**
+ * Decode excluded addons.
+ *
+ * @param string $excluded
+ */
+ public function getExcludedAddonsAttribute($excluded): array
{
- return Json::decode($excluded);
+ $excludedAddons = is_array($excluded) ? $excluded : Json::decode($excluded);
+ if (is_array($excludedAddons)) {
+ return $excludedAddons;
+ }
+
+ return [];
}
}
diff --git a/server/src/Providers/StorefrontServiceProvider.php b/server/src/Providers/StorefrontServiceProvider.php
index 05e67bd..8bc0fa0 100644
--- a/server/src/Providers/StorefrontServiceProvider.php
+++ b/server/src/Providers/StorefrontServiceProvider.php
@@ -87,7 +87,7 @@ public function boot()
{
$this->registerCommands();
$this->scheduleCommands(function ($schedule) {
- $schedule->command('storefront:notify-order-nearby')->everyMinute();
+ $schedule->command('storefront:notify-order-nearby')->everyMinute()->storeOutputInDb();
});
$this->registerObservers();
$this->registerMiddleware();
diff --git a/tests/integration/components/context-panel-test.js b/tests/integration/components/context-panel-test.js
new file mode 100644
index 0000000..cc58669
--- /dev/null
+++ b/tests/integration/components/context-panel-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | context-panel', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/customer-panel-test.js b/tests/integration/components/customer-panel-test.js
new file mode 100644
index 0000000..d9b55e7
--- /dev/null
+++ b/tests/integration/components/customer-panel-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | customer-panel', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/customer-panel/details-test.js b/tests/integration/components/customer-panel/details-test.js
new file mode 100644
index 0000000..f5dcf9e
--- /dev/null
+++ b/tests/integration/components/customer-panel/details-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | customer-panel/details', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/customer-panel/orders-test.js b/tests/integration/components/customer-panel/orders-test.js
new file mode 100644
index 0000000..5a965e5
--- /dev/null
+++ b/tests/integration/components/customer-panel/orders-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | customer-panel/orders', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/display-place-test.js b/tests/integration/components/display-place-test.js
new file mode 100644
index 0000000..31f0084
--- /dev/null
+++ b/tests/integration/components/display-place-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | display-place', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/order-panel-test.js b/tests/integration/components/order-panel-test.js
new file mode 100644
index 0000000..eff6352
--- /dev/null
+++ b/tests/integration/components/order-panel-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | order-panel', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/components/order-panel/details-test.js b/tests/integration/components/order-panel/details-test.js
new file mode 100644
index 0000000..e5c292c
--- /dev/null
+++ b/tests/integration/components/order-panel/details-test.js
@@ -0,0 +1,26 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | order-panel/details', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.set('myAction', function(val) { ... });
+
+ await render(hbs``);
+
+ assert.dom().hasText('');
+
+ // Template block usage:
+ await render(hbs`
+
+ template block text
+
+ `);
+
+ assert.dom().hasText('template block text');
+ });
+});
diff --git a/tests/integration/helpers/avatar-url-test.js b/tests/integration/helpers/avatar-url-test.js
new file mode 100644
index 0000000..6e79805
--- /dev/null
+++ b/tests/integration/helpers/avatar-url-test.js
@@ -0,0 +1,17 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'dummy/tests/helpers';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Helper | avatar-url', function (hooks) {
+ setupRenderingTest(hooks);
+
+ // TODO: Replace this with your real tests.
+ test('it renders', async function (assert) {
+ this.set('inputValue', '1234');
+
+ await render(hbs`{{avatar-url this.inputValue}}`);
+
+ assert.dom().hasText('1234');
+ });
+});
diff --git a/tests/unit/controllers/customers/index/view-test.js b/tests/unit/controllers/customers/index/view-test.js
new file mode 100644
index 0000000..3d9a2d0
--- /dev/null
+++ b/tests/unit/controllers/customers/index/view-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'dummy/tests/helpers';
+
+module('Unit | Controller | customers/index/view', function (hooks) {
+ setupTest(hooks);
+
+ // TODO: Replace this with your real tests.
+ test('it exists', function (assert) {
+ let controller = this.owner.lookup('controller:customers/index/view');
+ assert.ok(controller);
+ });
+});
diff --git a/tests/unit/controllers/orders/index/view-test.js b/tests/unit/controllers/orders/index/view-test.js
new file mode 100644
index 0000000..90bec71
--- /dev/null
+++ b/tests/unit/controllers/orders/index/view-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'dummy/tests/helpers';
+
+module('Unit | Controller | orders/index/view', function (hooks) {
+ setupTest(hooks);
+
+ // TODO: Replace this with your real tests.
+ test('it exists', function (assert) {
+ let controller = this.owner.lookup('controller:orders/index/view');
+ assert.ok(controller);
+ });
+});
diff --git a/tests/unit/routes/customers/index/view-test.js b/tests/unit/routes/customers/index/view-test.js
new file mode 100644
index 0000000..8ae4a70
--- /dev/null
+++ b/tests/unit/routes/customers/index/view-test.js
@@ -0,0 +1,11 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'dummy/tests/helpers';
+
+module('Unit | Route | customers/index/view', function (hooks) {
+ setupTest(hooks);
+
+ test('it exists', function (assert) {
+ let route = this.owner.lookup('route:customers/index/view');
+ assert.ok(route);
+ });
+});
diff --git a/tests/unit/serializers/product-variant-option-test.js b/tests/unit/serializers/product-variant-option-test.js
new file mode 100644
index 0000000..c8b82e5
--- /dev/null
+++ b/tests/unit/serializers/product-variant-option-test.js
@@ -0,0 +1,24 @@
+import { module, test } from 'qunit';
+
+import { setupTest } from 'dummy/tests/helpers';
+
+module('Unit | Serializer | product variant option', function (hooks) {
+ setupTest(hooks);
+
+ // Replace this with your real tests.
+ test('it exists', function (assert) {
+ let store = this.owner.lookup('service:store');
+ let serializer = store.serializerFor('product-variant-option');
+
+ assert.ok(serializer);
+ });
+
+ test('it serializes records', function (assert) {
+ let store = this.owner.lookup('service:store');
+ let record = store.createRecord('product-variant-option', {});
+
+ let serializedRecord = record.serialize();
+
+ assert.ok(serializedRecord);
+ });
+});
diff --git a/tests/unit/services/context-panel-test.js b/tests/unit/services/context-panel-test.js
new file mode 100644
index 0000000..2fe54f4
--- /dev/null
+++ b/tests/unit/services/context-panel-test.js
@@ -0,0 +1,12 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'dummy/tests/helpers';
+
+module('Unit | Service | context-panel', function (hooks) {
+ setupTest(hooks);
+
+ // TODO: Replace this with your real tests.
+ test('it exists', function (assert) {
+ let service = this.owner.lookup('service:context-panel');
+ assert.ok(service);
+ });
+});
diff --git a/translations/en-us.yaml b/translations/en-us.yaml
index 8f365bf..895ac09 100644
--- a/translations/en-us.yaml
+++ b/translations/en-us.yaml
@@ -21,6 +21,7 @@ storefront:
category: Category
delivery-tip: Delivery Tip
delivery: Delivery
+ details: Details
description: Description
driver: Driver
dropoff: Dropoff
@@ -28,11 +29,12 @@ storefront:
email: Email
export: Export
id: ID
+ internal-id: Internal ID
import: Import
invalid: Invalid
loading: Loading...
logo: logo
- name: Name
+ name: Name
neighborhood: Neighborhood
online: Online
orders: Orders
@@ -48,8 +50,9 @@ storefront:
storefront: Storefront
tag: Tags
tip: Tip
+ title: Title
total: Total
- type: Type
+ type: Type
upload-new: Upload new
uploading: Uploading...
view: View
@@ -66,7 +69,7 @@ storefront:
new: New
facebook: Facebook
instagram: Instagram
- twitter: Twitter
+ twitter: Twitter
sidebar:
storefront: Storefront
dashboard: Dashboard
@@ -77,10 +80,10 @@ storefront:
settings: Settings
launch-app: Launch App
component:
- storefront-order-summary:
+ storefront-order-summary:
order-summary-title: Storefront Order Summary
modals:
- add-store-hours:
+ add-store-hours:
start-time: Start time
operation-start: When availability/operation start
end-time: End time
@@ -190,12 +193,12 @@ storefront:
description: Addon Description
delete-this-addon-category-assosiated-will-lost: Are you sure you wish to delete this addon category? All addons assosciated will be lost!
untitled-addon-category: Untitled Addon Category
- order-ready-assign-driver:
+ order-ready-assign-driver:
driver-dispatch: You are about to set this order as ready and dispatch, use the dropdown below to select a driver to dispatch to.
Or optionally you can opt to dispatch order as adhoc which will ping the order to all nearby drivers to be accepted.
adhoc-dispatch-nearby-drivers: Adhoc dispatch to nearby drivers
select-driver: Select Driver
select-driver-to-assign: Select Driver to Assign
- share-network:
+ share-network:
invite-member: Invite members to your network
email-below: Grab a shareable invitiation link or send individual invites via email below.
invite-network: Enter the emails of people or organizations you want to send an invite to your network.
@@ -243,12 +246,12 @@ storefront:
mark-as-ready-modal-title: Are you want to mark order as ready?
mark-as-ready-modal-body: Marking the order as ready will dispatch the order to nearby drivers, only mark the order as ready when it can be picked up.
mark-as-ready-modal-accept-button-text: Dispatch!
- mark-as-completed-modal-title : Are you sure you want to mark order as completed?
+ mark-as-completed-modal-title: Are you sure you want to mark order as completed?
mark-as-completed-modal-body: Marking the order as completed is a confirmation that the customer has picked up the order and the order is completed.
mark-as-completed-accept-button-text: Order Completed!
assign-driver-modal-title: Assign Driver
assign-driver-modal-accept-button-text: Assign Driver
- storefront-metrics:
+ storefront-metrics:
last-day: Last 30 days
file-record:
delete-this-file: Are you sure you wish to delete this file?
@@ -265,7 +268,7 @@ storefront:
by-removing-these-operation: By removing these operation/availability hours, your store or product may become inactive or unavailable according to the updated schedule...
store-selector:
no-stores: No stores to select
- create-storefront: Create a new
+ create-storefront: Create a new
home:
title: Storefront Dashboard
customers:
@@ -277,7 +280,13 @@ storefront:
view-customer-details: View Customer Details
edit-customer: Edit Customer
success-message: Your new storefront network has been created!
- delete-customer: Delete Customer
+ delete-customer: Delete Customer
+ customer-panel:
+ details:
+ web-url: Website URL
+ edit-button: Edit customer
+ cancel-edit-button: Cancel edit customer
+ cancel-new-button: Cancel new customer
networks:
index:
network-option: Network Options
@@ -294,7 +303,7 @@ storefront:
orders: Orders
Network-changes-not-save: Network changes not saved!
going-back-will-rollback-all-unsaved-changes: Going back will rollback all unsaved changes, are you sure you wish to continue?
- index:
+ index:
change-network-saved: Changes to network saved.
create-new-payment-gateway: Create a new payment gateway
save-gateway: Save Gateway
@@ -404,7 +413,7 @@ storefront:
add-stores-to-network: Add stores to network
network-stores-update: Network stores updated.
remove-this-store: Remove this store ({storeName}) from this network ({networkName})?
- done: Done
+ done: Done
longer-findable-by-this-network: Are you sure you wish to remove this store from this network? It will no longer be findable by this network.
viewing-storefront: Viewing {storeName} storefront
editing-storefront: Editing {storeName} storefront
@@ -413,27 +422,80 @@ storefront:
invalid-emails-provided-error: Invalid emails provided!
orders:
index:
- internal-id: Internal ID
- customer: Customer
- select-order-customer: Select order customer
- select-order-pickup-location: Select order pickup location
- select-order-dropoff-location: Select order dropoff location
- scheduled-at: Scheduled At
- transaction-total: Transaction Total
- tracking-number: Tracking Number
- driver-assigned: Driver Assigned
- select-driver-for-order: Select driver for order
- created-at: Created At
- updated-at: Updated At
- created-by: Created By
- updated-by: Updated By
- select-user: Select user
- view-order: View Order
- cancel-order: Cancel Order
- delete-order: Delete Order
- products:
+ internal-id: Internal ID
+ customer: Customer
+ select-order-customer: Select order customer
+ select-order-pickup-location: Select order pickup location
+ select-order-dropoff-location: Select order dropoff location
+ scheduled-at: Scheduled At
+ transaction-total: Transaction Total
+ tracking-number: Tracking Number
+ driver-assigned: Driver Assigned
+ select-driver-for-order: Select driver for order
+ created-at: Created At
+ updated-at: Updated At
+ created-by: Created By
+ updated-by: Updated By
+ select-user: Select user
+ view-order: View Order
+ cancel-order: Cancel Order
+ delete-order: Delete Order
+ view:
+ route-panel-title: Route
+ comments-title: Comments
+ notes-title: Notes
+ dispatch: Dispatch
+ unassign-driver: Unassign Driver
+ assign-driver: Assign Driver
+ cancel-order: Cancel Order
+ delete-order: Delete Order
+ activity: Activity
+ unable-load-order-activity: Unable to load order activity
+ ad-hoc: Ad-Hoc
+ customer: Customer
+ facilitator: Facilitator
+ driver-assigned: Driver Assigned
+ change-driver: Change Driver
+ tracking-number: Tracking Number
+ date-scheduled: Date Scheduled
+ date-dispatched: Date Dispatched
+ date-started: Date Started
+ order-details-title: Order Details
+ route: Route
+ pickup: Pickup
+ dropoff: Dropoff
+ return: Return
+ order-summary: Order Summary
+ subtotal: Subtotal
+ delivery-fee: Delivery fee
+ tip: Tip
+ delivery-tip: Delivery Tip
+ total: Total
+ payload: Payload
+ items-drop: Items drop at
+ tracking: Tracking
+ view-activity: View Activity
+ order-metadata: Order Metadata
+ unassign-title: Are you sure you wish to unassing the driver ({driverName}) from this order?
+ unassign-body: Once the driver is unassigned, the driver will no longer have access to this orders details.
+ unassign-success: Driver has been unassigned from this order.
+ route-error: Route optimization failed, check route entry and try again.
+ invalid-warning: Invalid custom status entry.
+ change-order: Change order driver
+ assign-order: Assign driver to order
+ assign-success: '{orderId} assigned driver updated.'
+ order-title: Order Label
+ waypoint-title: Waypoint Label
+ proof-of-delivery: Proof of Delivery
+ notes-placeholder: Enter order notes here....
+ save-order-note: Save Order Note
+ order-notes-updated: Order notes updated.
+ products:
index:
manage-addons: Manage Addons
+ manage-addons-dialog:
+ manage-addons-title: Manage Product Addon Categories & Options
+ manage-addons-accept-button: Save Changes
done: Done
create-new-product-category: Create a new product category
product-category-created-success: New product category created.
@@ -443,7 +505,7 @@ storefront:
products-success-message: Successfully imported {resultsLength} products...
delete-product: Are you sure you wish to delete this product?
body-warning: Warning! Once this product is deleted it will no longer be accessible.
- aside-scroller:
+ aside-scroller:
title: Product Categories
custom-top-item-text: All Products
import-products-success-message: Successfully imported {resultsLength} products...
@@ -456,13 +518,13 @@ storefront:
warning-only-select-an-image-file-to-be-primary: You can only select an image file to be primary!
made-the-primary-success-image: >-
{fileName} was made the primary image.
- title: Product is not saved!
+ title: Product is not saved!
body: Going back will cancel this product creation, if you continue all input fields will be cleared!
select-addon-categories: Select addon categories
add-new-product-variant: Add new product variant
edit-product-variant: Edit product variant
untitled-field: Untitled Field
- category:
+ category:
category: category
title: Product is not saved!
body: Warning! Deleting this category will also remove all products listed under this category.
@@ -471,7 +533,7 @@ storefront:
category-changes-saved-success: Category changes saved.
delete-product: Are you sure you wish to delete this product?
body-warning: Warning! Once this product is deleted it will no longer be accessible.
- settings:
+ settings:
api:
api-settings: API Settings
access-key-for-storefront-api-integrations: Access key for Storefront API & Integrations.
@@ -539,7 +601,7 @@ storefront:
enable-tip: Enable tips
enable-integrated-vendors: Enable integrated vendors
save-changes: Save Changes
- locations:
+ locations:
new-store-location: New store location
add-new-location: Add new Location
edit-store-location: Edit store location
@@ -567,7 +629,7 @@ storefront:
notification-storefront: Configure notification channels for your storefront, each notification channel additionally can have it's own rules and options.
new-channel: New channel
service:
- storefront:
+ storefront:
new-incoming-order: You have a new incoming order!
accept-order: Accept Order
decline-order: Decline Order
@@ -575,5 +637,5 @@ storefront:
storefront-has-been-create-success: Your new storefront has been created!
create-new-storefront: Create a new Storefront
storefront-create-success: Your new storefront has been created!
- application:
+ application:
launch-app: Launch App