Skip to content

Commit

Permalink
Merge pull request #33 from fleetbase/dev-v0.2.5
Browse files Browse the repository at this point in the history
v0.2.5
  • Loading branch information
roncodes authored Mar 11, 2024
2 parents e9f4dc4 + d1e0081 commit d0c5757
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 334 deletions.
34 changes: 29 additions & 5 deletions addon/adapters/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { get } from '@ember/object';
import { isBlank } from '@ember/utils';
import { dasherize } from '@ember/string';
import { pluralize } from 'ember-inflector';
import { decompress as decompressJson } from 'compress-json';
import getUserOptions from '../utils/get-user-options';
import config from 'ember-get-config';

Expand Down Expand Up @@ -161,14 +162,37 @@ export default class ApplicationAdapter extends RESTAdapter {
* 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.
* For valid responses, it delegates the handling to the superclass's `handleResponse` method.
*/
handleResponse(status, headers, payload) {
async handleResponse(status, headers, payload, requestData) {
let decompressedPayload = this.decompressPayload(payload, headers);
let errors = this.normalizeErrorResponse(status, headers, payload);
let detailedMessage = this.generatedDetailedMessage(...arguments);

if (this.isInvalid(status, headers, payload)) {
return new AdapterError(errors, detailedMessage);
return new AdapterError(errors);
}

return super.handleResponse(status, headers, decompressedPayload, requestData);
}

/**
* Decompresses the response payload if it's marked as compressed in the response headers.
*
* This method checks the response headers for a specific 'x-compressed-json' flag.
* If this flag is set, indicating that the response payload is compressed, the method
* decompresses the payload. The decompressed payload is then parsed as JSON and returned.
* If the payload is not compressed, it is returned as is.
*
* @param {object} payload - The original payload of the response.
* @param {object} headers - The headers of the response, used to check if the payload is compressed.
* @return {object} The decompressed payload if it was compressed, or the original payload otherwise.
*/
async decompressPayload(payload, headers) {
// Check if the response is compressed
if (headers['x-compressed-json'] === '1' || headers['x-compressed-json'] === 1) {
// Decompress the payload
const decompressedPayload = decompressJson(payload);
// Replace payload with decompressed json payload
payload = JSON.parse(decompressedPayload);
}

return super.handleResponse(...arguments);
return payload;
}
}
11 changes: 8 additions & 3 deletions addon/initializers/load-socketcluster-client.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
export function initialize() {
const socketClusterClientScript = document.createElement('script');
socketClusterClientScript.src = '/assets/socketcluster-client.min.js';
document.body.appendChild(socketClusterClientScript);
// Check if the script already exists
// Only insert the script tag if it doesn't already exist
if (!document.querySelector('script[data-socketcluster-client]')) {
const socketClusterClientScript = document.createElement('script');
socketClusterClientScript.setAttribute('data-socketcluster-client', '1');
socketClusterClientScript.src = '/assets/socketcluster-client.min.js';
document.body.appendChild(socketClusterClientScript);
}
}

export default {
Expand Down
3 changes: 2 additions & 1 deletion addon/services/app-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export default class AppCacheService extends Service {
@storageFor('local-cache') localCache;

get cachePrefix() {
return `${this.currentUser.id}:${this.currentUser.companyId}:`;
const userId = this.currentUser.id ?? 'anon';
return `${userId}:${this.currentUser.companyId}:`;
}

@action setEmberData(key, value, except = []) {
Expand Down
11 changes: 11 additions & 0 deletions addon/services/current-user.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Service from '@ember/service';
import Evented from '@ember/object/evented';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { dasherize } from '@ember/string';
import { computed, get, action } from '@ember/object';
import { isBlank } from '@ember/utils';
Expand Down Expand Up @@ -43,6 +44,16 @@ export default class CurrentUserService extends Service.extend(Evented) {
*/
@service notifications;

/**
* Property to hold loaded user.
*
* @var {UserModel|Object}
* @memberof CurrentUserService
*/
@tracked user = {
id: 'anon',
};

/**
* User options in localStorage
*
Expand Down
42 changes: 26 additions & 16 deletions addon/services/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { singularize, pluralize } from 'ember-inflector';
import { task } from 'ember-concurrency';
import { storageFor } from 'ember-local-storage';
import { intervalToDuration, parseISO } from 'date-fns';
import { decompress as decompressJson } from 'compress-json';
import config from 'ember-get-config';
import corslite from '../utils/corslite';
import getMimeType from '../utils/get-mime-type';
Expand Down Expand Up @@ -226,22 +227,31 @@ export default class FetchService extends Service {
*
* @return {Promise}
*/
parseJSON(response) {
return new Promise((resolve, reject) =>
response
.json()
.then((json) =>
resolve({
statusText: response.statusText,
status: response.status,
ok: response.ok,
json,
})
)
.catch(() => {
reject(new Error('Oops! Something went wrong when handling your request.'));
})
);
async parseJSON(response) {
try {
const compressedHeader = await response.headers.get('x-compressed-json');
let json;

if (compressedHeader === '1') {
// Handle compressed json
const text = await response.text();
json = JSON.parse(text);
json = decompressJson(json);
json = JSON.parse(json);
} else {
// Handle regular json
json = await response.json();
}

return {
statusText: response.statusText,
status: response.status,
ok: response.ok,
json,
};
} catch (error) {
throw new Error('Error processing response: ' + error.message);
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion addon/services/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export default class ThemeService extends Service {
setTheme(theme = 'light') {
document.body.classList.remove(`${this.currentTheme}-theme`);
document.body.classList.add(`${theme}-theme`);
this.currentUser.setOption(`theme`, theme);
this.currentUser.setOption('theme', theme);
this.activeTheme = theme;
}

Expand Down
49 changes: 49 additions & 0 deletions addon/services/universe.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export default class UniverseService extends Service.extend(Evented) {
name: registryName,
menuItems: [],
menuPanels: [],
renderableComponents: [],
...options,
};

Expand Down Expand Up @@ -426,6 +427,26 @@ export default class UniverseService extends Service.extend(Evented) {
return [];
}

/**
* Retrieves renderable components from a specified registry.
* This action checks the internal registry, identified by the given registry name,
* and returns the 'renderableComponents' if they are present and are an array.
*
* @action
* @param {string} registryName - The name of the registry to retrieve components from.
* @returns {Array} An array of renderable components from the specified registry, or an empty array if none found.
*/
@action getRenderableComponentsFromRegistry(registryName) {
const internalRegistryName = this.createInternalRegistryName(registryName);
const registry = this[internalRegistryName];

if (!isBlank(registry) && isArray(registry.renderableComponents)) {
return registry.renderableComponents;
}

return [];
}

/**
* Loads a component from the specified registry based on a given slug and view.
*
Expand Down Expand Up @@ -550,6 +571,34 @@ export default class UniverseService extends Service.extend(Evented) {
});
}

/**
* Registers a renderable component or an array of components into a specified registry.
* If a single component is provided, it is registered directly.
* If an array of components is provided, each component in the array is registered individually.
* The component is also registered into the specified engine.
*
* @param {string} engineName - The name of the engine to register the component(s) into.
* @param {string} registryName - The registry name where the component(s) should be registered.
* @param {Object|Array} component - The component or array of components to register.
*/
registerRenderableComponent(engineName, registryName, component) {
if (isArray(component)) {
component.forEach((_) => this.registerRenderableComponent(registryName, _));
return;
}

// register component to engine
this.registerComponentInEngine(engineName, component);

// register to registry
const internalRegistryName = this.createInternalRegistryName(registryName);
if (isArray(this[internalRegistryName].renderableComponents)) {
this[internalRegistryName].renderableComponents.pushObject(component);
} else {
this[internalRegistryName].renderableComponents = [component];
}
}

/**
* Registers a new menu panel in a registry.
*
Expand Down
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ module.exports = {

if (app.options['ember-cli-notifications'] !== undefined) {
app.options['ember-cli-notifications'].autoClear = true;
app.options['ember-cli-notifications'].clearDuration = 1000 * 5;
app.options['ember-cli-notifications'].clearDuration = 1000 * 3.5;
} else {
app.options['ember-cli-notifications'] = {
autoClear: true,
clearDuration: 1000 * 5,
clearDuration: 1000 * 3.5,
};
}
},
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fleetbase/ember-core",
"version": "0.2.4",
"version": "0.2.5",
"description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.",
"keywords": [
"fleetbase-core",
Expand Down Expand Up @@ -35,6 +35,7 @@
},
"dependencies": {
"@babel/core": "^7.23.2",
"compress-json": "^3.0.0",
"date-fns": "^2.30.0",
"ember-auto-import": "^2.6.3",
"ember-cli-babel": "^8.2.0",
Expand Down Expand Up @@ -71,13 +72,13 @@
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-data": "^4.12.5",
"ember-file-upload": "8.4.0",
"ember-load-initializers": "^2.1.2",
"ember-page-title": "^8.0.0",
"ember-qunit": "^8.0.1",
"ember-resolver": "^11.0.1",
"ember-source": "~5.4.0",
"ember-data": "^4.12.5",
"ember-source-channel-url": "^3.0.0",
"ember-template-lint": "^5.11.2",
"ember-try": "^3.0.0",
Expand Down
Loading

0 comments on commit d0c5757

Please sign in to comment.