From a4b001d7e20d0b9960f4cd3d78313a76bed70d09 Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Thu, 1 Oct 2026 03:00:40 +0800 Subject: [PATCH 1/2] feat: resource view registries for fleet-ops tables and panels Extensions can add columns, row actions, bulk actions and toolbar buttons to fleet-ops tables through fleet-ops:table::, and buttons and menu items to its details panels through fleet-ops:details::. - @registry on every top-level Tabular/TabularActions index view and Panel details view; the contacts header follows the open tab's registry - *-actions panel.view passes registry: this.detailsRegistry, so the side panels merge the same buttons (customer and schedule map to their resource) - stable ids on built-in columns, actions and buttons; index query params include registered filter params; registries declared in extension.js Fixes found on the way: - driver, vehicle and trailer registeredTabs deleted `route` from the shared registry items (breaking those tabs in the routed details view once a side panel had opened) and kept only tabs without a component, which are the ones a panel cannot render; they now use registeredPanelTabs like the rest - the sensor details view read the place tab registry Requires @fleetbase/ember-core 0.3.25 and @fleetbase/ember-ui 0.4.5. --- addon/controllers/analytics/reports/index.js | 11 +++- .../controllers/connectivity/devices/index.js | 10 +++- .../connectivity/devices/index/details.js | 1 + .../controllers/connectivity/events/index.js | 32 +++++++++- .../controllers/connectivity/sensors/index.js | 38 +++++++++++- .../connectivity/sensors/index/details.js | 2 +- .../maintenance/equipment/index.js | 37 +++++++++--- .../maintenance/equipment/index/details.js | 4 +- .../maintenance/inspection-forms/index.js | 44 ++++++++++---- .../inspection-submissions/index.js | 58 ++++++++++++++++--- .../inspection-submissions/index/details.js | 3 +- .../maintenance/maintenances/index.js | 21 ++++++- .../maintenance/maintenances/index/details.js | 2 + addon/controllers/maintenance/parts/index.js | 36 +++++++++--- .../maintenance/parts/index/details.js | 4 +- .../maintenance/schedules/index.js | 37 ++++++++++-- .../maintenance/work-orders/index.js | 47 ++++++++++++--- .../maintenance/work-orders/index/details.js | 6 +- .../management/contacts/customers.js | 13 +++++ .../controllers/management/contacts/index.js | 44 +++++++++++++- addon/controllers/management/drivers/index.js | 34 ++++++++++- .../management/drivers/index/details.js | 1 + addon/controllers/management/fleets/index.js | 40 ++++++++++++- .../management/fleets/index/details.js | 1 + .../management/fuel-reports/index.js | 24 +++++++- .../management/fuel-transactions/index.js | 50 +++++++++++++--- addon/controllers/management/issues/index.js | 24 +++++++- .../management/issues/index/details.js | 1 + addon/controllers/management/places/index.js | 37 +++++++++++- .../controllers/management/trailers/index.js | 52 ++++++++++++++++- .../management/trailers/index/details.js | 1 + .../controllers/management/vehicles/index.js | 35 ++++++++++- .../management/vehicles/index/details.js | 1 + addon/controllers/management/vendors/index.js | 28 ++++++++- addon/controllers/operations/orders/index.js | 39 ++++++++++++- .../operations/orders/index/details.js | 7 +++ .../operations/service-rates/index.js | 16 ++++- addon/extension.js | 32 ++++++++++ addon/services/contact-actions.js | 1 + addon/services/customer-actions.js | 3 +- addon/services/device-actions.js | 1 + addon/services/device-event-actions.js | 1 + addon/services/driver-actions.js | 17 ++---- addon/services/equipment-actions.js | 1 + addon/services/fleet-actions.js | 1 + addon/services/fuel-report-actions.js | 1 + addon/services/inspection-form-actions.js | 1 + .../services/inspection-submission-actions.js | 1 + addon/services/integrated-vendor-actions.js | 1 + addon/services/issue-actions.js | 1 + addon/services/maintenance-actions.js | 1 + .../services/maintenance-schedule-actions.js | 3 +- addon/services/order-actions.js | 1 + addon/services/part-actions.js | 1 + addon/services/place-actions.js | 1 + addon/services/sensor-actions.js | 1 + addon/services/service-area-actions.js | 1 + addon/services/service-rate-actions.js | 1 + addon/services/telematic-actions.js | 1 + addon/services/trailer-actions.js | 18 ++---- addon/services/vehicle-actions.js | 17 ++---- addon/services/vendor-actions.js | 1 + addon/services/work-order-actions.js | 1 + addon/services/zone-actions.js | 1 + addon/templates/analytics/reports/index.hbs | 1 + .../analytics/reports/index/details.hbs | 1 + .../templates/connectivity/devices/index.hbs | 1 + .../connectivity/devices/index/details.hbs | 1 + addon/templates/connectivity/events/index.hbs | 1 + .../templates/connectivity/sensors/index.hbs | 1 + .../connectivity/sensors/index/details.hbs | 1 + .../templates/maintenance/equipment/index.hbs | 2 + .../maintenance/equipment/index/details.hbs | 1 + .../maintenance/inspection-forms/index.hbs | 1 + .../inspection-forms/index/details.hbs | 1 + .../inspection-submissions/index.hbs | 1 + .../inspection-submissions/index/details.hbs | 1 + .../maintenance/maintenances/index.hbs | 1 + .../maintenances/index/details.hbs | 1 + addon/templates/maintenance/parts/index.hbs | 2 + .../maintenance/parts/index/details.hbs | 1 + .../templates/maintenance/schedules/index.hbs | 2 + .../maintenance/schedules/index/details.hbs | 1 + .../maintenance/work-orders/index.hbs | 1 + .../maintenance/work-orders/index/details.hbs | 1 + addon/templates/management/contacts.hbs | 1 + .../management/contacts/customers.hbs | 1 + .../management/contacts/customers/details.hbs | 1 + addon/templates/management/contacts/index.hbs | 1 + .../management/contacts/index/details.hbs | 1 + addon/templates/management/drivers/index.hbs | 2 + .../management/drivers/index/details.hbs | 1 + addon/templates/management/fleets/index.hbs | 1 + .../management/fleets/index/details.hbs | 1 + .../management/fuel-reports/index.hbs | 1 + .../management/fuel-reports/index/details.hbs | 1 + .../management/fuel-transactions/index.hbs | 1 + addon/templates/management/issues/index.hbs | 1 + .../management/issues/index/details.hbs | 1 + addon/templates/management/places/index.hbs | 1 + .../management/places/index/details.hbs | 1 + addon/templates/management/trailers/index.hbs | 2 + .../management/trailers/index/details.hbs | 1 + addon/templates/management/vehicles/index.hbs | 2 + .../management/vehicles/index/details.hbs | 1 + addon/templates/management/vendors/index.hbs | 2 + .../management/vendors/index/details.hbs | 1 + .../management/vendors/integrated.hbs | 1 + addon/templates/operations/orders/index.hbs | 1 + .../operations/orders/index/details.hbs | 1 + .../operations/service-rates/index.hbs | 1 + .../service-rates/index/details.hbs | 1 + tests/unit/services/trailer-actions-test.js | 22 +++++++ 113 files changed, 897 insertions(+), 132 deletions(-) diff --git a/addon/controllers/analytics/reports/index.js b/addon/controllers/analytics/reports/index.js index 56052e63c..2067d6096 100644 --- a/addon/controllers/analytics/reports/index.js +++ b/addon/controllers/analytics/reports/index.js @@ -8,7 +8,7 @@ export default class AnalyticsReportsIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'name', 'created_at']; + @tracked queryParams = this.reportActions.queryParamsFor(['page', 'limit', 'sort', 'query', 'public_id', 'name', 'created_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -20,11 +20,13 @@ export default class AnalyticsReportsIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.reportActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -37,6 +39,7 @@ export default class AnalyticsReportsIndexController extends Controller { get bulkActions() { return [ { + id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.reportActions.bulkDelete, @@ -48,6 +51,7 @@ export default class AnalyticsReportsIndexController extends Controller { get columns() { return [ { + id: 'title', sticky: true, label: 'Title', valuePath: 'title', @@ -59,6 +63,7 @@ export default class AnalyticsReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'public-id', label: 'ID', valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -69,6 +74,7 @@ export default class AnalyticsReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -81,11 +87,13 @@ export default class AnalyticsReportsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: 'View report...', fn: this.reportActions.transition.view, permission: 'iam view report', }, { + id: 'edit', label: 'Edit report...', fn: this.reportActions.transition.edit, permission: 'iam update report', @@ -94,6 +102,7 @@ export default class AnalyticsReportsIndexController extends Controller { separator: true, }, { + id: 'delete', label: 'Delete report...', fn: this.reportActions.delete, permission: 'iam delete report', diff --git a/addon/controllers/connectivity/devices/index.js b/addon/controllers/connectivity/devices/index.js index b971d6681..c76ad53d4 100644 --- a/addon/controllers/connectivity/devices/index.js +++ b/addon/controllers/connectivity/devices/index.js @@ -17,7 +17,7 @@ export default class ConnectivityDevicesIndexController extends Controller { @service trailerActions; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.deviceActions.queryParamsFor([ 'name', 'status', 'attachment_state', @@ -36,7 +36,7 @@ export default class ConnectivityDevicesIndexController extends Controller { 'public_id', 'created_at', 'updated_at', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -56,11 +56,13 @@ export default class ConnectivityDevicesIndexController extends Controller { /** action buttons */ @tracked actionButtons = [ { + id: 'refresh', icon: 'refresh', onClick: this.deviceActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -68,6 +70,7 @@ export default class ConnectivityDevicesIndexController extends Controller { permission: 'fleet-ops create device', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -75,6 +78,7 @@ export default class ConnectivityDevicesIndexController extends Controller { permission: 'fleet-ops import device', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -87,6 +91,7 @@ export default class ConnectivityDevicesIndexController extends Controller { /** bulk action buttons */ @tracked bulkActions = [ { + id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.deviceActions.bulkDelete, @@ -111,6 +116,7 @@ export default class ConnectivityDevicesIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.device') }), fn: this.deviceActions.delete, permission: 'fleet-ops delete device', diff --git a/addon/controllers/connectivity/devices/index/details.js b/addon/controllers/connectivity/devices/index/details.js index 6068e2804..0ee1dbf77 100644 --- a/addon/controllers/connectivity/devices/index/details.js +++ b/addon/controllers/connectivity/devices/index/details.js @@ -39,6 +39,7 @@ export default class ConnectivityDevicesIndexDetailsController extends Controlle permission: 'fleet-ops update device', }, { + id: 'more', icon: 'ellipsis-h', iconPrefix: 'fas', renderInPlace: true, diff --git a/addon/controllers/connectivity/events/index.js b/addon/controllers/connectivity/events/index.js index 8932f927e..47857957c 100644 --- a/addon/controllers/connectivity/events/index.js +++ b/addon/controllers/connectivity/events/index.js @@ -78,7 +78,20 @@ export default class ConnectivityEventsIndexController extends Controller { @service telematicActions; /** query params */ - @tracked queryParams = ['page', 'limit', 'sort', 'query', 'telematic', 'device', 'event_type', 'severity', 'processed', 'occurred_at', 'created_at', 'updated_at']; + @tracked queryParams = this.deviceEventActions.queryParamsFor([ + 'page', + 'limit', + 'sort', + 'query', + 'telematic', + 'device', + 'event_type', + 'severity', + 'processed', + 'occurred_at', + 'created_at', + 'updated_at', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -95,6 +108,7 @@ export default class ConnectivityEventsIndexController extends Controller { /** action buttons */ @tracked actionButtons = [ { + id: 'refresh', icon: 'refresh', onClick: this.deviceEventActions.refresh, helpText: this.intl.t('common.refresh'), @@ -107,6 +121,7 @@ export default class ConnectivityEventsIndexController extends Controller { /** columns */ @tracked columns = [ { + id: 'event-type', sticky: true, label: 'Event', valuePath: 'event_type', @@ -121,6 +136,7 @@ export default class ConnectivityEventsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'device-display-name', label: 'Device', valuePath: 'device.displayName', cellComponent: 'cell/device-identity', @@ -137,6 +153,7 @@ export default class ConnectivityEventsIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'provider', label: 'Provider', valuePath: 'provider', cellComponent: 'cell/telematic-identity', @@ -152,6 +169,7 @@ export default class ConnectivityEventsIndexController extends Controller { model: 'telematic', }, { + id: 'severity', label: 'Severity', valuePath: 'severity', cellComponent: 'table/cell/status', @@ -165,12 +183,14 @@ export default class ConnectivityEventsIndexController extends Controller { filterOptionValue: 'value', }, { + id: 'message', label: 'Message', valuePath: 'message', resizable: true, sortable: false, }, { + id: 'code', label: 'Code', valuePath: 'code', resizable: true, @@ -180,6 +200,7 @@ export default class ConnectivityEventsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'ident', label: 'IDENT', valuePath: 'ident', hidden: true, @@ -187,6 +208,7 @@ export default class ConnectivityEventsIndexController extends Controller { sortable: true, }, { + id: 'protocol', label: 'Protocol', valuePath: 'protocol', hidden: true, @@ -194,6 +216,7 @@ export default class ConnectivityEventsIndexController extends Controller { sortable: true, }, { + id: 'state', label: 'State', valuePath: 'state', hidden: true, @@ -201,6 +224,7 @@ export default class ConnectivityEventsIndexController extends Controller { sortable: true, }, { + id: 'processed-at', label: 'Processed', valuePath: 'processedAt', sortParam: 'processed_at', @@ -214,6 +238,7 @@ export default class ConnectivityEventsIndexController extends Controller { filterOptionValue: 'value', }, { + id: 'occurred-at', label: 'Occurred', valuePath: 'occurredAt', sortParam: 'occurred_at', @@ -224,6 +249,7 @@ export default class ConnectivityEventsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -234,6 +260,7 @@ export default class ConnectivityEventsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -245,6 +272,7 @@ export default class ConnectivityEventsIndexController extends Controller { hidden: true, }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -257,11 +285,13 @@ export default class ConnectivityEventsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.device-event') }), fn: this.deviceEventActions.transition.view, permission: 'fleet-ops view device-event', }, { + id: 'mark-processed', label: 'Mark processed', fn: this.markProcessed, permission: 'fleet-ops update device-event', diff --git a/addon/controllers/connectivity/sensors/index.js b/addon/controllers/connectivity/sensors/index.js index 492a537d1..e8eb62d0a 100644 --- a/addon/controllers/connectivity/sensors/index.js +++ b/addon/controllers/connectivity/sensors/index.js @@ -65,7 +65,21 @@ export default class ConnectivitySensorsIndexController extends Controller { @service store; /** query params */ - @tracked queryParams = ['page', 'limit', 'sort', 'query', 'telematic', 'device', 'type', 'status', 'serial_number', 'imei', 'last_reading_at', 'created_at', 'updated_at']; + @tracked queryParams = this.sensorActions.queryParamsFor([ + 'page', + 'limit', + 'sort', + 'query', + 'telematic', + 'device', + 'type', + 'status', + 'serial_number', + 'imei', + 'last_reading_at', + 'created_at', + 'updated_at', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -83,11 +97,13 @@ export default class ConnectivitySensorsIndexController extends Controller { /** action buttons */ @tracked actionButtons = [ { + id: 'refresh', icon: 'refresh', onClick: this.sensorActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -95,6 +111,7 @@ export default class ConnectivitySensorsIndexController extends Controller { permission: 'fleet-ops create sensor', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -102,6 +119,7 @@ export default class ConnectivitySensorsIndexController extends Controller { permission: 'fleet-ops import sensor', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -114,6 +132,7 @@ export default class ConnectivitySensorsIndexController extends Controller { /** bulk action buttons */ @tracked bulkActions = [ { + id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.sensorActions.bulkDelete, @@ -124,6 +143,7 @@ export default class ConnectivitySensorsIndexController extends Controller { /** columns */ @tracked columns = [ { + id: 'display-name', sticky: true, label: this.intl.t('column.name'), valuePath: 'displayName', @@ -138,6 +158,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'telematic-provider', label: 'Telematic', valuePath: 'telematic.provider', cellComponent: 'cell/telematic-identity', @@ -153,6 +174,7 @@ export default class ConnectivitySensorsIndexController extends Controller { model: 'telematic', }, { + id: 'device-display-name', label: 'Device', valuePath: 'device.displayName', cellComponent: 'cell/device-identity', @@ -170,6 +192,7 @@ export default class ConnectivitySensorsIndexController extends Controller { query: this.telematic ? { telematic_uuid: this.telematic } : undefined, }, { + id: 'type', label: 'Type', valuePath: 'type', cellComponent: 'table/cell/base', @@ -184,18 +207,21 @@ export default class ConnectivitySensorsIndexController extends Controller { filterOptionValue: 'value', }, { + id: 'last-value', label: 'Last Value', valuePath: 'last_value', resizable: true, sortable: true, }, { + id: 'unit', label: 'Unit', valuePath: 'unit', resizable: true, sortable: true, }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -208,6 +234,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterOptionValue: 'value', }, { + id: 'threshold-status', label: 'Threshold', valuePath: 'threshold_status', cellComponent: 'table/cell/status', @@ -215,6 +242,7 @@ export default class ConnectivitySensorsIndexController extends Controller { sortable: true, }, { + id: 'serial-number', label: 'Serial Number', valuePath: 'serial_number', resizable: true, @@ -224,6 +252,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'imei', label: 'IMEI', valuePath: 'imei', resizable: true, @@ -233,6 +262,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'last-reading-at', label: 'Last Reading', valuePath: 'lastReadingAt', sortParam: 'last_reading_at', @@ -243,6 +273,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -253,6 +284,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -264,6 +296,7 @@ export default class ConnectivitySensorsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -276,11 +309,13 @@ export default class ConnectivitySensorsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.sensor') }), fn: this.sensorActions.transition.view, permission: 'fleet-ops view sensor', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.sensor') }), fn: this.sensorActions.transition.edit, permission: 'fleet-ops update sensor', @@ -289,6 +324,7 @@ export default class ConnectivitySensorsIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.sensor') }), fn: this.sensorActions.delete, permission: 'fleet-ops delete sensor', diff --git a/addon/controllers/connectivity/sensors/index/details.js b/addon/controllers/connectivity/sensors/index/details.js index c554b8571..936b8d261 100644 --- a/addon/controllers/connectivity/sensors/index/details.js +++ b/addon/controllers/connectivity/sensors/index/details.js @@ -7,7 +7,7 @@ export default class ConnectivitySensorsIndexDetailsController extends Controlle @service hostRouter; get tabs() { - const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:place:details'); + const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:sensor:details'); return [ { route: 'connectivity.sensors.index.details.index', diff --git a/addon/controllers/maintenance/equipment/index.js b/addon/controllers/maintenance/equipment/index.js index d0a95dac0..c6cdf82ab 100644 --- a/addon/controllers/maintenance/equipment/index.js +++ b/addon/controllers/maintenance/equipment/index.js @@ -7,7 +7,7 @@ export default class MaintenanceEquipmentIndexController extends Controller { @service intl; @service appCache; - @tracked queryParams = ['type', 'status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.equipmentActions.queryParamsFor(['type', 'status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -21,6 +21,7 @@ export default class MaintenanceEquipmentIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', @@ -45,10 +46,11 @@ export default class MaintenanceEquipmentIndexController extends Controller { renderInPlace: true, helpText: 'Change the layout', }, - { icon: 'refresh', onClick: this.equipmentActions.refresh, helpText: this.intl.t('common.refresh') }, - { text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.equipmentActions.transition.create, permission: 'fleet-ops create equipment' }, - { text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.equipmentActions.import, permission: 'fleet-ops import equipment' }, + { id: 'refresh', icon: 'refresh', onClick: this.equipmentActions.refresh, helpText: this.intl.t('common.refresh') }, + { id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.equipmentActions.transition.create, permission: 'fleet-ops create equipment' }, + { id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.equipmentActions.import, permission: 'fleet-ops import equipment' }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -60,12 +62,13 @@ export default class MaintenanceEquipmentIndexController extends Controller { } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.equipmentActions.bulkDelete, permission: 'fleet-ops delete equipment' }]; + return [{ id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.equipmentActions.bulkDelete, permission: 'fleet-ops delete equipment' }]; } get columns() { return [ { + id: 'name', label: this.intl.t('column.name'), valuePath: 'name', cellComponent: 'cell/equipment-identity', @@ -77,8 +80,9 @@ export default class MaintenanceEquipmentIndexController extends Controller { filterParam: 'name', filterComponent: 'filter/string', }, - { label: this.intl.t('column.code'), valuePath: 'code', resizable: true, sortable: true, filterable: true, filterParam: 'code', filterComponent: 'filter/string' }, + { id: 'code', label: this.intl.t('column.code'), valuePath: 'code', resizable: true, sortable: true, filterable: true, filterParam: 'code', filterComponent: 'filter/string' }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', cellComponent: 'table/cell/base', @@ -90,6 +94,7 @@ export default class MaintenanceEquipmentIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -99,10 +104,20 @@ export default class MaintenanceEquipmentIndexController extends Controller { filterParam: 'status', filterComponent: 'filter/string', }, - { label: this.intl.t('column.serial-number'), valuePath: 'serial_number', resizable: true, sortable: true }, - { label: this.intl.t('column.manufacturer'), valuePath: 'manufacturer', resizable: true, sortable: true }, - { label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { id: 'serial-number', label: this.intl.t('column.serial-number'), valuePath: 'serial_number', resizable: true, sortable: true }, + { id: 'manufacturer', label: this.intl.t('column.manufacturer'), valuePath: 'manufacturer', resizable: true, sortable: true }, { + id: 'created-at', + label: this.intl.t('column.created-at'), + valuePath: 'createdAt', + sortParam: 'created_at', + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/date', + }, + { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -113,6 +128,7 @@ export default class MaintenanceEquipmentIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -123,17 +139,20 @@ export default class MaintenanceEquipmentIndexController extends Controller { wrapperClass: 'flex items-center justify-end mx-2', actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.equipment') }), fn: this.equipmentActions.transition.view, permission: 'fleet-ops view equipment', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.equipment') }), fn: this.equipmentActions.transition.edit, permission: 'fleet-ops update equipment', }, { separator: true }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.equipment') }), fn: this.equipmentActions.delete, permission: 'fleet-ops delete equipment', diff --git a/addon/controllers/maintenance/equipment/index/details.js b/addon/controllers/maintenance/equipment/index/details.js index 50131af5d..204e9aac9 100644 --- a/addon/controllers/maintenance/equipment/index/details.js +++ b/addon/controllers/maintenance/equipment/index/details.js @@ -19,8 +19,8 @@ export default class MaintenanceEquipmentIndexDetailsController extends Controll get actionButtons() { return [ - { icon: 'edit', fn: this.edit, permission: 'fleet-ops update equipment' }, - { icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete equipment' }, + { id: 'edit', icon: 'edit', fn: this.edit, permission: 'fleet-ops update equipment' }, + { id: 'delete', icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete equipment' }, ]; } diff --git a/addon/controllers/maintenance/inspection-forms/index.js b/addon/controllers/maintenance/inspection-forms/index.js index f7fb1c0ff..8a235754c 100644 --- a/addon/controllers/maintenance/inspection-forms/index.js +++ b/addon/controllers/maintenance/inspection-forms/index.js @@ -6,7 +6,7 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle @service inspectionFormActions; @service intl; - @tracked queryParams = ['status', 'type', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.inspectionFormActions.queryParamsFor(['status', 'type', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -16,18 +16,26 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle get actionButtons() { return [ - { icon: 'refresh', onClick: this.inspectionFormActions.refresh, helpText: this.intl.t('common.refresh') }, - { text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.inspectionFormActions.transition.create, permission: 'fleet-ops create inspection-form' }, + { id: 'refresh', icon: 'refresh', onClick: this.inspectionFormActions.refresh, helpText: this.intl.t('common.refresh') }, + { + id: 'create', + text: this.intl.t('common.new'), + type: 'primary', + icon: 'plus', + onClick: this.inspectionFormActions.transition.create, + permission: 'fleet-ops create inspection-form', + }, ]; } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.inspectionFormActions.bulkDelete, permission: 'fleet-ops delete inspection-form' }]; + return [{ id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.inspectionFormActions.bulkDelete, permission: 'fleet-ops delete inspection-form' }]; } get columns() { return [ { + id: 'name', label: 'Name', valuePath: 'name', cellComponent: 'table/cell/anchor', @@ -40,6 +48,7 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle filterComponent: 'filter/string', }, { + id: 'type', label: 'Type', valuePath: 'type', cellComponent: 'table/cell/fleet-ops-option', @@ -51,6 +60,7 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle filterComponent: 'filter/string', }, { + id: 'status', label: 'Status', valuePath: 'status', cellComponent: 'table/cell/status', @@ -60,9 +70,19 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle filterParam: 'status', filterComponent: 'filter/string', }, - { label: 'Items', valuePath: 'item_count', resizable: true, sortable: false }, - { label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { id: 'item-count', label: 'Items', valuePath: 'item_count', resizable: true, sortable: false }, + { + id: 'created-at', + label: this.intl.t('column.created-at'), + valuePath: 'createdAt', + sortParam: 'created_at', + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/date', + }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -71,14 +91,14 @@ export default class MaintenanceInspectionFormsIndexController extends Controlle cellClassNames: 'overflow-visible', wrapperClass: 'flex items-center justify-end mx-2', actions: [ - { label: 'View form', fn: this.inspectionFormActions.transition.view, permission: 'fleet-ops view inspection-form' }, - { label: 'Edit form', fn: this.inspectionFormActions.transition.edit, permission: 'fleet-ops update inspection-form' }, + { id: 'view', label: 'View form', fn: this.inspectionFormActions.transition.view, permission: 'fleet-ops view inspection-form' }, + { id: 'edit', label: 'Edit form', fn: this.inspectionFormActions.transition.edit, permission: 'fleet-ops update inspection-form' }, { separator: true }, - { label: 'Publish', fn: this.inspectionFormActions.publish, permission: 'fleet-ops publish inspection-form' }, - { label: 'Archive', fn: this.inspectionFormActions.archive, permission: 'fleet-ops archive inspection-form' }, - { label: 'Generate inspection link', fn: this.inspectionFormActions.generateLink, permission: 'fleet-ops view inspection-form' }, + { id: 'publish', label: 'Publish', fn: this.inspectionFormActions.publish, permission: 'fleet-ops publish inspection-form' }, + { id: 'archive', label: 'Archive', fn: this.inspectionFormActions.archive, permission: 'fleet-ops archive inspection-form' }, + { id: 'generate-link', label: 'Generate inspection link', fn: this.inspectionFormActions.generateLink, permission: 'fleet-ops view inspection-form' }, { separator: true }, - { label: 'Delete form', fn: this.inspectionFormActions.delete, class: 'text-red-500', permission: 'fleet-ops delete inspection-form' }, + { id: 'delete', label: 'Delete form', fn: this.inspectionFormActions.delete, class: 'text-red-500', permission: 'fleet-ops delete inspection-form' }, ], sortable: false, filterable: false, diff --git a/addon/controllers/maintenance/inspection-submissions/index.js b/addon/controllers/maintenance/inspection-submissions/index.js index 0cfa6bd70..0286952eb 100644 --- a/addon/controllers/maintenance/inspection-submissions/index.js +++ b/addon/controllers/maintenance/inspection-submissions/index.js @@ -9,7 +9,20 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con @service inspectionSubmissionActions; @service intl; - @tracked queryParams = ['status', 'result', 'type', 'page', 'limit', 'sort', 'query', 'public_id', 'vehicle', 'driver', 'created_at', 'updated_at']; + @tracked queryParams = this.inspectionSubmissionActions.queryParamsFor([ + 'status', + 'result', + 'type', + 'page', + 'limit', + 'sort', + 'query', + 'public_id', + 'vehicle', + 'driver', + 'created_at', + 'updated_at', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -22,8 +35,9 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con get actionButtons() { return [ - { icon: 'refresh', onClick: this.inspectionSubmissionActions.refresh, helpText: this.intl.t('common.refresh') }, + { id: 'refresh', icon: 'refresh', onClick: this.inspectionSubmissionActions.refresh, helpText: this.intl.t('common.refresh') }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -34,12 +48,15 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.inspectionSubmissionActions.bulkDelete, permission: 'fleet-ops delete inspection-submission' }]; + return [ + { id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.inspectionSubmissionActions.bulkDelete, permission: 'fleet-ops delete inspection-submission' }, + ]; } get columns() { return [ { + id: 'public-id', label: 'Inspection', valuePath: 'public_id', cellComponent: 'table/cell/anchor', @@ -52,6 +69,7 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con filterComponent: 'filter/string', }, { + id: 'form-name', label: 'Form', valuePath: 'form_name', cellComponent: 'cell/inspection-form-identity', @@ -61,6 +79,7 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con sortable: false, }, { + id: 'vehicle-name', label: 'Vehicle', valuePath: 'vehicle_name', cellComponent: 'cell/vehicle-identity', @@ -72,6 +91,7 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con sortable: false, }, { + id: 'driver-name', label: 'Driver', valuePath: 'driver_name', cellComponent: 'cell/driver-identity', @@ -83,6 +103,7 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con sortable: false, }, { + id: 'result', label: 'Result', valuePath: 'result', cellComponent: 'table/cell/status', @@ -92,9 +113,19 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con filterParam: 'result', filterComponent: 'filter/string', }, - { label: 'Failed', valuePath: 'failed_items', resizable: true, sortable: true }, - { label: 'Submitted', valuePath: 'submittedAt', sortParam: 'submitted_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { id: 'failed-items', label: 'Failed', valuePath: 'failed_items', resizable: true, sortable: true }, { + id: 'submitted-at', + label: 'Submitted', + valuePath: 'submittedAt', + sortParam: 'submitted_at', + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/date', + }, + { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -103,8 +134,8 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con cellClassNames: 'overflow-visible', wrapperClass: 'flex items-center justify-end mx-2', actions: [ - { label: 'View inspection', fn: this.inspectionSubmissionActions.transition.view, permission: 'fleet-ops view inspection-submission' }, - { label: 'Edit inspection', fn: this.inspectionSubmissionActions.transition.edit, permission: 'fleet-ops update inspection-submission' }, + { id: 'view', label: 'View inspection', fn: this.inspectionSubmissionActions.transition.view, permission: 'fleet-ops view inspection-submission' }, + { id: 'edit', label: 'Edit inspection', fn: this.inspectionSubmissionActions.transition.edit, permission: 'fleet-ops update inspection-submission' }, { separator: true, // Everything below this rule is conditional. On a row @@ -114,6 +145,7 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con isVisible: (row) => row?.status === 'draft' || row?.status !== 'resolved' || Boolean(row?.has_failures && (!row?.issue_uuid || !row?.work_order_uuid)), }, { + id: 'submit', label: 'Submit', fn: this.inspectionSubmissionActions.submit, permission: 'fleet-ops submit inspection-submission', @@ -123,20 +155,28 @@ export default class MaintenanceInspectionSubmissionsIndexController extends Con isVisible: (row) => row?.status === 'draft', }, { + id: 'create-issue', label: 'Create issue', fn: this.inspectionSubmissionActions.createIssue, permission: 'fleet-ops create-issue inspection-submission', isVisible: (row) => row?.has_failures && !row?.issue_uuid, }, { + id: 'create-work-order', label: 'Create work order', fn: this.inspectionSubmissionActions.createWorkOrder, permission: 'fleet-ops create-work-order inspection-submission', isVisible: (row) => row?.has_failures && !row?.work_order_uuid, }, - { label: 'Resolve', fn: this.inspectionSubmissionActions.resolve, permission: 'fleet-ops resolve inspection-submission', isVisible: (row) => row?.status !== 'resolved' }, + { + id: 'resolve', + label: 'Resolve', + fn: this.inspectionSubmissionActions.resolve, + permission: 'fleet-ops resolve inspection-submission', + isVisible: (row) => row?.status !== 'resolved', + }, { separator: true }, - { label: 'Delete inspection', fn: this.inspectionSubmissionActions.delete, class: 'text-red-500', permission: 'fleet-ops delete inspection-submission' }, + { id: 'delete', label: 'Delete inspection', fn: this.inspectionSubmissionActions.delete, class: 'text-red-500', permission: 'fleet-ops delete inspection-submission' }, ], sortable: false, filterable: false, diff --git a/addon/controllers/maintenance/inspection-submissions/index/details.js b/addon/controllers/maintenance/inspection-submissions/index/details.js index 7b1480ede..f0166e4f4 100644 --- a/addon/controllers/maintenance/inspection-submissions/index/details.js +++ b/addon/controllers/maintenance/inspection-submissions/index/details.js @@ -24,8 +24,9 @@ export default class MaintenanceInspectionSubmissionsIndexDetailsController exte */ get actionButtons() { return [ - { icon: 'edit', fn: this.edit, permission: 'fleet-ops update inspection-submission' }, + { id: 'edit', icon: 'edit', fn: this.edit, permission: 'fleet-ops update inspection-submission' }, { + id: 'more', icon: 'ellipsis-h', iconPrefix: 'fas', renderInPlace: true, diff --git a/addon/controllers/maintenance/maintenances/index.js b/addon/controllers/maintenance/maintenances/index.js index a0d75c580..688812ae3 100644 --- a/addon/controllers/maintenance/maintenances/index.js +++ b/addon/controllers/maintenance/maintenances/index.js @@ -9,7 +9,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = ['type', 'status', 'priority', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.maintenanceActions.queryParamsFor(['type', 'status', 'priority', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -22,11 +22,13 @@ export default class MaintenanceMaintenancesIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.maintenanceActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -34,6 +36,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { permission: 'fleet-ops create maintenance', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -41,6 +44,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { permission: 'fleet-ops import maintenance', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -55,6 +59,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { get bulkActions() { return [ { + id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.maintenanceActions.bulkDelete, @@ -67,6 +72,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { get columns() { return [ { + id: 'summary', label: this.intl.t('column.summary'), valuePath: 'summary', cellComponent: 'table/cell/anchor', @@ -80,6 +86,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'maintainable-name', label: this.intl.t('column.asset'), valuePath: 'maintainable.name', cellComponent: 'cell/maintenance-subject-identity', @@ -88,6 +95,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { sortable: true, }, { + id: 'performed-by-name', label: this.intl.t('column.performed-by'), valuePath: 'performed_by.name', cellComponent: 'cell/facilitator-identity', @@ -96,6 +104,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { sortable: true, }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', cellComponent: 'table/cell/base', @@ -107,6 +116,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -117,6 +127,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'priority', label: this.intl.t('column.priority'), valuePath: 'priority', cellComponent: 'table/cell/base', @@ -128,6 +139,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'scheduled-at', label: this.intl.t('column.scheduled-at'), valuePath: 'scheduledAt', sortParam: 'scheduled_at', @@ -137,6 +149,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'total-cost', label: this.intl.t('column.total-cost'), valuePath: 'total_cost', cellComponent: 'table/cell/currency', @@ -144,6 +157,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { sortable: true, }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -153,6 +167,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -163,6 +178,7 @@ export default class MaintenanceMaintenancesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -173,17 +189,20 @@ export default class MaintenanceMaintenancesIndexController extends Controller { wrapperClass: 'flex items-center justify-end mx-2', actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.maintenance') }), fn: this.maintenanceActions.transition.view, permission: 'fleet-ops view maintenance', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.maintenance') }), fn: this.maintenanceActions.transition.edit, permission: 'fleet-ops update maintenance', }, { separator: true }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.maintenance') }), fn: this.maintenanceActions.delete, permission: 'fleet-ops delete maintenance', diff --git a/addon/controllers/maintenance/maintenances/index/details.js b/addon/controllers/maintenance/maintenances/index/details.js index 9ce632c39..1506d2705 100644 --- a/addon/controllers/maintenance/maintenances/index/details.js +++ b/addon/controllers/maintenance/maintenances/index/details.js @@ -27,11 +27,13 @@ export default class MaintenanceMaintenancesIndexDetailsController extends Contr get actionButtons() { return [ { + id: 'edit', icon: 'edit', fn: this.edit, permission: 'fleet-ops update maintenance', }, { + id: 'delete', icon: 'trash', fn: this.delete, type: 'danger', diff --git a/addon/controllers/maintenance/parts/index.js b/addon/controllers/maintenance/parts/index.js index 55bfc41c2..26e81d117 100644 --- a/addon/controllers/maintenance/parts/index.js +++ b/addon/controllers/maintenance/parts/index.js @@ -7,7 +7,7 @@ export default class MaintenancePartsIndexController extends Controller { @service intl; @service appCache; - @tracked queryParams = ['type', 'status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.partActions.queryParamsFor(['type', 'status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -21,6 +21,7 @@ export default class MaintenancePartsIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', @@ -45,10 +46,11 @@ export default class MaintenancePartsIndexController extends Controller { renderInPlace: true, helpText: 'Change the layout', }, - { icon: 'refresh', onClick: this.partActions.refresh, helpText: this.intl.t('common.refresh') }, - { text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.partActions.transition.create, permission: 'fleet-ops create part' }, - { text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.partActions.import, permission: 'fleet-ops import part' }, + { id: 'refresh', icon: 'refresh', onClick: this.partActions.refresh, helpText: this.intl.t('common.refresh') }, + { id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.partActions.transition.create, permission: 'fleet-ops create part' }, + { id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.partActions.import, permission: 'fleet-ops import part' }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -60,12 +62,13 @@ export default class MaintenancePartsIndexController extends Controller { } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.partActions.bulkDelete, permission: 'fleet-ops delete part' }]; + return [{ id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.partActions.bulkDelete, permission: 'fleet-ops delete part' }]; } get columns() { return [ { + id: 'name', label: this.intl.t('column.name'), valuePath: 'name', cellComponent: 'cell/part-identity', @@ -78,6 +81,7 @@ export default class MaintenancePartsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'sku', label: this.intl.t('column.part-number'), valuePath: 'sku', resizable: true, @@ -87,6 +91,7 @@ export default class MaintenancePartsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', cellComponent: 'table/cell/base', @@ -98,6 +103,7 @@ export default class MaintenancePartsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -107,10 +113,20 @@ export default class MaintenancePartsIndexController extends Controller { filterParam: 'status', filterComponent: 'filter/string', }, - { label: this.intl.t('column.quantity-on-hand'), valuePath: 'quantity_on_hand', resizable: true, sortable: true }, - { label: this.intl.t('column.unit-cost'), valuePath: 'unit_cost', cellComponent: 'table/cell/currency', resizable: true, sortable: true }, - { label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { id: 'quantity-on-hand', label: this.intl.t('column.quantity-on-hand'), valuePath: 'quantity_on_hand', resizable: true, sortable: true }, + { id: 'unit-cost', label: this.intl.t('column.unit-cost'), valuePath: 'unit_cost', cellComponent: 'table/cell/currency', resizable: true, sortable: true }, { + id: 'created-at', + label: this.intl.t('column.created-at'), + valuePath: 'createdAt', + sortParam: 'created_at', + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/date', + }, + { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -121,6 +137,7 @@ export default class MaintenancePartsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -131,17 +148,20 @@ export default class MaintenancePartsIndexController extends Controller { wrapperClass: 'flex items-center justify-end mx-2', actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.part') }), fn: this.partActions.transition.view, permission: 'fleet-ops view part', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.part') }), fn: this.partActions.transition.edit, permission: 'fleet-ops update part', }, { separator: true }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.part') }), fn: this.partActions.delete, permission: 'fleet-ops delete part', diff --git a/addon/controllers/maintenance/parts/index/details.js b/addon/controllers/maintenance/parts/index/details.js index 4cb7c5671..ab623c8ca 100644 --- a/addon/controllers/maintenance/parts/index/details.js +++ b/addon/controllers/maintenance/parts/index/details.js @@ -19,8 +19,8 @@ export default class MaintenancePartsIndexDetailsController extends Controller { get actionButtons() { return [ - { icon: 'edit', fn: this.edit, permission: 'fleet-ops update part' }, - { icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete part' }, + { id: 'edit', icon: 'edit', fn: this.edit, permission: 'fleet-ops update part' }, + { id: 'delete', icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete part' }, ]; } diff --git a/addon/controllers/maintenance/schedules/index.js b/addon/controllers/maintenance/schedules/index.js index 16f4b098f..9ca612813 100644 --- a/addon/controllers/maintenance/schedules/index.js +++ b/addon/controllers/maintenance/schedules/index.js @@ -33,7 +33,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { return this.maintenanceScheduleActions; } - @tracked queryParams = ['status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.maintenanceScheduleActions.queryParamsFor(['status', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -132,16 +132,19 @@ export default class MaintenanceSchedulesIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', items: [ { + id: 'list-view', label: this.intl.t('common.table-view'), icon: 'table-list', onClick: this.setLayoutList, }, { + id: 'calendar-view', label: this.intl.t('common.calendar-view'), icon: 'calendar', onClick: this.setLayoutCalendar, @@ -150,16 +153,25 @@ export default class MaintenanceSchedulesIndexController extends Controller { renderInPlace: true, helpText: this.intl.t('common.change-layout'), }, - { icon: 'refresh', onClick: this.maintenanceScheduleActions.refresh, helpText: this.intl.t('common.refresh') }, + { id: 'refresh', icon: 'refresh', onClick: this.maintenanceScheduleActions.refresh, helpText: this.intl.t('common.refresh') }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.maintenanceScheduleActions.transition.create, permission: 'fleet-ops create maintenance-schedule', }, - { text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.maintenanceScheduleActions.import, permission: 'fleet-ops import maintenance-schedule' }, { + id: 'import', + text: this.intl.t('common.import'), + type: 'magic', + icon: 'upload', + onClick: this.maintenanceScheduleActions.import, + permission: 'fleet-ops import maintenance-schedule', + }, + { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -171,12 +183,15 @@ export default class MaintenanceSchedulesIndexController extends Controller { } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.maintenanceScheduleActions.bulkDelete, permission: 'fleet-ops delete maintenance-schedule' }]; + return [ + { id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.maintenanceScheduleActions.bulkDelete, permission: 'fleet-ops delete maintenance-schedule' }, + ]; } get columns() { return [ { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'table/cell/anchor', @@ -190,6 +205,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'name', label: this.intl.t('column.name'), valuePath: 'name', resizable: true, @@ -199,6 +215,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'subject-name', label: this.intl.t('column.subject'), valuePath: 'subject.name', cellComponent: 'cell/maintenance-subject-identity', @@ -208,6 +225,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { sortable: false, }, { + id: 'default-assignee-name', label: this.intl.t('column.assignee'), valuePath: 'default_assignee_name', cellComponent: 'cell/facilitator-identity', @@ -218,6 +236,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { hidden: true, }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', cellComponent: 'table/cell/base', @@ -229,6 +248,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -239,6 +259,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'next-due-at-short', label: this.intl.t('column.next-due'), valuePath: 'nextDueAtShort', sortParam: 'next_due_date', @@ -248,6 +269,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -257,6 +279,7 @@ export default class MaintenanceSchedulesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -267,33 +290,39 @@ export default class MaintenanceSchedulesIndexController extends Controller { wrapperClass: 'flex items-center justify-end mx-2', actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.maintenance-schedule') }), fn: this.maintenanceScheduleActions.transition.view, permission: 'fleet-ops view maintenance-schedule', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.maintenance-schedule') }), fn: this.maintenanceScheduleActions.transition.edit, permission: 'fleet-ops update maintenance-schedule', }, { + id: 'trigger-now', label: this.intl.t('maintenance-schedule.actions.trigger-now'), fn: this.maintenanceScheduleActions.triggerNow, permission: 'fleet-ops update maintenance-schedule', }, { separator: true }, { + id: 'pause', label: this.intl.t('maintenance-schedule.actions.pause'), fn: this.maintenanceScheduleActions.pause, permission: 'fleet-ops update maintenance-schedule', }, { + id: 'resume', label: this.intl.t('maintenance-schedule.actions.resume'), fn: this.maintenanceScheduleActions.resume, permission: 'fleet-ops update maintenance-schedule', }, { separator: true }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.maintenance-schedule') }), fn: this.maintenanceScheduleActions.delete, permission: 'fleet-ops delete maintenance-schedule', diff --git a/addon/controllers/maintenance/work-orders/index.js b/addon/controllers/maintenance/work-orders/index.js index 082cb8ead..5c55373dd 100644 --- a/addon/controllers/maintenance/work-orders/index.js +++ b/addon/controllers/maintenance/work-orders/index.js @@ -9,7 +9,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { @service workOrderActions; @service intl; - @tracked queryParams = ['category', 'status', 'priority', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']; + @tracked queryParams = this.workOrderActions.queryParamsFor(['category', 'status', 'priority', 'page', 'limit', 'sort', 'query', 'public_id', 'created_at', 'updated_at']); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -20,10 +20,11 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { get actionButtons() { return [ - { icon: 'refresh', onClick: this.workOrderActions.refresh, helpText: this.intl.t('common.refresh') }, - { text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.workOrderActions.transition.create, permission: 'fleet-ops create work-order' }, - { text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.workOrderActions.import, permission: 'fleet-ops import work-order' }, + { id: 'refresh', icon: 'refresh', onClick: this.workOrderActions.refresh, helpText: this.intl.t('common.refresh') }, + { id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', onClick: this.workOrderActions.transition.create, permission: 'fleet-ops create work-order' }, + { id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', onClick: this.workOrderActions.import, permission: 'fleet-ops import work-order' }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -35,12 +36,13 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { } get bulkActions() { - return [{ label: 'Delete selected...', class: 'text-red-500', fn: this.workOrderActions.bulkDelete, permission: 'fleet-ops delete work-order' }]; + return [{ id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.workOrderActions.bulkDelete, permission: 'fleet-ops delete work-order' }]; } get columns() { return [ { + id: 'code', label: this.intl.t('column.code'), valuePath: 'code', cellComponent: 'table/cell/anchor', @@ -53,8 +55,18 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { filterParam: 'code', filterComponent: 'filter/string', }, - { label: this.intl.t('column.subject'), valuePath: 'subject', resizable: true, sortable: true, filterable: true, filterParam: 'subject', filterComponent: 'filter/string' }, { + id: 'subject', + label: this.intl.t('column.subject'), + valuePath: 'subject', + resizable: true, + sortable: true, + filterable: true, + filterParam: 'subject', + filterComponent: 'filter/string', + }, + { + id: 'category', label: this.intl.t('column.category'), valuePath: 'category', cellComponent: 'table/cell/base', @@ -70,6 +82,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { placeholder: 'Select work order category', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -80,6 +93,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'priority', label: this.intl.t('column.priority'), valuePath: 'priority', cellComponent: 'table/cell/base', @@ -91,6 +105,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'target-name', label: this.intl.t('column.target'), valuePath: 'target_name', cellComponent: 'cell/maintenance-subject-identity', @@ -100,6 +115,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { hidden: true, }, { + id: 'assignee-name', label: this.intl.t('column.assignee'), valuePath: 'assignee_name', cellComponent: 'cell/facilitator-identity', @@ -107,9 +123,19 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { resizable: true, sortable: false, }, - { label: this.intl.t('column.due-at'), valuePath: 'dueAt', sortParam: 'due_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, - { label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { id: 'due-at', label: this.intl.t('column.due-at'), valuePath: 'dueAt', sortParam: 'due_at', resizable: true, sortable: true, filterable: true, filterComponent: 'filter/date' }, + { + id: 'created-at', + label: this.intl.t('column.created-at'), + valuePath: 'createdAt', + sortParam: 'created_at', + resizable: true, + sortable: true, + filterable: true, + filterComponent: 'filter/date', + }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -120,6 +146,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -130,17 +157,20 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { wrapperClass: 'flex items-center justify-end mx-2', actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.work-order') }), fn: this.workOrderActions.transition.view, permission: 'fleet-ops view work-order', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.work-order') }), fn: this.workOrderActions.transition.edit, permission: 'fleet-ops update work-order', }, { separator: true }, { + id: 'send-email', label: 'Send Work Order to Vendor', fn: this.workOrderActions.sendEmail, icon: 'paper-plane', @@ -148,6 +178,7 @@ export default class MaintenanceWorkOrdersIndexController extends Controller { }, { separator: true }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.work-order') }), fn: this.workOrderActions.delete, permission: 'fleet-ops delete work-order', diff --git a/addon/controllers/maintenance/work-orders/index/details.js b/addon/controllers/maintenance/work-orders/index/details.js index 2e1ce8ca0..b8a4f09ab 100644 --- a/addon/controllers/maintenance/work-orders/index/details.js +++ b/addon/controllers/maintenance/work-orders/index/details.js @@ -19,9 +19,9 @@ export default class MaintenanceWorkOrdersIndexDetailsController extends Control get actionButtons() { return [ - { icon: 'paper-plane', fn: this.sendEmail, text: 'Send to Vendor', permission: 'fleet-ops update work-order' }, - { icon: 'edit', fn: this.edit, permission: 'fleet-ops update work-order' }, - { icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete work-order' }, + { id: 'send-email', icon: 'paper-plane', fn: this.sendEmail, text: 'Send to Vendor', permission: 'fleet-ops update work-order' }, + { id: 'edit', icon: 'edit', fn: this.edit, permission: 'fleet-ops update work-order' }, + { id: 'delete', icon: 'trash', fn: this.delete, type: 'danger', permission: 'fleet-ops delete work-order' }, ]; } diff --git a/addon/controllers/management/contacts/customers.js b/addon/controllers/management/contacts/customers.js index 91bd0c654..65375b6e8 100644 --- a/addon/controllers/management/contacts/customers.js +++ b/addon/controllers/management/contacts/customers.js @@ -18,6 +18,7 @@ export default class ManagementContactsCustomersController extends ManagementCon get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -31,6 +32,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -41,6 +43,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'click-to-copy', @@ -51,6 +54,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'title', label: this.intl.t('column.title'), valuePath: 'title', cellComponent: 'click-to-copy', @@ -62,6 +66,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'email', label: this.intl.t('column.email'), valuePath: 'email', cellComponent: 'click-to-copy', @@ -72,6 +77,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'phone', label: this.intl.t('column.phone'), valuePath: 'phone', cellComponent: 'click-to-copy', @@ -82,6 +88,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'address', label: this.intl.t('column.address'), valuePath: 'address', cellComponent: 'cell/place-identity', @@ -94,6 +101,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/string', }, { + id: 'created-at', label: this.intl.t('column.created'), valuePath: 'createdAt', sortParam: 'created_at', @@ -104,6 +112,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -115,6 +124,7 @@ export default class ManagementContactsCustomersController extends ManagementCon filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -127,12 +137,14 @@ export default class ManagementContactsCustomersController extends ManagementCon width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.customer') }), icon: 'eye', fn: this.customerActions.transition.view, permission: 'fleet-ops view contact', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.customer') }), icon: 'pencil', fn: this.customerActions.transition.edit, @@ -146,6 +158,7 @@ export default class ManagementContactsCustomersController extends ManagementCon separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.customer') }), icon: 'trash', fn: this.customerActions.delete, diff --git a/addon/controllers/management/contacts/index.js b/addon/controllers/management/contacts/index.js index 056a1a696..714766d82 100644 --- a/addon/controllers/management/contacts/index.js +++ b/addon/controllers/management/contacts/index.js @@ -12,7 +12,28 @@ export default class ManagementContactsIndexController extends Controller { @service appCache; /** query params */ - @tracked queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'internal_id', 'created_by', 'updated_by', 'status', 'title', 'email', 'phone']; + /** + * This tab's table registry, e.g. `fleet-ops:table:contact`. The contacts + * header (`management/contacts.hbs`) renders for whichever tab is open. + */ + get tableRegistry() { + return this.contactActions.tableRegistry; + } + + @tracked queryParams = this.contactActions.queryParamsFor([ + 'page', + 'limit', + 'sort', + 'query', + 'public_id', + 'internal_id', + 'created_by', + 'updated_by', + 'status', + 'title', + 'email', + 'phone', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -34,16 +55,19 @@ export default class ManagementContactsIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', items: [ { + id: 'table-view', label: this.intl.t('common.table-view'), icon: 'table-list', onClick: () => this.setLayout('table'), }, { + id: 'grid-view', label: this.intl.t('common.grid-view'), icon: 'grip', onClick: () => this.setLayout('grid'), @@ -53,11 +77,13 @@ export default class ManagementContactsIndexController extends Controller { helpText: this.intl.t('common.change-layout'), }, { + id: 'refresh', icon: 'refresh', onClick: this.contactActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -65,6 +91,7 @@ export default class ManagementContactsIndexController extends Controller { permission: 'fleet-ops create contact', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -72,6 +99,7 @@ export default class ManagementContactsIndexController extends Controller { permission: 'fleet-ops import contact', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -88,6 +116,7 @@ export default class ManagementContactsIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.contactActions.bulkDelete, @@ -100,6 +129,7 @@ export default class ManagementContactsIndexController extends Controller { get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -112,6 +142,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -121,6 +152,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'click-to-copy', @@ -130,6 +162,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'title', label: this.intl.t('column.title'), valuePath: 'title', cellComponent: 'click-to-copy', @@ -140,6 +173,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'email', label: this.intl.t('column.email'), valuePath: 'email', cellComponent: 'click-to-copy', @@ -149,6 +183,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'phone', label: this.intl.t('column.phone'), valuePath: 'phone', cellComponent: 'click-to-copy', @@ -158,6 +193,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'address', label: this.intl.t('column.address'), valuePath: 'address', cellComponent: 'cell/place-identity', @@ -170,6 +206,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'created-at', label: this.intl.t('column.created'), valuePath: 'createdAt', sortParam: 'created_at', @@ -179,6 +216,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -189,6 +227,7 @@ export default class ManagementContactsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -201,12 +240,14 @@ export default class ManagementContactsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.contact') }), icon: 'eye', fn: this.contactActions.transition.view, permission: 'fleet-ops view contact', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.contact') }), icon: 'pencil', fn: this.contactActions.transition.edit, @@ -220,6 +261,7 @@ export default class ManagementContactsIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.contact') }), icon: 'trash', fn: this.contactActions.delete, diff --git a/addon/controllers/management/drivers/index.js b/addon/controllers/management/drivers/index.js index 30612981f..a5da9ae68 100644 --- a/addon/controllers/management/drivers/index.js +++ b/addon/controllers/management/drivers/index.js @@ -17,7 +17,7 @@ export default class ManagementDriversIndexController extends Controller { @service appCache; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.driverActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -34,7 +34,7 @@ export default class ManagementDriversIndexController extends Controller { 'created_at', 'updated_at', 'status', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -75,16 +75,19 @@ export default class ManagementDriversIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', items: [ { + id: 'table-view', label: this.intl.t('common.table-view'), icon: 'table-list', onClick: () => this.changeLayout('table'), }, { + id: 'grid-view', label: this.intl.t('common.grid-view'), icon: 'grip', onClick: () => this.changeLayout('grid'), @@ -94,11 +97,13 @@ export default class ManagementDriversIndexController extends Controller { helpText: 'Change the layout', }, { + id: 'refresh', icon: 'refresh', onClick: this.driverActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -106,6 +111,7 @@ export default class ManagementDriversIndexController extends Controller { permission: 'fleet-ops create driver', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -113,6 +119,7 @@ export default class ManagementDriversIndexController extends Controller { permission: 'fleet-ops import driver', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -129,6 +136,7 @@ export default class ManagementDriversIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.driverActions.bulkDelete, @@ -141,6 +149,7 @@ export default class ManagementDriversIndexController extends Controller { get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -153,6 +162,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -163,6 +173,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'phone', label: this.intl.t('column.phone'), valuePath: 'phone', cellComponent: 'table/cell/base', @@ -173,6 +184,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'drivers-license-number', label: this.intl.t('column.license'), valuePath: 'drivers_license_number', cellComponent: 'table/cell/base', @@ -182,6 +194,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'vehicle-display-name', label: this.intl.t('column.vehicle'), cellComponent: 'cell/vehicle-identity', permission: 'fleet-ops view vehicle', @@ -206,6 +219,7 @@ export default class ManagementDriversIndexController extends Controller { model: 'vehicle', }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'click-to-copy', @@ -215,6 +229,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'vendor-name', label: this.intl.t('column.vendor'), cellComponent: 'cell/vendor-identity', permission: 'fleet-ops view vendor', @@ -233,6 +248,7 @@ export default class ManagementDriversIndexController extends Controller { model: 'vendor', }, { + id: 'fleets', label: this.intl.t('column.fleet'), cellComponent: 'table/cell/link-list', cellComponentLabelPath: 'name', @@ -247,6 +263,7 @@ export default class ManagementDriversIndexController extends Controller { model: 'fleet', }, { + id: 'country', label: this.intl.t('column.country'), valuePath: 'country', cellComponent: 'table/cell/country', @@ -264,6 +281,7 @@ export default class ManagementDriversIndexController extends Controller { multiOptionSearchPlaceholder: this.intl.t('common.search-countries'), }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -274,6 +292,7 @@ export default class ManagementDriversIndexController extends Controller { filterFetchOptions: 'drivers/statuses', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -284,6 +303,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -295,6 +315,7 @@ export default class ManagementDriversIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -307,12 +328,14 @@ export default class ManagementDriversIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.driver') }), icon: 'eye', fn: this.driverActions.transition.view, permission: 'fleet-ops view driver', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.driver') }), icon: 'pencil', fn: this.driverActions.transition.edit, @@ -322,18 +345,21 @@ export default class ManagementDriversIndexController extends Controller { separator: true, }, { + id: 'assign-order', label: this.intl.t('driver.actions.assign-order'), icon: 'clipboard-list', fn: this.driverActions.assignOrder, permission: 'fleet-ops assign-order-for driver', }, { + id: 'assign-vehicle', label: this.intl.t('driver.actions.assign-vehicle'), icon: 'car', fn: this.driverActions.assignVehicle, permission: 'fleet-ops assign-vehicle-for driver', }, { + id: 'unassign-orders', label: this.intl.t('driver.actions.unassign-orders'), icon: 'user-minus', fn: this.driverActions.unassignOrders, @@ -341,6 +367,7 @@ export default class ManagementDriversIndexController extends Controller { isVisible: (driver) => Number(driver.assigned_orders_count) > 0, }, { + id: 'unassign-vehicle', label: this.intl.t('driver.actions.unassign-vehicle'), icon: 'link-slash', fn: this.driverActions.unassignVehicle, @@ -348,12 +375,14 @@ export default class ManagementDriversIndexController extends Controller { isVisible: (driver) => this.hasAssignedVehicle(driver), }, { + id: 'locate', label: this.intl.t('driver.actions.locate-driver'), icon: 'location-dot', fn: this.driverActions.locate, permission: 'fleet-ops view driver', }, { + id: 'create-issue', label: this.intl.t('driver.actions.create-issue'), icon: 'triangle-exclamation', fn: this.createIssue, @@ -367,6 +396,7 @@ export default class ManagementDriversIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.driver') }), icon: 'trash', fn: this.driverActions.delete, diff --git a/addon/controllers/management/drivers/index/details.js b/addon/controllers/management/drivers/index/details.js index 2f9689fac..b26c37c23 100644 --- a/addon/controllers/management/drivers/index/details.js +++ b/addon/controllers/management/drivers/index/details.js @@ -39,6 +39,7 @@ export default class ManagementDriverIndexDetailsController extends Controller { permission: 'fleet-ops update driver', }, { + id: 'more', icon: 'ellipsis-h', iconPrefix: 'fas', renderInPlace: true, diff --git a/addon/controllers/management/fleets/index.js b/addon/controllers/management/fleets/index.js index 80f6d84ae..e69a840e1 100644 --- a/addon/controllers/management/fleets/index.js +++ b/addon/controllers/management/fleets/index.js @@ -15,7 +15,22 @@ export default class ManagementFleetsIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = ['page', 'limit', 'sort', 'query', 'public_id', 'zone', 'service_area', 'parent_fleet', 'vendor', 'created_by', 'updated_by', 'status', 'task', 'name']; + @tracked queryParams = this.fleetActions.queryParamsFor([ + 'page', + 'limit', + 'sort', + 'query', + 'public_id', + 'zone', + 'service_area', + 'parent_fleet', + 'vendor', + 'created_by', + 'updated_by', + 'status', + 'task', + 'name', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -33,11 +48,13 @@ export default class ManagementFleetsIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.fleetActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -45,6 +62,7 @@ export default class ManagementFleetsIndexController extends Controller { permission: 'fleet-ops create fleet', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -52,6 +70,7 @@ export default class ManagementFleetsIndexController extends Controller { permission: 'fleet-ops import fleet', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -68,6 +87,7 @@ export default class ManagementFleetsIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.fleetActions.bulkDelete, @@ -80,6 +100,7 @@ export default class ManagementFleetsIndexController extends Controller { get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -93,6 +114,7 @@ export default class ManagementFleetsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'service-area-name', label: this.intl.t('column.service-area'), cellComponent: 'cell/service-area-identity', permission: 'fleet-ops view service-area', @@ -107,6 +129,7 @@ export default class ManagementFleetsIndexController extends Controller { model: 'service-area', }, { + id: 'parent-fleet-name', label: this.intl.t('column.parent-fleet'), cellComponent: 'cell/fleet-identity', permission: 'fleet-ops view fleet', @@ -120,6 +143,7 @@ export default class ManagementFleetsIndexController extends Controller { model: 'fleet', }, { + id: 'vendor-name', label: this.intl.t('column.vendor'), cellComponent: 'cell/vendor-identity', permission: 'fleet-ops view vendor', @@ -134,6 +158,7 @@ export default class ManagementFleetsIndexController extends Controller { model: 'vendor', }, { + id: 'zone-name', label: this.intl.t('column.zone'), cellComponent: 'cell/zone-identity', permission: 'fleet-ops view zone', @@ -147,6 +172,7 @@ export default class ManagementFleetsIndexController extends Controller { model: 'zone', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -158,6 +184,7 @@ export default class ManagementFleetsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'drivers-count', label: this.intl.t('column.manpower'), valuePath: 'drivers_count', resizable: true, @@ -165,6 +192,7 @@ export default class ManagementFleetsIndexController extends Controller { filterable: false, }, { + id: 'drivers-online-count', label: this.intl.t('column.active-manpower'), valuePath: 'drivers_online_count', hidden: true, @@ -173,6 +201,7 @@ export default class ManagementFleetsIndexController extends Controller { filterable: false, }, { + id: 'task', label: this.intl.t('column.task'), valuePath: 'task', cellComponent: 'table/cell/base', @@ -182,6 +211,7 @@ export default class ManagementFleetsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -194,6 +224,7 @@ export default class ManagementFleetsIndexController extends Controller { filterOptions: fleetOpsOptions('fleetStatuses'), }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -203,6 +234,7 @@ export default class ManagementFleetsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -213,6 +245,7 @@ export default class ManagementFleetsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -225,21 +258,25 @@ export default class ManagementFleetsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.fleet') }), fn: this.fleetActions.transition.view, permission: 'fleet-ops view fleet', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.fleet') }), fn: this.fleetActions.transition.edit, permission: 'fleet-ops update fleet', }, { + id: 'assign-driver', label: this.intl.t('fleet.actions.assign-driver'), permission: 'fleet-ops assign-driver-for fleet', fn: this.fleetActions.assignDriver, }, { + id: 'assign-vehicle', label: this.intl.t('fleet.actions.assign-vehicle'), permission: 'fleet-ops assign-vehicle-for fleet', fn: this.fleetActions.assignVehicle, @@ -248,6 +285,7 @@ export default class ManagementFleetsIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.fleet') }), fn: this.fleetActions.delete, permission: 'fleet-ops delete fleet', diff --git a/addon/controllers/management/fleets/index/details.js b/addon/controllers/management/fleets/index/details.js index 56807d64c..45fe88194 100644 --- a/addon/controllers/management/fleets/index/details.js +++ b/addon/controllers/management/fleets/index/details.js @@ -35,6 +35,7 @@ export default class ManagementFleetsIndexDetailsController extends Controller { permission: 'fleet-ops update fleet', }, { + id: 'more', icon: 'ellipsis-h', iconPrefix: 'fas', renderInPlace: true, diff --git a/addon/controllers/management/fuel-reports/index.js b/addon/controllers/management/fuel-reports/index.js index cdf74dfbe..3b087751b 100644 --- a/addon/controllers/management/fuel-reports/index.js +++ b/addon/controllers/management/fuel-reports/index.js @@ -10,7 +10,7 @@ export default class ManagementFuelReportsIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.fuelReportActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -27,7 +27,7 @@ export default class ManagementFuelReportsIndexController extends Controller { 'country', 'volume', 'odometer', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -47,11 +47,13 @@ export default class ManagementFuelReportsIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.fuelReportActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -59,6 +61,7 @@ export default class ManagementFuelReportsIndexController extends Controller { permission: 'fleet-ops create fuel-report', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -66,6 +69,7 @@ export default class ManagementFuelReportsIndexController extends Controller { permission: 'fleet-ops import fuel-report', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -82,6 +86,7 @@ export default class ManagementFuelReportsIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.fuelReportActions.bulkDelete, @@ -94,6 +99,7 @@ export default class ManagementFuelReportsIndexController extends Controller { get columns() { return [ { + id: 'public-id', sticky: true, label: this.intl.t('column.id'), valuePath: 'public_id', @@ -106,6 +112,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'reporter-name', label: this.intl.t('column.reporter'), valuePath: 'reporter_name', cellComponent: 'table/cell/user-identity', @@ -120,6 +127,7 @@ export default class ManagementFuelReportsIndexController extends Controller { model: 'user', }, { + id: 'driver-name', label: this.intl.t('column.driver'), valuePath: 'driver_name', cellComponent: 'cell/driver-identity', @@ -136,6 +144,7 @@ export default class ManagementFuelReportsIndexController extends Controller { model: 'driver', }, { + id: 'vehicle-name', label: this.intl.t('column.vehicle'), valuePath: 'vehicle_name', cellComponent: 'cell/vehicle-identity', @@ -153,6 +162,7 @@ export default class ManagementFuelReportsIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -163,6 +173,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterOptions: ['draft', 'pending-approval', 'approved', 'rejected', 'revised', 'submitted', 'in-review', 'confirmed', 'processed', 'archived', 'cancelled'], }, { + id: 'source', label: 'Source', valuePath: 'source', resizable: true, @@ -172,6 +183,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterOptions: ['manual', 'import', 'fuel_provider'], }, { + id: 'provider', label: 'Provider', valuePath: 'provider', resizable: true, @@ -180,6 +192,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'volume', label: this.intl.t('column.volume'), valuePath: 'volume', cellComponent: 'click-to-copy', @@ -190,6 +203,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'odometer', label: this.intl.t('column.odometer'), valuePath: 'odometer', cellComponent: 'click-to-copy', @@ -200,6 +214,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -209,6 +224,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -219,6 +235,7 @@ export default class ManagementFuelReportsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -231,11 +248,13 @@ export default class ManagementFuelReportsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.fuel-report') }), fn: this.fuelReportActions.transition.view, permission: 'fleet-ops view fuel-report', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.fuel-report') }), fn: this.fuelReportActions.transition.edit, permission: 'fleet-ops update fuel-report', @@ -244,6 +263,7 @@ export default class ManagementFuelReportsIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.fuel-report') }), fn: this.fuelReportActions.delete, permission: 'fleet-ops delete fuel-report', diff --git a/addon/controllers/management/fuel-transactions/index.js b/addon/controllers/management/fuel-transactions/index.js index 30e940e3e..f3e1bfa52 100644 --- a/addon/controllers/management/fuel-transactions/index.js +++ b/addon/controllers/management/fuel-transactions/index.js @@ -63,11 +63,13 @@ export default class ManagementFuelTransactionsIndexController extends Controlle get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.refresh, helpText: 'Refresh', }, { + id: 'fuel-integrations', icon: 'gas-pump', text: 'Fuel Integrations', onClick: () => this.hostRouter.transitionTo('console.fleet-ops.connectivity.fuel-providers.index'), @@ -85,6 +87,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle return [ { + id: 'bulk-reprocess', label: `Reprocess ${selected.length} selected`, fn: () => this.confirmAction('reprocess', selected), permission: 'fleet-ops update fuel-provider-transaction', @@ -95,6 +98,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle get columns() { return [ { + id: 'provider-transaction-id', sticky: true, label: 'Transaction', valuePath: 'provider_transaction_id', @@ -107,6 +111,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle filterComponent: 'filter/string', }, { + id: 'provider', label: 'Provider', valuePath: 'provider', resizable: true, @@ -115,6 +120,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle filterComponent: 'filter/string', }, { + id: 'sync-status', label: 'Status', valuePath: 'sync_status', cellComponent: 'fuel-transaction-status', @@ -125,6 +131,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle filterOptions: ['imported', 'matched', 'unmatched', 'reviewed', 'ignored', 'duplicate', 'error'], }, { + id: 'vehicle-name', label: 'Vehicle', valuePath: 'vehicle_name', cellComponent: 'cell/vehicle-identity', @@ -139,28 +146,33 @@ export default class ManagementFuelTransactionsIndexController extends Controlle modelNamePath: 'displayName', }, { + id: 'vehicle-card-id', label: 'Card / Internal', valuePath: 'vehicle_card_id', resizable: true, }, { + id: 'trip-number', label: 'Trip', valuePath: 'trip_number', resizable: true, hidden: true, }, { + id: 'station-name', label: 'Station', valuePath: 'station_name', resizable: true, }, { + id: 'volume', label: 'Liters', valuePath: 'volume', resizable: true, sortable: true, }, { + id: 'amount', label: 'Amount', valuePath: 'amount', cellComponent: 'table/cell/currency', @@ -168,6 +180,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle sortable: true, }, { + id: 'fuel-report-id', label: 'Fuel Report', valuePath: 'fuel_report_id', cellComponent: 'cell/fuel-report-identity', @@ -177,6 +190,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle resizable: true, }, { + id: 'transaction-at', label: 'Date', valuePath: 'transactionAt', sortParam: 'transaction_at', @@ -187,6 +201,7 @@ export default class ManagementFuelTransactionsIndexController extends Controlle filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -198,14 +213,35 @@ export default class ManagementFuelTransactionsIndexController extends Controlle sticky: 'right', width: 60, actions: [ - { label: 'Review Details', fn: this.openDetails, permission: 'fleet-ops view fuel-provider-transaction' }, - { label: 'Open Fuel Report', fn: this.openFuelReport, isVisible: (transaction) => Boolean(transaction.fuel_report_id), permission: 'fleet-ops view fuel-report' }, + { id: 'open-details', label: 'Review Details', fn: this.openDetails, permission: 'fleet-ops view fuel-provider-transaction' }, + { + id: 'open-fuel-report', + label: 'Open Fuel Report', + fn: this.openFuelReport, + isVisible: (transaction) => Boolean(transaction.fuel_report_id), + permission: 'fleet-ops view fuel-report', + }, { separator: true }, - { label: 'Match to Vehicle', fn: this.matchVehicle, permission: 'fleet-ops update fuel-provider-transaction' }, - { label: 'Match to Order', fn: this.matchOrder, permission: 'fleet-ops update fuel-provider-transaction' }, - { label: 'Reprocess / Rematch', fn: (transaction) => this.confirmAction('reprocess', transaction), permission: 'fleet-ops update fuel-provider-transaction' }, - { label: 'Ignore Transaction', fn: (transaction) => this.confirmAction('ignored', transaction), permission: 'fleet-ops review fuel-provider-transaction' }, - { label: 'Mark Reviewed', fn: (transaction) => this.confirmAction('reviewed', transaction), permission: 'fleet-ops review fuel-provider-transaction' }, + { id: 'match-vehicle', label: 'Match to Vehicle', fn: this.matchVehicle, permission: 'fleet-ops update fuel-provider-transaction' }, + { id: 'match-order', label: 'Match to Order', fn: this.matchOrder, permission: 'fleet-ops update fuel-provider-transaction' }, + { + id: 'reprocess', + label: 'Reprocess / Rematch', + fn: (transaction) => this.confirmAction('reprocess', transaction), + permission: 'fleet-ops update fuel-provider-transaction', + }, + { + id: 'ignore', + label: 'Ignore Transaction', + fn: (transaction) => this.confirmAction('ignored', transaction), + permission: 'fleet-ops review fuel-provider-transaction', + }, + { + id: 'mark-reviewed', + label: 'Mark Reviewed', + fn: (transaction) => this.confirmAction('reviewed', transaction), + permission: 'fleet-ops review fuel-provider-transaction', + }, ], sortable: false, filterable: false, diff --git a/addon/controllers/management/issues/index.js b/addon/controllers/management/issues/index.js index 5774b8865..f955153a1 100644 --- a/addon/controllers/management/issues/index.js +++ b/addon/controllers/management/issues/index.js @@ -11,7 +11,7 @@ export default class ManagementIssuesIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.issueActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -28,7 +28,7 @@ export default class ManagementIssuesIndexController extends Controller { 'priority', 'cateogry', 'type', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -47,11 +47,13 @@ export default class ManagementIssuesIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.issueActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -59,6 +61,7 @@ export default class ManagementIssuesIndexController extends Controller { permission: 'fleet-ops create issue', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -66,6 +69,7 @@ export default class ManagementIssuesIndexController extends Controller { permission: 'fleet-ops import issue', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -82,6 +86,7 @@ export default class ManagementIssuesIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.issueActions.bulkDelete, @@ -94,6 +99,7 @@ export default class ManagementIssuesIndexController extends Controller { get columns() { return [ { + id: 'public-id', sticky: true, label: this.intl.t('column.id'), valuePath: 'public_id', @@ -104,6 +110,7 @@ export default class ManagementIssuesIndexController extends Controller { sortable: true, }, { + id: 'priority', label: this.intl.t('column.priority'), valuePath: 'priority', cellComponent: 'table/cell/status', @@ -114,6 +121,7 @@ export default class ManagementIssuesIndexController extends Controller { filterOptions: ['low', 'medium', 'high', 'critical', 'scheduled-maintenance', 'operational-suggestion'], }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', humanize: true, @@ -127,6 +135,7 @@ export default class ManagementIssuesIndexController extends Controller { placeholder: 'Select issue type', }, { + id: 'category', label: this.intl.t('column.category'), valuePath: 'category', humanize: true, @@ -140,6 +149,7 @@ export default class ManagementIssuesIndexController extends Controller { placeholder: 'Select issue category', }, { + id: 'reporter-name', label: this.intl.t('column.reporter'), valuePath: 'reporter_name', cellComponent: 'table/cell/user-identity', @@ -155,6 +165,7 @@ export default class ManagementIssuesIndexController extends Controller { model: 'user', }, { + id: 'assignee-name', label: this.intl.t('column.assignee'), valuePath: 'assignee_name', cellComponent: 'table/cell/user-identity', @@ -170,6 +181,7 @@ export default class ManagementIssuesIndexController extends Controller { model: 'user', }, { + id: 'driver-name', label: this.intl.t('column.driver'), valuePath: 'driver_name', cellComponent: 'cell/driver-identity', @@ -186,6 +198,7 @@ export default class ManagementIssuesIndexController extends Controller { model: 'driver', }, { + id: 'vehicle-name', label: this.intl.t('column.vehicle'), valuePath: 'vehicle_name', cellComponent: 'cell/vehicle-identity', @@ -203,6 +216,7 @@ export default class ManagementIssuesIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -213,6 +227,7 @@ export default class ManagementIssuesIndexController extends Controller { filterOptions: ['pending', 'in-progress', 'backlogged', 'requires-update', 'in-review', 're-opened', 'duplicate', 'pending-review', 'escalated', 'completed', 'canceled'], }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -222,6 +237,7 @@ export default class ManagementIssuesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -232,6 +248,7 @@ export default class ManagementIssuesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -244,11 +261,13 @@ export default class ManagementIssuesIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.issue') }), fn: this.issueActions.transition.view, permission: 'fleet-ops view issue', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.issue') }), fn: this.issueActions.transition.edit, permission: 'fleet-ops update issue', @@ -257,6 +276,7 @@ export default class ManagementIssuesIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.issue') }), fn: this.issueActions.delete, permission: 'fleet-ops delete issue', diff --git a/addon/controllers/management/issues/index/details.js b/addon/controllers/management/issues/index/details.js index 748d72224..06579a11a 100644 --- a/addon/controllers/management/issues/index/details.js +++ b/addon/controllers/management/issues/index/details.js @@ -20,6 +20,7 @@ export default class ManagementIssuesIndexDetailsController extends Controller { fn: () => this.hostRouter.transitionTo('console.fleet-ops.management.issues.index.edit', this.model), }, { + id: 'more', icon: 'ellipsis', type: 'default', items: this.issueActions.workflowItems(this.model, () => this.refreshIssue()), diff --git a/addon/controllers/management/places/index.js b/addon/controllers/management/places/index.js index 6fdc416b4..b0bc0bd0a 100644 --- a/addon/controllers/management/places/index.js +++ b/addon/controllers/management/places/index.js @@ -8,7 +8,21 @@ export default class ManagementPlacesIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = ['name', 'page', 'limit', 'sort', 'query', 'public_id', 'country', 'phone', 'created_at', 'updated_at', 'city', 'neighborhood', 'state']; + @tracked queryParams = this.placeActions.queryParamsFor([ + 'name', + 'page', + 'limit', + 'sort', + 'query', + 'public_id', + 'country', + 'phone', + 'created_at', + 'updated_at', + 'city', + 'neighborhood', + 'state', + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -25,11 +39,13 @@ export default class ManagementPlacesIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.placeActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -37,6 +53,7 @@ export default class ManagementPlacesIndexController extends Controller { permission: 'fleet-ops create place', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -44,6 +61,7 @@ export default class ManagementPlacesIndexController extends Controller { permission: 'fleet-ops import place', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -60,6 +78,7 @@ export default class ManagementPlacesIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.placeActions.bulkDelete, @@ -72,6 +91,7 @@ export default class ManagementPlacesIndexController extends Controller { get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -87,6 +107,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'address', sticky: true, label: this.intl.t('column.address'), valuePath: 'address', @@ -100,6 +121,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -110,6 +132,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'city', label: this.intl.t('column.city'), valuePath: 'city', cellComponent: 'table/cell/anchor', @@ -124,6 +147,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'state', label: this.intl.t('column.state'), valuePath: 'state', cellComponent: 'table/cell/anchor', @@ -138,6 +162,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'postal-code', label: this.intl.t('column.postal-code'), valuePath: 'postal_code', cellComponent: 'table/cell/anchor', @@ -149,6 +174,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'country-name', label: this.intl.t('column.country'), valuePath: 'country_name', cellComponent: 'table/cell/base', @@ -160,6 +186,7 @@ export default class ManagementPlacesIndexController extends Controller { filterParam: 'country', }, { + id: 'neighborhood', label: this.intl.t('column.neighborhood'), valuePath: 'neighborhood', cellComponent: 'table/cell/anchor', @@ -174,6 +201,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'phone', label: this.intl.t('column.phone'), valuePath: 'phone', cellComponent: 'table/cell/base', @@ -184,6 +212,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -193,6 +222,7 @@ export default class ManagementPlacesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -204,6 +234,7 @@ export default class ManagementPlacesIndexController extends Controller { }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -216,11 +247,13 @@ export default class ManagementPlacesIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.place') }), fn: this.placeActions.transition.view, permission: 'fleet-ops view place', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.place') }), fn: this.placeActions.transition.edit, permission: 'fleet-ops update place', @@ -229,6 +262,7 @@ export default class ManagementPlacesIndexController extends Controller { separator: true, }, { + id: 'locate', label: this.intl.t('place.actions.locate-place', { resource: this.intl.t('resource.place') }), fn: this.placeActions.locate, permission: 'fleet-ops view place', @@ -237,6 +271,7 @@ export default class ManagementPlacesIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.place') }), fn: this.placeActions.delete, permission: 'fleet-ops delete place', diff --git a/addon/controllers/management/trailers/index.js b/addon/controllers/management/trailers/index.js index 43fc27013..3020697c7 100644 --- a/addon/controllers/management/trailers/index.js +++ b/addon/controllers/management/trailers/index.js @@ -16,7 +16,7 @@ export default class ManagementTrailersIndexController extends Controller { @service store; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.trailerActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -42,7 +42,7 @@ export default class ManagementTrailersIndexController extends Controller { 'last_online_at', 'created_at', 'updated_at', - ]; + ]); @tracked query = null; @tracked page = 1; @tracked limit; @@ -75,16 +75,19 @@ export default class ManagementTrailersIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', items: [ { + id: 'table-view', label: this.intl.t('common.table-view'), icon: 'table-list', onClick: () => this.setLayout('table'), }, { + id: 'grid-view', label: this.intl.t('common.grid-view'), icon: 'grip', onClick: () => this.setLayout('grid'), @@ -94,11 +97,13 @@ export default class ManagementTrailersIndexController extends Controller { helpText: this.intl.t('common.change-layout'), }, { + id: 'refresh', icon: 'refresh', onClick: this.trailerActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -106,6 +111,7 @@ export default class ManagementTrailersIndexController extends Controller { permission: 'fleet-ops create trailer', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -113,6 +119,7 @@ export default class ManagementTrailersIndexController extends Controller { permission: 'fleet-ops import trailer', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -129,6 +136,7 @@ export default class ManagementTrailersIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.trailerActions.bulkDelete, @@ -161,6 +169,7 @@ export default class ManagementTrailersIndexController extends Controller { get columns() { return [ { + id: 'display-name', sticky: true, label: this.intl.t('trailer.columns.name'), valuePath: 'displayName', @@ -175,6 +184,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'name', }, { + id: 'type', label: this.intl.t('trailer.columns.type'), valuePath: 'type', cellComponent: 'cell/translated-value', @@ -190,6 +200,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 130, }, { + id: 'plate-number', label: this.intl.t('trailer.columns.plate-number'), valuePath: 'plate_number', cellComponent: 'table/cell/base', @@ -201,6 +212,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'plate_number', }, { + id: 'code', label: this.intl.t('trailer.columns.code'), valuePath: 'code', cellComponent: 'table/cell/base', @@ -211,6 +223,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'code', }, { + id: 'current-vehicle-name', label: this.intl.t('trailer.columns.vehicle'), valuePath: 'current_vehicle_name', cellComponent: 'cell/vehicle-identity', @@ -232,6 +245,7 @@ export default class ManagementTrailersIndexController extends Controller { model: 'vehicle', }, { + id: 'attachment-state', label: this.intl.t('trailer.columns.attachment-state'), valuePath: 'attachment_state', cellComponent: 'cell/translated-value', @@ -248,6 +262,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 120, }, { + id: 'status', label: this.intl.t('trailer.columns.status'), valuePath: 'status', cellComponent: 'cell/translated-value', @@ -264,6 +279,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 120, }, { + id: 'connectivity-status', label: this.intl.t('trailer.columns.connectivity'), valuePath: 'connectivity_status', cellComponent: 'cell/translated-value', @@ -279,6 +295,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 140, }, { + id: 'last-online-at', label: this.intl.t('trailer.columns.last-online'), valuePath: 'lastOnlineAt', sortParam: 'last_online_at', @@ -290,6 +307,7 @@ export default class ManagementTrailersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'location', label: this.intl.t('trailer.columns.location'), valuePath: 'location', cellComponent: 'table/cell/point', @@ -300,6 +318,7 @@ export default class ManagementTrailersIndexController extends Controller { sortable: false, }, { + id: 'devices-count', label: this.intl.t('trailer.columns.devices'), valuePath: 'devices_count', cellComponent: 'table/cell/base', @@ -309,6 +328,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 90, }, { + id: 'equipment-count', label: this.intl.t('trailer.columns.equipment'), valuePath: 'equipment_count', cellComponent: 'table/cell/base', @@ -318,6 +338,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 100, }, { + id: 'public-id', label: this.intl.t('trailer.columns.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -329,6 +350,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'public_id', }, { + id: 'vin', label: this.intl.t('trailer.columns.vin'), valuePath: 'vin', cellComponent: 'table/cell/base', @@ -340,6 +362,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'vin', }, { + id: 'serial-number', label: this.intl.t('trailer.columns.serial-number'), valuePath: 'serial_number', cellComponent: 'table/cell/base', @@ -351,6 +374,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'serial_number', }, { + id: 'make', label: this.intl.t('trailer.columns.make'), valuePath: 'make', cellComponent: 'table/cell/base', @@ -362,6 +386,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'trailer_make', }, { + id: 'model', label: this.intl.t('trailer.columns.model'), valuePath: 'model', cellComponent: 'table/cell/base', @@ -373,6 +398,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'trailer_model', }, { + id: 'year', label: this.intl.t('trailer.columns.year'), valuePath: 'year', cellComponent: 'table/cell/base', @@ -384,6 +410,7 @@ export default class ManagementTrailersIndexController extends Controller { filterParam: 'trailer_year', }, { + id: 'vendor-name', label: this.intl.t('trailer.columns.vendor'), valuePath: 'vendor_name', cellComponent: 'cell/vendor-identity', @@ -401,6 +428,7 @@ export default class ManagementTrailersIndexController extends Controller { model: 'vendor', }, { + id: 'ownership-type', label: this.intl.t('trailer.columns.ownership'), valuePath: 'ownership_type', cellComponent: 'cell/translated-value', @@ -416,6 +444,7 @@ export default class ManagementTrailersIndexController extends Controller { filterOptionValue: 'value', }, { + id: 'axle-count', label: this.intl.t('trailer.columns.axles'), valuePath: 'axle_count', cellComponent: 'table/cell/base', @@ -426,6 +455,7 @@ export default class ManagementTrailersIndexController extends Controller { width: 90, }, { + id: 'gvwr', label: this.intl.t('trailer.columns.gvwr'), valuePath: 'gvwr', cellComponent: 'table/cell/base', @@ -435,6 +465,7 @@ export default class ManagementTrailersIndexController extends Controller { filterable: false, }, { + id: 'payload-capacity', label: this.intl.t('trailer.columns.payload-capacity'), valuePath: 'payload_capacity', cellComponent: 'table/cell/base', @@ -444,6 +475,7 @@ export default class ManagementTrailersIndexController extends Controller { filterable: false, }, { + id: 'length', label: this.intl.t('trailer.columns.length'), valuePath: 'length', cellComponent: 'table/cell/base', @@ -453,6 +485,7 @@ export default class ManagementTrailersIndexController extends Controller { filterable: false, }, { + id: 'created-at', label: this.intl.t('trailer.columns.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -464,6 +497,7 @@ export default class ManagementTrailersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('trailer.columns.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -476,6 +510,7 @@ export default class ManagementTrailersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -488,16 +523,19 @@ export default class ManagementTrailersIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.trailer') }), fn: this.trailerActions.transition.view, permission: 'fleet-ops view trailer', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.trailer') }), fn: this.trailerActions.transition.edit, permission: 'fleet-ops update trailer', }, { + id: 'locate', label: this.intl.t('trailer.actions.locate'), fn: this.trailerActions.locate, permission: 'fleet-ops view trailer', @@ -507,23 +545,27 @@ export default class ManagementTrailersIndexController extends Controller { separator: true, }, { + id: 'attach-vehicle', label: this.intl.t('trailer.actions.attach-vehicle'), fn: this.trailerActions.attachVehicle, permission: 'fleet-ops attach-vehicle-for trailer', isVisible: (trailer) => trailer.attachment_state !== 'attached', }, { + id: 'detach-vehicle', label: this.intl.t('trailer.actions.detach-vehicle'), fn: this.trailerActions.detachVehicle, permission: 'fleet-ops detach-vehicle-for trailer', isVisible: (trailer) => trailer.attachment_state === 'attached', }, { + id: 'attach-device', label: this.intl.t('trailer.actions.attach-device'), fn: this.trailerActions.attachDevice, permission: 'fleet-ops attach-device-for trailer', }, { + id: 'attach-equipment', label: this.intl.t('trailer.actions.attach-equipment'), fn: this.trailerActions.attachEquipment, permission: 'fleet-ops attach-equipment-for trailer', @@ -532,16 +574,19 @@ export default class ManagementTrailersIndexController extends Controller { separator: true, }, { + id: 'schedule-maintenance', label: this.intl.t('trailer.actions.schedule-maintenance'), fn: this.trailerActions.scheduleMaintenance, permission: 'fleet-ops create maintenance-schedule', }, { + id: 'create-work-order', label: this.intl.t('trailer.actions.create-work-order'), fn: this.trailerActions.createWorkOrder, permission: 'fleet-ops create work-order', }, { + id: 'log-maintenance', label: this.intl.t('trailer.actions.log-maintenance'), fn: this.trailerActions.logMaintenance, permission: 'fleet-ops create maintenance', @@ -550,6 +595,7 @@ export default class ManagementTrailersIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.trailer') }), fn: this.trailerActions.delete, permission: 'fleet-ops delete trailer', @@ -562,6 +608,7 @@ export default class ManagementTrailersIndexController extends Controller { searchable: false, }, { + id: 'devices', label: this.intl.t('resource.devices'), valuePath: 'devices', cellComponent: 'cell/resource-list', @@ -575,6 +622,7 @@ export default class ManagementTrailersIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'refrigerated', label: this.intl.t('trailer.columns.refrigerated'), valuePath: 'refrigerated', cellComponent: 'table/cell/checkbox', diff --git a/addon/controllers/management/trailers/index/details.js b/addon/controllers/management/trailers/index/details.js index 1f5907c79..74bb09217 100644 --- a/addon/controllers/management/trailers/index/details.js +++ b/addon/controllers/management/trailers/index/details.js @@ -32,6 +32,7 @@ export default class ManagementTrailersIndexDetailsController extends Controller permission: 'fleet-ops update trailer', }, { + id: 'more', // Actions dropdown — shared with the trailer context panel icon: 'ellipsis-h', iconPrefix: 'fas', diff --git a/addon/controllers/management/vehicles/index.js b/addon/controllers/management/vehicles/index.js index 1e63fbf4d..4ed54996d 100644 --- a/addon/controllers/management/vehicles/index.js +++ b/addon/controllers/management/vehicles/index.js @@ -16,7 +16,7 @@ export default class ManagementVehiclesIndexController extends Controller { @service appCache; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.vehicleActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -38,7 +38,7 @@ export default class ManagementVehiclesIndexController extends Controller { 'has_trailer', 'has_driver', 'has_device', - ]; + ]); @tracked query = null; @tracked page = 1; @tracked limit; @@ -68,6 +68,7 @@ export default class ManagementVehiclesIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', @@ -93,11 +94,13 @@ export default class ManagementVehiclesIndexController extends Controller { helpText: 'Change the layout', }, { + id: 'refresh', icon: 'refresh', onClick: this.vehicleActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -105,6 +108,7 @@ export default class ManagementVehiclesIndexController extends Controller { permission: 'fleet-ops create vehicle', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -112,6 +116,7 @@ export default class ManagementVehiclesIndexController extends Controller { permission: 'fleet-ops import vehicle', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -128,6 +133,7 @@ export default class ManagementVehiclesIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.vehicleActions.bulkDelete, @@ -151,6 +157,7 @@ export default class ManagementVehiclesIndexController extends Controller { get columns() { return [ { + id: 'display-name', sticky: true, label: this.intl.t('column.name'), valuePath: 'displayName', @@ -165,6 +172,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterParam: 'name', }, { + id: 'plate-number', label: this.intl.t('column.plate-number'), valuePath: 'plate_number', cellComponent: 'table/cell/base', @@ -176,6 +184,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterParam: 'plate_number', }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'table/cell/base', @@ -188,6 +197,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterParam: 'internal_id', }, { + id: 'driver-name', label: this.intl.t('column.driver-assigned'), cellComponent: 'cell/driver-identity', permission: 'fleet-ops view driver', @@ -203,6 +213,7 @@ export default class ManagementVehiclesIndexController extends Controller { model: 'driver', }, { + id: 'trailers', label: this.intl.t('resource.trailers'), valuePath: 'trailers', cellComponent: 'cell/resource-list', @@ -216,6 +227,7 @@ export default class ManagementVehiclesIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'devices', label: this.intl.t('resource.devices'), valuePath: 'devices', cellComponent: 'cell/resource-list', @@ -229,6 +241,7 @@ export default class ManagementVehiclesIndexController extends Controller { modelNamePath: 'displayName', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -238,6 +251,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'make', label: this.intl.t('column.make'), valuePath: 'make', cellComponent: 'table/cell/base', @@ -249,6 +263,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'model', label: this.intl.t('column.model'), valuePath: 'model', cellComponent: 'table/cell/base', @@ -260,6 +275,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'year', label: this.intl.t('column.year'), valuePath: 'year', cellComponent: 'table/cell/base', @@ -270,6 +286,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'vendor-name', label: this.intl.t('column.vendor'), cellComponent: 'cell/vendor-identity', permission: 'fleet-ops view vendor', @@ -287,6 +304,7 @@ export default class ManagementVehiclesIndexController extends Controller { model: 'vendor', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -297,6 +315,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterFetchOptions: 'vehicles/statuses', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -308,6 +327,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -351,6 +371,7 @@ export default class ManagementVehiclesIndexController extends Controller { filterParam: 'has_device', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -363,26 +384,31 @@ export default class ManagementVehiclesIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.vehicle') }), fn: this.vehicleActions.transition.view, permission: 'fleet-ops view vehicle', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.vehicle') }), fn: this.vehicleActions.transition.edit, permission: 'fleet-ops update vehicle', }, { + id: 'locate', label: this.intl.t('vehicle.actions.locate-vehicle'), fn: this.vehicleActions.locate, permission: 'fleet-ops view vehicle', }, { + id: 'attach-device', label: this.intl.t('vehicle.actions.attach-device'), fn: this.vehicleActions.attachDevice, permission: 'fleet-ops update vehicle', }, { + id: 'unassign-orders', label: this.intl.t('vehicle.actions.unassign-orders'), fn: this.vehicleActions.unassignOrders, permission: 'fleet-ops update vehicle', @@ -392,21 +418,25 @@ export default class ManagementVehiclesIndexController extends Controller { separator: true, }, { + id: 'schedule-maintenance', label: this.intl.t('vehicle.actions.schedule-maintenance'), fn: this.vehicleActions.scheduleMaintenance, permission: 'fleet-ops create maintenance-schedule', }, { + id: 'create-work-order', label: this.intl.t('vehicle.actions.create-work-order'), fn: this.vehicleActions.createWorkOrder, permission: 'fleet-ops create work-order', }, { + id: 'log-maintenance', label: this.intl.t('vehicle.actions.log-maintenance'), fn: this.vehicleActions.logMaintenance, permission: 'fleet-ops create maintenance', }, { + id: 'create-issue', label: this.intl.t('vehicle.actions.create-issue'), fn: this.createIssue, permission: 'fleet-ops create issue', @@ -415,6 +445,7 @@ export default class ManagementVehiclesIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.vehicle') }), fn: this.vehicleActions.delete, permission: 'fleet-ops delete vehicle', diff --git a/addon/controllers/management/vehicles/index/details.js b/addon/controllers/management/vehicles/index/details.js index a159b35cc..493b2cf32 100644 --- a/addon/controllers/management/vehicles/index/details.js +++ b/addon/controllers/management/vehicles/index/details.js @@ -68,6 +68,7 @@ export default class ManagementVehiclesIndexDetailsController extends Controller permission: 'fleet-ops update vehicle', }, { + id: 'more', // Actions dropdown — shared with the vehicle context panel icon: 'ellipsis-h', iconPrefix: 'fas', diff --git a/addon/controllers/management/vendors/index.js b/addon/controllers/management/vendors/index.js index e76a713ee..2de8fb775 100644 --- a/addon/controllers/management/vendors/index.js +++ b/addon/controllers/management/vendors/index.js @@ -13,7 +13,7 @@ export default class ManagementVendorsIndexController extends Controller { @service appCache; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.vendorActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -30,7 +30,7 @@ export default class ManagementVendorsIndexController extends Controller { 'country', 'address', 'website_url', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -55,16 +55,19 @@ export default class ManagementVendorsIndexController extends Controller { get actionButtons() { return [ { + id: 'more', component: 'dropdown-button', icon: 'display', size: 'xs', items: [ { + id: 'table-view', label: this.intl.t('common.table-view'), icon: 'table-list', onClick: () => this.setLayout('table'), }, { + id: 'grid-view', label: this.intl.t('common.grid-view'), icon: 'grip', onClick: () => this.setLayout('grid'), @@ -74,11 +77,13 @@ export default class ManagementVendorsIndexController extends Controller { helpText: this.intl.t('common.change-layout'), }, { + id: 'refresh', icon: 'refresh', onClick: this.vendorActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -86,6 +91,7 @@ export default class ManagementVendorsIndexController extends Controller { permission: 'fleet-ops create vendor', }, { + id: 'import', text: this.intl.t('common.import'), type: 'magic', icon: 'upload', @@ -93,6 +99,7 @@ export default class ManagementVendorsIndexController extends Controller { permission: 'fleet-ops import vendor', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -109,6 +116,7 @@ export default class ManagementVendorsIndexController extends Controller { return [ { + id: 'bulk-delete', label: this.intl.t('common.delete-selected-count', { count: selected.length }), class: 'text-red-500', fn: this.vendorActions.bulkDelete, @@ -121,6 +129,7 @@ export default class ManagementVendorsIndexController extends Controller { get columns() { return [ { + id: 'name', sticky: true, label: this.intl.t('column.name'), valuePath: 'name', @@ -134,6 +143,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'public-id', label: this.intl.t('column.id'), valuePath: 'public_id', cellComponent: 'click-to-copy', @@ -143,6 +153,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'click-to-copy', @@ -152,6 +163,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'email', label: this.intl.t('column.email'), valuePath: 'email', cellComponent: 'click-to-copy', @@ -162,6 +174,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'website-url', label: this.intl.t('column.website-url'), valuePath: 'website_url', cellComponent: 'click-to-copy', @@ -172,6 +185,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'phone', label: this.intl.t('column.phone'), valuePath: 'phone', cellComponent: 'click-to-copy', @@ -182,6 +196,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'address', label: this.intl.t('column.address'), valuePath: 'address', cellComponent: 'cell/place-identity', @@ -194,6 +209,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'pretty-type', label: this.intl.t('column.type'), valuePath: 'prettyType', humanize: true, @@ -204,6 +220,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'country', label: this.intl.t('column.country'), valuePath: 'country', cellComponent: 'table/cell/base', @@ -216,6 +233,7 @@ export default class ManagementVendorsIndexController extends Controller { filterParam: 'country', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -225,6 +243,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -235,6 +254,7 @@ export default class ManagementVendorsIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -247,6 +267,7 @@ export default class ManagementVendorsIndexController extends Controller { filterOptions: fleetOpsOptions('vendorStatuses'), }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -259,11 +280,13 @@ export default class ManagementVendorsIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.vendor') }), fn: this.vendorActions.transition.view, permission: 'fleet-ops view vendor', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.vendor') }), fn: this.vendorActions.transition.edit, permission: 'fleet-ops update vendor', @@ -272,6 +295,7 @@ export default class ManagementVendorsIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.vendor') }), fn: this.vendorActions.delete, permission: 'fleet-ops delete vendor', diff --git a/addon/controllers/operations/orders/index.js b/addon/controllers/operations/orders/index.js index ab9563a89..c18379903 100644 --- a/addon/controllers/operations/orders/index.js +++ b/addon/controllers/operations/orders/index.js @@ -18,7 +18,7 @@ export default class OperationsOrdersIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = [ + @tracked queryParams = this.orderActions.queryParamsFor([ 'page', 'limit', 'sort', @@ -46,7 +46,7 @@ export default class OperationsOrdersIndexController extends Controller { 'drawerOpen', 'drawerTab', 'orderPanelOpen', - ]; + ]); @tracked page = 1; @tracked limit; @tracked sort = '-created_at'; @@ -77,11 +77,13 @@ export default class OperationsOrdersIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.orderActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -89,6 +91,7 @@ export default class OperationsOrdersIndexController extends Controller { permission: 'fleet-ops create order', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -97,6 +100,7 @@ export default class OperationsOrdersIndexController extends Controller { permission: 'fleet-ops export order', }, { + id: 'import-orders', text: this.intl.t('common.import'), icon: 'file-import', wrapperClass: 'hidden md:flex', @@ -110,12 +114,14 @@ export default class OperationsOrdersIndexController extends Controller { get bulkActions() { return [ { + id: 'bulk-cancel', label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.orders') }), icon: 'ban', fn: this.orderActions.bulkCancel, permission: 'fleet-ops cancel order', }, { + id: 'bulk-delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.orders') }), icon: 'trash', class: 'text-red-500', @@ -124,12 +130,14 @@ export default class OperationsOrdersIndexController extends Controller { }, { separator: true }, { + id: 'bulk-dispatch', label: this.intl.t('common.dispatch-orders'), icon: 'rocket', fn: this.orderActions.bulkDispatch, permission: 'fleet-ops dispatch order', }, { + id: 'bulk-assign-driver', label: this.intl.t('common.assign-drivers'), icon: 'user-plus', fn: this.orderActions.bulkAssignDriver, @@ -142,6 +150,7 @@ export default class OperationsOrdersIndexController extends Controller { get columns() { return [ { + id: 'public-id', sticky: true, label: this.intl.t('column.id'), valuePath: 'public_id', @@ -155,6 +164,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'payload-waypoints-length', label: this.intl.t('column.route-type'), valuePath: 'payload.waypoints.length', cellComponent: 'cell/order-route-type', @@ -162,6 +172,7 @@ export default class OperationsOrdersIndexController extends Controller { resizable: true, }, { + id: 'internal-id', label: this.intl.t('column.internal-id'), valuePath: 'internal_id', cellComponent: 'click-to-copy', @@ -174,6 +185,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponentPlaceholder: this.intl.t('order.placeholders.filter-internal-id'), }, { + id: 'payload-public-id', label: this.intl.t('column.payload'), valuePath: 'payload.public_id', cellComponent: 'cell/payload-identity', @@ -186,6 +198,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'driver-assigned', label: this.intl.t('column.driver-assigned'), cellComponent: 'cell/driver-identity', valuePath: 'driver_assigned', @@ -203,6 +216,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'driver', }, { + id: 'pickup-name', label: this.intl.t('column.pickup'), valuePath: 'pickupName', cellComponent: 'cell/place-identity', @@ -219,6 +233,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'place', }, { + id: 'dropoff-name', label: this.intl.t('column.dropoff'), valuePath: 'dropoffName', cellComponent: 'cell/place-identity', @@ -234,6 +249,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'place', }, { + id: 'customer-name', label: this.intl.t('column.customer'), valuePath: 'customer.name', cellComponent: 'cell/customer-identity', @@ -248,6 +264,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'customer', }, { + id: 'vehicle-assigned-display-name', label: this.intl.t('column.vehicle-assigned'), cellComponent: 'cell/vehicle-identity', valuePath: 'vehicle_assigned.display_name', @@ -271,6 +288,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'vehicle', }, { + id: 'facilitator-name', label: this.intl.t('column.facilitator'), valuePath: 'facilitator.name', cellComponent: 'cell/facilitator-identity', @@ -285,6 +303,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'vendor', }, { + id: 'scheduled-at', label: this.intl.t('column.scheduled-at'), valuePath: 'scheduledAt', sortParam: 'scheduled_at', @@ -295,6 +314,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'item-count', label: this.intl.t('column.items'), cellComponent: 'table/cell/base', valuePath: 'item_count', @@ -302,6 +322,7 @@ export default class OperationsOrdersIndexController extends Controller { hidden: true, }, { + id: 'transaction-amount', label: this.intl.t('column.transaction'), cellComponent: 'table/cell/currency', valuePath: 'transaction_amount', @@ -310,6 +331,7 @@ export default class OperationsOrdersIndexController extends Controller { sortable: true, }, { + id: 'tracking-number-tracking-number', label: this.intl.t('column.tracking'), valuePath: 'tracking_number.tracking_number', cellComponent: 'click-to-copy', @@ -319,6 +341,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'type', label: this.intl.t('column.type'), valuePath: 'type', resizable: true, @@ -330,6 +353,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponentPlaceholder: 'Filter by order config', }, { + id: 'status', label: this.intl.t('column.status'), valuePath: 'status', cellComponent: 'table/cell/status', @@ -340,6 +364,7 @@ export default class OperationsOrdersIndexController extends Controller { fetchUri: 'orders/statuses', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -350,6 +375,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -361,6 +387,7 @@ export default class OperationsOrdersIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'created-by-name', label: this.intl.t('column.created-by'), valuePath: 'created_by_name', cellComponent: 'table/cell/user-identity', @@ -374,6 +401,7 @@ export default class OperationsOrdersIndexController extends Controller { model: 'user', }, { + id: 'updated-by-name', label: this.intl.t('column.updated-by'), valuePath: 'updated_by_name', cellComponent: 'table/cell/user-identity', @@ -397,6 +425,7 @@ export default class OperationsOrdersIndexController extends Controller { hidden: true, }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -409,12 +438,14 @@ export default class OperationsOrdersIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.order') }), icon: 'eye', fn: this.orderActions.transition.view, permission: 'fleet-ops view order', }, { + id: 'dispatch', label: this.intl.t('common.dispatch-order'), icon: 'paper-plane', fn: this.orderActions.dispatch, @@ -422,6 +453,7 @@ export default class OperationsOrdersIndexController extends Controller { isVisible: (order) => order.canBeDispatched, }, { + id: 'assign-driver', label: this.intl.t('common.assign-driver'), icon: 'edit', fn: this.orderActions.assignDriver, @@ -429,6 +461,7 @@ export default class OperationsOrdersIndexController extends Controller { isVisible: (order) => !order.has_driver_assigned, }, { + id: 'unassign-driver', label: this.intl.t('common.unassign-driver'), icon: 'edit', fn: this.orderActions.unassignDriver, @@ -436,6 +469,7 @@ export default class OperationsOrdersIndexController extends Controller { isVisible: (order) => order.has_driver_assigned, }, { + id: 'cancel', label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.order') }), icon: 'ban', fn: this.orderActions.cancel, @@ -445,6 +479,7 @@ export default class OperationsOrdersIndexController extends Controller { separator: true, }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.order') }), icon: 'trash', fn: this.orderActions.delete, diff --git a/addon/controllers/operations/orders/index/details.js b/addon/controllers/operations/orders/index/details.js index 333846cc9..e7f8a0dcf 100644 --- a/addon/controllers/operations/orders/index/details.js +++ b/addon/controllers/operations/orders/index/details.js @@ -89,6 +89,7 @@ export default class OperationsOrdersIndexDetailsController extends Controller { { items: [ { + id: 'edit-order-details', text: 'Edit details', icon: 'pencil', permission: 'fleet-ops update order', @@ -96,6 +97,7 @@ export default class OperationsOrdersIndexDetailsController extends Controller { fn: () => this.orderActions.editOrderDetails(this.model), }, { + id: 'update-activity', text: 'Update activity', icon: 'signal', permission: 'fleet-ops update order', @@ -113,6 +115,7 @@ export default class OperationsOrdersIndexDetailsController extends Controller { fn: () => (this.model.has_driver_assigned ? this.orderActions.unassignDriver(this.model) : this.orderActions.assignDriver(this.model)), }, { + id: 'view-label', text: 'View order label', icon: 'file-invoice', permission: 'fleet-ops view order', @@ -122,11 +125,13 @@ export default class OperationsOrdersIndexDetailsController extends Controller { separator: true, }, { + id: 'listen-to-socket-channel', text: 'Listen to socket channel', icon: 'headphones', fn: () => this.hostRouter.transitionTo('console.developers.sockets.view', `order.${this.model.public_id}`), }, { + id: 'view-metadata', text: 'View metadata', icon: 'table', fn: () => this.orderActions.viewMetadata(this.model), @@ -135,6 +140,7 @@ export default class OperationsOrdersIndexDetailsController extends Controller { separator: true, }, { + id: 'cancel', text: 'Cancel order', icon: 'ban', class: 'text-danger', @@ -143,6 +149,7 @@ export default class OperationsOrdersIndexDetailsController extends Controller { fn: () => this.orderActions.cancel(this.model), }, { + id: 'delete', text: 'Delete order', icon: 'trash', class: 'text-danger', diff --git a/addon/controllers/operations/service-rates/index.js b/addon/controllers/operations/service-rates/index.js index 52413130a..a9049bc4e 100644 --- a/addon/controllers/operations/service-rates/index.js +++ b/addon/controllers/operations/service-rates/index.js @@ -10,7 +10,7 @@ export default class OperationsServiceRatesIndexController extends Controller { @service intl; /** query params */ - @tracked queryParams = ['page', 'query', 'limit', 'sort', 'zone', 'service_area']; + @tracked queryParams = this.serviceRateActions.queryParamsFor(['page', 'query', 'limit', 'sort', 'zone', 'service_area']); @tracked page = 1; @tracked limit; @tracked query; @@ -20,11 +20,13 @@ export default class OperationsServiceRatesIndexController extends Controller { get actionButtons() { return [ { + id: 'refresh', icon: 'refresh', onClick: this.serviceRateActions.refresh, helpText: this.intl.t('common.refresh'), }, { + id: 'create', text: this.intl.t('common.new'), type: 'primary', icon: 'plus', @@ -32,6 +34,7 @@ export default class OperationsServiceRatesIndexController extends Controller { permission: 'fleet-ops create service-rate', }, { + id: 'export', text: this.intl.t('common.export'), icon: 'long-arrow-up', iconClass: 'rotate-icon-45', @@ -46,6 +49,7 @@ export default class OperationsServiceRatesIndexController extends Controller { get bulkActions() { return [ { + id: 'bulk-delete', label: 'Delete selected...', class: 'text-red-500', fn: this.serviceRateActions.bulkDelete, @@ -58,6 +62,7 @@ export default class OperationsServiceRatesIndexController extends Controller { get columns() { return [ { + id: 'public-id', sticky: true, label: this.intl.t('column.id'), valuePath: 'public_id', @@ -70,6 +75,7 @@ export default class OperationsServiceRatesIndexController extends Controller { filterComponent: 'filter/string', }, { + id: 'service-name', label: this.intl.t('column.service'), valuePath: 'service_name', cellComponent: 'table/cell/base', @@ -78,6 +84,7 @@ export default class OperationsServiceRatesIndexController extends Controller { filterable: false, }, { + id: 'service-area-name', label: this.intl.t('column.service-area'), valuePath: 'service_area.name', cellComponent: 'cell/service-area-identity', @@ -93,6 +100,7 @@ export default class OperationsServiceRatesIndexController extends Controller { model: 'service-area', }, { + id: 'zone-name', label: this.intl.t('column.zone'), valuePath: 'zone.name', cellComponent: 'cell/zone-identity', @@ -107,6 +115,7 @@ export default class OperationsServiceRatesIndexController extends Controller { model: 'zone', }, { + id: 'created-at', label: this.intl.t('column.created-at'), valuePath: 'createdAt', sortParam: 'created_at', @@ -116,6 +125,7 @@ export default class OperationsServiceRatesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'updated-at', label: this.intl.t('column.updated-at'), valuePath: 'updatedAt', sortParam: 'updated_at', @@ -126,6 +136,7 @@ export default class OperationsServiceRatesIndexController extends Controller { filterComponent: 'filter/date', }, { + id: 'row-actions', label: '', cellComponent: 'table/cell/dropdown', ddButtonText: false, @@ -137,18 +148,21 @@ export default class OperationsServiceRatesIndexController extends Controller { width: 60, actions: [ { + id: 'view', label: this.intl.t('common.view-resource', { resource: this.intl.t('resource.service-rate') }), icon: 'eye', fn: this.serviceRateActions.transition.view, permission: 'fleet-ops view service-rate', }, { + id: 'edit', label: this.intl.t('common.edit-resource', { resource: this.intl.t('resource.service-rate') }), icon: 'pencil', fn: this.serviceRateActions.transition.edit, permission: 'fleet-ops view service-rate', }, { + id: 'delete', label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.service-rate') }), icon: 'trash', fn: this.serviceRateActions.delete, diff --git a/addon/extension.js b/addon/extension.js index 5aebbad9c..113b9f240 100644 --- a/addon/extension.js +++ b/addon/extension.js @@ -162,6 +162,38 @@ export default { // Create registries this.createRegistries(registryService); + + // Declare the registries extensions can add table columns, actions and + // buttons to, e.g. `fleet-ops:table:driver:columns` or `fleet-ops:details:order:menu`. + universe + .getService('universe/resource-view-service') + ?.declare('fleet-ops', [ + 'contact', + 'customer', + 'device', + 'device-event', + 'driver', + 'equipment', + 'fleet', + 'fuel-report', + 'fuel-transaction', + 'inspection-form', + 'inspection-submission', + 'integrated-vendor', + 'issue', + 'maintenance', + 'order', + 'part', + 'place', + 'report', + 'schedule', + 'sensor', + 'service-rate', + 'trailer', + 'vehicle', + 'vendor', + 'work-order', + ]); registryService.registerRenderableComponent('ai:action-preview:fleet-ops.create_order', new ExtensionComponent('@fleetbase/fleetops-engine', 'ai/create-order-preview')); // // Register console home guidance diff --git a/addon/services/contact-actions.js b/addon/services/contact-actions.js index 7021bd5cc..34d5f5383 100644 --- a/addon/services/contact-actions.js +++ b/addon/services/contact-actions.js @@ -48,6 +48,7 @@ export default class ContactActionsService extends ResourceActionService { }, view: (contact, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, contact, title: contact?.name, header: 'contact/panel-header', diff --git a/addon/services/customer-actions.js b/addon/services/customer-actions.js index 01756a80a..205899afe 100644 --- a/addon/services/customer-actions.js +++ b/addon/services/customer-actions.js @@ -4,7 +4,7 @@ import { PANEL_DEFAULTS, registeredPanelTabs } from '../utils/context-panel'; export default class CustomerActionsService extends ContactActionsService { constructor() { super(...arguments); - this.initialize('contact', { defaultAttributes: { type: 'customer', status: 'active' } }); + this.initialize('contact', { defaultAttributes: { type: 'customer', status: 'active' }, registryResource: 'customer' }); } transition = { @@ -38,6 +38,7 @@ export default class CustomerActionsService extends ContactActionsService { }, view: (customer, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, customer, title: customer?.name, header: 'contact/panel-header', diff --git a/addon/services/device-actions.js b/addon/services/device-actions.js index 54abcd788..4d4220308 100644 --- a/addon/services/device-actions.js +++ b/addon/services/device-actions.js @@ -48,6 +48,7 @@ export default class DeviceActionsService extends ResourceActionService { const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, device, header: 'device/panel-header', title: device.name ?? device.serial_number, diff --git a/addon/services/device-event-actions.js b/addon/services/device-event-actions.js index f1dcb927d..67f430761 100644 --- a/addon/services/device-event-actions.js +++ b/addon/services/device-event-actions.js @@ -17,6 +17,7 @@ export default class DeviceEventActionsService extends ResourceActionService { panel = { view: (deviceEvent) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, deviceEvent, tabs: [ { diff --git a/addon/services/driver-actions.js b/addon/services/driver-actions.js index 7a4692579..cd5a5fe22 100644 --- a/addon/services/driver-actions.js +++ b/addon/services/driver-actions.js @@ -2,9 +2,7 @@ import ResourceActionService, { inject as service } from '@fleetbase/ember-core/ import leafletIcon from '@fleetbase/ember-core/utils/leaflet-icon'; import config from 'ember-get-config'; import { action } from '@ember/object'; -import { isArray } from '@ember/array'; -import { dasherize } from '@ember/string'; -import { PANEL_DEFAULTS, closePanelsThen } from '../utils/context-panel'; +import { PANEL_DEFAULTS, closePanelsThen, registeredPanelTabs } from '../utils/context-panel'; import { confirmLoginAction, hasInactiveLogin, hasManagedLogin } from '../utils/profile-login-actions'; export default class DriverActionsService extends ResourceActionService { @@ -13,16 +11,8 @@ export default class DriverActionsService extends ResourceActionService { @service issueActions; get registeredTabs() { - const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:driver:details'); - return (isArray(registeredTabs) ? registeredTabs : []) - .map((tab) => { - delete tab.route; - if (!tab.key) { - tab.key = tab.id ?? dasherize(tab.label ?? tab.title); - } - return tab; - }) - .filter((tab) => !tab.component); + // Copies, so the shared registry items keep the \`route\` their routed details view needs. + return registeredPanelTabs(this.menuService, 'fleet-ops:component:driver:details'); } get panelTabs() { @@ -125,6 +115,7 @@ export default class DriverActionsService extends ResourceActionService { const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, driver, header: 'driver/panel-header', actionButtons: [ diff --git a/addon/services/equipment-actions.js b/addon/services/equipment-actions.js index bc8533f70..9e0863684 100644 --- a/addon/services/equipment-actions.js +++ b/addon/services/equipment-actions.js @@ -47,6 +47,7 @@ export default class EquipmentActionsService extends ResourceActionService { }, view: (equipment, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, equipment, title: equipment?.name, header: 'equipment/panel-header', diff --git a/addon/services/fleet-actions.js b/addon/services/fleet-actions.js index 716439bca..151f14a80 100644 --- a/addon/services/fleet-actions.js +++ b/addon/services/fleet-actions.js @@ -42,6 +42,7 @@ export default class FleetActionsService extends ResourceActionService { }, view: (fleet, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, fleet, title: fleet?.name, actionButtons: [ diff --git a/addon/services/fuel-report-actions.js b/addon/services/fuel-report-actions.js index 1fce62ba1..07d73f817 100644 --- a/addon/services/fuel-report-actions.js +++ b/addon/services/fuel-report-actions.js @@ -43,6 +43,7 @@ export default class FuelReportActionsService extends ResourceActionService { }, view: (fuelReport, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, fuelReport, title: fuelReport?.name ?? `Fuel reported on ${fuelReport?.createdAt ?? ''}`.trim(), actionButtons: [{ icon: 'pencil', permission: 'fleet-ops update fuel-report', fn: () => closePanelsThen(this.resourceContextPanel, () => this.panel.edit(fuelReport)) }], diff --git a/addon/services/inspection-form-actions.js b/addon/services/inspection-form-actions.js index 6624a6823..049c0f71e 100644 --- a/addon/services/inspection-form-actions.js +++ b/addon/services/inspection-form-actions.js @@ -59,6 +59,7 @@ export default class InspectionFormActionsService extends ResourceActionService const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, form, title: form?.name, get actionButtons() { diff --git a/addon/services/inspection-submission-actions.js b/addon/services/inspection-submission-actions.js index 6e4597696..cf715a30c 100644 --- a/addon/services/inspection-submission-actions.js +++ b/addon/services/inspection-submission-actions.js @@ -32,6 +32,7 @@ export default class InspectionSubmissionActionsService extends ResourceActionSe const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, submission, title: this.panelTitle(submission), actionButtons: [ diff --git a/addon/services/integrated-vendor-actions.js b/addon/services/integrated-vendor-actions.js index 2a4313c58..41f251c23 100644 --- a/addon/services/integrated-vendor-actions.js +++ b/addon/services/integrated-vendor-actions.js @@ -37,6 +37,7 @@ export default class IntegratedVendorActionsService extends ResourceActionServic }, view: (integratedVendor, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, integratedVendor, tabs: [ { diff --git a/addon/services/issue-actions.js b/addon/services/issue-actions.js index 8e81357d3..31aabdb34 100644 --- a/addon/services/issue-actions.js +++ b/addon/services/issue-actions.js @@ -50,6 +50,7 @@ export default class IssueActionsService extends ResourceActionService { }, view: (issue, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, issue, header: 'issue/panel-header', width: '800px', diff --git a/addon/services/maintenance-actions.js b/addon/services/maintenance-actions.js index 672b382c3..d7eb894c2 100644 --- a/addon/services/maintenance-actions.js +++ b/addon/services/maintenance-actions.js @@ -44,6 +44,7 @@ export default class MaintenanceActionsService extends ResourceActionService { }, view: (maintenance, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, maintenance, title: maintenance?.summary, header: 'maintenance/panel-header', diff --git a/addon/services/maintenance-schedule-actions.js b/addon/services/maintenance-schedule-actions.js index fe4f1a444..6a73bb52b 100644 --- a/addon/services/maintenance-schedule-actions.js +++ b/addon/services/maintenance-schedule-actions.js @@ -11,7 +11,7 @@ export default class MaintenanceScheduleActionsService extends ResourceActionSer constructor() { super(...arguments); - this.initialize('maintenance-schedule'); + this.initialize('maintenance-schedule', { registryResource: 'schedule' }); } transition = { @@ -43,6 +43,7 @@ export default class MaintenanceScheduleActionsService extends ResourceActionSer }, view: (schedule, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, schedule, title: schedule?.name, actionButtons: this.panelActionButtons(schedule, { onDeleted: () => this.resourceContextPanel.closeAll() }), diff --git a/addon/services/order-actions.js b/addon/services/order-actions.js index 14510ef6a..9abfb9d54 100644 --- a/addon/services/order-actions.js +++ b/addon/services/order-actions.js @@ -54,6 +54,7 @@ export default class OrderActionsService extends ResourceActionService { }, view: (order, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, order, tabs: [ { diff --git a/addon/services/part-actions.js b/addon/services/part-actions.js index a97d45457..d64c12c08 100644 --- a/addon/services/part-actions.js +++ b/addon/services/part-actions.js @@ -46,6 +46,7 @@ export default class PartActionsService extends ResourceActionService { }, view: (part, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, part, title: part?.name, header: 'part/panel-header', diff --git a/addon/services/place-actions.js b/addon/services/place-actions.js index 060558c87..dcc784ad7 100644 --- a/addon/services/place-actions.js +++ b/addon/services/place-actions.js @@ -52,6 +52,7 @@ export default class PlaceActionsService extends ResourceActionService { } return this.resourceContextPanel.open({ + registry: this.detailsRegistry, place, title: place?.name ?? place?.street1, actionButtons: [{ icon: 'pencil', permission: 'fleet-ops update place', fn: () => closePanelsThen(this.resourceContextPanel, () => this.panel.edit(place)) }], diff --git a/addon/services/sensor-actions.js b/addon/services/sensor-actions.js index a1b7ae357..94da25165 100644 --- a/addon/services/sensor-actions.js +++ b/addon/services/sensor-actions.js @@ -35,6 +35,7 @@ export default class SensorActionsService extends ResourceActionService { }, view: (sensor) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, sensor, header: 'sensor/panel-header', tabs: [ diff --git a/addon/services/service-area-actions.js b/addon/services/service-area-actions.js index 695674521..5cfc1bf66 100644 --- a/addon/services/service-area-actions.js +++ b/addon/services/service-area-actions.js @@ -41,6 +41,7 @@ export default class ServiceAreaActionsService extends ResourceActionService { }, view: (serviceArea, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, serviceArea, title: serviceArea?.name, actionButtons: [ diff --git a/addon/services/service-rate-actions.js b/addon/services/service-rate-actions.js index 2e24c098e..30072219e 100644 --- a/addon/services/service-rate-actions.js +++ b/addon/services/service-rate-actions.js @@ -51,6 +51,7 @@ export default class ServiceRateActionsService extends ResourceActionService { }, view: (serviceRate) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, serviceRate, tabs: [ { diff --git a/addon/services/telematic-actions.js b/addon/services/telematic-actions.js index 1d2d673e4..fe2694c84 100644 --- a/addon/services/telematic-actions.js +++ b/addon/services/telematic-actions.js @@ -41,6 +41,7 @@ export default class TelematicActionsService extends ResourceActionService { }, view: (telematic) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, telematic, tabs: [ { diff --git a/addon/services/trailer-actions.js b/addon/services/trailer-actions.js index 8349ce056..f18046d13 100644 --- a/addon/services/trailer-actions.js +++ b/addon/services/trailer-actions.js @@ -2,9 +2,7 @@ import ResourceActionService, { inject as service } from '@fleetbase/ember-core/ import leafletIcon from '@fleetbase/ember-core/utils/leaflet-icon'; import config from 'ember-get-config'; import { action } from '@ember/object'; -import { isArray } from '@ember/array'; -import { dasherize } from '@ember/string'; -import { PANEL_DEFAULTS, closePanelsThen } from '../utils/context-panel'; +import { PANEL_DEFAULTS, closePanelsThen, registeredPanelTabs } from '../utils/context-panel'; /** * Trailer resource actions. @@ -32,17 +30,8 @@ export default class TrailerActionsService extends ResourceActionService { } get registeredTabs() { - const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:trailer:details'); - - return (isArray(registeredTabs) ? registeredTabs : []) - .map((tab) => { - delete tab.route; - if (!tab.key) { - tab.key = tab.id ?? dasherize(tab.label ?? tab.title); - } - return tab; - }) - .filter((tab) => !tab.component); + // Copies, so the shared registry items keep the \`route\` their routed details view needs. + return registeredPanelTabs(this.menuService, 'fleet-ops:component:trailer:details'); } get panelTabs() { @@ -132,6 +121,7 @@ export default class TrailerActionsService extends ResourceActionService { const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, trailer, header: 'trailer/panel-header', actionButtons: [ diff --git a/addon/services/vehicle-actions.js b/addon/services/vehicle-actions.js index f3533b2ec..b85a56925 100644 --- a/addon/services/vehicle-actions.js +++ b/addon/services/vehicle-actions.js @@ -2,9 +2,7 @@ import ResourceActionService, { inject as service } from '@fleetbase/ember-core/ import leafletIcon from '@fleetbase/ember-core/utils/leaflet-icon'; import config from 'ember-get-config'; import { action } from '@ember/object'; -import { isArray } from '@ember/array'; -import { dasherize } from '@ember/string'; -import { PANEL_DEFAULTS, closePanelsThen } from '../utils/context-panel'; +import { PANEL_DEFAULTS, closePanelsThen, registeredPanelTabs } from '../utils/context-panel'; export default class VehicleActionsService extends ResourceActionService { @service('universe/menu-service') menuService; @@ -15,16 +13,8 @@ export default class VehicleActionsService extends ResourceActionService { @service issueActions; get registeredTabs() { - const registeredTabs = this.menuService.getMenuItems('fleet-ops:component:vehicle:details'); - return (isArray(registeredTabs) ? registeredTabs : []) - .map((tab) => { - delete tab.route; - if (!tab.key) { - tab.key = tab.id ?? dasherize(tab.label ?? tab.title); - } - return tab; - }) - .filter((tab) => !tab.component); + // Copies, so the shared registry items keep the \`route\` their routed details view needs. + return registeredPanelTabs(this.menuService, 'fleet-ops:component:vehicle:details'); } get panelTabs() { @@ -148,6 +138,7 @@ export default class VehicleActionsService extends ResourceActionService { const service = this; return this.resourceContextPanel.open({ + registry: this.detailsRegistry, vehicle, header: 'vehicle/panel-header', actionButtons: [ diff --git a/addon/services/vendor-actions.js b/addon/services/vendor-actions.js index ab0e9591b..3e13f0625 100644 --- a/addon/services/vendor-actions.js +++ b/addon/services/vendor-actions.js @@ -43,6 +43,7 @@ export default class VendorActionsService extends ResourceActionService { }, view: (vendor, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, vendor, title: vendor?.name, header: 'vendor/panel-header', diff --git a/addon/services/work-order-actions.js b/addon/services/work-order-actions.js index d0cd15c7c..4f08ce3d9 100644 --- a/addon/services/work-order-actions.js +++ b/addon/services/work-order-actions.js @@ -41,6 +41,7 @@ export default class WorkOrderActionsService extends ResourceActionService { }, view: (workOrder, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, workOrder, title: workOrder?.code ?? workOrder?.subject, header: 'work-order/panel-header', diff --git a/addon/services/zone-actions.js b/addon/services/zone-actions.js index e811ebea6..193a482e2 100644 --- a/addon/services/zone-actions.js +++ b/addon/services/zone-actions.js @@ -36,6 +36,7 @@ export default class ZoneActionsService extends ResourceActionService { }, view: (zone, options = {}) => { return this.resourceContextPanel.open({ + registry: this.detailsRegistry, zone, title: zone?.name, actionButtons: [ diff --git a/addon/templates/analytics/reports/index.hbs b/addon/templates/analytics/reports/index.hbs index 3d57ae916..3aff18e63 100644 --- a/addon/templates/analytics/reports/index.hbs +++ b/addon/templates/analytics/reports/index.hbs @@ -1,4 +1,5 @@
tab.key === 'devices').component, 'device/manager'); }); + test('registered tabs that render a component join the context panel without losing their route', function (assert) { + const componentTab = { id: 'safety', label: 'Safety', route: 'management.trailers.index.details.virtual', component: 'acme/safety' }; + const routeOnlyTab = { id: 'history', label: 'History', route: 'management.trailers.index.details.virtual' }; + this.owner.register( + 'service:universe/menu-service', + class extends Service { + getMenuItems(registry) { + return registry === 'fleet-ops:component:trailer:details' ? [componentTab, routeOnlyTab] : []; + } + } + ); + const service = this.owner.lookup('service:trailer-actions'); + + const safety = service.panelTabs.find((tab) => tab.key === 'safety'); + assert.ok(safety, 'a tab with a component renders in the panel'); + assert.notOk( + service.panelTabs.find((tab) => tab.key === 'history'), + 'a route-only tab has nothing to render there' + ); + assert.strictEqual(componentTab.route, 'management.trailers.index.details.virtual', 'the registered item keeps its route for the routed details view'); + }); + test('attaching to a vehicle posts the trailer endpoint with the vehicle and towing position', async function (assert) { const service = this.owner.lookup('service:trailer-actions'); const fetch = this.owner.lookup('service:fetch'); From 3bcaced69853c1d298dcea2c461edf81b4a0c38e Mon Sep 17 00:00:00 2001 From: "Ronald A. Richardson" Date: Sat, 3 Oct 2026 11:05:36 +0800 Subject: [PATCH 2/2] fix(order-form): handle a failed custom fields load ember-core 0.3.25's loadSubjectCustomFields rejects instead of resolving with undefined when the fields cannot be loaded. Every other caller already catches; this one now does too, leaving the form without custom fields as before. --- addon/components/order/form.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/addon/components/order/form.js b/addon/components/order/form.js index 3a3437f22..dadf47380 100644 --- a/addon/components/order/form.js +++ b/addon/components/order/form.js @@ -32,7 +32,13 @@ export default class OrderFormComponent extends Component { }); this.args.resource.payload.set('type', orderConfig.key); - this.customFields = yield this.customFieldsRegistry.loadSubjectCustomFields.perform(orderConfig); + // loadSubjectCustomFields rejects when the custom fields cannot be loaded (ember-core 0.3.25). + try { + this.customFields = yield this.customFieldsRegistry.loadSubjectCustomFields.perform(orderConfig); + } catch (err) { + this.customFields = undefined; + debug('Unable to load order custom fields: ' + err.message); + } } @task *selectDriver(driver) {