mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-03-04 06:27:40 +00:00
Compare commits
6 Commits
main
...
dev-v0.7.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0666bc611c | ||
|
|
8244fdce90 | ||
|
|
e0f9aeb5a9 | ||
|
|
b2fe2b909b | ||
|
|
3fcd21ec28 | ||
|
|
0bcd9ec165 |
90
console/app/models/template-query.js
Normal file
90
console/app/models/template-query.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import Model, { attr, belongsTo } from '@ember-data/model';
|
||||
import { computed } from '@ember/object';
|
||||
import { format, formatDistanceToNow } from 'date-fns';
|
||||
|
||||
export default class TemplateQueryModel extends Model {
|
||||
/** @ids */
|
||||
@attr('string') public_id;
|
||||
@attr('string') uuid;
|
||||
@attr('string') company_uuid;
|
||||
@attr('string') template_uuid;
|
||||
|
||||
/** @relationships */
|
||||
@belongsTo('template', { async: false, inverse: 'queries' }) template;
|
||||
|
||||
/** @attributes */
|
||||
@attr('string') name;
|
||||
@attr('string') label;
|
||||
@attr('string') description;
|
||||
|
||||
/**
|
||||
* The fully-qualified PHP model class this query runs against.
|
||||
* e.g. "Fleetbase\\Models\\Order", "Fleetbase\\Ledger\\Models\\Invoice"
|
||||
*/
|
||||
@attr('string') resource_type;
|
||||
|
||||
/**
|
||||
* JSON object of filter conditions applied to the query.
|
||||
* e.g. { "status": "completed", "created_at_gte": "2024-12-01" }
|
||||
*/
|
||||
@attr('object', { defaultValue: () => ({}) }) filters;
|
||||
|
||||
@attr('string') sort_by;
|
||||
@attr('string', { defaultValue: 'desc' }) sort_direction;
|
||||
@attr('number') limit;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') deleted_at;
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
|
||||
/** @computed */
|
||||
|
||||
/**
|
||||
* The variable name available in the template for iterating this query's results.
|
||||
* Derived from the `name` field — lowercased and underscored.
|
||||
* e.g. name "December Orders" → variable "{december_orders}"
|
||||
*/
|
||||
@computed('name') get variableName() {
|
||||
if (!this.name) return '';
|
||||
return this.name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '_')
|
||||
.replace(/^_+|_+$/g, '');
|
||||
}
|
||||
|
||||
@computed('variableName') get variableToken() {
|
||||
return `{${this.variableName}}`;
|
||||
}
|
||||
|
||||
@computed('resource_type') get resourceTypeLabel() {
|
||||
if (!this.resource_type) return '';
|
||||
// Extract the short class name from the fully-qualified namespace
|
||||
const parts = this.resource_type.split('\\');
|
||||
return parts[parts.length - 1];
|
||||
}
|
||||
|
||||
@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('updated_at') get updatedAtShort() {
|
||||
return format(this.updated_at, 'PP');
|
||||
}
|
||||
|
||||
@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('created_at') get createdAtShort() {
|
||||
return format(this.created_at, 'PP');
|
||||
}
|
||||
}
|
||||
74
console/app/models/template.js
Normal file
74
console/app/models/template.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import Model, { attr, hasMany } from '@ember-data/model';
|
||||
import { computed } from '@ember/object';
|
||||
import { format, formatDistanceToNow } from 'date-fns';
|
||||
|
||||
export default class TemplateModel extends Model {
|
||||
/** @ids */
|
||||
@attr('string') public_id;
|
||||
@attr('string') uuid;
|
||||
@attr('string') company_uuid;
|
||||
@attr('string') created_by_uuid;
|
||||
|
||||
/** @relationships */
|
||||
@hasMany('template-query', { async: false, inverse: 'template' }) queries;
|
||||
|
||||
/** @attributes */
|
||||
@attr('string') name;
|
||||
@attr('string') description;
|
||||
@attr('string') context_type;
|
||||
@attr('string', { defaultValue: 'A4' }) paper_size;
|
||||
@attr('string', { defaultValue: 'portrait' }) orientation;
|
||||
@attr('number') width;
|
||||
@attr('number') height;
|
||||
@attr('string', { defaultValue: 'mm' }) unit;
|
||||
@attr('string', { defaultValue: '#ffffff' }) background_color;
|
||||
@attr('array') content;
|
||||
@attr('boolean', { defaultValue: false }) is_default;
|
||||
@attr('string', { defaultValue: 'draft' }) status;
|
||||
@attr('object') meta;
|
||||
|
||||
/** @dates */
|
||||
@attr('date') deleted_at;
|
||||
@attr('date') created_at;
|
||||
@attr('date') updated_at;
|
||||
|
||||
/** @computed */
|
||||
@computed('status') get isDraft() {
|
||||
return this.status === 'draft';
|
||||
}
|
||||
|
||||
@computed('status') get isPublished() {
|
||||
return this.status === 'published';
|
||||
}
|
||||
|
||||
@computed('paper_size', 'orientation') get dimensionLabel() {
|
||||
if (this.paper_size === 'custom') {
|
||||
return `${this.width} × ${this.height} ${this.unit}`;
|
||||
}
|
||||
return `${this.paper_size} (${this.orientation})`;
|
||||
}
|
||||
|
||||
@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('updated_at') get updatedAtShort() {
|
||||
return format(this.updated_at, 'PP');
|
||||
}
|
||||
|
||||
@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('created_at') get createdAtShort() {
|
||||
return format(this.created_at, 'PP');
|
||||
}
|
||||
}
|
||||
@@ -59,27 +59,24 @@ module.exports = {
|
||||
|
||||
const extensions = await this.getExtensions();
|
||||
|
||||
if (extensions.length === 0) {
|
||||
console.log('[Fleetbase] No extensions found');
|
||||
return;
|
||||
if (extensions.length > 0) {
|
||||
console.log(`[Fleetbase] Discovered ${extensions.length} extension(s)`);
|
||||
extensions.forEach((ext) => {
|
||||
console.log(`[Fleetbase] - ${ext.name} (v${ext.version})`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
// Generate extension shims (only needed when extensions are present)
|
||||
this.generateExtensionShims(extensions);
|
||||
} else {
|
||||
console.log('[Fleetbase] No extensions found — generating empty extension loader to satisfy module dependencies.');
|
||||
}
|
||||
|
||||
console.log(`[Fleetbase] Discovered ${extensions.length} extension(s)`);
|
||||
extensions.forEach((ext) => {
|
||||
console.log(`[Fleetbase] - ${ext.name} (v${ext.version})`);
|
||||
});
|
||||
console.log('');
|
||||
|
||||
// Generate extension shims
|
||||
this.generateExtensionShims(extensions);
|
||||
|
||||
// Generate extension loaders
|
||||
// Always generate loaders, router, and manifest so that
|
||||
// @fleetbase/console/extensions (app/extensions/index.js) always exists
|
||||
// and the build does not fail when zero extensions are installed.
|
||||
this.generateExtensionLoaders(extensions);
|
||||
|
||||
// Generate router
|
||||
this.generateRouter(extensions);
|
||||
|
||||
// Generate manifest
|
||||
this.generateExtensionsManifest(extensions);
|
||||
},
|
||||
|
||||
@@ -227,7 +224,7 @@ export default getExtensionLoader;
|
||||
|
||||
recast.visit(ast, {
|
||||
visitCallExpression(path) {
|
||||
if (path.value.type === 'CallExpression' && path.value.callee.property.name === 'route' && path.value.arguments[0].value === 'console') {
|
||||
if (path.value.type === 'CallExpression' && path.value.callee.property && path.value.callee.property.name === 'route' && path.value.arguments[0] && path.value.arguments[0].value === 'console') {
|
||||
let functionExpression;
|
||||
|
||||
// Find the function expression
|
||||
@@ -270,7 +267,7 @@ export default getExtensionLoader;
|
||||
}
|
||||
}
|
||||
|
||||
if (path.value.type === 'CallExpression' && path.value.callee.property.name === 'map') {
|
||||
if (path.value.type === 'CallExpression' && path.value.callee.property && path.value.callee.property.name === 'map') {
|
||||
let functionExpression;
|
||||
|
||||
path.value.arguments.forEach((arg) => {
|
||||
|
||||
Reference in New Issue
Block a user