diff --git a/.ember-cli b/.ember-cli index 4ccb4bf..465c405 100644 --- a/.ember-cli +++ b/.ember-cli @@ -1,15 +1,7 @@ { /** - Ember CLI sends analytics information by default. The data is completely - anonymous, but there are times when you might want to disable this behavior. - - Setting `disableAnalytics` to true will prevent any data from being sent. - */ - "disableAnalytics": false, - - /** - Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript - rather than JavaScript by default, when a TypeScript version of a given blueprint is available. + Setting `isTypeScriptProject` to true will force the blueprint generators to generate TypeScript + rather than JavaScript by default, when a TypeScript version of a given blueprint is available. */ "isTypeScriptProject": false } diff --git a/.eslintignore b/.eslintignore index d474a40..1cbdb2b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,25 +1,17 @@ # unconventional js /blueprints/*/files/ -/vendor/ # compiled output /dist/ -/tmp/ - -# dependencies -/bower_components/ -/node_modules/ # misc /coverage/ !.* .*/ -.eslintcache # ember-try /.node_modules.ember-try/ -/bower.json.ember-try -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try + +# server +/server/ +/server_vendor/ diff --git a/.eslintrc.js b/.eslintrc.js index 4b91c6d..4277237 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,12 +2,13 @@ module.exports = { root: true, - parser: 'babel-eslint', + parser: '@babel/eslint-parser', parserOptions: { - ecmaVersion: 2018, + ecmaVersion: 'latest', sourceType: 'module', - ecmaFeatures: { - legacyDecorators: true, + requireConfigFile: false, + babelOptions: { + plugins: [['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }]], }, }, plugins: ['ember'], @@ -28,10 +29,10 @@ module.exports = { 'ember/classic-decorator-no-classic-methods': 'off', 'ember/no-shadow-route-definition': 'off', 'no-prototype-builtins': 'off', - 'node/no-unpublished-require': [ + 'n/no-unpublished-require': [ 'error', { - allowModules: ['resolve', 'broccoli-funnel'], + allowModules: ['resolve', 'broccoli-funnel', 'broccoli-merge-trees'], }, ], }, @@ -41,6 +42,7 @@ module.exports = { files: [ './.eslintrc.js', './.prettierrc.js', + './.stylelintrc.js', './.template-lintrc.js', './ember-cli-build.js', './index.js', @@ -56,13 +58,7 @@ module.exports = { browser: false, node: true, }, - plugins: ['node'], - extends: ['plugin:node/recommended'], - }, - { - // test files - files: ['tests/**/*-test.{js,ts}'], - extends: ['plugin:qunit/recommended'], + extends: ['plugin:n/recommended'], }, ], }; diff --git a/.github/workflows/ember.yml b/.github/workflows/ember.yml index 0d58da8..2f2c966 100644 --- a/.github/workflows/ember.yml +++ b/.github/workflows/ember.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - node-version: [16.x] # Build on Node.js 16 + node-version: [18.x] # Build on Node.js 18 steps: - uses: actions/checkout@v2 @@ -42,10 +42,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup Node.js 16.x + - name: Setup Node.js 18.x uses: actions/setup-node@v2 with: - node-version: 16.x + node-version: 18.x - name: Setup pnpm uses: pnpm/action-setup@v2.0.1 @@ -71,10 +71,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Setup Node.js 16.x + - name: Setup Node.js 18.x uses: actions/setup-node@v2 with: - node-version: 16.x + node-version: 18.x - name: Setup pnpm uses: pnpm/action-setup@v2.0.1 diff --git a/.gitignore b/.gitignore index 2fff49f..edf7568 100644 --- a/.gitignore +++ b/.gitignore @@ -1,28 +1,21 @@ -# See https://help.github.com/ignore-files/ for more about ignoring files. - # compiled output /dist/ -/tmp/ +/declarations/ # dependencies -/bower_components/ /node_modules/ # misc /.env* /.pnp* -/.sass-cache /.eslintcache -/connect.lock /coverage/ -/libpeerconnection.log /npm-debug.log* /testem.log /yarn-error.log # ember-try /.node_modules.ember-try/ -/bower.json.ember-try /npm-shrinkwrap.json.ember-try /package.json.ember-try /package-lock.json.ember-try diff --git a/.npmignore b/.npmignore index 3aac244..69beb28 100644 --- a/.npmignore +++ b/.npmignore @@ -2,11 +2,7 @@ /dist/ /tmp/ -# dependencies -/bower_components/ - # misc -/.bowerrc /.editorconfig /.ember-cli /.env* @@ -18,11 +14,11 @@ /.gitignore /.prettierignore /.prettierrc.js +/.stylelintignore +/.stylelintrc.js /.template-lintrc.js /.travis.yml /.watchmanconfig -/bower.json -/config/ember-try.js /CONTRIBUTING.md /ember-cli-build.js /testem.js @@ -33,7 +29,6 @@ # ember-try /.node_modules.ember-try/ -/bower.json.ember-try /npm-shrinkwrap.json.ember-try /package.json.ember-try /package-lock.json.ember-try diff --git a/.prettierignore b/.prettierignore index 4178fd5..9385391 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,25 +1,13 @@ # unconventional js /blueprints/*/files/ -/vendor/ # compiled output /dist/ -/tmp/ - -# dependencies -/bower_components/ -/node_modules/ # misc /coverage/ !.* -.eslintcache -.lint-todo/ +.*/ # ember-try /.node_modules.ember-try/ -/bower.json.ember-try -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try diff --git a/.prettierrc.js b/.prettierrc.js index cd88cc9..bf64a90 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -8,7 +8,7 @@ module.exports = { printWidth: 190, overrides: [ { - files: '*.hbs', + files: '*.{hbs,js,ts}', options: { singleQuote: false, }, diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..29348e2 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,12 @@ +# unconventional files +/blueprints/*/files/ + +# compiled output +/dist/ + +# addons +/.node_modules.ember-try/ + +# server +/server/ +/server_vendor/ diff --git a/.stylelintrc.js b/.stylelintrc.js new file mode 100644 index 0000000..62d4554 --- /dev/null +++ b/.stylelintrc.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'], +}; diff --git a/.template-lintrc.js b/.template-lintrc.js index c19bc29..d15584b 100644 --- a/.template-lintrc.js +++ b/.template-lintrc.js @@ -5,7 +5,7 @@ module.exports = { rules: { 'no-invalid-interactive': 'off', 'no-yield-only': 'off', - 'no-down-event-binding': 'off', + 'no-pointer-down-event-binding': 'off', 'table-groups': 'off', 'link-href-attributes': 'off', 'require-input-label': 'off', diff --git a/.watchmanconfig b/.watchmanconfig index e7834e3..f9c3d8f 100644 --- a/.watchmanconfig +++ b/.watchmanconfig @@ -1,3 +1,3 @@ { - "ignore_dirs": ["tmp", "dist"] + "ignore_dirs": ["dist"] } diff --git a/README.md b/README.md index cc91497..53b2ca9 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ This monorepo contains both the frontend and backend components of the Storefron ### Requirements -- PHP 7.3.0 or above -- Ember.js v3.24 or above -- Ember CLI v3.24 or above -- Node.js v14 or above +* PHP 7.3.0 or above +* Ember.js v4.8 or above +* Ember CLI v4.8 or above +* Node.js v18 or above ## Structure diff --git a/addon/components/modals/import-products.hbs b/addon/components/modals/import-products.hbs index 2ba4490..e5cac32 100644 --- a/addon/components/modals/import-products.hbs +++ b/addon/components/modals/import-products.hbs @@ -3,7 +3,7 @@ {{#if @options.isProcessing}}
- +
{{else}} diff --git a/addon/components/schedule-manager.hbs b/addon/components/schedule-manager.hbs index a51b4b0..8a41d10 100644 --- a/addon/components/schedule-manager.hbs +++ b/addon/components/schedule-manager.hbs @@ -2,9 +2,9 @@ {{#each-in this.schedule as |day hours|}}
-

{{day}}

+

{{day}}

-
diff --git a/addon/components/widget/customers.hbs b/addon/components/widget/customers.hbs index b47e7f2..b0e03fe 100644 --- a/addon/components/widget/customers.hbs +++ b/addon/components/widget/customers.hbs @@ -1,4 +1,4 @@ - + {{#if this.isLoading}}
diff --git a/addon/components/widget/customers.js b/addon/components/widget/customers.js index 3cb66a3..93df489 100644 --- a/addon/components/widget/customers.js +++ b/addon/components/widget/customers.js @@ -1,16 +1,19 @@ import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; -import { action, computed } from '@ember/object'; +import { action } from '@ember/object'; +import setComponentArg from '@fleetbase/ember-core/utils/set-component-arg'; export default class WidgetCustomersComponent extends Component { @service store; @service storefront; @tracked isLoading = true; @tracked customers = []; + @tracked title = 'Recent Customers'; - @computed('args.title') get title() { - return this.args.title || 'Recent Customers'; + constructor(owner, { title }) { + super(...arguments); + setComponentArg(this, 'title', title); } @action async getCustomers() { @@ -28,7 +31,7 @@ export default class WidgetCustomersComponent extends Component { this.isLoading = true; return new Promise((resolve) => { - const storefront = this.storefront?.activeStore?.public_id; + const storefront = this.storefront.getActiveStore('public_id'); if (!storefront) { this.isLoading = false; diff --git a/addon/components/widget/orders.js b/addon/components/widget/orders.js index 5e8befb..b2488a8 100644 --- a/addon/components/widget/orders.js +++ b/addon/components/widget/orders.js @@ -17,6 +17,10 @@ export default class WidgetOrdersComponent extends Component { return this.args.title ?? 'Recent Orders'; } + constructor() { + super(...arguments); + } + @action async setupWidget() { later( this, diff --git a/addon/controllers/base-controller.js b/addon/controllers/base-controller.js new file mode 100644 index 0000000..94dcc06 --- /dev/null +++ b/addon/controllers/base-controller.js @@ -0,0 +1,31 @@ +import Controller from '@ember/controller'; +import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; + +export default class BaseController extends Controller { + /** + * Inject the `universe` service + * + * @var {Service} + */ + @service universe; + + /** + * Transitions to a specified route within the '@fleetbase/storefront-engine' engine. + * + * This action is a wrapper around the `transitionToEngineRoute` method of the `universe` service (or object), + * specifically targeting the '@fleetbase/storefront-engine'. It allows for easy transitioning to routes + * within this engine, abstracting away the need to repeatedly specify the engine name. + * + * @param {string} route - The route within the '@fleetbase/storefront-engine' to transition to. + * @param {...any} args - Additional arguments to pass to the transitionToEngineRoute method. + * @returns {Promise} A Promise that resolves with the result of the transitionToEngineRoute method. + * + * @example + * // To transition to the 'management.fleets.index.new' route within the '@fleetbase/storefront-engine' + * this.transitionToRoute('management.fleets.index.new'); + */ + @action transitionToRoute(route, ...args) { + return this.universe.transitionToEngineRoute('@fleetbase/storefront-engine', route, ...args); + } +} diff --git a/addon/controllers/networks/index.js b/addon/controllers/networks/index.js index 7408014..1c20ac2 100644 --- a/addon/controllers/networks/index.js +++ b/addon/controllers/networks/index.js @@ -1,4 +1,5 @@ -import Controller, { inject as controller } from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; +import { inject as controller } from '@ember/controller'; import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; @@ -6,7 +7,7 @@ import { isBlank } from '@ember/utils'; import { timeout } from 'ember-concurrency'; import { task } from 'ember-concurrency-decorators'; -export default class NetworksIndexController extends Controller { +export default class NetworksIndexController extends BaseController { /** * Inject the `NetworksIndexNetworkStoresController` controller * diff --git a/addon/controllers/networks/index/network.js b/addon/controllers/networks/index/network.js index 1137487..c4dd5ce 100644 --- a/addon/controllers/networks/index/network.js +++ b/addon/controllers/networks/index/network.js @@ -1,8 +1,8 @@ -import Controller from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; -export default class NetworksIndexNetworkController extends Controller { +export default class NetworksIndexNetworkController extends BaseController { @service modalsManager; @action transitionBack({ closeOverlay }) { diff --git a/addon/controllers/products/index.js b/addon/controllers/products/index.js index ca8021e..8d9c85a 100644 --- a/addon/controllers/products/index.js +++ b/addon/controllers/products/index.js @@ -1,15 +1,14 @@ -import Controller from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import { alias } from '@ember/object/computed'; import { dasherize } from '@ember/string'; -export default class ProductsIndexController extends Controller { +export default class ProductsIndexController extends BaseController { @service store; @service modalsManager; @service currentUser; - @service modalsManager; @service notifications; @service fetch; @service hostRouter; diff --git a/addon/controllers/products/index/category.js b/addon/controllers/products/index/category.js index 9d9a4b3..6ebbba7 100644 --- a/addon/controllers/products/index/category.js +++ b/addon/controllers/products/index/category.js @@ -1,4 +1,4 @@ -import Controller from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; import { tracked } from '@glimmer/tracking'; import { inject as service } from '@ember/service'; import { action } from '@ember/object'; @@ -7,7 +7,7 @@ import { isBlank } from '@ember/utils'; import { timeout } from 'ember-concurrency'; import { task } from 'ember-concurrency-decorators'; -export default class ProductsIndexCategoryController extends Controller { +export default class ProductsIndexCategoryController extends BaseController { @service modalsManager; @service fetch; @service hostRouter; diff --git a/addon/controllers/products/index/category/new.js b/addon/controllers/products/index/category/new.js index 62acf68..e6cb6e5 100644 --- a/addon/controllers/products/index/category/new.js +++ b/addon/controllers/products/index/category/new.js @@ -1,4 +1,5 @@ -import Controller, { inject as controller } from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; +import { inject as controller } from '@ember/controller'; import { tracked } from '@glimmer/tracking'; import { isArray } from '@ember/array'; import { action } from '@ember/object'; @@ -6,7 +7,7 @@ import { alias } from '@ember/object/computed'; import { underscore } from '@ember/string'; import { inject as service } from '@ember/service'; -export default class ProductsIndexCategoryNewController extends Controller { +export default class ProductsIndexCategoryNewController extends BaseController { @controller('products.index.category') productsIndexCategoryController; @service notifications; @service modalsManager; @@ -89,6 +90,12 @@ export default class ProductsIndexCategoryNewController extends Controller { } @action queueFile(file) { + // since we have dropzone and upload button within dropzone validate the file state first + // as this method can be called twice from both functions + if (['queued', 'failed', 'timed_out', 'aborted'].indexOf(file.state) === -1) { + return; + } + this.uploadQueue.pushObject(file); this.fetch.uploadFile.perform( file, diff --git a/addon/controllers/products/index/index.js b/addon/controllers/products/index/index.js index 81753f4..f0ed1e3 100644 --- a/addon/controllers/products/index/index.js +++ b/addon/controllers/products/index/index.js @@ -1,4 +1,4 @@ -import Controller from '@ember/controller'; +import BaseController from '@fleetbase/storefront-engine/controllers/base-controller'; import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; @@ -6,7 +6,7 @@ import { isBlank } from '@ember/utils'; import { timeout } from 'ember-concurrency'; import { task } from 'ember-concurrency-decorators'; -export default class ProductsIndexIndexController extends Controller { +export default class ProductsIndexIndexController extends BaseController { /** * Inject the `filters` service * diff --git a/addon/models/network.js b/addon/models/network.js index 91590ea..83d4ecb 100644 --- a/addon/models/network.js +++ b/addon/models/network.js @@ -15,7 +15,6 @@ export default class NetworkModel extends Model { @hasMany('store') stores; @hasMany('notification-channel') notification_channels; @hasMany('gateway') gateways; - @hasMany('store') stores; @belongsTo('file') logo; @belongsTo('file') backdrop; diff --git a/addon/routes/customers/index.js b/addon/routes/customers/index.js index 157af7a..1a41a90 100644 --- a/addon/routes/customers/index.js +++ b/addon/routes/customers/index.js @@ -1,8 +1,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +import { action, set } from '@ember/object'; +import isNestedRouteTransition from '@fleetbase/ember-core/utils/is-nested-route-transition'; export default class CustomersIndexRoute extends Route { @service store; + @service storefront; queryParams = { page: { refreshModel: true }, @@ -19,7 +22,14 @@ export default class CustomersIndexRoute extends Route { updated_at: { refreshModel: true }, }; + @action willTransition(transition) { + if (isNestedRouteTransition(transition)) { + set(this.queryParams, 'page.refreshModel', false); + set(this.queryParams, 'sort.refreshModel', false); + } + } + model(params) { - return this.store.query('customer', params); + return this.store.query('customer', { ...params, storefront: this.storefront.getActiveStore('public_id') }); } } diff --git a/addon/routes/networks/index.js b/addon/routes/networks/index.js index 23a84a6..d4fd48e 100644 --- a/addon/routes/networks/index.js +++ b/addon/routes/networks/index.js @@ -1,5 +1,7 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +import { action, set } from '@ember/object'; +import isNestedRouteTransition from '@fleetbase/ember-core/utils/is-nested-route-transition'; export default class NetworksIndexRoute extends Route { @service store; @@ -13,6 +15,13 @@ export default class NetworksIndexRoute extends Route { updated_at: { refreshModel: true }, }; + @action willTransition(transition) { + if (isNestedRouteTransition(transition)) { + set(this.queryParams, 'page.refreshModel', false); + set(this.queryParams, 'sort.refreshModel', false); + } + } + model(params) { return this.store.query('network', params); } diff --git a/addon/routes/orders/index.js b/addon/routes/orders/index.js index 9cd2839..00a5de7 100644 --- a/addon/routes/orders/index.js +++ b/addon/routes/orders/index.js @@ -1,8 +1,11 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; +import { action, set } from '@ember/object'; +import isNestedRouteTransition from '@fleetbase/ember-core/utils/is-nested-route-transition'; export default class OrdersIndexRoute extends Route { @service store; + @service storefront; queryParams = { page: { refreshModel: true }, @@ -23,7 +26,14 @@ export default class OrdersIndexRoute extends Route { before: { refreshModel: true }, }; + @action willTransition(transition) { + if (isNestedRouteTransition(transition)) { + set(this.queryParams, 'page.refreshModel', false); + set(this.queryParams, 'sort.refreshModel', false); + } + } + model(params) { - return this.store.query('order', params); + return this.store.query('order', { ...params, storefront: this.storefront.getActiveStore('public_id') }); } } diff --git a/addon/routes/products/index.js b/addon/routes/products/index.js index d18bfbd..99754f1 100644 --- a/addon/routes/products/index.js +++ b/addon/routes/products/index.js @@ -1,13 +1,19 @@ import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; +import { action, set } from '@ember/object'; +import isNestedRouteTransition from '@fleetbase/ember-core/utils/is-nested-route-transition'; export default class ProductsIndexRoute extends Route { @service store; @service currentUser; - @action willTransition() { + @action willTransition(transition) { this.controller.category = null; + + if (isNestedRouteTransition(transition)) { + set(this.queryParams, 'page.refreshModel', false); + set(this.queryParams, 'sort.refreshModel', false); + } } model(params = {}) { diff --git a/addon/services/storefront.js b/addon/services/storefront.js index d04c6a8..a2df505 100644 --- a/addon/services/storefront.js +++ b/addon/services/storefront.js @@ -1,24 +1,86 @@ import Service from '@ember/service'; import Evented from '@ember/object/evented'; import { inject as service } from '@ember/service'; +import { get } from '@ember/object'; +/** + * Service to manage storefront operations. + */ export default class StorefrontService extends Service.extend(Evented) { + /** + * Ember service for data store. + * @type {Service} + */ @service store; + + /** + * Ember service for fetch operations. + * @type {Service} + */ @service fetch; + + /** + * Ember service for notifications. + * @type {Service} + */ @service notifications; + + /** + * Ember service for current user information. + * @type {Service} + */ @service currentUser; + + /** + * Ember service for managing modals. + * @type {Service} + */ @service modalsManager; + + /** + * Ember service for router operations. + * @type {Service} + */ @service hostRouter; + /** + * Gets the active store. + * @returns {Object} The active store object. + */ get activeStore() { return this.findActiveStore(); } + /** + * Sets the active storefront. + * @param {Object} store - The store to set as active. + */ setActiveStorefront(store) { this.currentUser.setOption('activeStorefront', store.id); this.trigger('storefront.changed', store); } + /** + * Gets the active store or a specific property of it. + * @param {string|null} property - The property to retrieve from the active store. + * @returns {Object|null} The active store or its specific property. + */ + getActiveStore(property = null) { + if (this.activeStore) { + if (typeof property === 'string') { + return get(this.activeStore, property); + } + + return this.activeStore; + } + + return null; + } + + /** + * Finds the active store based on the current user's settings. + * @returns {Object|null} The active store object or null if not found. + */ findActiveStore() { const activeStoreId = this.currentUser.getOption('activeStorefront'); @@ -43,6 +105,11 @@ export default class StorefrontService extends Service.extend(Evented) { return activeStore; } + /** + * Alerts about an incoming order. + * @param {string} orderId - The ID of the incoming order. + * @param {Object} store - The store associated with the order. + */ async alertIncomingOrder(orderId, store) { const order = await this.store.queryRecord('order', { public_id: orderId, @@ -80,6 +147,9 @@ export default class StorefrontService extends Service.extend(Evented) { }); } + /** + * Listens for incoming orders and handles them. + */ async listenForIncomingOrders() { const store = this.findActiveStore(); @@ -109,6 +179,10 @@ export default class StorefrontService extends Service.extend(Evented) { this.hostRouter.on('routeWillChange', channel.close); } + /** + * Creates the first store with given options. + * @param {Object} [options={}] - Options for creating the first store. + */ createFirstStore(options = {}) { const store = this.store.createRecord('store'); const currency = this.currentUser.getWhoisProperty('currency.code'); @@ -151,6 +225,10 @@ export default class StorefrontService extends Service.extend(Evented) { }); } + /** + * Creates a new storefront with given options. + * @param {Object} [options={}] - Options for creating the new storefront. + */ createNewStorefront(options = {}) { const store = this.store.createRecord('store'); const currency = this.currentUser.getWhoisProperty('currency.code'); @@ -191,6 +269,9 @@ export default class StorefrontService extends Service.extend(Evented) { }); } + /** + * Plays an alert sound. + */ playAlert() { // eslint-disable-next-line no-undef const alert = new Audio('/sounds/storefront_order_alert.mp3'); diff --git a/addon/templates/networks/index/network.hbs b/addon/templates/networks/index/network.hbs index d159223..7e7ad4b 100644 --- a/addon/templates/networks/index/network.hbs +++ b/addon/templates/networks/index/network.hbs @@ -1,4 +1,4 @@ - +
diff --git a/addon/templates/networks/index/network/stores.hbs b/addon/templates/networks/index/network/stores.hbs index 3321b6a..51de942 100644 --- a/addon/templates/networks/index/network/stores.hbs +++ b/addon/templates/networks/index/network/stores.hbs @@ -1,6 +1,6 @@ -