9 Commits
Author SHA1 Message Date
kor-elf 4cdf11be3d Update production Docker Compose to switch images to MDHub registry
- Replace Docker Hub image references with MDHub equivalents across all services.
- Update environment variables and volume bindings for web and app services.
- Add production-specific environment variables (`APP_ENV`) for queue and scheduler.
2026-07-26 02:20:36 +05:00
kor-elf 0fc181bf12 Update Docker Compose files to use consolidated Dockerfile
- Replace references to separate `php/Dockerfile` and `web/Dockerfile` with the unified `docker/Dockerfile`.
- Adjust target stages across services for development and production environments.
2026-07-26 02:20:13 +05:00
kor-elf 059d2b9d66 Consolidate PHP and Nginx Dockerfiles
- Merge separate PHP and Nginx Dockerfiles into a unified structure under `app/docker/Dockerfile`.
- Simplify build stages and streamline multi-service configuration for production, development, and utility containers.
- Remove outdated individual Dockerfiles (`php/Dockerfile` and `web/Dockerfile`).
2026-07-26 02:19:29 +05:00
kor-elf 136451dc5a Add breadcrumbs to site documentation views
- Integrate breadcrumb rendering across documentation views (`index`, `category`, `view`, and `no-default-version`).
- Add support for dynamic JSON-LD breadcrumb generation.
2026-07-25 23:10:37 +05:00
kor-elf 1ee453dcfe Add category path support to site documentation views
- Introduce `categoryPath` for `DocumentationService` methods.
- Resolve category paths dynamically based on parent or category ID.
2026-07-25 23:10:18 +05:00
kor-elf 2a26008e87 Add breadcrumbs to site views
- Introduce breadcrumb SCSS styles and integrate `breadcrumbs/site.blade.php`.
- Update SCSS imports to include new breadcrumb styles.
2026-07-25 23:09:49 +05:00
kor-elf 031aa196d1 Add breadcrumbs to site feedback page
- Extend breadcrumb definitions for `home` and `feedbacks.index`.
- Integrate breadcrumbs into the feedback page layout.
- Add support for dynamic JSON-LD breadcrumb rendering.
2026-07-25 22:34:21 +05:00
kor-elf c3b9fa56fb Add breadcrumbs and dynamic head stack to site layout
- Inject breadcrumbs into the main site layout for improved navigation.
- Add `@stack('head')` for dynamic head content integration.
2026-07-25 22:33:43 +05:00
kor-elf 0922ee217f Adjust breadcrumb icon styling in SCSS 2026-07-25 20:37:33 +05:00
17 changed files with 239 additions and 80 deletions
@@ -77,10 +77,16 @@ final class DocumentationService extends Service
return $this->errFobidden(__('Access is denied'));
}
$categoryPath = null;
if ($category->parent_id) {
$categoryPath = $this->documentationCategoryRepository->getPathFromRoot($category->parent_id, $documentation->getWebsiteTranslations()->getLanguage());
}
$data = array_merge($documentation->toArray(), [
'category' => $category,
'categories' => $this->getCategories($documentation, $category->id),
'documentations' => $this->getDocumentations($documentation, $category->id),
'categoryPath' => $categoryPath,
]);
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($category->content?->title));
}
@@ -98,8 +104,14 @@ final class DocumentationService extends Service
return $this->errFobidden(__('Access is denied'));
}
$categoryPath = null;
if ($document->category_id) {
$categoryPath = $this->documentationCategoryRepository->getPathFromRoot($document->category_id, $documentation->getWebsiteTranslations()->getLanguage());
}
$data = array_merge($documentation->toArray(), [
'documentation' => $document,
'categoryPath' => $categoryPath,
]);
return $this->resultSitePage($documentation->getProject(), $documentation->getWebsiteTranslations(), $data, \is_null($document->content?->title));
}
+54 -2
View File
@@ -1,8 +1,60 @@
<?php
use App\Models\DocumentationCategory;
use App\Models\DocumentationVersion;
use App\Models\Documentation;
use App\Services\WebsiteTranslations;
use App\Enums\Site\ProjectSection;
use App\Models\Project;
use Diglactic\Breadcrumbs\Breadcrumbs;
use Illuminate\Support\Collection;
Breadcrumbs::for('home', function ($trail, WebsiteTranslations $websiteTranslations) {
$trail->push($websiteTranslations->translate('Home'), route('home'));
Breadcrumbs::for('home', function ($trail, Project $project, WebsiteTranslations $websiteTranslations) {
$trail->push($websiteTranslations->translate('Home'), ProjectSection::Home->url($project, $websiteTranslations->getLanguage()));
});
Breadcrumbs::for('feedbacks.index', function ($trail, Project $project, WebsiteTranslations $websiteTranslations) {
$trail->parent('home', $project, $websiteTranslations);
$trail->push($websiteTranslations->translate('site.Feedback'), ProjectSection::Feedback->url($project, $websiteTranslations->getLanguage()));
});
// Documentation
Breadcrumbs::for('documentation.no-default-version', function ($trail, Project $project, WebsiteTranslations $websiteTranslations) {
$trail->parent('home', $project, $websiteTranslations);
$trail->push($websiteTranslations->translate('site.Documentation'), ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage()));
});
Breadcrumbs::for('documentation.index', function ($trail, Project $project, WebsiteTranslations $websiteTranslations, DocumentationVersion $version) {
$trail->parent('home', $project, $websiteTranslations);
$trail->push($websiteTranslations->translate('site.Documentation'), ProjectSection::DocumentationVersion->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug]));
});
Breadcrumbs::for('documentation.category-path', function ($trail, Project $project, WebsiteTranslations $websiteTranslations, DocumentationVersion $version, Collection $categoryPath) {
$trail->parent('documentation.index', $project, $websiteTranslations, $version);
foreach ($categoryPath as $pathItem) {
$trail->push(
$pathItem->content->title,
ProjectSection::DocumentationCategory->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $pathItem->slug])
);
}
});
Breadcrumbs::for('documentation.category', function ($trail, Project $project, WebsiteTranslations $websiteTranslations, DocumentationVersion $version, DocumentationCategory $category, ?Collection $categoryPath) {
$trail->parent('documentation.category-path', $project, $websiteTranslations, $version, $categoryPath ?? collect());
$trail->push(
$category->content->title,
ProjectSection::DocumentationCategory->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $category->slug])
);
});
Breadcrumbs::for('documentation.view', function ($trail, Project $project, WebsiteTranslations $websiteTranslations, DocumentationVersion $version, Documentation $documentation, ?Collection $categoryPath) {
$trail->parent('documentation.category-path', $project, $websiteTranslations, $version, $categoryPath ?? collect());
$trail->push(
$documentation->content->title,
ProjectSection::Documentation->url($project, $websiteTranslations->getLanguage(), ['version' => $version->slug, 'slug' => $documentation->slug])
);
});
// End Documentation
@@ -1,6 +1,7 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap');
@import "reset";
@import "forms";
@import "breadcrumb";
html,
body {
@@ -0,0 +1,45 @@
.breadcrumb-container {
display: flex;
flex-wrap: wrap;
padding: .5rem 1rem;
margin-bottom: 1rem;
list-style: none;
background-color: #eee;
border-radius: .5rem;
}
.breadcrumb-item+.breadcrumb-item {
padding-left: .5rem
}
.breadcrumb-item+.breadcrumb-item:before {
float: left;
padding-right: .5rem;
color: #4b5563;
content: "/";
}
.breadcrumb-item.active {
color: #4b5563;
font-weight: 400;
}
.breadcrumb-item {
font-size: .75rem
}
.breadcrumb-item,.breadcrumb-item a {
color: #374151;
font-weight: 400;
font-size: .75rem;
}
.breadcrumb-item a:hover {
color: #00040b;
text-decoration: none;
}
@media (min-width: 576px) {
.breadcrumb-item,.breadcrumb-item a {
font-size:.875rem
}
}
@@ -0,0 +1,13 @@
@unless ($breadcrumbs->isEmpty())
<nav aria-label="breadcrumb" class="breadcrumb">
<ol class="breadcrumb-container">
@foreach ($breadcrumbs as $breadcrumb)
@if ($breadcrumb->url && !$loop->last)
<li class="breadcrumb-item"><a href="{{ $breadcrumb->url }}">{{ $breadcrumb->title }}</a></li>
@else
<li class="breadcrumb-item active" aria-current="page">{{ $breadcrumb->title }}</li>
@endif
@endforeach
</ol>
</nav>
@endunless
@@ -9,6 +9,8 @@
<meta name="description" content="@yield('meta_description', '')" />
@vite('resources/site/scss/app.scss')
@stack('head')
</head>
<body>
<div class="wrapper">
@@ -46,6 +48,7 @@
</nav>
<div class="section-container">
<div class="content">
@yield('breadcrumbs', '')
@if($attributes->has('documentationVersion'))
<x-site.documentation-version :websiteTranslations="$websiteTranslations" :version="$attributes->get('documentationVersion')" />
@endif
@@ -1,6 +1,9 @@
@section('meta_title', $websiteTranslations->translate('site.Feedback'))
@section('h1', $websiteTranslations->translate('site.Feedback'))
@section('breadcrumbs', Breadcrumbs::render('feedbacks.index', $project, $websiteTranslations))
@push('head')
{{ Breadcrumbs::view('breadcrumbs::json-ld', 'feedbacks.index', $project, $websiteTranslations) }}
@endpush
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations">
@if(Session::has('success') !== true)
<form method="post" action="{{ \App\Enums\Site\ProjectSection::FeedbackSend->url($project, $websiteTranslations->getLanguage()) }}">
@@ -1,6 +1,9 @@
@section('meta_title', $category->content?->title . ' - ' . $project->name . ' ' . $version->title)
@section('h1', $category->content?->title)
@section('breadcrumbs', Breadcrumbs::render('documentation.category', $project, $websiteTranslations, $version, $category, $categoryPath))
@push('head')
{{ Breadcrumbs::view('breadcrumbs::json-ld', 'documentation.category', $project, $websiteTranslations, $version, $category, $categoryPath) }}
@endpush
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
@foreach($categories as $category)
@continue(! $category->content?->title)
@@ -1,6 +1,9 @@
@section('meta_title', $websiteTranslations->translate('site.Documentation') . ' - ' . $project->name . ' ' . $version->title)
@section('h1', $websiteTranslations->translate('site.Documentation'))
@section('breadcrumbs', Breadcrumbs::render('documentation.index', $project, $websiteTranslations, $version))
@push('head')
{{ Breadcrumbs::view('breadcrumbs::json-ld', 'documentation.index', $project, $websiteTranslations, $version) }}
@endpush
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
@foreach($categories as $category)
@continue(! $category->content?->title)
@@ -1,6 +1,9 @@
@section('meta_title', $websiteTranslations->translate('site.Documentation not created'))
@section('h1', $websiteTranslations->translate('site.Documentation not created'))
@section('breadcrumbs', Breadcrumbs::render('documentation.no-default-version', $project, $websiteTranslations))
@push('head')
{{ Breadcrumbs::view('breadcrumbs::json-ld', 'documentation.no-default-version', $project, $websiteTranslations) }}
@endpush
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations">
</x-site.layout>
@@ -1,6 +1,9 @@
@section('meta_title', $documentation->content?->title . ' - ' . $project->name . ' ' . $version->title)
@section('h1', $documentation->content?->title)
@section('breadcrumbs', Breadcrumbs::render('documentation.view', $project, $websiteTranslations, $version, $documentation, $categoryPath))
@push('head')
{{ Breadcrumbs::view('breadcrumbs::json-ld', 'documentation.view', $project, $websiteTranslations, $version, $documentation, $categoryPath) }}
@endpush
<x-site.layout :project="$project" :websiteTranslations="$websiteTranslations" :documentationVersion="$version">
<div class="line-numbers">{!! $documentation->content->content !!}</div>
@push('scripts')
@@ -24,6 +24,10 @@
padding: 0;
}
.breadcrumb .icon {
margin-top: -2px;
}
@each $color, $value in $theme-colors {
.breadcrumb-#{$color} {
background: $value;
@@ -1,4 +1,4 @@
FROM docker.io/php:8.5-fpm-alpine3.23 AS build
FROM docker.io/php:8.5-fpm-alpine3.23 AS php
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} \
@@ -29,20 +29,37 @@ RUN apk --no-cache add pcre2 libbz2 libpng libwebp libjpeg-turbo icu-libs freety
COPY docker/php/conf/app-fpm.conf /usr/local/etc/php-fpm.d/app-fpm.conf
FROM build AS app_build_for_production
FROM docker.io/nginx:1.31-alpine AS nginx
COPY docker/web/conf/default.conf.template /etc/nginx/templates/default.conf.template
COPY docker/web/conf/fastcgi_params /etc/nginx/fastcgi_params
COPY docker/web/start.sh /usr/local/bin/start
RUN chmod 755 /usr/local/bin/start
FROM nginx AS web_build_for_production
WORKDIR /home/app
COPY application /home/app
RUN apk --no-cache add git nodejs npm \
&& npm install && npm run build \
&& rm -rf /home/app/node_modules
FROM php AS app_build_for_production
WORKDIR /home/app
COPY application /home/app
RUN apk --no-cache add git \
RUN apk --no-cache add git \
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer \
&& composer install --optimize-autoloader --no-dev \
&& rm -rf /home/app/.env
&& rm -f /home/app/.env
FROM build AS production
FROM php AS app_production
COPY --from=app_build_for_production /home/app /var/www/html
COPY --from=web_build_for_production /home/app/public/build/ /var/www/html/public/build
COPY docker/php/start.sh /usr/local/bin/start
WORKDIR /var/www/html
@@ -57,8 +74,18 @@ USER www-data
EXPOSE 9000
CMD ["/usr/local/bin/start"]
FROM nginx AS web_production
FROM build AS develop
COPY --from=web_build_for_production /home/app/public /usr/share/nginx/html
RUN rm -f /usr/share/nginx/html/50x.html /usr/share/nginx/html/index.php /usr/share/nginx/html/.htaccess
WORKDIR /usr/share/nginx/html
EXPOSE 80
CMD ["/usr/local/bin/start"]
# develop
FROM php AS app_develop
WORKDIR /var/www/html
@@ -75,15 +102,12 @@ USER www-data
EXPOSE 9000
CMD ["/usr/local/bin/start"]
FROM build AS artisan
FROM php AS artisan
WORKDIR /var/www/html
STOPSIGNAL SIGTERM
ENTRYPOINT ["php", "/var/www/html/artisan"]
FROM build AS composer
FROM php AS composer
WORKDIR /var/www/html
STOPSIGNAL SIGTERM
RUN apk --no-cache add git \
@@ -91,11 +115,15 @@ RUN apk --no-cache add git \
RUN mkdir "/.composer" && chmod -R 0777 "/.composer"
ENTRYPOINT ["composer"]
FROM build AS npm
FROM php AS npm
RUN mkdir "/.npm" && chmod -R 0777 "/.npm"
WORKDIR /var/www/html
STOPSIGNAL SIGTERM
RUN apk --no-cache add nodejs npm
ENTRYPOINT ["npm"]
FROM nginx AS web_develop
WORKDIR /usr/share/nginx/html
EXPOSE 80
CMD ["/usr/local/bin/start"]
-31
View File
@@ -1,31 +0,0 @@
FROM docker.io/nginx:1.31-alpine AS build
COPY docker/web/conf/default.conf.template /etc/nginx/templates/default.conf.template
COPY docker/web/conf/fastcgi_params /etc/nginx/fastcgi_params
COPY docker/web/start.sh /usr/local/bin/start
RUN chmod 755 /usr/local/bin/start
FROM build AS app_build_for_production
WORKDIR /home/app
COPY application /home/app
RUN apk --no-cache add git nodejs npm \
&& npm install && npm run build \
&& rm -rf /home/app/node_modules
FROM build AS production
COPY --from=app_build_for_production /home/app/public /usr/share/nginx/html
WORKDIR /usr/share/nginx/html
EXPOSE 80
CMD ["/usr/local/bin/start"]
FROM build AS develop
WORKDIR /usr/share/nginx/html
EXPOSE 80
CMD ["/usr/local/bin/start"]
+9 -8
View File
@@ -3,8 +3,9 @@ services:
web:
build:
context: app
dockerfile: docker/web/Dockerfile
target: DEVELOP
dockerfile: docker/Dockerfile
target: WEB_PRODUCTION
# restart: always
depends_on:
- app
ports:
@@ -21,8 +22,8 @@ services:
app:
build:
context: app
dockerfile: docker/php/Dockerfile
target: PRODUCTION
dockerfile: docker/Dockerfile
target: APP_PRODUCTION
# restart: always
depends_on:
- db
@@ -37,8 +38,8 @@ services:
queue:
build:
context: app
dockerfile: docker/php/Dockerfile
target: PRODUCTION
dockerfile: docker/Dockerfile
target: APP_PRODUCTION
# restart: always
depends_on:
- app
@@ -52,8 +53,8 @@ services:
scheduler:
build:
context: app
dockerfile: docker/php/Dockerfile
target: PRODUCTION
dockerfile: docker/Dockerfile
target: APP_PRODUCTION
# restart: always
depends_on:
- app
+24 -8
View File
@@ -1,15 +1,29 @@
#version: '3.7'
services:
web:
# image: korelf/my-projects-website-web:0.7.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website-web:0.7.0 # MDHub
# restart: always
depends_on:
- app
ports:
- ${DOCKER_WEB_PORT}:80
environment:
IS_GZIP: 0
# FRONTEND_PORT: ${DOCKER_WEB_PORT}
BACKEND_HOST: app
BACKEND_PORT: 9000
TRUSTED_PROXY_CIDR: 172.16.0.0/12
volumes:
- ./app/storage/app/public:/usr/share/nginx/html/storage
app:
# image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# image: korelf/my-projects-website-app:0.7.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website-app:0.7.0 # MDHub
# restart: always
depends_on:
- db
- app-redis
- captcha-app
ports:
- ${DOCKER_APP_PORT}:9000
env_file: app/.env
environment:
CONTAINER_ROLE: app
@@ -20,8 +34,8 @@ services:
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
queue:
# image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# image: korelf/my-projects-website-app:0.7.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website-app:0.7.0 # MDHub
# restart: always
depends_on:
- app
@@ -29,6 +43,7 @@ services:
- app-redis
environment:
CONTAINER_ROLE: queue
APP_ENV: production
env_file: app/.env
volumes:
- ./app/storage/app:/var/www/html/storage/app
@@ -36,8 +51,8 @@ services:
# - ./app/translate/authorized_key.json:/var/www/html/storage/translation_service/authorized_key.json
scheduler:
# image: korelf/my-projects-website:0.6.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website:0.6.0 # MDHub
# image: korelf/my-projects-website-app:0.7.0 # docker hub
image: docker.mdhub.kor-elf.net/kor-elf/my-projects-website-app:0.7.0 # MDHub
# restart: always
depends_on:
- app
@@ -45,6 +60,7 @@ services:
- app-redis
environment:
CONTAINER_ROLE: scheduler
APP_ENV: production
env_file: app/.env
volumes:
- ./app/storage/app:/var/www/html/storage/app
+11 -11
View File
@@ -3,8 +3,8 @@ services:
web:
build:
context: app
dockerfile: docker/web/Dockerfile
target: DEVELOP
dockerfile: docker/Dockerfile
target: WEB_DEVELOP
depends_on:
- app
ports:
@@ -21,8 +21,8 @@ services:
app:
build:
context: app
dockerfile: docker/php/Dockerfile
target: DEVELOP
dockerfile: docker/Dockerfile
target: APP_DEVELOP
depends_on:
- db
- app-redis
@@ -36,8 +36,8 @@ services:
queue:
build:
context: app
dockerfile: docker/php/Dockerfile
target: DEVELOP
dockerfile: docker/Dockerfile
target: APP_DEVELOP
depends_on:
- db
- app
@@ -50,8 +50,8 @@ services:
scheduler:
build:
context: app
dockerfile: docker/php/Dockerfile
target: DEVELOP
dockerfile: docker/Dockerfile
target: APP_DEVELOP
depends_on:
- db
- app
@@ -146,7 +146,7 @@ services:
artisan:
build:
context: app
dockerfile: docker/php/Dockerfile
dockerfile: docker/Dockerfile
target: ARTISAN
user: "${UID}:${GID}"
volumes:
@@ -155,7 +155,7 @@ services:
composer:
build:
context: app
dockerfile: docker/php/Dockerfile
dockerfile: docker/Dockerfile
target: COMPOSER
user: "${UID}:${GID}"
volumes:
@@ -164,7 +164,7 @@ services:
npm:
build:
context: app
dockerfile: docker/php/Dockerfile
dockerfile: docker/Dockerfile
target: NPM
user: "${UID}:${GID}"
volumes: