Compare commits
17 Commits
21026cdf52
...
0.2.1
Author | SHA1 | Date | |
---|---|---|---|
417ce35fc8 | |||
da5201dd9a
|
|||
2910509218
|
|||
74f7b88bce
|
|||
6998424b78
|
|||
05f566c115
|
|||
c5fc106761
|
|||
d7dc80cca4
|
|||
6d3891979c
|
|||
f986e0396d
|
|||
9f6924935d
|
|||
e74456ee2f
|
|||
42701a24db
|
|||
78e6a1e396
|
|||
b6e1c50486
|
|||
3bc508b8b0
|
|||
4b6cf902ff |
14
app/.dockerignore
Normal file
14
app/.dockerignore
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
**/.env
|
||||||
|
**/*.env
|
||||||
|
**/.env.example
|
||||||
|
**/storage/app/*
|
||||||
|
**/storage/debugbar
|
||||||
|
**/storage/framework/cache/*
|
||||||
|
**/storage/framework/sessions/*
|
||||||
|
**/storage/framework/views/*
|
||||||
|
**/storage/framework/testing/*
|
||||||
|
**/storage/logs/*
|
||||||
|
**/vendor/
|
||||||
|
**/node_modules/
|
||||||
|
**/public/build/
|
||||||
|
**/public/storage
|
@@ -11,7 +11,6 @@ CAPTCHA_STATIC_PATH=http://your-domain-captcha-or-IP:8081/captcha
|
|||||||
CAPTCHA_PUBLIC_TOKEN=
|
CAPTCHA_PUBLIC_TOKEN=
|
||||||
|
|
||||||
APP_FORCE_HTTPS=false
|
APP_FORCE_HTTPS=false
|
||||||
#UNIT_SOURCE="\"172.16.0.0/12\""
|
|
||||||
|
|
||||||
APP_DEFAULT_LOCALE=ru
|
APP_DEFAULT_LOCALE=ru
|
||||||
APP_FAKER_LOCALE=ru_RU
|
APP_FAKER_LOCALE=ru_RU
|
||||||
|
1
app/application/.gitignore
vendored
1
app/application/.gitignore
vendored
@@ -8,6 +8,7 @@
|
|||||||
.env
|
.env
|
||||||
.env.backup
|
.env.backup
|
||||||
.env.production
|
.env.production
|
||||||
|
.env.testing
|
||||||
.phpunit.result.cache
|
.phpunit.result.cache
|
||||||
Homestead.json
|
Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
|
@@ -2,14 +2,22 @@
|
|||||||
|
|
||||||
namespace App\Dto\Builder;
|
namespace App\Dto\Builder;
|
||||||
|
|
||||||
|
use App\Dto\Builder\DocumentationCategory\Category;
|
||||||
|
|
||||||
final readonly class Documentation
|
final readonly class Documentation
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ?bool $isPublic = null,
|
private ?bool $isPublic = null,
|
||||||
|
private ?Category $categoryId = null,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public function isPublic(): ?bool
|
public function isPublic(): ?bool
|
||||||
{
|
{
|
||||||
return $this->isPublic;
|
return $this->isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCategoryId(): ?Category
|
||||||
|
{
|
||||||
|
return $this->categoryId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,14 +2,22 @@
|
|||||||
|
|
||||||
namespace App\Dto\Builder;
|
namespace App\Dto\Builder;
|
||||||
|
|
||||||
|
use App\Dto\Builder\DocumentationCategory\Category;
|
||||||
|
|
||||||
final readonly class DocumentationCategory
|
final readonly class DocumentationCategory
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ?bool $isPublic = null,
|
private ?bool $isPublic = null,
|
||||||
|
private ?Category $parentId = null,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public function isPublic(): ?bool
|
public function isPublic(): ?bool
|
||||||
{
|
{
|
||||||
return $this->isPublic;
|
return $this->isPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getParentId(): ?Category
|
||||||
|
{
|
||||||
|
return $this->parentId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Builder\DocumentationCategory;
|
||||||
|
|
||||||
|
final readonly class Category
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ?int $categoryId,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getCategoryId(): ?int
|
||||||
|
{
|
||||||
|
return $this->categoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCategoryNull(): bool
|
||||||
|
{
|
||||||
|
return $this->getCategoryId() === null;
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Dto\Service\Admin\Project\Translation;
|
namespace App\Dto\Service\Admin\Project\Translation;
|
||||||
|
|
||||||
|
use App\Enums\DocumentationVersionStatus;
|
||||||
use App\Exceptions\Dto\Admin\Project\Transaction\TranslationsException;
|
use App\Exceptions\Dto\Admin\Project\Transaction\TranslationsException;
|
||||||
|
|
||||||
final class Translations
|
final class Translations
|
||||||
@@ -23,7 +24,7 @@ final class Translations
|
|||||||
|
|
||||||
public static function getTranslationCodes(): array
|
public static function getTranslationCodes(): array
|
||||||
{
|
{
|
||||||
return [
|
$translations = [
|
||||||
'site.Menu',
|
'site.Menu',
|
||||||
'site.Powered by service',
|
'site.Powered by service',
|
||||||
'site.About project',
|
'site.About project',
|
||||||
@@ -38,6 +39,17 @@ final class Translations
|
|||||||
'site.attributes.message',
|
'site.attributes.message',
|
||||||
'site.Message sent successfully',
|
'site.Message sent successfully',
|
||||||
'Server Error',
|
'Server Error',
|
||||||
|
'site.Documentation',
|
||||||
|
'site.Documentation not created',
|
||||||
|
'site.Choose version',
|
||||||
|
'site.alert-status-not-supported',
|
||||||
|
'site.alert-status-future',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
foreach (DocumentationVersionStatus::cases() as $status) {
|
||||||
|
$translations[] = $status->getCodeForTranslation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $translations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
app/application/app/Dto/Service/Site/Documentation.php
Normal file
47
app/application/app/Dto/Service/Site/Documentation.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Dto\Service\Site;
|
||||||
|
|
||||||
|
use App\Models\DocumentationVersion;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\WebsiteTranslations;
|
||||||
|
|
||||||
|
final readonly class Documentation
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private Project $project,
|
||||||
|
private DocumentationVersion $version,
|
||||||
|
private WebsiteTranslations $websiteTranslations,
|
||||||
|
private ?User $user = null,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getProject(): Project
|
||||||
|
{
|
||||||
|
return $this->project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVersion(): DocumentationVersion
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWebsiteTranslations(): WebsiteTranslations
|
||||||
|
{
|
||||||
|
return $this->websiteTranslations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toArray(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'project' => $this->getProject(),
|
||||||
|
'version' => $this->getVersion(),
|
||||||
|
'websiteTranslations' => $this->getWebsiteTranslations(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -9,6 +9,7 @@ enum CacheTag: string
|
|||||||
{
|
{
|
||||||
case Project = 'project';
|
case Project = 'project';
|
||||||
case ProjectTranslation = 'project_translation';
|
case ProjectTranslation = 'project_translation';
|
||||||
|
case DocumantationVersion = 'documantation_version';
|
||||||
|
|
||||||
public function getCache(): TaggedCache
|
public function getCache(): TaggedCache
|
||||||
{
|
{
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Enums;
|
namespace App\Enums;
|
||||||
|
|
||||||
|
use App\Services\WebsiteTranslations;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
enum DocumentationVersionStatus: int
|
enum DocumentationVersionStatus: int
|
||||||
@@ -11,9 +12,18 @@ enum DocumentationVersionStatus: int
|
|||||||
case CurrentVersion = 100;
|
case CurrentVersion = 100;
|
||||||
case FutureVersion = 150;
|
case FutureVersion = 150;
|
||||||
|
|
||||||
public function getTitle(): string
|
public function getTitle(?WebsiteTranslations $websiteTranslations = null): string
|
||||||
{
|
{
|
||||||
return __('version-status.' . $this->name);
|
if (\is_null($websiteTranslations)) {
|
||||||
|
return __($this->getCodeForTranslation());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $websiteTranslations->translate($this->getCodeForTranslation());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCodeForTranslation(): string
|
||||||
|
{
|
||||||
|
return 'version-status.' . $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function toArray(): array
|
public static function toArray(): array
|
||||||
|
@@ -5,15 +5,18 @@ namespace App\Enums\Site;
|
|||||||
use App\Models\Project;
|
use App\Models\Project;
|
||||||
use App\Models\ProjectLanguage;
|
use App\Models\ProjectLanguage;
|
||||||
|
|
||||||
enum ProjectSection
|
enum ProjectSection: string
|
||||||
{
|
{
|
||||||
case Home;
|
case Home = 'home';
|
||||||
case Feedback;
|
case Feedback = 'feedback';
|
||||||
case FeedbackSend;
|
case FeedbackSend = 'feedback.send';
|
||||||
|
case Documentation = 'documentation';
|
||||||
|
case DocumentationVersion = 'documentation.version';
|
||||||
|
case DocumentationCategory = 'documentation.category';
|
||||||
|
case DocumentationView = 'documentation.view';
|
||||||
|
|
||||||
public function url(Project $project, ?ProjectLanguage $language = null): string
|
public function url(Project $project, ?ProjectLanguage $language = null, array $parameters = []): string
|
||||||
{
|
{
|
||||||
$parameters = [];
|
|
||||||
$prefixProject = '';
|
$prefixProject = '';
|
||||||
if ($project->http_host === null) {
|
if ($project->http_host === null) {
|
||||||
$prefixProject = 'project.';
|
$prefixProject = 'project.';
|
||||||
@@ -26,12 +29,7 @@ enum ProjectSection
|
|||||||
$prefixLanguage = '-language';
|
$prefixLanguage = '-language';
|
||||||
}
|
}
|
||||||
|
|
||||||
$route = match ($this) {
|
$route = \route($prefixProject . $this->value . $prefixLanguage, $parameters, false);
|
||||||
self::Home => \route($prefixProject . 'home' . $prefixLanguage, $parameters, false),
|
|
||||||
|
|
||||||
self::Feedback => \route($prefixProject . 'feedback' . $prefixLanguage, $parameters, false),
|
|
||||||
self::FeedbackSend => \route($prefixProject . 'feedback.send' . $prefixLanguage, $parameters, false),
|
|
||||||
};
|
|
||||||
|
|
||||||
return $project->http_host . $route;
|
return $project->http_host . $route;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Exceptions\Services\Rule;
|
||||||
|
|
||||||
|
final class RoleSyncPermissionsCommandHandlerException extends \Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,96 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Site;
|
||||||
|
|
||||||
|
use App\Dto\Service\Site\Documentation;
|
||||||
|
use App\Services\Site\DocumentationService;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
final class DocumentationController extends Controller
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentationService $documentationService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function defaultVersion(Request $request): RedirectResponse | View
|
||||||
|
{
|
||||||
|
$project = $request->get('project');
|
||||||
|
$websiteTranslations = $request->get('websiteTranslations');
|
||||||
|
|
||||||
|
$result = $this->documentationService->defaultVersion($project, $request->user());
|
||||||
|
if ($result->isError()) {
|
||||||
|
if ($result->getCode() === 404) {
|
||||||
|
return view('site.projects.documentation.no-default-version', [
|
||||||
|
'project' => $project,
|
||||||
|
'websiteTranslations' => $websiteTranslations,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = \App\Enums\Site\ProjectSection::DocumentationVersion->url($project, $websiteTranslations->getLanguage(), ['version' => $result->getVersion()->slug]);
|
||||||
|
/**
|
||||||
|
* 302 redirect because the documentation version can change at any time.
|
||||||
|
*/
|
||||||
|
return redirect($url, 302);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(Request $request): View
|
||||||
|
{
|
||||||
|
$documentation = new Documentation(
|
||||||
|
project: $request->get('project'),
|
||||||
|
version: $request->get('version'),
|
||||||
|
websiteTranslations: $request->get('websiteTranslations'),
|
||||||
|
user: $request->user(),
|
||||||
|
);
|
||||||
|
$result = $this->documentationService->index($documentation);
|
||||||
|
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('site.projects.documentation.index', $result->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function category(string $slug, Request $request): View
|
||||||
|
{
|
||||||
|
$documentation = new Documentation(
|
||||||
|
project: $request->get('project'),
|
||||||
|
version: $request->get('version'),
|
||||||
|
websiteTranslations: $request->get('websiteTranslations'),
|
||||||
|
user: $request->user(),
|
||||||
|
);
|
||||||
|
$result = $this->documentationService->category($slug, $documentation);
|
||||||
|
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
if ($result->isTranslation()) {
|
||||||
|
return $this->viewPageWithoutTranslation($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('site.projects.documentation.category', $result->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(string $slug, Request $request): View
|
||||||
|
{
|
||||||
|
$documentation = new Documentation(
|
||||||
|
project: $request->get('project'),
|
||||||
|
version: $request->get('version'),
|
||||||
|
websiteTranslations: $request->get('websiteTranslations'),
|
||||||
|
user: $request->user(),
|
||||||
|
);
|
||||||
|
$result = $this->documentationService->view($slug, $documentation);
|
||||||
|
|
||||||
|
if ($result->isError()) {
|
||||||
|
$this->errors($result);
|
||||||
|
}
|
||||||
|
if ($result->isTranslation()) {
|
||||||
|
return $this->viewPageWithoutTranslation($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('site.projects.documentation.view', $result->getData());
|
||||||
|
}
|
||||||
|
}
|
40
app/application/app/Http/Middleware/DocumentationVersion.php
Normal file
40
app/application/app/Http/Middleware/DocumentationVersion.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Enums\CacheTag;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
final readonly class DocumentationVersion
|
||||||
|
{
|
||||||
|
public function handle(Request $request, \Closure $next): Response
|
||||||
|
{
|
||||||
|
$project = $request->get('project');
|
||||||
|
$versionSlug = $request->route()?->parameter('version');
|
||||||
|
if ($versionSlug === null || $project === null) {
|
||||||
|
\abort(Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
$seconds = 3600;
|
||||||
|
$version = CacheTag::DocumantationVersion->getCache()->remember(self::class . $project->id . '-' . $versionSlug, $seconds, function () use ($project, $versionSlug) {
|
||||||
|
return $project->documentationVersions()->where('slug', $versionSlug)->first() ?? false;
|
||||||
|
});
|
||||||
|
if ($version === false) {
|
||||||
|
\abort(Response::HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($request->route()->parameters['version']);
|
||||||
|
|
||||||
|
$request->attributes->set('version', $version);
|
||||||
|
|
||||||
|
if (
|
||||||
|
$version->is_public === false
|
||||||
|
&& ( $request->user() === null || $request->user()->cannot('view', $version) )
|
||||||
|
) {
|
||||||
|
\abort(Response::HTTP_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
@@ -20,6 +20,13 @@ final class IsProject
|
|||||||
\abort(Response::HTTP_NOT_FOUND);
|
\abort(Response::HTTP_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
$project->is_public === false
|
||||||
|
&& ( $request->user() === null || $request->user()->cannot('view', $project) )
|
||||||
|
) {
|
||||||
|
\abort(Response::HTTP_FORBIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\Scopes\SortScope;
|
||||||
|
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
@@ -9,6 +11,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
|
#[ScopedBy([SortScope::class])]
|
||||||
final class Documentation extends Model
|
final class Documentation extends Model
|
||||||
{
|
{
|
||||||
use HasFactory, SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\DocumentationVersionStatus;
|
use App\Enums\DocumentationVersionStatus;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
@@ -37,6 +38,16 @@ final class DocumentationVersion extends Model
|
|||||||
'status',
|
'status',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "booted" method of the model.
|
||||||
|
*/
|
||||||
|
protected static function booted(): void
|
||||||
|
{
|
||||||
|
static::addGlobalScope('status', function (Builder $builder) {
|
||||||
|
$builder->orderBy('status', 'desc');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the attributes that should be cast.
|
* Get the attributes that should be cast.
|
||||||
*
|
*
|
||||||
|
@@ -59,6 +59,8 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
Route::pattern('language', '[a-z_]+');
|
Route::pattern('language', '[a-z_]+');
|
||||||
Route::pattern('project', '[a-z0-9_-]+');
|
Route::pattern('project', '[a-z0-9_-]+');
|
||||||
|
Route::pattern('slug', '[a-z0-9._-]+');
|
||||||
|
Route::pattern('version', '[a-z0-9._-]+');
|
||||||
|
|
||||||
$this->configureRateLimiting();
|
$this->configureRateLimiting();
|
||||||
Gate::define('AdminPanel', [\App\Policies\AdminPanel::class, 'view']);
|
Gate::define('AdminPanel', [\App\Policies\AdminPanel::class, 'view']);
|
||||||
|
@@ -4,6 +4,7 @@ namespace App\Repositories;
|
|||||||
|
|
||||||
use App\Contracts\Search;
|
use App\Contracts\Search;
|
||||||
use App\Models\DocumentationCategory;
|
use App\Models\DocumentationCategory;
|
||||||
|
use App\Models\DocumentationVersion;
|
||||||
use App\Models\ProjectLanguage;
|
use App\Models\ProjectLanguage;
|
||||||
use App\Services\DocumentationCategory\BuilderCommand;
|
use App\Services\DocumentationCategory\BuilderCommand;
|
||||||
use App\Services\Search\CreateSearchInstanceCommand;
|
use App\Services\Search\CreateSearchInstanceCommand;
|
||||||
@@ -35,9 +36,19 @@ final readonly class DocumentationCategoryRepository
|
|||||||
return DocumentationCategory::query()->where('id', $id)->first();
|
return DocumentationCategory::query()->where('id', $id)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCategoryByCode(string $code): ?DocumentationCategory
|
public function getCategoryBySlugWithContent(string $slug, int $versionId, ProjectLanguage $language): ?DocumentationCategory
|
||||||
{
|
{
|
||||||
return DocumentationCategory::query()->where('code', $code)->first();
|
$with = [
|
||||||
|
'content' => function (HasOne $hasOne) use ($language) {
|
||||||
|
$hasOne->where('language_id', $language->id);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return DocumentationCategory::query()
|
||||||
|
->where('version_id', $versionId)
|
||||||
|
->where('slug', $slug)
|
||||||
|
->with($with)
|
||||||
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isExistsSlug(int $versionId, string $slug, ?int $exceptId = null): bool
|
public function isExistsSlug(int $versionId, string $slug, ?int $exceptId = null): bool
|
||||||
|
@@ -5,9 +5,11 @@ namespace App\Repositories;
|
|||||||
use App\Dto\Builder\Documentation as DocumentationBuilderDto;
|
use App\Dto\Builder\Documentation as DocumentationBuilderDto;
|
||||||
use App\Contracts\Search;
|
use App\Contracts\Search;
|
||||||
use App\Models\Documentation;
|
use App\Models\Documentation;
|
||||||
|
use App\Models\ProjectLanguage;
|
||||||
use App\Services\Documentation\BuilderCommand;
|
use App\Services\Documentation\BuilderCommand;
|
||||||
use App\Services\Search\CreateSearchInstanceCommand;
|
use App\Services\Search\CreateSearchInstanceCommand;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
final readonly class DocumentationRepository
|
final readonly class DocumentationRepository
|
||||||
@@ -32,9 +34,19 @@ final readonly class DocumentationRepository
|
|||||||
return Documentation::query()->where('id', $id)->first();
|
return Documentation::query()->where('id', $id)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDocumentationByCode(string $code): ?Documentation
|
public function getDocumentationBySlugWithContent(string $slug, int $versionId, ProjectLanguage $language): ?Documentation
|
||||||
{
|
{
|
||||||
return Documentation::query()->where('code', $code)->first();
|
$with = [
|
||||||
|
'content' => function (HasOne $hasOne) use ($language) {
|
||||||
|
$hasOne->where('language_id', $language->id);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return Documentation::query()
|
||||||
|
->where('version_id', $versionId)
|
||||||
|
->where('slug', $slug)
|
||||||
|
->with($with)
|
||||||
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isExistsSlug(int $versionId, string $slug, ?int $exceptId = null): bool
|
public function isExistsSlug(int $versionId, string $slug, ?int $exceptId = null): bool
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\ServiceResults\Site\DocumentationService;
|
||||||
|
use App\Models\DocumentationVersion;
|
||||||
|
use App\ServiceResults\ServiceResult;
|
||||||
|
|
||||||
|
final class DefaultVersion extends ServiceResult
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentationVersion $version,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function getVersion(): DocumentationVersion
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
}
|
@@ -5,6 +5,7 @@ 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;
|
||||||
@@ -14,6 +15,7 @@ use App\ServiceResults\ServiceResultArray;
|
|||||||
use App\ServiceResults\ServiceResultError;
|
use App\ServiceResults\ServiceResultError;
|
||||||
use App\ServiceResults\ServiceResultSuccess;
|
use App\ServiceResults\ServiceResultSuccess;
|
||||||
use App\ServiceResults\StoreUpdateResult;
|
use App\ServiceResults\StoreUpdateResult;
|
||||||
|
use App\Services\ClearCacheCommandHandler;
|
||||||
use App\Services\DocumentationVersion\DocumentationVersionCommandHandler;
|
use App\Services\DocumentationVersion\DocumentationVersionCommandHandler;
|
||||||
use App\Services\Service;
|
use App\Services\Service;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@@ -24,6 +26,7 @@ final class DocumentationVersionService extends Service
|
|||||||
private readonly ProjectRepository $projectRepository,
|
private readonly ProjectRepository $projectRepository,
|
||||||
private readonly DocumentationVersionRepository $documentationVersionRepository,
|
private readonly DocumentationVersionRepository $documentationVersionRepository,
|
||||||
private readonly DocumentationVersionCommandHandler $documentationVersionCommandHandler,
|
private readonly DocumentationVersionCommandHandler $documentationVersionCommandHandler,
|
||||||
|
private readonly ClearCacheCommandHandler $clearCacheCommandHandler,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public function index(int $projectId, DocumentationVersionBuilderDto $documentationVersionBuilderDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
|
public function index(int $projectId, DocumentationVersionBuilderDto $documentationVersionBuilderDto, QuerySettingsDto $querySettingsDto, User $user): ServiceResultError | ServiceResultArray
|
||||||
@@ -138,6 +141,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);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
report($e);
|
report($e);
|
||||||
return $this->errService(__('Server Error'));
|
return $this->errService(__('Server Error'));
|
||||||
@@ -174,6 +178,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);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
report($e);
|
report($e);
|
||||||
return $this->errService(__('Server Error'));
|
return $this->errService(__('Server Error'));
|
||||||
@@ -202,6 +207,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);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
report($e);
|
report($e);
|
||||||
return $this->errService(__('Server Error'));
|
return $this->errService(__('Server Error'));
|
||||||
|
@@ -10,10 +10,12 @@ final readonly class BuilderCommand
|
|||||||
{
|
{
|
||||||
public function execute(Relation | Builder $query, DocumentationBuilderDto $documentationBuilderDto): Relation | Builder
|
public function execute(Relation | Builder $query, DocumentationBuilderDto $documentationBuilderDto): Relation | Builder
|
||||||
{
|
{
|
||||||
if ($documentationBuilderDto->isPublic() !== null) {
|
return $query
|
||||||
|
->when($documentationBuilderDto->isPublic(), function (Builder $query) use ($documentationBuilderDto) {
|
||||||
$query->where('is_public', $documentationBuilderDto->isPublic());
|
$query->where('is_public', $documentationBuilderDto->isPublic());
|
||||||
}
|
})
|
||||||
|
->when($documentationBuilderDto->getCategoryId(), function (Builder $query) use ($documentationBuilderDto) {
|
||||||
return $query;
|
$query->where('category_id', $documentationBuilderDto->getCategoryId()->getCategoryId());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,10 +10,12 @@ final readonly class BuilderCommand
|
|||||||
{
|
{
|
||||||
public function execute(Relation | Builder $query, DocumentationCategoryBuilderDto $documentationCategoryBuilderDto): Relation | Builder
|
public function execute(Relation | Builder $query, DocumentationCategoryBuilderDto $documentationCategoryBuilderDto): Relation | Builder
|
||||||
{
|
{
|
||||||
if ($documentationCategoryBuilderDto->isPublic() !== null) {
|
return $query
|
||||||
|
->when($documentationCategoryBuilderDto->isPublic(), function (Builder $query) use ($documentationCategoryBuilderDto) {
|
||||||
$query->where('is_public', $documentationCategoryBuilderDto->isPublic());
|
$query->where('is_public', $documentationCategoryBuilderDto->isPublic());
|
||||||
}
|
})
|
||||||
|
->when($documentationCategoryBuilderDto->getParentId(), function (Builder $query) use ($documentationCategoryBuilderDto) {
|
||||||
return $query;
|
$query->where('parent_id', $documentationCategoryBuilderDto->getParentId()->getCategoryId());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Services\Role;
|
namespace App\Services\Role;
|
||||||
|
|
||||||
use App\Enums\Permission;
|
use App\Enums\Permission;
|
||||||
use App\Exceptions\Rule\RoleSyncPermissionsCommandHandlerException;
|
use App\Exceptions\Services\Rule\RoleSyncPermissionsCommandHandlerException;
|
||||||
use App\Models\Role;
|
use App\Models\Role;
|
||||||
use App\Models\RolePermission;
|
use App\Models\RolePermission;
|
||||||
|
|
||||||
|
151
app/application/app/Services/Site/DocumentationService.php
Normal file
151
app/application/app/Services/Site/DocumentationService.php
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Services\Site;
|
||||||
|
|
||||||
|
use App\Dto\Service\Site\Documentation;
|
||||||
|
use App\Enums\CacheTag;
|
||||||
|
use App\Enums\DocumentationVersionStatus;
|
||||||
|
use App\Models\DocumentationCategory;
|
||||||
|
use App\Models\Documentation as ModelDocumentation;
|
||||||
|
use App\Models\DocumentationVersion;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Repositories\DocumentationCategoryRepository;
|
||||||
|
use App\Repositories\DocumentationRepository;
|
||||||
|
use App\ServiceResults\ServiceResultArray;
|
||||||
|
use App\ServiceResults\ServiceResultError;
|
||||||
|
use App\ServiceResults\Site\DocumentationService\DefaultVersion;
|
||||||
|
use app\ServiceResults\Site\PagePossibleWithoutTranslation;
|
||||||
|
use App\Services\Service;
|
||||||
|
use App\Dto\Builder\DocumentationCategory as DocumentationCategoryBuilderDto;
|
||||||
|
use App\Dto\Builder\Documentation as DocumentationBuilderDto;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
final class DocumentationService extends Service
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentationCategoryRepository $documentationCategoryRepository,
|
||||||
|
private readonly DocumentationRepository $documentationRepository
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function defaultVersion(Project $project, ?User $user): ServiceResultError | DefaultVersion
|
||||||
|
{
|
||||||
|
$seconds = 3600;
|
||||||
|
$isPublic = null;
|
||||||
|
if ($user?->cannot('viewAny', DocumentationVersion::class)) {
|
||||||
|
$isPublic = 1;
|
||||||
|
}
|
||||||
|
$version = CacheTag::DocumantationVersion->getCache()
|
||||||
|
->remember(self::class . $project->id . '_' . $isPublic ?? 0, $seconds, function () use ($project, $isPublic) {
|
||||||
|
$versions = $project->documentationVersions()
|
||||||
|
->when($isPublic, function (Builder $query) {
|
||||||
|
$query->where('is_public', 1);
|
||||||
|
})
|
||||||
|
->limit(10)
|
||||||
|
->get();
|
||||||
|
return $versions->firstWhere('status', DocumentationVersionStatus::CurrentVersion)
|
||||||
|
??
|
||||||
|
$versions->first() ?? false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($version === false) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultVersion($version);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(Documentation $documentation): ServiceResultError | ServiceResultArray
|
||||||
|
{
|
||||||
|
return $this->result(array_merge($documentation->toArray(), [
|
||||||
|
'categories' => $this->getCategories($documentation, null),
|
||||||
|
'documentations' => $this->getDocumentations($documentation, null),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function category(string $slug, Documentation $documentation): ServiceResultError | PagePossibleWithoutTranslation
|
||||||
|
{
|
||||||
|
$category = $this->documentationCategoryRepository->getCategoryBySlugWithContent($slug, $documentation->getVersion()->id, $documentation->getWebsiteTranslations()->getLanguage());
|
||||||
|
if (!$category) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$category->is_public === false &&
|
||||||
|
($documentation->getUser() === null || $documentation->getUser()->cannot('view', $category))
|
||||||
|
) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_merge($documentation->toArray(), [
|
||||||
|
'category' => $category,
|
||||||
|
'categories' => $this->getCategories($documentation, $category->id),
|
||||||
|
'documentations' => $this->getDocumentations($documentation, $category->id),
|
||||||
|
]);
|
||||||
|
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($category->content?->title));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(string $slug, Documentation $documentation): ServiceResultError | PagePossibleWithoutTranslation
|
||||||
|
{
|
||||||
|
$document = $this->documentationRepository->getDocumentationBySlugWithContent($slug, $documentation->getVersion()->id, $documentation->getWebsiteTranslations()->getLanguage());
|
||||||
|
if (!$document) {
|
||||||
|
return $this->errNotFound(__('Not Found'));
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
$document->is_public === false &&
|
||||||
|
($documentation->getUser() === null || $documentation->getUser()->cannot('view', $document))
|
||||||
|
) {
|
||||||
|
return $this->errFobidden(__('Access is denied'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_merge($documentation->toArray(), [
|
||||||
|
'documentation' => $document,
|
||||||
|
]);
|
||||||
|
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($document->content?->title));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCategories(Documentation $documentation, ?int $parentId): Collection
|
||||||
|
{
|
||||||
|
$isPublic = null;
|
||||||
|
if ($documentation->getUser() === null || $documentation->getUser()->cannot('viewAny', DocumentationCategory::class)) {
|
||||||
|
$isPublic = true;
|
||||||
|
}
|
||||||
|
$builderDto = new DocumentationCategoryBuilderDto(
|
||||||
|
isPublic: $isPublic,
|
||||||
|
parentId: new DocumentationCategoryBuilderDto\Category($parentId),
|
||||||
|
);
|
||||||
|
$with = [
|
||||||
|
'content' => function (HasOne $hasOne) use ($documentation) {
|
||||||
|
$hasOne->where('language_id', $documentation->getWebsiteTranslations()->getLanguage()->id);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return $this->documentationCategoryRepository->getCategories(
|
||||||
|
$documentation->getVersion()->id,
|
||||||
|
$builderDto,
|
||||||
|
$with
|
||||||
|
)->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDocumentations(Documentation $documentation, ?int $categoryId): Collection
|
||||||
|
{
|
||||||
|
$isPublic = null;
|
||||||
|
if ($documentation->getUser() === null || $documentation->getUser()->cannot('viewAny', ModelDocumentation::class)) {
|
||||||
|
$isPublic = true;
|
||||||
|
}
|
||||||
|
$builderDto = new DocumentationBuilderDto(
|
||||||
|
isPublic: $isPublic,
|
||||||
|
categoryId: new DocumentationCategoryBuilderDto\Category($categoryId),
|
||||||
|
);
|
||||||
|
$with = [
|
||||||
|
'content' => function (HasOne $hasOne) use ($documentation) {
|
||||||
|
$hasOne->where('language_id', $documentation->getWebsiteTranslations()->getLanguage()->id);
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return $this->documentationRepository->getDocumentations(
|
||||||
|
$documentation->getVersion()->id,
|
||||||
|
$builderDto,
|
||||||
|
$with
|
||||||
|
)->all();
|
||||||
|
}
|
||||||
|
}
|
48
app/application/app/View/Components/Site/ChooseVersion.php
Normal file
48
app/application/app/View/Components/Site/ChooseVersion.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\View\Components\Site;
|
||||||
|
|
||||||
|
use App\Enums\CacheTag;
|
||||||
|
use App\Models\DocumentationVersion;
|
||||||
|
use App\Models\Project;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\WebsiteTranslations;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
final class ChooseVersion extends Component
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly DocumentationVersion $version,
|
||||||
|
private readonly WebsiteTranslations $websiteTranslations,
|
||||||
|
private readonly Project $project,
|
||||||
|
private readonly ?User $user,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
$isPublic = null;
|
||||||
|
if (\is_null($this->user) || $this->user->cannot('viewAny', DocumentationVersion::class)) {
|
||||||
|
$isPublic = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$seconds = 3600 * 12;
|
||||||
|
$versions = CacheTag::DocumantationVersion->getCache()
|
||||||
|
->remember(self::class . $this->project->id . '-' . $isPublic ?? 0, $seconds, function () use ($isPublic) {
|
||||||
|
return $this->project->documentationVersions()
|
||||||
|
->when($isPublic, function (Builder $query) {
|
||||||
|
$query->where('is_public', 1);
|
||||||
|
})
|
||||||
|
->get();
|
||||||
|
});
|
||||||
|
|
||||||
|
return view('components.site.choose-version', [
|
||||||
|
'websiteTranslations' => $this->websiteTranslations,
|
||||||
|
'versions' => $versions,
|
||||||
|
'version' => $this->version,
|
||||||
|
'project' => $this->project,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\View\Components\Site;
|
||||||
|
|
||||||
|
use App\Services\WebsiteTranslations;
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
final class DocumentationVersion extends Component
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly \App\Models\DocumentationVersion $version,
|
||||||
|
private readonly WebsiteTranslations $websiteTranslations,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function render(): View
|
||||||
|
{
|
||||||
|
return view('components.site.documentation-version', [
|
||||||
|
'websiteTranslations' => $this->websiteTranslations,
|
||||||
|
'version' => $this->version,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -19,7 +19,7 @@ final class Languages extends Form
|
|||||||
private function getValue(): array
|
private function getValue(): array
|
||||||
{
|
{
|
||||||
$value = old($this->getRequestName(), null);
|
$value = old($this->getRequestName(), null);
|
||||||
if (\is_null($value)) {
|
if (\is_null($value) || !isset($value['items']) || !\is_array($value['items'])) {
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,4 +16,9 @@ return [
|
|||||||
'email' => 'email',
|
'email' => 'email',
|
||||||
'message' => 'message',
|
'message' => 'message',
|
||||||
],
|
],
|
||||||
|
'Documentation' => 'Documentation',
|
||||||
|
'Documentation not created' => 'Documentation not created',
|
||||||
|
'Choose version' => 'Choose version',
|
||||||
|
'alert-status-not-supported' => 'WARNING! You are viewing the documentation for an older version.',
|
||||||
|
'alert-status-future' => 'WARNING! You\'re browsing the documentation for an upcoming version. The documentation and features of this release are subject to change.',
|
||||||
];
|
];
|
||||||
|
@@ -16,4 +16,9 @@ return [
|
|||||||
'email' => 'email',
|
'email' => 'email',
|
||||||
'message' => 'сообщение',
|
'message' => 'сообщение',
|
||||||
],
|
],
|
||||||
|
'Documentation' => 'Документация',
|
||||||
|
'Documentation not created' => 'Документация не создана',
|
||||||
|
'Choose version' => 'Выберите версию',
|
||||||
|
'alert-status-not-supported' => 'ВНИМАНИЕ! Вы просматриваете документацию для старой версии.',
|
||||||
|
'alert-status-future' => 'ВНИМАНИЕ! Вы просматриваете документацию к будущей версии. Документация и функции этого выпуска могут быть изменены.',
|
||||||
];
|
];
|
||||||
|
10
app/application/package-lock.json
generated
10
app/application/package-lock.json
generated
@@ -17,7 +17,6 @@
|
|||||||
"sass": "^1.47.0",
|
"sass": "^1.47.0",
|
||||||
"simplebar": "^5.3.4",
|
"simplebar": "^5.3.4",
|
||||||
"smooth-scroll": "^16.1.3",
|
"smooth-scroll": "^16.1.3",
|
||||||
"sweetalert2": "^11.0.18",
|
|
||||||
"tinymce": "^7.0.1",
|
"tinymce": "^7.0.1",
|
||||||
"vanillajs-datepicker": "^1.2.0",
|
"vanillajs-datepicker": "^1.2.0",
|
||||||
"waypoints": "^4.0.1"
|
"waypoints": "^4.0.1"
|
||||||
@@ -2065,15 +2064,6 @@
|
|||||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sweetalert2": {
|
|
||||||
"version": "11.10.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.7.tgz",
|
|
||||||
"integrity": "sha512-5Jlzrmaitay6KzU+2+LhYu9q+L4v/dZ8oZyEDH14ep0C/QilCnFLHmqAyD/Lhq/lm5DiwsOs6Tr58iv8k3wyGg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/limonte"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
"sass": "^1.47.0",
|
"sass": "^1.47.0",
|
||||||
"simplebar": "^5.3.4",
|
"simplebar": "^5.3.4",
|
||||||
"smooth-scroll": "^16.1.3",
|
"smooth-scroll": "^16.1.3",
|
||||||
"sweetalert2": "^11.0.18",
|
|
||||||
"tinymce": "^7.0.1",
|
"tinymce": "^7.0.1",
|
||||||
"vanillajs-datepicker": "^1.2.0",
|
"vanillajs-datepicker": "^1.2.0",
|
||||||
"waypoints": "^4.0.1"
|
"waypoints": "^4.0.1"
|
||||||
|
@@ -0,0 +1,8 @@
|
|||||||
|
let blockDocumentationVersion = document.querySelector('#documentation-version');
|
||||||
|
blockDocumentationVersion.querySelector('.documentation-version__button').addEventListener('click', (e) => {
|
||||||
|
if (blockDocumentationVersion.classList.contains('active')) {
|
||||||
|
blockDocumentationVersion.classList.remove('active');
|
||||||
|
} else {
|
||||||
|
blockDocumentationVersion.classList.add('active');
|
||||||
|
}
|
||||||
|
});
|
@@ -1,2 +1,3 @@
|
|||||||
import './_menu.js';
|
import './_menu.js';
|
||||||
import './_choose-language.js';
|
import './_choose-language.js';
|
||||||
|
import './_choose-documentation-version.js';
|
||||||
|
@@ -43,7 +43,8 @@ body {
|
|||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"logo menu"
|
"logo menu"
|
||||||
"language language";
|
"language language"
|
||||||
|
"documentation-version documentation-version";
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
box-shadow: 0 3px 9px rgba(0,0,0,0.48);
|
box-shadow: 0 3px 9px rgba(0,0,0,0.48);
|
||||||
background: #eee;
|
background: #eee;
|
||||||
@@ -79,7 +80,7 @@ body {
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 10;
|
z-index: 110;
|
||||||
|
|
||||||
.open {
|
.open {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -138,6 +139,7 @@ body.mobile-menu-open {
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
z-index: 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#language {
|
#language {
|
||||||
@@ -176,6 +178,7 @@ body.mobile-menu-open {
|
|||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-radius: 0 0 5px 5px;
|
border-radius: 0 0 5px 5px;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -193,6 +196,77 @@ body.mobile-menu-open {
|
|||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#documentation-version {
|
||||||
|
grid-area: documentation-version;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #444;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.status.status__100 {
|
||||||
|
color: #0a6f4d;
|
||||||
|
}
|
||||||
|
.status.status__50 {
|
||||||
|
color: #0a53be;
|
||||||
|
}
|
||||||
|
.status.status__0 {
|
||||||
|
color: #6c0e22;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.documentation-version__block {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.documentation-version__button {
|
||||||
|
border: 0;
|
||||||
|
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.48);
|
||||||
|
background: #ccc;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px;
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.documentation-version__button__str {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(50% - 8px);
|
||||||
|
right: 10px;
|
||||||
|
}
|
||||||
|
.documentation-version__list {
|
||||||
|
background: #ddd;
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
list-style: none;
|
||||||
|
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.48);
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0 0 5px 5px;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000;
|
||||||
|
font-size: 16px;
|
||||||
|
display: block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#documentation-version.active {
|
||||||
|
.documentation-version__list {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.documentation-version__button {
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -223,6 +297,15 @@ body.mobile-menu-open {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.alert-version {
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.alert-version.version-status-not-supported {
|
||||||
|
color: #6c0e22;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1000px) {
|
@media (min-width: 1000px) {
|
||||||
body {
|
body {
|
||||||
@@ -230,8 +313,8 @@ body.mobile-menu-open {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
grid-template-areas: "logo language";
|
grid-template-areas: "logo documentation-version language";
|
||||||
grid-template-columns: 1fr 200px;
|
grid-template-columns: 1fr 200px 200px;
|
||||||
}
|
}
|
||||||
.header_logo {
|
.header_logo {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
@@ -248,6 +331,7 @@ body.mobile-menu-open {
|
|||||||
.main-container {
|
.main-container {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
#language {
|
#language {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
@@ -257,6 +341,17 @@ body.mobile-menu-open {
|
|||||||
.language__button {
|
.language__button {
|
||||||
padding: 7px 10px 7px 0;
|
padding: 7px 10px 7px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#documentation-version {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.documentation-version__block {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
.documentation-version__button {
|
||||||
|
padding: 7px 10px 7px 0;
|
||||||
|
}
|
||||||
|
|
||||||
#menu {
|
#menu {
|
||||||
flex: none;
|
flex: none;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
<div id="documentation-version">
|
||||||
|
<div class="documentation-version__block">
|
||||||
|
<button class="documentation-version__button" type="button" aria-label="{{ $websiteTranslations->translate('site.Choose version') }}">
|
||||||
|
<svg width="16" height="16" data-slot="icon" fill="currentColor" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
|
<path clip-rule="evenodd" fill-rule="evenodd" d="M4 2a1.5 1.5 0 0 0-1.5 1.5v9A1.5 1.5 0 0 0 4 14h8a1.5 1.5 0 0 0 1.5-1.5V6.621a1.5 1.5 0 0 0-.44-1.06L9.94 2.439A1.5 1.5 0 0 0 8.878 2H4Zm1 5.75A.75.75 0 0 1 5.75 7h4.5a.75.75 0 0 1 0 1.5h-4.5A.75.75 0 0 1 5 7.75Zm0 3a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Z"></path>
|
||||||
|
</svg>
|
||||||
|
{{ $version->title }} <span class="status status__{{ $version->status->value }}">({{ $version->status->getTitle($websiteTranslations) }})</span>
|
||||||
|
<svg width="16" height="16" class="documentation-version__button__str" data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<ul class="documentation-version__list">
|
||||||
|
@foreach($versions as $v)
|
||||||
|
<li><a href="{{ \App\Enums\Site\ProjectSection::DocumentationVersion->url($project, $websiteTranslations->getLanguage(), ['version' => $v->slug]) }}">{{ $v->title }} <span class="status status__{{ $v->status->value }}">({{ $v->status->getTitle($websiteTranslations) }})</span></a></li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,10 @@
|
|||||||
|
@if($version->status === \App\Enums\DocumentationVersionStatus::NotSupported)
|
||||||
|
<div class="alert-version version-status-not-supported">
|
||||||
|
{{ $websiteTranslations->translate('site.alert-status-not-supported') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if($version->status === \App\Enums\DocumentationVersionStatus::FutureVersion)
|
||||||
|
<div class="alert-version version-status-future">
|
||||||
|
{{ $websiteTranslations->translate('site.alert-status-future') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
@@ -30,6 +30,9 @@
|
|||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
@if($attributes->has('documentationVersion'))
|
||||||
|
<x-site.choose-version :version="$attributes->get('documentationVersion')" :websiteTranslations="$websiteTranslations" :project="$project" :user="auth()->user()" />
|
||||||
|
@endif
|
||||||
<x-site.choose-language :websiteTranslations="$websiteTranslations" :project="$project" />
|
<x-site.choose-language :websiteTranslations="$websiteTranslations" :project="$project" />
|
||||||
</header>
|
</header>
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
@@ -37,11 +40,15 @@
|
|||||||
<div class="menu__title">{{ __('site.Menu') }}</div>
|
<div class="menu__title">{{ __('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'])])>{{ $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::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'])])>{{ $websiteTranslations->translate('site.Feedback') }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="section-container">
|
<div class="section-container">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@if($attributes->has('documentationVersion'))
|
||||||
|
<x-site.documentation-version :websiteTranslations="$websiteTranslations" :version="$attributes->get('documentationVersion')" />
|
||||||
|
@endif
|
||||||
<h1>@yield('h1', '')</h1>
|
<h1>@yield('h1', '')</h1>
|
||||||
|
|
||||||
@includeWhen($errors->any(), 'layout.site._errors', ['errors' => $errors->all()])
|
@includeWhen($errors->any(), 'layout.site._errors', ['errors' => $errors->all()])
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
<span class="input-group-text" id="basic-addon2">
|
<span class="input-group-text" id="basic-addon2">
|
||||||
<svg class="icon icon-xs text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path></svg>
|
<svg class="icon icon-xs text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clip-rule="evenodd"></path></svg>
|
||||||
</span>
|
</span>
|
||||||
<input type="password" name="password" placeholder="Password" class="form-control" id="password" required>
|
<input type="password" name="password" placeholder="Password" class="form-control" id="password" autocomplete="off" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- End of Form -->
|
<!-- End of Form -->
|
||||||
|
@@ -23,8 +23,8 @@
|
|||||||
<form method="post" action="{{ route('profile.update-password') }}">
|
<form method="post" action="{{ route('profile.update-password') }}">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
<x-volt.forms.input :title="__('validation.attributes.password')" name="password" type="password" required />
|
<x-volt.forms.input :title="__('validation.attributes.password')" name="password" type="password" autocomplete="off" required />
|
||||||
<x-volt.forms.input :title="__('validation.attributes.password_confirmation')" name="password_confirmation" type="password" required />
|
<x-volt.forms.input :title="__('validation.attributes.password_confirmation')" name="password_confirmation" type="password" autocomplete="off" required />
|
||||||
<button class="btn btn-primary" type="submit">{{ __('Save') }}</button>
|
<button class="btn btn-primary" type="submit">{{ __('Save') }}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -0,0 +1,13 @@
|
|||||||
|
@section('meta_title', $category->content?->title . ' - ' . $project->name . ' ' . $version->title)
|
||||||
|
@section('h1', $category->content?->title)
|
||||||
|
|
||||||
|
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
|
||||||
|
@foreach($categories as $category)
|
||||||
|
@continue(! $category->content?->title)
|
||||||
|
<p><a href="{{ \App\Enums\Site\ProjectSection::DocumentationCategory->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $category->slug]) }}">{{ $category->content->title }}</a></p>
|
||||||
|
@endforeach
|
||||||
|
@foreach($documentations as $documentation)
|
||||||
|
@continue(! $documentation->content?->title)
|
||||||
|
<p><a href="{{ \App\Enums\Site\ProjectSection::DocumentationView->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $documentation->slug]) }}">{{ $documentation->content->title }}</a></p>
|
||||||
|
@endforeach
|
||||||
|
</x-site.layout>
|
@@ -0,0 +1,13 @@
|
|||||||
|
@section('meta_title', $websiteTranslations->translate('site.Documentation') . ' - ' . $project->name . ' ' . $version->title)
|
||||||
|
@section('h1', $websiteTranslations->translate('site.Documentation'))
|
||||||
|
|
||||||
|
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
|
||||||
|
@foreach($categories as $category)
|
||||||
|
@continue(! $category->content?->title)
|
||||||
|
<p><a href="{{ \App\Enums\Site\ProjectSection::DocumentationCategory->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $category->slug]) }}">{{ $category->content->title }}</a></p>
|
||||||
|
@endforeach
|
||||||
|
@foreach($documentations as $documentation)
|
||||||
|
@continue(! $documentation->content?->title)
|
||||||
|
<p><a href="{{ \App\Enums\Site\ProjectSection::DocumentationView->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $documentation->slug]) }}">{{ $documentation->content->title }}</a></p>
|
||||||
|
@endforeach
|
||||||
|
</x-site.layout>
|
@@ -0,0 +1,6 @@
|
|||||||
|
@section('meta_title', $websiteTranslations->translate('site.Documentation not created'))
|
||||||
|
@section('h1', $websiteTranslations->translate('site.Documentation not created'))
|
||||||
|
|
||||||
|
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations">
|
||||||
|
|
||||||
|
</x-site.layout>
|
@@ -0,0 +1,9 @@
|
|||||||
|
@section('meta_title', $documentation->content?->title . ' - ' . $project->name . ' ' . $version->title)
|
||||||
|
@section('h1', $documentation->content?->title)
|
||||||
|
|
||||||
|
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
|
||||||
|
<div class="line-numbers">{!! $documentation->content->content !!}</div>
|
||||||
|
@push('scripts')
|
||||||
|
@include('_prism')
|
||||||
|
@endpush
|
||||||
|
</x-site.layout>
|
@@ -19,53 +19,10 @@
|
|||||||
const d = document;
|
const d = document;
|
||||||
|
|
||||||
import * as bootstrap from 'bootstrap';
|
import * as bootstrap from 'bootstrap';
|
||||||
import Swal from 'sweetalert2';
|
|
||||||
import SmoothScroll from 'smooth-scroll';
|
import SmoothScroll from 'smooth-scroll';
|
||||||
import Chartist from 'chartist';
|
|
||||||
import 'chartist-plugin-tooltips';
|
|
||||||
|
|
||||||
d.addEventListener("DOMContentLoaded", function(event) {
|
d.addEventListener("DOMContentLoaded", function(event) {
|
||||||
|
|
||||||
const swalWithBootstrapButtons = Swal.mixin({
|
|
||||||
customClass: {
|
|
||||||
confirmButton: 'btn btn-primary me-3',
|
|
||||||
cancelButton: 'btn btn-gray'
|
|
||||||
},
|
|
||||||
buttonsStyling: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var themeSettingsEl = document.getElementById('theme-settings');
|
|
||||||
var themeSettingsExpandEl = document.getElementById('theme-settings-expand');
|
|
||||||
|
|
||||||
if(themeSettingsEl) {
|
|
||||||
|
|
||||||
var themeSettingsCollapse = new bootstrap.Collapse(themeSettingsEl, {
|
|
||||||
show: true,
|
|
||||||
toggle: false
|
|
||||||
});
|
|
||||||
|
|
||||||
if (window.localStorage.getItem('settings_expanded') === 'true') {
|
|
||||||
themeSettingsCollapse.show();
|
|
||||||
themeSettingsExpandEl.classList.remove('show');
|
|
||||||
} else {
|
|
||||||
themeSettingsCollapse.hide();
|
|
||||||
themeSettingsExpandEl.classList.add('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
themeSettingsEl.addEventListener('hidden.bs.collapse', function () {
|
|
||||||
themeSettingsExpandEl.classList.add('show');
|
|
||||||
window.localStorage.setItem('settings_expanded', false);
|
|
||||||
});
|
|
||||||
|
|
||||||
themeSettingsExpandEl.addEventListener('click', function () {
|
|
||||||
themeSettingsExpandEl.classList.remove('show');
|
|
||||||
window.localStorage.setItem('settings_expanded', true);
|
|
||||||
setTimeout(function() {
|
|
||||||
themeSettingsCollapse.show();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// options
|
// options
|
||||||
const breakpoints = {
|
const breakpoints = {
|
||||||
sm: 540,
|
sm: 540,
|
||||||
@@ -84,13 +41,6 @@ d.addEventListener("DOMContentLoaded", function(event) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var iconNotifications = d.querySelector('.notification-bell');
|
|
||||||
if (iconNotifications) {
|
|
||||||
iconNotifications.addEventListener('shown.bs.dropdown', function () {
|
|
||||||
iconNotifications.classList.remove('unread');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[].slice.call(d.querySelectorAll('[data-background]')).map(function(el) {
|
[].slice.call(d.querySelectorAll('[data-background]')).map(function(el) {
|
||||||
el.style.background = 'url(' + el.getAttribute('data-background') + ')';
|
el.style.background = 'url(' + el.getAttribute('data-background') + ')';
|
||||||
});
|
});
|
||||||
@@ -115,14 +65,12 @@ d.addEventListener("DOMContentLoaded", function(event) {
|
|||||||
return new bootstrap.Tooltip(tooltipTriggerEl)
|
return new bootstrap.Tooltip(tooltipTriggerEl)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// Popovers
|
// Popovers
|
||||||
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
|
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
|
||||||
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
|
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
|
||||||
return new bootstrap.Popover(popoverTriggerEl)
|
return new bootstrap.Popover(popoverTriggerEl)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// Datepicker
|
// Datepicker
|
||||||
var datepickers = [].slice.call(d.querySelectorAll('[data-datepicker]'))
|
var datepickers = [].slice.call(d.querySelectorAll('[data-datepicker]'))
|
||||||
var datepickersList = datepickers.map(function (el) {
|
var datepickersList = datepickers.map(function (el) {
|
||||||
@@ -131,164 +79,6 @@ d.addEventListener("DOMContentLoaded", function(event) {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
if(d.querySelector('.input-slider-container')) {
|
|
||||||
[].slice.call(d.querySelectorAll('.input-slider-container')).map(function(el) {
|
|
||||||
var slider = el.querySelector(':scope .input-slider');
|
|
||||||
var sliderId = slider.getAttribute('id');
|
|
||||||
var minValue = slider.getAttribute('data-range-value-min');
|
|
||||||
var maxValue = slider.getAttribute('data-range-value-max');
|
|
||||||
|
|
||||||
var sliderValue = el.querySelector(':scope .range-slider-value');
|
|
||||||
var sliderValueId = sliderValue.getAttribute('id');
|
|
||||||
var startValue = sliderValue.getAttribute('data-range-value-low');
|
|
||||||
|
|
||||||
var c = d.getElementById(sliderId),
|
|
||||||
id = d.getElementById(sliderValueId);
|
|
||||||
|
|
||||||
noUiSlider.create(c, {
|
|
||||||
start: [parseInt(startValue)],
|
|
||||||
connect: [true, false],
|
|
||||||
//step: 1000,
|
|
||||||
range: {
|
|
||||||
'min': [parseInt(minValue)],
|
|
||||||
'max': [parseInt(maxValue)]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.getElementById('input-slider-range')) {
|
|
||||||
var c = d.getElementById("input-slider-range"),
|
|
||||||
low = d.getElementById("input-slider-range-value-low"),
|
|
||||||
e = d.getElementById("input-slider-range-value-high"),
|
|
||||||
f = [d, e];
|
|
||||||
|
|
||||||
noUiSlider.create(c, {
|
|
||||||
start: [parseInt(low.getAttribute('data-range-value-low')), parseInt(e.getAttribute('data-range-value-high'))],
|
|
||||||
connect: !0,
|
|
||||||
tooltips: true,
|
|
||||||
range: {
|
|
||||||
min: parseInt(c.getAttribute('data-range-value-min')),
|
|
||||||
max: parseInt(c.getAttribute('data-range-value-max'))
|
|
||||||
}
|
|
||||||
}), c.noUiSlider.on("update", function (a, b) {
|
|
||||||
f[b].textContent = a[b]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//Chartist
|
|
||||||
|
|
||||||
if(d.querySelector('.ct-chart-sales-value')) {
|
|
||||||
//Chart 5
|
|
||||||
new Chartist.Line('.ct-chart-sales-value', {
|
|
||||||
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
|
||||||
series: [
|
|
||||||
[0, 10, 30, 40, 80, 60, 100]
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
low: 0,
|
|
||||||
showArea: true,
|
|
||||||
fullWidth: true,
|
|
||||||
plugins: [
|
|
||||||
Chartist.plugins.tooltip()
|
|
||||||
],
|
|
||||||
axisX: {
|
|
||||||
// On the x-axis start means top and end means bottom
|
|
||||||
position: 'end',
|
|
||||||
showGrid: true
|
|
||||||
},
|
|
||||||
axisY: {
|
|
||||||
// On the y-axis start means left and end means right
|
|
||||||
showGrid: false,
|
|
||||||
showLabel: false,
|
|
||||||
labelInterpolationFnc: function(value) {
|
|
||||||
return '$' + (value / 1) + 'k';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d.querySelector('.ct-chart-ranking')) {
|
|
||||||
var chart = new Chartist.Bar('.ct-chart-ranking', {
|
|
||||||
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
||||||
series: [
|
|
||||||
[1, 5, 2, 5, 4, 3],
|
|
||||||
[2, 3, 4, 8, 1, 2],
|
|
||||||
]
|
|
||||||
}, {
|
|
||||||
low: 0,
|
|
||||||
showArea: true,
|
|
||||||
plugins: [
|
|
||||||
Chartist.plugins.tooltip()
|
|
||||||
],
|
|
||||||
axisX: {
|
|
||||||
// On the x-axis start means top and end means bottom
|
|
||||||
position: 'end'
|
|
||||||
},
|
|
||||||
axisY: {
|
|
||||||
// On the y-axis start means left and end means right
|
|
||||||
showGrid: false,
|
|
||||||
showLabel: false,
|
|
||||||
offset: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
chart.on('draw', function(data) {
|
|
||||||
if(data.type === 'line' || data.type === 'area') {
|
|
||||||
data.element.animate({
|
|
||||||
d: {
|
|
||||||
begin: 2000 * data.index,
|
|
||||||
dur: 2000,
|
|
||||||
from: data.path.clone().scale(1, 0).translate(0, data.chartRect.height()).stringify(),
|
|
||||||
to: data.path.clone().stringify(),
|
|
||||||
easing: Chartist.Svg.Easing.easeOutQuint
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d.querySelector('.ct-chart-traffic-share')) {
|
|
||||||
var data = {
|
|
||||||
series: [70, 20, 10]
|
|
||||||
};
|
|
||||||
|
|
||||||
var sum = function(a, b) { return a + b };
|
|
||||||
|
|
||||||
new Chartist.Pie('.ct-chart-traffic-share', data, {
|
|
||||||
labelInterpolationFnc: function(value) {
|
|
||||||
return Math.round(value / data.series.reduce(sum) * 100) + '%';
|
|
||||||
},
|
|
||||||
low: 0,
|
|
||||||
high: 8,
|
|
||||||
donut: true,
|
|
||||||
donutWidth: 20,
|
|
||||||
donutSolid: true,
|
|
||||||
fullWidth: false,
|
|
||||||
showLabel: false,
|
|
||||||
plugins: [
|
|
||||||
Chartist.plugins.tooltip()
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.getElementById('loadOnClick')) {
|
|
||||||
d.getElementById('loadOnClick').addEventListener('click', function () {
|
|
||||||
var button = this;
|
|
||||||
var loadContent = d.getElementById('extraContent');
|
|
||||||
var allLoaded = d.getElementById('allLoadedText');
|
|
||||||
|
|
||||||
button.classList.add('btn-loading');
|
|
||||||
button.setAttribute('disabled', 'true');
|
|
||||||
|
|
||||||
setTimeout(function () {
|
|
||||||
loadContent.style.display = 'block';
|
|
||||||
button.style.display = 'none';
|
|
||||||
allLoaded.style.display = 'block';
|
|
||||||
}, 1500);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var scroll = new SmoothScroll('a[href*="#"]', {
|
var scroll = new SmoothScroll('a[href*="#"]', {
|
||||||
speed: 500,
|
speed: 500,
|
||||||
speedAsDuration: true
|
speedAsDuration: true
|
||||||
@@ -297,68 +87,4 @@ d.addEventListener("DOMContentLoaded", function(event) {
|
|||||||
if(d.querySelector('.current-year')){
|
if(d.querySelector('.current-year')){
|
||||||
d.querySelector('.current-year').textContent = new Date().getFullYear();
|
d.querySelector('.current-year').textContent = new Date().getFullYear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Glide JS
|
|
||||||
|
|
||||||
if (d.querySelector('.glide')) {
|
|
||||||
new Glide('.glide', {
|
|
||||||
type: 'carousel',
|
|
||||||
startAt: 0,
|
|
||||||
perView: 3
|
|
||||||
}).mount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.querySelector('.glide-testimonials')) {
|
|
||||||
new Glide('.glide-testimonials', {
|
|
||||||
type: 'carousel',
|
|
||||||
startAt: 0,
|
|
||||||
perView: 1,
|
|
||||||
autoplay: 2000
|
|
||||||
}).mount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.querySelector('.glide-clients')) {
|
|
||||||
new Glide('.glide-clients', {
|
|
||||||
type: 'carousel',
|
|
||||||
startAt: 0,
|
|
||||||
perView: 5,
|
|
||||||
autoplay: 2000
|
|
||||||
}).mount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.querySelector('.glide-news-widget')) {
|
|
||||||
new Glide('.glide-news-widget', {
|
|
||||||
type: 'carousel',
|
|
||||||
startAt: 0,
|
|
||||||
perView: 1,
|
|
||||||
autoplay: 2000
|
|
||||||
}).mount();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.querySelector('.glide-autoplay')) {
|
|
||||||
new Glide('.glide-autoplay', {
|
|
||||||
type: 'carousel',
|
|
||||||
startAt: 0,
|
|
||||||
perView: 3,
|
|
||||||
autoplay: 2000
|
|
||||||
}).mount();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pricing countup
|
|
||||||
var billingSwitchEl = d.getElementById('billingSwitch');
|
|
||||||
if(billingSwitchEl) {
|
|
||||||
const countUpStandard = new countUp.CountUp('priceStandard', 99, { startVal: 199 });
|
|
||||||
const countUpPremium = new countUp.CountUp('pricePremium', 199, { startVal: 299 });
|
|
||||||
|
|
||||||
billingSwitchEl.addEventListener('change', function() {
|
|
||||||
if(billingSwitch.checked) {
|
|
||||||
countUpStandard.start();
|
|
||||||
countUpPremium.start();
|
|
||||||
} else {
|
|
||||||
countUpStandard.reset();
|
|
||||||
countUpPremium.reset();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -6,6 +6,22 @@ Route::get('/', [\App\Http\Controllers\Site\ProjectsController::class, 'index'])
|
|||||||
Route::middleware([\App\Http\Middleware\IsProject::class, \App\Http\Middleware\IsWebsiteTranslations::class])->group(function () {
|
Route::middleware([\App\Http\Middleware\IsProject::class, \App\Http\Middleware\IsWebsiteTranslations::class])->group(function () {
|
||||||
Route::get('/language/{language}', [\App\Http\Controllers\Site\ProjectsController::class, 'index'])->name('home-language');
|
Route::get('/language/{language}', [\App\Http\Controllers\Site\ProjectsController::class, 'index'])->name('home-language');
|
||||||
|
|
||||||
|
Route::prefix('docs')->group(function () {
|
||||||
|
Route::get('/', [\App\Http\Controllers\Site\DocumentationController::class, 'defaultVersion'])->name('documentation');
|
||||||
|
Route::get('language/{language}', [\App\Http\Controllers\Site\DocumentationController::class, 'defaultVersion'])->name('documentation-language');
|
||||||
|
|
||||||
|
Route::middleware([\App\Http\Middleware\DocumentationVersion::class])->prefix('{version}')->group(function () {
|
||||||
|
Route::get('/', [\App\Http\Controllers\Site\DocumentationController::class, 'index'])->name('documentation.version');
|
||||||
|
Route::get('language/{language}', [\App\Http\Controllers\Site\DocumentationController::class, 'index'])->name('documentation.version-language');
|
||||||
|
|
||||||
|
Route::get('category/{slug}', [\App\Http\Controllers\Site\DocumentationController::class, 'category'])->name('documentation.category');
|
||||||
|
Route::get('category/{slug}/language/{language}', [\App\Http\Controllers\Site\DocumentationController::class, 'category'])->name('documentation.category-language');
|
||||||
|
|
||||||
|
Route::get('{slug}', [\App\Http\Controllers\Site\DocumentationController::class, 'view'])->name('documentation.view');
|
||||||
|
Route::get('{slug}/language/{language}', [\App\Http\Controllers\Site\DocumentationController::class, 'view'])->name('documentation.view-language');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Route::prefix('feedback')->group(function () {
|
Route::prefix('feedback')->group(function () {
|
||||||
Route::get('/', [\App\Http\Controllers\Site\FeedbackController::class, 'index'])->name('feedback');
|
Route::get('/', [\App\Http\Controllers\Site\FeedbackController::class, 'index'])->name('feedback');
|
||||||
Route::get('language/{language}', [\App\Http\Controllers\Site\FeedbackController::class, 'index'])->name('feedback-language');
|
Route::get('language/{language}', [\App\Http\Controllers\Site\FeedbackController::class, 'index'])->name('feedback-language');
|
||||||
|
@@ -1,8 +0,0 @@
|
|||||||
**/*.env
|
|
||||||
**/*.env.example
|
|
||||||
application/bootstrap/cache/*
|
|
||||||
application/storage/**
|
|
||||||
application/vendor/**
|
|
||||||
application/node_modules/**
|
|
||||||
application/public/build/**
|
|
||||||
application/public/storage
|
|
@@ -5,6 +5,7 @@ set -euo pipefail
|
|||||||
WAITLOOPS=5
|
WAITLOOPS=5
|
||||||
SLEEPSEC=1
|
SLEEPSEC=1
|
||||||
unitd="unitd"
|
unitd="unitd"
|
||||||
|
role=${CONTAINER_ROLE:-app}
|
||||||
|
|
||||||
curl_put()
|
curl_put()
|
||||||
{
|
{
|
||||||
@@ -22,7 +23,7 @@ curl_put()
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then
|
if [ "$role" = "app" ]; then
|
||||||
echo "$0: Launching Unit daemon to perform initial configuration..."
|
echo "$0: Launching Unit daemon to perform initial configuration..."
|
||||||
/usr/sbin/$unitd --control unix:/var/run/control.unit.sock
|
/usr/sbin/$unitd --control unix:/var/run/control.unit.sock
|
||||||
for i in $(/usr/bin/seq $WAITLOOPS); do
|
for i in $(/usr/bin/seq $WAITLOOPS); do
|
||||||
@@ -61,7 +62,7 @@ if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then
|
|||||||
|
|
||||||
if [ ! -z ${UNIT_SOURCE+x} ]
|
if [ ! -z ${UNIT_SOURCE+x} ]
|
||||||
then
|
then
|
||||||
echo "[${UNIT_SOURCE}]" > /docker-entrypoint.d/unit_source.json
|
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
|
||||||
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@ set -euo pipefail
|
|||||||
WAITLOOPS=5
|
WAITLOOPS=5
|
||||||
SLEEPSEC=1
|
SLEEPSEC=1
|
||||||
unitd="unitd"
|
unitd="unitd"
|
||||||
|
role=${CONTAINER_ROLE:-app}
|
||||||
|
|
||||||
curl_put()
|
curl_put()
|
||||||
{
|
{
|
||||||
@@ -22,7 +23,7 @@ curl_put()
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then
|
if [ "$role" = "app" ]; then
|
||||||
echo "$0: Launching Unit daemon to perform initial configuration..."
|
echo "$0: Launching Unit daemon to perform initial configuration..."
|
||||||
/usr/sbin/$unitd --control unix:/var/run/control.unit.sock
|
/usr/sbin/$unitd --control unix:/var/run/control.unit.sock
|
||||||
for i in $(/usr/bin/seq $WAITLOOPS); do
|
for i in $(/usr/bin/seq $WAITLOOPS); do
|
||||||
@@ -61,7 +62,7 @@ if [ "$unitd" = "unitd" ] || [ "$unitd" = "unitd-debug" ]; then
|
|||||||
|
|
||||||
if [ ! -z ${UNIT_SOURCE+x} ]
|
if [ ! -z ${UNIT_SOURCE+x} ]
|
||||||
then
|
then
|
||||||
echo "[${UNIT_SOURCE}]" > /docker-entrypoint.d/unit_source.json
|
echo $UNIT_SOURCE > /docker-entrypoint.d/unit_source.json
|
||||||
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
curl_put "/docker-entrypoint.d/unit_source.json" "config/listeners/*:9000/forwarded/source"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -102,8 +103,10 @@ php artisan config:cache
|
|||||||
php artisan event:cache
|
php artisan event:cache
|
||||||
php artisan route:cache
|
php artisan route:cache
|
||||||
php artisan view:cache
|
php artisan view:cache
|
||||||
|
php artisan storage:link
|
||||||
|
if [ "$role" = "app" ]; then
|
||||||
php artisan migrate --force
|
php artisan migrate --force
|
||||||
|
fi
|
||||||
chown -R unit:unit /var/www/html
|
chown -R unit:unit /var/www/html
|
||||||
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
|
chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
|
||||||
chmod -R 777 /var/www/html/storage /var/www/html/bootstrap/cache
|
chmod -R 777 /var/www/html/storage /var/www/html/bootstrap/cache
|
||||||
|
1
captcha-app/redis/.gitignore
vendored
Normal file
1
captcha-app/redis/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
data/
|
@@ -14,12 +14,17 @@ 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
|
||||||
|
UNIT_SOURCE: '["172.16.0.0/12"]'
|
||||||
app-redis:
|
app-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
# restart: always
|
# restart: always
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
captcha-app:
|
captcha-app:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
@@ -32,10 +37,13 @@ services:
|
|||||||
- db
|
- db
|
||||||
- captcha-redis
|
- captcha-redis
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: app
|
||||||
|
UNIT_SOURCE: '["172.16.0.0/12"]'
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_PORT}:9000
|
- ${DOCKER_CAPTCHA_PORT}:9000
|
||||||
captcha-queue:
|
captcha-queue:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -44,7 +52,7 @@ services:
|
|||||||
CONTAINER_ROLE: queue
|
CONTAINER_ROLE: queue
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
captcha-reverb:
|
captcha-reverb:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -55,7 +63,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
||||||
captcha-scheduler:
|
captcha-scheduler:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -66,6 +74,8 @@ services:
|
|||||||
captcha-redis:
|
captcha-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
# restart: always
|
# restart: always
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/redis/data:/data
|
||||||
db:
|
db:
|
||||||
image: docker.io/mysql:8.0.33
|
image: docker.io/mysql:8.0.33
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
version: '3.7'
|
version: '3.7'
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
image: korelf/my-projects-website:0.1.0
|
image: korelf/my-projects-website:0.2.1
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -10,15 +10,20 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- ${DOCKER_APP_PORT}:9000
|
- ${DOCKER_APP_PORT}:9000
|
||||||
env_file: app/.env
|
env_file: app/.env
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: app
|
||||||
|
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-redis:
|
app-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
# restart: always
|
# restart: always
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
captcha-app:
|
captcha-app:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
@@ -33,8 +38,11 @@ services:
|
|||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_PORT}:9000
|
- ${DOCKER_CAPTCHA_PORT}:9000
|
||||||
|
environment:
|
||||||
|
CONTAINER_ROLE: app
|
||||||
|
UNIT_SOURCE: '["172.16.0.0/12"]'
|
||||||
captcha-queue:
|
captcha-queue:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -43,7 +51,7 @@ services:
|
|||||||
CONTAINER_ROLE: queue
|
CONTAINER_ROLE: queue
|
||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
captcha-reverb:
|
captcha-reverb:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -54,7 +62,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
- ${DOCKER_CAPTCHA_WEBSOCKET_PORT}:9000
|
||||||
captcha-scheduler:
|
captcha-scheduler:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.2
|
||||||
# restart: always
|
# restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
@@ -65,6 +73,8 @@ services:
|
|||||||
captcha-redis:
|
captcha-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
# restart: always
|
# restart: always
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/redis/data:/data
|
||||||
db:
|
db:
|
||||||
image: docker.io/mysql:8.0.33
|
image: docker.io/mysql:8.0.33
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
@@ -15,6 +15,8 @@ services:
|
|||||||
- ./app/application:/var/www/html
|
- ./app/application:/var/www/html
|
||||||
app-redis:
|
app-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
|
volumes:
|
||||||
|
- ./redis/data:/data
|
||||||
|
|
||||||
captcha-app:
|
captcha-app:
|
||||||
image: korelf/service-captcha:0.8.1
|
image: korelf/service-captcha:0.8.1
|
||||||
@@ -62,6 +64,8 @@ services:
|
|||||||
env_file: captcha-app/.env
|
env_file: captcha-app/.env
|
||||||
captcha-redis:
|
captcha-redis:
|
||||||
image: redis:3.0-alpine
|
image: redis:3.0-alpine
|
||||||
|
volumes:
|
||||||
|
- ./captcha-app/redis/data:/data
|
||||||
db:
|
db:
|
||||||
image: docker.io/mysql:8.0.33
|
image: docker.io/mysql:8.0.33
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
1
redis/.gitignore
vendored
Normal file
1
redis/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
data/
|
Reference in New Issue
Block a user