@fleetbase/ember-core 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/addon/adapters/application.js +24 -0
- package/addon/services/crud.js +15 -7
- package/addon/services/fetch.js +10 -5
- package/addon/services/universe.js +185 -12
- package/addon/utils/array-unique-by.js +8 -0
- package/addon/utils/get-mounted-engine-route-prefix.js +8 -0
- package/addon/utils/get-resource-name-from-transition.js +12 -0
- package/addon/utils/is-nested-route-transition.js +11 -0
- package/addon/utils/is-object.js +1 -1
- package/addon/utils/map-engines.js +14 -3
- package/addon/utils/set-component-arg.js +9 -0
- package/app/utils/array-unique-by.js +1 -0
- package/app/utils/get-mounted-engine-route-prefix.js +1 -0
- package/app/utils/get-resource-name-from-transition.js +1 -0
- package/app/utils/is-nested-route-transition.js +1 -0
- package/app/utils/set-component-arg.js +1 -0
- package/index.js +10 -0
- package/package.json +125 -119
- package/tsconfig.declarations.json +10 -0
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@ Ember Core Services, Utilities and Framework for building Fleetbase Extensions i
|
|
|
4
4
|
|
|
5
5
|
## Compatibility
|
|
6
6
|
|
|
7
|
-
* Ember.js
|
|
8
|
-
* Ember CLI
|
|
9
|
-
* Node.js
|
|
7
|
+
* Ember.js v4.8 or above
|
|
8
|
+
* Ember CLI v4.8 or above
|
|
9
|
+
* Node.js v18 or above
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import RESTAdapter from '@ember-data/adapter/rest';
|
|
2
|
+
import AdapterError from '@ember-data/adapter/error';
|
|
2
3
|
import { tracked } from '@glimmer/tracking';
|
|
3
4
|
import { inject as service } from '@ember/service';
|
|
4
5
|
import { storageFor } from 'ember-local-storage';
|
|
@@ -145,4 +146,27 @@ export default class ApplicationAdapter extends RESTAdapter {
|
|
|
145
146
|
pathForType(type) {
|
|
146
147
|
return dasherize(pluralize(type));
|
|
147
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Handles the response from an AJAX request in an Ember application.
|
|
152
|
+
*
|
|
153
|
+
* @param {number} status - The HTTP status code of the response.
|
|
154
|
+
* @param {object} headers - The headers of the response.
|
|
155
|
+
* @param {object} payload - The payload of the response.
|
|
156
|
+
* @return {Object | AdapterError} response - Returns a new `AdapterError` instance with detailed error information if the response is invalid; otherwise, it returns the result of the superclass's `handleResponse` method.
|
|
157
|
+
*
|
|
158
|
+
* This method first normalizes the error response and generates a detailed message.
|
|
159
|
+
* It then checks if the response is invalid based on the status code. If invalid, it constructs an `AdapterError` with the normalized errors and detailed message.
|
|
160
|
+
* For valid responses, it delegates the handling to the superclass's `handleResponse` method.
|
|
161
|
+
*/
|
|
162
|
+
handleResponse(status, headers, payload) {
|
|
163
|
+
let errors = this.normalizeErrorResponse(status, headers, payload);
|
|
164
|
+
let detailedMessage = this.generatedDetailedMessage(...arguments);
|
|
165
|
+
|
|
166
|
+
if (this.isInvalid(status, headers, payload)) {
|
|
167
|
+
return new AdapterError(errors, detailedMessage);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return super.handleResponse(...arguments);
|
|
171
|
+
}
|
|
148
172
|
}
|
package/addon/services/crud.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import Service from '@ember/service';
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
|
-
import { action } from '@ember/object';
|
|
3
|
+
import { action, get } from '@ember/object';
|
|
4
4
|
import { isArray } from '@ember/array';
|
|
5
5
|
import { dasherize } from '@ember/string';
|
|
6
6
|
import { later } from '@ember/runloop';
|
|
7
7
|
import { pluralize } from 'ember-inflector';
|
|
8
8
|
import { format as formatDate } from 'date-fns';
|
|
9
9
|
import getModelName from '../utils/get-model-name';
|
|
10
|
+
import getWithDefault from '../utils/get-with-default';
|
|
10
11
|
import humanize from '../utils/humanize';
|
|
11
12
|
import first from '../utils/first';
|
|
12
13
|
|
|
@@ -47,7 +48,7 @@ export default class CrudService extends Service {
|
|
|
47
48
|
* @void
|
|
48
49
|
*/
|
|
49
50
|
@action delete(model, options = {}) {
|
|
50
|
-
const modelName = getModelName(model, options
|
|
51
|
+
const modelName = getModelName(model, get(options, 'modelName'), { humanize: true, capitalizeWords: true });
|
|
51
52
|
|
|
52
53
|
this.modalsManager.confirm({
|
|
53
54
|
title: `Are you sure to delete this ${modelName}?`,
|
|
@@ -98,7 +99,7 @@ export default class CrudService extends Service {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
const firstModel = first(selected);
|
|
101
|
-
const modelName = getModelName(firstModel, options
|
|
102
|
+
const modelName = getModelName(firstModel, get(options, 'modelName'), { humanize: true, capitalizeWords: true });
|
|
102
103
|
|
|
103
104
|
// make sure all are the same type
|
|
104
105
|
selected = selected.filter((m) => getModelName(m) === getModelName(firstModel));
|
|
@@ -126,9 +127,11 @@ export default class CrudService extends Service {
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
const firstModel = first(selected);
|
|
129
|
-
const modelName = getModelName(firstModel, options
|
|
130
|
+
const modelName = getModelName(firstModel, get(options, 'modelName'), { humanize: true, capitalizeWords: true });
|
|
130
131
|
const count = selected.length;
|
|
131
132
|
const actionMethod = (typeof options.actionMethod === 'string' ? options.actionMethod : `POST`).toLowerCase();
|
|
133
|
+
const fetchParams = getWithDefault(options, 'fetchParams', {});
|
|
134
|
+
const fetchOptions = getWithDefault(options, 'fetchOptions', {});
|
|
132
135
|
|
|
133
136
|
this.modalsManager.show('modals/bulk-action-model', {
|
|
134
137
|
title: `Bulk ${verb} ${pluralize(modelName)}`,
|
|
@@ -152,9 +155,14 @@ export default class CrudService extends Service {
|
|
|
152
155
|
|
|
153
156
|
modal.startLoading();
|
|
154
157
|
|
|
155
|
-
return this.fetch[actionMethod](
|
|
156
|
-
|
|
157
|
-
|
|
158
|
+
return this.fetch[actionMethod](
|
|
159
|
+
options.actionPath,
|
|
160
|
+
{
|
|
161
|
+
ids: selected.map((model) => model.id),
|
|
162
|
+
...fetchParams,
|
|
163
|
+
},
|
|
164
|
+
fetchOptions
|
|
165
|
+
)
|
|
158
166
|
.then((response) => {
|
|
159
167
|
this.notifications.success(response.message ?? options.successNotification ?? `${count} ${pluralize(modelName, count)} were updated successfully.`);
|
|
160
168
|
|
package/addon/services/fetch.js
CHANGED
|
@@ -5,7 +5,6 @@ import { get, set } from '@ember/object';
|
|
|
5
5
|
import { isBlank } from '@ember/utils';
|
|
6
6
|
import { dasherize } from '@ember/string';
|
|
7
7
|
import { isArray } from '@ember/array';
|
|
8
|
-
import { assign } from '@ember/polyfills';
|
|
9
8
|
import { singularize, pluralize } from 'ember-inflector';
|
|
10
9
|
import { task } from 'ember-concurrency';
|
|
11
10
|
import { storageFor } from 'ember-local-storage';
|
|
@@ -256,7 +255,7 @@ export default class FetchService extends Service {
|
|
|
256
255
|
* @return {Promise}
|
|
257
256
|
*/
|
|
258
257
|
request(path, method = 'GET', data = {}, options = {}) {
|
|
259
|
-
const headers = assign(this.getHeaders(), options.headers ?? {});
|
|
258
|
+
const headers = Object.assign(this.getHeaders(), options.headers ?? {});
|
|
260
259
|
const host = options.host ?? this.host;
|
|
261
260
|
const namespace = options.namespace ?? this.namespace;
|
|
262
261
|
const url = options.externalRequest === true ? path : [host, namespace, path].filter(Boolean).join('/');
|
|
@@ -525,6 +524,12 @@ export default class FetchService extends Service {
|
|
|
525
524
|
const { queue } = file;
|
|
526
525
|
const headers = this.getHeaders();
|
|
527
526
|
|
|
527
|
+
// make sure this task runs once for this file in correct state
|
|
528
|
+
// this can occur when the task is called twice when upload button exists inside upload dropzone
|
|
529
|
+
if (['queued', 'failed', 'timed_out', 'aborted'].indexOf(file.state) === -1) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
528
533
|
// remove Content-Type header
|
|
529
534
|
delete headers['Content-Type'];
|
|
530
535
|
|
|
@@ -540,7 +545,7 @@ export default class FetchService extends Service {
|
|
|
540
545
|
})
|
|
541
546
|
.then((response) => response.json())
|
|
542
547
|
.catch((error) => {
|
|
543
|
-
this.notifications.serverError(error,
|
|
548
|
+
this.notifications.serverError(error, 'File upload failed.');
|
|
544
549
|
});
|
|
545
550
|
|
|
546
551
|
const model = this.store.push(this.store.normalize('file', upload.file));
|
|
@@ -553,7 +558,7 @@ export default class FetchService extends Service {
|
|
|
553
558
|
return model;
|
|
554
559
|
} catch (error) {
|
|
555
560
|
queue.remove(file);
|
|
556
|
-
this.notifications.serverError(error,
|
|
561
|
+
this.notifications.serverError(error, 'File upload failed.');
|
|
557
562
|
|
|
558
563
|
if (typeof errorCallback === 'function') {
|
|
559
564
|
errorCallback(error);
|
|
@@ -574,7 +579,7 @@ export default class FetchService extends Service {
|
|
|
574
579
|
* @return {Promise}
|
|
575
580
|
*/
|
|
576
581
|
download(path, query = {}, options = {}) {
|
|
577
|
-
const headers = assign(this.getHeaders(), options.headers ?? {});
|
|
582
|
+
const headers = Object.assign(this.getHeaders(), options.headers ?? {});
|
|
578
583
|
|
|
579
584
|
return new Promise((resolve, reject) => {
|
|
580
585
|
return fetch(`${options.host || this.host}/${options.namespace || this.namespace}/${path}?${!isBlank(query) ? new URLSearchParams(query).toString() : ''}`, {
|
|
@@ -4,7 +4,7 @@ import { tracked } from '@glimmer/tracking';
|
|
|
4
4
|
import { inject as service } from '@ember/service';
|
|
5
5
|
import { computed, action } from '@ember/object';
|
|
6
6
|
import { isBlank } from '@ember/utils';
|
|
7
|
-
import { isArray } from '@ember/array';
|
|
7
|
+
import { A, isArray } from '@ember/array';
|
|
8
8
|
import { later } from '@ember/runloop';
|
|
9
9
|
import { dasherize, camelize } from '@ember/string';
|
|
10
10
|
import { getOwner } from '@ember/application';
|
|
@@ -14,20 +14,20 @@ import RSVP from 'rsvp';
|
|
|
14
14
|
export default class UniverseService extends Service.extend(Evented) {
|
|
15
15
|
@service router;
|
|
16
16
|
@service intl;
|
|
17
|
-
@tracked headerMenuItems = [];
|
|
18
|
-
@tracked organizationMenuItems = [];
|
|
19
|
-
@tracked userMenuItems = [];
|
|
17
|
+
@tracked headerMenuItems = A([]);
|
|
18
|
+
@tracked organizationMenuItems = A([]);
|
|
19
|
+
@tracked userMenuItems = A([]);
|
|
20
20
|
@tracked adminRegistry = {
|
|
21
|
-
menuItems: [],
|
|
22
|
-
menuPanels: [],
|
|
21
|
+
menuItems: A([]),
|
|
22
|
+
menuPanels: A([]),
|
|
23
23
|
};
|
|
24
24
|
@tracked accountRegistry = {
|
|
25
|
-
menuItems: [],
|
|
26
|
-
menuPanels: [],
|
|
25
|
+
menuItems: A([]),
|
|
26
|
+
menuPanels: A([]),
|
|
27
27
|
};
|
|
28
28
|
@tracked settingsRegistry = {
|
|
29
|
-
menuItems: [],
|
|
30
|
-
menuPanels: [],
|
|
29
|
+
menuItems: A([]),
|
|
30
|
+
menuPanels: A([]),
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -82,6 +82,130 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
82
82
|
return this.settingsRegistry.menuPanels;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Transitions to a given route within a specified Ember engine.
|
|
87
|
+
*
|
|
88
|
+
* This action dynamically retrieves the specified engine's instance and its configuration to prepend the
|
|
89
|
+
* engine's route prefix to the provided route. If the engine instance or its route prefix is not found,
|
|
90
|
+
* it falls back to transitioning to the route without the prefix.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} engineName - The name of the Ember engine.
|
|
93
|
+
* @param {string} route - The route to transition to within the engine.
|
|
94
|
+
* @param {...any} args - Additional arguments to pass to the router's transitionTo method.
|
|
95
|
+
* @returns {Promise} A Promise that resolves with the result of the router's transitionTo method.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Transitions to the 'management.fleets.index.new' route within the '@fleetbase/fleet-ops' engine.
|
|
99
|
+
* this.transitionToEngineRoute('@fleetbase/fleet-ops', 'management.fleets.index.new');
|
|
100
|
+
*/
|
|
101
|
+
@action transitionToEngineRoute(engineName, route, ...args) {
|
|
102
|
+
const engineInstance = this.getEngineInstance(engineName);
|
|
103
|
+
|
|
104
|
+
if (engineInstance) {
|
|
105
|
+
const config = engineInstance.resolveRegistration('config:environment');
|
|
106
|
+
|
|
107
|
+
if (config) {
|
|
108
|
+
let mountedEngineRoutePrefix = config.mountedEngineRoutePrefix;
|
|
109
|
+
|
|
110
|
+
if (!mountedEngineRoutePrefix) {
|
|
111
|
+
mountedEngineRoutePrefix = this._mountPathFromEngineName(engineName);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!mountedEngineRoutePrefix.endsWith('.')) {
|
|
115
|
+
mountedEngineRoutePrefix = mountedEngineRoutePrefix + '.';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return this.router.transitionTo(`${mountedEngineRoutePrefix}${route}`, ...args);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this.router.transitionTo(route, ...args);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves the mount point of a specified engine by its name.
|
|
127
|
+
|
|
128
|
+
* @param {string} engineName - The name of the engine for which to get the mount point.
|
|
129
|
+
* @returns {string|null} The mount point of the engine or null if not found.
|
|
130
|
+
*/
|
|
131
|
+
getEngineMountPoint(engineName) {
|
|
132
|
+
const engineInstance = this.getEngineInstance(engineName);
|
|
133
|
+
return this._getMountPointFromEngineInstance(engineInstance);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Determines the mount point from an engine instance by reading its configuration.
|
|
138
|
+
|
|
139
|
+
* @param {object} engineInstance - The instance of the engine.
|
|
140
|
+
* @returns {string|null} The resolved mount point or null if the instance is undefined or the configuration is not set.
|
|
141
|
+
* @private
|
|
142
|
+
*/
|
|
143
|
+
_getMountPointFromEngineInstance(engineInstance) {
|
|
144
|
+
if (engineInstance) {
|
|
145
|
+
const config = engineInstance.resolveRegistration('config:environment');
|
|
146
|
+
|
|
147
|
+
if (config) {
|
|
148
|
+
let engineName = config.modulePrefix;
|
|
149
|
+
let mountedEngineRoutePrefix = config.mountedEngineRoutePrefix;
|
|
150
|
+
|
|
151
|
+
if (!mountedEngineRoutePrefix) {
|
|
152
|
+
mountedEngineRoutePrefix = this._mountPathFromEngineName(engineName);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!mountedEngineRoutePrefix.endsWith('.')) {
|
|
156
|
+
mountedEngineRoutePrefix = mountedEngineRoutePrefix + '.';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return mountedEngineRoutePrefix;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Extracts and formats the mount path from a given engine name.
|
|
168
|
+
*
|
|
169
|
+
* This function takes an engine name in the format '@scope/engine-name',
|
|
170
|
+
* extracts the 'engine-name' part, removes the '-engine' suffix if present,
|
|
171
|
+
* and formats it into a string that represents a console path.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} engineName - The full name of the engine, typically in the format '@scope/engine-name'.
|
|
174
|
+
* @returns {string} A string representing the console path derived from the engine name.
|
|
175
|
+
* @example
|
|
176
|
+
* // returns 'console.some'
|
|
177
|
+
* _mountPathFromEngineName('@fleetbase/some-engine');
|
|
178
|
+
*/
|
|
179
|
+
_mountPathFromEngineName(engineName) {
|
|
180
|
+
let engineNameSegments = engineName.split('/');
|
|
181
|
+
let mountName = engineNameSegments[1];
|
|
182
|
+
|
|
183
|
+
if (typeof mountName !== 'string') {
|
|
184
|
+
mountName = engineNameSegments[0];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const mountPath = mountName.replace('-engine', '');
|
|
188
|
+
return `console.${mountPath}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Refreshes the current route.
|
|
193
|
+
*
|
|
194
|
+
* This action is a simple wrapper around the router's refresh method. It can be used to re-run the
|
|
195
|
+
* model hooks and reset the controller properties on the current route, effectively reloading the route.
|
|
196
|
+
* This is particularly useful in scenarios where the route needs to be reloaded due to changes in
|
|
197
|
+
* state or data.
|
|
198
|
+
*
|
|
199
|
+
* @returns {Promise} A Promise that resolves with the result of the router's refresh method.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* // To refresh the current route
|
|
203
|
+
* this.refreshRoute();
|
|
204
|
+
*/
|
|
205
|
+
@action refreshRoute() {
|
|
206
|
+
return this.router.refresh();
|
|
207
|
+
}
|
|
208
|
+
|
|
85
209
|
/**
|
|
86
210
|
* Action to transition to a specified route based on the provided menu item.
|
|
87
211
|
*
|
|
@@ -756,7 +880,7 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
756
880
|
loadEngine(name) {
|
|
757
881
|
const router = getOwner(this).lookup('router:main');
|
|
758
882
|
const instanceId = 'manual'; // Arbitrary instance id, should be unique per engine
|
|
759
|
-
const mountPoint =
|
|
883
|
+
const mountPoint = this._mountPathFromEngineName(name); // No mount point for manually loaded engines
|
|
760
884
|
|
|
761
885
|
if (!router._enginePromises[name]) {
|
|
762
886
|
router._enginePromises[name] = Object.create(null);
|
|
@@ -805,7 +929,6 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
805
929
|
assert("You attempted to load the engine '" + name + "', but the engine cannot be found.", owner.hasRegistration(`engine:${name}`));
|
|
806
930
|
|
|
807
931
|
let engineInstances = owner.lookup('router:main')._engineInstances;
|
|
808
|
-
|
|
809
932
|
if (!engineInstances[name]) {
|
|
810
933
|
engineInstances[name] = Object.create(null);
|
|
811
934
|
}
|
|
@@ -815,6 +938,18 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
815
938
|
mountPoint,
|
|
816
939
|
});
|
|
817
940
|
|
|
941
|
+
// correct mountPoint using engine instance
|
|
942
|
+
let _mountPoint = this._getMountPointFromEngineInstance(engineInstance);
|
|
943
|
+
if (_mountPoint) {
|
|
944
|
+
engineInstance.mountPoint = _mountPoint;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// make sure to set dependencies from base instance
|
|
948
|
+
if (engineInstance.base) {
|
|
949
|
+
engineInstance.dependencies = this._setupEngineParentDependenciesBeforeBoot(engineInstance.base.dependencies);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// store loaded instance to engineInstances for booting
|
|
818
953
|
engineInstances[name][instanceId] = engineInstance;
|
|
819
954
|
|
|
820
955
|
return engineInstance.boot().then(() => {
|
|
@@ -822,6 +957,44 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
822
957
|
});
|
|
823
958
|
}
|
|
824
959
|
|
|
960
|
+
_setupEngineParentDependenciesBeforeBoot(baseDependencies = {}) {
|
|
961
|
+
const dependencies = { ...baseDependencies };
|
|
962
|
+
|
|
963
|
+
// fix services
|
|
964
|
+
const servicesObject = {};
|
|
965
|
+
if (isArray(dependencies.services)) {
|
|
966
|
+
for (let i = 0; i < dependencies.services.length; i++) {
|
|
967
|
+
const service = dependencies.services.objectAt(i);
|
|
968
|
+
|
|
969
|
+
if (typeof service === 'object') {
|
|
970
|
+
Object.assign(servicesObject, service);
|
|
971
|
+
continue;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
servicesObject[service] = service;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// fix external routes
|
|
979
|
+
const externalRoutesObject = {};
|
|
980
|
+
if (isArray(dependencies.externalRoutes)) {
|
|
981
|
+
for (let i = 0; i < dependencies.externalRoutes.length; i++) {
|
|
982
|
+
const externalRoute = dependencies.externalRoutes.objectAt(i);
|
|
983
|
+
|
|
984
|
+
if (typeof externalRoute === 'object') {
|
|
985
|
+
Object.assign(externalRoutesObject, externalRoute);
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
externalRoutesObject[externalRoute] = externalRoute;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
dependencies.externalRoutes = externalRoutesObject;
|
|
994
|
+
dependencies.services = servicesObject;
|
|
995
|
+
return dependencies;
|
|
996
|
+
}
|
|
997
|
+
|
|
825
998
|
/**
|
|
826
999
|
* Retrieve an existing engine instance by its name and instanceId.
|
|
827
1000
|
*
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default function getMountedEngineRoutePrefix(defaultName, fleetbase = {}) {
|
|
2
|
+
let mountedEngineRoutePrefix = defaultName;
|
|
3
|
+
if (fleetbase && typeof fleetbase.route === 'string') {
|
|
4
|
+
mountedEngineRoutePrefix = fleetbase.route;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
return `console.${mountedEngineRoutePrefix}.`;
|
|
8
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default function getResourceNameFromTransition(transition) {
|
|
2
|
+
const { to } = transition;
|
|
3
|
+
|
|
4
|
+
if (typeof to.name === 'string') {
|
|
5
|
+
let routePathSegments = to.name.split('.');
|
|
6
|
+
let resourceName = routePathSegments[3];
|
|
7
|
+
|
|
8
|
+
return resourceName;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { get } from '@ember/object';
|
|
2
|
+
|
|
3
|
+
export default function isNestedRouteTransition(transition) {
|
|
4
|
+
const toRoute = get(transition, 'to.name');
|
|
5
|
+
const fromRouteParent = get(transition, 'from.parent.name');
|
|
6
|
+
const toRouteParent = get(transition, 'to.parent.name');
|
|
7
|
+
const isNested = toRoute.startsWith(fromRouteParent);
|
|
8
|
+
const isMatchingParents = fromRouteParent && toRouteParent && fromRouteParent === toRouteParent;
|
|
9
|
+
|
|
10
|
+
return isNested || isMatchingParents;
|
|
11
|
+
}
|
package/addon/utils/is-object.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { dasherize } from '@ember/string';
|
|
2
2
|
import hostServices from '../exports/host-services';
|
|
3
3
|
|
|
4
|
-
function
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export function getExtensionMountPath(extensionName) {
|
|
5
|
+
let extensionNameSegments = extensionName.split('/');
|
|
6
|
+
let mountName = extensionNameSegments[1];
|
|
7
|
+
|
|
8
|
+
if (typeof mountName !== 'string') {
|
|
9
|
+
mountName = extensionNameSegments[0];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return mountName.replace('-engine', '');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function routeNameFromExtension(extension) {
|
|
16
|
+
const mountPath = getExtensionMountPath(extension.name);
|
|
7
17
|
let route = mountPath;
|
|
8
18
|
|
|
9
19
|
if (extension.fleetbase && extension.fleetbase.route) {
|
|
@@ -18,6 +28,7 @@ export default function mapEngines(extensions, withServices = []) {
|
|
|
18
28
|
const externalRoutes = {
|
|
19
29
|
console: 'console.home',
|
|
20
30
|
extensions: 'console.extensions',
|
|
31
|
+
notifications: 'console.notifications',
|
|
21
32
|
};
|
|
22
33
|
|
|
23
34
|
for (let i = 0; i < extensions.length; i++) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/array-unique-by';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/get-mounted-engine-route-prefix';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/get-resource-name-from-transition';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/is-nested-route-transition';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/set-component-arg';
|
package/index.js
CHANGED
|
@@ -21,6 +21,16 @@ module.exports = {
|
|
|
21
21
|
useSessionSetupMethod: true,
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
if (app.options['ember-cli-notifications'] !== undefined) {
|
|
26
|
+
app.options['ember-cli-notifications'].autoClear = true;
|
|
27
|
+
app.options['ember-cli-notifications'].clearDuration = 1000 * 5;
|
|
28
|
+
} else {
|
|
29
|
+
app.options['ember-cli-notifications'] = {
|
|
30
|
+
autoClear: true,
|
|
31
|
+
clearDuration: 1000 * 5,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
24
34
|
},
|
|
25
35
|
|
|
26
36
|
treeForPublic: function () {
|
package/package.json
CHANGED
|
@@ -1,121 +1,127 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
2
|
+
"name": "@fleetbase/ember-core",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"fleetbase-core",
|
|
7
|
+
"fleetbase-services",
|
|
8
|
+
"fleetbase",
|
|
9
|
+
"ember-addon"
|
|
10
|
+
],
|
|
11
|
+
"repository": "https://github.com/fleetbase/ember-core",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
|
|
14
|
+
"directories": {
|
|
15
|
+
"app": "app",
|
|
16
|
+
"addon": "addon",
|
|
17
|
+
"tests": "tests"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "ember build --environment=production",
|
|
21
|
+
"lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
|
|
22
|
+
"lint:css": "stylelint \"**/*.css\"",
|
|
23
|
+
"lint:css:fix": "concurrently \"npm:lint:css -- --fix\"",
|
|
24
|
+
"lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
|
|
25
|
+
"lint:hbs": "ember-template-lint .",
|
|
26
|
+
"lint:hbs:fix": "ember-template-lint . --fix",
|
|
27
|
+
"lint:js": "eslint . --cache",
|
|
28
|
+
"lint:js:fix": "eslint . --fix",
|
|
29
|
+
"start": "ember serve",
|
|
30
|
+
"test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"",
|
|
31
|
+
"test:ember": "ember test",
|
|
32
|
+
"test:ember-compatibility": "ember try:each",
|
|
33
|
+
"publish:npm": "npm config set registry https://registry.npmjs.org/ && npm publish",
|
|
34
|
+
"publish:github": "npm config set '@fleetbase:registry' https://npm.pkg.github.com/ && npm publish"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@babel/core": "^7.23.2",
|
|
38
|
+
"date-fns": "^2.30.0",
|
|
39
|
+
"ember-auto-import": "^2.6.3",
|
|
40
|
+
"ember-cli-babel": "^8.2.0",
|
|
41
|
+
"ember-cli-htmlbars": "^6.3.0",
|
|
42
|
+
"ember-cli-notifications": "^9.0.0",
|
|
43
|
+
"ember-concurrency": "^3.1.1",
|
|
44
|
+
"ember-concurrency-decorators": "^2.0.3",
|
|
45
|
+
"ember-decorators": "^6.1.1",
|
|
46
|
+
"ember-get-config": "^2.1.1",
|
|
47
|
+
"ember-inflector": "^4.0.2",
|
|
48
|
+
"ember-intl": "6.3.2",
|
|
49
|
+
"ember-loading": "^2.0.0",
|
|
50
|
+
"ember-local-storage": "^2.0.4",
|
|
51
|
+
"ember-simple-auth": "^6.0.0",
|
|
52
|
+
"ember-wormhole": "^0.6.0",
|
|
53
|
+
"socketcluster-client": "^17.1.1"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@babel/eslint-parser": "^7.22.15",
|
|
57
|
+
"@babel/plugin-proposal-decorators": "^7.23.2",
|
|
58
|
+
"@ember/optional-features": "^2.0.0",
|
|
59
|
+
"@ember/test-helpers": "^3.2.0",
|
|
60
|
+
"@embroider/test-setup": "^3.0.2",
|
|
61
|
+
"@glimmer/component": "^1.1.2",
|
|
62
|
+
"@glimmer/tracking": "^1.1.2",
|
|
63
|
+
"broccoli-asset-rev": "^3.0.0",
|
|
64
|
+
"broccoli-funnel": "^3.0.8",
|
|
65
|
+
"broccoli-merge-trees": "^4.2.0",
|
|
66
|
+
"broccoli-persistent-filter": "^3.1.3",
|
|
67
|
+
"concurrently": "^8.2.2",
|
|
68
|
+
"ember-cli": "~5.4.1",
|
|
69
|
+
"ember-cli-clean-css": "^3.0.0",
|
|
70
|
+
"ember-cli-dependency-checker": "^3.3.2",
|
|
71
|
+
"ember-cli-inject-live-reload": "^2.1.0",
|
|
72
|
+
"ember-cli-sri": "^2.1.1",
|
|
73
|
+
"ember-cli-terser": "^4.0.2",
|
|
74
|
+
"ember-file-upload": "8.4.0",
|
|
75
|
+
"ember-load-initializers": "^2.1.2",
|
|
76
|
+
"ember-page-title": "^8.0.0",
|
|
77
|
+
"ember-qunit": "^8.0.1",
|
|
78
|
+
"ember-resolver": "^11.0.1",
|
|
79
|
+
"ember-source": "~5.4.0",
|
|
80
|
+
"ember-data": "^4.12.5",
|
|
81
|
+
"ember-source-channel-url": "^3.0.0",
|
|
82
|
+
"ember-template-lint": "^5.11.2",
|
|
83
|
+
"ember-try": "^3.0.0",
|
|
84
|
+
"eslint": "^8.52.0",
|
|
85
|
+
"eslint-config-prettier": "^9.0.0",
|
|
86
|
+
"eslint-plugin-ember": "^11.11.1",
|
|
87
|
+
"eslint-plugin-n": "^16.2.0",
|
|
88
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
89
|
+
"eslint-plugin-qunit": "^8.0.1",
|
|
90
|
+
"loader.js": "^4.7.0",
|
|
91
|
+
"prettier": "^3.0.3",
|
|
92
|
+
"qunit": "^2.20.0",
|
|
93
|
+
"qunit-dom": "^2.0.0",
|
|
94
|
+
"resolve": "^1.22.2",
|
|
95
|
+
"stylelint": "^15.11.0",
|
|
96
|
+
"stylelint-config-standard": "^34.0.0",
|
|
97
|
+
"stylelint-prettier": "^4.0.2",
|
|
98
|
+
"webpack": "^5.89.0"
|
|
99
|
+
},
|
|
100
|
+
"overrides": {
|
|
101
|
+
"broccoli-persistent-filter": "^3.1.3"
|
|
102
|
+
},
|
|
103
|
+
"engines": {
|
|
104
|
+
"node": ">= 18"
|
|
105
|
+
},
|
|
106
|
+
"ember": {
|
|
107
|
+
"edition": "octane"
|
|
108
|
+
},
|
|
109
|
+
"ember-addon": {
|
|
110
|
+
"configPath": "tests/dummy/config"
|
|
111
|
+
},
|
|
112
|
+
"prettier": {
|
|
113
|
+
"trailingComma": "es5",
|
|
114
|
+
"tabWidth": 4,
|
|
115
|
+
"semi": true,
|
|
116
|
+
"singleQuote": true,
|
|
117
|
+
"printWidth": 190,
|
|
118
|
+
"overrides": [
|
|
119
|
+
{
|
|
120
|
+
"files": "*.hbs",
|
|
121
|
+
"options": {
|
|
122
|
+
"singleQuote": false
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
121
127
|
}
|