mirror of
https://github.com/fleetbase/fleetbase.git
synced 2026-01-09 07:47:14 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0626bc0171 | ||
|
|
a8adf3fd84 | ||
|
|
7b8bc4a593 | ||
|
|
490f2f1b41 | ||
|
|
e1fc7850d3 | ||
|
|
cc278bf1bb | ||
|
|
af86aaba8b | ||
|
|
f35dcb1544 | ||
|
|
29c8f4340d | ||
|
|
1cb833e407 | ||
|
|
41bc6e39a7 | ||
|
|
5dbe2fb5bb | ||
|
|
313b5ea3ba | ||
|
|
698f5979b1 | ||
|
|
f6f6899650 | ||
|
|
83a7ab7338 | ||
|
|
acf7b209af | ||
|
|
5c048a8238 | ||
|
|
de00ad31db | ||
|
|
8fe52c6157 | ||
|
|
a371e055ca | ||
|
|
bbec73fcef | ||
|
|
838a829a11 | ||
|
|
dbb7bc793a | ||
|
|
f0fa867ef9 | ||
|
|
3cc64913ca | ||
|
|
d034c4ad03 | ||
|
|
b740cf035e | ||
|
|
cc42779efc | ||
|
|
4a5422e357 | ||
|
|
21a0808b99 | ||
|
|
f6cb850219 | ||
|
|
80707774ac | ||
|
|
96318bb909 | ||
|
|
2c10f3551e | ||
|
|
41a469c983 | ||
|
|
edf7efe167 | ||
|
|
d7a2dd474a | ||
|
|
2b0c6f793d | ||
|
|
1e331d70b1 |
@@ -9,10 +9,11 @@
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"fleetbase/core-api": "^1.5.29",
|
||||
"fleetbase/fleetops-api": "^0.5.21",
|
||||
"fleetbase/registry-bridge": "^0.0.18",
|
||||
"fleetbase/storefront-api": "^0.3.27",
|
||||
"appstract/laravel-opcache": "^4.0",
|
||||
"fleetbase/core-api": "^1.6.5",
|
||||
"fleetbase/fleetops-api": "^0.6.8",
|
||||
"fleetbase/registry-bridge": "^0.0.19",
|
||||
"fleetbase/storefront-api": "^0.3.31",
|
||||
"guzzlehttp/guzzle": "^7.0.1",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/octane": "^2.3",
|
||||
|
||||
1467
api/composer.lock
generated
1467
api/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ return [
|
||||
|
||||
'allowed_methods' => ['*'],
|
||||
|
||||
'allowed_origins' => array_filter(['http://localhost:4200', env('CONSOLE_HOST'), Utils::addWwwToUrl(env('CONSOLE_HOST'))]),
|
||||
'allowed_origins' => array_filter(['http://localhost:4200', env('CONSOLE_HOST'), Utils::addWwwToUrl(env('CONSOLE_HOST')), ...Utils::arrayFrom(env('FRONTEND_HOSTS', ''))]),
|
||||
|
||||
'allowed_origins_patterns' => [],
|
||||
|
||||
|
||||
30
api/config/opcache.php
Normal file
30
api/config/opcache.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'url' => env('OPCACHE_URL', config('app.url')),
|
||||
'prefix' => 'opcache-api',
|
||||
'verify' => true,
|
||||
'headers' => [],
|
||||
'directories' => [
|
||||
base_path('app'),
|
||||
base_path('bootstrap'),
|
||||
base_path('public'),
|
||||
base_path('resources'),
|
||||
base_path('routes'),
|
||||
base_path('storage'),
|
||||
base_path('vendor'),
|
||||
],
|
||||
'exclude' => [
|
||||
'test',
|
||||
'Test',
|
||||
'tests',
|
||||
'Tests',
|
||||
'stub',
|
||||
'Stub',
|
||||
'stubs',
|
||||
'Stubs',
|
||||
'dumper',
|
||||
'Dumper',
|
||||
'Autoload',
|
||||
],
|
||||
];
|
||||
@@ -26,10 +26,14 @@ php artisan schedule-monitor:sync
|
||||
|
||||
# Clear cache
|
||||
php artisan cache:clear
|
||||
php artisan route:clear
|
||||
|
||||
# Optimize
|
||||
# php artisan config:cache
|
||||
# php artisan route:cache
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
|
||||
# Initialize registry
|
||||
php artisan registry:init
|
||||
|
||||
# Restart octane
|
||||
# php artisan octane:reload
|
||||
|
||||
19
api/resources/lang/ar/auth.php
Normal file
19
api/resources/lang/ar/auth.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| أسطر لغة المصادقة
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| تحتوي الأسطر التالية على رسائل المصادقة التي نعرضها للمستخدم أثناء
|
||||
| عمليات تسجيل الدخول أو غيرها. يمكنك تعديل هذه الرسائل حسب متطلباتك.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => 'بيانات الاعتماد هذه غير متطابقة مع سجلاتنا.',
|
||||
'password' => 'كلمة المرور التي تم إدخالها غير صحيحة.',
|
||||
'throttle' => 'عدد كبير جداً من محاولات الدخول. يرجى المحاولة مرة أخرى خلال :seconds ثانية.',
|
||||
|
||||
];
|
||||
19
api/resources/lang/ar/pagination.php
Normal file
19
api/resources/lang/ar/pagination.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| أسطر لغة الترقيم الصفحي
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| تُستخدم الأسطر التالية من قبل مكتبة الترقيم الصفحي لبناء روابط
|
||||
| الترقيم البسيطة. يمكنك تعديلها كما تشاء لتخصيص العرض بما يناسب
|
||||
| تطبيقك بشكل أفضل.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« السابق',
|
||||
'next' => 'التالي »',
|
||||
|
||||
];
|
||||
21
api/resources/lang/ar/passwords.php
Normal file
21
api/resources/lang/ar/passwords.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| أسطر لغة إعادة تعيين كلمة المرور
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| الأسطر التالية هي الرسائل الافتراضية التي يقدمها نظام إعادة تعيين
|
||||
| كلمة المرور عند فشل المحاولة، مثل رمز التحقق غير صالح أو كلمة مرور جديدة غير صحيحة.
|
||||
|
|
||||
*/
|
||||
|
||||
'reset' => 'تم إعادة تعيين كلمة المرور الخاصة بك!',
|
||||
'sent' => 'لقد أرسلنا رابط إعادة تعيين كلمة المرور إلى بريدك الإلكتروني!',
|
||||
'throttled' => 'يرجى الانتظار قبل المحاولة مرة أخرى.',
|
||||
'token' => 'رمز إعادة تعيين كلمة المرور هذا غير صالح.',
|
||||
'user' => 'لا يمكننا العثور على مستخدم بهذا العنوان الإلكتروني.',
|
||||
|
||||
];
|
||||
168
api/resources/lang/ar/validation.php
Normal file
168
api/resources/lang/ar/validation.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => 'يجب قبول :attribute.',
|
||||
'accepted_if' => 'يجب قبول :attribute عندما يكون :other يساوي :value.',
|
||||
'active_url' => ':attribute ليس عنوان URL صالحًا.',
|
||||
'after' => 'يجب أن يكون :attribute تاريخًا بعد :date.',
|
||||
'after_or_equal' => 'يجب أن يكون :attribute تاريخًا بعد أو يساوي :date.',
|
||||
'alpha' => 'يجب أن يحتوي :attribute على أحرف فقط.',
|
||||
'alpha_dash' => 'يجب أن يحتوي :attribute على أحرف وأرقام وشرطات فقط.',
|
||||
'alpha_num' => 'يجب أن يحتوي :attribute على أحرف وأرقام فقط.',
|
||||
'array' => 'يجب أن يكون :attribute مصفوفة.',
|
||||
'before' => 'يجب أن يكون :attribute تاريخًا قبل :date.',
|
||||
'before_or_equal' => 'يجب أن يكون :attribute تاريخًا قبل أو يساوي :date.',
|
||||
'between' => [
|
||||
'numeric' => 'يجب أن يكون :attribute بين :min و :max.',
|
||||
'file' => 'يجب أن يكون :attribute بين :min و :max كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute بين :min و :max حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على عدد عناصر بين :min و :max.',
|
||||
],
|
||||
'boolean' => 'يجب أن يكون حقل :attribute صحيحًا أو خاطئًا.',
|
||||
'confirmed' => 'تأكيد :attribute غير متطابق.',
|
||||
'current_password' => 'كلمة المرور غير صحيحة.',
|
||||
'date' => ':attribute ليس تاريخًا صالحًا.',
|
||||
'date_equals' => 'يجب أن يكون :attribute تاريخًا يساوي :date.',
|
||||
'date_format' => 'لا يتطابق :attribute مع الصيغة :format.',
|
||||
'declined' => 'يجب رفض :attribute.',
|
||||
'declined_if' => 'يجب رفض :attribute عندما يكون :other يساوي :value.',
|
||||
'different' => 'يجب أن يكون :attribute و :other مختلفين.',
|
||||
'digits' => 'يجب أن يتكون :attribute من :digits أرقام.',
|
||||
'digits_between' => 'يجب أن يتكون :attribute من :min إلى :max أرقام.',
|
||||
'dimensions' => ':attribute يحتوي على أبعاد صورة غير صالحة.',
|
||||
'distinct' => 'حقل :attribute يحتوي على قيمة مكررة.',
|
||||
'email' => 'يجب أن يكون :attribute عنوان بريد إلكتروني صالحًا.',
|
||||
'ends_with' => 'يجب أن ينتهي :attribute بأحد القيم التالية: :values.',
|
||||
'enum' => ':attribute المحدد غير صالح.',
|
||||
'exists' => ':attribute المحدد غير صالح.',
|
||||
'file' => 'يجب أن يكون :attribute ملفًا.',
|
||||
'filled' => 'يجب أن يحتوي حقل :attribute على قيمة.',
|
||||
'gt' => [
|
||||
'numeric' => 'يجب أن يكون :attribute أكبر من :value.',
|
||||
'file' => 'يجب أن يكون :attribute أكبر من :value كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute أكبر من :value حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على أكثر من :value عنصر.',
|
||||
],
|
||||
'gte' => [
|
||||
'numeric' => 'يجب أن يكون :attribute أكبر من أو يساوي :value.',
|
||||
'file' => 'يجب أن يكون :attribute أكبر من أو يساوي :value كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute أكبر من أو يساوي :value حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على :value عنصر أو أكثر.',
|
||||
],
|
||||
'image' => 'يجب أن يكون :attribute صورة.',
|
||||
'in' => ':attribute المحدد غير صالح.',
|
||||
'in_array' => 'حقل :attribute غير موجود في :other.',
|
||||
'integer' => 'يجب أن يكون :attribute عددًا صحيحًا.',
|
||||
'ip' => 'يجب أن يكون :attribute عنوان IP صالحًا.',
|
||||
'ipv4' => 'يجب أن يكون :attribute عنوان IPv4 صالحًا.',
|
||||
'ipv6' => 'يجب أن يكون :attribute عنوان IPv6 صالحًا.',
|
||||
'json' => 'يجب أن يكون :attribute نصًا بصيغة JSON صالحة.',
|
||||
'lt' => [
|
||||
'numeric' => 'يجب أن يكون :attribute أقل من :value.',
|
||||
'file' => 'يجب أن يكون :attribute أقل من :value كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute أقل من :value حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على أقل من :value عنصر.',
|
||||
],
|
||||
'lte' => [
|
||||
'numeric' => 'يجب أن يكون :attribute أقل من أو يساوي :value.',
|
||||
'file' => 'يجب أن يكون :attribute أقل من أو يساوي :value كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute أقل من أو يساوي :value حرفًا.',
|
||||
'array' => 'يجب ألا يحتوي :attribute على أكثر من :value عنصر.',
|
||||
],
|
||||
'mac_address' => 'يجب أن يكون :attribute عنوان MAC صالحًا.',
|
||||
'max' => [
|
||||
'numeric' => 'يجب ألا يتجاوز :attribute :max.',
|
||||
'file' => 'يجب ألا يتجاوز :attribute :max كيلوبايت.',
|
||||
'string' => 'يجب ألا يتجاوز :attribute :max حرفًا.',
|
||||
'array' => 'يجب ألا يحتوي :attribute على أكثر من :max عنصر.',
|
||||
],
|
||||
'mimes' => 'يجب أن يكون :attribute ملفًا من النوع: :values.',
|
||||
'mimetypes' => 'يجب أن يكون :attribute ملفًا من النوع: :values.',
|
||||
'min' => [
|
||||
'numeric' => 'يجب أن يكون :attribute على الأقل :min.',
|
||||
'file' => 'يجب أن يكون :attribute على الأقل :min كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute على الأقل :min حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على الأقل على :min عنصر.',
|
||||
],
|
||||
'multiple_of' => 'يجب أن يكون :attribute مضاعفًا لـ :value.',
|
||||
'not_in' => ':attribute المحدد غير صالح.',
|
||||
'not_regex' => 'صيغة :attribute غير صالحة.',
|
||||
'numeric' => 'يجب أن يكون :attribute رقمًا.',
|
||||
'password' => 'كلمة المرور غير صحيحة.',
|
||||
'present' => 'يجب أن يكون حقل :attribute موجودًا.',
|
||||
'prohibited' => 'حقل :attribute محظور.',
|
||||
'prohibited_if' => 'حقل :attribute محظور عندما يكون :other يساوي :value.',
|
||||
'prohibited_unless' => 'حقل :attribute محظور إلا إذا كان :other ضمن :values.',
|
||||
'prohibits' => 'حقل :attribute يحظر وجود :other.',
|
||||
'regex' => 'صيغة :attribute غير صالحة.',
|
||||
'required' => 'حقل :attribute مطلوب.',
|
||||
'required_array_keys' => 'يجب أن يحتوي حقل :attribute على إدخالات لـ: :values.',
|
||||
'required_if' => 'حقل :attribute مطلوب عندما يكون :other يساوي :value.',
|
||||
'required_unless' => 'حقل :attribute مطلوب إلا إذا كان :other ضمن :values.',
|
||||
'required_with' => 'حقل :attribute مطلوب عند وجود :values.',
|
||||
'required_with_all' => 'حقل :attribute مطلوب عند وجود جميع القيم :values.',
|
||||
'required_without' => 'حقل :attribute مطلوب عند عدم وجود :values.',
|
||||
'required_without_all' => 'حقل :attribute مطلوب عند عدم وجود أي من القيم :values.',
|
||||
'same' => 'يجب أن يتطابق :attribute مع :other.',
|
||||
'size' => [
|
||||
'numeric' => 'يجب أن يكون :attribute مساويًا لـ :size.',
|
||||
'file' => 'يجب أن يكون :attribute مساويًا لـ :size كيلوبايت.',
|
||||
'string' => 'يجب أن يكون :attribute مساويًا لـ :size حرفًا.',
|
||||
'array' => 'يجب أن يحتوي :attribute على :size عنصر.',
|
||||
],
|
||||
'starts_with' => 'يجب أن يبدأ :attribute بأحد القيم التالية: :values.',
|
||||
'string' => 'يجب أن يكون :attribute نصًا.',
|
||||
'timezone' => 'يجب أن يكون :attribute منطقة زمنية صالحة.',
|
||||
'unique' => 'تم استخدام :attribute مسبقًا.',
|
||||
'uploaded' => 'فشل تحميل :attribute.',
|
||||
'url' => 'يجب أن يكون :attribute عنوان URL صالحًا.',
|
||||
'uuid' => 'يجب أن يكون :attribute UUID صالحًا.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'attribute-name' => [
|
||||
'rule-name' => 'رسالة مخصصة',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap our attribute placeholder
|
||||
| with something more reader friendly such as "E-Mail Address" instead
|
||||
| of "email". This simply helps us make our message more expressive.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
@@ -16,7 +16,7 @@
|
||||
{{/if}}
|
||||
</InputGroup>
|
||||
<InputGroup @wrapperClass="mb-0i">
|
||||
<Checkbox @label="APN Production" @value={{this.apn.production}} @onToggle={{fn (mut this.apn.production)}} @disabled={{this.isLoading}} />
|
||||
<Checkbox @label="APN Production" @value={{this.apn.production}} @onToggle={{this.toggleApnProduction}} />
|
||||
</InputGroup>
|
||||
</ContentPanel>
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@ export default class ConfigureNotificationChannelsComponent extends Component {
|
||||
this.loadConfigValues();
|
||||
}
|
||||
|
||||
@action toggleApnProduction(checked) {
|
||||
this.apn = {
|
||||
...this.apn,
|
||||
production: checked,
|
||||
};
|
||||
}
|
||||
|
||||
@action removeApnFile() {
|
||||
const apnConfig = this.apn;
|
||||
apnConfig.private_key_file = null;
|
||||
|
||||
@@ -2,27 +2,28 @@ import Controller from '@ember/controller';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import createNotificationKey from '../../../utils/create-notification-key';
|
||||
import createNotificationKey from '@fleetbase/ember-core/utils/create-notification-key';
|
||||
import { task } from 'ember-concurrency';
|
||||
|
||||
export default class ConsoleAdminNotificationsController extends Controller {
|
||||
export default class ConsoleSettingsNotificationsController extends Controller {
|
||||
/**
|
||||
* Inject the notifications service.
|
||||
*
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
@service notifications;
|
||||
|
||||
/**
|
||||
* Inject the fetch service.
|
||||
*
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
@service fetch;
|
||||
|
||||
/**
|
||||
* The notification settings value JSON.
|
||||
*
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
* @var {Object}
|
||||
*/
|
||||
@tracked notificationSettings = {};
|
||||
@@ -30,26 +31,18 @@ export default class ConsoleAdminNotificationsController extends Controller {
|
||||
/**
|
||||
* Notification transport methods enabled.
|
||||
*
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
* @var {Array}
|
||||
*/
|
||||
@tracked notificationTransportMethods = ['email', 'sms'];
|
||||
|
||||
/**
|
||||
* Tracked property for the loading state
|
||||
*
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @var {Boolean}
|
||||
*/
|
||||
@tracked isLoading = false;
|
||||
|
||||
/**
|
||||
* Creates an instance of ConsoleAdminNotificationsController.
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* Creates an instance of ConsoleSettingsNotificationsController.
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.getSettings();
|
||||
this.getSettings.perform();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +50,7 @@ export default class ConsoleAdminNotificationsController extends Controller {
|
||||
*
|
||||
* @param {Object} notification
|
||||
* @param {Array} notifiables
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
@action onSelectNotifiable(notification, notifiables) {
|
||||
const notificationKey = createNotificationKey(notification.definition, notification.name);
|
||||
@@ -83,7 +76,7 @@ export default class ConsoleAdminNotificationsController extends Controller {
|
||||
* Mutates the notification settings property.
|
||||
*
|
||||
* @param {Object} [_notificationSettings={}]
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
mutateNotificationSettings(_notificationSettings = {}) {
|
||||
this.notificationSettings = {
|
||||
@@ -93,44 +86,32 @@ export default class ConsoleAdminNotificationsController extends Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save notification settings to the server.
|
||||
* Save notification settings.
|
||||
*
|
||||
* @action
|
||||
* @method saveSettings
|
||||
* @returns {Promise}
|
||||
* @memberof ConsoleAdminNotificationsController
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
@action saveSettings() {
|
||||
@task *saveSettings() {
|
||||
const { notificationSettings } = this;
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
return this.fetch
|
||||
.post('notifications/save-settings', { notificationSettings })
|
||||
.then(() => {
|
||||
this.notifications.success('Notification settings successfully saved.');
|
||||
})
|
||||
.catch((error) => {
|
||||
this.notifications.serverError(error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
try {
|
||||
yield this.fetch.post('notifications/save-settings', { notificationSettings });
|
||||
this.notifications.success('Notification settings successfully saved.');
|
||||
} catch (error) {
|
||||
this.notifications.serverError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches and updates notification settings asynchronously.
|
||||
* Get notification settings.
|
||||
*
|
||||
* @returns {Promise<void>} A promise for successful retrieval and update, or an error on failure.
|
||||
* @memberof ConsoleSettingsNotificationsController
|
||||
*/
|
||||
getSettings() {
|
||||
return this.fetch
|
||||
.get('notifications/get-settings')
|
||||
.then(({ notificationSettings }) => {
|
||||
this.notificationSettings = notificationSettings;
|
||||
})
|
||||
.catch((error) => {
|
||||
this.notifications.serverError(error);
|
||||
});
|
||||
@task *getSettings() {
|
||||
try {
|
||||
const { notificationSettings } = yield this.fetch.get('notifications/get-settings');
|
||||
this.notificationSettings = notificationSettings;
|
||||
} catch (error) {
|
||||
this.notifications.serverError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { helper } from '@ember/component/helper';
|
||||
import createNotificationKey from '../utils/create-notification-key';
|
||||
|
||||
export default helper(function getNotificationKey([definition, name]) {
|
||||
return createNotificationKey(definition, name);
|
||||
});
|
||||
@@ -22,7 +22,12 @@
|
||||
</head>
|
||||
<body>
|
||||
{{content-for "body"}}
|
||||
|
||||
<div id="boot-loader" class="overloader">
|
||||
<div class="loader-container">
|
||||
<span class="fleetbase-loader" width="16" height="16"></span>
|
||||
<div class="loading-message">Starting up...</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{rootURL}}assets/vendor.js"></script>
|
||||
<script src="{{rootURL}}assets/@fleetbase/console.js"></script>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import isElectron from '@fleetbase/ember-core/utils/is-electron';
|
||||
import pathToRoute from '@fleetbase/ember-core/utils/path-to-route';
|
||||
import removeBootLoader from '../utils/remove-boot-loader';
|
||||
|
||||
export default class ApplicationRoute extends Route {
|
||||
@service session;
|
||||
@@ -88,6 +89,17 @@ export default class ApplicationRoute extends Route {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove boot loader if not authenticated.
|
||||
*
|
||||
* @memberof ApplicationRoute
|
||||
*/
|
||||
afterModel() {
|
||||
if (!this.session.isAuthenticated) {
|
||||
removeBootLoader();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the application's theme settings, applying necessary class names and default theme configurations.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import removeBootLoader from '../utils/remove-boot-loader';
|
||||
import '@fleetbase/leaflet-routing-machine';
|
||||
|
||||
export default class ConsoleRoute extends Route {
|
||||
@@ -37,6 +38,10 @@ export default class ConsoleRoute extends Route {
|
||||
*/
|
||||
async afterModel(model, transition) {
|
||||
this.universe.callHooks('console:after-model', this.session, this.router, model, transition);
|
||||
removeBootLoader();
|
||||
|
||||
// Reboot extensions
|
||||
this.universe.bootEngines();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import groupBy from '@fleetbase/ember-core/utils/group-by';
|
||||
|
||||
export default class ConsoleAdminNotificationsRoute extends Route {
|
||||
export default class ConsoleSettingsNotificationsRoute extends Route {
|
||||
@service fetch;
|
||||
|
||||
model() {
|
||||
@@ -14,6 +14,8 @@ export default class ConsoleAdminNotificationsRoute extends Route {
|
||||
}
|
||||
|
||||
setupController(controller, { registry, notifiables }) {
|
||||
super.setupController(...arguments);
|
||||
|
||||
controller.groupedNotifications = groupBy(registry, 'package');
|
||||
controller.notifiables = notifiables;
|
||||
}
|
||||
@@ -38,3 +38,32 @@ body[data-theme='dark'] .two-fa-enforcement-alert button#two-fa-setup-button.btn
|
||||
body.console-admin-organizations-index-index .next-table-wrapper > table {
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
#boot-loader {
|
||||
position: absolute;
|
||||
z-index: 9999999999;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#boot-loader > .loader-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#boot-loader > .loader-container > .loading-message {
|
||||
margin-left: 0.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
body[data-theme='dark'] #boot-loader > .loader-container > .loading-message {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<Layout::Sidebar::Item @route="console.admin.index" @icon="rectangle-list">{{t "common.overview"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.organizations" @icon="building">{{t "common.organizations"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.branding" @icon="palette">{{t "common.branding"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.notifications" @icon="bell">{{t "common.notifications"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.two-fa-settings" @icon="shield-halved">{{t "common.2fa-config"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.admin.schedule-monitor" @icon="calendar-check">{{t "console.admin.schedule-monitor.schedule-monitor"}}</Layout::Sidebar::Item>
|
||||
{{#each this.universe.adminMenuItems as |menuItem|}}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<Layout::Sidebar::Panel @open={{true}} @title={{t "common.settings"}}>
|
||||
<Layout::Sidebar::Item @route="console.settings.index" @icon="cog">{{t "common.organization"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.settings.two-fa" @icon="shield-halved">{{t "common.two-factor"}}</Layout::Sidebar::Item>
|
||||
<Layout::Sidebar::Item @route="console.settings.notifications" @icon="bell">{{t "common.notifications"}}</Layout::Sidebar::Item>
|
||||
{{#each this.universe.settingsMenuItems as |menuItem|}}
|
||||
<Layout::Sidebar::Item
|
||||
@onClick={{fn this.universe.transitionMenuItem "console.settings.virtual" menuItem}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{page-title "Push Notifications"}}
|
||||
<Layout::Section::Header @title={{t "console.admin.notifications.title"}}>
|
||||
<Button @type="primary" @size="sm" @icon="save" @text={{t "common.save-button-text"}} @onClick={{this.saveSettings}} @disabled={{this.isLoading}} @isLoading={{this.isLoading}} />
|
||||
{{page-title "Notifications"}}
|
||||
<Layout::Section::Header @title={{t "common.notifications"}}>
|
||||
<Button @type="primary" @size="sm" @icon="save" @text={{t "common.save-button-text"}} @onClick={{perform this.saveSettings}} @disabled={{this.saveSettings.isRunning}} @isLoading={{or this.saveSettings.isRunning this.getSettings.isRunning}} />
|
||||
</Layout::Section::Header>
|
||||
|
||||
<Layout::Section::Body class="overflow-y-scroll h-full">
|
||||
@@ -1,9 +1,11 @@
|
||||
<div class="bg-white dark:bg-gray-800 py-5 px-4 shadow rounded-lg w-full">
|
||||
<div class="mb-4">
|
||||
<Image src={{@model.logo_url}} @fallbackSrc="/images/fleetbase-logo-svg.svg" alt={{t "app.name"}} width="160" height="56" class="w-40 h-14 mx-auto" />
|
||||
<h2 class="text-center text-lg font-extrabold text-gray-900 dark:text-white truncate">
|
||||
{{t "onboard.index.title"}}
|
||||
</h2>
|
||||
<Image src={{@model.logo_url}} @fallbackSrc="/images/fleetbase-logo-svg.svg" alt={{t "app.name"}} height="56" class="h-10 object-contain mx-auto" />
|
||||
<div class="mt-2">
|
||||
<h2 class="text-center text-lg font-extrabold text-gray-900 dark:text-white truncate">
|
||||
{{t "onboard.index.title"}}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex px-3 py-2 mb-4 rounded-md shadow-sm bg-blue-200">
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { camelize } from '@ember/string';
|
||||
|
||||
export default function createNotificationKey(definition, name) {
|
||||
const withoutSlashes = definition.replace(/[\W_]+/g, '');
|
||||
const key = `${camelize(withoutSlashes)}__${camelize(name)}`;
|
||||
|
||||
return key;
|
||||
}
|
||||
@@ -19,6 +19,8 @@ export default function getPermissionAction(permissionName) {
|
||||
'notify',
|
||||
'assign_vehicle',
|
||||
'assign_order_to',
|
||||
'assign_driver_to',
|
||||
'assign_vehicle_to',
|
||||
'dispatch_order_to',
|
||||
'dispatch',
|
||||
'assign',
|
||||
|
||||
6
console/app/utils/remove-boot-loader.js
Normal file
6
console/app/utils/remove-boot-loader.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default function removeBootLoader() {
|
||||
const bootLoaderElement = document.getElementById('boot-loader');
|
||||
if (bootLoaderElement && typeof bootLoaderElement.remove === 'function') {
|
||||
bootLoaderElement.remove();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fleetbase/console",
|
||||
"version": "0.5.27",
|
||||
"version": "0.7.0",
|
||||
"private": true,
|
||||
"description": "Modular logistics and supply chain operating system (LSOS)",
|
||||
"repository": "https://github.com/fleetbase/fleetbase",
|
||||
@@ -29,18 +29,18 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/legacy-built-in-components": "^0.4.2",
|
||||
"@fleetbase/dev-engine": "^0.2.9",
|
||||
"@fleetbase/ember-core": "latest",
|
||||
"@fleetbase/ember-ui": "latest",
|
||||
"@fleetbase/fleetops-data": "latest",
|
||||
"@fleetbase/fleetops-engine": "^0.5.21",
|
||||
"@fleetbase/fleetops-engine": "^0.6.8",
|
||||
"@fleetbase/iam-engine": "^0.1.3",
|
||||
"@fleetbase/dev-engine": "^0.2.9",
|
||||
"@fleetbase/registry-bridge-engine": "^0.0.19",
|
||||
"@fleetbase/storefront-engine": "^0.3.31",
|
||||
"@fleetbase/leaflet-routing-machine": "^3.2.16",
|
||||
"@fleetbase/registry-bridge-engine": "^0.0.18",
|
||||
"@fleetbase/storefront-engine": "^0.3.27",
|
||||
"@fortawesome/ember-fontawesome": "^2.0.0",
|
||||
"ember-changeset": "^4.1.2",
|
||||
"ember-changeset-validations": "^4.1.1",
|
||||
"ember-changeset": "4.1.2",
|
||||
"ember-changeset-validations": "4.1.2",
|
||||
"ember-composable-helpers": "^5.0.0",
|
||||
"ember-concurrency": "^3.1.1",
|
||||
"ember-concurrency-decorators": "^2.0.3",
|
||||
@@ -56,6 +56,7 @@
|
||||
"postcss-nth-list": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@embroider/macros": "1.16.12",
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/eslint-parser": "^7.25.1",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||
@@ -127,7 +128,7 @@
|
||||
"stylelint-prettier": "^4.1.0",
|
||||
"tailwindcss": "^3.4.10",
|
||||
"tracked-built-ins": "^3.3.0",
|
||||
"webpack": "^5.94.0"
|
||||
"webpack": "^5.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
|
||||
4729
console/pnpm-lock.yaml
generated
4729
console/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ Router.map(function () {
|
||||
this.route('settings', function () {
|
||||
this.route('virtual', { path: '/:slug' });
|
||||
this.route('two-fa');
|
||||
this.route('notifications');
|
||||
});
|
||||
this.route('virtual', { path: '/:slug' });
|
||||
this.route('admin', function () {
|
||||
@@ -49,7 +50,6 @@ Router.map(function () {
|
||||
this.route('socket');
|
||||
});
|
||||
this.route('branding');
|
||||
this.route('notifications');
|
||||
this.route('two-fa-settings');
|
||||
this.route('virtual', { path: '/:slug' });
|
||||
this.route('organizations', function () {
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
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 | Helper | get-notification-key', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it renders', async function (assert) {
|
||||
this.set('inputValue', '1234');
|
||||
|
||||
await render(hbs`{{get-notification-key this.inputValue}}`);
|
||||
|
||||
assert.dom(this.element).hasText('1234');
|
||||
});
|
||||
});
|
||||
@@ -1,12 +1,12 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from '@fleetbase/console/tests/helpers';
|
||||
|
||||
module('Unit | Controller | console/admin/notifications', function (hooks) {
|
||||
module('Unit | Controller | console/settings/notifications', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it exists', function (assert) {
|
||||
let controller = this.owner.lookup('controller:console/admin/notifications');
|
||||
let controller = this.owner.lookup('controller:console/settings/notifications');
|
||||
assert.ok(controller);
|
||||
});
|
||||
});
|
||||
@@ -1,11 +1,11 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from '@fleetbase/console/tests/helpers';
|
||||
|
||||
module('Unit | Route | console/admin/notifications', function (hooks) {
|
||||
module('Unit | Route | console/settings/notifications', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it exists', function (assert) {
|
||||
let route = this.owner.lookup('route:console/admin/notifications');
|
||||
let route = this.owner.lookup('route:console/settings/notifications');
|
||||
assert.ok(route);
|
||||
});
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import createNotificationKey from '@fleetbase/console/utils/create-notification-key';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Utility | create-notification-key', function () {
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it works', function (assert) {
|
||||
let result = createNotificationKey();
|
||||
assert.ok(result);
|
||||
});
|
||||
});
|
||||
10
console/tests/unit/utils/remove-boot-loader-test.js
Normal file
10
console/tests/unit/utils/remove-boot-loader-test.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import removeBootLoader from '@fleetbase/console/utils/remove-boot-loader';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Utility | remove-boot-loader', function () {
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it works', function (assert) {
|
||||
let result = removeBootLoader();
|
||||
assert.ok(result);
|
||||
});
|
||||
});
|
||||
365
console/translations/bg-bg.yaml
Normal file
365
console/translations/bg-bg.yaml
Normal file
@@ -0,0 +1,365 @@
|
||||
app:
|
||||
name: Fleetbase
|
||||
terms:
|
||||
new: Ново
|
||||
sort: Сортиране
|
||||
filter: Филтър
|
||||
columns: Колони
|
||||
settings: Настройки
|
||||
home: Начало
|
||||
admin: Админ
|
||||
logout: Изход
|
||||
dashboard: Табло
|
||||
search: Търсене
|
||||
search-input: Поле за търсене
|
||||
common:
|
||||
confirm: Потвърждение
|
||||
edit: Редактиране
|
||||
save: Запазване
|
||||
save-changes: Запази промените
|
||||
cancel: Отказ
|
||||
2fa-config: 2FA Конфигурация
|
||||
account: Акаунт
|
||||
admin: Админ
|
||||
branding: Брандиране
|
||||
columns: Колони
|
||||
dashboard: Табло
|
||||
date-of-birth: Дата на раждане
|
||||
delete: Изтрий
|
||||
email: Имейл
|
||||
filesystem: Файлова система
|
||||
filter: Филтър
|
||||
home: Начало
|
||||
logout: Изход
|
||||
mail: Поща
|
||||
name: Име
|
||||
new: Ново
|
||||
notification-channels: Канали за известия
|
||||
notifications: Известия
|
||||
organization: Организация
|
||||
organizations: Организации
|
||||
overview: Общ преглед
|
||||
phone: Вашият телефонен номер
|
||||
profile: Профил
|
||||
queue: Опашка
|
||||
save-button-text: Запази промените
|
||||
search-input: Поле за търсене
|
||||
search: Търсене
|
||||
services: Услуги
|
||||
settings: Настройки
|
||||
socket: Сокет
|
||||
sort: Сортиране
|
||||
two-factor: Двуфакторно
|
||||
uploading: Качване...
|
||||
your-profile: Вашият профил
|
||||
created-at: Създаден на
|
||||
country: Държава
|
||||
phone-number: Телефон
|
||||
status: Статус
|
||||
close-and-save: Затвори и запази
|
||||
users: Потребители
|
||||
changelog: Дневник на промените
|
||||
ok: ОК
|
||||
select-file: Избери файл
|
||||
back: Назад
|
||||
next: Напред
|
||||
continue: Продължи
|
||||
done: Готово
|
||||
export: Експорт
|
||||
reload: Презареди
|
||||
reload-data: Презареди данните
|
||||
unauthorized: Неразрешено
|
||||
unauthorized-to: Нямате разрешение за
|
||||
unauthorized-access: Неразрешен достъп
|
||||
unauthorized-access-message: Неразрешен достъп, трябва да заявите необходимите разрешения.
|
||||
permissions-required-for-changes: Нямате нужните разрешения, за да направите промени.
|
||||
push-notifications: Push известия
|
||||
role: Роля
|
||||
component:
|
||||
file:
|
||||
dropdown-label: Действия с файла
|
||||
import-modal:
|
||||
loading-message: Обработване на импорта...
|
||||
drop-upload: Пуснете, за да качите
|
||||
invalid: Невалидно
|
||||
ready-upload: готово за качване.
|
||||
upload-spreadsheets: Качване на електронни таблици
|
||||
drag-drop: Плъзнете и пуснете файлове с електронни таблици върху тази зона
|
||||
button-text: или изберете електронни таблици за качване
|
||||
spreadsheets: електронни таблици
|
||||
upload-queue: Опашка за качване
|
||||
dropzone:
|
||||
file: файл
|
||||
drop-to-upload: Пуснете, за да качите
|
||||
invalid: Невалидно
|
||||
files-ready-for-upload: >-
|
||||
{numOfFiles} готови за качване.
|
||||
upload-images-videos: Качване на изображения и видеа
|
||||
upload-documents: Качване на документи
|
||||
upload-documents-files: Качване на документи и файлове
|
||||
upload-avatar-files: Качване на персонализирани аватари
|
||||
dropzone-supported-images-videos: Плъзнете и пуснете изображения или видео файлове в тази зона
|
||||
dropzone-supported-avatars: Плъзнете и пуснете SVG или PNG файлове
|
||||
dropzone-supported-files: Плъзнете и пуснете файлове в тази зона
|
||||
or-select-button-text: или изберете файлове за качване.
|
||||
upload-queue: Опашка за качване
|
||||
uploading: Качване...
|
||||
two-fa-enforcement-alert:
|
||||
message: За да подобрите сигурността на акаунта си, организацията ви изисква двуфакторно удостоверяване (2FA). Активирайте 2FA в настройките на акаунта си за допълнителен слой защита.
|
||||
button-text: Настройте 2FA
|
||||
comment-thread:
|
||||
publish-comment-button-text: Публикувай коментар
|
||||
publish-reply-button-text: Публикувай отговор
|
||||
reply-comment-button-text: Отговори
|
||||
edit-comment-button-text: Редактирай
|
||||
delete-comment-button-text: Изтрий
|
||||
comment-published-ago: >-
|
||||
Преди {createdAgo}
|
||||
comment-input-placeholder: Напишете нов коментар...
|
||||
comment-reply-placeholder: Напишете вашия отговор...
|
||||
comment-input-empty-notification: Не можете да публикувате празен коментар...
|
||||
comment-min-length-notification: Коментарът трябва да е поне 2 символа
|
||||
dashboard:
|
||||
select-dashboard: Изберете табло
|
||||
create-new-dashboard: Създайте ново табло
|
||||
create-a-new-dashboard: Създайте ново табло
|
||||
confirm-create-dashboard: Създаване на табло!
|
||||
edit-layout: Редактиране на подредбата
|
||||
add-widgets: Добавяне на джаджи
|
||||
delete-dashboard: Изтрийте таблото
|
||||
save-dashboard: Запазете таблото
|
||||
you-cannot-delete-this-dashboard: Не можете да изтриете това табло.
|
||||
are-you-sure-you-want-delete-dashboard: Сигурни ли сте, че искате да изтриете {dashboardName}?
|
||||
dashboard-widget-panel:
|
||||
widget-name: >-
|
||||
Джаджа {widgetName}
|
||||
select-widgets: Изберете джаджи
|
||||
close-and-save: Затвори и запази
|
||||
services:
|
||||
dashboard-service:
|
||||
create-dashboard-success-notification: Ново табло `{dashboardName}` е създадено успешно.
|
||||
delete-dashboard-success-notification: Таблото `{dashboardName}` беше изтрито.
|
||||
auth:
|
||||
verification:
|
||||
header-title: Верификация на акаунта
|
||||
title: Потвърдете своя имейл адрес
|
||||
message-text: <strong>Почти готово!</strong><br> Проверете имейла си за код за потвърждение.
|
||||
verification-code-text: Въведете кода за потвърждение, който сте получили по имейл.
|
||||
verification-input-label: Код за потвърждение
|
||||
verify-button-text: Потвърдете и продължете
|
||||
didnt-receive-a-code: Все още не сте получили код?
|
||||
not-sent:
|
||||
message: Все още не сте получили код?
|
||||
alternative-choice: Използвайте алтернативните опции по-долу, за да потвърдите акаунта си.
|
||||
resend-email: Изпратете имейл отново
|
||||
send-by-sms: Изпратете по SMS
|
||||
two-fa:
|
||||
verify-code:
|
||||
verification-code: Код за потвърждение
|
||||
check-title: Проверете своя имейл или телефон
|
||||
check-subtitle: Изпратихме ви код за потвърждение. Въведете го по-долу, за да завършите процеса на вход.
|
||||
expired-help-text: Вашият 2FA код е изтекъл. Можете да заявите нов код, ако ви е нужно още време.
|
||||
resend-code: Изпрати кода отново
|
||||
verify-code: Потвърдете кода
|
||||
cancel-two-factor: Откажи двуфакторното удостоверяване
|
||||
invalid-session-error-notification: Невалидна сесия. Моля, опитайте отново.
|
||||
verification-successful-notification: Успешна верификация!
|
||||
verification-code-expired-notification: Кодът за потвърждение е изтекъл. Моля, заявете нов.
|
||||
verification-code-failed-notification: Верификацията не беше успешна. Моля, опитайте отново.
|
||||
resend-code:
|
||||
verification-code-resent-notification: Изпратен е нов код за потвърждение.
|
||||
verification-code-resent-error-notification: Възникна грешка при повторното изпращане на кода. Моля, опитайте отново.
|
||||
forgot-password:
|
||||
success-message: Проверете имейла си, за да продължите!
|
||||
is-sent:
|
||||
title: Почти готово!
|
||||
message: <strong>Проверете имейла си!</strong><br> Изпратихме ви магически линк, който ще ви позволи да нулирате паролата си. Линкът изтича след 15 минути.
|
||||
not-sent:
|
||||
title: Забравена парола?
|
||||
message: <strong>Не се притеснявайте, ние ще помогнем.</strong><br> Въведете имейла, който използвате за вход в {appName}, и ще ви изпратим сигурен линк за нулиране на паролата.
|
||||
form:
|
||||
email-label: Вашият имейл адрес
|
||||
submit-button: Добре, изпратете ми магически линк!
|
||||
nevermind-button: Отказ
|
||||
login:
|
||||
title: Влезте в акаунта си
|
||||
no-identity-notification: Пропуснахте ли да въведете своя имейл?
|
||||
no-password-notification: Пропуснахте ли да въведете своята парола?
|
||||
unverified-notification: Акаунтът ви трябва да бъде потвърден, за да продължите.
|
||||
password-reset-required: Необходимо е нулиране на паролата, за да продължите.
|
||||
failed-attempt:
|
||||
message: <strong>Забравихте паролата си?</strong><br> Кликнете върху бутона по-долу, за да я нулирате.
|
||||
button-text: Добре, помогнете ми!
|
||||
form:
|
||||
email-label: Имейл адрес
|
||||
password-label: Парола
|
||||
remember-me-label: Запомни ме
|
||||
forgot-password-label: Забравена парола?
|
||||
sign-in-button: Вход
|
||||
create-account-button: Създаване на нов акаунт
|
||||
slow-connection-message: Забавена връзка.
|
||||
reset-password:
|
||||
success-message: Паролата ви е нулирана! Влезте, за да продължите.
|
||||
invalid-verification-code: Тази връзка за нулиране на паролата е невалидна или е изтекла.
|
||||
title: Нулирайте паролата си
|
||||
form:
|
||||
code:
|
||||
label: Вашият код за нулиране
|
||||
help-text: Кодът за потвърждение, който получихте по имейл.
|
||||
password:
|
||||
label: Нова парола
|
||||
help-text: Въведете парола от поне 6 символа, за да продължите.
|
||||
confirm-password:
|
||||
label: Потвърдете новата парола
|
||||
help-text: Въведете парола от поне 6 символа, за да продължите.
|
||||
submit-button: Нулирай паролата
|
||||
back-button: Назад
|
||||
console:
|
||||
create-or-join-organization:
|
||||
modal-title: Създаване или присъединяване към организация
|
||||
join-success-notification: Присъединихте се към нова организация!
|
||||
create-success-notification: Създадохте нова организация!
|
||||
switch-organization:
|
||||
modal-title: Сигурни ли сте, че искате да превключите към организацията {organizationName}?
|
||||
modal-body: При потвърждение акаунтът ви ще остане вписан, но основната ви организация ще бъде сменена.
|
||||
modal-accept-button-text: Да, искам да превключа
|
||||
success-notification: Превключихте организацията
|
||||
account:
|
||||
index:
|
||||
upload-new: Качете нов
|
||||
phone: Вашият телефонен номер.
|
||||
photos: снимки
|
||||
admin:
|
||||
schedule-monitor:
|
||||
schedule-monitor: Монитор на графика
|
||||
task-logs-for: >-
|
||||
Логове на задачите за:
|
||||
showing-last-count: Показване на последните {count} записа
|
||||
name: Име
|
||||
type: Тип
|
||||
timezone: Часова зона
|
||||
last-started: Последно стартиране
|
||||
last-finished: Последно приключване
|
||||
last-failure: Последна грешка
|
||||
date: Дата
|
||||
memory: Памет
|
||||
runtime: Времетраене
|
||||
output: Резултат
|
||||
no-output: Няма резултат
|
||||
config:
|
||||
database:
|
||||
title: Конфигурация на базата данни
|
||||
filesystem:
|
||||
title: Конфигурация на файловата система
|
||||
mail:
|
||||
title: Конфигурация на пощата
|
||||
notification-channels:
|
||||
title: Конфигурация на Push известия
|
||||
queue:
|
||||
title: Конфигурация на опашката
|
||||
services:
|
||||
title: Конфигурация на услугите
|
||||
socket:
|
||||
title: Конфигурация на сокета
|
||||
branding:
|
||||
title: Брандиране
|
||||
icon-text: Икона
|
||||
upload-new: Качете нов
|
||||
reset-default: Възстанови по подразбиране
|
||||
logo-text: Лого
|
||||
theme: Основна тема
|
||||
index:
|
||||
total-users: Общо потребители
|
||||
total-organizations: Общо организации
|
||||
total-transactions: Общо транзакции
|
||||
notifications:
|
||||
title: Известия
|
||||
notification-settings: Настройки за известия
|
||||
organizations:
|
||||
index:
|
||||
title: Организации
|
||||
owner-name-column: Собственик
|
||||
owner-phone-column: Телефон на собственика
|
||||
owner-email-column: Имейл на собственика
|
||||
users-count-column: Потребители
|
||||
phone-column: Телефон
|
||||
email-column: Имейл
|
||||
users:
|
||||
title: Потребители
|
||||
settings:
|
||||
index:
|
||||
title: Настройки на организацията
|
||||
organization-name: Име на организацията
|
||||
organization-description: Описание на организацията
|
||||
organization-phone: Телефонен номер на организацията
|
||||
organization-currency: Валута на организацията
|
||||
organization-id: Идентификатор на организацията
|
||||
organization-branding: Брандиране на организацията
|
||||
logo: Лого
|
||||
logo-help-text: Лого на вашата организация.
|
||||
upload-new-logo: Качете ново лого
|
||||
backdrop: Фон
|
||||
backdrop-help-text: По желание можете да зададете банер или фонова картинка за организацията.
|
||||
upload-new-backdrop: Качете нов фон
|
||||
extensions:
|
||||
title: Разширенията идват скоро!
|
||||
message: Моля, проверете отново в следващите версии, докато подготвяме хранилище и пазар за разширения.
|
||||
notifications:
|
||||
select-all: Избери всички
|
||||
mark-as-read: Маркирай като прочетени
|
||||
received: >-
|
||||
Получено:
|
||||
message: Няма известия за показване.
|
||||
invite:
|
||||
for-users:
|
||||
invitation-message: Поканени сте да се присъедините към {companyName}
|
||||
invitation-sent-message: Поканени сте да се присъедините към организацията {companyName} в {appName}. За да приемете тази покана, въведете кода за покана, който сте получили по имейл, и натиснете Продължи.
|
||||
invitation-code-sent-text: Вашият код за покана
|
||||
accept-invitation-text: Приемете поканата
|
||||
onboard:
|
||||
index:
|
||||
title: Създайте своя акаунт
|
||||
welcome-title: <strong>Добре дошли в {companyName}!</strong><br />
|
||||
welcome-text: Попълнете изискваните данни по-долу, за да започнете.
|
||||
full-name: Пълно име
|
||||
full-name-help-text: Вашето пълно име
|
||||
your-email: Имейл адрес
|
||||
your-email-help-text: Вашият имейл адрес
|
||||
phone: Телефонен номер
|
||||
phone-help-text: Вашият телефонен номер
|
||||
organization-name: Име на организацията
|
||||
organization-help-text: Името на вашата организация; всички услуги и ресурси ще се управляват под тази организация. По-късно можете да създавате колкото организации желаете.
|
||||
password: Въведете парола
|
||||
password-help-text: Вашата парола; уверете се, че е достатъчно сигурна.
|
||||
confirm-password: Потвърдете паролата
|
||||
confirm-password-help-text: Просто за да я потвърдите, въведете я отново.
|
||||
continue-button-text: Продължи
|
||||
verify-email:
|
||||
header-title: Верификация на акаунта
|
||||
title: Потвърдете своя имейл адрес
|
||||
message-text: <strong>Почти готово!</strong><br> Проверете имейла си за код за потвърждение.
|
||||
verification-code-text: Въведете кода за потвърждение, който сте получили по имейл.
|
||||
verification-input-label: Код за потвърждение
|
||||
verify-button-text: Потвърдете и продължете
|
||||
didnt-receive-a-code: Все още не сте получили код?
|
||||
not-sent:
|
||||
message: Все още не сте получили код?
|
||||
alternative-choice: Използвайте алтернативните опции по-долу, за да потвърдите акаунта си.
|
||||
resend-email: Изпратете имейл отново
|
||||
send-by-sms: Изпратете по SMS
|
||||
install:
|
||||
installer-header: Инсталатор
|
||||
failed-message-sent: Инсталацията не беше успешна! Кликнете бутона по-долу, за да опитате отново.
|
||||
retry-install: Опитайте да инсталирате отново
|
||||
start-install: Стартиране на инсталацията
|
||||
layout:
|
||||
header:
|
||||
menus:
|
||||
organization:
|
||||
settings: Настройки на организацията
|
||||
create-or-join: Създаване или присъединяване към организации
|
||||
explore-extensions: Разгледайте разширенията
|
||||
user:
|
||||
view-profile: Преглед на профила
|
||||
keyboard-shortcuts: Покажи клавишните комбинации
|
||||
changelog: Дневник на промените
|
||||
@@ -1,6 +1,11 @@
|
||||
services:
|
||||
cache:
|
||||
image: redis:4-alpine
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
database:
|
||||
image: mysql:8.0-oracle
|
||||
@@ -12,6 +17,11 @@ services:
|
||||
environment:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: "fleetbase"
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
socket:
|
||||
image: socketcluster/socketcluster:v17.4.0
|
||||
@@ -28,6 +38,11 @@ services:
|
||||
target: events-dev
|
||||
args:
|
||||
ENVIRONMENT: development
|
||||
healthcheck:
|
||||
test: ["CMD", "php", "artisan", "queue:status"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
environment:
|
||||
DATABASE_URL: "mysql://root@database/fleetbase"
|
||||
QUEUE_CONNECTION: redis
|
||||
@@ -44,8 +59,6 @@ services:
|
||||
ENVIRONMENT: development
|
||||
ports:
|
||||
- "4200:4200"
|
||||
volumes:
|
||||
- console-build:/console
|
||||
|
||||
application:
|
||||
build:
|
||||
@@ -54,9 +67,6 @@ services:
|
||||
target: app-dev
|
||||
args:
|
||||
ENVIRONMENT: development
|
||||
GITHUB_AUTH_KEY: ${GITHUB_AUTH_KEY}
|
||||
volumes:
|
||||
- console-build:/fleetbase/console
|
||||
environment:
|
||||
ENVIRONMENT: development
|
||||
DATABASE_URL: "mysql://root@database/fleetbase"
|
||||
@@ -85,7 +95,4 @@ services:
|
||||
ports:
|
||||
- "8000:80"
|
||||
depends_on:
|
||||
- application
|
||||
|
||||
volumes:
|
||||
console-build:
|
||||
- application
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.2
|
||||
# Base stage
|
||||
FROM dunglas/frankenphp:1.2.3-php8.2-bookworm as base
|
||||
FROM dunglas/frankenphp:1.5.0-php8.2-bookworm AS base
|
||||
|
||||
# Install packages
|
||||
RUN apt-get update && apt-get install -y git bind9-utils mycli nodejs npm nano \
|
||||
@@ -20,11 +20,35 @@ RUN install-php-extensions \
|
||||
opcache \
|
||||
memcached \
|
||||
imagick \
|
||||
geos \
|
||||
# geos \
|
||||
sockets \
|
||||
pcntl \
|
||||
@composer
|
||||
|
||||
# Install build dependencies for GEOS
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
pkg-config \
|
||||
libgeos-dev \
|
||||
libgeos++-dev \
|
||||
autoconf \
|
||||
build-essential \
|
||||
unzip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Download, extract, compile, and enable the php-geos extension
|
||||
RUN curl -fsSL -o php-geos.zip \
|
||||
https://github.com/libgeos/php-geos/archive/dfe1ab17b0f155cc315bc13c75689371676e02e1.zip \
|
||||
&& unzip php-geos.zip \
|
||||
&& rm php-geos.zip \
|
||||
&& cd php-geos-* \
|
||||
&& ./autogen.sh \
|
||||
&& ./configure \
|
||||
&& make -j"$(nproc)" install \
|
||||
&& docker-php-ext-enable geos \
|
||||
&& cd .. \
|
||||
&& rm -rf php-geos-*
|
||||
|
||||
# Update PHP configurations
|
||||
RUN sed -e 's/^expose_php.*/expose_php = Off/' "$PHP_INI_DIR/php.ini-production" > "$PHP_INI_DIR/php.ini" \
|
||||
&& sed -i -e 's/^upload_max_filesize.*/upload_max_filesize = 600M/' -e 's/^post_max_size.*/post_max_size = 0/' \
|
||||
@@ -38,10 +62,10 @@ COPY --from=ghcr.io/springload/ssm-parent:1.8 /usr/bin/ssm-parent /sbin/ssm-pare
|
||||
|
||||
# Create the pnpm directory and set the PNPM_HOME environment variable
|
||||
RUN mkdir -p ~/.pnpm
|
||||
ENV PNPM_HOME /root/.pnpm
|
||||
ENV PNPM_HOME=/root/.pnpm
|
||||
|
||||
# Add the pnpm global bin to the PATH
|
||||
ENV PATH /root/.pnpm/bin:$PATH
|
||||
ENV PATH=/root/.pnpm/bin:$PATH
|
||||
|
||||
# Set some build ENV variables
|
||||
ENV LOG_CHANNEL=stdout
|
||||
@@ -56,9 +80,6 @@ ENV OCTANE_SERVER=frankenphp
|
||||
ARG ENVIRONMENT=production
|
||||
ENV APP_ENV=$ENVIRONMENT
|
||||
|
||||
# Setup github auth
|
||||
ARG GITHUB_AUTH_KEY
|
||||
|
||||
# Copy Caddyfile
|
||||
COPY --chown=www-data:www-data ./Caddyfile $CADDYFILE_PATH
|
||||
|
||||
@@ -68,9 +89,6 @@ RUN mkdir -p /fleetbase/api && mkdir -p /fleetbase/console && chown -R www-data:
|
||||
# Set working directory
|
||||
WORKDIR /fleetbase/api
|
||||
|
||||
# If GITHUB_AUTH_KEY is provided, create auth.json with it
|
||||
RUN if [ -n "$GITHUB_AUTH_KEY" ]; then echo "{\"github-oauth\": {\"github.com\": \"$GITHUB_AUTH_KEY\"}}" > auth.json; fi
|
||||
|
||||
# Prepare composer cache directory
|
||||
RUN mkdir -p /var/www/.cache/composer && chown -R www-data:www-data /var/www/.cache/composer
|
||||
|
||||
@@ -99,7 +117,7 @@ RUN chmod -R 755 /fleetbase/api/storage
|
||||
RUN chmod +x /fleetbase/api/deploy.sh
|
||||
|
||||
# Scheduler base stage
|
||||
FROM base as scheduler-base
|
||||
FROM base AS scheduler-base
|
||||
|
||||
# Install go-crond
|
||||
RUN curl -L https://github.com/webdevops/go-crond/releases/download/23.12.0/go-crond.linux.amd64 > /usr/local/bin/go-crond && chmod +x /usr/local/bin/go-crond
|
||||
@@ -107,32 +125,31 @@ COPY docker/crontab ./crontab
|
||||
RUN chmod 0600 ./crontab
|
||||
|
||||
# Scheduler dev stage
|
||||
FROM scheduler-base as scheduler-dev
|
||||
FROM scheduler-base AS scheduler-dev
|
||||
ENTRYPOINT []
|
||||
CMD ["go-crond", "--verbose", "root:./crontab"]
|
||||
|
||||
# Scheduler stage
|
||||
FROM scheduler-base as scheduler
|
||||
FROM scheduler-base AS scheduler
|
||||
ENTRYPOINT ["/sbin/ssm-parent", "-c", ".ssm-parent.yaml", "run", "--"]
|
||||
CMD ["go-crond", "--verbose", "root:./crontab"]
|
||||
|
||||
# Events stage
|
||||
FROM base as events
|
||||
FROM base AS events
|
||||
ENTRYPOINT ["/sbin/ssm-parent", "-c", ".ssm-parent.yaml", "run", "--", "docker-php-entrypoint"]
|
||||
CMD ["php", "artisan", "queue:work"]
|
||||
|
||||
# Events stage
|
||||
FROM base as events-dev
|
||||
FROM base AS events-dev
|
||||
ENTRYPOINT []
|
||||
CMD ["php", "artisan", "queue:work"]
|
||||
|
||||
# Application dev stage
|
||||
FROM base as app-dev
|
||||
FROM base AS app-dev
|
||||
ENTRYPOINT ["docker-php-entrypoint"]
|
||||
# Add --watch flag later
|
||||
CMD ["sh", "-c", "php artisan octane:frankenphp --workers=6 --max-requests=250 --port=8000 --host=0.0.0.0 --caddyfile $CADDYFILE_PATH"]
|
||||
CMD ["sh", "-c", "php artisan octane:frankenphp --max-requests=250 --port=8000 --host=0.0.0.0 --watch"]
|
||||
|
||||
# Application stage
|
||||
FROM base as app
|
||||
FROM base AS app
|
||||
ENTRYPOINT ["/sbin/ssm-parent", "-c", ".ssm-parent.yaml", "run", "--", "docker-php-entrypoint"]
|
||||
CMD ["sh", "-c", "php artisan octane:frankenphp --workers=6 --max-requests=250 --port=8000 --host=0.0.0.0 --https --http-redirect --caddyfile $CADDYFILE_PATH"]
|
||||
CMD ["sh", "-c", "php artisan octane:frankenphp --max-requests=250 --port=8000 --host=0.0.0.0"]
|
||||
|
||||
Submodule packages/core-api updated: c7438a27e8...377f05b3f7
Submodule packages/ember-core updated: 8cf9fc6537...996a9358b1
Submodule packages/ember-ui updated: eab5966713...b5215c9866
Submodule packages/fleetops updated: abc3b40c27...dfff83b3f1
Submodule packages/fleetops-data updated: 748cb40dfc...5d9cc9d759
Submodule packages/registry-bridge updated: 35fd33767a...f90f7a6b16
Submodule packages/storefront updated: c94205cf35...4718080d88
Reference in New Issue
Block a user