Skip to content

Commit

Permalink
Merge pull request #15 from fleetbase/dev-v0.3.3
Browse files Browse the repository at this point in the history
v0.3.3
  • Loading branch information
roncodes authored Nov 9, 2023
2 parents ebd072d + 403f0b3 commit 5ce11e2
Show file tree
Hide file tree
Showing 48 changed files with 2,148 additions and 916 deletions.
1 change: 1 addition & 0 deletions addon/components/admin/visibility-controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default class AdminVisibilityControlsComponent extends Component {
@tracked visibilitySettings = [
{ name: 'Dashboard', route: 'operations.orders', visible: true },
{ name: 'Service Rates', route: 'operations.service-rates', visible: true },
{ name: 'Scheduler', route: 'operations.scheduler', visible: true },
{ name: 'Drivers', route: 'management.drivers', visible: true },
{ name: 'Vehicles', route: 'management.vehicles', visible: true },
{ name: 'Fleets', route: 'management.fleets', visible: true },
Expand Down
1 change: 0 additions & 1 deletion addon/components/full-calendar.js

This file was deleted.

1 change: 0 additions & 1 deletion addon/components/full-calendar/draggable.js

This file was deleted.

3 changes: 2 additions & 1 deletion addon/components/layout/fleet-ops-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
const operationsItems = [
{ title: 'Dashboard', icon: 'home', route: 'operations.orders' },
{ title: 'Service Rates', icon: 'file-invoice-dollar', route: 'operations.service-rates' },
{ title: 'Scheduler', icon: 'calendar-day', route: 'operations.scheduler' },
];

const resourcesItems = [
{ title: 'Drivers', icon: 'route', route: 'management.drivers' },
{ title: 'Drivers', icon: 'id-card', route: 'management.drivers' },
{ title: 'Vehicles', icon: 'truck', route: 'management.vehicles' },
{ title: 'Fleets', icon: 'user-group', route: 'management.fleets' },
{ title: 'Vendors', icon: 'warehouse', route: 'management.vendors' },
Expand Down
17 changes: 17 additions & 0 deletions addon/components/live-map-drawer.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Drawer @isMinimized={{true}} @notchEnabled={{true}} @onLoad={{this.setDrawerContext}}>
<div class="ui-tabs pt-4">
<nav>
{{#each this.tabs as |tab|}}
<a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active' }}" {{on "click" (fn this.onTabChanged tab.slug)}}>
<FaIcon @icon={{tab.icon}} class="mr-1" />
<span>{{tab.title}}</span>
</a>
{{/each}}
</nav>
</div>
<div class="tab-content tab-{{this.tab.slug}}">
{{#if this.drawer}}
{{component this.tab.component drivers=@drivers vehicles=@vehicles places=@places drawer=this.drawer liveMap=@liveMap tabOptions=this.tab options=this.tab.componentParams}}
{{/if}}
</div>
</Drawer>
104 changes: 104 additions & 0 deletions addon/components/live-map-drawer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { isArray } from '@ember/array';
import contextComponentCallback from '../utils/context-component-callback';
import applyContextComponentArguments from '../utils/apply-context-component-arguments';
import LiveMapDrawerVehicleListingComponent from './live-map-drawer/vehicle-listing';
import LiveMapDrawerDriverListingComponent from './live-map-drawer/driver-listing';
import LiveMapDrawerPlaceListingComponent from './live-map-drawer/place-listing';

export default class LiveMapDrawerComponent extends Component {
/**
* Universe service for managing global data and settings.
*
* @type {Service}
*/
@service universe;

/**
* The current active tab.
*
* @type {Object}
* @tracked
*/
@tracked tab;

/**
* The drawer component context api.
*
* @type {Object}
* @tracked
*/
@tracked drawer;

/**
* Returns the array of tabs available for the drawer.
*
* @type {Array}
*/
get tabs() {
const registeredTabs = this.universe.getMenuItemsFromRegistry('component:live-map-drawer');
const defaultTabs = [
this.universe._createMenuItem('Vehicles', null, { icon: 'car', component: LiveMapDrawerVehicleListingComponent }),
this.universe._createMenuItem('Drivers', null, { icon: 'id-card', component: LiveMapDrawerDriverListingComponent }),
this.universe._createMenuItem('Places', null, { icon: 'building', component: LiveMapDrawerPlaceListingComponent }),
];

if (isArray(registeredTabs)) {
return [...defaultTabs, ...registeredTabs];
}

return defaultTabs;
}

/**
* Initializes the vehicle panel component.
*/
constructor() {
super(...arguments);
this.tab = this.getTabUsingSlug(this.args.tab);
applyContextComponentArguments(this);
}

/**
* Sets the drawer component context api.
*
* @param {Object} drawerApi
* @memberof LiveMapDrawerComponent
*/
@action setDrawerContext(drawerApi) {
this.drawer = drawerApi;

if (typeof this.args.onDrawerReady === 'function') {
this.args.onDrawerReady(...arguments);
}
}

/**
* Handles changing the active tab.
*
* @method
* @param {String} tab - The new tab to switch to.
* @action
*/
@action onTabChanged(tab) {
this.tab = this.getTabUsingSlug(tab);
contextComponentCallback(this, 'onTabChanged', tab);
}

/**
* Finds and returns a tab based on its slug.
*
* @param {String} tabSlug - The slug of the tab.
* @returns {Object|null} The found tab or null.
*/
getTabUsingSlug(tabSlug) {
if (tabSlug) {
return this.tabs.find(({ slug }) => slug === tabSlug);
}

return this.tabs[0];
}
}
6 changes: 6 additions & 0 deletions addon/components/live-map-drawer/driver-listing.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="flex flex-row items-center px-5 py-2 border-b border-gray-200 dark:border-gray-700">
<div>
<Input @value={{this.query}} {{on "input" this.performSearch}} @type="text" class="form-input form-input-sm w-60" placeholder="Filter drivers by keyword..." />
</div>
</div>
<Table @rows={{this.drivers}} @columns={{this.columns}} @onSetup={{fn (mut this.table)}} />
240 changes: 240 additions & 0 deletions addon/components/live-map-drawer/driver-listing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { isBlank } from '@ember/utils';
import { later } from '@ember/runloop';
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';

/**
* Represents a live map drawer driver listing component.
* This component is responsible for displaying and interacting with a list of drivers on a live map.
*
* @extends Component
*/
export default class LiveMapDrawerDriverListingComponent extends Component {
/**
* Service for managing context panels within the application.
* @service
*/
@service contextPanel;

/**
* Service for triggering notifications.
* @service
*/
@service notifications;

/**
* Service for triggering notifications.
* @service
*/
@service hostRouter;

/**
* Service for CRUD operations.
* @service
*/
@service crud;

/**
* The list of drivers to display, tracked for reactivity.
* @tracked
*/
@tracked drivers = [];

/**
* The internal list of drivers used for searching, tracked for reactivity.
* @tracked
*/
@tracked _drivers = [];

/**
* The current search query, tracked for reactivity.
* @tracked
*/
@tracked query = '';

/**
* The table component reference, tracked for reactivity.
* @tracked
*/
@tracked table = null;

/**
* The configuration for table columns including details like label, valuePath, and cellComponent,
* tracked for reactivity.
* @tracked
*/
@tracked columns = [
{
label: 'Driver',
valuePath: 'name',
photoPath: 'photo_url',
width: '100px',
cellComponent: 'cell/driver-name',
onClick: this.focus,
},
{
label: 'Location',
valuePath: 'location',
width: '80px',
cellComponent: 'table/cell/point',
onClick: this.locate,
},
{
label: 'Current Job',
valuePath: 'current_job_id',
width: '80px',
cellComponent: 'table/cell/anchor',
onClick: this.job,
},
{
label: 'Status',
valuePath: 'status',
cellComponent: 'table/cell/status',
width: '60px',
},
{
label: 'Last Seen',
valuePath: 'updatedAgo',
width: '60px',
},
{
label: '',
cellComponent: 'table/cell/dropdown',
ddButtonText: false,
ddButtonIcon: 'ellipsis-h',
ddButtonIconPrefix: 'fas',
ddMenuLabel: 'Actions',
cellClassNames: 'overflow-visible',
wrapperClass: 'flex items-center justify-end mx-2',
width: '90px',
actions: [
{
label: 'View driver details...',
fn: this.focus,
},
{
label: 'Edit driver...',
fn: (driver) => {
return this.focus(driver, 'editing');
},
},
{
label: 'Locate driver...',
fn: this.locate,
},
{
label: 'Delete driver...',
fn: this.delete,
},
],
sortable: false,
filterable: false,
resizable: false,
searchable: false,
},
];

/**
* Initializes the component with drivers passed in from `this.args` and sets up the live map reference.
*/
constructor() {
super(...arguments);
this.drivers = getWithDefault(this.args, 'drivers', []);
this._drivers = [...this.drivers];
this.liveMap = this.args.liveMap;
}

/**
* Filters the drivers list based on a query.
*
* @param {string} query - The query string to filter the drivers list.
*/
search(query) {
if (typeof query !== 'string' && !isBlank(query)) {
return;
}

this.drivers = [
...this._drivers.filter((driver) => {
return typeof driver.name === 'string' && driver.name.toLowerCase().includes(query.toLowerCase());
}),
];
}

/**
* Action to perform a search based on the input event's value.
*
* @param {Event} event - The input event containing the search value.
*/
@action performSearch({ target: { value } }) {
this.search(value);
}

/**
* Action to focus on a driver in the live map and context panel.
*
* @param {object} driver - The driver object to focus on.
* @param {string} intent - The intent for focusing, default is 'viewing'.
*/
@action focus(driver, intent = 'viewing') {
if (this.liveMap) {
this.liveMap.focusLayerByRecord(driver, 16, {
onAfterFocusWithRecord: () => {
later(
this,
() => {
this.contextPanel.focus(driver, intent);
},
600 * 2
);
},
});
} else {
this.contextPanel.focus(driver, intent);
}
}

/**
* Action to locate a driver on the live map.
*
* @param {object} driver - The driver object to locate.
*/
@action locate(driver) {
if (this.liveMap) {
this.liveMap.focusLayerByRecord(driver, 18);
} else {
this.notifications.warning('Unable to locate driver.');
}
}

/**
* Transitino to view the drivers current job
*
* @param {DriverModel} driver
* @memberof LiveMapDrawerDriverListingComponent
*/
@action job(driver) {
if (driver.current_job_id) {
this.hostRouter.transitionTo('console.fleet-ops.operations.orders.index.view', driver.current_job_id);
}
}

/**
* Action to delete a driver from the list and perform cleanup.
*
* @param {object} driver - The driver object to delete.
* @param {object} options - Additional options for the delete operation.
*/
@action delete(driver, options = {}) {
this.crud.delete(driver, {
onSuccess: () => {
this._drivers.removeObject(driver);
this.drivers.removeObject(driver);
},
...options,
});
}
}
Loading

0 comments on commit 5ce11e2

Please sign in to comment.