Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18589823f3 | ||
|
|
ab2b3fd9ef | ||
|
|
123d9b306f | ||
|
|
ca3445103d | ||
| 18f3de1ba9 | |||
| 52571c651f | |||
|
|
b9712643de | ||
| e954402959 | |||
|
|
98d9032068 | ||
| 5f6277d412 |
@@ -31,6 +31,10 @@ frontend/services/dto/ # Types TypeScript
|
|||||||
frontend/i18n/locales/ # Fichiers de traduction
|
frontend/i18n/locales/ # Fichiers de traduction
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Composants UI
|
||||||
|
|
||||||
|
La librairie `@malio/layer-ui` fournit les composants de formulaire et d'action. La documentation complète des props, events et exemples d'utilisation se trouve dans `frontend/node_modules/@malio/layer-ui/COMPONENTS.md`. Toujours s'y référer avant d'utiliser un composant Malio.
|
||||||
|
|
||||||
## Commandes
|
## Commandes
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.1.22'
|
app.version: '0.1.26'
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
ports:
|
ports:
|
||||||
- "3003:3003"
|
- "3005:3003"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:1.27-alpine
|
image: nginx:1.27-alpine
|
||||||
@@ -47,7 +47,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
db:
|
db:
|
||||||
image: postgres:16-alpine
|
image: postgres:16-alpine
|
||||||
command: -p ${POSTGRES_PORT:-5436}
|
command: -p ${POSTGRES_PORT:-5437}
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
POSTGRES_USER: ${POSTGRES_USER}
|
POSTGRES_USER: ${POSTGRES_USER}
|
||||||
@@ -55,7 +55,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- pg_data:/var/lib/postgresql/data
|
- pg_data:/var/lib/postgresql/data
|
||||||
ports:
|
ports:
|
||||||
- "${POSTGRES_PORT:-5436}:${POSTGRES_PORT:-5436}"
|
- "${POSTGRES_PORT:-5437}:${POSTGRES_PORT:-5437}"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
pg_data:
|
pg_data:
|
||||||
|
|||||||
@@ -138,6 +138,7 @@
|
|||||||
"uptime": "Uptime",
|
"uptime": "Uptime",
|
||||||
"cpu": "CPU",
|
"cpu": "CPU",
|
||||||
"memory": "Memoire",
|
"memory": "Memoire",
|
||||||
|
"ports": "Ports",
|
||||||
"noData": "Aucune donnee disponible"
|
"noData": "Aucune donnee disponible"
|
||||||
},
|
},
|
||||||
"deploy": {
|
"deploy": {
|
||||||
|
|||||||
8
frontend/package-lock.json
generated
8
frontend/package-lock.json
generated
@@ -7,7 +7,7 @@
|
|||||||
"name": "nuxt-app",
|
"name": "nuxt-app",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@malio/layer-ui": "^1.2.2",
|
"@malio/layer-ui": "^1.2.3",
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/i18n": "^10.2.3",
|
"@nuxtjs/i18n": "^10.2.3",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
@@ -1668,9 +1668,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@malio/layer-ui": {
|
"node_modules/@malio/layer-ui": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"resolved": "https://gitea.malio.fr/api/packages/MALIO-DEV/npm/%40malio%2Flayer-ui/-/1.2.2/layer-ui-1.2.2.tgz",
|
"resolved": "https://gitea.malio.fr/api/packages/MALIO-DEV/npm/%40malio%2Flayer-ui/-/1.2.3/layer-ui-1.2.3.tgz",
|
||||||
"integrity": "sha512-nV4FL19rYSiXqMDTUlAtp6AYdj7YiwpHbf7/usiOPj7llpjHIC3GmcOX0X7oQeOMTtSU1aKL8k8wn1bhptrHYg==",
|
"integrity": "sha512-5nRnBzRkXfs3PfKwKl6sH2ikrmSK7lTifcd0TX1QZP3rFRVRTgcT6mrsrpsbR9PwI27OeCNm0X6d0Ii92Rq7Yg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"build:dist": "nuxt generate && rm -rf dist && cp -R .output/public dist"
|
"build:dist": "nuxt generate && rm -rf dist && cp -R .output/public dist"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@malio/layer-ui": "^1.2.2",
|
"@malio/layer-ui": "^1.2.3",
|
||||||
"@nuxt/icon": "^2.2.1",
|
"@nuxt/icon": "^2.2.1",
|
||||||
"@nuxtjs/i18n": "^10.2.3",
|
"@nuxtjs/i18n": "^10.2.3",
|
||||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ onMounted(loadApplication)
|
|||||||
<!-- Health metrics -->
|
<!-- Health metrics -->
|
||||||
<div v-if="healthByEnvId[env.id!]" class="mt-4 border-t border-neutral-200 py-3">
|
<div v-if="healthByEnvId[env.id!]" class="mt-4 border-t border-neutral-200 py-3">
|
||||||
<p class="text-sm font-bold uppercase tracking-wider mb-2">{{ t('environments.health.title') }}</p>
|
<p class="text-sm font-bold uppercase tracking-wider mb-2">{{ t('environments.health.title') }}</p>
|
||||||
<div class="grid grid-cols-2 sm:grid-cols-5 gap-3">
|
<div class="grid grid-cols-2 sm:grid-cols-6 gap-3">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-xs text-neutral-400">{{ t('environments.health.status') }}</p>
|
<p class="text-xs text-neutral-400">{{ t('environments.health.status') }}</p>
|
||||||
<span
|
<span
|
||||||
@@ -456,6 +456,19 @@ onMounted(loadApplication)
|
|||||||
<span class="text-neutral-400">({{ healthByEnvId[env.id!].memoryPercent }}%)</span>
|
<span class="text-neutral-400">({{ healthByEnvId[env.id!].memoryPercent }}%)</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-xs text-neutral-400">{{ t('environments.health.ports') }}</p>
|
||||||
|
<div v-if="healthByEnvId[env.id!].ports?.length" class="mt-1 flex flex-wrap gap-1">
|
||||||
|
<span
|
||||||
|
v-for="(p, i) in healthByEnvId[env.id!].ports"
|
||||||
|
:key="i"
|
||||||
|
class="inline-block rounded bg-neutral-100 px-2 py-0.5 text-xs font-mono text-neutral-700"
|
||||||
|
>
|
||||||
|
{{ p.hostPort }}:{{ p.containerPort }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p v-else class="text-sm text-neutral-400 mt-1">-</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center gap-4 mt-4">
|
<div class="flex justify-center gap-4 mt-4">
|
||||||
|
|||||||
@@ -20,18 +20,12 @@
|
|||||||
v-model="username"
|
v-model="username"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div>
|
<MalioInputPassword
|
||||||
<label class="text-sm font-semibold text-neutral-700" for="password">
|
v-model="password"
|
||||||
Mot de passe
|
label="Mot de passe"
|
||||||
</label>
|
autocomplete="current-password"
|
||||||
<input
|
inputClass="w-full"
|
||||||
id="password"
|
/>
|
||||||
v-model="password"
|
|
||||||
type="password"
|
|
||||||
autocomplete="current-password"
|
|
||||||
class="mt-2 w-full rounded-md border border-neutral-300 bg-white px-3 py-2 text-base text-neutral-900 focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-secondary-500/20"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<MalioButton
|
<MalioButton
|
||||||
label="Se connecter"
|
label="Se connecter"
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ type DashboardResponse = {
|
|||||||
applications: DashboardApplication[]
|
applications: DashboardApplication[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PortMapping = {
|
||||||
|
hostPort: string
|
||||||
|
containerPort: string
|
||||||
|
protocol: string
|
||||||
|
}
|
||||||
|
|
||||||
type EnvironmentHealth = {
|
type EnvironmentHealth = {
|
||||||
status: string
|
status: string
|
||||||
version: string
|
version: string
|
||||||
@@ -24,4 +30,5 @@ type EnvironmentHealth = {
|
|||||||
memoryUsage: string
|
memoryUsage: string
|
||||||
memoryLimit: string
|
memoryLimit: string
|
||||||
memoryPercent: number
|
memoryPercent: number
|
||||||
|
ports: PortMapping[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ APP_USER=www-data
|
|||||||
POSTGRES_DB=central
|
POSTGRES_DB=central
|
||||||
POSTGRES_USER=root
|
POSTGRES_USER=root
|
||||||
POSTGRES_PASSWORD=root
|
POSTGRES_PASSWORD=root
|
||||||
POSTGRES_PORT=5436
|
POSTGRES_PORT=5437
|
||||||
XDEBUG_CLIENT_HOST=host.docker.internal
|
XDEBUG_CLIENT_HOST=host.docker.internal
|
||||||
HOST_APPS_PATH=/home/user/workspace
|
HOST_APPS_PATH=/home/user/workspace
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ RUN mkdir -p /var/www/.composer/cache/vcs \
|
|||||||
ENV COMPOSER_HOME=/var/www/.composer
|
ENV COMPOSER_HOME=/var/www/.composer
|
||||||
|
|
||||||
# Création de la structure du projet
|
# Création de la structure du projet
|
||||||
RUN mkdir /var/www/html/LOG
|
RUN mkdir -p /var/www/html/LOG /var/www/html/var/cache /var/www/html/var/log
|
||||||
|
|
||||||
###> User ###
|
###> User ###
|
||||||
ARG CURRENT_UID
|
ARG CURRENT_UID
|
||||||
|
|||||||
@@ -40,10 +40,16 @@ FROM php:8.4-fpm AS production
|
|||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
libicu-dev libpq-dev libpng-dev libzip-dev libxml2-dev \
|
libicu-dev libpq-dev libpng-dev libzip-dev libxml2-dev \
|
||||||
nginx supervisor docker.io \
|
nginx supervisor docker.io curl \
|
||||||
&& docker-php-ext-install -j$(nproc) intl pdo_pgsql zip gd opcache \
|
&& docker-php-ext-install -j$(nproc) intl pdo_pgsql zip gd opcache \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install Docker Compose plugin
|
||||||
|
RUN DOCKER_COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep '"tag_name"' | sed 's/.*"v\(.*\)".*/\1/') \
|
||||||
|
&& mkdir -p /usr/local/lib/docker/cli-plugins \
|
||||||
|
&& curl -SL "https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64" -o /usr/local/lib/docker/cli-plugins/docker-compose \
|
||||||
|
&& chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
|
||||||
|
|
||||||
# PHP production config
|
# PHP production config
|
||||||
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
|
||||||
|
|
||||||
|
|||||||
6
makefile
6
makefile
@@ -43,7 +43,11 @@ install: composer-install cache-clear node-use build-nuxtJS migration-migrate
|
|||||||
# Supprime tout est réinstalle tout (Attention ça supprime la bdd aussi)
|
# Supprime tout est réinstalle tout (Attention ça supprime la bdd aussi)
|
||||||
reset: delete_built_dir remove_orphans build-without-cache start wait install
|
reset: delete_built_dir remove_orphans build-without-cache start wait install
|
||||||
|
|
||||||
composer-install:
|
fix-permissions:
|
||||||
|
$(EXEC_PHP_ROOT) mkdir -p var/cache var/log
|
||||||
|
$(EXEC_PHP_ROOT) chown -R $(APP_USER):$(APP_USER) var/
|
||||||
|
|
||||||
|
composer-install: fix-permissions
|
||||||
$(EXEC_PHP) composer install
|
$(EXEC_PHP) composer install
|
||||||
$(SYMFONY_CONSOLE) lexik:jwt:generate-keypair --skip-if-exists
|
$(SYMFONY_CONSOLE) lexik:jwt:generate-keypair --skip-if-exists
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,6 @@ final class EnvironmentHealth
|
|||||||
public string $memoryUsage = '';
|
public string $memoryUsage = '';
|
||||||
public string $memoryLimit = '';
|
public string $memoryLimit = '';
|
||||||
public float $memoryPercent = 0.0;
|
public float $memoryPercent = 0.0;
|
||||||
|
/** @var list<array{hostPort: string, containerPort: string, protocol: string}> */
|
||||||
|
public array $ports = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ final class DockerService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{status: string, image: string, version: string, startedAt: string}
|
* @return array{status: string, image: string, version: string, startedAt: string, ports: list<array{hostPort: string, containerPort: string, protocol: string}>}
|
||||||
*/
|
*/
|
||||||
public function getContainerStatus(string $containerName): array
|
public function getContainerStatus(string $containerName): array
|
||||||
{
|
{
|
||||||
@@ -33,12 +33,13 @@ final class DockerService
|
|||||||
'image' => '',
|
'image' => '',
|
||||||
'version' => '',
|
'version' => '',
|
||||||
'startedAt' => '',
|
'startedAt' => '',
|
||||||
|
'ports' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$process = new Process([
|
$process = new Process([
|
||||||
'docker', 'inspect',
|
'docker', 'inspect',
|
||||||
'--format', '{{.State.Status}}||{{.Config.Image}}||{{.State.StartedAt}}',
|
'--format', '{{.State.Status}}||{{.Config.Image}}||{{.State.StartedAt}}||{{json .NetworkSettings.Ports}}',
|
||||||
$containerName,
|
$containerName,
|
||||||
]);
|
]);
|
||||||
$process->setTimeout(10);
|
$process->setTimeout(10);
|
||||||
@@ -50,10 +51,11 @@ final class DockerService
|
|||||||
'image' => '',
|
'image' => '',
|
||||||
'version' => '',
|
'version' => '',
|
||||||
'startedAt' => '',
|
'startedAt' => '',
|
||||||
|
'ports' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$parts = explode('||', trim($process->getOutput()));
|
$parts = explode('||', trim($process->getOutput()), 4);
|
||||||
|
|
||||||
if (\count($parts) < 3) {
|
if (\count($parts) < 3) {
|
||||||
return [
|
return [
|
||||||
@@ -61,6 +63,7 @@ final class DockerService
|
|||||||
'image' => '',
|
'image' => '',
|
||||||
'version' => '',
|
'version' => '',
|
||||||
'startedAt' => '',
|
'startedAt' => '',
|
||||||
|
'ports' => [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,11 +73,32 @@ final class DockerService
|
|||||||
$version = substr($image, strrpos($image, ':') + 1);
|
$version = substr($image, strrpos($image, ':') + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$ports = [];
|
||||||
|
if (isset($parts[3])) {
|
||||||
|
$portsJson = json_decode($parts[3], true);
|
||||||
|
if (\is_array($portsJson)) {
|
||||||
|
foreach ($portsJson as $containerPort => $bindings) {
|
||||||
|
if (!\is_array($bindings)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
[$port, $protocol] = explode('/', $containerPort) + [1 => 'tcp'];
|
||||||
|
foreach ($bindings as $binding) {
|
||||||
|
$ports[] = [
|
||||||
|
'hostPort' => $binding['HostPort'] ?? '',
|
||||||
|
'containerPort' => $port,
|
||||||
|
'protocol' => $protocol,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'status' => $parts[0],
|
'status' => $parts[0],
|
||||||
'image' => $image,
|
'image' => $image,
|
||||||
'version' => $version,
|
'version' => $version,
|
||||||
'startedAt' => $parts[2],
|
'startedAt' => $parts[2],
|
||||||
|
'ports' => $ports,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ final readonly class EnvironmentHealthProvider implements ProviderInterface
|
|||||||
$dto->memoryUsage = $stats['memoryUsage'];
|
$dto->memoryUsage = $stats['memoryUsage'];
|
||||||
$dto->memoryLimit = $stats['memoryLimit'];
|
$dto->memoryLimit = $stats['memoryLimit'];
|
||||||
$dto->memoryPercent = $stats['memoryPercent'];
|
$dto->memoryPercent = $stats['memoryPercent'];
|
||||||
|
$dto->ports = $status['ports'];
|
||||||
|
|
||||||
return $dto;
|
return $dto;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user