@fleetbase/ember-core 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 (224) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +32 -0
  3. package/addon/adapters/application.js +155 -0
  4. package/addon/adapters/user.js +19 -0
  5. package/addon/authenticators/fleetbase.js +72 -0
  6. package/addon/decorators/fetch-from.js +55 -0
  7. package/addon/decorators/from-store.js +56 -0
  8. package/addon/decorators/is-equal.js +15 -0
  9. package/addon/exports/host-services.js +18 -0
  10. package/addon/exports/services.js +18 -0
  11. package/addon/initializers/local-storage-adapter.js +21 -0
  12. package/addon/serializers/application.js +87 -0
  13. package/addon/services/app-cache.js +59 -0
  14. package/addon/services/crud.js +226 -0
  15. package/addon/services/current-user.js +259 -0
  16. package/addon/services/fetch.js +648 -0
  17. package/addon/services/filters.js +183 -0
  18. package/addon/services/loader.js +136 -0
  19. package/addon/services/notifications.js +32 -0
  20. package/addon/services/session.js +221 -0
  21. package/addon/services/theme.js +200 -0
  22. package/addon/services/url-search-params.js +92 -0
  23. package/addon/transforms/array.js +29 -0
  24. package/addon/transforms/object.js +11 -0
  25. package/addon/transforms/raw.js +11 -0
  26. package/addon/utils/api-url.js +11 -0
  27. package/addon/utils/apply-column-filters.js +3 -0
  28. package/addon/utils/auto-serialize.js +100 -0
  29. package/addon/utils/calculate-percentage.js +3 -0
  30. package/addon/utils/close-sidebar.js +7 -0
  31. package/addon/utils/console-url.js +56 -0
  32. package/addon/utils/copy-to-clipboard.js +35 -0
  33. package/addon/utils/corslite.js +95 -0
  34. package/addon/utils/download.js +157 -0
  35. package/addon/utils/env.js +3 -0
  36. package/addon/utils/extract-coordinates.js +35 -0
  37. package/addon/utils/extract-latitude.js +28 -0
  38. package/addon/utils/extract-longitude.js +28 -0
  39. package/addon/utils/find-closest-waypoint.js +20 -0
  40. package/addon/utils/first.js +10 -0
  41. package/addon/utils/frontend-url.js +30 -0
  42. package/addon/utils/generate-slug.js +11 -0
  43. package/addon/utils/generate-uuid.js +3 -0
  44. package/addon/utils/get-length-units.js +44 -0
  45. package/addon/utils/get-meta-field-types.js +3 -0
  46. package/addon/utils/get-mime-type.js +25 -0
  47. package/addon/utils/get-model-name.js +45 -0
  48. package/addon/utils/get-permission-action.js +47 -0
  49. package/addon/utils/get-permission-resource.js +16 -0
  50. package/addon/utils/get-pod-methods.js +7 -0
  51. package/addon/utils/get-routing-host.js +44 -0
  52. package/addon/utils/get-service-name.js +21 -0
  53. package/addon/utils/get-user-options.js +21 -0
  54. package/addon/utils/get-weight-units.js +32 -0
  55. package/addon/utils/get-with-default.js +6 -0
  56. package/addon/utils/group-api-events.js +20 -0
  57. package/addon/utils/group-by.js +26 -0
  58. package/addon/utils/has-extension.js +11 -0
  59. package/addon/utils/has-json-structure.js +10 -0
  60. package/addon/utils/hason-structure.js +3 -0
  61. package/addon/utils/haversine.js +59 -0
  62. package/addon/utils/humanize.js +16 -0
  63. package/addon/utils/is-electron.js +18 -0
  64. package/addon/utils/is-email.js +5 -0
  65. package/addon/utils/is-function.js +3 -0
  66. package/addon/utils/is-image-file.js +3 -0
  67. package/addon/utils/is-iterable.js +7 -0
  68. package/addon/utils/is-json.js +9 -0
  69. package/addon/utils/is-latitude.js +3 -0
  70. package/addon/utils/is-letter.js +3 -0
  71. package/addon/utils/is-longitude.js +3 -0
  72. package/addon/utils/is-model.js +6 -0
  73. package/addon/utils/is-not-empty.js +5 -0
  74. package/addon/utils/is-not-model.js +5 -0
  75. package/addon/utils/is-numeric.js +3 -0
  76. package/addon/utils/is-object.js +3 -0
  77. package/addon/utils/is-proxy.js +5 -0
  78. package/addon/utils/is-relation-missing.js +21 -0
  79. package/addon/utils/is-valid-coordinates.js +38 -0
  80. package/addon/utils/is-video-file.js +3 -0
  81. package/addon/utils/is-waypoint-record.js +5 -0
  82. package/addon/utils/ison.js +3 -0
  83. package/addon/utils/isset.js +10 -0
  84. package/addon/utils/last.js +23 -0
  85. package/addon/utils/lazy-load-script.js +25 -0
  86. package/addon/utils/leaflet-icon.js +13 -0
  87. package/addon/utils/leaflet-points-from-coordinates.js +3 -0
  88. package/addon/utils/load-engines.js +37 -0
  89. package/addon/utils/load-extensions.js +8 -0
  90. package/addon/utils/macros/group-by.js +28 -0
  91. package/addon/utils/make-dataset.js +57 -0
  92. package/addon/utils/map-engines.js +30 -0
  93. package/addon/utils/mock-response.js +15 -0
  94. package/addon/utils/numbers-only.js +11 -0
  95. package/addon/utils/past-tense.js +40 -0
  96. package/addon/utils/path-to-route.js +10 -0
  97. package/addon/utils/polyline.js +161 -0
  98. package/addon/utils/range.js +19 -0
  99. package/addon/utils/refresh-route.js +3 -0
  100. package/addon/utils/replace-table-row.js +17 -0
  101. package/addon/utils/reverse-point.js +3 -0
  102. package/addon/utils/serialize/normalize-polymorphic-type-within-hash.js +27 -0
  103. package/addon/utils/serialize/normalize-polymorphic-type.js +13 -0
  104. package/addon/utils/serialize/normalize-relations-with-hash.js +32 -0
  105. package/addon/utils/set-column-filter-options.js +3 -0
  106. package/addon/utils/strip-html.js +3 -0
  107. package/addon/utils/to-leaflet-bounds.js +6 -0
  108. package/addon/utils/to-model.js +18 -0
  109. package/addon/utils/waypoint-label.js +3 -0
  110. package/addon/utils/with-default-value.js +5 -0
  111. package/addon/utils/words.js +5 -0
  112. package/app/adapters/user.js +1 -0
  113. package/app/authenticators/fleetbase.js +1 -0
  114. package/app/decorators/fetch-from.js +1 -0
  115. package/app/decorators/from-store.js +1 -0
  116. package/app/decorators/is-equal.js +1 -0
  117. package/app/exports/host-services.js +1 -0
  118. package/app/exports/services.js +1 -0
  119. package/app/initializers/local-storage-adapter.js +1 -0
  120. package/app/serializers/application.js +1 -0
  121. package/app/services/app-cache.js +1 -0
  122. package/app/services/crud.js +1 -0
  123. package/app/services/current-user.js +1 -0
  124. package/app/services/fetch.js +1 -0
  125. package/app/services/filters.js +1 -0
  126. package/app/services/loader.js +1 -0
  127. package/app/services/notifications.js +1 -0
  128. package/app/services/session.js +1 -0
  129. package/app/services/theme.js +1 -0
  130. package/app/services/url-search-params.js +1 -0
  131. package/app/storages/local-cache.js +12 -0
  132. package/app/storages/user-options.js +12 -0
  133. package/app/transforms/array.js +1 -0
  134. package/app/transforms/object.js +1 -0
  135. package/app/transforms/raw.js +1 -0
  136. package/app/utils/api-url.js +1 -0
  137. package/app/utils/apply-column-filters.js +1 -0
  138. package/app/utils/auto-serialize.js +1 -0
  139. package/app/utils/calculate-percentage.js +1 -0
  140. package/app/utils/close-sidebar.js +1 -0
  141. package/app/utils/console-url.js +1 -0
  142. package/app/utils/copy-to-clipboard.js +1 -0
  143. package/app/utils/corslite.js +1 -0
  144. package/app/utils/download.js +1 -0
  145. package/app/utils/env.js +1 -0
  146. package/app/utils/extract-coordinates.js +1 -0
  147. package/app/utils/extract-latitude.js +1 -0
  148. package/app/utils/extract-longitude.js +1 -0
  149. package/app/utils/find-closest-waypoint.js +1 -0
  150. package/app/utils/first.js +1 -0
  151. package/app/utils/frontend-url.js +1 -0
  152. package/app/utils/generate-slug.js +1 -0
  153. package/app/utils/generate-uuid.js +1 -0
  154. package/app/utils/get-length-units.js +1 -0
  155. package/app/utils/get-meta-field-types.js +1 -0
  156. package/app/utils/get-mime-type.js +1 -0
  157. package/app/utils/get-model-name.js +1 -0
  158. package/app/utils/get-permission-action.js +1 -0
  159. package/app/utils/get-permission-resource.js +1 -0
  160. package/app/utils/get-pod-methods.js +1 -0
  161. package/app/utils/get-routing-host.js +1 -0
  162. package/app/utils/get-service-name.js +1 -0
  163. package/app/utils/get-user-options.js +1 -0
  164. package/app/utils/get-weight-units.js +1 -0
  165. package/app/utils/get-with-default.js +1 -0
  166. package/app/utils/group-api-events.js +1 -0
  167. package/app/utils/group-by.js +1 -0
  168. package/app/utils/has-extension.js +1 -0
  169. package/app/utils/has-json-structure.js +1 -0
  170. package/app/utils/hason-structure.js +1 -0
  171. package/app/utils/haversine.js +1 -0
  172. package/app/utils/humanize.js +1 -0
  173. package/app/utils/is-electron.js +1 -0
  174. package/app/utils/is-email.js +1 -0
  175. package/app/utils/is-function.js +1 -0
  176. package/app/utils/is-image-file.js +1 -0
  177. package/app/utils/is-iterable.js +1 -0
  178. package/app/utils/is-latitude.js +1 -0
  179. package/app/utils/is-letter.js +1 -0
  180. package/app/utils/is-longitude.js +1 -0
  181. package/app/utils/is-model.js +1 -0
  182. package/app/utils/is-not-empty.js +1 -0
  183. package/app/utils/is-not-model.js +1 -0
  184. package/app/utils/is-numeric.js +1 -0
  185. package/app/utils/is-object.js +1 -0
  186. package/app/utils/is-proxy.js +1 -0
  187. package/app/utils/is-relation-missing.js +1 -0
  188. package/app/utils/is-valid-coordinates.js +1 -0
  189. package/app/utils/is-video-file.js +1 -0
  190. package/app/utils/is-waypoint-record.js +1 -0
  191. package/app/utils/ison.js +1 -0
  192. package/app/utils/isset.js +1 -0
  193. package/app/utils/last.js +1 -0
  194. package/app/utils/lazy-load-script.js +1 -0
  195. package/app/utils/leaflet-icon.js +1 -0
  196. package/app/utils/leaflet-points-from-coordinates.js +1 -0
  197. package/app/utils/load-engines.js +1 -0
  198. package/app/utils/load-extensions.js +1 -0
  199. package/app/utils/macros/group-by.js +1 -0
  200. package/app/utils/make-dataset.js +1 -0
  201. package/app/utils/map-engines.js +1 -0
  202. package/app/utils/mock-response.js +1 -0
  203. package/app/utils/numbers-only.js +1 -0
  204. package/app/utils/past-tense.js +1 -0
  205. package/app/utils/path-to-route.js +1 -0
  206. package/app/utils/polyline.js +1 -0
  207. package/app/utils/range.js +1 -0
  208. package/app/utils/refresh-route.js +1 -0
  209. package/app/utils/replace-table-row.js +1 -0
  210. package/app/utils/reverse-point.js +1 -0
  211. package/app/utils/serialize/normalize-polymorphic-type-within-hash.js +1 -0
  212. package/app/utils/serialize/normalize-polymorphic-type.js +1 -0
  213. package/app/utils/serialize/normalize-relations-with-hash.js +1 -0
  214. package/app/utils/set-column-filter-options.js +1 -0
  215. package/app/utils/strip-html.js +1 -0
  216. package/app/utils/to-leaflet-bounds.js +1 -0
  217. package/app/utils/to-model.js +1 -0
  218. package/app/utils/waypoint-label.js +1 -0
  219. package/app/utils/with-default-value.js +1 -0
  220. package/app/utils/words.js +1 -0
  221. package/config/environment.js +5 -0
  222. package/index.js +26 -0
  223. package/package.json +117 -0
  224. package/pnpm-lock.yaml +12750 -0
@@ -0,0 +1,200 @@
1
+ import Service from '@ember/service';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { dasherize } from '@ember/string';
5
+ import { isArray } from '@ember/array';
6
+ import { getOwner } from '@ember/application';
7
+ import closeSidebar from '@fleetbase/ember-ui/utils/close-sidebar';
8
+
9
+ export default class ThemeService extends Service {
10
+ /**
11
+ * Lookup the correct router for the engine and or console.
12
+ *
13
+ * @readonly
14
+ * @memberof ThemeService
15
+ */
16
+ get router() {
17
+ const owner = getOwner(this);
18
+ const router = owner.lookup('service:router');
19
+
20
+ return router;
21
+ }
22
+
23
+ /**
24
+ * Inject the current user service
25
+ *
26
+ * @var {Service}
27
+ */
28
+ @service currentUser;
29
+
30
+ /**
31
+ * The current active theme, uses the system preffered mode to set default
32
+ * refers to the theme in headData service
33
+ *
34
+ * @var {String}
35
+ */
36
+ get activeTheme() {
37
+ const userSetTheme = this.currentUser.getOption(`theme`);
38
+
39
+ if (userSetTheme) {
40
+ return userSetTheme;
41
+ }
42
+
43
+ if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
44
+ return 'dark';
45
+ }
46
+
47
+ // default to dark theme
48
+ return 'dark';
49
+ }
50
+
51
+ /**
52
+ * Set the activeTheme in the headData service
53
+ */
54
+ set activeTheme(theme) {
55
+ document.body.dataset.theme = theme;
56
+ this.currentTheme = theme;
57
+ }
58
+
59
+ /**
60
+ * Current theme, defaults to light, active theme represents the theme set by user OS
61
+ *
62
+ * @var {String}
63
+ */
64
+ @tracked currentTheme = 'dark';
65
+
66
+ /**
67
+ * The current route name as style class
68
+ *
69
+ * @var {String}
70
+ */
71
+ get routeClassName() {
72
+ return dasherize(typeof this.router.currentRouteName === 'string' ? this.router.currentRouteName.replace(/\./g, ' ') : 'fleetbase-console');
73
+ }
74
+
75
+ /**
76
+ * The current route
77
+ *
78
+ * @var {Route}
79
+ */
80
+ get currentRoute() {
81
+ return getOwner(this).lookup(`route:${this.router.currentRouteName}`);
82
+ }
83
+
84
+ /**
85
+ * The current route
86
+ *
87
+ * @var {Route}
88
+ */
89
+ get currentRouteBodyClasses() {
90
+ if (this.currentRoute && this.currentRoute.bodyClassNames && isArray(this.currentRoute.bodyClassNames)) {
91
+ return this.currentRoute.bodyClassNames;
92
+ }
93
+ return [];
94
+ }
95
+
96
+ /**
97
+ * Hook for handling when route does change
98
+ *
99
+ * @void
100
+ */
101
+ routeDidChange() {
102
+ this.setRoutebodyClassNames(this.currentRouteBodyClasses);
103
+ }
104
+
105
+ /**
106
+ * Hook for handling when route does change
107
+ *
108
+ * @void
109
+ */
110
+ routeWillChange() {
111
+ closeSidebar();
112
+ this.removeRoutebodyClassNames(this.currentRouteBodyClasses);
113
+ }
114
+
115
+ /**
116
+ * Initialize theme configurations
117
+ *
118
+ * @void
119
+ */
120
+ initialize(options = {}) {
121
+ this.setTheme(this.activeTheme);
122
+ this.setEnvironment();
123
+ this.resetScroll();
124
+ this.setRoutebodyClassNames(options.bodyClassNames && isArray(options.bodyClassNames) ? options.bodyClassNames : []);
125
+ // on every subsequent transition set the body class
126
+ this.router.on('routeDidChange', this.routeDidChange.bind(this));
127
+ // remove route class as exiting
128
+ this.router.on('routeWillChange', this.routeWillChange.bind(this));
129
+ // remove console-loader
130
+ const consoleLoader = document.getElementById(`console-loader`);
131
+ if (consoleLoader) {
132
+ consoleLoader.remove();
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Resets window scroll
138
+ *
139
+ * @void
140
+ */
141
+ resetScroll() {
142
+ window.scrollTo(0, 0);
143
+ }
144
+
145
+ /**
146
+ * Appends the current route name to body
147
+ *
148
+ * @void
149
+ */
150
+ setRoutebodyClassNames(classes = []) {
151
+ document.body.classList.add(...[this.routeClassName, `${this.currentTheme}-theme`, ...classes]);
152
+ }
153
+
154
+ /**
155
+ * Remove thes current route name from body
156
+ *
157
+ * @void
158
+ */
159
+ removeRoutebodyClassNames(classes = []) {
160
+ document.body.classList.remove(...[this.routeClassName, `${this.currentTheme}-theme`, ...classes]);
161
+ }
162
+
163
+ /**
164
+ * Toggle the activeTheme between light and dark, and returns the toggled them
165
+ *
166
+ * @return string
167
+ */
168
+ toggleTheme() {
169
+ const nextTheme = this.currentTheme === 'light' ? 'dark' : 'light';
170
+ this.setTheme(nextTheme);
171
+ return nextTheme;
172
+ }
173
+
174
+ /**
175
+ * Set the theme to the headData
176
+ *
177
+ * @void
178
+ */
179
+ setTheme(theme = 'light') {
180
+ document.body.classList.remove(`${this.currentTheme}-theme`);
181
+ document.body.classList.add(`${theme}-theme`);
182
+ this.currentUser.setOption(`theme`, theme);
183
+ this.activeTheme = theme;
184
+ }
185
+
186
+ /**
187
+ * Set the theme to the headData
188
+ *
189
+ * @void
190
+ */
191
+ setEnvironment() {
192
+ const isSandbox = this.currentUser.getOption('sandbox') || false;
193
+
194
+ if (isSandbox) {
195
+ document.body.classList.add('sandbox-console');
196
+ } else {
197
+ document.body.classList.remove('sandbox-console');
198
+ }
199
+ }
200
+ }
@@ -0,0 +1,92 @@
1
+ import Service from '@ember/service';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import hasJsonStructure from '../utils/has-json-structure';
4
+
5
+ export default class UrlSearchParamsService extends Service {
6
+ /**
7
+ * The active URL params
8
+ *
9
+ * @var {Array}
10
+ */
11
+ @tracked urlParams;
12
+
13
+ /**
14
+ * Update the URL params
15
+ *
16
+ * @void
17
+ */
18
+ setSearchParams() {
19
+ this.urlParams = new URLSearchParams(window.location.search);
20
+
21
+ return this;
22
+ }
23
+
24
+ /**
25
+ * Get a param
26
+ *
27
+ * @param {String} key the url param
28
+ * @return mixed
29
+ */
30
+ getParam(key) {
31
+ this.setSearchParams();
32
+
33
+ let value = this.urlParams.get(key);
34
+
35
+ if (hasJsonStructure(value)) {
36
+ value = JSON.parse(value);
37
+ }
38
+
39
+ return value;
40
+ }
41
+
42
+ /**
43
+ * Get a param
44
+ *
45
+ * @param {String} key the url param
46
+ * @return mixed
47
+ */
48
+ get(key) {
49
+ return this.getParam(key);
50
+ }
51
+
52
+ /**
53
+ * Determines if a queryParam exists
54
+ *
55
+ * @param {String} key the url param
56
+ * @var {Boolean}
57
+ */
58
+ exists(key) {
59
+ this.setSearchParams();
60
+
61
+ return this.urlParams.has(key);
62
+ }
63
+
64
+ /**
65
+ * Remove a queryparam
66
+ *
67
+ * @param {String} key the url param
68
+ * @void
69
+ */
70
+ remove(key) {
71
+ this.setSearchParams();
72
+
73
+ return this.urlParams.delete(key);
74
+ }
75
+
76
+ /**
77
+ * Returns object of all params
78
+ *
79
+ * @return {Array}
80
+ */
81
+ all() {
82
+ this.setSearchParams();
83
+
84
+ const all = {};
85
+
86
+ for (let key of this.urlParams.keys()) {
87
+ all[key] = this.getParam(key);
88
+ }
89
+
90
+ return all;
91
+ }
92
+ }
@@ -0,0 +1,29 @@
1
+ import Transform from '@ember-data/serializer/transform';
2
+ import isIterable from '../utils/is-iterable';
3
+ import { isArray } from '@ember/array';
4
+
5
+ export default class ArrayTransform extends Transform {
6
+ deserialize(serialized) {
7
+ if (isArray(serialized)) {
8
+ return serialized;
9
+ }
10
+
11
+ if (!isIterable(serialized)) {
12
+ return [];
13
+ }
14
+
15
+ return Array.from(serialized);
16
+ }
17
+
18
+ serialize(deserialized) {
19
+ if (isArray(deserialized)) {
20
+ return deserialized;
21
+ }
22
+
23
+ if (!isIterable(deserialized)) {
24
+ return [];
25
+ }
26
+
27
+ return Array.from(deserialized);
28
+ }
29
+ }
@@ -0,0 +1,11 @@
1
+ import Transform from '@ember-data/serializer/transform';
2
+
3
+ export default class ObjectTransform extends Transform {
4
+ deserialize(serialized) {
5
+ return Object.assign({}, serialized);
6
+ }
7
+
8
+ serialize(deserialized) {
9
+ return Object.assign({}, deserialized);
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ import Transform from '@ember-data/serializer/transform';
2
+
3
+ export default class RawTransform extends Transform {
4
+ deserialize(serialized) {
5
+ return serialized;
6
+ }
7
+
8
+ serialize(deserialized) {
9
+ return deserialized;
10
+ }
11
+ }
@@ -0,0 +1,11 @@
1
+ import consoleUrl from './console-url';
2
+ import config from '@fleetbase/console/config/environment';
3
+ import { get } from '@ember/object';
4
+
5
+ export default function apiUrl(path, queryParams = {}, subdomain = null, host = null) {
6
+ if (host === null) {
7
+ host = `${get(config, 'API.host')}/${get(config, 'API.namespace')}`;
8
+ }
9
+
10
+ return consoleUrl(path, queryParams, subdomain, host);
11
+ }
@@ -0,0 +1,3 @@
1
+ export default function applyColumnFilters() {
2
+ return true;
3
+ }
@@ -0,0 +1,100 @@
1
+ import Model from '@ember-data/model';
2
+ import { isArray } from '@ember/array';
3
+ import { get } from '@ember/object';
4
+ import { isEmpty, tryInvoke } from '@ember/utils';
5
+
6
+ const _isEmpty = (value) => {
7
+ let empty = isEmpty(value);
8
+
9
+ if (empty) {
10
+ return empty;
11
+ }
12
+
13
+ // edge case for empty object {}
14
+ if (typeof value === 'object' && Object.values(value).length === 0) {
15
+ return true;
16
+ }
17
+
18
+ return empty;
19
+ };
20
+
21
+ const invoke = (context, method, ...params) => {
22
+ if (typeof context.method === 'function') {
23
+ return context.method(...params);
24
+ }
25
+
26
+ return null;
27
+ };
28
+
29
+ const serialize = (model) => {
30
+ let serializerMethods = ['toJSON', 'toJson', 'serialize'];
31
+
32
+ for (let i = 0; i < serializerMethods.length; i++) {
33
+ const serializer = serializerMethods.objectAt(i);
34
+ const serialized = invoke(model, serializer);
35
+
36
+ if (!_isEmpty(serialized)) {
37
+ return serialized;
38
+ }
39
+ }
40
+
41
+ return autoSerialize(model);
42
+ };
43
+
44
+ export default function autoSerialize(model, except = []) {
45
+ if (isArray(model)) {
46
+ return model.map((record) => autoSerialize(record, except));
47
+ }
48
+
49
+ if (!(model instanceof Model)) {
50
+ return {};
51
+ }
52
+
53
+ // hacky patch
54
+ const modelName = get(model, '_internalModel.modelName');
55
+
56
+ if (modelName === 'fleet') {
57
+ except.push('drivers');
58
+ }
59
+
60
+ if (modelName === 'zone') {
61
+ except.push('service_area');
62
+ }
63
+
64
+ const serialized = {};
65
+
66
+ // set uuid from id
67
+ serialized.id = model.id;
68
+ serialized.uuid = model.id;
69
+
70
+ // serialize attributes
71
+ model.eachAttribute((attr) => {
72
+ if (except.includes(attr)) {
73
+ return;
74
+ }
75
+
76
+ serialized[attr] = model[attr];
77
+ });
78
+
79
+ // serialize relationships
80
+ model.eachRelationship((attr, descriptor) => {
81
+ const { kind } = descriptor;
82
+
83
+ if (except.includes(attr)) {
84
+ return;
85
+ }
86
+
87
+ if (_isEmpty(model.get(attr))) {
88
+ serialized[attr] = null;
89
+ return;
90
+ }
91
+
92
+ if (kind === 'hasMany') {
93
+ serialized[attr] = model[attr].toArray().map((instance) => serialize(instance));
94
+ } else {
95
+ serialized[attr] = serialize(model[attr]);
96
+ }
97
+ });
98
+
99
+ return serialized;
100
+ }
@@ -0,0 +1,3 @@
1
+ export default function calculatePercentage(percentage, number) {
2
+ return (percentage / 100) * number;
3
+ }
@@ -0,0 +1,7 @@
1
+ export default function closeSidebar() {
2
+ const sidebarNode = window?.document?.querySelector('nav.next-sidebar');
3
+
4
+ if (sidebarNode?.classList?.contains('is-open')) {
5
+ sidebarNode?.classList?.remove('is-open');
6
+ }
7
+ }
@@ -0,0 +1,56 @@
1
+ import config from '@fleetbase/console/config/environment';
2
+ import { isBlank } from '@ember/utils';
3
+
4
+ const isDevelopment = ['local', 'development'].includes(config.environment);
5
+ const isProduction = ['production'].includes(config.environment);
6
+
7
+ function queryString(params) {
8
+ return Object.keys(params)
9
+ .map((key) => `${key}=${params[key]}`)
10
+ .join('&');
11
+ }
12
+
13
+ function extractHostAndPort(url) {
14
+ try {
15
+ const parsedUrl = new URL(url);
16
+ const host = parsedUrl.hostname;
17
+ const port = parsedUrl.port;
18
+
19
+ return {
20
+ host: host,
21
+ port: port || null,
22
+ };
23
+ } catch (error) {
24
+ console.error('Invalid URL:', error);
25
+ return null;
26
+ }
27
+ }
28
+
29
+ export default function consoleUrl(path = '', queryParams = {}, subdomain = 'console', host = 'fleetbase.io') {
30
+ let parsedHost = extractHostAndPort(host);
31
+ let url = isDevelopment ? 'http://' : 'https://';
32
+
33
+ if (subdomain) {
34
+ url += subdomain + '.';
35
+ }
36
+
37
+ let urlParams = !isBlank(queryParams) ? queryString(queryParams) : '';
38
+
39
+ if (!isProduction && !isDevelopment) {
40
+ url += `${config.environment}.`;
41
+ }
42
+
43
+ url += parsedHost.host;
44
+
45
+ if (parsedHost.port) {
46
+ url += `:${parsedHost.port}`;
47
+ }
48
+
49
+ url += `/${path}`;
50
+
51
+ if (urlParams) {
52
+ url += `?${urlParams}`;
53
+ }
54
+
55
+ return url;
56
+ }
@@ -0,0 +1,35 @@
1
+ export default function copyToClipboard(value) {
2
+ const fallbackCopyToClipboard = (value) => {
3
+ return new Promise((resolve, reject) => {
4
+ const textArea = document.createElement('textarea');
5
+ textArea.value = value;
6
+
7
+ // Avoid scrolling to bottom
8
+ textArea.style.top = '0';
9
+ textArea.style.left = '0';
10
+ textArea.style.position = 'fixed';
11
+
12
+ document.body.appendChild(textArea);
13
+ textArea.focus();
14
+ textArea.select();
15
+
16
+ try {
17
+ document.execCommand('copy');
18
+ resolve(value);
19
+ } catch (error) {
20
+ reject(new Error(error));
21
+ }
22
+
23
+ document.body.removeChild(textArea);
24
+ });
25
+ };
26
+
27
+ const _copyToClipboard = (value) => {
28
+ if (!navigator.clipboard) {
29
+ return fallbackCopyToClipboard(value);
30
+ }
31
+ return navigator.clipboard.writeText(value);
32
+ };
33
+
34
+ return _copyToClipboard(value);
35
+ }
@@ -0,0 +1,95 @@
1
+ function corslite(url, callback, cors) {
2
+ var sent = false;
3
+
4
+ if (typeof window.XMLHttpRequest === 'undefined') {
5
+ return callback(Error('Browser not supported'));
6
+ }
7
+
8
+ if (typeof cors === 'undefined') {
9
+ var m = url.match(/^\s*https?:\/\/[^\/]*/);
10
+ cors = m && m[0] !== location.protocol + '//' + location.hostname + (location.port ? ':' + location.port : '');
11
+ }
12
+
13
+ var x = new window.XMLHttpRequest();
14
+
15
+ function isSuccessful(status) {
16
+ return (status >= 200 && status < 300) || status === 304;
17
+ }
18
+
19
+ if (cors && !('withCredentials' in x)) {
20
+ // IE8-9
21
+ x = new window.XDomainRequest();
22
+
23
+ // Ensure callback is never called synchronously, i.e., before
24
+ // x.send() returns (this has been observed in the wild).
25
+ // See https://github.com/mapbox/mapbox.js/issues/472
26
+ var original = callback;
27
+ callback = function () {
28
+ if (sent) {
29
+ original.apply(this, arguments);
30
+ } else {
31
+ var that = this,
32
+ args = arguments;
33
+ setTimeout(function () {
34
+ original.apply(that, args);
35
+ }, 0);
36
+ }
37
+ };
38
+ }
39
+
40
+ function loaded() {
41
+ if (
42
+ // XDomainRequest
43
+ x.status === undefined ||
44
+ // modern browsers
45
+ isSuccessful(x.status)
46
+ )
47
+ callback.call(x, null, x);
48
+ else callback.call(x, x, null);
49
+ }
50
+
51
+ // Both `onreadystatechange` and `onload` can fire. `onreadystatechange`
52
+ // has [been supported for longer](http://stackoverflow.com/a/9181508/229001).
53
+ if ('onload' in x) {
54
+ x.onload = loaded;
55
+ } else {
56
+ x.onreadystatechange = function readystate() {
57
+ if (x.readyState === 4) {
58
+ loaded();
59
+ }
60
+ };
61
+ }
62
+
63
+ // Call the callback with the XMLHttpRequest object as an error and prevent
64
+ // it from ever being called again by reassigning it to `noop`
65
+ x.onerror = function error(evt) {
66
+ // XDomainRequest provides no evt parameter
67
+ callback.call(this, evt || true, null);
68
+ callback = function () {};
69
+ };
70
+
71
+ // IE9 must have onprogress be set to a unique function.
72
+ x.onprogress = function () {};
73
+
74
+ x.ontimeout = function (evt) {
75
+ callback.call(this, evt, null);
76
+ callback = function () {};
77
+ };
78
+
79
+ x.onabort = function (evt) {
80
+ callback.call(this, evt, null);
81
+ callback = function () {};
82
+ };
83
+
84
+ // GET is the only supported HTTP Verb by XDomainRequest and is the
85
+ // only one supported here.
86
+ x.open('GET', url, true);
87
+
88
+ // Send the request. Sending data is not supported.
89
+ x.send(null);
90
+ sent = true;
91
+
92
+ return x;
93
+ }
94
+
95
+ export default corslite;