Language editor refactoring part 4 (backend + frontend)

This commit is contained in:
Peter Papp
2021-04-01 10:40:48 +02:00
parent 5130082111
commit 7772ef6b40
32 changed files with 288 additions and 161 deletions

View File

@@ -21,7 +21,7 @@ class SetupDevEnvironment extends Command
* @var string * @var string
*/ */
protected $signature = 'setup:dev'; protected $signature = 'setup:dev';
protected $license = 'Regular'; protected $license = 'Extended';
/** /**
* The console command description. * The console command description.

View File

@@ -6,7 +6,7 @@ use App\Http\Resources\LanguageCollection;
use App\Http\Resources\LanguageResource; use App\Http\Resources\LanguageResource;
use App\Models\Language; use App\Models\Language;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Services\DemoService; use App\Models\Setting;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory; use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response; use Illuminate\Http\Response;
@@ -16,13 +16,6 @@ use App\Http\Requests\Languages\UpdateLanguageRequest;
class LanguageController extends Controller class LanguageController extends Controller
{ {
protected $demo;
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/** /**
* Get all languages for admin translate * Get all languages for admin translate
* *
@@ -42,7 +35,9 @@ class LanguageController extends Controller
*/ */
public function get_language(Language $language) public function get_language(Language $language)
{ {
return response(new LanguageResource($language), 200); return response(
new LanguageResource($language), 200
);
} }
/** /**
@@ -53,6 +48,7 @@ class LanguageController extends Controller
*/ */
public function create_language(CreateLanguageRequest $request) public function create_language(CreateLanguageRequest $request)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
$language = Language::create([ $language = Language::create([
@@ -73,6 +69,7 @@ class LanguageController extends Controller
*/ */
public function update_language(UpdateLanguageRequest $request, Language $language) public function update_language(UpdateLanguageRequest $request, Language $language)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
$language->update(make_single_input($request)); $language->update(make_single_input($request));
@@ -91,18 +88,21 @@ class LanguageController extends Controller
*/ */
public function update_string(UpdateStringRequest $request, Language $language) public function update_string(UpdateStringRequest $request, Language $language)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
$language $language
->languageStrings() ->languageTranslations()
->where('key', $request->name) ->where('key', $request->name)
->update([ ->update([
'value' => $request->value 'value' => $request->value
]); ]);
cache()->forget("language-strings-{$language->locale}"); cache()->forget("language-translations-{$language->locale}");
return response('Done', 204); return response(
'Done', 204
);
} }
/** /**
@@ -113,14 +113,24 @@ class LanguageController extends Controller
*/ */
public function delete_language(Language $language) public function delete_language(Language $language)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
if ($language->locale === 'en') { if ($language->locale === 'en') {
abort(401, "Sorry, you can't delete default language."); abort(401, "Sorry, you can't delete default language.");
} }
// If user try to delete language used as default,
// then set en language as default
if ($language->locale === get_setting('language')) {
Setting::whereName('language')->first()
->update(['value' => 'en']);
}
$language->delete(); $language->delete();
return response('Done', 204); return response(
'Done', 204
);
} }
} }

View File

@@ -51,6 +51,7 @@ class PagesController extends Controller
*/ */
public function update(Request $request, Page $page) public function update(Request $request, Page $page)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
$page->update( $page->update(

View File

@@ -110,6 +110,7 @@ class PlanController extends Controller
*/ */
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
// Update plan // Update plan
@@ -129,6 +130,7 @@ class PlanController extends Controller
*/ */
public function delete($id) public function delete($id)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
// Delete plan // Delete plan

View File

@@ -49,6 +49,7 @@ class SettingController extends Controller
*/ */
public function update(Request $request) public function update(Request $request)
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
// Store image if exist // Store image if exist
@@ -82,6 +83,7 @@ class SettingController extends Controller
public function set_email(Request $request) public function set_email(Request $request)
{ {
// TODO: pridat validator do requestu // TODO: pridat validator do requestu
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
if (!app()->runningUnitTests()) { if (!app()->runningUnitTests()) {
@@ -174,6 +176,7 @@ class SettingController extends Controller
*/ */
public function flush_cache() public function flush_cache()
{ {
// Abort in demo mode
abort_if(is_demo(), 204, 'Done.'); abort_if(is_demo(), 204, 'Done.');
if (!app()->runningUnitTests()) { if (!app()->runningUnitTests()) {

View File

@@ -164,17 +164,10 @@ class AppFunctionsController extends Controller
*/ */
public function get_storage_plans() public function get_storage_plans()
{ {
if (Cache::has('pricing')) { // Get pricing from cache
$pricing = Cache::rememberForever('pricing', function () {
// Get pricing from cache return $this->stripe->getActivePlans();
$pricing = Cache::get('pricing'); });
} else {
// Store pricing to cache
$pricing = Cache::rememberForever('pricing', function () {
return $this->stripe->getActivePlans();
});
}
// Format pricing to collection // Format pricing to collection
$collection = new PricingCollection($pricing); $collection = new PricingCollection($pricing);
@@ -194,11 +187,10 @@ class AppFunctionsController extends Controller
*/ */
public function get_translations($lang) public function get_translations($lang)
{ {
$translations = Cache::rememberForever("language-strings-$lang", function () use ($lang) { $translations = Cache::rememberForever("language-translations-$lang", function () use ($lang) {
return Language::whereLocale($lang) return Language::whereLocale($lang)
->firstOrFail() ->firstOrFail()
->languageStrings; ->languageTranslations;
}); });
return map_language_translations($translations); return map_language_translations($translations);

View File

@@ -17,15 +17,15 @@ class LanguageCollection extends ResourceCollection
*/ */
public function toArray($request) public function toArray($request)
{ {
$current_language = Language::with('languageStrings') $current_language = Language::with('languageTranslations')
->whereLocale(get_setting('language') ?? 'en') ->whereLocale(get_setting('language') ?? 'en')
->first(); ->first();
return [ return [
'data' => $this->collection, 'data' => $this->collection,
'meta' => [ 'meta' => [
'current_language' => new LanguageResource($current_language), 'current_language' => new LanguageResource($current_language),
'default_translations' => get_default_language_strings() 'reference_translations' => get_default_language_translations()
], ],
]; ];
} }

View File

@@ -21,7 +21,7 @@ class LanguageResource extends JsonResource
'attributes' => [ 'attributes' => [
'name' => $this->name, 'name' => $this->name,
'locale' => $this->locale, 'locale' => $this->locale,
'translations' => map_language_translations($this->languageStrings), 'translations' => map_language_translations($this->languageTranslations),
'updated_at' => $this->updated_at, 'updated_at' => $this->updated_at,
'created_at' => $this->created_at, 'created_at' => $this->created_at,
] ]

View File

@@ -6,7 +6,7 @@ use App\Models\Setting;
use App\Models\User; use App\Models\User;
use App\Models\Share; use App\Models\Share;
use App\Models\Language; use App\Models\Language;
use App\Models\LanguageString; use App\Models\LanguageTranslation;
use ByteUnits\Metric; use ByteUnits\Metric;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -599,11 +599,12 @@ function get_image_meta_data($file)
/** /**
* @return Collection * @return Collection
*/ */
function get_default_language_strings() function get_default_language_translations()
{ {
return collect([ return collect([
config("language-strings.extended"), config("language-translations.extended"),
config("language-strings.regular") config("language-translations.regular"),
config("custom-language-translations")
])->collapse(); ])->collapse();
} }
@@ -614,7 +615,7 @@ function get_default_language_strings()
*/ */
function is_dev() function is_dev()
{ {
return env('APP_ENV') === 'local' ? 1 : 0; return env('APP_ENV') === 'local';
} }
/** /**
@@ -853,8 +854,8 @@ function __t($key, $values = null)
return get_setting('language') ?? 'en'; return get_setting('language') ?? 'en';
}); });
$strings = cache()->rememberForever("language-strings-$locale", function () use ($locale) { $strings = cache()->rememberForever("language-translations-$locale", function () use ($locale) {
return Language::whereLocale($locale)->first()->languageStrings ?? get_default_language_strings(); return Language::whereLocale($locale)->first()->languageTranslations ?? get_default_language_translations();
}); });
// Find the string by key // Find the string by key

View File

@@ -29,9 +29,9 @@ class Language extends Model
public $incrementing = false; public $incrementing = false;
public function languageStrings() public function languageTranslations()
{ {
return $this->hasMany(LanguageString::class, 'lang', 'locale'); return $this->hasMany(LanguageTranslation::class, 'lang', 'locale');
} }
protected static function boot() protected static function boot()
@@ -42,21 +42,21 @@ class Language extends Model
$language->id = Str::uuid(); $language->id = Str::uuid();
resolve(HelperService::class) resolve(HelperService::class)
->create_default_language_strings( ->create_default_language_translations(
get_setting('license') ?? 'extended', $language->locale get_setting('license') ?? 'extended', $language->locale
); );
}); });
static::updating(function ($language) { static::updating(function ($language) {
cache()->forget("language-strings-$language->locale"); cache()->forget("language-translations-$language->locale");
}); });
static::deleting(function ($language) { static::deleting(function ($language) {
DB::table('language_strings') DB::table('language_translations')
->whereLang($language->locale) ->whereLang($language->locale)
->delete(); ->delete();
cache()->forget("language-strings-$language->locale"); cache()->forget("language-translations-$language->locale");
}); });
} }
} }

View File

@@ -4,7 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class LanguageString extends Model class LanguageTranslation extends Model
{ {
public $timestamps = false; public $timestamps = false;

View File

@@ -5,6 +5,9 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
/**
* @method static whereName(string $string)
*/
class Setting extends Model class Setting extends Model
{ {
use HasFactory; use HasFactory;

View File

@@ -328,16 +328,18 @@ class HelperService
* @param $license * @param $license
* @param $locale * @param $locale
*/ */
function create_default_language_strings($license, $locale) function create_default_language_translations($license, $locale)
{ {
$translations = [ $translations = [
'extended' => collect([ 'extended' => collect([
config("language-strings.extended"), config("language-translations.extended"),
config("language-strings.regular") config("language-translations.regular"),
config("custom-language-translations")
])->collapse(),
'regular' => collect([
config("language-translations.regular"),
config("custom-language-translations")
])->collapse(), ])->collapse(),
'regular' => collect(
config("language-strings.regular")
),
]; ];
$translations = $translations[strtolower($license)] $translations = $translations[strtolower($license)]
@@ -349,7 +351,7 @@ class HelperService
]; ];
})->toArray(); })->toArray();
DB::table('language_strings') DB::table('language_translations')
->insert($translations); ->insert($translations);
} }
} }

View File

@@ -0,0 +1,11 @@
<?php
/*
* Place here your custom translations for your project.
* These translation will be automatically seeded after you
* run setup:dev script or installing app via Setup Wizard Tool
*/
return [
'custom' => 'translation'
];

View File

@@ -6,6 +6,7 @@ return [
"activation.stripe.description" => "To charge your users, please set up your Stripe account credentials.", "activation.stripe.description" => "To charge your users, please set up your Stripe account credentials.",
"activation.stripe.title" => "Your Stripe account is not set", "activation.stripe.title" => "Your Stripe account is not set",
"admin_menu.invoices" => "Invoices", "admin_menu.invoices" => "Invoices",
"admin_menu.plans" => "Plans",
"admin_page_dashboard.w_total_premium.link" => "Show All Plans", "admin_page_dashboard.w_total_premium.link" => "Show All Plans",
"admin_page_dashboard.w_total_premium.title" => "Total Premium Users", "admin_page_dashboard.w_total_premium.title" => "Total Premium Users",
"admin_page_invoices.empty.description" => "All customers invoices will be showed here.", "admin_page_invoices.empty.description" => "All customers invoices will be showed here.",
@@ -72,10 +73,10 @@ return [
"admin_settings.payments.allow_payments" => "Allow Subscription Payments", "admin_settings.payments.allow_payments" => "Allow Subscription Payments",
"admin_settings.payments.button_submit" => "Test and Save Stripe", "admin_settings.payments.button_submit" => "Test and Save Stripe",
"admin_settings.payments.button_testing" => "Testing Stripe Connection", "admin_settings.payments.button_testing" => "Testing Stripe Connection",
"admin_settings.payments.credentials_disclaimer" => "Your Stripe credentials is not showed because these values are secret and must not be revealed by stranger. You can change your Stripe credentials in your <b>.env</b> file.", "admin_settings.payments.credentials_disclaimer" => "Your Stripe credentials is not showed because these values are secret and must not be revealed by stranger. You can change your Stripe credentials in your <b class='text-theme'>.env</b> file.",
"admin_settings.payments.section_payments" => "Stripe Payments", "admin_settings.payments.section_payments" => "Stripe Payments",
"admin_settings.payments.stripe_create_acc" => "If you dont have stripe account, please <a href=\"https://dashboard.stripe.com/register\" target=\"_blank\">register here</a> and get your Publishable Key, Secret Key and create your webhook.", "admin_settings.payments.stripe_create_acc" => "If you dont have stripe account, please <a href=\"https://dashboard.stripe.com/register\" target=\"_blank\">register here</a> and get your Publishable Key, Secret Key and create your webhook.",
"admin_settings.payments.stripe_create_webhook" => "You have to create webhook endpoint in your Stripe Dashboard. You can find it in <b>Dashboard -> Developers -> Webhooks -> Add Endpoint</b>. In Endpoint URL please copy and paste url bellow. Make sure, this url is your public domain, not localhost. In events section, please click on <b>receive all events</b>. That's all.", "admin_settings.payments.stripe_create_webhook" => "You have to create webhook endpoint in your Stripe Dashboard. You can find it in <b class='text-theme'>Dashboard -> Developers -> Webhooks -> Add Endpoint</b>. In Endpoint URL please copy and paste url bellow. Make sure, this url is your public domain, not localhost. In events section, please click on <b class='text-theme'>receive all events</b>. That's all.",
"admin_settings.payments.stripe_currency" => "Stripe Currency", "admin_settings.payments.stripe_currency" => "Stripe Currency",
"admin_settings.payments.stripe_currency_plac" => "Select your Stripe currency", "admin_settings.payments.stripe_currency_plac" => "Select your Stripe currency",
"admin_settings.payments.stripe_pub_key" => "Publishable Key", "admin_settings.payments.stripe_pub_key" => "Publishable Key",
@@ -276,7 +277,7 @@ return [
"admin_settings.appearance.title_plac" => "Type your app title", "admin_settings.appearance.title_plac" => "Type your app title",
"admin_settings.email.driver" => "Mail Driver", "admin_settings.email.driver" => "Mail Driver",
"admin_settings.email.driver_plac" => "Type your mail driver", "admin_settings.email.driver_plac" => "Type your mail driver",
"admin_settings.email.email_disclaimer" => "This form is not fully pre-filled for security reasons. Your email settings is available in your <b>.env</b> file. For apply new Email settings, please confirm your options by button at the end of formular.", "admin_settings.email.email_disclaimer" => "This form is not fully pre-filled for security reasons. Your email settings is available in your <b class='text-theme'>.env</b> file. For apply new Email settings, please confirm your options by button at the end of formular.",
"admin_settings.email.encryption" => "Mail Encryption", "admin_settings.email.encryption" => "Mail Encryption",
"admin_settings.email.encryption_plac" => "Select your mail encryption", "admin_settings.email.encryption_plac" => "Select your mail encryption",
"admin_settings.email.host" => "Mail Host", "admin_settings.email.host" => "Mail Host",
@@ -560,7 +561,7 @@ return [
"shared_form.button_generate" => "Generate Link", "shared_form.button_generate" => "Generate Link",
"shared_form.button_more_options" => "Set Expiration", "shared_form.button_more_options" => "Set Expiration",
"shared_form.email_placeholder" => "Type your emails", "shared_form.email_placeholder" => "Type your emails",
"shared_form.email_successfully_send_message" => "Your item was <b>successfully sended</b> to recipients emails.", "shared_form.email_successfully_send_message" => "Your item was <b class='text-theme'>successfully sended</b> to recipients emails.",
"shared_form.expiration_day" => "{value}d.", "shared_form.expiration_day" => "{value}d.",
"shared_form.expiration_hour" => "{value}h.", "shared_form.expiration_hour" => "{value}h.",
"shared_form.label_expiration" => "Link Expiration", "shared_form.label_expiration" => "Link Expiration",
@@ -655,5 +656,25 @@ return [
'salutation' => 'Regards', 'salutation' => 'Regards',
'user_sending' => ':name is sending you this file', 'user_sending' => ':name is sending you this file',
'protected_file' => 'This link is protected by password', 'protected_file' => 'This link is protected by password',
'routes_title.language' => 'Languages',
'languages' => 'Languages',
'add_language' => 'Add Language',
'create_language' => 'Create Language',
'edit_translations' => 'Edit Translations',
'language_name' => 'Language Name',
'set_as_default_language' => 'Set as Default Language',
'language_settings' => 'Language Settings',
'search_translations' => 'Search Language Translations...',
'select_locale' => 'Select Locale',
'locale_name' => 'Language Name',
'select_language_locale' => 'Select Language Locale',
'type_language_name' => 'Type Language Name',
'go_to_files' => 'Go to Files',
'color_theme' => 'Color Theme',
'color_theme_description' => 'Your color change will be visible after app refresh.',
'og_image' => 'OG Image',
'og_image_description' => 'Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627',
'app_touch_icon' => 'App Touch Icon',
'app_touch_icon_description' => 'If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156',
] ]
]; ];

View File

@@ -13,7 +13,7 @@ class CreateLanguageStrings extends Migration
*/ */
public function up() public function up()
{ {
Schema::create('language_strings', function (Blueprint $table) { Schema::create('language_translations', function (Blueprint $table) {
$table->string('key'); $table->string('key');
$table->longText('value'); $table->longText('value');
$table->string('lang'); $table->string('lang');
@@ -27,6 +27,6 @@ class CreateLanguageStrings extends Migration
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('language_strings'); Schema::dropIfExists('language_translations');
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,22 +1,22 @@
{ {
"/js/main.js": "/js/main.js", "/js/main.js": "/js/main.js",
"/css/app.css": "/css/app.css", "/css/app.css": "/css/app.css",
"/chunks/admin.js": "/chunks/admin.js?id=72b9b9917f6cc48e8349", "/chunks/admin.js": "/chunks/admin.js?id=f3df96ed0302c713ab20",
"/chunks/admin-account.js": "/chunks/admin-account.js?id=3036df3e72596fabc42e", "/chunks/admin-account.js": "/chunks/admin-account.js?id=3036df3e72596fabc42e",
"/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js?id=62b552a0492fe95b2223", "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js": "/chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chu~c7a13fb0.js?id=62b552a0492fe95b2223",
"/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a001bb84.js": "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a001bb84.js?id=0cad8279d29d79cd0e82", "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a001bb84.js": "/chunks/admin-account~chunks/app-setup~chunks/billings-detail~chunks/create-new-password~chunks/datab~a001bb84.js?id=0cad8279d29d79cd0e82",
"/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js?id=99dbb760d4e3dd0acdbf", "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js": "/chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/~eeab5771.js?id=99dbb760d4e3dd0acdbf",
"/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js?id=9b66c2dab4c6103bb53c", "/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js": "/chunks/admin~chunks/files~chunks/settings~chunks/shared-files~chunks/shared/file-browser.js?id=9b66c2dab4c6103bb53c",
"/chunks/admin~chunks/platform.js": "/chunks/admin~chunks/platform.js?id=861487bdb5c3a4fa3ff2", "/chunks/admin~chunks/platform.js": "/chunks/admin~chunks/platform.js?id=3d9f93a03cb1ffa61d01",
"/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=12f0aaeb615c37d0515d", "/chunks/admin~chunks/platform~chunks/shared.js": "/chunks/admin~chunks/platform~chunks/shared.js?id=12f0aaeb615c37d0515d",
"/chunks/app-appearance.js": "/chunks/app-appearance.js?id=ff4a6b02105eaac93dcd", "/chunks/app-appearance.js": "/chunks/app-appearance.js?id=b4e2d99a172f06a1d312",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js?id=45c8f27411287c7bbf73", "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~605f4c49.js?id=45c8f27411287c7bbf73",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js?id=7702f37f277478ad66c6", "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~8cc7d96f.js?id=7702f37f277478ad66c6",
"/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js?id=04f0cd9719723459b685", "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js": "/chunks/app-appearance~chunks/app-billings~chunks/app-email~chunks/app-index~chunks/app-others~chunks~b9e5655a.js?id=04f0cd9719723459b685",
"/chunks/app-billings.js": "/chunks/app-billings.js?id=82133cc16f55222bbbe6", "/chunks/app-billings.js": "/chunks/app-billings.js?id=82133cc16f55222bbbe6",
"/chunks/app-email.js": "/chunks/app-email.js?id=c578a85112c6a4b1ed0e", "/chunks/app-email.js": "/chunks/app-email.js?id=c578a85112c6a4b1ed0e",
"/chunks/app-index.js": "/chunks/app-index.js?id=7f07dceace5c9c8255bb", "/chunks/app-index.js": "/chunks/app-index.js?id=7f07dceace5c9c8255bb",
"/chunks/app-language.js": "/chunks/app-language.js?id=218c5ee4bf34a6fdb487", "/chunks/app-language.js": "/chunks/app-language.js?id=e97b8b4e0a0f5ac93c97",
"/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=91d6a4649c9277a7bb29", "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=91d6a4649c9277a7bb29",
"/chunks/app-others.js": "/chunks/app-others.js?id=9156adba3b1697a8bf3e", "/chunks/app-others.js": "/chunks/app-others.js?id=9156adba3b1697a8bf3e",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=7e1a982c90174f568fb2", "/chunks/app-payments.js": "/chunks/app-payments.js?id=7e1a982c90174f568fb2",
@@ -25,9 +25,9 @@
"/chunks/app-setup.js": "/chunks/app-setup.js?id=d0e3e046e147ca928f34", "/chunks/app-setup.js": "/chunks/app-setup.js?id=d0e3e046e147ca928f34",
"/chunks/billings-detail.js": "/chunks/billings-detail.js?id=d0ade32264f71dd7a2af", "/chunks/billings-detail.js": "/chunks/billings-detail.js?id=d0ade32264f71dd7a2af",
"/chunks/contact-us.js": "/chunks/contact-us.js?id=f5276b101b2e0c97d6d1", "/chunks/contact-us.js": "/chunks/contact-us.js?id=f5276b101b2e0c97d6d1",
"/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js": "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js?id=5814ff43ba7c67297af1", "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js": "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.js?id=22bd5db44c72e8de5f5b",
"/chunks/create-new-password.js": "/chunks/create-new-password.js?id=48dc53ccbd502c2739ec", "/chunks/create-new-password.js": "/chunks/create-new-password.js?id=48dc53ccbd502c2739ec",
"/chunks/dashboard.js": "/chunks/dashboard.js?id=d93f9d9fbc991dd6a080", "/chunks/dashboard.js": "/chunks/dashboard.js?id=74bd69ac9feddf058188",
"/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js": "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js?id=7540af768b1cfda01a13", "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js": "/chunks/dashboard~chunks/invoices~chunks/pages~chunks/plan-subscribers~chunks/plans~chunks/settings-i~0e2a0654.js?id=7540af768b1cfda01a13",
"/chunks/database.js": "/chunks/database.js?id=7374830dc3cbddf41abb", "/chunks/database.js": "/chunks/database.js?id=7374830dc3cbddf41abb",
"/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=6dccc2158cc6278f683d", "/chunks/dynamic-page.js": "/chunks/dynamic-page.js?id=6dccc2158cc6278f683d",
@@ -53,7 +53,7 @@
"/chunks/plan-settings.js": "/chunks/plan-settings.js?id=66123f72696b47a986a2", "/chunks/plan-settings.js": "/chunks/plan-settings.js?id=66123f72696b47a986a2",
"/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=08e2056bc3744b2ea8f9", "/chunks/plan-subscribers.js": "/chunks/plan-subscribers.js?id=08e2056bc3744b2ea8f9",
"/chunks/plans.js": "/chunks/plans.js?id=608bdbd5c041b728691a", "/chunks/plans.js": "/chunks/plans.js?id=608bdbd5c041b728691a",
"/chunks/platform.js": "/chunks/platform.js?id=6900ccecf3a9a157be76", "/chunks/platform.js": "/chunks/platform.js?id=559a62d18ff169793e54",
"/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=3d5804463c897995e9d1", "/chunks/platform~chunks/shared.js": "/chunks/platform~chunks/shared.js?id=3d5804463c897995e9d1",
"/chunks/profile.js": "/chunks/profile.js?id=fb4a46afdd09cdcdc7da", "/chunks/profile.js": "/chunks/profile.js?id=fb4a46afdd09cdcdc7da",
"/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=d448806bfefc6cc43f0d", "/chunks/profile~chunks/settings-password.js": "/chunks/profile~chunks/settings-password.js?id=d448806bfefc6cc43f0d",
@@ -90,5 +90,46 @@
"/chunks/users.js": "/chunks/users.js?id=f1057be5cf73ebc32c14", "/chunks/users.js": "/chunks/users.js?id=f1057be5cf73ebc32c14",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js?id=a9facd8e57a0dd054f8c", "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~0d496e20.js?id=a9facd8e57a0dd054f8c",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js?id=6d6e7e4191c9e2705c8a", "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~7afe9e20.js?id=6d6e7e4191c9e2705c8a",
"/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3" "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3",
"/chunks/app-language.5e86b6c8aedb968aabd1.hot-update.js": "/chunks/app-language.5e86b6c8aedb968aabd1.hot-update.js",
"/chunks/app-language.3e137679fcd212ecdb43.hot-update.js": "/chunks/app-language.3e137679fcd212ecdb43.hot-update.js",
"/chunks/app-language.8069ae5a36cc4868d1d3.hot-update.js": "/chunks/app-language.8069ae5a36cc4868d1d3.hot-update.js",
"/chunks/app-language.d4c9d87012f92cbb3694.hot-update.js": "/chunks/app-language.d4c9d87012f92cbb3694.hot-update.js",
"/chunks/app-language.c0acc236afe078713927.hot-update.js": "/chunks/app-language.c0acc236afe078713927.hot-update.js",
"/chunks/app-language.42b3b09042f97ffb073a.hot-update.js": "/chunks/app-language.42b3b09042f97ffb073a.hot-update.js",
"/chunks/app-language.7478a2ac686bc8208aac.hot-update.js": "/chunks/app-language.7478a2ac686bc8208aac.hot-update.js",
"/chunks/app-language.695a92293d8dc92d833b.hot-update.js": "/chunks/app-language.695a92293d8dc92d833b.hot-update.js",
"/chunks/app-language.25fa944544b002f36615.hot-update.js": "/chunks/app-language.25fa944544b002f36615.hot-update.js",
"/chunks/app-language.aee54dee7bdbae4a4dad.hot-update.js": "/chunks/app-language.aee54dee7bdbae4a4dad.hot-update.js",
"/chunks/app-language.62fa61e8408e9fd42b23.hot-update.js": "/chunks/app-language.62fa61e8408e9fd42b23.hot-update.js",
"/js/main.21d047cff85c2cc93f65.hot-update.js": "/js/main.21d047cff85c2cc93f65.hot-update.js",
"/chunks/app-language.13a02b269488a9ed8054.hot-update.js": "/chunks/app-language.13a02b269488a9ed8054.hot-update.js",
"/chunks/app-language.ff6a3c1bce44294e69aa.hot-update.js": "/chunks/app-language.ff6a3c1bce44294e69aa.hot-update.js",
"/chunks/app-language.0aff16e91050419f056f.hot-update.js": "/chunks/app-language.0aff16e91050419f056f.hot-update.js",
"/chunks/admin.00d9afd473b8b4521765.hot-update.js": "/chunks/admin.00d9afd473b8b4521765.hot-update.js",
"/chunks/admin.b85158f2cba3bfbbf404.hot-update.js": "/chunks/admin.b85158f2cba3bfbbf404.hot-update.js",
"/chunks/admin.bf53021a67ae75f1b0ee.hot-update.js": "/chunks/admin.bf53021a67ae75f1b0ee.hot-update.js",
"/chunks/admin.bda5e8845d2e437ffe7c.hot-update.js": "/chunks/admin.bda5e8845d2e437ffe7c.hot-update.js",
"/chunks/admin.a97d84e1d8754867cef5.hot-update.js": "/chunks/admin.a97d84e1d8754867cef5.hot-update.js",
"/chunks/app-language.8ca3efeede3cedbd37e0.hot-update.js": "/chunks/app-language.8ca3efeede3cedbd37e0.hot-update.js",
"/chunks/app-language.23f838b7be45ce10476b.hot-update.js": "/chunks/app-language.23f838b7be45ce10476b.hot-update.js",
"/chunks/app-language.fd910667c3258a91322b.hot-update.js": "/chunks/app-language.fd910667c3258a91322b.hot-update.js",
"/chunks/app-language.6a163294803727b4d501.hot-update.js": "/chunks/app-language.6a163294803727b4d501.hot-update.js",
"/chunks/platform.085176bd0065608cb370.hot-update.js": "/chunks/platform.085176bd0065608cb370.hot-update.js",
"/chunks/dashboard.f475c4f86956a8e5419b.hot-update.js": "/chunks/dashboard.f475c4f86956a8e5419b.hot-update.js",
"/chunks/app-language.1dd1423a8af00cb8c9bd.hot-update.js": "/chunks/app-language.1dd1423a8af00cb8c9bd.hot-update.js",
"/chunks/app-language.040639168a8e73d40dec.hot-update.js": "/chunks/app-language.040639168a8e73d40dec.hot-update.js",
"/chunks/app-language.72377b182d4f8ae86208.hot-update.js": "/chunks/app-language.72377b182d4f8ae86208.hot-update.js",
"/chunks/app-language.d82931f09bfdd6dbc955.hot-update.js": "/chunks/app-language.d82931f09bfdd6dbc955.hot-update.js",
"/chunks/app-language.2193825771658065f586.hot-update.js": "/chunks/app-language.2193825771658065f586.hot-update.js",
"/chunks/app-language.cab91ceba0b383f64680.hot-update.js": "/chunks/app-language.cab91ceba0b383f64680.hot-update.js",
"/chunks/app-language.a42ea53577d7e0f0a5fb.hot-update.js": "/chunks/app-language.a42ea53577d7e0f0a5fb.hot-update.js",
"/chunks/app-language.09d631da1a2172e96bce.hot-update.js": "/chunks/app-language.09d631da1a2172e96bce.hot-update.js",
"/chunks/app-appearance.690e1a1f6d721bca8cdf.hot-update.js": "/chunks/app-appearance.690e1a1f6d721bca8cdf.hot-update.js",
"/chunks/contact-us~chunks/dynamic-page~chunks/homepage.51e62febff164672078a.hot-update.js": "/chunks/contact-us~chunks/dynamic-page~chunks/homepage.51e62febff164672078a.hot-update.js",
"/chunks/app-language.439fa6fafc54298cdf2b.hot-update.js": "/chunks/app-language.439fa6fafc54298cdf2b.hot-update.js",
"/chunks/app-language.9ee4a795d26a6e44820c.hot-update.js": "/chunks/app-language.9ee4a795d26a6e44820c.hot-update.js",
"/js/main.8517a680822ffe9748c9.hot-update.js": "/js/main.8517a680822ffe9748c9.hot-update.js",
"/chunks/admin.9396f79fef53ad7070fe.hot-update.js": "/chunks/admin.9396f79fef53ad7070fe.hot-update.js",
"/chunks/platform.9396f79fef53ad7070fe.hot-update.js": "/chunks/platform.9396f79fef53ad7070fe.hot-update.js"
} }

View File

@@ -32,7 +32,7 @@
<ul v-if="config.isAuthenticated" class="navigation-links"> <ul v-if="config.isAuthenticated" class="navigation-links">
<li v-if="config.userRegistration"> <li v-if="config.userRegistration">
<router-link class="cta-button text-theme bg-theme-100" :to="{name: 'Files'}"> <router-link class="cta-button text-theme bg-theme-100" :to="{name: 'Files'}">
Go to Files <!--todo: preklad--> {{ $t('go_to_files') }}
</router-link> </router-link>
</li> </li>
</ul> </ul>

View File

@@ -11,7 +11,7 @@
<!--More Actions--> <!--More Actions-->
<div @click="showMobileNavigation" class="mobile-menu"> <div @click="showMobileNavigation" class="mobile-menu">
<menu-icon size="17" class="icon"></menu-icon> <menu-icon size="17" class="icon" />
</div> </div>
</header> </header>
</template> </template>

View File

@@ -2,8 +2,7 @@
<PopupWrapper name="create-language"> <PopupWrapper name="create-language">
<!--Title--> <!--Title-->
<!--TODO: jazyk--> <PopupHeader :title="$t('create_language')" icon="edit" />
<PopupHeader title="Create Language" icon="edit" />
<!--Content--> <!--Content-->
<PopupContent> <PopupContent>
@@ -12,14 +11,14 @@
<ValidationObserver @submit.prevent="createLanguage" ref="createForm" v-slot="{ invalid }" tag="form" class="form-wrapper"> <ValidationObserver @submit.prevent="createLanguage" ref="createForm" v-slot="{ invalid }" tag="form" class="form-wrapper">
<ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Locale" rules="required" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Locale" rules="required" v-slot="{ errors }">
<label class="input-label">Select Locale:</label> <label class="input-label">{{ $t('select_locale') }}:</label>
<SelectInput v-model="form.locale" :options="locals" placeholder="Select Language Locale" :isError="errors[0]" /> <SelectInput v-model="form.locale" :options="locales" :placeholder="$t('select_language_locale')" :isError="errors[0]" />
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span> <span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider> </ValidationProvider>
<ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Name" rules="required" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper password" name="Language Name" rules="required" v-slot="{ errors }">
<label class="input-label">Type Name:</label> <label class="input-label">{{ $t('locale_name') }}:</label>
<input v-model="form.name" :class="{'is-error': errors[0]}" type="text" ref="input" class="focus-border-theme" placeholder="Type Language Name"> <input v-model="form.name" :class="{'is-error': errors[0]}" type="text" ref="input" class="focus-border-theme" :placeholder="$t('type_language_name')">
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span> <span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider> </ValidationProvider>
</ValidationObserver> </ValidationObserver>
@@ -32,7 +31,7 @@
@click.native="$closePopup()" @click.native="$closePopup()"
button-style="secondary" button-style="secondary"
> >
Cancel {{ $t('global.cancel') }}
</ButtonBase> </ButtonBase>
<ButtonBase <ButtonBase
class="popup-button" class="popup-button"
@@ -41,7 +40,7 @@
:loading="isLoading" :loading="isLoading"
:disabled="isLoading" :disabled="isLoading"
> >
Create Language {{ $t('create_language') }}
</ButtonBase> </ButtonBase>
</PopupActions> </PopupActions>
</PopupWrapper> </PopupWrapper>
@@ -79,7 +78,7 @@ export default {
locale: undefined, locale: undefined,
}, },
isLoading: false, isLoading: false,
locals: [ locales: [
{ {
value: "ab", value: "ab",
label: "Abkhaz" label: "Abkhaz"
@@ -851,10 +850,6 @@ export default {
}) })
} }
}, },
},
mounted() {
this.name = undefined,
this.locale = undefined
} }
} }
</script> </script>

View File

@@ -9,10 +9,10 @@
<input <input
v-model="query" v-model="query"
@input="$emit('input', query)" @input="$emit('input', query)"
class="query" class="query focus-border-theme"
type="text" type="text"
name="searchInput" name="searchInput"
placeholder="Search Language Strings..." :placeholder="$t('search_translations')"
/> />
</div> </div>
</template> </template>
@@ -34,7 +34,6 @@ export default {
methods: { methods: {
clearInput() { clearInput() {
this.query = undefined this.query = undefined
this.$emit('reset-query') this.$emit('reset-query')
}, },
}, },
@@ -74,13 +73,13 @@ export default {
} }
&:focus { &:focus {
border: 1px solid $theme; border-width: 1px;
box-shadow: 0 0 7px rgba($theme, 0.3); border-style: solid;
} }
&:focus + .icon { &:focus + .icon {
path { path {
fill: $theme; color: inherit;
} }
} }
} }
@@ -105,4 +104,12 @@ export default {
} }
} }
@media (prefers-color-scheme: dark) {
.search-bar {
input {
background: $dark_mode_foreground;
}
}
}
</style> </style>

View File

@@ -33,7 +33,7 @@
<!--Permision Select--> <!--Permision Select-->
<ValidationProvider v-if="isFolder" tag="div" mode="passive" class="input-wrapper" name="Permission" rules="required" v-slot="{ errors }"> <ValidationProvider v-if="isFolder" tag="div" mode="passive" class="input-wrapper" name="Permission" rules="required" v-slot="{ errors }">
<label class="input-label">{{ $t('shared_form.label_permission') }}:</label> <label class="input-label">{{ $t('shared_form.label_permission') }}:</label>
<SelectInput v-model="shareOptions.permission" :options="permissionOptions" :default="shareOptions.permission" :placeholder="$t('shared_form.placeholder_permission')" :isError="errors[0]"/> <SelectInput v-model="shareOptions.permission" :options="$translateSelectOptions(permissionOptions)" :default="shareOptions.permission" :placeholder="$t('shared_form.placeholder_permission')" :isError="errors[0]"/>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span> <span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</ValidationProvider> </ValidationProvider>
@@ -60,7 +60,7 @@
<!--Set expiration--> <!--Set expiration-->
<div class="input-wrapper"> <div class="input-wrapper">
<label class="input-label">{{ $t('shared_form.label_expiration') }}:</label> <label class="input-label">{{ $t('shared_form.label_expiration') }}:</label>
<SelectBoxInput v-model="shareOptions.expiration" :data="expirationList" :value="shareOptions.expiration" class="box"/> <SelectBoxInput v-model="shareOptions.expiration" :data="$translateSelectOptions(expirationList)" :value="shareOptions.expiration" class="box"/>
</div> </div>
</div> </div>

View File

@@ -292,7 +292,6 @@ const routesAdmin = [
import(/* webpackChunkName: "chunks/app-language" */ './views/Admin/Languages/Language'), import(/* webpackChunkName: "chunks/app-language" */ './views/Admin/Languages/Language'),
meta: { meta: {
requiresAuth: true, requiresAuth: true,
title: 'routes_title.language'
}, },
} }
] ]

View File

@@ -1,6 +1,9 @@
<template> <template>
<section id="viewport"> <section id="viewport">
<!--Mobile Navigation-->
<MobileNavigation />
<!--Confirm Popup--> <!--Confirm Popup-->
<Confirm /> <Confirm />
@@ -87,6 +90,7 @@
<script> <script>
import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon, GlobeIcon } from 'vue-feather-icons' import { UsersIcon, SettingsIcon, FileTextIcon, CreditCardIcon, DatabaseIcon, BoxIcon, MonitorIcon, GlobeIcon } from 'vue-feather-icons'
import MobileNavigation from '@/components/Others/MobileNavigation'
import ContentSidebar from '@/components/Sidebar/ContentSidebar' import ContentSidebar from '@/components/Sidebar/ContentSidebar'
import CreateLanguage from '@/components/Others/CreateLanguage' import CreateLanguage from '@/components/Others/CreateLanguage'
import ContentGroup from '@/components/Sidebar/ContentGroup' import ContentGroup from '@/components/Sidebar/ContentGroup'
@@ -100,6 +104,7 @@
...mapGetters(['config']), ...mapGetters(['config']),
}, },
components: { components: {
MobileNavigation,
CreateLanguage, CreateLanguage,
ContentSidebar, ContentSidebar,
CreditCardIcon, CreditCardIcon,

View File

@@ -26,13 +26,12 @@
<FormLabel class="mt-70">{{ $t('admin_settings.appearance.section_appearance') }}</FormLabel> <FormLabel class="mt-70">{{ $t('admin_settings.appearance.section_appearance') }}</FormLabel>
<!--TODO: add language-->
<div class="block-wrapper"> <div class="block-wrapper">
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Title" rules="required" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Title" rules="required" v-slot="{ errors }">
<div class="inline-wrapper"> <div class="inline-wrapper">
<div class="switch-label"> <div class="switch-label">
<label class="input-label">Color Theme:</label> <label class="input-label">{{ $t('color_theme') }}:</label>
<small class="input-help">Your color change will be visible after app refresh.</small> <small class="input-help">{{ $t('color_theme_description') }}</small>
<span class="error-message" v-if="errors[0]">{{ errors[0] }}</span> <span class="error-message" v-if="errors[0]">{{ errors[0] }}</span>
</div> </div>
<input @input="$updateText('/admin/settings', 'app_color', app.color)" v-model="app.color" :placeholder="$t('admin_settings.appearance.title_plac')" type="color" <input @input="$updateText('/admin/settings', 'app_color', app.color)" v-model="app.color" :placeholder="$t('admin_settings.appearance.title_plac')" type="color"
@@ -63,21 +62,19 @@
</ValidationProvider> </ValidationProvider>
</div> </div>
<!--TODO: add language-->
<div class="block-wrapper"> <div class="block-wrapper">
<label>OG Image:</label> <label>{{ $t('og_image') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }">
<ImageInput @input="$updateImage('/admin/settings', 'app_og_image', app.og_image)" :image="$getImage(app.og_image)" v-model="app.og_image" :error="errors[0]"/> <ImageInput @input="$updateImage('/admin/settings', 'app_og_image', app.og_image)" :image="$getImage(app.og_image)" v-model="app.og_image" :error="errors[0]"/>
<small class="input-help">Image that appear when someone shares the content to Facebook or any other social medium. Preferred size is 1200x627</small> <small class="input-help">{{ $t('og_image_description') }}</small>
</ValidationProvider> </ValidationProvider>
</div> </div>
<!--TODO: add language-->
<div class="block-wrapper"> <div class="block-wrapper">
<label>App Touch Icon:</label> <label>{{ $t('app_touch_icon') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Favicon" v-slot="{ errors }">
<ImageInput @input="$updateImage('/admin/settings', 'app_touch_icon', app.touch_icon)" :image="$getImage(app.touch_icon)" v-model="app.touch_icon" :error="errors[0]"/> <ImageInput @input="$updateImage('/admin/settings', 'app_touch_icon', app.touch_icon)" :image="$getImage(app.touch_icon)" v-model="app.touch_icon" :error="errors[0]"/>
<small class="input-help">If user store bookmark on his phone screen, this icon appear in app thumbnail. Preferred size is 156x156</small> <small class="input-help">{{ $t('app_touch_icon_description') }}</small>
</ValidationProvider> </ValidationProvider>
</div> </div>
</div> </div>

View File

@@ -10,7 +10,7 @@
</a> </a>
</div> </div>
<div class="metadata"> <div class="metadata">
<a href="https://vuefilemanager.com/changelog" target="_blank" class="meta"> <a href="https://gist.github.com/MakingCG/9c07f8af392081ae5d5290d920a79b5d" target="_blank" class="meta">
<span class="meta-title">{{ $t('admin_page_dashboard.version') }}:</span> <span class="meta-title">{{ $t('admin_page_dashboard.version') }}:</span>
<ColorLabel color="purple"> <ColorLabel color="purple">
{{ data.app_version }} {{ data.app_version }}

View File

@@ -1,8 +1,8 @@
<template> <template>
<div id="single-page"> <div id="single-page">
<div id="page-content"> <div id="page-content">
<MobileHeader title="Languages" /> <MobileHeader :title="$t('routes_title.language')" />
<PageHeader title="Languages" /> <PageHeader :title="$t('routes_title.language')" />
<div v-if="languages" class="content-page"> <div v-if="languages" class="content-page">
@@ -12,14 +12,14 @@
<div class="sticky top-65"> <div class="sticky top-65">
<div class="languages-wrapper page-tab from-fixed-width"> <div class="languages-wrapper page-tab from-fixed-width">
<div class="language-label-wrapper"> <div class="language-label-wrapper">
<label class="language-label">Languages</label> <label class="language-label">{{ $t('languages') }}</label>
</div> </div>
<!-- Languages --> <!-- Languages -->
<div class="all-language-wrapper"> <div class="all-language-wrapper">
<div @click="getLanguage(language)" v-for="language in languages" :key="language.data.id" class="language"> <div @click="getLanguage(language)" v-for="language in languages" :key="language.data.id" class="language group">
<label class="name" :class="{'active': selectedLanguage && selectedLanguage.data.attributes.locale === language.data.attributes.locale}"> <label class="name" :class="{'active': selectedLanguage && selectedLanguage.data.attributes.locale === language.data.attributes.locale}">
{{ language.data.attributes.name }} <span class="active-text-theme group-hover-text-theme">{{ language.data.attributes.name }}</span>
</label> </label>
<x-icon <x-icon
v-if="language.data.attributes.locale !== 'en'" v-if="language.data.attributes.locale !== 'en'"
@@ -32,7 +32,7 @@
</div> </div>
<MobileActionButton @click.native="createLanguage" icon="plus" class="button-add-language"> <MobileActionButton @click.native="createLanguage" icon="plus" class="button-add-language">
Add Language {{ $t('add_language') }}
</MobileActionButton> </MobileActionButton>
</div> </div>
</div> </div>
@@ -40,36 +40,16 @@
<!--Content--> <!--Content-->
<div class="form block-form content"> <div class="form block-form content">
<div v-if="! selectedLanguage"> <Spinner v-if="! selectedLanguage" />
<Spinner />
</div>
<div v-if="selectedLanguage"> <div v-if="selectedLanguage">
<FormLabel icon="settings"> <FormLabel icon="settings">
Language Settings {{ $t('language_settings') }}
</FormLabel> </FormLabel>
<!--Set default language-->
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">
Set as Default Language:
</label>
</div>
<SwitchInput
@input="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'language', selectedLanguage.data.attributes.locale)"
class="switch"
:class="{'disable-switch': selectedLanguage.data.attributes.locale !== }"
/>
</div>
</div>
</div>
<!--Language name--> <!--Language name-->
<div class="block-wrapper"> <div class="block-wrapper">
<label>Language Name:</label> <label>{{ $t('language_name') }}:</label>
<ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Description" rules="required" v-slot="{ errors }"> <ValidationProvider tag="div" mode="passive" class="input-wrapper" name="App Description" rules="required" v-slot="{ errors }">
<input @input="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'name', selectedLanguage.data.attributes.name)" v-model="selectedLanguage.data.attributes.name" <input @input="$updateText(`/admin/languages/${selectedLanguage.data.id}`, 'name', selectedLanguage.data.attributes.name)" v-model="selectedLanguage.data.attributes.name"
:placeholder="$t('admin_settings.appearance.description_plac')" type="text" :class="{'is-error': errors[0]}" class="focus-border-theme" /> :placeholder="$t('admin_settings.appearance.description_plac')" type="text" :class="{'is-error': errors[0]}" class="focus-border-theme" />
@@ -77,18 +57,45 @@
</ValidationProvider> </ValidationProvider>
</div> </div>
<!--Set default language-->
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">
{{ $t('set_as_default_language') }}:
</label>
<small class="input-help">
If this language is set as default, app will appear in this language for all users.
</small>
</div>
<SwitchInput
@input="setDefaultLanguage"
class="switch"
:class="{'disable-switch': selectedLanguage.data.attributes.locale === this.defaultLanguageLocale }"
:state="selectedLanguage.data.attributes.locale === this.defaultLanguageLocale"
/>
</div>
</div>
</div>
<!--Translations--> <!--Translations-->
<FormLabel class="mt-70"> <FormLabel class="mt-70">
Edit Translations {{ $t('edit_translations') }}
</FormLabel> </FormLabel>
<InfoBox class="info-box">
<p>Please preserve in your translations special string variables defined in format as <b class="text-theme">:variable</b> or <b class="text-theme">{variable}</b>.</p>
</InfoBox>
<!--Inline Search--> <!--Inline Search-->
<div class="block-wrapper sticky top-50 search-bar-wrapper"> <div class="block-wrapper sticky top-50 search-bar-wrapper">
<SearchInput v-model="query" @reset-query="query = ''" /> <SearchInput v-model="query" @reset-query="query = ''" />
</div> </div>
<!--Translation-->
<div class="block-wrapper" v-for="(translation, key) in translationList" :key="key"> <div class="block-wrapper" v-for="(translation, key) in translationList" :key="key">
<label> {{ defaultTranslations[key] }}:</label> <label> {{ referenceTranslations[key] }}:</label>
<ValidationProvider tag="div" class="input-wrapper" name="Language string" rules="required" v-slot="{ errors }"> <ValidationProvider tag="div" class="input-wrapper" name="Language string" rules="required" v-slot="{ errors }">
<input type="text" <input type="text"
:class="{'is-error': errors[0]}" :class="{'is-error': errors[0]}"
@@ -116,6 +123,7 @@
import FormLabel from '@/components/Others/Forms/FormLabel' import FormLabel from '@/components/Others/Forms/FormLabel'
import MobileHeader from '@/components/Mobile/MobileHeader' import MobileHeader from '@/components/Mobile/MobileHeader'
import ButtonBase from '@/components/FilesView/ButtonBase' import ButtonBase from '@/components/FilesView/ButtonBase'
import InfoBox from '@/components/Others/Forms/InfoBox'
import PageHeader from '@/components/Others/PageHeader' import PageHeader from '@/components/Others/PageHeader'
import Spinner from '@/components/FilesView/Spinner' import Spinner from '@/components/FilesView/Spinner'
import {PlusIcon, XIcon} from 'vue-feather-icons' import {PlusIcon, XIcon} from 'vue-feather-icons'
@@ -135,40 +143,48 @@
PageHeader, PageHeader,
FormLabel, FormLabel,
PlusIcon, PlusIcon,
InfoBox,
Spinner, Spinner,
XIcon XIcon
}, },
data() { data() {
return { return {
defaultTranslations: undefined, searchedTranslationResults: undefined,
referenceTranslations: undefined,
defaultLanguageLocale: undefined,
selectedLanguage: undefined, selectedLanguage: undefined,
occurrences: undefined,
languages: undefined, languages: undefined,
query: '', query: '',
} }
}, },
watch: { watch: {
query: debounce(function (val) { query: debounce(function (val) {
this.occurrences = omitBy(this.selectedLanguage.data.attributes.translations, (string, key) => { this.searchedTranslationResults = omitBy(this.selectedLanguage.data.attributes.translations, string => {
return !string.toLowerCase().includes(val.toLowerCase()) return !string.toLowerCase().includes(val.toLowerCase())
}) })
}, 300), }, 300),
}, },
computed: { computed: {
translationList() { translationList() {
return this.occurrences && this.query !== '' return this.searchedTranslationResults && this.query !== ''
? this.occurrences ? this.searchedTranslationResults
: this.selectedLanguage.data.attributes.translations : this.selectedLanguage.data.attributes.translations
} }
}, },
methods: { methods: {
setDefaultLanguage() {
this.$updateText('/admin/settings', 'language', this.selectedLanguage.data.attributes.locale)
this.defaultLanguageLocale = this.selectedLanguage.data.attributes.locale
},
getLanguages() { getLanguages() {
axios axios
.get('/api/admin/languages') .get('/api/admin/languages')
.then(response => { .then(response => {
this.languages = response.data.data this.languages = response.data.data
this.defaultTranslations = response.data.meta.default_translations this.referenceTranslations = response.data.meta.reference_translations
this.selectedLanguage = response.data.meta.current_language this.selectedLanguage = response.data.meta.current_language
this.defaultLanguageLocale = response.data.meta.current_language.data.attributes.locale
}) })
.catch(() => { .catch(() => {
this.$isSomethingWrong() this.$isSomethingWrong()
@@ -243,6 +259,18 @@
} }
} }
.disable-switch {
cursor: not-allowed;
/deep/ .text-right {
pointer-events: none;
}
}
.info-box {
margin-bottom: 12px;
}
.side-content { .side-content {
flex: 0 0 225px; flex: 0 0 225px;
@@ -275,10 +303,6 @@
.icon { .icon {
display: block; display: block;
} }
.name {
color: $theme !important;
}
} }
.name { .name {
@@ -294,10 +318,6 @@
cursor: pointer; cursor: pointer;
} }
.active {
color: $theme !important;
}
} }
} }
@@ -327,6 +347,10 @@
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.search-bar-wrapper {
background: $dark_mode_background;
}
.language { .language {
.name { .name {

View File

@@ -65,7 +65,7 @@
}, },
{ {
icon: 'language', icon: 'language',
title: this.$t('admin_menu.language'), title: this.$t('languages'),
routeName: 'Language', routeName: 'Language',
isVisible: true, isVisible: true,

View File

@@ -52,7 +52,7 @@ class LanguageEditorTest extends TestCase
'locale' => 'sk', 'locale' => 'sk',
]); ]);
$this->assertDatabaseHas('language_strings', [ $this->assertDatabaseHas('language_translations', [
'key' => 'actions.close', 'key' => 'actions.close',
'value' => 'Close', 'value' => 'Close',
'lang' => 'sk', 'lang' => 'sk',
@@ -111,7 +111,7 @@ class LanguageEditorTest extends TestCase
'locale' => 'sk', 'locale' => 'sk',
]); ]);
$this->assertDatabaseMissing('language_strings', [ $this->assertDatabaseMissing('language_translations', [
'key' => 'actions.close', 'key' => 'actions.close',
'value' => 'Close', 'value' => 'Close',
'lang' => 'sk', 'lang' => 'sk',
@@ -151,8 +151,8 @@ class LanguageEditorTest extends TestCase
$this->getJson('/api/admin/languages') $this->getJson('/api/admin/languages')
->assertStatus(200) ->assertStatus(200)
->assertJsonFragment([ ->assertJsonFragment([
"name" => "English", "locale" => "en",
"current_language" => "en", "actions.close" => "Close",
]); ]);
} }
@@ -175,7 +175,7 @@ class LanguageEditorTest extends TestCase
'value' => 'Close It, now!', 'value' => 'Close It, now!',
]); ]);
$this->assertDatabaseHas('language_strings', [ $this->assertDatabaseHas('language_translations', [
'key' => 'actions.close', 'key' => 'actions.close',
'value' => 'Close It, now!', 'value' => 'Close It, now!',
'lang' => 'en', 'lang' => 'en',
@@ -185,7 +185,7 @@ class LanguageEditorTest extends TestCase
/** /**
* @test * @test
*/ */
public function it_get_language_strings_by_selected_language_id() public function it_get_language_with_strings_by_selected_language_id()
{ {
$this->setup->seed_default_language(); $this->setup->seed_default_language();
@@ -196,12 +196,11 @@ class LanguageEditorTest extends TestCase
$language = Language::first(); $language = Language::first();
$this->getJson("/api/admin/languages/$language->id/strings") $this->getJson("/api/admin/languages/$language->id")
->assertStatus(200) ->assertStatus(200)
->assertJsonFragment([ ->assertJsonFragment([
"key" => "actions.close", "actions.close" => "Close",
"value" => "Close", "locale" => "en",
"lang" => "en",
]); ]);
} }
@@ -219,6 +218,20 @@ class LanguageEditorTest extends TestCase
]); ]);
} }
/**
* @test
*/
public function it_get_custom_translations_from_file_config()
{
$this->setup->seed_default_language();
$this->assertDatabaseHas('language_translations', [
'key' => 'custom',
'value' => 'translation',
'lang' => 'en',
]);
}
/** /**
* @test * @test
*/ */
@@ -227,7 +240,7 @@ class LanguageEditorTest extends TestCase
$this->setup->seed_default_language(); $this->setup->seed_default_language();
Language::first() Language::first()
->languageStrings() ->languageTranslations()
->forceCreate([ ->forceCreate([
"key" => "test", "key" => "test",
"value" => "Hi, my name is :name :surname", "value" => "Hi, my name is :name :surname",

View File

@@ -3,7 +3,7 @@
namespace Tests\Feature\Setup; namespace Tests\Feature\Setup;
use App\Models\Language; use App\Models\Language;
use App\Models\LanguageString; use App\Models\LanguageTranslation;
use App\Models\Setting; use App\Models\Setting;
use App\Services\SetupService; use App\Services\SetupService;
use Illuminate\Foundation\Testing\DatabaseMigrations; use Illuminate\Foundation\Testing\DatabaseMigrations;
@@ -55,7 +55,7 @@ class SetupServiceTest extends TestCase
'locale' => 'en', 'locale' => 'en',
]); ]);
$this->assertDatabaseHas('language_strings', [ $this->assertDatabaseHas('language_translations', [
'key' => 'actions.close', 'key' => 'actions.close',
'value' => 'Close', 'value' => 'Close',
'lang' => 'en', 'lang' => 'en',

View File

@@ -270,7 +270,7 @@ class SetupWizardTest extends TestCase
'locale' => 'en', 'locale' => 'en',
]); ]);
$this->assertDatabaseHas('language_strings', [ $this->assertDatabaseHas('language_translations', [
'key' => 'actions.close', 'key' => 'actions.close',
'value' => 'Close', 'value' => 'Close',
'lang' => 'en', 'lang' => 'en',