14 Commits

Author SHA1 Message Date
kor-elf 859187bafa Update image version to 0.6.0 in production configuration 2026-06-21 00:17:32 +05:00
kor-elf 9e6e699db0 Add "Do not translate" functionality to TinyMCE editor
- Add a custom TinyMCE plugin to mark content with `translate="no"`.
- Update WYSIWYG editor to support the "Do not translate" toggle button and menu item.
- Highlight non-translatable content with custom styles in the editor.
- Localize plugin strings for English and Russian.
2026-06-20 23:54:25 +05:00
kor-elf 993350073c Cast description input to string with default value in StoreUpdateRequest. 2026-06-20 23:13:59 +05:00
kor-elf 9a6604a40b Replace InterventionImage::read with InterventionImage::decodePath for image processing 2026-06-20 22:18:51 +05:00
kor-elf 85a4361d0c UpUpdated Laravel to version 13. 2026-06-20 22:18:21 +05:00
kor-elf d4174cf7d2 Update image version to 0.5.0 in production config 2025-08-23 02:29:39 +05:00
kor-elf de496eaea1 Comment out version declaration in docker-compose-prod.yml 2025-08-23 02:28:49 +05:00
kor-elf 94db6aa51d Add jq to Docker image and improve UNIT_SOURCE handling
- Include jq in the Docker image for JSON processing.
- Refactor UNIT_SOURCE logic to cleanly update configuration using jq.
- Remove obsolete UNIT_SOURCE handling code.
2025-08-23 01:59:57 +05:00
kor-elf c33fcd1d7c Add required_with validation for language.*.code
- Enforces `language.*.code` to be required when `language.*.source_language_id` is present.
2025-08-22 22:33:39 +05:00
kor-elf 3d4bef0e56 Handle expired session errors gracefully
- Add custom response for 419 (CSRF token expiration) using exception handler.
- Update language files to include localized error messages for expired sessions.
2025-08-22 19:07:55 +05:00
kor-elf 19b0e68b8b The active menu was not highlighted when we went to the documentation section. 2025-08-22 16:47:04 +05:00
kor-elf ba74aa9977 The active menu was not highlighted if it was not the primary language. 2025-08-22 16:42:20 +05:00
kor-elf 224240708d The cache was not cleared when saving
Clearing the cache using tags did not work correctly. Had to abandon them.
2025-08-22 16:14:22 +05:00
kor-elf 4049f9df53 Fixes for not saving sorting in documentation. Add 'sort' attribute to fillable properties in Documentation model. 2025-08-22 15:56:01 +05:00
31 changed files with 2467 additions and 4043 deletions
-18
View File
@@ -1,18 +0,0 @@
<?php declare(strict_types=1);
namespace App\Enums;
use Illuminate\Cache\TaggedCache;
use Illuminate\Support\Facades\Cache;
enum CacheTag: string
{
case Project = 'project';
case ProjectTranslation = 'project_translation';
case DocumantationVersion = 'documantation_version';
public function getCache(): TaggedCache
{
return Cache::tags($this->value);
}
}
@@ -2,8 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Enums\CacheTag;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
final readonly class DocumentationVersion final readonly class DocumentationVersion
@@ -17,7 +17,7 @@ final readonly class DocumentationVersion
} }
$seconds = 3600; $seconds = 3600;
$version = CacheTag::DocumantationVersion->getCache()->remember(self::class . $project->id . '-' . $versionSlug, $seconds, function () use ($project, $versionSlug) { $version = Cache::remember(self::class . $project->id . '-' . $versionSlug, $seconds, function () use ($project, $versionSlug) {
return $project->documentationVersions()->where('slug', $versionSlug)->first() ?? false; return $project->documentationVersions()->where('slug', $versionSlug)->first() ?? false;
}); });
if ($version === false) { if ($version === false) {
@@ -2,8 +2,8 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Enums\CacheTag;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Closure; use Closure;
@@ -17,7 +17,7 @@ final class ProjectAndLanguage extends ProjectLanguage
} }
$seconds = 3600; $seconds = 3600;
$project = CacheTag::Project->getCache()->remember(self::class . $projectCode, $seconds, function () use ($projectCode) { $project = Cache::remember(self::class . $projectCode, $seconds, function () use ($projectCode) {
return $this->projectRepository->getProjectByCode($projectCode) ?? false; return $this->projectRepository->getProjectByCode($projectCode) ?? false;
}); });
if ($project === false) { if ($project === false) {
@@ -2,9 +2,9 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Enums\CacheTag;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
@@ -21,7 +21,7 @@ final class ProjectDomainAndLanguage extends ProjectLanguage
} }
$seconds = 3600; $seconds = 3600;
$project = CacheTag::Project->getCache()->remember(self::class . $httpHost, $seconds, function () use ($httpHost) { $project = Cache::remember(self::class . $httpHost, $seconds, function () use ($httpHost) {
return $this->projectRepository->getProjectByHttpHost($httpHost) ?? false; return $this->projectRepository->getProjectByHttpHost($httpHost) ?? false;
}); });
if ($project === false) { if ($project === false) {
@@ -2,13 +2,13 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Enums\CacheTag;
use App\Models\Project; use App\Models\Project;
use App\Repositories\ProjectLanguageRepository; use App\Repositories\ProjectLanguageRepository;
use App\Repositories\ProjectRepository; use App\Repositories\ProjectRepository;
use App\Repositories\ProjectTranslationRepository; use App\Repositories\ProjectTranslationRepository;
use App\Services\WebsiteTranslations; use App\Services\WebsiteTranslations;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
abstract class ProjectLanguage abstract class ProjectLanguage
{ {
@@ -21,7 +21,7 @@ abstract class ProjectLanguage
protected function getWebsiteTranslations(Project $project, ?string $languageCode): ?WebsiteTranslations protected function getWebsiteTranslations(Project $project, ?string $languageCode): ?WebsiteTranslations
{ {
$seconds = 3600 * 3; $seconds = 3600 * 3;
$language = CacheTag::Project->getCache()->remember(self::class . $project->id . '-' . $languageCode, $seconds, function () use ($project, $languageCode) { $language = Cache::remember(self::class . $project->id . '-' . $languageCode, $seconds, function () use ($project, $languageCode) {
return $this->projectLanguageRepository->getProjectLanguageByCodeOrDefault($project, $languageCode) ?? false; return $this->projectLanguageRepository->getProjectLanguageByCodeOrDefault($project, $languageCode) ?? false;
}); });
if ($language === false) { if ($language === false) {
@@ -34,7 +34,7 @@ abstract class ProjectLanguage
} }
$seconds = 3600 * 24; $seconds = 3600 * 24;
$translations = CacheTag::ProjectTranslation->getCache()->remember(self::class . '-translations-' . $project->id . '-' . $language->id, $seconds, function () use ($project, $language) { $translations = Cache::remember(self::class . '-translations-' . $project->id . '-' . $language->id, $seconds, function () use ($project, $language) {
return $this->projectTranslationRepository->getProjectTranslations($project->id, $language->id)->all()->pluck('text', 'code')->toArray(); return $this->projectTranslationRepository->getProjectTranslations($project->id, $language->id)->all()->pluck('text', 'code')->toArray();
}); });
@@ -34,7 +34,7 @@ final class StoreUpdateRequest extends FormRequest implements FormRequestDto
{ {
return new StoreUpdate( return new StoreUpdate(
title: $this->input('title'), title: $this->input('title'),
description: $this->input('description'), description: (string) $this->input('description', ''),
storages: $this->storages(), storages: $this->storages(),
isTranslateAutomatically: (bool) $this->input('translate-automatically', false), isTranslateAutomatically: (bool) $this->input('translate-automatically', false),
); );
@@ -26,7 +26,7 @@ final class UpdateRequest extends FormRequest implements FormRequestDto
{ {
return [ return [
'language.*.id' => ['required', 'numeric', 'min:1'], 'language.*.id' => ['required', 'numeric', 'min:1'],
'language.*.code' => ['nullable', 'string', 'min:2', 'max:50'], 'language.*.code' => ['nullable', 'string', 'min:2', 'max:50', 'required_with:language.*.source_language_id'],
'language.*.source_language_id' => ['nullable', 'numeric', 'min:1', 'different:language.*.id'], 'language.*.source_language_id' => ['nullable', 'numeric', 'min:1', 'different:language.*.id'],
]; ];
} }
@@ -37,6 +37,7 @@ final class Documentation extends Model
'slug', 'slug',
'is_public', 'is_public',
'category_id', 'category_id',
'sort',
]; ];
/** /**
@@ -5,7 +5,6 @@ namespace App\Services\Admin\Project;
use App\Dto\QuerySettingsDto; use App\Dto\QuerySettingsDto;
use App\Dto\Builder\DocumentationVersion as DocumentationVersionBuilderDto; use App\Dto\Builder\DocumentationVersion as DocumentationVersionBuilderDto;
use App\Dto\Service\Admin\Project\DocumentationVersion\StoreUpdate; use App\Dto\Service\Admin\Project\DocumentationVersion\StoreUpdate;
use App\Enums\CacheTag;
use App\Enums\DocumentationVersionStatus; use App\Enums\DocumentationVersionStatus;
use App\Models\DocumentationVersion; use App\Models\DocumentationVersion;
use App\Models\User; use App\Models\User;
@@ -141,7 +140,7 @@ final class DocumentationVersionService extends Service
$dataVersion = $this->getDataVersion($data); $dataVersion = $this->getDataVersion($data);
return $this->documentationVersionCommandHandler->handleStore($project, $dataVersion); return $this->documentationVersionCommandHandler->handleStore($project, $dataVersion);
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -178,7 +177,7 @@ final class DocumentationVersionService extends Service
$dataVersion = $this->getDataVersion($data); $dataVersion = $this->getDataVersion($data);
return $this->documentationVersionCommandHandler->handleUpdate($version, $dataVersion); return $this->documentationVersionCommandHandler->handleUpdate($version, $dataVersion);
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -207,7 +206,7 @@ final class DocumentationVersionService extends Service
DB::transaction(function () use ($version) { DB::transaction(function () use ($version) {
$this->documentationVersionCommandHandler->handleDestroy($version); $this->documentationVersionCommandHandler->handleDestroy($version);
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::DocumantationVersion); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -5,7 +5,6 @@ namespace App\Services\Admin\Project;
use App\Dto\Service\Admin\Project\Translation\Translations; use App\Dto\Service\Admin\Project\Translation\Translations;
use App\Dto\Service\Admin\Project\Translation\Translation; use App\Dto\Service\Admin\Project\Translation\Translation;
use App\Dto\Service\Admin\Project\Translation\Update; use App\Dto\Service\Admin\Project\Translation\Update;
use App\Enums\CacheTag;
use App\Jobs\Translate\ProcessTranslationText; use App\Jobs\Translate\ProcessTranslationText;
use App\Models\ProjectTranslation; use App\Models\ProjectTranslation;
use App\Models\User; use App\Models\User;
@@ -83,7 +82,7 @@ final class TranslationService extends Service
DB::transaction(function () use ($data, $project, $language) { DB::transaction(function () use ($data, $project, $language) {
$this->translationModelSyncCommand->execute($project, $language, $data->getTranslations()); $this->translationModelSyncCommand->execute($project, $language, $data->getTranslations());
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::ProjectTranslation); $this->clearCacheCommandHandler->all();
if (\config('translation_service.enable', false)) { if (\config('translation_service.enable', false)) {
$this->translateContent($projectId, $languageId, $data); $this->translateContent($projectId, $languageId, $data);
} }
@@ -5,7 +5,6 @@ namespace App\Services\Admin;
use App\Dto\Builder\Project as ProjectBuilderDto; use App\Dto\Builder\Project as ProjectBuilderDto;
use App\Dto\QuerySettingsDto; use App\Dto\QuerySettingsDto;
use App\Dto\Service\Admin\Project\StoreUpdate; use App\Dto\Service\Admin\Project\StoreUpdate;
use App\Enums\CacheTag;
use App\Enums\Morph; use App\Enums\Morph;
use App\Models\Project; use App\Models\Project;
use App\Models\ProjectLanguage; use App\Models\ProjectLanguage;
@@ -134,7 +133,7 @@ final class ProjectService extends Service
return $project; return $project;
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::Project); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -177,7 +176,7 @@ final class ProjectService extends Service
return $project; return $project;
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::Project); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -202,7 +201,7 @@ final class ProjectService extends Service
DB::transaction(function () use ($project) { DB::transaction(function () use ($project) {
$this->projectCommandHandler->handleDestroy($project); $this->projectCommandHandler->handleDestroy($project);
}); });
$this->clearCacheCommandHandler->byTag(CacheTag::Project); $this->clearCacheCommandHandler->all();
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($e); report($e);
return $this->errService(__('Server Error')); return $this->errService(__('Server Error'));
@@ -2,12 +2,12 @@
namespace App\Services; namespace App\Services;
use App\Enums\CacheTag; use Illuminate\Support\Facades\Cache;
final readonly class ClearCacheCommandHandler final readonly class ClearCacheCommandHandler
{ {
public function byTag(CacheTag $tag): void public function all(): void
{ {
$tag->getCache()->flush(); Cache::flush();
} }
} }
@@ -3,7 +3,6 @@
namespace App\Services\Site; namespace App\Services\Site;
use App\Dto\Service\Site\Documentation; use App\Dto\Service\Site\Documentation;
use App\Enums\CacheTag;
use App\Enums\DocumentationVersionStatus; use App\Enums\DocumentationVersionStatus;
use App\Models\DocumentationCategory; use App\Models\DocumentationCategory;
use App\Models\Documentation as ModelDocumentation; use App\Models\Documentation as ModelDocumentation;
@@ -22,6 +21,7 @@ use App\Dto\Builder\Documentation as DocumentationBuilderDto;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
final class DocumentationService extends Service final class DocumentationService extends Service
{ {
@@ -37,8 +37,7 @@ final class DocumentationService extends Service
if ($user?->cannot('viewAny', DocumentationVersion::class)) { if ($user?->cannot('viewAny', DocumentationVersion::class)) {
$isPublic = 1; $isPublic = 1;
} }
$version = CacheTag::DocumantationVersion->getCache() $version = Cache::remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
->remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
$versions = $project->documentationVersions() $versions = $project->documentationVersions()
->when($isPublic, function (Builder $query) { ->when($isPublic, function (Builder $query) {
$query->where('is_public', 1); $query->where('is_public', 1);
@@ -9,7 +9,7 @@ final readonly class ResizeCommandHandler
{ {
public function resize(Storage $storage, int $width, int $height): Storage public function resize(Storage $storage, int $width, int $height): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->width() < $width && $image->height() < $height) { if ($image->width() < $width && $image->height() < $height) {
return $storage; return $storage;
} }
@@ -23,7 +23,7 @@ final readonly class ResizeCommandHandler
public function width(Storage $storage, int $width): Storage public function width(Storage $storage, int $width): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->width() < $width) { if ($image->width() < $width) {
return $storage; return $storage;
} }
@@ -37,7 +37,7 @@ final readonly class ResizeCommandHandler
public function height(Storage $storage, int $height): Storage public function height(Storage $storage, int $height): Storage
{ {
$image = InterventionImage::read($storage->path); $image = InterventionImage::decodePath($storage->path);
if ($image->height() < $height) { if ($image->height() < $height) {
return $storage; return $storage;
} }
@@ -2,9 +2,9 @@
namespace app\View\Components\Site; namespace app\View\Components\Site;
use App\Enums\CacheTag;
use App\Models\Project; use App\Models\Project;
use App\Services\WebsiteTranslations; use App\Services\WebsiteTranslations;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\View\Component; use Illuminate\View\Component;
use Illuminate\View\View; use Illuminate\View\View;
@@ -24,7 +24,7 @@ final class ChooseLanguage extends Component
} }
$seconds = 3600 * 12; $seconds = 3600 * 12;
$languages = CacheTag::Project->getCache()->remember(self::class . $this->project->id, $seconds, function () { $languages = Cache::remember(self::class . $this->project->id, $seconds, function () {
return $this->project->languages; return $this->project->languages;
}); });
@@ -2,13 +2,12 @@
namespace App\View\Components\Site; namespace App\View\Components\Site;
use App\Enums\CacheTag;
use App\Models\DocumentationVersion; use App\Models\DocumentationVersion;
use App\Models\Project; use App\Models\Project;
use App\Models\User; use App\Models\User;
use App\Services\WebsiteTranslations; use App\Services\WebsiteTranslations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str; use Illuminate\Support\Facades\Cache;
use Illuminate\View\Component; use Illuminate\View\Component;
use Illuminate\View\View; use Illuminate\View\View;
@@ -29,8 +28,7 @@ final class ChooseVersion extends Component
} }
$seconds = 3600 * 12; $seconds = 3600 * 12;
$versions = CacheTag::DocumantationVersion->getCache() $versions = Cache::remember(self::class . $this->project->id . '-' . $isPublic ?? 0, $seconds, function () use ($isPublic) {
->remember(self::class . $this->project->id . '-' . $isPublic ?? 0, $seconds, function () use ($isPublic) {
return $this->project->documentationVersions() return $this->project->documentationVersions()
->when($isPublic, function (Builder $query) { ->when($isPublic, function (Builder $query) {
$query->where('is_public', 1); $query->where('is_public', 1);
+10 -2
View File
@@ -4,6 +4,7 @@ use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Symfony\Component\HttpFoundation\Response;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
->withRouting( ->withRouting(
@@ -19,8 +20,15 @@ return Application::configure(basePath: dirname(__DIR__))
}, },
) )
->withMiddleware(function (Middleware $middleware) { ->withMiddleware(function (Middleware $middleware) {
//
}) })
->withExceptions(function (Exceptions $exceptions) { ->withExceptions(function (Exceptions $exceptions) {
// $exceptions->respond(function (Response $response) {
if ($response->getStatusCode() === 419) {
return back()
->withInput()
->withErrors(['csrf' => __('http-statuses.csrfError')]);
}
return $response;
});
})->create(); })->create();
+31 -12
View File
@@ -1,4 +1,5 @@
{ {
"$schema": "https://getcomposer.org/schema.json",
"name": "laravel/laravel", "name": "laravel/laravel",
"type": "project", "type": "project",
"description": "The skeleton application for the Laravel framework.", "description": "The skeleton application for the Laravel framework.",
@@ -6,23 +7,22 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.3", "php": "^8.3",
"intervention/image-laravel": "^1.2", "intervention/image-laravel": "^4.0",
"kor-elf/captcha-rule-for-laravel": "^1.0", "kor-elf/captcha-rule-for-laravel": "^1.0",
"kor-elf/translate-laravel": "1.3.0", "kor-elf/translate-laravel": "^2.0",
"laravel/framework": "^11.0", "laravel/framework": "^13.8",
"laravel/tinker": "^2.9", "laravel/tinker": "^3.0",
"staudenmeir/laravel-adjacency-list": "^1.0" "staudenmeir/laravel-adjacency-list": "^1.26"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.13", "barryvdh/laravel-debugbar": "^4.3",
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",
"laravel-lang/common": "^6.2", "laravel/pail": "^1.2.5",
"laravel/pint": "^1.13", "laravel/pao": "^1.0.6",
"laravel/sail": "^1.26", "laravel/pint": "^1.27",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.0", "nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^10.5", "phpunit/phpunit": "^12.5.12"
"spatie/laravel-ignition": "^2.4"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@@ -37,6 +37,22 @@
} }
}, },
"scripts": { "scripts": {
"setup": [
"composer install",
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
"@php artisan key:generate",
"@php artisan migrate --force",
"npm install --ignore-scripts",
"npm run build"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1 --timeout=0\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
],
"test": [
"@php artisan config:clear --ansi @no_additional_args",
"@php artisan test"
],
"post-autoload-dump": [ "post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi" "@php artisan package:discover --ansi"
@@ -51,6 +67,9 @@
"@php artisan key:generate --ansi", "@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"", "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi" "@php artisan migrate --graceful --ansi"
],
"pre-package-uninstall": [
"Illuminate\\Foundation\\ComposerScripts::prePackageUninstall"
] ]
}, },
"extra": { "extra": {
+2252 -3946
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
<?php declare(strict_types=1);
return [
'Do not translate' => 'Do not translate',
'Mark as not to translate' => 'Mark as not to translate',
];
@@ -81,4 +81,5 @@ return [
'598' => 'Network Read Timeout Error', '598' => 'Network Read Timeout Error',
'599' => 'Network Connect Timeout Error', '599' => 'Network Connect Timeout Error',
'unknownError' => 'Unknown Error', 'unknownError' => 'Unknown Error',
'csrfError' => 'It looks like your session has expired. Please try again.',
]; ];
+6
View File
@@ -0,0 +1,6 @@
<?php declare(strict_types=1);
return [
'Do not translate' => 'Не переводить',
'Mark as not to translate' => 'Пометить как не переводить',
];
@@ -81,4 +81,5 @@ return [
'598' => 'Истекло время ожидания', '598' => 'Истекло время ожидания',
'599' => 'Истекло время подключения', '599' => 'Истекло время подключения',
'unknownError' => 'Неизвестная ошибка', 'unknownError' => 'Неизвестная ошибка',
'csrfError' => 'Похоже, что срок действия Вашей сессии истек. Пожалуйста, попробуйте еще раз.',
]; ];
@@ -95,14 +95,96 @@
xhr.send(formData); xhr.send(formData);
}); });
@endif @endif
tinymce.PluginManager.add('translateNo', (editor) => {
const ATTR = 'translate';
const VALUE = 'no';
const isTranslateNo = (node) =>
node && node.nodeType === 1 && node.getAttribute(ATTR) === VALUE;
const toggleTranslateNo = () => {
const selectedNode = editor.selection.getNode();
if (isTranslateNo(selectedNode)) {
// Remove translate="no", expand span
if (selectedNode.tagName === 'SPAN') {
editor.dom.remove(selectedNode, true); // true = сохранить детей
} else {
editor.dom.setAttrib(selectedNode, ATTR, null);
}
return;
}
// If inside translate="no", remove the mark
const wrapper = editor.dom.getParent(selectedNode, `[${ATTR}="${VALUE}"]`);
if (wrapper) {
if (wrapper.tagName === 'SPAN') {
editor.dom.remove(wrapper, true);
} else {
editor.dom.setAttrib(wrapper, ATTR, null);
}
return;
}
// Otherwise, wrap the selection
editor.formatter.register('translateNo', {
inline: 'span',
attributes: { [ATTR]: VALUE },
remove: 'all'
});
editor.formatter.apply('translateNo');
};
editor.ui.registry.addToggleButton('translateNo', {
icon: 'translate',
tooltip: '{{ __('editor.Do not translate') }}',
onAction: toggleTranslateNo,
onSetup: (api) => {
const setActive = () => {
const node = editor.selection.getNode();
api.setActive(
isTranslateNo(node) ||
!!editor.dom.getParent(node, `[${ATTR}="${VALUE}"]`)
);
};
editor.on('NodeChange', setActive);
return () => editor.off('NodeChange', setActive);
}
});
editor.ui.registry.addMenuItem('translateNo', {
text: '{{ __('editor.Mark as not to translate') }}',
icon: 'translate',
onAction: toggleTranslateNo
});
});
tinymce.init({ tinymce.init({
content_style: `
span[translate="no"] {
background: rgba(255, 215, 0, 0.35);
outline: 1px dashed #e0a800;
position: relative;
}
span[translate="no"]:hover::before {
position: absolute;
content: "{{ __('editor.Do not translate') }}";
left: 0;
bottom: 100%;
background: #e0a800;
white-space: nowrap;
padding: 0.25rem;
border: 1px solid #ddd;
}
`,
selector: '#{{ $tinyId }}', selector: '#{{ $tinyId }}',
@if(in_array(app()->getLocale(), ['ru'], true)) @if(in_array(app()->getLocale(), ['ru'], true))
language: '{{ app()->getLocale() }}', language: '{{ app()->getLocale() }}',
@endif @endif
license_key: '{{ $tinymceLicenseKey }}', license_key: '{{ $tinymceLicenseKey }}',
plugins: 'advlist code emoticons link lists table codesample media my-image', plugins: 'advlist code emoticons link lists table codesample media my-image translateNo',
toolbar: 'bold italic | bullist numlist | link image emoticons media codesample', toolbar: 'bold italic | bullist numlist | link image emoticons media codesample translateNo',
referrer_policy: 'origin', referrer_policy: 'origin',
@if($storageUpload !== null) @if($storageUpload !== null)
images_upload_handler: imageUpload, images_upload_handler: imageUpload,
@@ -39,9 +39,9 @@
<nav id="menu"> <nav id="menu">
<div class="menu__title">{{ $websiteTranslations->translate('site.Menu') }}</div> <div class="menu__title">{{ $websiteTranslations->translate('site.Menu') }}</div>
<ul> <ul>
<li><a href="{{ \App\Enums\Site\ProjectSection::Home->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['home', 'language.home', 'project.home', 'project.language.home'])])>{{ $websiteTranslations->translate('site.About project') }}</a></li> <li><a href="{{ \App\Enums\Site\ProjectSection::Home->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['home', 'language.home', 'project.home', 'project.language.home', 'home-language'])])>{{ $websiteTranslations->translate('site.About project') }}</a></li>
<li><a href="{{ \App\Enums\Site\ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['documentation', 'documentation.home'])])>{{ $websiteTranslations->translate('site.Documentation') }}</a></li> <li><a href="{{ \App\Enums\Site\ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['documentation.*'])])>{{ $websiteTranslations->translate('site.Documentation') }}</a></li>
<li><a href="{{ \App\Enums\Site\ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['feedback', 'language.feedback', 'project.feedback', 'project.language.feedback'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li> <li><a href="{{ \App\Enums\Site\ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()) }}" @class(['active' => request()->route()->named(['feedback', 'language.feedback', 'project.feedback', 'project.language.feedback', 'feedback-language'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li>
</ul> </ul>
</nav> </nav>
<div class="section-container"> <div class="section-container">
+1 -1
View File
@@ -19,7 +19,7 @@ COPY --from=unit_builder /var/lib/unit/ /var/lib/unit/
COPY docker/unit-config.json /docker-entrypoint.d/config.json COPY docker/unit-config.json /docker-entrypoint.d/config.json
RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freetype oniguruma libzip \ RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freetype oniguruma libzip jq \
&& apk add --no-cache --virtual .phpize-deps icu-dev libpng-dev bzip2-dev libwebp-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libzip-dev pcre2-dev ${PHPIZE_DEPS} \ && apk add --no-cache --virtual .phpize-deps icu-dev libpng-dev bzip2-dev libwebp-dev libjpeg-turbo-dev freetype-dev oniguruma-dev libzip-dev pcre2-dev ${PHPIZE_DEPS} \
&& docker-php-ext-configure intl --enable-intl && \ && docker-php-ext-configure intl --enable-intl && \
docker-php-ext-configure bcmath --enable-bcmath && \ docker-php-ext-configure bcmath --enable-bcmath && \
+14 -6
View File
@@ -42,6 +42,20 @@ if [ "$role" = "app" ]; then
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then
echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..." echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..."
if [[ -n "${UNIT_SOURCE:-}" ]]; then
config="/docker-entrypoint.d/config.json"
tmp="$(mktemp)"
jq --arg src "${UNIT_SOURCE}" '
.listeners["*:9000"].forwarded.source =
( $src
| split(",")
| map( gsub("^\\s+|\\s+$"; "") ) # trim пробелы
| map( select(. != "") ) # убрать пустые
)
' "$config" > "$tmp"
mv "$tmp" "$config"
fi
echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..." echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do
echo "$0: Uploading certificates bundle: $f" echo "$0: Uploading certificates bundle: $f"
@@ -60,12 +74,6 @@ if [ "$role" = "app" ]; then
curl_put $f "config" curl_put $f "config"
done done
if [ ! -z ${UNIT_SOURCE+x} ]
then
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
fi
echo "$0: Looking for shell scripts in /docker-entrypoint.d/..." echo "$0: Looking for shell scripts in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do
echo "$0: Launching $f"; echo "$0: Launching $f";
+14 -6
View File
@@ -42,6 +42,20 @@ if [ "$role" = "app" ]; then
if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -print -quit 2>/dev/null | /bin/grep -q .; then
echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..." echo "$0: /docker-entrypoint.d/ is not empty, applying initial configuration..."
if [[ -n "${UNIT_SOURCE:-}" ]]; then
config="/docker-entrypoint.d/config.json"
tmp="$(mktemp)"
jq --arg src "${UNIT_SOURCE}" '
.listeners["*:9000"].forwarded.source =
( $src
| split(",")
| map( gsub("^\\s+|\\s+$"; "") ) # trim пробелы
| map( select(. != "") ) # убрать пустые
)
' "$config" > "$tmp"
mv "$tmp" "$config"
fi
echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..." echo "$0: Looking for certificate bundles in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.pem"); do
echo "$0: Uploading certificates bundle: $f" echo "$0: Uploading certificates bundle: $f"
@@ -60,12 +74,6 @@ if [ "$role" = "app" ]; then
curl_put $f "config" curl_put $f "config"
done done
if [ ! -z ${UNIT_SOURCE+x} ]
then
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
fi
echo "$0: Looking for shell scripts in /docker-entrypoint.d/..." echo "$0: Looking for shell scripts in /docker-entrypoint.d/..."
for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do for f in $(/usr/bin/find /docker-entrypoint.d/ -type f -name "*.sh"); do
echo "$0: Launching $f"; echo "$0: Launching $f";
+2 -2
View File
@@ -1,4 +1,4 @@
version: '3.7' #version: '3.7'
services: services:
app: app:
build: build:
@@ -16,7 +16,7 @@ services:
- ./app/application:/var/www/html - ./app/application:/var/www/html
environment: environment:
CONTAINER_ROLE: app CONTAINER_ROLE: app
UNIT_SOURCE: '"172.16.0.0/12"' UNIT_SOURCE: "172.16.0.0/12"
queue: queue:
build: build:
+8 -8
View File
@@ -1,8 +1,8 @@
version: '3.7' #version: '3.7'
services: services:
app: app:
# image: korelf/my-projects-website:0.4.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.4.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db
@@ -13,15 +13,15 @@ services:
env_file: app/.env env_file: app/.env
environment: environment:
CONTAINER_ROLE: app CONTAINER_ROLE: app
UNIT_SOURCE: '"172.16.0.0/12"' UNIT_SOURCE: "172.16.0.0/12"
volumes: volumes:
- ./app/storage/app:/var/www/html/storage/app - ./app/storage/app:/var/www/html/storage/app
- ./app/storage/logs:/var/www/html/storage/logs - ./app/storage/logs:/var/www/html/storage/logs
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json # - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
queue: queue:
# image: korelf/my-projects-website:0.4.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.4.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db
@@ -35,8 +35,8 @@ services:
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json # - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
scheduler: scheduler:
# image: korelf/my-projects-website:0.4.0 # docker hub # image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.4.0 # MDHub image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# restart: always # restart: always
depends_on: depends_on:
- db - db
+3 -1
View File
@@ -1,4 +1,4 @@
version: '3.7' #version: '3.7'
services: services:
app: app:
build: build:
@@ -13,6 +13,8 @@ services:
- ${DOCKER_APP_PORT}:9000 - ${DOCKER_APP_PORT}:9000
volumes: volumes:
- ./app/application:/var/www/html - ./app/application:/var/www/html
environment:
CONTAINER_ROLE: app
queue: queue:
build: build: