Compare commits

..

2 Commits

Author SHA1 Message Date
Ronald A. Richardson
ff59941947 wip: binary build 2024-04-03 15:15:27 +08:00
Ronald A. Richardson
013e19f39e working on single executable binary for linux and macos of fleetbase 2024-04-02 21:21:24 +08:00
35 changed files with 8005 additions and 14413 deletions

View File

@@ -9,8 +9,8 @@
"license": "MIT",
"require": {
"php": "^8.0",
"fleetbase/core-api": "^1.4.22",
"fleetbase/fleetops-api": "^0.4.27",
"fleetbase/core-api": "^1.4.16",
"fleetbase/fleetops-api": "^0.4.24",
"fleetbase/storefront-api": "^0.3.7",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^10.0",
@@ -32,12 +32,6 @@
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.0"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/fleetbase/laravel-model-caching"
}
],
"autoload": {
"psr-4": {
"App\\": "app/",
@@ -98,6 +92,6 @@
"php-http/discovery": true
}
},
"minimum-stability": "dev",
"minimum-stability": "stable",
"prefer-stable": true
}

1167
api/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -52,7 +52,7 @@ return [
|
*/
'url' => env('APP_URL', 'http://localhost:8000'),
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL', null),

View File

@@ -20,6 +20,3 @@ php artisan queue:restart
# Sync scheduler
php artisan schedule-monitor:sync
# Clear cache
php artisan cache:clear

View File

@@ -0,0 +1,30 @@
<div class="next-user-button" ...attributes>
<BasicDropdown @defaultClass={{@wrapperClass}} @onOpen={{@onOpen}} @onClose={{@onClose}} @verticalPosition={{@verticalPosition}} @horizontalPosition={{@horizontalPosition}} @renderInPlace={{or @renderInPlace true}} @initiallyOpened={{@initiallyOpened}} as |dd|>
<dd.Trigger class={{@triggerClass}}>
<div class="next-org-button-trigger flex-shrink-0 {{if dd.isOpen 'is-open'}}">
<FaIcon @icon="globe" @size="sm" />
</div>
</dd.Trigger>
<dd.Content class={{@contentClass}}>
<div class="next-dd-menu {{@dropdownMenuClass}} {{if dd.isOpen 'is-open'}}">
{{#each-in this.availableLocales as |key country|}}
<div class="px-1">
<a href="javascript:;" class="next-dd-item" {{on "click" (fn this.changeLocale key)}}>
<div class="flex flex-row items-center justify-between w-full">
<div class="flex-1">
<span class="mr-1">{{country.emoji}}</span>
<span>{{country.language}}</span>
</div>
{{#if (eq this.currentLocale key)}}
<div>
<FaIcon @icon="check" class="text-green-400" />
</div>
{{/if}}
</div>
</a>
</div>
{{/each-in}}
</div>
</dd.Content>
</BasicDropdown>
</div>

View File

@@ -0,0 +1,144 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { task } from 'ember-concurrency-decorators';
export default class LocaleSelectorComponent extends Component {
/**
* Inject the intl service.
*
* @memberof LocaleSelectorComponent
*/
@service intl;
/**
* Inject the intl service.
*
* @memberof LocaleSelectorComponent
*/
@service fetch;
/**
* Tracks all the available locales.
*
* @memberof LocaleSelectorComponent
*/
@tracked locales = [];
/**
* All available countries data.
*
* @memberof LocaleSelectorComponent
*/
@tracked countries = [];
/**
* The current locale in use.
*
* @memberof LocaleSelectorComponent
*/
@tracked currentLocale;
/**
* Creates an instance of LocaleSelectorComponent.
* @memberof LocaleSelectorComponent
*/
constructor() {
super(...arguments);
this.locales = this.intl.locales;
this.currentLocale = this.intl.primaryLocale;
this.loadAvailableCountries.perform();
// Check for locale change
this.intl.onLocaleChanged(() => {
this.currentLocale = this.intl.primaryLocale;
});
}
/**
* Handles the change of locale.
* @param {string} selectedLocale - The selected locale.
* @returns {void}
* @memberof LocaleSelectorComponent
* @method changeLocale
* @instance
* @action
*/
@action changeLocale(selectedLocale) {
this.currentLocale = selectedLocale;
this.intl.setLocale(selectedLocale);
// Persist to server
this.saveUserLocale.perform(selectedLocale);
}
/**
* Loads available countries asynchronously.
* @returns {void}
* @memberof LocaleSelectorComponent
* @method loadAvailableCountries
* @instance
* @task
* @generator
*/
@task *loadAvailableCountries() {
this.countries = yield this.fetch.get('lookup/countries', { columns: ['name', 'cca2', 'flag', 'emoji', 'languages'] });
this.availableLocales = this._createAvailableLocaleMap();
}
/**
* Saves the user's selected locale to the server.
* @param {string} locale - The user's selected locale.
* @returns {void}
* @memberof LocaleSelectorComponent
* @method saveUserLocale
* @instance
* @task
* @generator
*/
@task *saveUserLocale(locale) {
yield this.fetch.post('users/locale', { locale });
}
/**
* Creates a map of available locales.
* @private
* @returns {Object} - The map of available locales.
* @memberof LocaleSelectorComponent
* @method _createAvailableLocaleMap
* @instance
*/
_createAvailableLocaleMap() {
const localeMap = {};
for (let i = 0; i < this.locales.length; i++) {
const locale = this.locales.objectAt(i);
localeMap[locale] = this._findCountryDataForLocale(locale);
}
return localeMap;
}
/**
* Finds country data for a given locale.
* @private
* @param {string} locale - The locale to find country data for.
* @returns {Object|null} - The country data or null if not found.
* @memberof LocaleSelectorComponent
* @method _findCountryDataForLocale
* @instance
*/
_findCountryDataForLocale(locale) {
const localeCountry = locale.split('-')[1];
const country = this.countries.find((country) => country.cca2.toLowerCase() === localeCountry);
if (country) {
// get the language
country.language = Object.values(country.languages)[0];
}
return country;
}
}

View File

@@ -174,7 +174,6 @@ export default class ConsoleController extends Controller {
@action setSidebarContext(sidebarContext) {
this.sidebarContext = sidebarContext;
this.universe.sidebarContext = sidebarContext;
this.universe.trigger('sidebarContext.available', sidebarContext);
if (this.hiddenSidebarRoutes.includes(this.router.currentRouteName)) {
this.sidebarContext.hideNow();

View File

@@ -1,84 +0,0 @@
import Model, { attr, belongsTo } from '@ember-data/model';
import { getOwner } from '@ember/application';
import { computed } from '@ember/object';
import { format, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
import isVideoFile from '@fleetbase/ember-core/utils/is-video-file';
import isImageFile from '@fleetbase/ember-core/utils/is-image-file';
export default class ChatAttachment extends Model {
/** @ids */
@attr('string') chat_channel_uuid;
@attr('string') sender_uuid;
@attr('string') file_uuid;
@attr('string') chat_message_uuid;
/** @relationships */
@belongsTo('user', { async: true }) sender;
@belongsTo('chat-channel', { async: true }) chatChannel;
@belongsTo('file', { async: true }) file;
/** @attributes */
@attr('string') chat_channel_uuid;
@attr('string') sender_uuid;
@attr('string') file_uuid;
@attr('string') url;
@attr('string') filename;
@attr('string') content_type;
/** @dates */
@attr('date') created_at;
@attr('date') updated_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at);
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at);
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
@computed('content_type') get isVideo() {
return isVideoFile(this.content_type);
}
@computed('content_type') get isImage() {
return isImageFile(this.content_type);
}
/** @methods */
downloadFromApi() {
window.open(ENV.api.host + '/' + ENV.api.namespace + '/files/download?file=' + this.file_uuid, '_self');
}
download() {
const owner = getOwner(this);
const fetch = owner.lookup('service:fetch');
return fetch.download('files/download', { file: this.file_uuid }, { fileName: this.filename, mimeType: this.content_type });
}
}

View File

@@ -1,87 +0,0 @@
import Model, { attr, hasMany, belongsTo } from '@ember-data/model';
import { computed } from '@ember/object';
import { getOwner } from '@ember/application';
import { format, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
export default class ChatChannelModel extends Model {
/** @ids */
@attr('string') public_id;
@attr('string') company_uuid;
@attr('string') created_by_uuid;
/** @attributes */
@attr('string') name;
@attr('string') title;
@attr('number') unread_count;
@attr('string') slug;
@attr('array') feed;
@attr('array') meta;
/** @relationships */
@hasMany('chat-participant', { async: false }) participants;
@belongsTo('chat-message', { async: false }) last_message;
/** @dates */
@attr('date') created_at;
@attr('date') updated_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at);
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at);
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
/** @methods */
toJSON() {
return {
company_uuid: this.company_uuid,
name: this.name,
meta: this.meta,
};
}
reloadParticipants() {
const owner = getOwner(this);
const store = owner.lookup('service:store');
return store.query('chat-participant', { chat_channel_uuid: this.id }).then((participants) => {
this.set('participants', participants);
return participants;
});
}
existsInFeed(type, record) {
return this.feed.find((_) => _.type === type && _.record.id === record.id) !== undefined;
}
doesntExistsInFeed(type, record) {
return this.feed.find((_) => _.type === type && _.record.id === record.id) === undefined;
}
}

View File

@@ -1,54 +0,0 @@
import Model, { attr, belongsTo } from '@ember-data/model';
import { computed } from '@ember/object';
import { format, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
export default class ChatLogModel extends Model {
/** @ids */
@attr('string') company_uuid;
@attr('string') chat_channel_uuid;
@attr('string') initiator_uuid;
/** @attributes */
@attr('string') content;
@attr('string') resolved_content;
@attr('string') event_type;
@attr('string') status;
@attr('array') meta;
/** @dates */
@attr('date') created_at;
@attr('date') updated_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at, { addSuffix: true });
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at, { addSuffix: true });
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
}

View File

@@ -1,64 +0,0 @@
import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
import { computed } from '@ember/object';
import { format, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
export default class ChatMessage extends Model {
/** @ids */
@attr('string') chat_channel_uuid;
@attr('string') sender_uuid;
/** @attributes */
@attr('string') content;
@attr('array') attachment_files;
/** @relationships */
@belongsTo('chat-participant', { async: false }) sender;
@hasMany('chat-attachment', { async: false }) attachments;
@hasMany('chat-receipt', { async: false }) receipts;
/** @dates */
@attr('date') created_at;
@attr('date') updated_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at, { addSuffix: true });
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at, { addSuffix: true });
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
/** @methods */
hasReadReceipt(chatParticipant) {
return chatParticipant && this.receipts.find((receipt) => chatParticipant.id === receipt.participant_uuid) !== undefined;
}
doesntHaveReadReceipt(chatParticipant) {
return !this.hasReadReceipt(chatParticipant);
}
}

View File

@@ -1,75 +0,0 @@
import Model, { attr, belongsTo } from '@ember-data/model';
import { computed } from '@ember/object';
import { format, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
export default class ChatParticipant extends Model {
/** @ids */
@attr('string') user_uuid;
@attr('string') chat_channel_uuid;
/** @attributes */
@attr('string') name;
@attr('string') username;
@attr('string') phone;
@attr('string') email;
@attr('string') avatar_url;
@attr('boolean') is_online;
/** @relationships */
@belongsTo('user', { async: true }) user;
@belongsTo('chat-channel', { async: true }) chatChannel;
/** @dates */
@attr('date') last_seen_at;
@attr('date') created_at;
@attr('date') updated_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at);
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at);
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
@computed('last_seen_at') get lastSeenAgo() {
if (!isValidDate(this.last_seen_at)) {
return null;
}
return formatDistanceToNow(this.last_seen_at);
}
@computed('last_seen_at') get lastSeenAt() {
if (!isValidDate(this.last_seen_at)) {
return null;
}
return formatDate(this.last_seen_at, 'PP HH:mm');
}
}

View File

@@ -1,70 +0,0 @@
import Model, { attr, belongsTo } from '@ember-data/model';
import { computed } from '@ember/object';
import { format as formatDate, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
export default class ChatReceipt extends Model {
/** @ids */
@attr('string') participant_uuid;
@attr('string') chat_message_uuid;
/** @relationships */
@belongsTo('chat-participant', { async: true }) participant;
@belongsTo('chat-message', { async: true }) chatMessage;
/** @attributes */
@attr('string') participant_name;
/** @dates */
@attr('date') created_at;
@attr('date') updated_at;
@attr('date') read_at;
/** @computed */
@computed('updated_at') get updatedAgo() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDistanceToNow(this.updated_at, { addSuffix: true });
}
@computed('updated_at') get updatedAt() {
if (!isValidDate(this.updated_at)) {
return null;
}
return formatDate(this.updated_at, 'PP HH:mm');
}
@computed('created_at') get createdAgo() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDistanceToNow(this.created_at, { addSuffix: true });
}
@computed('created_at') get createdAt() {
if (!isValidDate(this.created_at)) {
return null;
}
return formatDate(this.created_at, 'PP HH:mm');
}
@computed('read_at') get readAgo() {
if (!isValidDate(this.read_at)) {
return null;
}
return formatDistanceToNow(this.read_at, { addSuffix: true });
}
@computed('read_at') get readAt() {
if (!isValidDate(this.read_at)) {
return null;
}
return formatDate(this.read_at, 'PP HH:mm');
}
}

View File

@@ -69,8 +69,8 @@ export default class FileModel extends Model {
download() {
const owner = getOwner(this);
const fetch = owner.lookup('service:fetch');
const fetch = owner.lookup(`service:store`);
return fetch.download('files/download', { file: this.id }, { fileName: this.original_filename, mimeType: this.content_type });
return fetch.download('files/download', { file: this.id });
}
}

View File

@@ -26,13 +26,11 @@ export default class UserModel extends Model {
@attr('string') type;
@attr('string') session_status;
@attr('string') status;
@attr('boolean') is_online;
@attr('boolean') is_admin;
@attr('raw') types;
@attr('raw') meta;
/** @dates */
@attr('date') last_seen_at;
@attr('date') phone_verified_at;
@attr('date') email_verified_at;
@attr('date') last_login;

View File

@@ -1,60 +0,0 @@
import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
import { getOwner } from '@ember/application';
import { underscore } from '@ember/string';
import { isArray } from '@ember/array';
export default class ChatChannelSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
/**
* Embedded relationship attributes
*
* @var {Object}
*/
get attrs() {
return {
participants: { embedded: 'always' },
last_message: { embedded: 'always' },
};
}
serialize(snapshot) {
let json = {
name: snapshot.attr('name'),
meta: snapshot.attr('meta'),
};
return json;
}
normalize(typeClass, hash) {
if (isArray(hash.feed)) {
hash.feed = this.serializeFeed(hash.feed);
}
return super.normalize(...arguments);
}
serializeFeed(feed = []) {
return feed.map((item) => this.serializeItem(item)).sortBy('created_at');
}
serializeItem(item) {
switch (item.type) {
case 'message':
return { ...item, record: this.serializeItemType('chat-message', item.data) };
case 'log':
return { ...item, record: this.serializeItemType('chat-log', item.data) };
case 'attachment':
return { ...item, record: this.serializeItemType('chat-attachment', item.data) };
default:
return null;
}
}
serializeItemType(modelType, data) {
const owner = getOwner(this);
const store = owner.lookup('service:store');
const normalized = store.normalize(modelType, data);
return store.push(normalized);
}
}

View File

@@ -1,17 +0,0 @@
import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
export default class ChatMessageSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
/**
* Embedded relationship attributes
*
* @var {Object}
*/
get attrs() {
return {
sender: { embedded: 'always' },
attachments: { embedded: 'always' },
receipts: { embedded: 'always' },
};
}
}

View File

@@ -1,3 +0,0 @@
import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
export default class ChatParticipantSerializer extends ApplicationSerializer {}

View File

@@ -14,5 +14,9 @@
</Layout::Main>
<Layout::MobileNavbar @brand={{@model}} @user={{this.user}} @organizations={{this.organizations}} @menuItems={{this.universe.headerMenuItems}} @extensions={{this.extensions}} @onAction={{this.onAction}} />
</Layout::Container>
<ChatContainer />
<ConsoleWormhole />
{{!-- Add Locale Selector to Header --}}
<EmberWormhole @to="view-header-actions">
<LocaleSelector class="mr-0.5" />
</EmberWormhole>
<ConsoleWormhole />

View File

@@ -1,6 +1,6 @@
{
"name": "@fleetbase/console",
"version": "0.4.21",
"version": "0.4.16",
"private": true,
"description": "Fleetbase Console",
"repository": "https://github.com/fleetbase/fleetbase",
@@ -29,9 +29,9 @@
"test:ember": "ember test"
},
"dependencies": {
"@fleetbase/ember-core": "^0.2.9",
"@fleetbase/ember-ui": "^0.2.13",
"@fleetbase/fleetops-engine": "^0.4.27",
"@fleetbase/ember-core": "^0.2.8",
"@fleetbase/ember-ui": "^0.2.12",
"@fleetbase/fleetops-engine": "^0.4.24",
"@fleetbase/fleetops-data": "^0.1.14",
"@fleetbase/storefront-engine": "^0.3.7",
"@fleetbase/dev-engine": "^0.2.2",
@@ -142,8 +142,8 @@
},
"pnpm": {
"overrides": {
"@fleetbase/ember-core": "^0.2.9",
"@fleetbase/ember-ui": "^0.2.13",
"@fleetbase/ember-core": "^0.2.8",
"@fleetbase/ember-ui": "^0.2.12",
"@fleetbase/fleetops-data": "^0.1.14"
}
},

1496
console/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from '@fleetbase/console/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | locale-selector', function (hooks) {
setupRenderingTest(hooks);
test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<LocaleSelector />`);
assert.dom().hasText('');
// Template block usage:
await render(hbs`
<LocaleSelector>
template block text
</LocaleSelector>
`);
assert.dom().hasText('template block text');
});
});

View File

@@ -1,14 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from '@fleetbase/console/tests/helpers';
module('Unit | Model | chat log', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('chat-log', {});
assert.ok(model);
});
});

View File

@@ -1,24 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from '@fleetbase/console/tests/helpers';
module('Unit | Serializer | chat channel', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let serializer = store.serializerFor('chat-channel');
assert.ok(serializer);
});
test('it serializes records', function (assert) {
let store = this.owner.lookup('service:store');
let record = store.createRecord('chat-channel', {});
let serializedRecord = record.serialize();
assert.ok(serializedRecord);
});
});

View File

@@ -1,24 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from '@fleetbase/console/tests/helpers';
module('Unit | Serializer | chat message', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let serializer = store.serializerFor('chat-message');
assert.ok(serializer);
});
test('it serializes records', function (assert) {
let store = this.owner.lookup('service:store');
let record = store.createRecord('chat-message', {});
let serializedRecord = record.serialize();
assert.ok(serializedRecord);
});
});

View File

@@ -1,24 +0,0 @@
import { module, test } from 'qunit';
import { setupTest } from '@fleetbase/console/tests/helpers';
module('Unit | Serializer | chat participant', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let serializer = store.serializerFor('chat-participant');
assert.ok(serializer);
});
test('it serializes records', function (assert) {
let store = this.owner.lookup('service:store');
let record = store.createRecord('chat-participant', {});
let serializedRecord = record.serialize();
assert.ok(serializedRecord);
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -69,9 +69,6 @@ services:
MAIL_FROM_NAME: Fleetbase
APP_NAME: Fleetbase
LOG_CHANNEL: daily
MODEL_CACHE_ENABLED: true
RESPONSE_CACHE_ENABLED: true
RESPONSE_CACHE_DRIVER: redis
depends_on:
- database
- cache

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

17568
erd.svg

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 794 KiB

47
static-build.Dockerfile Normal file
View File

@@ -0,0 +1,47 @@
FROM --platform=linux/amd64 dunglas/frankenphp:static-builder
# # Install packages
# RUN apt-get update && apt-get install -y git bind9-utils mycli nodejs npm \
# && mkdir -p /root/.ssh \
# && ssh-keyscan github.com >> /root/.ssh/known_hosts
# Set some build ENV variables
ENV LOG_CHANNEL=stdout
ENV CACHE_DRIVER=null
ENV BROADCAST_DRIVER=socketcluster
ENV QUEUE_CONNECTION=redis
ENV CADDYFILE_PATH=/fleetbase/Caddyfile
ENV OCTANE_SERVER=frankenphp
# Set environment
ARG ENVIRONMENT=production
ENV APP_ENV=$ENVIRONMENT
# Copy Caddyfile
COPY ./Caddyfile $CADDYFILE_PATH
# Create /fleetbase directory and set correct permissions
RUN mkdir -p /fleetbase && mkdir -p /fleetbase/api && mkdir -p /fleetbase/console
# Set working directory
WORKDIR /fleetbase/api
# Setup api
COPY ./api /fleetbase/api
# Setup console
COPY ./console /fleetbase/console
# Set permissions for deploy script
RUN chmod +x /fleetbase/api/deploy.sh
# Pre-install Composer dependencies
# RUN /bin/sh -c "composer install --no-scripts --optimize-autoloader --no-dev"
# Dump autoload
# RUN /bin/sh -c "composer dumpautoload"
# Build binary
RUN EMBED=/ \
PHP_EXTENSIONS=pdo_mysql,gd,bcmath,redis,intl,zip,gmp,apcu,opcache,memcached,imagick,geos,sockets,pcntl \
./build-static.sh