From 27652db9c31ef30c23796233d7c97f730399e11b Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Sun, 7 Dec 2025 14:15:31 +0800 Subject: [PATCH] Organizations can now set their own alpha-numeric sender ID for SMS --- RELEASE.md | 68 ++------------- api/composer.json | 2 +- api/composer.lock | 42 ++++----- .../app/components/dashboard/widget-panel.hbs | 31 ------- .../app/components/dashboard/widget-panel.js | 60 ------------- .../console/settings/notifications.js | 87 +++++++++++++------ console/app/models/company.js | 2 +- .../routes/console/settings/notifications.js | 4 +- .../console/settings/notifications.hbs | 17 +++- console/package.json | 2 +- .../components/dashboard/widget-panel-test.js | 26 ------ docker/Dockerfile | 2 +- packages/core-api | 2 +- 13 files changed, 113 insertions(+), 232 deletions(-) delete mode 100644 console/app/components/dashboard/widget-panel.hbs delete mode 100644 console/app/components/dashboard/widget-panel.js delete mode 100644 console/tests/integration/components/dashboard/widget-panel-test.js diff --git a/RELEASE.md b/RELEASE.md index 7ecfedb4..016e427c 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,40 +1,24 @@ -# πŸš€ Fleetbase v0.7.21 β€” 2025-12-06 +# πŸš€ Fleetbase v0.7.22 β€” 2025-12-07 -> "5x faster css compiling and flawless builds." +> "Organizations can now set their own alpha-numeric sender ID for SMS" --- ## ✨ Highlights - -### πŸ”§ Critical Production Build Fix - -This release resolves a **critical issue** that prevented production builds from succeeding when using ember-ui in Ember Engines environments. All Fleetbase applications and engines should upgrade immediately. - -**What was broken:** -Production builds were failing with "Broken @import declaration" errors during CSS minification. Development builds worked fine, but production deployments were completely blocked. - -**What we fixed:** -Implemented a proper architectural solution that prevents Ember Engines from attempting to recompile ember-ui styles. The addon now correctly detects when it's being included by an engine and blocks both the style tree distribution and PostCSS configuration override. - -**The impact:** -- βœ… **Production builds now succeed** without CSS import errors -- βœ… **5x faster builds** β€” CSS is compiled once in the host app instead of being reprocessed by each engine -- βœ… **4x smaller bundles** β€” Eliminated CSS duplication across engine vendor files (reduced from ~3MB to ~750KB in typical setups) -- βœ… **Consistent styling** β€” All engines now use the same compiled CSS from the host application - -**Technical details:** -The fix adds engine detection to both the `treeForStyles` and `included` hooks, ensuring that ember-ui styles are compiled exclusively in the host application and inherited by all engines. This follows the proper Ember Engines architecture pattern for shared addon styles. +- **Custom Alphanumeric Sender ID for SMS:** + Organizations can now configure their own **Alphanumeric Sender ID** used when sending verification codes and other SMS notifications. + This feature improves brand recognition, enhances trust, and aligns outbound communication with each organization’s identity. + Supported in regions/carriers where alphanumeric senders are allowed (e.g., Mongolia and others). --- ## ⚠️ Breaking Changes -- None β€” This is a fully backward-compatible patch that only changes internal build behavior +- None πŸ™‚ --- ## πŸ”§ Upgrade Steps -### For System ```bash # Pull latest version git pull origin main --no-rebase @@ -47,44 +31,6 @@ docker compose down && docker compose up -d docker compose exec application bash -c "./deploy.sh" ``` -### For Extension Developers -```bash -# Update ember-ui -pnpm upgrade @fleetbase/ember-ui@^0.3.14 @fleetbase/ember-core@^0.3.8 - -# Reinstall dependencies -pnpm install -``` - -### Verification -```bash -# Verify production build succeeds -pnpm build --environment production - -# Check bundle sizes (should see significant reduction) -ls -lh dist/assets/vendor*.css -ls -lh dist/engines-dist/*/assets/engine-vendor*.css -``` - ---- - -## πŸ“¦ What Changed - -### Fixed -- **Critical**: Production build failures in Ember Engines environments with "Broken @import declaration" errors -- CSS duplication across engine bundles causing bloated file sizes -- PostCSS configuration conflicts between host app and engines - -### Changed -- Added `treeForStyles` hook with engine detection to prevent style tree distribution to engines -- Added engine detection guard in `included` hook to prevent `postcssOptions` override -- Improved CSS import path resolution in PostCSS configuration - -### Performance -- Reduced build time by 5x through single CSS compilation -- Reduced total CSS bundle size by 4x through elimination of duplication -- Improved caching efficiency with shared vendor.css - --- ## Need help? diff --git a/api/composer.json b/api/composer.json index 24a57d62..9e24edca 100644 --- a/api/composer.json +++ b/api/composer.json @@ -20,7 +20,7 @@ "require": { "php": ">=8.0 <=8.2.28", "appstract/laravel-opcache": "^4.0", - "fleetbase/core-api": "^1.6.27", + "fleetbase/core-api": "^1.6.28", "fleetbase/fleetops-api": "^0.6.29", "fleetbase/registry-bridge": "^0.1.2", "fleetbase/storefront-api": "^0.4.9", diff --git a/api/composer.lock b/api/composer.lock index 088617b5..4e21641b 100644 --- a/api/composer.lock +++ b/api/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2917c30c56c080bdb6a6bf6adbde7a1", + "content-hash": "357a3d180da0e49157a3d7057c279056", "packages": [ { "name": "appstract/laravel-opcache", @@ -2157,16 +2157,16 @@ }, { "name": "fleetbase/core-api", - "version": "1.6.27", + "version": "1.6.28", "source": { "type": "git", "url": "https://github.com/fleetbase/core-api.git", - "reference": "831600c1818cbe76cfe280bfaaa3896ff1e2c597" + "reference": "d964db3f4264f0a261364ce0c655f8aa561aeb84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fleetbase/core-api/zipball/831600c1818cbe76cfe280bfaaa3896ff1e2c597", - "reference": "831600c1818cbe76cfe280bfaaa3896ff1e2c597", + "url": "https://api.github.com/repos/fleetbase/core-api/zipball/d964db3f4264f0a261364ce0c655f8aa561aeb84", + "reference": "d964db3f4264f0a261364ce0c655f8aa561aeb84", "shasum": "" }, "require": { @@ -2252,9 +2252,9 @@ ], "support": { "issues": "https://github.com/fleetbase/core-api/issues", - "source": "https://github.com/fleetbase/core-api/tree/v1.6.27" + "source": "https://github.com/fleetbase/core-api/tree/v1.6.28" }, - "time": "2025-12-05T11:24:12+00:00" + "time": "2025-12-07T06:10:01+00:00" }, { "name": "fleetbase/countries", @@ -7755,16 +7755,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.6.2", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "3a454ca033b9e06b63282ce19562e892747449bb" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", - "reference": "3a454ca033b9e06b63282ce19562e892747449bb", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -7807,9 +7807,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-10-21T19:32:17+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "nunomaduro/termwind", @@ -10041,16 +10041,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.15", + "version": "v0.12.16", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "38953bc71491c838fcb6ebcbdc41ab7483cd549c" + "reference": "ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/38953bc71491c838fcb6ebcbdc41ab7483cd549c", - "reference": "38953bc71491c838fcb6ebcbdc41ab7483cd549c", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67", + "reference": "ee6d5028be4774f56c6c2c85ec4e6bc9acfe6b67", "shasum": "" }, "require": { @@ -10058,8 +10058,8 @@ "ext-tokenizer": "*", "nikic/php-parser": "^5.0 || ^4.0", "php": "^8.0 || ^7.4", - "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + "symfony/console": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^8.0 || ^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" @@ -10114,9 +10114,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.15" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.16" }, - "time": "2025-11-28T00:00:14+00:00" + "time": "2025-12-07T03:39:01+00:00" }, { "name": "ralouphie/getallheaders", diff --git a/console/app/components/dashboard/widget-panel.hbs b/console/app/components/dashboard/widget-panel.hbs deleted file mode 100644 index e6e7969c..00000000 --- a/console/app/components/dashboard/widget-panel.hbs +++ /dev/null @@ -1,31 +0,0 @@ - - -
-
-
- - -
- {{#each this.availableWidgets as |widget|}} -
-
-
- -
-

- {{t "component.dashboard-widget-panel.widget-name" widgetName=widget.name}} -

-
-
-

{{widget.description}}

-
-
- {{/each}} -
- -
-
\ No newline at end of file diff --git a/console/app/components/dashboard/widget-panel.js b/console/app/components/dashboard/widget-panel.js deleted file mode 100644 index 32afd371..00000000 --- a/console/app/components/dashboard/widget-panel.js +++ /dev/null @@ -1,60 +0,0 @@ -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; -import { inject as service } from '@ember/service'; -import { action } from '@ember/object'; - -export default class DashboardWidgetPanelComponent extends Component { - @service universe; - @tracked availableWidgets = []; - @tracked dashboard; - @tracked isOpen = true; - @service notifications; - - /** - * Constructs the component and applies initial state. - */ - constructor(owner, { dashboard }) { - super(...arguments); - - this.availableWidgets = this.universe.getDashboardWidgets(); - this.dashboard = dashboard; - } - - /** - * Sets the overlay context. - * - * @action - * @param {OverlayContextObject} overlayContext - */ - @action setOverlayContext(overlayContext) { - this.context = overlayContext; - - if (typeof this.args.onLoad === 'function') { - this.args.onLoad(...arguments); - } - } - - @action addWidgetToDashboard(widget) { - // If widget is a component definition/class - if (typeof widget.component === 'function') { - widget.component = widget.component.name; - } - - this.args.dashboard.addWidget(widget).catch((error) => { - this.notifications.serverError(error); - }); - } - - /** - * Handles cancel button press. - * - * @action - */ - @action onPressClose() { - this.isOpen = false; - - if (typeof this.args.onClose === 'function') { - this.args.onClose(); - } - } -} diff --git a/console/app/controllers/console/settings/notifications.js b/console/app/controllers/console/settings/notifications.js index f070e4ff..6957d351 100644 --- a/console/app/controllers/console/settings/notifications.js +++ b/console/app/controllers/console/settings/notifications.js @@ -6,35 +6,13 @@ import createNotificationKey from '@fleetbase/ember-core/utils/create-notificati import { task } from 'ember-concurrency'; export default class ConsoleSettingsNotificationsController extends Controller { - /** - * Inject the notifications service. - * - * @memberof ConsoleSettingsNotificationsController - */ @service notifications; - - /** - * Inject the fetch service. - * - * @memberof ConsoleSettingsNotificationsController - */ @service fetch; - - /** - * The notification settings value JSON. - * - * @memberof ConsoleSettingsNotificationsController - * @var {Object} - */ + @service store; + @service currentUser; @tracked notificationSettings = {}; - - /** - * Notification transport methods enabled. - * - * @memberof ConsoleSettingsNotificationsController - * @var {Array} - */ @tracked notificationTransportMethods = ['email', 'sms']; + @tracked company; /** * Creates an instance of ConsoleSettingsNotificationsController. @@ -45,6 +23,40 @@ export default class ConsoleSettingsNotificationsController extends Controller { this.getSettings.perform(); } + /** + * Toggles the "Alphanumeric Sender ID" feature for the current company. + * + * Updates the company's `options` object by setting the + * `alpha_numeric_sender_id_enabled` flag. This controls whether the + * organization uses a custom alphanumeric sender ID when sending SMS. + * + * @action + * @param {boolean} enabled - Whether the feature should be enabled or disabled. + * @returns {void} + */ + @action toggleAlphaNumericSenderId(enabled) { + const currentOptions = this.company.options ?? {}; + this.company.set('options', { ...currentOptions, alpha_numeric_sender_id_enabled: enabled }); + } + + /** + * Sets the Alphanumeric Sender ID string for the current company. + * + * Reads the input's value from the event and updates the company's `options` + * object by setting the `alpha_numeric_sender_id` field. This value represents + * the sender name that will appear in outbound SMS messages (subject to carrier + * support and restrictions). + * + * @action + * @param {Event} event - Input event containing the alphanumeric sender ID value. + * @returns {void} + */ + @action setAlphaNumericSenderId(event) { + const value = event.target.value; + const currentOptions = this.company.options ?? {}; + this.company.set('options', { ...currentOptions, alpha_numeric_sender_id: value }); + } + /** * Selectes notifiables for settings. * @@ -94,7 +106,8 @@ export default class ConsoleSettingsNotificationsController extends Controller { const { notificationSettings } = this; try { - yield this.fetch.post('notifications/save-settings', { notificationSettings }); + yield this.fetch.post('notifications/save-settings', { notificationSettings: notificationSettings ?? {} }); + yield this.saveCompanyOptions.perform(); this.notifications.success('Notification settings successfully saved.'); } catch (error) { this.notifications.serverError(error); @@ -114,4 +127,26 @@ export default class ConsoleSettingsNotificationsController extends Controller { this.notifications.serverError(error); } } + + /** + * Saves the updated company options to the backend. + * + * This ember-concurrency task attempts to persist the company's modified + * `options` object by calling `company.save()`. If the request fails, a server + * error notification is displayed. No action is taken if no company is loaded. + * + * @task + * @generator + * @yields {Promise} Resolves when the save request completes. + * @returns {Promise} Task completion state. + */ + @task *saveCompanyOptions() { + if (!this.company) return; + + try { + yield this.company.save(); + } catch (error) { + this.notifications.serverError(error); + } + } } diff --git a/console/app/models/company.js b/console/app/models/company.js index 9bc0c999..213fc707 100644 --- a/console/app/models/company.js +++ b/console/app/models/company.js @@ -24,7 +24,7 @@ export default class Company extends Model { @attr('string') logo_url; @attr('string') backdrop_url; @attr('string') description; - @attr('raw') options; + @attr('object') options; @attr('number') users_count; @attr('string') type; @attr('string') currency; diff --git a/console/app/routes/console/settings/notifications.js b/console/app/routes/console/settings/notifications.js index 06c3a4a7..bef0b84b 100644 --- a/console/app/routes/console/settings/notifications.js +++ b/console/app/routes/console/settings/notifications.js @@ -5,6 +5,7 @@ import groupBy from '@fleetbase/ember-core/utils/group-by'; export default class ConsoleSettingsNotificationsRoute extends Route { @service fetch; + @service currentUser; model() { return hash({ @@ -13,10 +14,11 @@ export default class ConsoleSettingsNotificationsRoute extends Route { }); } - setupController(controller, { registry, notifiables }) { + async setupController(controller, { registry, notifiables }) { super.setupController(...arguments); controller.groupedNotifications = groupBy(registry, 'package'); controller.notifiables = notifiables; + controller.company = await this.currentUser.loadCompany(); } } diff --git a/console/app/templates/console/settings/notifications.hbs b/console/app/templates/console/settings/notifications.hbs index 468d5fc8..f4ea3b48 100644 --- a/console/app/templates/console/settings/notifications.hbs +++ b/console/app/templates/console/settings/notifications.hbs @@ -17,7 +17,7 @@ @selected={{get this.notificationSettings (concat (get-notification-key notification.definition notification.name) ".notifiables")}} @onChange={{fn this.onSelectNotifiable notification}} @placeholder="Select notifiables..." - @triggerClass="form-select form-input form-input-sm flex-1" + @triggerClass="form-select form-input flex-1" as |notifiable| > {{notifiable.label}} @@ -27,6 +27,21 @@ {{/each}} {{/each-in}} + + + + +
+ +

Alphanumeric Sender IDs allow your organization to replace a traditional phone number with a custom text-based sender name when sending SMS notifications (e.g., Fleetbase, MyStore, DispatchHQ). This can improve brand recognition, increase message trust, and enhance deliverability in regions where numeric senders are restricted by local carriers.

+

When enabled, Fleetbase will use this sender ID for all outbound SMS messages sent on behalf of your organization, including order updates, verification codes, driver notifications, and other automated alerts. Sender IDs can contain up to 11 characters using letters and numbers.

+

Some countries require or enforce specific messaging rules, and certain carriers may only support alphanumeric senders. Using a Sender ID can significantly improve message delivery in these regions.

+
+ +

Delivery of SMS using Alphanumeric Sender IDs depends on local carrier policies. Some regions may restrict or block numeric senders or require the use of alphanumeric senders for successful delivery. While Fleetbase will attempt to deliver all messages using your configured Sender ID, message delivery cannot be guaranteed in countries with carrier-level filtering or regulatory restrictions. Your organization is responsible for ensuring compliance with local messaging regulations in the countries you send SMS to.

+
+
+
diff --git a/console/package.json b/console/package.json index b6a614b2..5f4ffa50 100644 --- a/console/package.json +++ b/console/package.json @@ -1,6 +1,6 @@ { "name": "@fleetbase/console", - "version": "0.7.21", + "version": "0.7.22", "private": true, "description": "Modular logistics and supply chain operating system (LSOS)", "repository": "https://github.com/fleetbase/fleetbase", diff --git a/console/tests/integration/components/dashboard/widget-panel-test.js b/console/tests/integration/components/dashboard/widget-panel-test.js deleted file mode 100644 index 278059c6..00000000 --- a/console/tests/integration/components/dashboard/widget-panel-test.js +++ /dev/null @@ -1,26 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from '@fleetbase/console/tests/helpers'; -import { render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; - -module('Integration | Component | dashboard/widget-panel', function (hooks) { - setupRenderingTest(hooks); - - test('it renders', async function (assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.set('myAction', function(val) { ... }); - - await render(hbs``); - - assert.dom().hasText(''); - - // Template block usage: - await render(hbs` - - template block text - - `); - - assert.dom().hasText('template block text'); - }); -}); diff --git a/docker/Dockerfile b/docker/Dockerfile index 7abe6fb7..4886924c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -75,7 +75,7 @@ ENV QUEUE_CONNECTION=redis ENV CADDYFILE_PATH=/fleetbase/Caddyfile ENV CONSOLE_PATH=/fleetbase/console ENV OCTANE_SERVER=frankenphp -ENV FLEETBASE_VERSION=0.7.21 +ENV FLEETBASE_VERSION=0.7.22 # Set environment ARG ENVIRONMENT=production diff --git a/packages/core-api b/packages/core-api index 831600c1..d964db3f 160000 --- a/packages/core-api +++ b/packages/core-api @@ -1 +1 @@ -Subproject commit 831600c1818cbe76cfe280bfaaa3896ff1e2c597 +Subproject commit d964db3f4264f0a261364ce0c655f8aa561aeb84