From a44e915cd456db96f4d304959a1246d4c0b1e760 Mon Sep 17 00:00:00 2001 From: Jannis Klose <69921578+janni1288@users.noreply.github.com> Date: Sun, 2 Aug 2026 17:51:49 +0200 Subject: [PATCH 1/2] feat(labels): add view label action for individual entities --- addon/components/entity/card.hbs | 1 + addon/components/modals/entity-label.hbs | 7 ++++++ addon/services/entity-actions.js | 31 ++++++++++++++++++++++++ app/components/modals/entity-label.js | 1 + server/src/routes.php | 4 +++ translations/en-us.yaml | 5 ++++ 6 files changed, 49 insertions(+) create mode 100644 addon/components/modals/entity-label.hbs create mode 100644 app/components/modals/entity-label.js diff --git a/addon/components/entity/card.hbs b/addon/components/entity/card.hbs index ccd63de5a..9defaf2d1 100644 --- a/addon/components/entity/card.hbs +++ b/addon/components/entity/card.hbs @@ -15,6 +15,7 @@
{{#if (has-block "footer")}} diff --git a/addon/components/modals/entity-label.hbs b/addon/components/modals/entity-label.hbs new file mode 100644 index 000000000..1efb743a1 --- /dev/null +++ b/addon/components/modals/entity-label.hbs @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/addon/services/entity-actions.js b/addon/services/entity-actions.js index 29bacc098..1bbfc49df 100644 --- a/addon/services/entity-actions.js +++ b/addon/services/entity-actions.js @@ -1,4 +1,6 @@ import ResourceActionService from '@fleetbase/ember-core/services/resource-action'; +import { action } from '@ember/object'; +import { debug } from '@ember/debug'; export default class EntityActionsService extends ResourceActionService { constructor() { @@ -38,4 +40,33 @@ export default class EntityActionsService extends ResourceActionService { }); }, }; + + @action async viewLabel(entity) { + // render dialog to display label within + this.modalsManager.show(`modals/entity-label`, { + title: this.intl.t('order.fields.entity-label'), + modalClass: 'modal-xl', + acceptButtonText: this.intl.t('common.done'), + hideDeclineButton: true, + entity, + }); + try { + // load the pdf label from base64 + // eslint-disable-next-line no-undef + const fileReader = new FileReader(); + const { data: pdfStream } = await this.fetch.get(`labels/${entity.public_id}?type=entity&format=base64`); + // eslint-disable-next-line no-undef + const base64 = await fetch(`data:application/pdf;base64,${pdfStream}`); + const blob = await base64.blob(); + // load into file reader + fileReader.onload = (event) => { + const data = event.target.result; + this.modalsManager.setOption('data', data); + }; + fileReader.readAsDataURL(blob); + } catch (err) { + this.notifications.error(this.intl.t('order.prompts.failed-to-load-entity-label')); + debug('Error loading entity label data: ' + err.message); + } + } } diff --git a/app/components/modals/entity-label.js b/app/components/modals/entity-label.js new file mode 100644 index 000000000..0738a7673 --- /dev/null +++ b/app/components/modals/entity-label.js @@ -0,0 +1 @@ +export { default } from '@fleetbase/fleetops-engine/components/modals/entity-label'; diff --git a/server/src/routes.php b/server/src/routes.php index 2ec7286be..01011de33 100644 --- a/server/src/routes.php +++ b/server/src/routes.php @@ -382,6 +382,10 @@ function ($router, $controller) { } ); $router->fleetbaseRoutes('entities'); + // labels routes (needed within internal namespace for console access) + $router->group(['prefix' => 'labels'], function () use ($router) { + $router->get('{id}', '\Fleetbase\FleetOps\Http\Controllers\Api\v1\LabelController@getLabel'); + }); $router->fleetbaseRoutes( 'fleets', function ($router, $controller) { diff --git a/translations/en-us.yaml b/translations/en-us.yaml index bd27d73a3..0ce5dabe3 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -727,6 +727,7 @@ order: order-metadata: Order Metadata order-label: Order Label waypoint-label: Waypoint Label + entity-label: Entity Label current-eta: Current ETA ect: ECT current-destination: Current Destination @@ -743,6 +744,7 @@ order: no-driver-assigned-error: No driver assigned to this order. failed-to-load-order-label: Failed to load order label. failed-to-load-waypoint-label: Failed to load waypoint label. + failed-to-load-entity-label: Failed to load entity label.s unable-to-add-entity: Unable to add new entity to order. assign-driver-success: Driver ({driverName}) has been assigned to order {orderId}. cancel-title: Are you sure you wish to cancel this order? @@ -1559,6 +1561,9 @@ modals: order-label: loading: Loading Label... + entity-label: + loading: Loading Label... + order-new-activity: select-message: Select an activity status to update order tracking activity, or input a custom activity. order-currently-message: This order is currently {options}, additional activity will overwrite this status. From b3e5a5e12b95725785239aaee5be1d4d554eb105 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Mon, 3 Aug 2026 17:16:14 +0800 Subject: [PATCH 2/2] fix(labels): use existing order label endpoint and scope lookups by company MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The entity label action reached for a new internal `labels/{id}` route wired across into the public `Api\v1\LabelController`. The internal namespace already exposes `orders/label/{id}` via `Internal\v1\OrderController@label`, which already resolves `type=entity` through `findEntityLabelSubject()`, so no new backend route is needed. `$type` also defaults to `strtok($publicId, '_')`, so an `entity_*` public id resolves on its own and the query param can go. - drop the added internal `labels` route group - call `orders/label/{public_id}?format=base64`, matching `viewWaypointLabel` - reuse `modals/order-label` instead of cloning it, as the waypoint action does, with an `@options.subject` fallback so the object alt still resolves - fix the `Failed to load entity label.s` typo and add the two new keys to the six other locales that already carry the waypoint equivalents Also scopes label subject resolution to the session company. The lookups matched on identifier alone, so any authenticated user could render a label for any order, waypoint or entity in another organization by supplying its public id. The identifier match is grouped in a closure — appending the company constraint to the existing chain would read as `public_id = ? OR (uuid = ? AND company_uuid = ?)` and still leak. Resolution fails closed when there is no company session. Applied to both the internal and public API paths, with regression coverage for the foreign-company, precedence and no-session cases. Co-Authored-By: Claude Opus 5 --- addon/components/modals/entity-label.hbs | 7 --- addon/components/modals/order-label.hbs | 2 +- addon/services/entity-actions.js | 11 ++--- app/components/modals/entity-label.js | 1 - .../Controllers/Api/v1/LabelController.php | 30 +++++++++++-- .../Internal/v1/OrderController.php | 30 +++++++++++-- server/src/routes.php | 4 -- .../Http/Api/LabelControllerSubjectsTest.php | 45 +++++++++++++++++++ .../OrderControllerHelperSeamsTest.php | 29 ++++++++++++ translations/bg-bg.yaml | 2 + translations/en-us.yaml | 5 +-- translations/es-pa.yaml | 2 + translations/fr-fr.yaml | 2 + translations/mn-mn.yaml | 2 + translations/pt-br.yaml | 2 + translations/ru-ru.yaml | 2 + 16 files changed, 148 insertions(+), 28 deletions(-) delete mode 100644 addon/components/modals/entity-label.hbs delete mode 100644 app/components/modals/entity-label.js diff --git a/addon/components/modals/entity-label.hbs b/addon/components/modals/entity-label.hbs deleted file mode 100644 index 1efb743a1..000000000 --- a/addon/components/modals/entity-label.hbs +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/addon/components/modals/order-label.hbs b/addon/components/modals/order-label.hbs index 68126b76d..94f53f815 100644 --- a/addon/components/modals/order-label.hbs +++ b/addon/components/modals/order-label.hbs @@ -1,6 +1,6 @@