diff --git a/RELEASE.md b/RELEASE.md index 0c8854947..b6209ab42 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,58 +1,22 @@ -> v0.6.70 ~ "Telematics data retention" +> v0.6.71 ~ "Extensions can add columns, actions and buttons to Fleet-Ops tables and panels" --- -## What's New -- **Telematics Data settings.** A new Fleet-Ops → Settings → Telematics Data page lets each organization decide how long telemetry is kept: device events, raw event payloads, positions, processed and quarantined delivery envelopes, and sync run diagnostics. Administrators set system-wide defaults from the admin console (Fleet-Ops Config → Telematics Data). A value of 0 keeps rows forever. -- **Scheduled retention sweep.** `fleetops:prune-telematics-data` runs every fifteen minutes and applies each organization's policy in bounded batches, so a large backlog is drained gradually without stalling ingestion. Defaults: events 30 days, raw payloads stripped after 7 days, positions 90 days, processed deliveries 24 hours, quarantined deliveries 7 days, sync runs 7 days. -- **Storage usage and on-demand cleanup.** The settings page shows rows, oldest row and estimated size per table for your organization, and "Run cleanup now" queues an immediate retention run. +## Highlights ---- -## Fixes -- Device events no longer store the raw provider unit twice. `payload` keeps the raw unit; `meta` holds only the normalized block (speed, heading, odometer, ignition, fuel level, timing). New event rows are roughly half the size. -- Telemetry-driven saves (device, event, position, vehicle, sensors) no longer write to the activity log on every poll. Organizations that want them can enable "Log telemetry activity" in Telematics Data settings. Manual edits are logged as before. -- Delivery inbox and sync run retention moved from the drain command into the retention sweep; `fleetops:drain-telematic-inbox` now only recovers deliveries and finishes interrupted runs. - ---- -## Upgrade notes -- New indexes on `device_events (company_uuid, created_at)`, `positions (company_uuid, created_at)` and `telematic_sync_runs (telematic_uuid, updated_at)`; on very large tables run `php artisan migrate` in a maintenance window. -- Retention is enabled by default. Existing rows older than the defaults are removed over successive runs after upgrading; set the values to 0 before upgrading if you need to keep history indefinitely. -- Deleting rows frees space inside the database files, not on disk. Run `OPTIMIZE TABLE` off-peak to return space to the operating system. -- Run `php artisan fleetbase:create-permissions` to register the `telematics-settings` permission and the Telematics Settings Manager policy and role. +- **Resource view registries.** Extensions can add the following through `fleet-ops:table::` and `fleet-ops:details::`: + - columns, row actions, bulk actions and toolbar buttons on every top-level Fleet-Ops table; + - header buttons and "…" menu items on its details panels and side panels. ---- -## Testing -- Backend tests cover the retention policy layering and clamping, the prune command (per-company policies, compaction, inbox tables via connections, orphans, batch caps, dry runs, filters, locking), the settings and storage usage endpoints, the index migrations, the on-demand job, and the meta and activity-log changes to ingestion. -- Ember tests cover the settings route guard, the settings controller, and the admin defaults component. -> v0.6.70 ~ "Order reporting and a cleaner default dashboard" - ---- -## What's New -- **Report on orders, their items and tracking.** The report builder can answer questions like "Which products sold the most this month?" and "What did orders total this month?". - - Orders expose their ID and Internal ID, and relationships for tracking (tracking number, region, latest status), Order Config, Customer Vendor, Created By, Purchase Rate › Service Quote and Payload Return. - - `Payload` exposes its items with name, SKU, price, dimensions, metadata and destination. Select an item column for one row per item, or group by one to summarise per product. - - Summary columns count orders distinctly, so they stay correct when item rows are selected. Distance, duration and transaction amount have totals and averages. - - `meta` has no fixed shape, so no column assumes a key in it. Read keys with a computed column, for example `CAST(JSON_UNQUOTE(JSON_EXTRACT(payload.entities.meta, '$.quantity')) AS DECIMAL(15,2))`. - - Column labels drop the table name ("Type", not "Order Type"). Distance and duration are labelled in meters and seconds, and money columns are marked "(minor units)". -- **A cleaner default dashboard.** Fleet-Ops widgets declare their place on the default dashboard: Radar first, then Active Orders and Drivers Online, a full-width Live Fleet map, and Revenue Trend, Top Drivers and Maintenance side by side. -- **Live Fleet widget cards match the live map.** Clicking a driver or vehicle on the widget map shows the same card as **Operations › Live Map**. + Built-in items carry stable ids, so registered items can be placed before or after them. +- **Fix: registered details tabs.** Opening a driver, vehicle or trailer side panel removed the route from tabs other extensions had registered, which broke them in the full details view. Side panels also left out the tabs they could render. +- **Fix: the sensor details view showed the tabs registered for places.** --- -## Fixes -- Custom field values on fuel reports and service areas are saved. They were dropped because the save hooks read the snake_case payload root, while the console sends `fuelReport` and `serviceArea`. -- The report schema no longer references 13 columns and join keys that don't exist: driver name, email and phone and the driver's vehicle, the vehicle's driver, and the fuel report cost, odometer and date. Transaction summaries sum `transaction.amount`. -- Every report table, and the item join, leaves soft-deleted rows out on core-api v1.6.64 and later. - ---- -## Dependencies -- Order items, JSON totals and soft deletes in reports need `fleetbase/core-api` v1.6.64. The schema still registers on older versions. -- The report builder and the default dashboard order ship in `@fleetbase/ember-ui` v0.4.4. - ---- -## Testing -- Every declared report column and join key was checked against the database schema, and order reports were run against real storefront orders on MySQL in strict mode. -- Tests cover the report schema at 100% line coverage, the Live Fleet map cards and the default dashboard order. +## Upgrading +Needs fleetbase/ember-core v0.3.25 and fleetbase/ember-ui v0.4.5. --- ## Need help? - [GitHub Discussions](https://github.com/fleetbase/fleetbase/discussions) - [Discord](https://discord.gg/HnTqQ6zAVn) +--- 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) { 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..361832e77 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:contact:table`. 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..0427f7d69 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:driver:table:columns` or `fleet-ops:order:details: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..789bc2d50 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');