@fleetbase/storefront-engine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +32 -0
  3. package/addon/adapters/addon-category.js +1 -0
  4. package/addon/adapters/customer.js +1 -0
  5. package/addon/adapters/gateway.js +1 -0
  6. package/addon/adapters/network.js +1 -0
  7. package/addon/adapters/notification-channel.js +1 -0
  8. package/addon/adapters/product-addon-category.js +1 -0
  9. package/addon/adapters/product-addon.js +1 -0
  10. package/addon/adapters/product-hour.js +1 -0
  11. package/addon/adapters/product-store-location.js +1 -0
  12. package/addon/adapters/product-variant-option.js +1 -0
  13. package/addon/adapters/product-variant.js +1 -0
  14. package/addon/adapters/product.js +1 -0
  15. package/addon/adapters/store-hour.js +1 -0
  16. package/addon/adapters/store-location.js +1 -0
  17. package/addon/adapters/store.js +1 -0
  18. package/addon/adapters/storefront.js +5 -0
  19. package/addon/components/file-record.hbs +22 -0
  20. package/addon/components/file-record.js +43 -0
  21. package/addon/components/modals/add-store-hours.hbs +8 -0
  22. package/addon/components/modals/add-stores-to-network.hbs +5 -0
  23. package/addon/components/modals/assign-driver.hbs +25 -0
  24. package/addon/components/modals/create-first-store.hbs +21 -0
  25. package/addon/components/modals/create-gateway.hbs +35 -0
  26. package/addon/components/modals/create-network-category.hbs +50 -0
  27. package/addon/components/modals/create-network.hbs +20 -0
  28. package/addon/components/modals/create-new-variant.hbs +15 -0
  29. package/addon/components/modals/create-notification-channel.hbs +45 -0
  30. package/addon/components/modals/create-product-category.hbs +30 -0
  31. package/addon/components/modals/create-store.hbs +9 -0
  32. package/addon/components/modals/edit-network.hbs +1 -0
  33. package/addon/components/modals/import-products.hbs +97 -0
  34. package/addon/components/modals/incoming-order.hbs +242 -0
  35. package/addon/components/modals/manage-addons.hbs +50 -0
  36. package/addon/components/modals/manage-addons.js +86 -0
  37. package/addon/components/modals/order-ready-assign-driver.hbs +36 -0
  38. package/addon/components/modals/select-addon-category.hbs +5 -0
  39. package/addon/components/modals/share-network.hbs +35 -0
  40. package/addon/components/modals/store-location-form.hbs +30 -0
  41. package/addon/components/order-card.hbs +1 -0
  42. package/addon/components/order-card.js +3 -0
  43. package/addon/components/schedule-manager.hbs +22 -0
  44. package/addon/components/schedule-manager.js +73 -0
  45. package/addon/components/settings-container.hbs +7 -0
  46. package/addon/components/store-selector.hbs +21 -0
  47. package/addon/components/store-selector.js +20 -0
  48. package/addon/components/widget/customers.hbs +44 -0
  49. package/addon/components/widget/customers.js +53 -0
  50. package/addon/components/widget/orders.hbs +111 -0
  51. package/addon/components/widget/orders.js +248 -0
  52. package/addon/components/widget/storefront-metrics.hbs +54 -0
  53. package/addon/components/widget/storefront-metrics.js +61 -0
  54. package/addon/controllers/application.js +33 -0
  55. package/addon/controllers/customers/index.js +267 -0
  56. package/addon/controllers/home.js +3 -0
  57. package/addon/controllers/networks/index/network/customers.js +3 -0
  58. package/addon/controllers/networks/index/network/index.js +147 -0
  59. package/addon/controllers/networks/index/network/orders.js +3 -0
  60. package/addon/controllers/networks/index/network/stores.js +370 -0
  61. package/addon/controllers/networks/index/network.js +29 -0
  62. package/addon/controllers/networks/index.js +138 -0
  63. package/addon/controllers/orders/index.js +331 -0
  64. package/addon/controllers/products/index/category/edit.js +62 -0
  65. package/addon/controllers/products/index/category/new.js +287 -0
  66. package/addon/controllers/products/index/category.js +163 -0
  67. package/addon/controllers/products/index/index/edit.js +1 -0
  68. package/addon/controllers/products/index/index.js +136 -0
  69. package/addon/controllers/products/index.js +203 -0
  70. package/addon/controllers/settings/api.js +3 -0
  71. package/addon/controllers/settings/gateways.js +110 -0
  72. package/addon/controllers/settings/index.js +102 -0
  73. package/addon/controllers/settings/locations.js +186 -0
  74. package/addon/controllers/settings/notifications.js +102 -0
  75. package/addon/engine.js +19 -0
  76. package/addon/helpers/get-tip-amount.js +5 -0
  77. package/addon/models/addon-category.js +6 -0
  78. package/addon/models/gateway.js +46 -0
  79. package/addon/models/network.js +166 -0
  80. package/addon/models/notification-channel.js +47 -0
  81. package/addon/models/product-addon-category.js +41 -0
  82. package/addon/models/product-addon.js +41 -0
  83. package/addon/models/product-hour.js +72 -0
  84. package/addon/models/product-store-location.js +41 -0
  85. package/addon/models/product-variant-option.js +39 -0
  86. package/addon/models/product-variant.js +44 -0
  87. package/addon/models/product.js +208 -0
  88. package/addon/models/store-hour.js +72 -0
  89. package/addon/models/store-location.js +93 -0
  90. package/addon/models/store.js +100 -0
  91. package/addon/routes/application.js +47 -0
  92. package/addon/routes/customers/index/edit.js +3 -0
  93. package/addon/routes/customers/index.js +25 -0
  94. package/addon/routes/home.js +3 -0
  95. package/addon/routes/networks/index/network/customers.js +3 -0
  96. package/addon/routes/networks/index/network/index.js +15 -0
  97. package/addon/routes/networks/index/network/orders.js +3 -0
  98. package/addon/routes/networks/index/network/stores.js +28 -0
  99. package/addon/routes/networks/index/network.js +10 -0
  100. package/addon/routes/networks/index.js +19 -0
  101. package/addon/routes/orders/index/edit.js +3 -0
  102. package/addon/routes/orders/index/new.js +3 -0
  103. package/addon/routes/orders/index/view.js +3 -0
  104. package/addon/routes/orders/index.js +29 -0
  105. package/addon/routes/products/index/category/edit.js +15 -0
  106. package/addon/routes/products/index/category/new.js +7 -0
  107. package/addon/routes/products/index/category.js +54 -0
  108. package/addon/routes/products/index/index/edit.js +1 -0
  109. package/addon/routes/products/index/index.js +22 -0
  110. package/addon/routes/products/index.js +21 -0
  111. package/addon/routes/settings/api.js +10 -0
  112. package/addon/routes/settings/gateways.js +11 -0
  113. package/addon/routes/settings/index.js +16 -0
  114. package/addon/routes/settings/locations.js +14 -0
  115. package/addon/routes/settings/notifications.js +11 -0
  116. package/addon/routes.js +48 -0
  117. package/addon/serializers/addon-category.js +15 -0
  118. package/addon/serializers/network.js +19 -0
  119. package/addon/serializers/notification-channel.js +15 -0
  120. package/addon/serializers/product-addon-category.js +15 -0
  121. package/addon/serializers/product-variant.js +15 -0
  122. package/addon/serializers/product.js +20 -0
  123. package/addon/serializers/store-location.js +17 -0
  124. package/addon/serializers/store.js +19 -0
  125. package/addon/services/storefront.js +208 -0
  126. package/addon/templates/application.hbs +16 -0
  127. package/addon/templates/customers/index/edit.hbs +2 -0
  128. package/addon/templates/customers/index.hbs +22 -0
  129. package/addon/templates/home.hbs +7 -0
  130. package/addon/templates/networks/index/network/customers.hbs +2 -0
  131. package/addon/templates/networks/index/network/index.hbs +254 -0
  132. package/addon/templates/networks/index/network/orders.hbs +2 -0
  133. package/addon/templates/networks/index/network/stores.hbs +164 -0
  134. package/addon/templates/networks/index/network.hbs +38 -0
  135. package/addon/templates/networks/index.hbs +60 -0
  136. package/addon/templates/orders/index/edit.hbs +2 -0
  137. package/addon/templates/orders/index/new.hbs +2 -0
  138. package/addon/templates/orders/index/view.hbs +2 -0
  139. package/addon/templates/orders/index.hbs +22 -0
  140. package/addon/templates/products/index/category/edit.hbs +1 -0
  141. package/addon/templates/products/index/category/new.hbs +248 -0
  142. package/addon/templates/products/index/category.hbs +41 -0
  143. package/addon/templates/products/index/index/edit.hbs +1 -0
  144. package/addon/templates/products/index/index.hbs +40 -0
  145. package/addon/templates/products/index.hbs +22 -0
  146. package/addon/templates/settings/api.hbs +18 -0
  147. package/addon/templates/settings/gateways.hbs +48 -0
  148. package/addon/templates/settings/index.hbs +229 -0
  149. package/addon/templates/settings/locations.hbs +39 -0
  150. package/addon/templates/settings/notifications.hbs +35 -0
  151. package/addon/templates/settings.hbs +30 -0
  152. package/addon/utils/get-gateway-schemas.js +34 -0
  153. package/addon/utils/get-notification-schemas.js +18 -0
  154. package/app/adapters/addon-category.js +1 -0
  155. package/app/adapters/gateway.js +1 -0
  156. package/app/adapters/network.js +1 -0
  157. package/app/adapters/notification-channel.js +1 -0
  158. package/app/adapters/product-addon-category.js +1 -0
  159. package/app/adapters/product-addon.js +1 -0
  160. package/app/adapters/product-hour.js +1 -0
  161. package/app/adapters/product-store-location.js +1 -0
  162. package/app/adapters/product-variant-option.js +1 -0
  163. package/app/adapters/product-variant.js +1 -0
  164. package/app/adapters/product.js +1 -0
  165. package/app/adapters/store-hour.js +1 -0
  166. package/app/adapters/store-location.js +1 -0
  167. package/app/adapters/store.js +1 -0
  168. package/app/adapters/storefront.js +1 -0
  169. package/app/components/file-record.js +1 -0
  170. package/app/components/modals/add-store-hours.js +1 -0
  171. package/app/components/modals/add-stores-to-network.js +1 -0
  172. package/app/components/modals/assign-driver.js +1 -0
  173. package/app/components/modals/create-first-store.js +1 -0
  174. package/app/components/modals/create-gateway.js +1 -0
  175. package/app/components/modals/create-network-category.js +1 -0
  176. package/app/components/modals/create-network.js +1 -0
  177. package/app/components/modals/create-new-variant.js +1 -0
  178. package/app/components/modals/create-notification-channel.js +1 -0
  179. package/app/components/modals/create-product-category.js +1 -0
  180. package/app/components/modals/create-store.js +1 -0
  181. package/app/components/modals/edit-network.js +1 -0
  182. package/app/components/modals/import-products.js +1 -0
  183. package/app/components/modals/incoming-order.js +1 -0
  184. package/app/components/modals/manage-addons.js +1 -0
  185. package/app/components/modals/order-ready-assign-driver.js +1 -0
  186. package/app/components/modals/select-addon-category.js +1 -0
  187. package/app/components/modals/share-network.js +1 -0
  188. package/app/components/modals/store-location-form.js +1 -0
  189. package/app/components/order-card.js +1 -0
  190. package/app/components/schedule-manager.js +1 -0
  191. package/app/components/settings-container.js +1 -0
  192. package/app/components/store-selector.js +1 -0
  193. package/app/components/widget/customers.js +1 -0
  194. package/app/components/widget/orders.js +1 -0
  195. package/app/components/widget/storefront-metrics.js +1 -0
  196. package/app/controllers/application.js +1 -0
  197. package/app/controllers/customers/index.js +1 -0
  198. package/app/controllers/home.js +1 -0
  199. package/app/controllers/networks/index/network/customers.js +1 -0
  200. package/app/controllers/networks/index/network/index.js +1 -0
  201. package/app/controllers/networks/index/network/orders.js +1 -0
  202. package/app/controllers/networks/index/network/stores.js +1 -0
  203. package/app/controllers/networks/index/network.js +1 -0
  204. package/app/controllers/networks/index.js +1 -0
  205. package/app/controllers/orders/index.js +1 -0
  206. package/app/controllers/products/index/category/edit.js +1 -0
  207. package/app/controllers/products/index/category/new.js +1 -0
  208. package/app/controllers/products/index/category.js +1 -0
  209. package/app/controllers/products/index/index/edit.js +1 -0
  210. package/app/controllers/products/index/index.js +1 -0
  211. package/app/controllers/products/index.js +1 -0
  212. package/app/controllers/settings/api.js +1 -0
  213. package/app/controllers/settings/gateways.js +1 -0
  214. package/app/controllers/settings/index.js +1 -0
  215. package/app/controllers/settings/locations.js +1 -0
  216. package/app/controllers/settings/notifications.js +1 -0
  217. package/app/helpers/get-tip-amount.js +1 -0
  218. package/app/models/addon-category.js +1 -0
  219. package/app/models/gateway.js +1 -0
  220. package/app/models/network.js +1 -0
  221. package/app/models/notification-channel.js +1 -0
  222. package/app/models/product-addon-category.js +1 -0
  223. package/app/models/product-addon.js +1 -0
  224. package/app/models/product-hour.js +1 -0
  225. package/app/models/product-store-location.js +1 -0
  226. package/app/models/product-variant-option.js +1 -0
  227. package/app/models/product-variant.js +1 -0
  228. package/app/models/product.js +1 -0
  229. package/app/models/store-hour.js +1 -0
  230. package/app/models/store-location.js +1 -0
  231. package/app/models/store.js +1 -0
  232. package/app/routes/application.js +1 -0
  233. package/app/routes/customers/index/edit.js +1 -0
  234. package/app/routes/customers/index.js +1 -0
  235. package/app/routes/home.js +1 -0
  236. package/app/routes/networks/index/network/customers.js +1 -0
  237. package/app/routes/networks/index/network/index.js +1 -0
  238. package/app/routes/networks/index/network/orders.js +1 -0
  239. package/app/routes/networks/index/network/stores.js +1 -0
  240. package/app/routes/networks/index/network.js +1 -0
  241. package/app/routes/networks/index.js +1 -0
  242. package/app/routes/orders/index/edit.js +1 -0
  243. package/app/routes/orders/index/new.js +1 -0
  244. package/app/routes/orders/index/view.js +1 -0
  245. package/app/routes/orders/index.js +1 -0
  246. package/app/routes/products/index/category/edit.js +1 -0
  247. package/app/routes/products/index/category/new.js +1 -0
  248. package/app/routes/products/index/category.js +1 -0
  249. package/app/routes/products/index/index/edit.js +1 -0
  250. package/app/routes/products/index/index.js +1 -0
  251. package/app/routes/products/index.js +1 -0
  252. package/app/routes/settings/api.js +1 -0
  253. package/app/routes/settings/gateways.js +1 -0
  254. package/app/routes/settings/index.js +1 -0
  255. package/app/routes/settings/locations.js +1 -0
  256. package/app/routes/settings/notifications.js +1 -0
  257. package/app/serializers/addon-category.js +1 -0
  258. package/app/serializers/network.js +1 -0
  259. package/app/serializers/notification-channel.js +1 -0
  260. package/app/serializers/product-addon-category.js +1 -0
  261. package/app/serializers/product-variant.js +1 -0
  262. package/app/serializers/product.js +1 -0
  263. package/app/serializers/store-location.js +1 -0
  264. package/app/serializers/store.js +1 -0
  265. package/app/services/storefront.js +1 -0
  266. package/app/templates/customers/index/edit.js +1 -0
  267. package/app/templates/customers/index.js +1 -0
  268. package/app/templates/home.js +1 -0
  269. package/app/templates/networks/index/network/customers.js +1 -0
  270. package/app/templates/networks/index/network/index.js +1 -0
  271. package/app/templates/networks/index/network/orders.js +1 -0
  272. package/app/templates/networks/index/network/stores.js +1 -0
  273. package/app/templates/networks/index/network.js +1 -0
  274. package/app/templates/networks/index.js +1 -0
  275. package/app/templates/orders/index/edit.js +1 -0
  276. package/app/templates/orders/index/new.js +1 -0
  277. package/app/templates/orders/index/view.js +1 -0
  278. package/app/templates/orders/index.js +1 -0
  279. package/app/templates/products/index/category/edit.js +1 -0
  280. package/app/templates/products/index/category/new.js +1 -0
  281. package/app/templates/products/index/category.js +1 -0
  282. package/app/templates/products/index/index/edit.js +1 -0
  283. package/app/templates/products/index/index.js +1 -0
  284. package/app/templates/products/index.js +1 -0
  285. package/app/templates/settings/api.js +1 -0
  286. package/app/templates/settings/gateways.js +1 -0
  287. package/app/templates/settings/index.js +1 -0
  288. package/app/templates/settings/locations.js +1 -0
  289. package/app/templates/settings/notifications.js +1 -0
  290. package/app/templates/settings.js +1 -0
  291. package/app/utils/get-gateway-schemas.js +1 -0
  292. package/app/utils/get-notification-schemas.js +1 -0
  293. package/config/environment.js +21 -0
  294. package/index.js +22 -0
  295. package/package.json +123 -0
  296. package/pnpm-lock.yaml +12509 -0
@@ -0,0 +1,370 @@
1
+ import Controller from '@ember/controller';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action, set } from '@ember/object';
5
+ import consoleUrl from '@fleetbase/console/utils/console-url';
6
+ import isEmail from '@fleetbase/console/utils/is-email';
7
+
8
+ export default class NetworksIndexNetworkStoresController extends Controller {
9
+ @service notifications;
10
+ @service modalsManager;
11
+ @service fetch;
12
+ @service store;
13
+ @tracked network;
14
+ @tracked category;
15
+ @tracked isLoading = false;
16
+ @tracked categories = [];
17
+ @tracked subCategories = [];
18
+ @tracked stores = [];
19
+
20
+ dragulaConfig = {
21
+ isContainer: (el) => el.classList.contains('dragula-container'),
22
+ moves: (el) => el.classList.contains('network-store'),
23
+ accepts: (el) => el.classList.contains('network-store'),
24
+ revertOnSpill: true,
25
+ };
26
+
27
+ @action dropdownAction(dd, action, ...params) {
28
+ if (dd.actions && typeof dd.actions.close === 'function') {
29
+ dd.actions.close();
30
+ }
31
+
32
+ if (typeof this[action] === 'function') {
33
+ this[action](...params);
34
+ }
35
+ }
36
+
37
+ @action enterCategory(category) {
38
+ this.category = category;
39
+ this.fetchStores(category);
40
+ this.fetchSubcategories(category);
41
+ }
42
+
43
+ @action leaveCategory(parentCategory) {
44
+ if (parentCategory) {
45
+ return this.enterCategory(parentCategory);
46
+ }
47
+
48
+ this.category = null;
49
+ this.fetchStores();
50
+ }
51
+
52
+ @action deleteCategory(category) {
53
+ this.modalsManager.confirm({
54
+ title: 'Delete network category?',
55
+ body: 'Deleting this category will move all stores inside to the top level, are you sure you want to delete this category?',
56
+ confirm: (modal) => {
57
+ modal.startLoading();
58
+
59
+ this.fetch.delete(`networks/${this.network.id}/remove-category`, { category: category.id }, { namespace: 'storefront/int/v1' }).then(() => {
60
+ this.categories.removeObject(category);
61
+ this.leaveCategory();
62
+ modal.done();
63
+ });
64
+ },
65
+ });
66
+ }
67
+
68
+ @action fetchSubcategories(parentCategory) {
69
+ this.store
70
+ .query('category', { parent_uuid: parentCategory.id })
71
+ .then((subCategories) => {
72
+ this.subCategories = subCategories.toArray().map((category) => {
73
+ category.parent_category = parentCategory;
74
+
75
+ return category;
76
+ });
77
+ this.isLoading = false;
78
+ })
79
+ .finally(() => {
80
+ this.isLoading = false;
81
+ });
82
+ }
83
+
84
+ @action fetchStores(category) {
85
+ const params = {
86
+ network: this.network.id,
87
+ };
88
+
89
+ if (category) {
90
+ params.category = category.id;
91
+ } else {
92
+ params.without_category = true;
93
+ }
94
+
95
+ this.isLoading = true;
96
+
97
+ this.store
98
+ .query('store', params)
99
+ .then((stores) => {
100
+ this.stores = stores.toArray();
101
+ this.isLoading = false;
102
+ })
103
+ .finally(() => {
104
+ this.isLoading = false;
105
+ });
106
+ }
107
+
108
+ @action setDragulaInstance(dragula) {
109
+ dragula
110
+ .on('over', (el, container) => {
111
+ // console.log('over()', el, container);
112
+ if (container.classList.contains('network-folder')) {
113
+ container.classList.add('hovering');
114
+ }
115
+ })
116
+ .on('drop', (el, target) => {
117
+ // console.log('drop()', el, target);
118
+ const storeId = el?.dataset?.store;
119
+ const categoryId = target?.dataset?.category;
120
+
121
+ Array.from(dragula.containers).forEach((container) => {
122
+ container.classList.remove('hovering');
123
+ });
124
+
125
+ if (categoryId) {
126
+ const store = this.store.peekRecord('store', storeId);
127
+ const category = this.store.peekRecord('category', categoryId);
128
+
129
+ this.addStoreToCategory(store, category);
130
+ }
131
+ });
132
+ }
133
+
134
+ @action addStoreToCategory(store, category) {
135
+ this.fetch.post(
136
+ `networks/${this.network.id}/set-store-category`,
137
+ {
138
+ category: category.id,
139
+ store: store.id,
140
+ },
141
+ { namespace: 'storefront/int/v1' }
142
+ );
143
+ }
144
+
145
+ @action createNewCategory(network) {
146
+ const category = this.store.createRecord('category', {
147
+ owner_uuid: network.id,
148
+ owner_type: 'network:storefront',
149
+ for: 'storefront_network',
150
+ });
151
+
152
+ return this.editCategory(category, {
153
+ title: 'Add new network category',
154
+ acceptButtonIcon: 'check',
155
+ category,
156
+ confirm: (modal) => {
157
+ modal.startLoading();
158
+
159
+ return category.save().then((category) => {
160
+ this.notifications.success('New network category created.');
161
+ this.categories.pushObject(category);
162
+ });
163
+ },
164
+ });
165
+ }
166
+
167
+ @action createNewSubCategory(parentCategory) {
168
+ const category = this.store.createRecord('category', {
169
+ parent_uuid: parentCategory.id,
170
+ owner_uuid: parentCategory.owner_uuid,
171
+ owner_type: 'network:storefront',
172
+ for: 'storefront_network',
173
+ });
174
+
175
+ return this.editCategory(category, {
176
+ title: 'Add new network category',
177
+ acceptButtonIcon: 'check',
178
+ category,
179
+ confirm: (modal) => {
180
+ modal.startLoading();
181
+
182
+ return category.save().then((category) => {
183
+ this.notifications.success('New network category created.');
184
+ this.subCategories.pushObject(category);
185
+ });
186
+ },
187
+ });
188
+ }
189
+
190
+ @action editCategory(category, options = {}) {
191
+ this.modalsManager.show('modals/create-network-category', {
192
+ title: `Edit category (${category.name})`,
193
+ acceptButtonText: 'Save Changes',
194
+ acceptButtonIcon: 'save',
195
+ iconType: category.icon_file_uuid ? 'image' : 'svg',
196
+ category,
197
+ clearImage: () => {
198
+ category.setProperties({
199
+ icon_file_uuid: null,
200
+ icon_url: null,
201
+ icon_file: null,
202
+ });
203
+ },
204
+ uploadIcon: (file) => {
205
+ this.fetch.uploadFile.perform(
206
+ file,
207
+ {
208
+ path: `uploads/${category.company_uuid}/icons/${category.slug}`,
209
+ key_uuid: category.id,
210
+ key_type: `category`,
211
+ type: `category_icon`,
212
+ },
213
+ (uploadedFile) => {
214
+ category.setProperties({
215
+ icon_file_uuid: uploadedFile.id,
216
+ icon_url: uploadedFile.s3url,
217
+ icon_file: uploadedFile,
218
+ });
219
+ }
220
+ );
221
+ },
222
+ confirm: (modal) => {
223
+ modal.startLoading();
224
+
225
+ return category.save().then(() => {
226
+ this.notifications.success('Network category changes saved.');
227
+ });
228
+ },
229
+ ...options,
230
+ });
231
+ }
232
+
233
+ @action async addStores(network) {
234
+ this.modalsManager.displayLoader();
235
+
236
+ const stores = await this.store.findAll('store');
237
+ const members = await network.loadStores();
238
+
239
+ return this.modalsManager.done().then(() => {
240
+ this.modalsManager.show('modals/add-stores-to-network', {
241
+ title: 'Add stores to network',
242
+ acceptButtonIcon: 'check',
243
+ stores,
244
+ members,
245
+ selected: members.toArray(),
246
+ network,
247
+ updateSelected: (selected) => {
248
+ this.modalsManager.setOption('selected', selected);
249
+ },
250
+ confirm: (modal) => {
251
+ modal.startLoading();
252
+
253
+ const stores = modal.getOption('selected');
254
+ const allStores = modal.getOption('stores');
255
+ const remove = allStores.filter((store) => !stores.includes(store)); // stores to be removed
256
+
257
+ return network.addStores(stores, remove).then(() => {
258
+ this.updateNetworkStores(stores, remove);
259
+ });
260
+ },
261
+ });
262
+ });
263
+ }
264
+
265
+ @action async removeStore(store, network) {
266
+ this.modalsManager.confirm({
267
+ title: `Remove this store (${store.name}) from this network (${network.name})?`,
268
+ body: 'Are you sure you wish to remove this store from this network? It will no longer be findable by this network.',
269
+ acceptButtonIcon: 'check',
270
+ acceptButtonIconPrefix: 'fas',
271
+ declineButtonIcon: 'times',
272
+ declineButtonIconPrefix: 'fas',
273
+ confirm: (modal) => {
274
+ modal.startLoading();
275
+
276
+ this.fetch
277
+ .post(`networks/${this.network.id}/remove-stores`, { stores: [store.id] }, { namespace: 'storefront/int/v1' })
278
+ .then(() => {
279
+ this.stores.removeObject(store);
280
+ modal.done();
281
+ })
282
+ .catch((error) => {
283
+ modal.stopLoading();
284
+ this.notifications.serverError(error);
285
+ });
286
+ },
287
+ });
288
+ }
289
+
290
+ @action updateNetworkStores(added = [], removed = []) {
291
+ const updatedStores = [];
292
+
293
+ for (let index = 0; index < this.stores.length; index++) {
294
+ const store = this.stores.objectAt(index);
295
+
296
+ if (removed.includes(store)) {
297
+ continue;
298
+ }
299
+
300
+ updatedStores.push(store);
301
+ }
302
+
303
+ for (let index = 0; index < added.length; index++) {
304
+ const addedStore = added.objectAt(index);
305
+
306
+ if (updatedStores.includes(addedStore)) {
307
+ continue;
308
+ }
309
+
310
+ updatedStores.push(addedStore);
311
+ }
312
+
313
+ this.stores = updatedStores.filter(Boolean).uniq();
314
+ }
315
+
316
+ @action invite(network) {
317
+ const shareableLink = consoleUrl(`join/network/${network.public_id}`);
318
+
319
+ this.modalsManager.show('modals/share-network', {
320
+ title: 'Add stores to network',
321
+ acceptButtonText: 'Send Invitations',
322
+ acceptButtonIcon: 'paper-plane',
323
+ acceptButtonDisabled: true,
324
+ shareableLink,
325
+ recipients: [],
326
+ network,
327
+ addRecipient: (email) => {
328
+ const recipients = this.modalsManager.getOption('recipients');
329
+ recipients.pushObject(email);
330
+
331
+ if (recipients.length === 0) {
332
+ this.modalsManager.setOption('acceptButtonDisabled', true);
333
+ } else {
334
+ this.modalsManager.setOption('acceptButtonDisabled', false);
335
+ }
336
+ },
337
+ removeRecipient: (index) => {
338
+ const recipients = this.modalsManager.getOption('recipients');
339
+ recipients.removeAt(index);
340
+
341
+ if (recipients.length === 0) {
342
+ this.modalsManager.setOption('acceptButtonDisabled', true);
343
+ } else {
344
+ this.modalsManager.setOption('acceptButtonDisabled', false);
345
+ }
346
+ },
347
+ toggleShareableLink: (enabled) => {
348
+ set(network, 'options.shareable_link_enabled', enabled);
349
+ network.save();
350
+ },
351
+ confirm: (modal) => {
352
+ modal.startLoading();
353
+
354
+ const recipients = modal.getOption('recipients');
355
+ const isValid = recipients.every((email) => isEmail(email));
356
+
357
+ if (!isValid) {
358
+ modal.stopLoading();
359
+
360
+ return this.notifications.error('Invalid emails provided!');
361
+ }
362
+
363
+ return network.sendInvites(recipients).then(() => {
364
+ modal.stopLoading();
365
+ this.notifications.success('Invitations sent to recipients!');
366
+ });
367
+ },
368
+ });
369
+ }
370
+ }
@@ -0,0 +1,29 @@
1
+ import Controller from '@ember/controller';
2
+ import { inject as service } from '@ember/service';
3
+ import { action } from '@ember/object';
4
+
5
+ export default class NetworksIndexNetworkController extends Controller {
6
+ @service modalsManager;
7
+
8
+ @action transitionBack({ closeOverlay }) {
9
+ if (this.model.hasDirtyAttributes) {
10
+ // warn user about unsaved changes
11
+ return this.modalsManager.confirm({
12
+ title: 'Network changes not saved!',
13
+ body: 'Going back will rollback all unsaved changes, are you sure you wish to continue?',
14
+ confirm: (modal) => {
15
+ modal.done();
16
+ return this.exit(closeOverlay);
17
+ },
18
+ });
19
+ }
20
+
21
+ return this.exit(closeOverlay);
22
+ }
23
+
24
+ @action exit(closeOverlay) {
25
+ return closeOverlay(() => {
26
+ return this.transitionToRoute('networks.index');
27
+ });
28
+ }
29
+ }
@@ -0,0 +1,138 @@
1
+ import Controller, { inject as controller } from '@ember/controller';
2
+ import { inject as service } from '@ember/service';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { action } from '@ember/object';
5
+ import { isBlank } from '@ember/utils';
6
+ import { timeout } from 'ember-concurrency';
7
+ import { task } from 'ember-concurrency-decorators';
8
+
9
+ export default class NetworksIndexController extends Controller {
10
+ /**
11
+ * Inject the `NetworksIndexNetworkStoresController` controller
12
+ *
13
+ * @memberof NetworksIndexController
14
+ */
15
+ @controller('networks.index.network.stores') networkStoresController;
16
+
17
+ /**
18
+ * Inject the `notifications` service
19
+ *
20
+ * @var {Service}
21
+ */
22
+ @service notifications;
23
+
24
+ /**
25
+ * Inject the `modals-manager` service
26
+ *
27
+ * @var {Service}
28
+ */
29
+ @service modalsManager;
30
+
31
+ /**
32
+ * Inject the `crud` service
33
+ *
34
+ * @var {Service}
35
+ */
36
+ @service crud;
37
+
38
+ /**
39
+ * Inject the `currentUser` service
40
+ *
41
+ * @var {Service}
42
+ */
43
+ @service currentUser;
44
+
45
+ /**
46
+ * Inject the `store` service
47
+ *
48
+ * @var {Service}
49
+ */
50
+ @service store;
51
+
52
+ /**
53
+ * Inject the `fetch` service
54
+ *
55
+ * @var {Service}
56
+ */
57
+ @service fetch;
58
+
59
+ /**
60
+ * Inject the `filters` service
61
+ *
62
+ * @var {Service}
63
+ */
64
+ @service filters;
65
+
66
+ /**
67
+ * Queryable parameters for this controller's model
68
+ *
69
+ * @var {Array}
70
+ */
71
+ queryParams = ['page', 'limit', 'sort', 'query'];
72
+
73
+ @tracked page = 1;
74
+ @tracked limit;
75
+ @tracked query;
76
+ @tracked sort = '-created_at';
77
+
78
+ /**
79
+ * The search task.
80
+ *
81
+ * @void
82
+ */
83
+ @task({ restartable: true }) *search({ target: { value } }) {
84
+ // if no query don't search
85
+ if (isBlank(value)) {
86
+ this.query = null;
87
+ return;
88
+ }
89
+
90
+ // timeout for typing
91
+ yield timeout(250);
92
+
93
+ // reset page for results
94
+ if (this.page > 1) {
95
+ this.page = 1;
96
+ }
97
+
98
+ // update the query param
99
+ this.query = value;
100
+ }
101
+
102
+ @action sendInvites(network) {
103
+ this.networkStoresController.invite(network);
104
+ }
105
+
106
+ @action manageNetwork(network) {
107
+ this.transitionToRoute('networks.index.network', network);
108
+ }
109
+
110
+ @action createNetwork() {
111
+ const network = this.store.createRecord('network');
112
+ const currency = this.currentUser.getWhoisProperty('currency.code');
113
+
114
+ if (currency) {
115
+ network.setProperties({ currency });
116
+ }
117
+
118
+ this.modalsManager.show('modals/create-network', {
119
+ title: 'Create a new network',
120
+ network,
121
+ confirm: (modal) => {
122
+ modal.startLoading();
123
+
124
+ return network.save().then((network) => {
125
+ this.notifications.success('Your new storefront network has been created!');
126
+ this.networks.pushObject(network);
127
+ });
128
+ },
129
+ decline: () => {
130
+ return network.destroyRecord();
131
+ },
132
+ });
133
+ }
134
+
135
+ @action deleteNetwork(network) {
136
+ return this.crud.delete(network);
137
+ }
138
+ }