mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-01-08 07:16:49 +00:00
Merge remote-tracking branch 'upstream/main'
This commit is contained in:
14
RELEASE.md
14
RELEASE.md
@@ -1,13 +1,17 @@
|
||||
# 🚀 Fleetbase v0.7.12 — 2025-10-22
|
||||
# 🚀 Fleetbase v0.7.13 — 2025-10-28
|
||||
|
||||
> “Patches”
|
||||
> “Connectivity Module + Positions Playback + Positions & Device Events Drawer”
|
||||
|
||||
---
|
||||
|
||||
## ✨ Highlights
|
||||
- Improvements to Fleet-Ops orders Kanban view, filter by order type and search/filters working.
|
||||
- Patches to food truck API.
|
||||
- Patches to multiple waypoints API handling.
|
||||
- Introduces the new Connectivity module in Fleet-Ops for managing telematics, devices, sensors with native support for Flespi, Geotab, and Samsara built in.
|
||||
- Introduces Position replay for Vehicles
|
||||
- Added new live map drawer tabs "Positions", and "Events" to view all trackable resources position data, as well as replay positions
|
||||
- Improved the report query builder + fix drag sort on group by/aggregate fn and order by columns
|
||||
- Patched entities by destination order view
|
||||
- Improved movement tracker service to account for spead, improved bearing/heading for accurate playback and live tracking of assets
|
||||
- Improved tracking endpoint for both vehicles and drivers
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"appstract/laravel-opcache": "^4.0",
|
||||
"fleetbase/core-api": "^1.6.19",
|
||||
"fleetbase/fleetops-api": "^0.6.20",
|
||||
"fleetbase/core-api": "^1.6.20",
|
||||
"fleetbase/fleetops-api": "^0.6.21",
|
||||
"fleetbase/registry-bridge": "^0.1.0",
|
||||
"fleetbase/storefront-api": "^0.4.3",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
|
||||
26
api/composer.lock
generated
26
api/composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "f985446e2caaac2043fa2956abae1819",
|
||||
"content-hash": "e7233912fa3ae9936f14283737e39794",
|
||||
"packages": [
|
||||
{
|
||||
"name": "appstract/laravel-opcache",
|
||||
@@ -2158,16 +2158,16 @@
|
||||
},
|
||||
{
|
||||
"name": "fleetbase/core-api",
|
||||
"version": "1.6.19",
|
||||
"version": "1.6.20",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fleetbase/core-api.git",
|
||||
"reference": "71c3273b6dcf93abe98eadb54707d2a59e190b7e"
|
||||
"reference": "f5786609b581593945907a67f659a56bff8e0b93"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fleetbase/core-api/zipball/71c3273b6dcf93abe98eadb54707d2a59e190b7e",
|
||||
"reference": "71c3273b6dcf93abe98eadb54707d2a59e190b7e",
|
||||
"url": "https://api.github.com/repos/fleetbase/core-api/zipball/f5786609b581593945907a67f659a56bff8e0b93",
|
||||
"reference": "f5786609b581593945907a67f659a56bff8e0b93",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2252,9 +2252,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/fleetbase/core-api/issues",
|
||||
"source": "https://github.com/fleetbase/core-api/tree/v1.6.19"
|
||||
"source": "https://github.com/fleetbase/core-api/tree/v1.6.20"
|
||||
},
|
||||
"time": "2025-10-22T03:35:41+00:00"
|
||||
"time": "2025-10-27T21:04:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fleetbase/countries",
|
||||
@@ -2323,16 +2323,16 @@
|
||||
},
|
||||
{
|
||||
"name": "fleetbase/fleetops-api",
|
||||
"version": "0.6.20",
|
||||
"version": "0.6.21",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fleetbase/fleetops.git",
|
||||
"reference": "f0bbf9cc6fa2e68dca73c95fb93cf7d2b3cdae9d"
|
||||
"reference": "df585850698a8deaa69c77a965f8ab6de145493e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fleetbase/fleetops/zipball/f0bbf9cc6fa2e68dca73c95fb93cf7d2b3cdae9d",
|
||||
"reference": "f0bbf9cc6fa2e68dca73c95fb93cf7d2b3cdae9d",
|
||||
"url": "https://api.github.com/repos/fleetbase/fleetops/zipball/df585850698a8deaa69c77a965f8ab6de145493e",
|
||||
"reference": "df585850698a8deaa69c77a965f8ab6de145493e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2407,9 +2407,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/fleetbase/fleetops/issues",
|
||||
"source": "https://github.com/fleetbase/fleetops/tree/v0.6.20"
|
||||
"source": "https://github.com/fleetbase/fleetops/tree/v0.6.21"
|
||||
},
|
||||
"time": "2025-10-22T03:37:16+00:00"
|
||||
"time": "2025-10-27T21:19:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fleetbase/laravel-mysql-spatial",
|
||||
|
||||
@@ -17,9 +17,9 @@ export default class ConsoleController extends Controller {
|
||||
@service intl;
|
||||
@service universe;
|
||||
@service abilities;
|
||||
@service sidebar;
|
||||
@tracked organizations = [];
|
||||
@tracked sidebarContext;
|
||||
@tracked sidebarToggleEnabled = true;
|
||||
@tracked sidebarToggleState = {};
|
||||
@tracked hiddenSidebarRoutes = ['console.home', 'console.notifications', 'console.virtual'];
|
||||
@tracked menuItems = [];
|
||||
@@ -42,17 +42,17 @@ export default class ConsoleController extends Controller {
|
||||
|
||||
// Hide the sidebar if the current route is in hiddenSidebarRoutes
|
||||
if (shouldHideSidebar) {
|
||||
this.sidebarContext.hideNow();
|
||||
this.sidebar.hideNow();
|
||||
this.sidebarToggleEnabled = false;
|
||||
return; // Exit early as no further action is required
|
||||
}
|
||||
|
||||
// If the sidebar was manually closed and not on a hidden route, keep it closed
|
||||
if (isSidebarManuallyClosed) {
|
||||
this.sidebarContext.hideNow();
|
||||
this.sidebar.hideNow();
|
||||
} else {
|
||||
// Otherwise, show the sidebar
|
||||
this.sidebarContext.show();
|
||||
this.sidebar.show();
|
||||
}
|
||||
|
||||
// Ensure toggle is enabled unless on a hidden route
|
||||
@@ -87,7 +87,7 @@ export default class ConsoleController extends Controller {
|
||||
this.universe.trigger('sidebarContext.available', sidebarContext);
|
||||
|
||||
if (this.hiddenSidebarRoutes.includes(this.router.currentRouteName)) {
|
||||
this.sidebarContext.hideNow();
|
||||
this.sidebar.hideNow();
|
||||
this.sidebarToggleEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,11 @@ export default class DashboardModel extends Model {
|
||||
|
||||
/** @attributes */
|
||||
@attr('string') name;
|
||||
@attr('string') extension;
|
||||
@attr('boolean') is_default;
|
||||
@attr('array') tags;
|
||||
@attr('object') options;
|
||||
@attr('object') meta;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') created_at;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { computed } from '@ember/object';
|
||||
import { isArray } from '@ember/array';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { isPresent, isEmpty } from '@ember/utils';
|
||||
import { format, formatDistanceToNow } from 'date-fns';
|
||||
|
||||
export default class ReportModel extends Model {
|
||||
/** @ids */
|
||||
@@ -35,6 +36,10 @@ export default class ReportModel extends Model {
|
||||
@attr('raw') meta;
|
||||
@attr('string') status;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
|
||||
/** @relationships */
|
||||
// @belongsTo('company') company;
|
||||
// @belongsTo('user') createdBy;
|
||||
@@ -54,8 +59,23 @@ export default class ReportModel extends Model {
|
||||
}
|
||||
|
||||
/** @computed */
|
||||
@computed('query_config.columns.length', 'query_config.table.name')
|
||||
get hasValidConfig() {
|
||||
@computed('updated_at') get updatedAgo() {
|
||||
return formatDistanceToNow(this.updated_at);
|
||||
}
|
||||
|
||||
@computed('updated_at') get updatedAt() {
|
||||
return format(this.updated_at, 'yyyy-MM-dd HH:mm');
|
||||
}
|
||||
|
||||
@computed('created_at') get createdAgo() {
|
||||
return formatDistanceToNow(this.created_at);
|
||||
}
|
||||
|
||||
@computed('created_at') get createdAt() {
|
||||
return format(this.created_at, 'yyyy-MM-dd HH:mm');
|
||||
}
|
||||
|
||||
@computed('query_config.columns.length', 'query_config.table.name') get hasValidConfig() {
|
||||
return (
|
||||
isPresent(this.query_config) &&
|
||||
isPresent(this.query_config.table) &&
|
||||
@@ -65,23 +85,19 @@ export default class ReportModel extends Model {
|
||||
);
|
||||
}
|
||||
|
||||
@computed('query_config.table.name')
|
||||
get tableName() {
|
||||
@computed('query_config.table.name') get tableName() {
|
||||
return this.query_config?.table?.name || '';
|
||||
}
|
||||
|
||||
@computed('query_config.table.label', 'tableName')
|
||||
get tableLabel() {
|
||||
@computed('query_config.table.label', 'tableName') get tableLabel() {
|
||||
return this.query_config?.table?.label || this.tableName;
|
||||
}
|
||||
|
||||
@computed('query_config.columns.[]')
|
||||
get selectedColumns() {
|
||||
@computed('query_config.columns.[]') get selectedColumns() {
|
||||
return this.query_config?.columns || [];
|
||||
}
|
||||
|
||||
@computed('selectedColumns.[]', 'query_config.joins.[]')
|
||||
get totalSelectedColumns() {
|
||||
@computed('selectedColumns.[]', 'query_config.joins.[]') get totalSelectedColumns() {
|
||||
let count = this.selectedColumns.length;
|
||||
|
||||
// Add columns from joins
|
||||
@@ -96,13 +112,11 @@ export default class ReportModel extends Model {
|
||||
return count;
|
||||
}
|
||||
|
||||
@computed('query_config.joins.[]')
|
||||
get hasJoins() {
|
||||
@computed('query_config.joins.[]') get hasJoins() {
|
||||
return isArray(this.query_config?.joins) && this.query_config.joins.length > 0;
|
||||
}
|
||||
|
||||
@computed('hasJoins', 'query_config.joins.[]')
|
||||
get joinedTables() {
|
||||
@computed('hasJoins', 'query_config.joins.[]') get joinedTables() {
|
||||
if (!this.hasJoins) {
|
||||
return [];
|
||||
}
|
||||
@@ -115,13 +129,11 @@ export default class ReportModel extends Model {
|
||||
}));
|
||||
}
|
||||
|
||||
@computed('query_config.conditions.[]')
|
||||
get hasConditions() {
|
||||
@computed('query_config.conditions.[]') get hasConditions() {
|
||||
return isArray(this.query_config?.conditions) && this.query_config.conditions.length > 0;
|
||||
}
|
||||
|
||||
@computed('hasConditions', 'query_config.conditions.[]')
|
||||
get conditionsCount() {
|
||||
@computed('hasConditions', 'query_config.conditions.[]') get conditionsCount() {
|
||||
if (!this.hasConditions) {
|
||||
return 0;
|
||||
}
|
||||
@@ -129,23 +141,19 @@ export default class ReportModel extends Model {
|
||||
return this.countConditionsRecursively(this.query_config.conditions);
|
||||
}
|
||||
|
||||
@computed('query_config.groupBy.[]')
|
||||
get hasGrouping() {
|
||||
@computed('query_config.groupBy.[]') get hasGrouping() {
|
||||
return isArray(this.query_config?.groupBy) && this.query_config.groupBy.length > 0;
|
||||
}
|
||||
|
||||
@computed('query_config.sortBy.[]')
|
||||
get hasSorting() {
|
||||
@computed('query_config.sortBy.[]') get hasSorting() {
|
||||
return isArray(this.query_config?.sortBy) && this.query_config.sortBy.length > 0;
|
||||
}
|
||||
|
||||
@computed('query_config.limit')
|
||||
get hasLimit() {
|
||||
@computed('query_config.limit') get hasLimit() {
|
||||
return isPresent(this.query_config?.limit) && this.query_config.limit > 0;
|
||||
}
|
||||
|
||||
@computed('conditionsCount', 'hasGrouping', 'hasJoins', 'joinedTables.length', 'totalSelectedColumns')
|
||||
get complexity() {
|
||||
@computed('conditionsCount', 'hasGrouping', 'hasJoins', 'joinedTables.length', 'totalSelectedColumns') get complexity() {
|
||||
let score = 0;
|
||||
|
||||
score += this.totalSelectedColumns;
|
||||
@@ -162,8 +170,7 @@ export default class ReportModel extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
@computed('complexity', 'totalSelectedColumns', 'joinedTables.length')
|
||||
get estimatedPerformance() {
|
||||
@computed('complexity', 'totalSelectedColumns', 'joinedTables.length') get estimatedPerformance() {
|
||||
if (this.complexity === 'simple' && this.totalSelectedColumns <= 10) {
|
||||
return 'fast';
|
||||
} else if (this.complexity === 'moderate' && this.joinedTables.length <= 2) {
|
||||
@@ -173,8 +180,7 @@ export default class ReportModel extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
@computed('last_executed_at')
|
||||
get lastExecutedDisplay() {
|
||||
@computed('last_executed_at') get lastExecutedDisplay() {
|
||||
if (!this.last_executed_at) {
|
||||
return 'Never executed';
|
||||
}
|
||||
@@ -182,8 +188,7 @@ export default class ReportModel extends Model {
|
||||
return this.last_executed_at.toLocaleDateString() + ' ' + this.last_executed_at.toLocaleTimeString();
|
||||
}
|
||||
|
||||
@computed('average_execution_time')
|
||||
get averageExecutionTimeDisplay() {
|
||||
@computed('average_execution_time') get averageExecutionTimeDisplay() {
|
||||
if (!this.average_execution_time) {
|
||||
return 'N/A';
|
||||
}
|
||||
@@ -195,13 +200,11 @@ export default class ReportModel extends Model {
|
||||
}
|
||||
}
|
||||
|
||||
@computed('execution_count')
|
||||
get executionCountDisplay() {
|
||||
@computed('execution_count') get executionCountDisplay() {
|
||||
return this.execution_count || 0;
|
||||
}
|
||||
|
||||
@computed('last_result_count')
|
||||
get lastResultCountDisplay() {
|
||||
@computed('last_result_count') get lastResultCountDisplay() {
|
||||
if (this.last_result_count === null || this.last_result_count === undefined) {
|
||||
return 'N/A';
|
||||
}
|
||||
@@ -209,23 +212,19 @@ export default class ReportModel extends Model {
|
||||
return this.last_result_count.toLocaleString();
|
||||
}
|
||||
|
||||
@computed('export_formats.[]')
|
||||
get availableExportFormats() {
|
||||
@computed('export_formats.[]') get availableExportFormats() {
|
||||
return this.export_formats || ['csv', 'excel', 'json'];
|
||||
}
|
||||
|
||||
@computed('tags.[]')
|
||||
get tagsList() {
|
||||
@computed('tags.[]') get tagsList() {
|
||||
return this.tags || [];
|
||||
}
|
||||
|
||||
@computed('shared_with.[]')
|
||||
get sharedWithList() {
|
||||
@computed('shared_with.[]') get sharedWithList() {
|
||||
return this.shared_with || [];
|
||||
}
|
||||
|
||||
@computed('is_scheduled', 'next_scheduled_run', 'schedule_frequency', 'schedule_timezone')
|
||||
get scheduleInfo() {
|
||||
@computed('is_scheduled', 'next_scheduled_run', 'schedule_frequency', 'schedule_timezone') get scheduleInfo() {
|
||||
if (!this.is_scheduled) {
|
||||
return null;
|
||||
}
|
||||
@@ -237,8 +236,7 @@ export default class ReportModel extends Model {
|
||||
};
|
||||
}
|
||||
|
||||
@computed('hasConditions', 'query_config.conditions.[]')
|
||||
get conditionsSummary() {
|
||||
@computed('hasConditions', 'query_config.conditions.[]') get conditionsSummary() {
|
||||
if (!this.hasConditions) {
|
||||
return [];
|
||||
}
|
||||
@@ -246,8 +244,7 @@ export default class ReportModel extends Model {
|
||||
return this.extractConditionsSummary(this.query_config.conditions);
|
||||
}
|
||||
|
||||
@computed('status')
|
||||
get statusDisplay() {
|
||||
@computed('status') get statusDisplay() {
|
||||
const statusMap = {
|
||||
draft: 'Draft',
|
||||
active: 'Active',
|
||||
@@ -258,8 +255,7 @@ export default class ReportModel extends Model {
|
||||
return statusMap[this.status] || this.status;
|
||||
}
|
||||
|
||||
@computed('status')
|
||||
get statusClass() {
|
||||
@computed('status') get statusClass() {
|
||||
const statusClasses = {
|
||||
draft: 'status-draft',
|
||||
active: 'status-active',
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@userMenuItems={{this.userMenuItems}}
|
||||
@onAction={{this.onAction}}
|
||||
@showSidebarToggle={{true}}
|
||||
@sidebarToggleEnabled={{this.sidebarToggleEnabled}}
|
||||
@sidebarToggleEnabled={{true}}
|
||||
@onSidebarToggle={{this.onSidebarToggle}}
|
||||
/>
|
||||
<Layout::Main class={{this.currentRouteClass}}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{{page-title "Dashboard"}}
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
<TwoFaEnforcementAlert />
|
||||
<Dashboard @sidebar={{this.sidebarContext}} @createWrapperClass="px-10" class="flex items-center justify-between mb-4 mt-6 px-14" />
|
||||
<Dashboard @extension="core" @createWrapperClass="px-10" class="flex items-center justify-between mb-4 mt-6 px-14" />
|
||||
<Spacer @height="300px" />
|
||||
</Layout::Section::Body>
|
||||
<div id="console-home-wormhole" />
|
||||
@@ -49,7 +49,8 @@ module.exports = function (environment) {
|
||||
|
||||
defaultValues: {
|
||||
categoryImage: getenv('DEFAULT_CATEGORY_IMAGE', 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/images/fallback-placeholder-1.png'),
|
||||
placeholderImage: getenv('DEFAULT_PLACEHOLDER_IMAGE', 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/images/fallback-placeholder-2.png'),
|
||||
placeholderImage: getenv('DEFAULT_PLACEHOLDER_IMAGE', 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/static/image-file-icon.png'),
|
||||
placeholderImageOld: getenv('DEFAULT_PLACEHOLDER_IMAGE_OLD', 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/images/fallback-placeholder-2.png'),
|
||||
driverImage: getenv('DEFAULT_DRIVER_IMAGE', 'https://s3.ap-southeast-1.amazonaws.com/flb-assets/static/no-avatar.png'),
|
||||
userImage: getenv('DEFAULT_USER_IMAGE', 'https://s3.ap-southeast-1.amazonaws.com/flb-assets/static/no-avatar.png'),
|
||||
contactImage: getenv('DEFAULT_CONTACT_IMAGE', 'https://s3.ap-southeast-1.amazonaws.com/flb-assets/static/no-avatar.png'),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fleetbase/console",
|
||||
"version": "0.7.12",
|
||||
"version": "0.7.13",
|
||||
"private": true,
|
||||
"description": "Modular logistics and supply chain operating system (LSOS)",
|
||||
"repository": "https://github.com/fleetbase/fleetbase",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@fleetbase/ember-core": "latest",
|
||||
"@fleetbase/ember-ui": "latest",
|
||||
"@fleetbase/fleetops-data": "latest",
|
||||
"@fleetbase/fleetops-engine": "^0.6.20",
|
||||
"@fleetbase/fleetops-engine": "^0.6.21",
|
||||
"@fleetbase/iam-engine": "^0.1.4",
|
||||
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
||||
"@fleetbase/registry-bridge-engine": "^0.1.0",
|
||||
|
||||
832
console/pnpm-lock.yaml
generated
832
console/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -75,7 +75,7 @@ ENV QUEUE_CONNECTION=redis
|
||||
ENV CADDYFILE_PATH=/fleetbase/Caddyfile
|
||||
ENV CONSOLE_PATH=/fleetbase/console
|
||||
ENV OCTANE_SERVER=frankenphp
|
||||
ENV FLEETBASE_VERSION=0.7.12
|
||||
ENV FLEETBASE_VERSION=0.7.13
|
||||
|
||||
# Set environment
|
||||
ARG ENVIRONMENT=production
|
||||
|
||||
Submodule packages/core-api updated: 71c3273b6d...f5786609b5
Submodule packages/ember-ui updated: f54679889c...248243492b
Submodule packages/fleetops updated: f0bbf9cc6f...df58585069
Submodule packages/fleetops-data updated: 6330695dae...2fd746efe7
Reference in New Issue
Block a user