From b4c433bdac98bd2acd52f9e6e820f2bb9543decf Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Fri, 18 Sep 2026 12:22:13 +0800 Subject: [PATCH 1/5] feat(dev): add resource action services for API keys and webhooks Move the create, edit and delete dialogs out of the index controllers into `api-key-actions` and `webhook-actions` services extending ember-core's `ResourceActionService`. The controllers now delegate to them, so behavior is unchanged. This lets other engines (the AI extension in particular) open the Developers dialogs through `universe.getServiceFromEngine` instead of query-param deep links. --- addon/controllers/api-keys/index.js | 81 +----------- addon/controllers/webhooks/index.js | 152 ++--------------------- addon/services/api-key-actions.js | 102 +++++++++++++++ addon/services/webhook-actions.js | 185 ++++++++++++++++++++++++++++ app/services/api-key-actions.js | 1 + app/services/webhook-actions.js | 1 + 6 files changed, 303 insertions(+), 219 deletions(-) create mode 100644 addon/services/api-key-actions.js create mode 100644 addon/services/webhook-actions.js create mode 100644 app/services/api-key-actions.js create mode 100644 app/services/webhook-actions.js diff --git a/addon/controllers/api-keys/index.js b/addon/controllers/api-keys/index.js index 9e52881..b49b2e6 100644 --- a/addon/controllers/api-keys/index.js +++ b/addon/controllers/api-keys/index.js @@ -11,6 +11,7 @@ import { format as formatDate } from 'date-fns'; import getWithDefault from '@fleetbase/ember-core/utils/get-with-default'; export default class ApiKeysIndexController extends Controller { + @service apiKeyActions; @service currentUser; @service intl; @service modalsManager; @@ -261,83 +262,13 @@ export default class ApiKeysIndexController extends Controller { this.currentUser.setOption('testKey', value); } - /** - * Toggles modal to create a new API key - * - * @void - */ - @action createApiKey() { - const formPermission = 'developers create api-key'; - const apiKey = this.store.createRecord('api-credential', { - test_mode: this.testMode, - }); - - this.editApiKey(apiKey, { - title: this.intl.t('developers.api-keys.index.new-api-key-title'), - acceptButtonIcon: 'check', - acceptButtonIconPrefix: 'fas', - acceptButtonDisabled: this.abilities.cannot(formPermission), - acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, - successMessage: this.intl.t('developers.api-keys.index.new-api-key-message'), - formPermission, - apiKey, - confirm: async (modal) => { - modal.startLoading(); - - if (this.abilities.cannot(formPermission)) { - return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); - } - - try { - await apiKey.save(); - this.notifications.success(modal.getOption('successMessage')); - return this.hostRouter.refresh(); - } catch (error) { - this.notifications.serverError(error); - modal.stopLoading(); - } - }, - }); + // Creating and editing keys lives in the api-key-actions service so other engines can open these dialogs too. + @action createApiKey(...args) { + return this.apiKeyActions.createApiKey(...args); } - /** - * Toggles modal to create a new API key - * - * @void - */ - @action editApiKey(apiKey, options = {}) { - const formPermission = 'developers update api-key'; - this.modalsManager.show('modals/api-key-form', { - title: this.intl.t('developers.api-keys.index.edit-api-key-title'), - acceptButtonIcon: 'save', - acceptButtonDisabled: this.abilities.cannot(formPermission), - acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, - successMessage: this.intl.t('developers.api-keys.index.edit-api-key-message'), - expirationOptions: this.expirationOptions, - testMode: this.currentUser.getOption('sandbox') || false, - apiKey, - formPermission, - setExpiration: ({ target }) => { - apiKey.expires_at = target.value || null; - }, - confirm: async (modal) => { - modal.startLoading(); - - if (this.abilities.cannot(formPermission)) { - return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); - } - - try { - await apiKey.save(); - this.notifications.success(modal.getOption('successMessage')); - return this.hostRouter.refresh(); - } catch (error) { - this.notifications.serverError(error); - modal.stopLoading(); - } - }, - ...options, - }); + @action editApiKey(...args) { + return this.apiKeyActions.editApiKey(...args); } /** diff --git a/addon/controllers/webhooks/index.js b/addon/controllers/webhooks/index.js index 17ae163..83f2ebe 100644 --- a/addon/controllers/webhooks/index.js +++ b/addon/controllers/webhooks/index.js @@ -10,6 +10,7 @@ import fromStore from '@fleetbase/ember-core/decorators/legacy-from-store'; import fetchFrom from '@fleetbase/ember-core/decorators/legacy-fetch-from'; export default class WebhooksIndexController extends BaseController { + @service webhookActions; @service currentUser; @service intl; @service modalsManager; @@ -177,154 +178,17 @@ export default class WebhooksIndexController extends BaseController { this.query = value; } - /** - * Toggles modal to create a new API key - * - * @void - */ - @action createWebhook() { - const formPermission = 'developers create webhook'; - const webhook = this.store.createRecord('webhook-endpoint', { - events: [], - mode: this.currentUser.getOption('sandbox') ? 'test' : 'live', - }); - - this.editWebhook(webhook, { - title: this.intl.t('developers.webhooks.index.add-webhook'), - acceptButtonText: this.intl.t('developers.webhooks.index.add-webhook-button-text'), - acceptButtonIcon: 'check', - acceptButtonIconPrefix: 'fas', - acceptButtonDisabled: this.abilities.cannot(formPermission), - acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, - formPermission, - webhook, - confirm: async (modal) => { - modal.startLoading(); - - if (this.abilities.cannot(formPermission)) { - return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); - } - - try { - await webhook.save(); - this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message')); - return this.hostRouter.refresh(); - } catch (error) { - this.notifications.serverError(error); - modal.stopLoading(); - } - }, - }); + // Webhook dialogs live in the webhook-actions service so other engines can open them too. + @action createWebhook(...args) { + return this.webhookActions.createWebhook(...args); } - /** - * Triggers dialog to edit webhook - * - * @param {WebhookEndpointModel} webhook - * @param {Object} options - * @void - */ - @action async editWebhook(webhook, options = {}) { - await this.apiCredentials; - - const formPermission = 'developers update webhook'; - this.modalsManager.show('modals/webhook-form', { - title: this.intl.t('developers.webhooks.index.edit-webhook-endpoint'), - acceptButtonText: this.intl.t('developers.webhooks.index.edit-webhook-endpoint-button-text'), - acceptButtonIcon: 'save', - acceptButtonDisabled: this.abilities.cannot(formPermission), - acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, - formPermission, - declineButtonIcon: 'times', - declineButtonIconPrefix: 'fas', - eventOptions: this.groupedApiEvents, - versionOptions: this.apiVersions, - apiCredentialOptions: this.apiCredentials, - webhook, - setVersion: ({ target }) => { - webhook.version = target.value || null; - }, - setApiCredential: ({ target }) => { - webhook.api_credential_uuid = target.value || null; - }, - searchEvents: (query) => { - if (typeof query !== 'string') { - return; - } - const resources = Object.keys(this.groupedApiEvents); - const filteredEvents = {}; - resources.forEach((eventResource) => { - filteredEvents[eventResource] = this.groupedApiEvents[eventResource].filter((event) => { - return event.toLowerCase().includes(query.toLowerCase()); - }); - // if 0 events remove from filter - if (filteredEvents[eventResource].length === 0) { - delete filteredEvents[eventResource]; - } - }); - this.modalsManager.setOption('eventOptions', filteredEvents); - }, - addEvent: (event) => { - if (webhook.events.includes(event)) { - return; - } - - webhook.events.pushObject(event); - }, - removeEvent: (event) => { - webhook.events.removeObject(event); - }, - clearEvents: () => { - webhook.events.clear(); - }, - receiveAllEvents: () => { - webhook.events.pushObjects(this.webhookEvents); - }, - confirm: async (modal) => { - modal.startLoading(); - - if (this.abilities.cannot(formPermission)) { - return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); - } - - try { - await webhook.save(); - this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message')); - return this.hostRouter.refresh(); - } catch (error) { - this.notifications.serverError(error); - modal.stopLoading(); - } - }, - ...options, - }); + @action editWebhook(...args) { + return this.webhookActions.editWebhook(...args); } - /** - * Toggles dialog to delete webhook - * - * @param {WebhookEndpointModel} webhook - * @param {Object} options - * @void - */ - @action deleteWebhook(webhook, options = {}) { - this.modalsManager.confirm({ - title: this.intl.t('developers.webhooks.index.delete-webhook-endpoint'), - body: this.intl.t('developers.webhooks.index.delete-webhook-endpoint-body'), - confirm: async (modal) => { - modal.startLoading(); - - try { - await webhook.destroyRecord(); - this.notifications.success(this.intl.t('developers.webhooks.index.delete-webhook-success-message')); - return this.hostRouter.refresh(); - } catch (error) { - this.notifications.serverError(error); - modal.stopLoading(); - } - }, - ...options, - }); + @action deleteWebhook(...args) { + return this.webhookActions.deleteWebhook(...args); } /** diff --git a/addon/services/api-key-actions.js b/addon/services/api-key-actions.js new file mode 100644 index 0000000..a76abea --- /dev/null +++ b/addon/services/api-key-actions.js @@ -0,0 +1,102 @@ +import ResourceActionService from '@fleetbase/ember-core/services/resource-action'; +import { action } from '@ember/object'; + +/** + * API key actions shared by the Developers console and other engines (for example Fleetbase AI). + */ +export default class ApiKeyActionsService extends ResourceActionService { + expirationOptions = ['never', 'immediately', 'in 1 hour', 'in 24 hours', 'in 3 days', 'in 7 days']; + + constructor() { + super(...arguments); + this.initialize('api-credential', { permissionPrefix: 'developers', mountPrefix: 'console.developers' }); + } + + transition = { + list: () => this.transitionTo('api-keys.index'), + }; + + modal = { + create: (...args) => this.createApiKey(...args), + edit: (...args) => this.editApiKey(...args), + }; + + /** + * Toggles modal to create a new API key + * + * @void + */ + @action createApiKey() { + const formPermission = 'developers create api-key'; + const apiKey = this.store.createRecord('api-credential', { + test_mode: this.currentUser.getOption('sandbox') || false, + }); + + this.editApiKey(apiKey, { + title: this.intl.t('developers.api-keys.index.new-api-key-title'), + acceptButtonIcon: 'check', + acceptButtonIconPrefix: 'fas', + acceptButtonDisabled: this.abilities.cannot(formPermission), + acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, + successMessage: this.intl.t('developers.api-keys.index.new-api-key-message'), + formPermission, + apiKey, + confirm: async (modal) => { + modal.startLoading(); + + if (this.abilities.cannot(formPermission)) { + return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); + } + + try { + await apiKey.save(); + this.notifications.success(modal.getOption('successMessage')); + return this.hostRouter.refresh(); + } catch (error) { + this.notifications.serverError(error); + modal.stopLoading(); + } + }, + }); + } + + /** + * Opens the dialog to edit an API key + * + * @void + */ + @action editApiKey(apiKey, options = {}) { + const formPermission = 'developers update api-key'; + this.modalsManager.show('modals/api-key-form', { + title: this.intl.t('developers.api-keys.index.edit-api-key-title'), + acceptButtonIcon: 'save', + acceptButtonDisabled: this.abilities.cannot(formPermission), + acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, + successMessage: this.intl.t('developers.api-keys.index.edit-api-key-message'), + expirationOptions: this.expirationOptions, + testMode: this.currentUser.getOption('sandbox') || false, + apiKey, + formPermission, + setExpiration: ({ target }) => { + apiKey.expires_at = target.value || null; + }, + confirm: async (modal) => { + modal.startLoading(); + + if (this.abilities.cannot(formPermission)) { + return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); + } + + try { + await apiKey.save(); + this.notifications.success(modal.getOption('successMessage')); + return this.hostRouter.refresh(); + } catch (error) { + this.notifications.serverError(error); + modal.stopLoading(); + } + }, + ...options, + }); + } +} diff --git a/addon/services/webhook-actions.js b/addon/services/webhook-actions.js new file mode 100644 index 0000000..d15d7e2 --- /dev/null +++ b/addon/services/webhook-actions.js @@ -0,0 +1,185 @@ +import ResourceActionService from '@fleetbase/ember-core/services/resource-action'; +import { action } from '@ember/object'; +import groupApiEvents from '@fleetbase/ember-core/utils/group-api-events'; + +/** + * Webhook endpoint actions shared by the Developers console and other engines (for example Fleetbase AI). + */ +export default class WebhookActionsService extends ResourceActionService { + constructor() { + super(...arguments); + this.initialize('webhook-endpoint', { permissionPrefix: 'developers', mountPrefix: 'console.developers' }); + } + + transition = { + list: () => this.transitionTo('webhooks.index'), + }; + + modal = { + create: (...args) => this.createWebhook(...args), + edit: (...args) => this.editWebhook(...args), + }; + + /** + * Loads the event, version, and credential options the webhook form needs. + */ + async loadWebhookOptions() { + const [webhookEvents, apiVersions, apiCredentials] = await Promise.all([ + this.fetch.get('webhook-endpoints/events'), + this.fetch.get('webhook-endpoints/versions'), + this.store.query('api-credential', { limit: -1 }), + ]); + + return { webhookEvents, groupedApiEvents: groupApiEvents(webhookEvents), apiVersions, apiCredentials }; + } + + /** + * Opens the dialog to add a webhook endpoint + * + * @void + */ + @action createWebhook() { + const formPermission = 'developers create webhook'; + const webhook = this.store.createRecord('webhook-endpoint', { + events: [], + mode: this.currentUser.getOption('sandbox') ? 'test' : 'live', + }); + + this.editWebhook(webhook, { + title: this.intl.t('developers.webhooks.index.add-webhook'), + acceptButtonText: this.intl.t('developers.webhooks.index.add-webhook-button-text'), + acceptButtonIcon: 'check', + acceptButtonIconPrefix: 'fas', + acceptButtonDisabled: this.abilities.cannot(formPermission), + acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, + formPermission, + webhook, + confirm: async (modal) => { + modal.startLoading(); + + if (this.abilities.cannot(formPermission)) { + return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); + } + + try { + await webhook.save(); + this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message')); + return this.hostRouter.refresh(); + } catch (error) { + this.notifications.serverError(error); + modal.stopLoading(); + } + }, + }); + } + + /** + * Triggers dialog to edit webhook + * + * @param {WebhookEndpointModel} webhook + * @param {Object} options + * @void + */ + @action async editWebhook(webhook, options = {}) { + const { webhookEvents, groupedApiEvents, apiVersions, apiCredentials } = await this.loadWebhookOptions(); + + const formPermission = 'developers update webhook'; + this.modalsManager.show('modals/webhook-form', { + title: this.intl.t('developers.webhooks.index.edit-webhook-endpoint'), + acceptButtonText: this.intl.t('developers.webhooks.index.edit-webhook-endpoint-button-text'), + acceptButtonIcon: 'save', + acceptButtonDisabled: this.abilities.cannot(formPermission), + acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null, + formPermission, + declineButtonIcon: 'times', + declineButtonIconPrefix: 'fas', + eventOptions: groupedApiEvents, + versionOptions: apiVersions, + apiCredentialOptions: apiCredentials, + webhook, + setVersion: ({ target }) => { + webhook.version = target.value || null; + }, + setApiCredential: ({ target }) => { + webhook.api_credential_uuid = target.value || null; + }, + searchEvents: (query) => { + if (typeof query !== 'string') { + return; + } + const resources = Object.keys(groupedApiEvents); + const filteredEvents = {}; + resources.forEach((eventResource) => { + filteredEvents[eventResource] = groupedApiEvents[eventResource].filter((event) => { + return event.toLowerCase().includes(query.toLowerCase()); + }); + // if 0 events remove from filter + if (filteredEvents[eventResource].length === 0) { + delete filteredEvents[eventResource]; + } + }); + this.modalsManager.setOption('eventOptions', filteredEvents); + }, + addEvent: (event) => { + if (webhook.events.includes(event)) { + return; + } + + webhook.events.pushObject(event); + }, + removeEvent: (event) => { + webhook.events.removeObject(event); + }, + clearEvents: () => { + webhook.events.clear(); + }, + receiveAllEvents: () => { + webhook.events.pushObjects(webhookEvents); + }, + confirm: async (modal) => { + modal.startLoading(); + + if (this.abilities.cannot(formPermission)) { + return this.notifications.warning(this.intl.t('common.permissions-required-for-changes')); + } + + try { + await webhook.save(); + this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message')); + return this.hostRouter.refresh(); + } catch (error) { + this.notifications.serverError(error); + modal.stopLoading(); + } + }, + ...options, + }); + } + + /** + * Toggles dialog to delete webhook + * + * @param {WebhookEndpointModel} webhook + * @param {Object} options + * @void + */ + @action deleteWebhook(webhook, options = {}) { + this.modalsManager.confirm({ + title: this.intl.t('developers.webhooks.index.delete-webhook-endpoint'), + body: this.intl.t('developers.webhooks.index.delete-webhook-endpoint-body'), + confirm: async (modal) => { + modal.startLoading(); + + try { + await webhook.destroyRecord(); + this.notifications.success(this.intl.t('developers.webhooks.index.delete-webhook-success-message')); + return this.hostRouter.refresh(); + } catch (error) { + this.notifications.serverError(error); + modal.stopLoading(); + } + }, + ...options, + }); + } +} diff --git a/app/services/api-key-actions.js b/app/services/api-key-actions.js new file mode 100644 index 0000000..1be5bde --- /dev/null +++ b/app/services/api-key-actions.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/dev-engine/services/api-key-actions'; diff --git a/app/services/webhook-actions.js b/app/services/webhook-actions.js new file mode 100644 index 0000000..6cc10d7 --- /dev/null +++ b/app/services/webhook-actions.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/dev-engine/services/webhook-actions'; From eed79a5360ac29495dbf51523ec284e1e8efc5e9 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 21 Sep 2026 15:28:05 +0800 Subject: [PATCH 2/5] chore: open release v0.2.16 --- RELEASE.md | 5 ++--- package.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 7e6cf95..3d8f989 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,10 +1,9 @@ -> v0.2.15 ~ "API key expiry actually persists" +> v0.2.16 ~ "API key and webhook dialogs open from anywhere" --- ## Highlights -- **API key expiration works again.** Selecting an expiry in the developers console (`immediately`, `in 1 hour`, `in 24 hours`, …) silently saved `NULL` — Ember Data's `date` transform discarded the relative expiration strings before they reached the API. A new `expiration` transform passes them through for the server to resolve, so `expires_at` is persisted for every option. Pair with fleetbase/core-api#246 for `immediately` to revoke a key reliably at the boundary instant. ([#43](https://github.com/fleetbase/dev-engine/pull/43)) -- **The engine's test suite is runnable.** `ember test` previously crashed before executing a single test; the engine now eager-loads for its own test runs (hosts still get the lazy engine), and regression tests cover the expiration serialization path. +- **API key and webhook dialogs are reusable services.** New `api-key-actions` and `webhook-actions` services hold the create, edit and delete dialogs that lived in the index controllers, so other engines can open them — Fleetbase AI uses this to open **New API Key** and **New Webhook** from its confirmation cards. The Developers pages delegate to the same services, so they behave as before. ([#46](https://github.com/fleetbase/dev-engine/pull/46)) --- ## Need help? diff --git a/package.json b/package.json index da7e226..795ca6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/dev-engine", - "version": "0.2.15", + "version": "0.2.16", "description": "Fleetbase Developers extension provides a module for managing developer resources such as API keys, webhooks, sockets, events and logs.", "fleetbase": { "route": "developers" From 5984425f32b30e2fbdaae48d735290424c7b2bb2 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 21 Sep 2026 15:33:31 +0800 Subject: [PATCH 3/5] ci: run checks on pull requests into release branches Feature pull requests now target a release branch rather than main, but CI only ran on pull requests into main, so they merged unchecked. Match fleetops, which already runs on release/v* and the legacy dev-v* branches. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa2f721..3c3554a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: tags: - 'v*' pull_request: - branches: [ main ] + branches: [ main, 'release/v*', 'dev-v*' ] env: NODE_VERSION: 22.x From 5d23a1592a717c59f0104021be4c02120fc372f5 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 21 Sep 2026 16:08:49 +0800 Subject: [PATCH 4/5] chore(deps): upgrade @fleetbase/ember-core and @fleetbase/ember-ui to latest ember-core ^0.3.24 and ember-ui ^0.4.2, the latest published versions. --- package.json | 4 +- pnpm-lock.yaml | 103 +++++++++++++++++++++---------------------------- 2 files changed, 45 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 795ca6e..fd4e9fa 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ }, "dependencies": { "@babel/core": "^7.23.2", - "@fleetbase/ember-core": "^0.3.22", - "@fleetbase/ember-ui": "^0.3.34", + "@fleetbase/ember-core": "^0.3.24", + "@fleetbase/ember-ui": "^0.4.2", "@fortawesome/ember-fontawesome": "^2.0.0", "@fortawesome/fontawesome-svg-core": "6.4.0", "@fortawesome/free-brands-svg-icons": "6.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ce9537..b821564 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,11 +12,11 @@ importers: specifier: ^7.23.2 version: 7.28.5 '@fleetbase/ember-core': - specifier: ^0.3.22 - version: 0.3.22(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(eslint@8.57.1)(webpack@5.103.0) + specifier: ^0.3.24 + version: 0.3.24(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(eslint@8.57.1)(webpack@5.103.0) '@fleetbase/ember-ui': - specifier: ^0.3.34 - version: 0.3.34(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(postcss@8.5.6)(rollup@2.79.2)(tracked-built-ins@3.4.0(@babel/core@7.28.5))(webpack@5.103.0) + specifier: ^0.4.2 + version: 0.4.2(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(postcss@8.5.6)(rollup@2.79.2)(tracked-built-ins@3.4.0(@babel/core@7.28.5))(webpack@5.103.0) '@fortawesome/ember-fontawesome': specifier: ^2.0.0 version: 2.0.0(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(rollup@2.79.2)(webpack@5.103.0) @@ -1272,12 +1272,12 @@ packages: peerDependencies: ember-source: '>= 4.0.0' - '@fleetbase/ember-core@0.3.22': - resolution: {integrity: sha512-tCYgxJoemUXgjsUztzeJZSwU2ejDp5x2WYI3FsBO55AlcC+mfWm0FsYtuPd9xd9PoO1jZ3T3VyvQQ06HRPtqWw==} + '@fleetbase/ember-core@0.3.24': + resolution: {integrity: sha512-WG32JlX4S75ofa34RQEMxFEqc20fTv2Qn3A5+NlqXtL0lfnCthdO+a1DrGqIIierthHl3mVTxhe+z63f8sM6EA==} engines: {node: '>= 18'} - '@fleetbase/ember-ui@0.3.34': - resolution: {integrity: sha512-l67lrbpeh0JRLDHr1sJ3QnxP6vPKwVW614CVWEASs6ZImGCBr6CK3DjsT3h+1uslQa51dpixN/stiQ+C/Z1etA==} + '@fleetbase/ember-ui@0.4.2': + resolution: {integrity: sha512-jRpu9fYIKis9QDvOr6Ih2zPbIrGhHa+f8tLzKJCl4bFtqtYMGlr0XNW/ckp4VLmoPmWPwJHmVbtvmwLeVoEmhQ==} engines: {node: '>= 18'} '@fleetbase/intl-lint@0.0.1': @@ -2066,11 +2066,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.17.0: resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} engines: {node: '>=0.4.0'} @@ -3528,9 +3523,6 @@ packages: decorator-transforms@1.2.1: resolution: {integrity: sha512-UUtmyfdlHvYoX3VSG1w5rbvBQ2r5TX1JsE4hmKU9snleFymadA3VACjl6SRfi9YgBCSjBbfQvR1bs9PRW9yBKw==} - decorator-transforms@2.3.0: - resolution: {integrity: sha512-jo8c1ss9yFPudHuYYcrJ9jpkDZIoi+lOGvt+Uyp9B+dz32i50icRMx9Bfa8hEt7TnX1FyKWKkjV+cUdT/ep2kA==} - decorator-transforms@2.3.2: resolution: {integrity: sha512-XcErcjlmCzG5ODgYjt6ZTXwd6S8fPKln/sJmw15ZXkWG2JpoQNwszis+AwF6XSGlOoG7g8MCEO97g+Yw3fk5OQ==} @@ -9935,7 +9927,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@fleetbase/ember-core@0.3.22(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(eslint@8.57.1)(webpack@5.103.0)': + '@fleetbase/ember-core@0.3.24(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(eslint@8.57.1)(webpack@5.103.0)': dependencies: '@babel/core': 7.28.5 compress-json: 3.4.0 @@ -9968,7 +9960,7 @@ snapshots: - utf-8-validate - webpack - '@fleetbase/ember-ui@0.3.34(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(postcss@8.5.6)(rollup@2.79.2)(tracked-built-ins@3.4.0(@babel/core@7.28.5))(webpack@5.103.0)': + '@fleetbase/ember-ui@0.4.2(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(postcss@8.5.6)(rollup@2.79.2)(tracked-built-ins@3.4.0(@babel/core@7.28.5))(webpack@5.103.0)': dependencies: '@babel/core': 7.28.5 '@ember/render-modifiers': 2.1.0(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) @@ -11091,8 +11083,6 @@ snapshots: acorn@6.4.2: {} - acorn@8.15.0: {} - acorn@8.17.0: {} ag-channel@5.0.0: @@ -11878,7 +11868,7 @@ snapshots: fast-ordered-set: 1.0.3 fs-tree-diff: 0.5.9 heimdalljs: 0.2.6 - minimatch: 3.1.2 + minimatch: 3.1.5 mkdirp: 0.5.6 path-posix: 1.0.0 rimraf: 2.7.1 @@ -12193,7 +12183,7 @@ snapshots: broccoli-string-replace@0.1.2: dependencies: broccoli-persistent-filter: 1.4.6 - minimatch: 3.1.2 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -12940,18 +12930,11 @@ snapshots: decorator-transforms@1.2.1(@babel/core@7.28.5): dependencies: - '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.28.5) babel-import-util: 2.1.1 transitivePeerDependencies: - '@babel/core' - decorator-transforms@2.3.0(@babel/core@7.28.5): - dependencies: - '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.28.5) - babel-import-util: 3.0.1 - transitivePeerDependencies: - - '@babel/core' - decorator-transforms@2.3.2(@babel/core@7.28.5): dependencies: '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.28.5) @@ -13096,7 +13079,7 @@ snapshots: ember-animated@1.1.4(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 '@embroider/macros': 1.19.5 '@embroider/util': 1.13.5(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) assert-never: 1.4.0 @@ -13129,7 +13112,7 @@ snapshots: ember-assign-helper@0.5.1: dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 transitivePeerDependencies: - supports-color @@ -13157,11 +13140,11 @@ snapshots: fs-tree-diff: 2.0.1 handlebars: 4.7.8 js-string-escape: 1.0.1 - lodash: 4.17.21 + lodash: 4.18.1 mkdirp: 0.5.6 resolve-package-path: 3.1.0 rimraf: 2.7.1 - semver: 7.7.3 + semver: 7.8.4 symlink-or-copy: 1.3.1 typescript-memoize: 1.1.1 walk-sync: 0.3.4 @@ -13219,12 +13202,12 @@ snapshots: dependencies: '@babel/core': 7.28.5 '@ember/test-helpers': 3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0) - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 '@embroider/macros': 1.19.5 '@embroider/util': 1.13.5(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) '@glimmer/component': 1.1.2(@babel/core@7.28.5) '@glimmer/tracking': 1.1.2 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-element-helper: 0.8.8 ember-lifeline: 7.0.0(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0)) ember-modifier: 4.2.2(@babel/core@7.28.5) @@ -13264,8 +13247,8 @@ snapshots: ember-can@6.0.0(@babel/core@7.28.5)(@ember/string@3.1.1)(ember-inflector@4.0.3(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-resolver@11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: '@ember/string': 3.1.1 - '@embroider/addon-shim': 1.10.2 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + '@embroider/addon-shim': 1.10.3 + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-inflector: 4.0.3(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) ember-resolver: 11.0.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) @@ -13459,8 +13442,8 @@ snapshots: ember-cli-notifications@9.1.0(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + '@embroider/addon-shim': 1.10.3 + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) transitivePeerDependencies: - '@babel/core' @@ -13806,7 +13789,7 @@ snapshots: ember-concurrency-async@1.0.0(ember-concurrency@2.3.7(@babel/core@7.28.5)): dependencies: - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.29.7 '@babel/types': 7.28.5 ember-cli-babel: 7.26.11 ember-cli-babel-plugin-helpers: 1.1.1 @@ -13825,7 +13808,7 @@ snapshots: ember-concurrency@2.3.7(@babel/core@7.28.5): dependencies: - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.29.7 '@babel/types': 7.28.5 '@glimmer/tracking': 1.1.2 ember-cli-babel: 7.26.11 @@ -13840,9 +13823,9 @@ snapshots: ember-concurrency@4.0.6(@babel/core@7.28.5): dependencies: '@babel/helper-module-imports': 7.27.1 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.29.7 '@babel/types': 7.28.5 - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 decorator-transforms: 1.2.1(@babel/core@7.28.5) transitivePeerDependencies: - '@babel/core' @@ -13850,7 +13833,7 @@ snapshots: ember-cookies@1.3.0(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) transitivePeerDependencies: - supports-color @@ -13934,7 +13917,7 @@ snapshots: ember-element-helper@0.8.8: dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 transitivePeerDependencies: - supports-color @@ -13968,7 +13951,7 @@ snapshots: dependencies: '@ember/test-helpers': 3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0) '@ember/test-waiters': 3.1.0 - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 '@embroider/macros': 1.19.5 '@glimmer/component': 1.1.2(@babel/core@7.28.5) '@glimmer/tracking': 1.1.2 @@ -13982,7 +13965,7 @@ snapshots: ember-focus-trap@1.1.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) focus-trap: 6.9.4 transitivePeerDependencies: @@ -14087,7 +14070,7 @@ snapshots: ember-lifeline@7.0.0(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 optionalDependencies: '@ember/test-helpers': 3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0) transitivePeerDependencies: @@ -14130,7 +14113,7 @@ snapshots: ember-math-helpers@4.2.1(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) transitivePeerDependencies: - supports-color @@ -14157,8 +14140,8 @@ snapshots: ember-modifier@4.2.2(@babel/core@7.28.5): dependencies: - '@embroider/addon-shim': 1.10.2 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + '@embroider/addon-shim': 1.10.3 + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-cli-normalize-entity-name: 1.0.0 ember-cli-string-utils: 1.1.0 transitivePeerDependencies: @@ -14199,11 +14182,11 @@ snapshots: ember-power-select@8.6.2(@babel/core@7.28.5)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-basic-dropdown@8.4.0(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)))(ember-concurrency@4.0.6(@babel/core@7.28.5))(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: '@ember/test-helpers': 3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0) - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 '@embroider/util': 1.13.5(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) '@glimmer/component': 1.1.2(@babel/core@7.28.5) '@glimmer/tracking': 1.1.2 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-assign-helper: 0.5.1 ember-basic-dropdown: 8.4.0(@ember/string@3.1.1)(@ember/test-helpers@3.3.1(@babel/core@7.28.5)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0))(webpack@5.103.0))(@glimmer/component@1.1.2(@babel/core@7.28.5))(@glimmer/tracking@1.1.2)(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) ember-concurrency: 4.0.6(@babel/core@7.28.5) @@ -14290,7 +14273,7 @@ snapshots: dependencies: '@babel/eslint-parser': 7.28.5(@babel/core@7.28.5)(eslint@8.57.1) '@ember/test-waiters': 3.1.0 - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 '@embroider/macros': 1.19.5 ember-cli-is-package-missing: 1.0.0 ember-cookies: 1.3.0(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) @@ -14380,9 +14363,9 @@ snapshots: ember-style-modifier@4.5.1(@babel/core@7.28.5)(@ember/string@3.1.1): dependencies: '@ember/string': 3.1.1 - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 csstype: 3.2.3 - decorator-transforms: 2.3.0(@babel/core@7.28.5) + decorator-transforms: 2.3.2(@babel/core@7.28.5) ember-modifier: 4.2.2(@babel/core@7.28.5) transitivePeerDependencies: - '@babel/core' @@ -14470,7 +14453,7 @@ snapshots: ember-truth-helpers@4.0.3(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)): dependencies: - '@embroider/addon-shim': 1.10.2 + '@embroider/addon-shim': 1.10.3 ember-functions-as-helper-polyfill: 2.1.3(ember-source@5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0)) ember-source: 5.4.1(@babel/core@7.28.5)(@glimmer/component@1.1.2(@babel/core@7.28.5))(rsvp@4.8.5)(webpack@5.103.0) transitivePeerDependencies: @@ -16520,7 +16503,7 @@ snapshots: md5.js@1.3.5: dependencies: - hash-base: 3.0.5 + hash-base: 3.1.2 inherits: 2.0.4 safe-buffer: 5.2.1 @@ -18872,7 +18855,7 @@ snapshots: terser@4.8.1: dependencies: - acorn: 8.15.0 + acorn: 8.17.0 commander: 2.20.3 source-map: 0.6.1 source-map-support: 0.5.21 From 8442cf2cbd57faea363a945bd08b736a8bef81e2 Mon Sep 17 00:00:00 2001 From: ispdomnet <95652995+ispdomnet@users.noreply.github.com> Date: Tue, 22 Sep 2026 09:37:23 +0300 Subject: [PATCH 5/5] Add Ukrainian translation --- translations/uk-ua.yaml | 285 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 translations/uk-ua.yaml diff --git a/translations/uk-ua.yaml b/translations/uk-ua.yaml new file mode 100644 index 0000000..7e7177d --- /dev/null +++ b/translations/uk-ua.yaml @@ -0,0 +1,285 @@ +developers: + extension-name: Розробникам + common: + all: Усі + attempt: Спроба + back: Назад + bulk-action: Масова дія + clear: Очистити + code: Код + created: Створено + date: Дата + description: Опис + email: Електронна пошта + event-id: ID події + event-type: Тип події + event: Подія + export: Експорт + failed: Помилка + id: ID + key: Ключ + mode: Режим + name: Назва + new: Новий + password: Пароль + result: Результат + source: Джерело + status: Статус + succeeded: Успішно + time: Час + url: URL + version: Версія + reload: Перезавантажити + reload-data: Оновити дані + + component: + api-event: + data: + title: Дані події + no-data: Немає даних події + details: + prefixTitle: Подія + api-request-log: + details: + prefixTitle: Запит + duration: Тривалість + ip-address: IP-адреса + query-params: + title: Параметри запиту (query) + no-parameters: Немає параметрів запиту + request-headers: + title: Заголовки запиту + no-headers: Немає заголовків запиту + request-body: + title: Запит + title-second-part: тіло + no-request-body: Немає тіла {method} запиту + response-body: + title: Тіло відповіді + no-response-body: Немає тіла відповіді + modals: + api-key-form: + api-name-aria-label: Назва ключа API + api-expiration-aria-label: Дата закінчення терміну дії ключа API + name-placeholder: Введіть псевдонім або назву середовища для ключа API + expiration-label: Термін дії + expiration-help-text: Додатково встановити дату закінчення терміну дії для цього ключа API. + select-expiration-date: Виберіть дату закінчення терміну... + key-expires: Після закінчення терміну дії ключа ви не зможете виконувати з ним жодних дій. + enter-domain-placeholder: Введіть домен + allowed-browser-label: Дозволені джерела браузера (CORS) + allowed-browser-help-text: Введіть домени, які визначатимуть політику CORS для браузерних запитів з цього ключа API. + test-key: Тестовий ключ + testing-environments: Ви створюєте ключ для тестового середовища, використовуйте його для тестових оточень. + live-key: Бойовий ключ + production-environments: Ви створюєте ключ для робочого середовища, використовуйте його для продакшену. + listen-custom-channel: + name: ID каналу подій + name-help-text: Введіть ідентифікатор сокет-каналу, який ви хочете прослуховувати + rename-api-key-form: + api-key-label: Назва ключа API + api-key-placeholder: Введіть псевдонім або назву середовища для ключа API + roll-api-key-form: + view-button-text: Переглянути логи + last-used: Востаннє використано + expiration: Термін дії + api-key-expiration-label: Термін дії ключа API + select-date: Виберіть дату закінчення терміну... + key-expires: Після закінчення терміну дії ключа ви не зможете виконувати з ним жодних дій. + additional-required: Потрібна додаткова автентифікація + enter-password: Щоб продовжити, будь ласка, введіть свій пароль. + user-email: Email користувача + user-password: Пароль користувача + user-password-placeholder: Підтвердьте запит за допомогою пароля + webhook-form: + endpoint-url: URL-адреса кінцевої точки (Endpoint URL) + endpoint-url-help-text: URL, на який Fleetbase має надсилати зворотні виклики (callbacks) подій. + endpoint-url-placeholder: https:// + description-label: Опис + description-help-text: Необов'язково додайте опис для кінцевої точки вебхука. + description-aria-label: Опис вебхука + description-placeholder: Додатковий опис того, для чого використовується ця кінцева точка вебхука. + api-credential-label: Ключ API (API Credential) + api-credential-help-text: Обмежити кінцеву точку вебхука отриманням викликів лише від конкретного ключа API. + api-credential-message: Отримувати від усіх ключів API... + api-credential-infoblock: Ви можете вибрати конкретний ключ API, який використовуватиметься для запуску викликів на цю кінцеву точку, або вибрати "Усі ключі API", і вебхук отримуватиме виклики незалежно від використовуваного ключа API. + version-help-text: Виберіть конкретну версію API для отримання зворотних викликів. + version-message: Виберіть версію API... + events-send-label: Події для надсилання + events-send-help-text: Явно вкажіть, для яких подій отримувати зворотні виклики. + select-events: Виберіть події... + event-search-label: Пошук подій + event-search-placeholder: Пошук... + no-selected: Не вибрано жодної події + dropdown: Шукайте події за допомогою випадаючого списку вище, або + all-events: отримувати всі події + webhook: + attempts: + copy-event-id: Копіювати ID події в буфер обміну + view-event: Переглянути подію + info-message: ID події скопійовано в буфер обміну. + webhook-header: Спроби вебхука + webhook-message: Спроби надіслати подію на вашу кінцеву точку за останні 15 днів + http-code: Код статусу HTTP + response-time: Час відповіді + request-endpoint: Запит до вашої кінцевої точки + no-request-body: Немає тіла запиту + response: Відповідь + no-response-body: Немає тіла відповіді + details: + webhook-details: Деталі вебхука + update-details: Оновити деталі... + event-types: Типи подій + help-text: Ви отримуватимете вебхуки для нових типів подій у міру їх додавання, за винятком тих, які вимагають явного вибору. Прослуховування всіх типів подій зазвичай не потрібне і може збільшити навантаження на ваші сервери. + all-events: Усі події + api-credential: Ключ API + help-text-event: Ви отримуватимете виклики вебхуків незалежно від того, який ключ API використовується для активації події. + api-credentials: Отримання від усіх ключів API + metrics: + date-created: Дата створення + widget: + dashboard: + name: Панель розробника + period: 30д + empty: Немає доступних даних + kpi: + api-requests: Запити API + api-error-rate: Рівень помилок API + api-latency: Ср. затримка API + webhook-success: Успішність вебхуків + active-api-keys: Активні ключі API + active-webhooks: Активні вебхуки + webhook-failures: Збої вебхуків + events-emitted: Відправлено подій + api-traffic: + title: Трафік API + subtitle: Обсяг запитів, успіхи та помилки + webhook-delivery: + title: Стан доставки вебхуків + subtitle: Обсяг доставки, повторні спроби та збої + endpoint-health: + title: Стан кінцевих точок + subtitle: Надійність кінцевих точок вебхуків за останній час + event-stream: + title: Потік подій + subtitle: Популярні типи подій та джерела + types: Типи подій + sources: Джерела + developer-activity: + title: Активність розробника + subtitle: Останні логи, вебхуки та події + quick-resources: + title: Швидкі ресурси + subtitle: Швидкий перехід до інструментів розробника + api-metrics: + title: Моніторинг + api-requests: Запити API + api-error: Розподіл помилок API + webhooks: Вебхуки + webhooks-response: Час відповіді вебхуків + success-label: успішно + error-label: помилка + get-error: Помилка GET + post-error: Помилка POST + put-error: Помилка PUT + delete-error: Помилка DELETE + duration-ms: Тривалість (мс) + api-keys: + index: + public-key: Публічний ключ + secret-key: Секретний ключ + enviroment: Середовище + expiry: Завершення терміну + last-used: Останнє використання + edit-key: Редагувати ключ... + roll-key: Оновити (roll) ключ... + view-logs: Переглянути логи запитів... + delete-key: Видалити ключ... + new-api-key-title: Новий ключ API + new-api-key-message: Нові ключі API створено. + edit-api-key-title: Редагувати ключ API + edit-api-key-message: Зміни ключа API збережено. + rename-api-key-title: Перейменувати ключ API {apiKeyName} + untitled: Без назви + rename-api-key-success-message: Ключ API перейменовано на {apiKeyName} + delete-api-key-title: Видалити ключ API {apiKeyName} + delete-api-key-body: Ви впевнені, що хочете видалити цей ключ API? Усі ваші дані, пов'язані з цим ключем API, стануть недоступними. Цю дію неможливо скасувати. + delete-api-key-success-message: Ключ API {apiKeyName} видалено. + delete-accept-button-text: Видалити ключ API + roll-api-key: Перевипустити (roll) ключ API {apiKeyName} + roll-api-key-button-text: Перевипустити ключ API + roll-api-key-success-message: Ключ API {apiKeyName} успішно перевипущено. + roll-api-key-error-message: Не вдалося перевипустити ключ API. + export-api: Експортувати ключі API + export-api-accept-button-text: Завантажити + export-api-error-message: Не вдалося завантажити експорт ключів API. + title: Ключі API + label: Перегляд тестових даних + help-text: Увімкнення перегляду тестових даних дозволить консолі відображати всі тестові дані з вашого пісочничного середовища (sandbox) + select-api-key-aria-label: Вибрати ключ API + select-key: Вибрати конкретний ключ + test-data: Усі тестові дані... + delete-api: Видалити ключі API + events: + index: + title: Події + logs: + index: + api-credential: Ключ API + http-method: Метод HTTP + title: Логи + sockets: + index: + link-text: Відстежувати канал + channel: Канал + listen-channel-title: Прослуховувати власний канал + listen-channel-button-text: Прослуховувати + title: Канали, що отримують події з вашого облікового запису + button-text: Прослуховувати власний канал + view: + socket-connection-error: Помилка підключення до сокета! + socket-connected: Сокет підключено + socket-subscribed: Сокет підписано на канал {modelName} + output: Вивід + awaiting-events: Очікування подій... + webhooks: + index: + view-logs: Переглянути логи + edit-webhook: Редагувати вебхук + delete-webhook: Видалити вебхук + add-webhook: Додати кінцеву точку вебхука + add-webhook-button-text: Підтвердити та створити + edit-webhook-endpoint: Редагувати кінцеву точку вебхука + edit-webhook-endpoint-button-text: Зберегти зміни + new-webhook-success-message: Новий вебхук створено. + delete-webhook-endpoint: Видалити цю кінцеву точку вебхука + delete-webhook-endpoint-body: Ви впевнені, що хочете видалити цей вебхук? Усі ваші дані, пов'язані з цим вебхуком, стануть недоступними. Ця кінцева точка також припинить отримувати майбутні події. Цю дію неможливо скасувати. + delete-webhook-success-message: Кінцеву точку вебхука видалено. + title: Вебхуки + button-text: Додати нову кінцеву точку + view: + webhook-deleted-success-message: Кінцеву точку вебхука видалено. + disable-webhook-title: Вимкнути кінцеву точку вебхука + disable-webhook-body: Цю кінцеву точку вебхука можна тимчасово вимкнути, щоб вона не отримувала сповіщення, доки її знову не буде ввімкнено. Fleetbase не повторюватиме спроби надсилання сповіщень, згенерованих під час вимкнення кінцевої точки. + disable-webhook-button-text: Вимкнути кінцеву точку вебхука + disable-webhook-success-message: Вебхук вимкнено. + enable-webhook-title: Увімкнути кінцеву точку вебхука + enable-webhook-body: Цей вебхук вимкнено, і він більше не отримує сповіщень. Це могло статися автоматично через тривалий період помилок. Якщо ви усунули проблему, ви можете повторно ввімкнути кінцеву точку вебхука тут. Fleetbase не повторюватиме спроби надсилання сповіщень, які були згенеровані у проміжок часу, і якщо ми продовжимо фіксувати помилки на цій кінцевій точці, ми вимкнемо її знову. + enable-webhook-button-text: Увімкнути кінцеву точку вебхука + enable-webhook-success-message: Вебхук увімкнено. + update-endpoint-button-text: Оновити кінцеву точку + update-endpoint-success-message: Деталі вебхука оновлено. + send-button-text: Надіслати тестовий вебхук... + disable-button-text: Вимкнути... + enable-button-text: Увімкнути... + delete-button-text: Видалити... + application: + sidebar: + title: Консоль розробника + items: + home: Панель керування + api-keys: Ключі API + webhooks: Вебхуки + websockets: WebSockets + logs: Логи + events: Події \ No newline at end of file