diff --git a/.gitignore b/.gitignore index 0976ad5..2a8db47 100644 --- a/.gitignore +++ b/.gitignore @@ -1,111 +1,111 @@ -# ============================================ -# Quarkus JSF Frontend .gitignore -# ============================================ - -# Maven -target/ -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties -.mvn/wrapper/maven-wrapper.jar - -# Quarkus -.quarkus/ -quarkus.log - -# IDE -.idea/ -*.iml -*.ipr -*.iws -.vscode/ -.classpath -.project -.settings/ -.factorypath -.apt_generated/ -.apt_generated_tests/ - -# Eclipse -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.loadpath -.recommenders - -# IntelliJ -out/ -.idea_modules/ - -# Logs -*.log -*.log.* -logs/ - -# OS -.DS_Store -Thumbs.db -*.pid - -# Java -*.class -*.jar -!.mvn/wrapper/maven-wrapper.jar -*.war -*.ear -hs_err_pid* - -# JSF/Faces specific -**/META-INF/resources/.faces-config.xml.jsfdia -**/javax.faces.resource/ - -# PrimeFaces cache -**/primefaces_resource_cache/ - -# Node modules (if using npm/webpack) -node_modules/ -npm-debug.log -yarn-error.log -package-lock.json -yarn.lock - -# Static resources compiled -src/main/resources/META-INF/resources/dist/ -src/main/resources/META-INF/resources/assets/vendor/ - -# Application secrets -*.jks -*.p12 -*.pem -*.key -*-secret.properties -application-local.properties -application-dev-override.properties - -# Docker -.dockerignore -docker-compose.override.yml - -# Database -*.db -*.sqlite -*.h2.db - -# Test -test-output/ -.gradle/ -build/ - -# Temporary -.tmp/ -temp/ +# ============================================ +# Quarkus JSF Frontend .gitignore +# ============================================ + +# Maven +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + +# Quarkus +.quarkus/ +quarkus.log + +# IDE +.idea/ +*.iml +*.ipr +*.iws +.vscode/ +.classpath +.project +.settings/ +.factorypath +.apt_generated/ +.apt_generated_tests/ + +# Eclipse +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.loadpath +.recommenders + +# IntelliJ +out/ +.idea_modules/ + +# Logs +*.log +*.log.* +logs/ + +# OS +.DS_Store +Thumbs.db +*.pid + +# Java +*.class +*.jar +!.mvn/wrapper/maven-wrapper.jar +*.war +*.ear +hs_err_pid* + +# JSF/Faces specific +**/META-INF/resources/.faces-config.xml.jsfdia +**/javax.faces.resource/ + +# PrimeFaces cache +**/primefaces_resource_cache/ + +# Node modules (if using npm/webpack) +node_modules/ +npm-debug.log +yarn-error.log +package-lock.json +yarn.lock + +# Static resources compiled +src/main/resources/META-INF/resources/dist/ +src/main/resources/META-INF/resources/assets/vendor/ + +# Application secrets +*.jks +*.p12 +*.pem +*.key +*-secret.properties +application-local.properties +application-dev-override.properties + +# Docker +.dockerignore +docker-compose.override.yml + +# Database +*.db +*.sqlite +*.h2.db + +# Test +test-output/ +.gradle/ +build/ + +# Temporary +.tmp/ +temp/ diff --git a/BUILD-SYNC-API.md b/BUILD-SYNC-API.md index a13c458..c785878 100644 --- a/BUILD-SYNC-API.md +++ b/BUILD-SYNC-API.md @@ -1,19 +1,19 @@ -# Build pour éviter 404 sur le dashboard Sync - -Le client utilise l’interface **SyncResourceApi** du module `lions-user-manager-server-api`. -Si vous lancez uniquement `mvn quarkus:dev` dans le client, une ancienne version de l’API (en cache dans `.m2`) peut être utilisée et provoquer des **404** sur `/api/sync/keycloak-health`, `/api/sync/users`, etc. - -**À faire une fois** (ou après toute modification de l’API) : - -Depuis la **racine** `lions-user-manager` : - -```bash -mvn clean install -pl lions-user-manager-server-api,lions-user-manager-server-impl-quarkus,lions-user-manager-client-quarkus-primefaces-freya -am -``` - -Puis lancer le serveur et le client chacun dans son terminal : - -- **Terminal 1** (serveur) : `cd lions-user-manager-server-impl-quarkus && mvn quarkus:dev` -- **Terminal 2** (client) : `cd lions-user-manager-client-quarkus-primefaces-freya && mvn quarkus:dev` - -Le client appelle le backend sur **http://localhost:8081** (configuré dans `application-dev.properties`). +# Build pour éviter 404 sur le dashboard Sync + +Le client utilise l’interface **SyncResourceApi** du module `lions-user-manager-server-api`. +Si vous lancez uniquement `mvn quarkus:dev` dans le client, une ancienne version de l’API (en cache dans `.m2`) peut être utilisée et provoquer des **404** sur `/api/sync/keycloak-health`, `/api/sync/users`, etc. + +**À faire une fois** (ou après toute modification de l’API) : + +Depuis la **racine** `lions-user-manager` : + +```bash +mvn clean install -pl lions-user-manager-server-api,lions-user-manager-server-impl-quarkus,lions-user-manager-client-quarkus-primefaces-freya -am +``` + +Puis lancer le serveur et le client chacun dans son terminal : + +- **Terminal 1** (serveur) : `cd lions-user-manager-server-impl-quarkus && mvn quarkus:dev` +- **Terminal 2** (client) : `cd lions-user-manager-client-quarkus-primefaces-freya && mvn quarkus:dev` + +Le client appelle le backend sur **http://localhost:8081** (configuré dans `application-dev.properties`). diff --git a/Dockerfile.prod b/Dockerfile.prod index e4d5f3b..ef5df23 100644 --- a/Dockerfile.prod +++ b/Dockerfile.prod @@ -1,93 +1,93 @@ -#### -# Dockerfile de production pour Lions User Manager Client (Frontend) -# Multi-stage build optimisé avec sécurité renforcée -# Basé sur la structure de btpxpress-client -#### - -## Stage 1 : Build avec Maven -FROM maven:3.9.6-eclipse-temurin-17 AS builder - -WORKDIR /app - -# Copier pom.xml et télécharger les dépendances (cache Docker) -COPY pom.xml . -RUN mvn dependency:go-offline -B - -# Copier le code source -COPY src ./src - -# Build de l'application avec profil production (fast-jar par défaut) -RUN mvn clean package -DskipTests -B -Dquarkus.profile=prod - -## Stage 2 : Image de production optimisée et sécurisée -FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 - -ENV LANGUAGE='fr_FR:fr' - -# Variables d'environnement de production -# Ces valeurs peuvent être surchargées via docker-compose ou Kubernetes -ENV QUARKUS_PROFILE=prod -ENV QUARKUS_HTTP_PORT=8080 -ENV QUARKUS_HTTP_HOST=0.0.0.0 - -# Proxy forwarding (SSL termination par l'ingress nginx K8s) -ENV QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING=true -ENV QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED=true - -# Configuration Keycloak/OIDC (production) -ENV QUARKUS_OIDC_AUTH_SERVER_URL=https://security.lions.dev/realms/lions-user-manager -ENV QUARKUS_OIDC_CLIENT_ID=lions-user-manager-client -ENV KEYCLOAK_CLIENT_SECRET=oGCivOdgbNHroNsHS1MRBZJXX8VpRGk3 -ENV QUARKUS_OIDC_CREDENTIALS_SECRET=oGCivOdgbNHroNsHS1MRBZJXX8VpRGk3 -ENV QUARKUS_OIDC_ENABLED=true -ENV QUARKUS_OIDC_TLS_VERIFICATION=required -ENV QUARKUS_OIDC_AUTHENTICATION_COOKIE_SAME_SITE=lax -ENV OIDC_ENCRYPTION_SECRET=gbztZB3CYpou0vFL2LqOWJQdXnvwVQkhjrHpsZHOJPI= - -# Configuration API Backend -ENV LIONS_USER_MANAGER_BACKEND_URL=https://api.lions.dev/lions-user-manager - -# Configuration CORS -ENV QUARKUS_HTTP_CORS_ORIGINS=https://users.lions.dev,https://admin.lions.dev -ENV QUARKUS_HTTP_CORS_ALLOW_CREDENTIALS=true - -# Installer curl pour les health checks -USER root -RUN microdnf install -y curl && \ - microdnf clean all && \ - rm -rf /var/cache/yum - -# Créer les répertoires et permissions pour utilisateur non-root -RUN mkdir -p /deployments /app/logs && \ - chown -R 185:185 /deployments /app/logs - -# Passer à l'utilisateur non-root pour la sécurité -USER 185 - -# Copier l'application depuis le builder (format fast-jar Quarkus) -COPY --from=builder --chown=185 /app/target/quarkus-app/ /deployments/ - -# Exposer le port -EXPOSE 8080 - -# Variables JVM optimisées pour production avec sécurité -ENV JAVA_OPTS="-Xmx768m -Xms256m \ - -XX:+UseG1GC \ - -XX:MaxGCPauseMillis=200 \ - -XX:+UseStringDeduplication \ - -XX:+ParallelRefProcEnabled \ - -XX:+HeapDumpOnOutOfMemoryError \ - -XX:HeapDumpPath=/app/logs/heapdump.hprof \ - -Djava.security.egd=file:/dev/./urandom \ - -Djava.awt.headless=true \ - -Dfile.encoding=UTF-8 \ - -Djava.util.logging.manager=org.jboss.logmanager.LogManager \ - -Dquarkus.profile=${QUARKUS_PROFILE}" - -# Health check avec endpoints Quarkus -HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \ - CMD curl -f http://localhost:8080/q/health/ready || exit 1 - -# Point d'entrée avec profil production (format fast-jar) -ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /deployments/quarkus-run.jar"] - +#### +# Dockerfile de production pour Lions User Manager Client (Frontend) +# Multi-stage build optimisé avec sécurité renforcée +# Basé sur la structure de btpxpress-client +#### + +## Stage 1 : Build avec Maven +FROM maven:3.9.6-eclipse-temurin-17 AS builder + +WORKDIR /app + +# Copier pom.xml et télécharger les dépendances (cache Docker) +COPY pom.xml . +RUN mvn dependency:go-offline -B + +# Copier le code source +COPY src ./src + +# Build de l'application avec profil production (fast-jar par défaut) +RUN mvn clean package -DskipTests -B -Dquarkus.profile=prod + +## Stage 2 : Image de production optimisée et sécurisée +FROM registry.access.redhat.com/ubi8/openjdk-17:1.18 + +ENV LANGUAGE='fr_FR:fr' + +# Variables d'environnement de production +# Ces valeurs peuvent être surchargées via docker-compose ou Kubernetes +ENV QUARKUS_PROFILE=prod +ENV QUARKUS_HTTP_PORT=8080 +ENV QUARKUS_HTTP_HOST=0.0.0.0 + +# Proxy forwarding (SSL termination par l'ingress nginx K8s) +ENV QUARKUS_HTTP_PROXY_PROXY_ADDRESS_FORWARDING=true +ENV QUARKUS_HTTP_PROXY_ALLOW_X_FORWARDED=true + +# Configuration Keycloak/OIDC (production) +ENV QUARKUS_OIDC_AUTH_SERVER_URL=https://security.lions.dev/realms/lions-user-manager +ENV QUARKUS_OIDC_CLIENT_ID=lions-user-manager-client +ENV KEYCLOAK_CLIENT_SECRET=oGCivOdgbNHroNsHS1MRBZJXX8VpRGk3 +ENV QUARKUS_OIDC_CREDENTIALS_SECRET=oGCivOdgbNHroNsHS1MRBZJXX8VpRGk3 +ENV QUARKUS_OIDC_ENABLED=true +ENV QUARKUS_OIDC_TLS_VERIFICATION=required +ENV QUARKUS_OIDC_AUTHENTICATION_COOKIE_SAME_SITE=lax +ENV OIDC_ENCRYPTION_SECRET=gbztZB3CYpou0vFL2LqOWJQdXnvwVQkhjrHpsZHOJPI= + +# Configuration API Backend +ENV LIONS_USER_MANAGER_BACKEND_URL=https://api.lions.dev/lions-user-manager + +# Configuration CORS +ENV QUARKUS_HTTP_CORS_ORIGINS=https://users.lions.dev,https://admin.lions.dev +ENV QUARKUS_HTTP_CORS_ALLOW_CREDENTIALS=true + +# Installer curl pour les health checks +USER root +RUN microdnf install -y curl && \ + microdnf clean all && \ + rm -rf /var/cache/yum + +# Créer les répertoires et permissions pour utilisateur non-root +RUN mkdir -p /deployments /app/logs && \ + chown -R 185:185 /deployments /app/logs + +# Passer à l'utilisateur non-root pour la sécurité +USER 185 + +# Copier l'application depuis le builder (format fast-jar Quarkus) +COPY --from=builder --chown=185 /app/target/quarkus-app/ /deployments/ + +# Exposer le port +EXPOSE 8080 + +# Variables JVM optimisées pour production avec sécurité +ENV JAVA_OPTS="-Xmx768m -Xms256m \ + -XX:+UseG1GC \ + -XX:MaxGCPauseMillis=200 \ + -XX:+UseStringDeduplication \ + -XX:+ParallelRefProcEnabled \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:HeapDumpPath=/app/logs/heapdump.hprof \ + -Djava.security.egd=file:/dev/./urandom \ + -Djava.awt.headless=true \ + -Dfile.encoding=UTF-8 \ + -Djava.util.logging.manager=org.jboss.logmanager.LogManager \ + -Dquarkus.profile=${QUARKUS_PROFILE}" + +# Health check avec endpoints Quarkus +HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \ + CMD curl -f http://localhost:8080/q/health/ready || exit 1 + +# Point d'entrée avec profil production (format fast-jar) +ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /deployments/quarkus-run.jar"] + diff --git a/README.md b/README.md index c81fef5..d89333b 100644 --- a/README.md +++ b/README.md @@ -1,141 +1,141 @@ -# lions-user-manager-client-quarkus-primefaces-freya - -> Interface web d'administration — Quarkus + JSF + PrimeFaces Freya - -## Dépôt Git - -`https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya` - ---- - -## Responsabilités - -- Interface d'administration des utilisateurs et rôles Keycloak -- Authentification SSO via OIDC (Keycloak) -- Communication avec le backend via MicroProfile REST Client -- Dashboard, gestion CRUD, audit, synchronisation, assignation de realms - ---- - -## Pages - -| Page | Bean | Description | -|------|------|-------------| -| `/dashboard.xhtml` | `DashboardBean` | Vue d'ensemble et statistiques | -| `/users/list.xhtml` | `UserListBean` | Liste paginée avec filtres et export CSV | -| `/users/creation.xhtml` | `UserCreationBean` | Formulaire de création | -| `/users/profil.xhtml` | `UserProfilBean` | Édition profil utilisateur | -| `/roles/gestion.xhtml` | `RoleGestionBean` | Gestion des rôles par realm | -| `/audit/consultation.xhtml` | `AuditConsultationBean` | Consultation des logs d'audit | -| `/sync/dashboard.xhtml` | `SyncDashboardBean` | État et pilotage des synchronisations | -| `/realms/assignment.xhtml` | `RealmAssignmentBean` | Assignation utilisateurs/realms | - ---- - -## Stack - -| Composant | Technologie | -|-----------|-------------| -| Framework | Quarkus 3.17.8 + Undertow (Servlet) | -| UI | PrimeFaces 14.0.5 (Jakarta) | -| Thème | Freya Enterprise | -| Auth | `quarkus-oidc` (Keycloak) + PKCE | -| REST Client | MicroProfile REST Client (`quarkus-rest-client-jackson`) | -| Token Propagation | `quarkus-rest-client-oidc-token-propagation` | - ---- - -## Développement local - -### Prérequis - -- Java 17+, Maven 3.9+ -- Keycloak sur `localhost:8180` (realm `lions-user-manager` configuré) -- Backend `server-impl` démarré sur `localhost:8081` - -### Démarrage - -```bash -mvn quarkus:dev -``` - -Application disponible sur : `http://localhost:8082` - -### Configuration dev - -Fichier : `src/main/resources/application-dev.properties` - -```properties -quarkus.http.port=8082 -quarkus.oidc.auth-server-url=http://localhost:8180/realms/lions-user-manager -lions.user.manager.backend.url=http://localhost:8081 -``` - ---- - -## Configuration production - -Fichier : `src/main/resources/application-prod.properties` - -| Variable | Description | -|----------|-------------| -| `KEYCLOAK_AUTH_SERVER_URL` | URL du realm Keycloak | -| `KEYCLOAK_CLIENT_ID` | Client OIDC (défaut : `lions-user-manager-client`) | -| `OIDC_ENCRYPTION_SECRET` | Secret de chiffrement des tokens (32 caractères min) | -| `LIONS_USER_MANAGER_BACKEND_URL` | URL de l'API backend | - ---- - -## Build - -```bash -# Build standard (développement) -mvn clean package -DskipTests - -# Build production -mvn clean package -P prod -DskipTests -``` - ---- - -## Déploiement (lionsctl) - -```bash -lionsctl pipeline \ - -u https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya \ - -b main -j 17 -e production -c k1 -p prod -``` - -**Pipeline** : clone → `mvn package -P prod` → `docker build -f Dockerfile.prod` → push `registry.lions.dev` → `kubectl apply` → health check - -**URL prod** : `https://users.lions.dev` - ---- - -## Structure - -``` -src/main/ -├── java/dev/lions/user/manager/client/ -│ ├── bean/ # Beans JSF (@Named, @ViewScoped / @SessionScoped) -│ └── client/ # REST Clients (UserRestClient, RoleRestClient, ...) -└── resources/ - ├── META-INF/resources/ - │ ├── templates/ - │ │ └── components/ # Composants PrimeFaces réutilisables - │ ├── dashboard.xhtml - │ ├── users/ - │ ├── roles/ - │ ├── audit/ - │ ├── sync/ - │ └── realms/ - ├── application.properties - ├── application-dev.properties - └── application-prod.properties -``` - ---- - -## Licence - -Propriétaire — Lions Dev © 2025 +# lions-user-manager-client-quarkus-primefaces-freya + +> Interface web d'administration — Quarkus + JSF + PrimeFaces Freya + +## Dépôt Git + +`https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya` + +--- + +## Responsabilités + +- Interface d'administration des utilisateurs et rôles Keycloak +- Authentification SSO via OIDC (Keycloak) +- Communication avec le backend via MicroProfile REST Client +- Dashboard, gestion CRUD, audit, synchronisation, assignation de realms + +--- + +## Pages + +| Page | Bean | Description | +|------|------|-------------| +| `/dashboard.xhtml` | `DashboardBean` | Vue d'ensemble et statistiques | +| `/users/list.xhtml` | `UserListBean` | Liste paginée avec filtres et export CSV | +| `/users/creation.xhtml` | `UserCreationBean` | Formulaire de création | +| `/users/profil.xhtml` | `UserProfilBean` | Édition profil utilisateur | +| `/roles/gestion.xhtml` | `RoleGestionBean` | Gestion des rôles par realm | +| `/audit/consultation.xhtml` | `AuditConsultationBean` | Consultation des logs d'audit | +| `/sync/dashboard.xhtml` | `SyncDashboardBean` | État et pilotage des synchronisations | +| `/realms/assignment.xhtml` | `RealmAssignmentBean` | Assignation utilisateurs/realms | + +--- + +## Stack + +| Composant | Technologie | +|-----------|-------------| +| Framework | Quarkus 3.17.8 + Undertow (Servlet) | +| UI | PrimeFaces 14.0.5 (Jakarta) | +| Thème | Freya Enterprise | +| Auth | `quarkus-oidc` (Keycloak) + PKCE | +| REST Client | MicroProfile REST Client (`quarkus-rest-client-jackson`) | +| Token Propagation | `quarkus-rest-client-oidc-token-propagation` | + +--- + +## Développement local + +### Prérequis + +- Java 17+, Maven 3.9+ +- Keycloak sur `localhost:8180` (realm `lions-user-manager` configuré) +- Backend `server-impl` démarré sur `localhost:8081` + +### Démarrage + +```bash +mvn quarkus:dev +``` + +Application disponible sur : `http://localhost:8082` + +### Configuration dev + +Fichier : `src/main/resources/application-dev.properties` + +```properties +quarkus.http.port=8082 +quarkus.oidc.auth-server-url=http://localhost:8180/realms/lions-user-manager +lions.user.manager.backend.url=http://localhost:8081 +``` + +--- + +## Configuration production + +Fichier : `src/main/resources/application-prod.properties` + +| Variable | Description | +|----------|-------------| +| `KEYCLOAK_AUTH_SERVER_URL` | URL du realm Keycloak | +| `KEYCLOAK_CLIENT_ID` | Client OIDC (défaut : `lions-user-manager-client`) | +| `OIDC_ENCRYPTION_SECRET` | Secret de chiffrement des tokens (32 caractères min) | +| `LIONS_USER_MANAGER_BACKEND_URL` | URL de l'API backend | + +--- + +## Build + +```bash +# Build standard (développement) +mvn clean package -DskipTests + +# Build production +mvn clean package -P prod -DskipTests +``` + +--- + +## Déploiement (lionsctl) + +```bash +lionsctl pipeline \ + -u https://git.lions.dev/lionsdev/lions-user-manager-client-quarkus-primefaces-freya \ + -b main -j 17 -e production -c k1 -p prod +``` + +**Pipeline** : clone → `mvn package -P prod` → `docker build -f Dockerfile.prod` → push `registry.lions.dev` → `kubectl apply` → health check + +**URL prod** : `https://users.lions.dev` + +--- + +## Structure + +``` +src/main/ +├── java/dev/lions/user/manager/client/ +│ ├── bean/ # Beans JSF (@Named, @ViewScoped / @SessionScoped) +│ └── client/ # REST Clients (UserRestClient, RoleRestClient, ...) +└── resources/ + ├── META-INF/resources/ + │ ├── templates/ + │ │ └── components/ # Composants PrimeFaces réutilisables + │ ├── dashboard.xhtml + │ ├── users/ + │ ├── roles/ + │ ├── audit/ + │ ├── sync/ + │ └── realms/ + ├── application.properties + ├── application-dev.properties + └── application-prod.properties +``` + +--- + +## Licence + +Propriétaire — Lions Dev © 2025 diff --git a/pom.xml b/pom.xml index ebd0dee..ae99e7a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,42 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - dev.lions.user.manager - lions-user-manager-parent - 1.0.0 - + dev.lions.user.manager + 1.1.0 + + + 21 + ${java.version} + ${java.version} + UTF-8 + 3.27.3 + 1.18.38 + 1.0.3 + + + + + + io.quarkus.platform + quarkus-bom + ${quarkus.platform.version} + pom + import + + + dev.lions.user.manager + lions-user-manager-server-api + ${project.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + lions-user-manager-client-quarkus-primefaces-freya jar @@ -26,66 +57,39 @@ + + + + + + + dev.lions + lions-faces-layout + 1.0.3 + + dev.lions.user.manager lions-user-manager-server-api - - - io.quarkiverse.primefaces - quarkus-primefaces - 3.15.1 - - + io.quarkus quarkus-rest-client-jackson - - io.quarkus - quarkus-oidc - - io.quarkus quarkus-rest-client-oidc-token-propagation - - io.quarkus - quarkus-security - - io.quarkus quarkus-hibernate-validator - - - org.primefaces - primefaces - 14.0.5 - jakarta - - - - - org.primefaces.themes - freya-theme-jakarta - 5.0.0 - - - - - io.quarkiverse.omnifaces - quarkus-omnifaces - 4.4.1 - - io.quarkus @@ -135,6 +139,7 @@ io.quarkus.platform quarkus-maven-plugin + ${quarkus.platform.version} @@ -149,6 +154,7 @@ org.apache.maven.plugins maven-compiler-plugin + 3.13.0 21 @@ -157,6 +163,7 @@ org.apache.maven.plugins maven-surefire-plugin + 3.5.2 diff --git a/script/docker/dependencies-docker-compose.yml b/script/docker/dependencies-docker-compose.yml index 68c05d6..ac12994 100644 --- a/script/docker/dependencies-docker-compose.yml +++ b/script/docker/dependencies-docker-compose.yml @@ -1,37 +1,37 @@ -# Dépendances pour le client : Postgres + Keycloak (et optionnellement le serveur API) -# Pour run-dev, le serveur tourne en local (mvn quarkus:dev) et le client pointe vers localhost:8080 -services: - postgres: - image: postgres:15 - environment: - POSTGRES_DB: ${DB_NAME:-lions_user_manager} - POSTGRES_USER: ${DB_USER:-lions} - POSTGRES_PASSWORD: ${DB_PASSWORD:-lions} - ports: - - "${DB_PORT:-5432}:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-lions} -d ${DB_NAME:-lions_user_manager}"] - interval: 5s - timeout: 5s - retries: 5 - - keycloak: - image: quay.io/keycloak/keycloak:26.3.3 - command: start-dev - environment: - KC_DB: postgres - KC_DB_URL: jdbc:postgresql://postgres:5432/${DB_NAME:-lions_user_manager} - KC_DB_USERNAME: ${DB_USER:-lions} - KC_DB_PASSWORD: ${DB_PASSWORD:-lions} - KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_ADMIN:-admin} - KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:-admin} - ports: - - "${KC_PORT:-8180}:8080" - depends_on: - postgres: - condition: service_healthy - -volumes: - postgres_data: +# Dépendances pour le client : Postgres + Keycloak (et optionnellement le serveur API) +# Pour run-dev, le serveur tourne en local (mvn quarkus:dev) et le client pointe vers localhost:8080 +services: + postgres: + image: postgres:15 + environment: + POSTGRES_DB: ${DB_NAME:-lions_user_manager} + POSTGRES_USER: ${DB_USER:-lions} + POSTGRES_PASSWORD: ${DB_PASSWORD:-lions} + ports: + - "${DB_PORT:-5432}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-lions} -d ${DB_NAME:-lions_user_manager}"] + interval: 5s + timeout: 5s + retries: 5 + + keycloak: + image: quay.io/keycloak/keycloak:26.3.3 + command: start-dev + environment: + KC_DB: postgres + KC_DB_URL: jdbc:postgresql://postgres:5432/${DB_NAME:-lions_user_manager} + KC_DB_USERNAME: ${DB_USER:-lions} + KC_DB_PASSWORD: ${DB_PASSWORD:-lions} + KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_ADMIN:-admin} + KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:-admin} + ports: + - "${KC_PORT:-8180}:8080" + depends_on: + postgres: + condition: service_healthy + +volumes: + postgres_data: diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index cb37e4e..a5692cc 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -1,49 +1,49 @@ -# Client + Keycloak + Postgres (serveur API à lancer à part ou via stack racine) -services: - postgres: - image: postgres:15 - environment: - POSTGRES_DB: ${DB_NAME:-lions_user_manager} - POSTGRES_USER: ${DB_USER:-lions} - POSTGRES_PASSWORD: ${DB_PASSWORD:-lions} - ports: - - "${DB_PORT:-5432}:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-lions} -d ${DB_NAME:-lions_user_manager}"] - interval: 5s - timeout: 5s - retries: 5 - - keycloak: - image: quay.io/keycloak/keycloak:26.3.3 - command: start-dev - environment: - KC_DB: postgres - KC_DB_URL: jdbc:postgresql://postgres:5432/${DB_NAME:-lions_user_manager} - KC_DB_USERNAME: ${DB_USER:-lions} - KC_DB_PASSWORD: ${DB_PASSWORD:-lions} - KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_ADMIN:-admin} - KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:-admin} - ports: - - "${KC_PORT:-8180}:8080" - depends_on: - postgres: - condition: service_healthy - - lions-user-manager-client: - build: - context: ../.. - dockerfile: src/main/docker/Dockerfile.jvm - ports: - - "${CLIENT_PORT:-8082}:8082" - environment: - KEYCLOAK_SERVER_URL: http://keycloak:8080 - LIONS_USER_MANAGER_API_URL: ${LIONS_USER_MANAGER_API_URL:-http://host.docker.internal:8080} - depends_on: - keycloak: - condition: service_started - -volumes: - postgres_data: +# Client + Keycloak + Postgres (serveur API à lancer à part ou via stack racine) +services: + postgres: + image: postgres:15 + environment: + POSTGRES_DB: ${DB_NAME:-lions_user_manager} + POSTGRES_USER: ${DB_USER:-lions} + POSTGRES_PASSWORD: ${DB_PASSWORD:-lions} + ports: + - "${DB_PORT:-5432}:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-lions} -d ${DB_NAME:-lions_user_manager}"] + interval: 5s + timeout: 5s + retries: 5 + + keycloak: + image: quay.io/keycloak/keycloak:26.3.3 + command: start-dev + environment: + KC_DB: postgres + KC_DB_URL: jdbc:postgresql://postgres:5432/${DB_NAME:-lions_user_manager} + KC_DB_USERNAME: ${DB_USER:-lions} + KC_DB_PASSWORD: ${DB_PASSWORD:-lions} + KC_BOOTSTRAP_ADMIN_USERNAME: ${KC_ADMIN:-admin} + KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD:-admin} + ports: + - "${KC_PORT:-8180}:8080" + depends_on: + postgres: + condition: service_healthy + + lions-user-manager-client: + build: + context: ../.. + dockerfile: src/main/docker/Dockerfile.jvm + ports: + - "${CLIENT_PORT:-8082}:8082" + environment: + KEYCLOAK_SERVER_URL: http://keycloak:8080 + LIONS_USER_MANAGER_API_URL: ${LIONS_USER_MANAGER_API_URL:-http://host.docker.internal:8080} + depends_on: + keycloak: + condition: service_started + +volumes: + postgres_data: diff --git a/script/docker/run-dev.bat b/script/docker/run-dev.bat index 5e86215..9c1c248 100644 --- a/script/docker/run-dev.bat +++ b/script/docker/run-dev.bat @@ -1,5 +1,5 @@ -@echo off -REM Demarre les dependances (postgres + keycloak) puis le client en mode dev (mvn quarkus:dev -P dev) -cd /d "%~dp0\..\.." -docker-compose -f script/docker/dependencies-docker-compose.yml up -d -mvn quarkus:dev -P dev +@echo off +REM Demarre les dependances (postgres + keycloak) puis le client en mode dev (mvn quarkus:dev -P dev) +cd /d "%~dp0\..\.." +docker-compose -f script/docker/dependencies-docker-compose.yml up -d +mvn quarkus:dev -P dev diff --git a/script/docker/run-dev.sh b/script/docker/run-dev.sh index d997e63..51cb224 100644 --- a/script/docker/run-dev.sh +++ b/script/docker/run-dev.sh @@ -1,7 +1,7 @@ -#!/usr/bin/env bash -# Démarre les dépendances (postgres + keycloak) puis le client en mode dev (mvn quarkus:dev -P dev) -set -e -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$SCRIPT_DIR/../.." -docker-compose -f script/docker/dependencies-docker-compose.yml up -d -mvn quarkus:dev -P dev +#!/usr/bin/env bash +# Démarre les dépendances (postgres + keycloak) puis le client en mode dev (mvn quarkus:dev -P dev) +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/../.." +docker-compose -f script/docker/dependencies-docker-compose.yml up -d +mvn quarkus:dev -P dev diff --git a/src/main/docker/Dockerfile.jvm b/src/main/docker/Dockerfile.jvm index 8277526..ba0e2d3 100644 --- a/src/main/docker/Dockerfile.jvm +++ b/src/main/docker/Dockerfile.jvm @@ -1,11 +1,11 @@ -FROM registry.access.redhat.com/ubi8/openjdk-17:1.20 -ENV LANGUAGE='en_US:en' -COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ -COPY --chown=185 target/quarkus-app/*.jar /deployments/ -COPY --chown=185 target/quarkus-app/app/ /deployments/app/ -COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ -EXPOSE 8082 -USER 185 -ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" -ENTRYPOINT ["/opt/jboss/container/java/run/run-java.sh"] +FROM registry.access.redhat.com/ubi8/openjdk-17:1.20 +ENV LANGUAGE='en_US:en' +COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=185 target/quarkus-app/*.jar /deployments/ +COPY --chown=185 target/quarkus-app/app/ /deployments/app/ +COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ +EXPOSE 8082 +USER 185 +ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" +ENTRYPOINT ["/opt/jboss/container/java/run/run-java.sh"] diff --git a/src/main/java/dev/lions/user/manager/client/api/AuditRestClient.java b/src/main/java/dev/lions/user/manager/client/api/AuditRestClient.java index 72f1a95..4c5bf20 100644 --- a/src/main/java/dev/lions/user/manager/client/api/AuditRestClient.java +++ b/src/main/java/dev/lions/user/manager/client/api/AuditRestClient.java @@ -1,55 +1,55 @@ -package dev.lions.user.manager.client.api; - -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import dev.lions.user.manager.dto.audit.AuditLogDTO; -import dev.lions.user.manager.enums.audit.TypeActionAudit; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -import java.util.List; -import java.util.Map; - -@RegisterRestClient(configKey = "user-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@Path("/api/audit") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public interface AuditRestClient { - - @GET - List searchLogs( - @QueryParam("acteur") String acteur, - @QueryParam("dateDebut") String dateDebut, - @QueryParam("dateFin") String dateFin, - @QueryParam("typeAction") TypeActionAudit typeAction, - @QueryParam("ressourceType") String ressourceType, - @QueryParam("succes") Boolean succes, - @QueryParam("page") int page, - @QueryParam("pageSize") int pageSize); - - @GET - @Path("/stats/actions") - Map getActionStatistics( - @QueryParam("dateDebut") String dateDebut, - @QueryParam("dateFin") String dateFin); - - @GET - @Path("/stats/activity") - Map getUserActivityStatistics( - @QueryParam("dateDebut") String dateDebut, - @QueryParam("dateFin") String dateFin); - - @GET - @Path("/stats/failures") - long getFailureCount( - @QueryParam("dateDebut") String dateDebut, - @QueryParam("dateFin") String dateFin); - - @GET - @Path("/stats/successes") - long getSuccessCount( - @QueryParam("dateDebut") String dateDebut, - @QueryParam("dateFin") String dateFin); -} +package dev.lions.user.manager.client.api; + +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import dev.lions.user.manager.dto.audit.AuditLogDTO; +import dev.lions.user.manager.enums.audit.TypeActionAudit; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import java.util.List; +import java.util.Map; + +@RegisterRestClient(configKey = "user-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@Path("/api/audit") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface AuditRestClient { + + @GET + List searchLogs( + @QueryParam("acteur") String acteur, + @QueryParam("dateDebut") String dateDebut, + @QueryParam("dateFin") String dateFin, + @QueryParam("typeAction") TypeActionAudit typeAction, + @QueryParam("ressourceType") String ressourceType, + @QueryParam("succes") Boolean succes, + @QueryParam("page") int page, + @QueryParam("pageSize") int pageSize); + + @GET + @Path("/stats/actions") + Map getActionStatistics( + @QueryParam("dateDebut") String dateDebut, + @QueryParam("dateFin") String dateFin); + + @GET + @Path("/stats/activity") + Map getUserActivityStatistics( + @QueryParam("dateDebut") String dateDebut, + @QueryParam("dateFin") String dateFin); + + @GET + @Path("/stats/failures") + long getFailureCount( + @QueryParam("dateDebut") String dateDebut, + @QueryParam("dateFin") String dateFin); + + @GET + @Path("/stats/successes") + long getSuccessCount( + @QueryParam("dateDebut") String dateDebut, + @QueryParam("dateFin") String dateFin); +} diff --git a/src/main/java/dev/lions/user/manager/client/api/HealthRestClient.java b/src/main/java/dev/lions/user/manager/client/api/HealthRestClient.java index 9046408..2fc2172 100644 --- a/src/main/java/dev/lions/user/manager/client/api/HealthRestClient.java +++ b/src/main/java/dev/lions/user/manager/client/api/HealthRestClient.java @@ -1,26 +1,26 @@ -package dev.lions.user.manager.client.api; - -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.core.MediaType; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -import java.util.Map; - -@RegisterRestClient(configKey = "user-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@Path("/api/health") -@Produces(MediaType.APPLICATION_JSON) -public interface HealthRestClient { - - @GET - @Path("/keycloak") - Map getKeycloakHealth(); - - @GET - @Path("/status") - Map getServiceStatus(); -} +package dev.lions.user.manager.client.api; + +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import java.util.Map; + +@RegisterRestClient(configKey = "user-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@Path("/api/health") +@Produces(MediaType.APPLICATION_JSON) +public interface HealthRestClient { + + @GET + @Path("/keycloak") + Map getKeycloakHealth(); + + @GET + @Path("/status") + Map getServiceStatus(); +} diff --git a/src/main/java/dev/lions/user/manager/client/api/RoleRestClient.java b/src/main/java/dev/lions/user/manager/client/api/RoleRestClient.java index 731095a..80da4ee 100644 --- a/src/main/java/dev/lions/user/manager/client/api/RoleRestClient.java +++ b/src/main/java/dev/lions/user/manager/client/api/RoleRestClient.java @@ -1,60 +1,60 @@ -package dev.lions.user.manager.client.api; - -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import dev.lions.user.manager.dto.role.RoleAssignmentDTO; -import dev.lions.user.manager.dto.role.RoleDTO; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -import java.util.List; - -@RegisterRestClient(configKey = "user-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@Path("/api/roles") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public interface RoleRestClient { - - @GET - @Path("/realm") - List getAllRealmRoles(@QueryParam("realm") String realmName); - - @POST - @Path("/realm") - RoleDTO createRealmRole(@QueryParam("realm") String realmName, RoleDTO role); - - @GET - @Path("/realm/{roleName}") - RoleDTO getRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName); - - @PUT - @Path("/realm/{roleName}") - RoleDTO updateRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName, - RoleDTO role); - - @DELETE - @Path("/realm/{roleName}") - void deleteRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName); - - @POST - @Path("/users/{userId}/realm-roles") - void assignRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, - RoleAssignmentRequest request); - - @DELETE - @Path("/users/{userId}/realm-roles") - void revokeRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, - RoleAssignmentRequest request); - - @GET - @Path("/users/{userId}/realm-roles") - List getUserRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName); - - // Inner class for role assignment request - class RoleAssignmentRequest { - public List roleNames; - } -} +package dev.lions.user.manager.client.api; + +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import dev.lions.user.manager.dto.role.RoleAssignmentDTO; +import dev.lions.user.manager.dto.role.RoleDTO; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import java.util.List; + +@RegisterRestClient(configKey = "user-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@Path("/api/roles") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface RoleRestClient { + + @GET + @Path("/realm") + List getAllRealmRoles(@QueryParam("realm") String realmName); + + @POST + @Path("/realm") + RoleDTO createRealmRole(@QueryParam("realm") String realmName, RoleDTO role); + + @GET + @Path("/realm/{roleName}") + RoleDTO getRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName); + + @PUT + @Path("/realm/{roleName}") + RoleDTO updateRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName, + RoleDTO role); + + @DELETE + @Path("/realm/{roleName}") + void deleteRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName); + + @POST + @Path("/users/{userId}/realm-roles") + void assignRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, + RoleAssignmentRequest request); + + @DELETE + @Path("/users/{userId}/realm-roles") + void revokeRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, + RoleAssignmentRequest request); + + @GET + @Path("/users/{userId}/realm-roles") + List getUserRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName); + + // Inner class for role assignment request + class RoleAssignmentRequest { + public List roleNames; + } +} diff --git a/src/main/java/dev/lions/user/manager/client/api/UserRestClient.java b/src/main/java/dev/lions/user/manager/client/api/UserRestClient.java index f1560ee..d3ae847 100644 --- a/src/main/java/dev/lions/user/manager/client/api/UserRestClient.java +++ b/src/main/java/dev/lions/user/manager/client/api/UserRestClient.java @@ -1,91 +1,91 @@ -package dev.lions.user.manager.client.api; - -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import dev.lions.user.manager.dto.user.SessionsRevokedDTO; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.dto.user.UserSearchResultDTO; -import jakarta.ws.rs.*; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -import java.util.List; - -@RegisterRestClient(configKey = "user-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@Path("/api/users") -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public interface UserRestClient { - - @GET - UserSearchResultDTO searchUsers( - @QueryParam("realm") String realmName, - @QueryParam("search") String searchTerm, - @QueryParam("username") String username, - @QueryParam("email") String email, - @QueryParam("prenom") String prenom, - @QueryParam("nom") String nom, - @QueryParam("enabled") Boolean enabled, - @QueryParam("page") int page, - @QueryParam("pageSize") int pageSize); - - @GET - @Path("/{id}") - UserDTO getUserById(@PathParam("id") String id, @QueryParam("realm") String realmName); - - @POST - Response createUser(@QueryParam("realm") String realmName, UserDTO user); - - @PUT - @Path("/{id}") - UserDTO updateUser(@PathParam("id") String id, @QueryParam("realm") String realmName, UserDTO user); - - @DELETE - @Path("/{id}") - void deleteUser(@PathParam("id") String id, @QueryParam("realm") String realmName, - @QueryParam("hard") boolean hardDelete); - - // Correction : @POST (était @PUT — mismatch avec le serveur → 405) - @POST - @Path("/{id}/activate") - void activateUser(@PathParam("id") String id, @QueryParam("realm") String realmName); - - // Correction : @POST (était @PUT — mismatch avec le serveur → 405) - @POST - @Path("/{id}/deactivate") - void deactivateUser(@PathParam("id") String id, @QueryParam("realm") String realmName, - @QueryParam("reason") String reason); - - @POST - @Path("/{id}/reset-password") - void resetPassword(@PathParam("id") String id, @QueryParam("realm") String realmName, - PasswordResetRequest request); - - // Correction : path send-verification-email (était send-verify-email → 404) - @POST - @Path("/{id}/send-verification-email") - void sendVerificationEmail(@PathParam("id") String id, @QueryParam("realm") String realmName); - - // Ajout : correspondance avec UserResourceApi.logoutAllSessions() - @POST - @Path("/{id}/logout-sessions") - SessionsRevokedDTO logoutAllSessions(@PathParam("id") String id, @QueryParam("realm") String realmName); - - // Ajout : correspondance avec UserResourceApi.getActiveSessions() - @GET - @Path("/{id}/sessions") - List getActiveSessions(@PathParam("id") String id, @QueryParam("realm") String realmName); - - @GET - @Path("/export/csv") - @Produces(MediaType.TEXT_PLAIN) - String exportUsersToCSV(@QueryParam("realm") String realmName); - - // Inner class pour la réinitialisation de mot de passe - class PasswordResetRequest { - public String password; - public boolean temporary; - } -} +package dev.lions.user.manager.client.api; + +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import dev.lions.user.manager.dto.user.SessionsRevokedDTO; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.dto.user.UserSearchResultDTO; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +import java.util.List; + +@RegisterRestClient(configKey = "user-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@Path("/api/users") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface UserRestClient { + + @GET + UserSearchResultDTO searchUsers( + @QueryParam("realm") String realmName, + @QueryParam("search") String searchTerm, + @QueryParam("username") String username, + @QueryParam("email") String email, + @QueryParam("prenom") String prenom, + @QueryParam("nom") String nom, + @QueryParam("enabled") Boolean enabled, + @QueryParam("page") int page, + @QueryParam("pageSize") int pageSize); + + @GET + @Path("/{id}") + UserDTO getUserById(@PathParam("id") String id, @QueryParam("realm") String realmName); + + @POST + Response createUser(@QueryParam("realm") String realmName, UserDTO user); + + @PUT + @Path("/{id}") + UserDTO updateUser(@PathParam("id") String id, @QueryParam("realm") String realmName, UserDTO user); + + @DELETE + @Path("/{id}") + void deleteUser(@PathParam("id") String id, @QueryParam("realm") String realmName, + @QueryParam("hard") boolean hardDelete); + + // Correction : @POST (était @PUT — mismatch avec le serveur → 405) + @POST + @Path("/{id}/activate") + void activateUser(@PathParam("id") String id, @QueryParam("realm") String realmName); + + // Correction : @POST (était @PUT — mismatch avec le serveur → 405) + @POST + @Path("/{id}/deactivate") + void deactivateUser(@PathParam("id") String id, @QueryParam("realm") String realmName, + @QueryParam("reason") String reason); + + @POST + @Path("/{id}/reset-password") + void resetPassword(@PathParam("id") String id, @QueryParam("realm") String realmName, + PasswordResetRequest request); + + // Correction : path send-verification-email (était send-verify-email → 404) + @POST + @Path("/{id}/send-verification-email") + void sendVerificationEmail(@PathParam("id") String id, @QueryParam("realm") String realmName); + + // Ajout : correspondance avec UserResourceApi.logoutAllSessions() + @POST + @Path("/{id}/logout-sessions") + SessionsRevokedDTO logoutAllSessions(@PathParam("id") String id, @QueryParam("realm") String realmName); + + // Ajout : correspondance avec UserResourceApi.getActiveSessions() + @GET + @Path("/{id}/sessions") + List getActiveSessions(@PathParam("id") String id, @QueryParam("realm") String realmName); + + @GET + @Path("/export/csv") + @Produces(MediaType.TEXT_PLAIN) + String exportUsersToCSV(@QueryParam("realm") String realmName); + + // Inner class pour la réinitialisation de mot de passe + class PasswordResetRequest { + public String password; + public boolean temporary; + } +} diff --git a/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandler.java b/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandler.java deleted file mode 100644 index 7ea65da..0000000 --- a/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -package dev.lions.user.manager.client.exception; - -import jakarta.faces.application.ViewExpiredException; -import jakarta.faces.context.ExceptionHandler; -import jakarta.faces.context.ExceptionHandlerWrapper; -import jakarta.faces.context.FacesContext; -import jakarta.faces.event.ExceptionQueuedEvent; -import jakarta.servlet.http.HttpServletResponse; - -import java.io.IOException; -import java.util.Iterator; - -/** - * Redirige vers la page d'accueil lorsque la vue a expiré (session ou state saving), - * au lieu d'afficher une stack trace. - */ -public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper { - - private final ExceptionHandler wrapped; - - public ViewExpiredExceptionHandler(ExceptionHandler wrapped) { - this.wrapped = wrapped; - } - - @Override - public ExceptionHandler getWrapped() { - return wrapped; - } - - @Override - public void handle() { - Iterator it = getUnhandledExceptionQueuedEvents().iterator(); - while (it.hasNext()) { - ExceptionQueuedEvent event = it.next(); - Throwable t = event.getContext().getException(); - if (t instanceof ViewExpiredException) { - it.remove(); - FacesContext fc = FacesContext.getCurrentInstance(); - if (fc != null && !fc.getResponseComplete()) { - try { - String ctx = fc.getExternalContext().getRequestContextPath(); - fc.getExternalContext().redirect(ctx == null || ctx.isEmpty() ? "/" : ctx + "/"); - fc.responseComplete(); - } catch (IOException e) { - // fallback: set status and let default handling - HttpServletResponse resp = (HttpServletResponse) fc.getExternalContext().getResponse(); - if (resp != null && !resp.isCommitted()) { - resp.setStatus(HttpServletResponse.SC_FOUND); - try { - resp.sendRedirect(fc.getExternalContext().getRequestContextPath() + "/"); - } catch (IOException ignored) { - } - } - } - } - return; - } - } - getWrapped().handle(); - } -} diff --git a/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandlerFactory.java b/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandlerFactory.java deleted file mode 100644 index f5aa5d9..0000000 --- a/src/main/java/dev/lions/user/manager/client/exception/ViewExpiredExceptionHandlerFactory.java +++ /dev/null @@ -1,21 +0,0 @@ -package dev.lions.user.manager.client.exception; - -import jakarta.faces.context.ExceptionHandler; -import jakarta.faces.context.ExceptionHandlerFactory; - -/** - * Factory pour enregistrer le gestionnaire de ViewExpiredException. - */ -public class ViewExpiredExceptionHandlerFactory extends ExceptionHandlerFactory { - - private final ExceptionHandlerFactory parent; - - public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory parent) { - this.parent = parent; - } - - @Override - public ExceptionHandler getExceptionHandler() { - return new ViewExpiredExceptionHandler(parent.getExceptionHandler()); - } -} diff --git a/src/main/java/dev/lions/user/manager/client/filter/AuthHeaderFactory.java b/src/main/java/dev/lions/user/manager/client/filter/AuthHeaderFactory.java index 33c47db..664bbd9 100644 --- a/src/main/java/dev/lions/user/manager/client/filter/AuthHeaderFactory.java +++ b/src/main/java/dev/lions/user/manager/client/filter/AuthHeaderFactory.java @@ -1,59 +1,59 @@ -package dev.lions.user.manager.client.filter; - -import io.quarkus.oidc.AccessTokenCredential; -import jakarta.enterprise.context.RequestScoped; -import jakarta.inject.Inject; -import jakarta.ws.rs.core.MultivaluedHashMap; -import jakarta.ws.rs.core.MultivaluedMap; -import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory; - -import java.util.logging.Logger; - -/** - * Factory to automatically add the OIDC access token (Bearer) - * to REST Client request headers. - */ -@RequestScoped -public class AuthHeaderFactory implements ClientHeadersFactory { - - private static final Logger LOGGER = Logger.getLogger(AuthHeaderFactory.class.getName()); - - @Inject - AccessTokenCredential accessTokenCredential; - - @Override - public MultivaluedMap update( - MultivaluedMap incomingHeaders, - MultivaluedMap clientOutgoingHeaders) { - - MultivaluedMap result = new MultivaluedHashMap<>(); - - // 1. Log incoming and outgoing headers for debugging - if (incomingHeaders != null) { - LOGGER.fine("Incoming Headers: " + incomingHeaders.keySet()); - } - if (clientOutgoingHeaders != null) { - LOGGER.fine("Client Outgoing Headers: " + clientOutgoingHeaders.keySet()); - } - - try { - if (accessTokenCredential != null) { - // 2. Check if the token is available - String accessToken = accessTokenCredential.getToken(); - if (accessToken != null && !accessToken.isEmpty()) { - result.add("Authorization", "Bearer " + accessToken); - LOGGER.info("Access token added to Authorization header. Token length: " + accessToken.length()); - } else { - LOGGER.warning("Access token is empty or null in AccessTokenCredential."); - } - } else { - LOGGER.warning("AccessTokenCredential is unavailable - user might not be authenticated."); - } - } catch (Exception e) { - LOGGER.severe("Error adding Bearer token: " + e.getMessage()); - e.printStackTrace(); - } - - return result; - } -} +package dev.lions.user.manager.client.filter; + +import io.quarkus.oidc.AccessTokenCredential; +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Inject; +import jakarta.ws.rs.core.MultivaluedHashMap; +import jakarta.ws.rs.core.MultivaluedMap; +import org.eclipse.microprofile.rest.client.ext.ClientHeadersFactory; + +import java.util.logging.Logger; + +/** + * Factory to automatically add the OIDC access token (Bearer) + * to REST Client request headers. + */ +@RequestScoped +public class AuthHeaderFactory implements ClientHeadersFactory { + + private static final Logger LOGGER = Logger.getLogger(AuthHeaderFactory.class.getName()); + + @Inject + AccessTokenCredential accessTokenCredential; + + @Override + public MultivaluedMap update( + MultivaluedMap incomingHeaders, + MultivaluedMap clientOutgoingHeaders) { + + MultivaluedMap result = new MultivaluedHashMap<>(); + + // 1. Log incoming and outgoing headers for debugging + if (incomingHeaders != null) { + LOGGER.fine("Incoming Headers: " + incomingHeaders.keySet()); + } + if (clientOutgoingHeaders != null) { + LOGGER.fine("Client Outgoing Headers: " + clientOutgoingHeaders.keySet()); + } + + try { + if (accessTokenCredential != null) { + // 2. Check if the token is available + String accessToken = accessTokenCredential.getToken(); + if (accessToken != null && !accessToken.isEmpty()) { + result.add("Authorization", "Bearer " + accessToken); + LOGGER.info("Access token added to Authorization header. Token length: " + accessToken.length()); + } else { + LOGGER.warning("Access token is empty or null in AccessTokenCredential."); + } + } else { + LOGGER.warning("AccessTokenCredential is unavailable - user might not be authenticated."); + } + } catch (Exception e) { + LOGGER.severe("Error adding Bearer token: " + e.getMessage()); + e.printStackTrace(); + } + + return result; + } +} diff --git a/src/main/java/dev/lions/user/manager/client/service/AuditServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/AuditServiceClient.java index 68c5342..0bb974b 100644 --- a/src/main/java/dev/lions/user/manager/client/service/AuditServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/AuditServiceClient.java @@ -1,26 +1,26 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.AuditResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service d'audit. - * Étend maintenant l'interface API commune définie dans server-api. - */ -@Path("/api/audit") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -public interface AuditServiceClient extends AuditResourceApi { - - // Méthodes héritées de AuditResourceApi - // Note: getLogsByActeur (FR) a été remplacé par getLogsByActor (EN) dans l'API - // commune. - - // Si des méthodes spécifiques au client (non présentes sur le serveur) - // existaient, elles devraient être ici. - // L'ancienne méthode getLogsByRealm n'existait pas sur le serveur, donc - // supprimée. -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.AuditResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service d'audit. + * Étend maintenant l'interface API commune définie dans server-api. + */ +@Path("/api/audit") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +public interface AuditServiceClient extends AuditResourceApi { + + // Méthodes héritées de AuditResourceApi + // Note: getLogsByActeur (FR) a été remplacé par getLogsByActor (EN) dans l'API + // commune. + + // Si des méthodes spécifiques au client (non présentes sur le serveur) + // existaient, elles devraient être ici. + // L'ancienne méthode getLogsByRealm n'existait pas sur le serveur, donc + // supprimée. +} diff --git a/src/main/java/dev/lions/user/manager/client/service/RealmAssignmentServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/RealmAssignmentServiceClient.java index 0192789..adbdb12 100644 --- a/src/main/java/dev/lions/user/manager/client/service/RealmAssignmentServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/RealmAssignmentServiceClient.java @@ -1,21 +1,21 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.RealmAssignmentResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service de gestion des affectations de realms. - * Étend maintenant l'interface API commune définie dans server-api. - */ -@Path("/api/realm-assignments") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -public interface RealmAssignmentServiceClient extends RealmAssignmentResourceApi { - - // Méthodes héritées de RealmAssignmentResourceApi - // Les classes internes CheckResponse et AuthorizedRealmsResponse ont été - // remplacées par des DTOs dans server-api. -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.RealmAssignmentResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service de gestion des affectations de realms. + * Étend maintenant l'interface API commune définie dans server-api. + */ +@Path("/api/realm-assignments") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +public interface RealmAssignmentServiceClient extends RealmAssignmentResourceApi { + + // Méthodes héritées de RealmAssignmentResourceApi + // Les classes internes CheckResponse et AuthorizedRealmsResponse ont été + // remplacées par des DTOs dans server-api. +} diff --git a/src/main/java/dev/lions/user/manager/client/service/RealmServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/RealmServiceClient.java index bfe6804..065a74f 100644 --- a/src/main/java/dev/lions/user/manager/client/service/RealmServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/RealmServiceClient.java @@ -1,21 +1,21 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.RealmResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service de gestion des realms Keycloak - * Étend maintenant l'interface API commune définie dans server-api. - */ -@Path("/api/realms") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@RegisterProvider(RestClientExceptionMapper.class) -public interface RealmServiceClient extends RealmResourceApi { - - // Méthode getAllRealms héritée de RealmResourceApi -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.RealmResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service de gestion des realms Keycloak + * Étend maintenant l'interface API commune définie dans server-api. + */ +@Path("/api/realms") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@RegisterProvider(RestClientExceptionMapper.class) +public interface RealmServiceClient extends RealmResourceApi { + + // Méthode getAllRealms héritée de RealmResourceApi +} diff --git a/src/main/java/dev/lions/user/manager/client/service/RestClientExceptionMapper.java b/src/main/java/dev/lions/user/manager/client/service/RestClientExceptionMapper.java index 4e90b0d..ea00dc5 100644 --- a/src/main/java/dev/lions/user/manager/client/service/RestClientExceptionMapper.java +++ b/src/main/java/dev/lions/user/manager/client/service/RestClientExceptionMapper.java @@ -1,112 +1,112 @@ -package dev.lions.user.manager.client.service; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import jakarta.ws.rs.core.MultivaluedMap; -import jakarta.ws.rs.core.Response; -import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; - -/** - * Mapper d'exceptions pour les clients REST - * Convertit les réponses HTTP d'erreur en exceptions appropriées - */ -public class RestClientExceptionMapper implements ResponseExceptionMapper { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public RuntimeException toThrowable(Response response) { - int status = response.getStatus(); - String reasonPhrase = response.getStatusInfo().getReasonPhrase(); - - // Lire le corps de la réponse pour plus de détails - String errorMessage = reasonPhrase; - try { - if (response.hasEntity()) { - String body = response.readEntity(String.class); - if (body != null && !body.isEmpty()) { - // Essayer de parser le JSON pour extraire le message - try { - JsonNode jsonNode = objectMapper.readTree(body); - if (jsonNode.has("message")) { - errorMessage = jsonNode.get("message").asText(); - } else { - errorMessage = body; - } - } catch (Exception e) { - // Si ce n'est pas du JSON, utiliser le body tel quel - errorMessage = body; - } - } - } - } catch (Exception e) { - // Ignorer les erreurs de lecture du body - } - - return switch (status) { - case 400 -> new BadRequestException("Requête invalide: " + errorMessage); - case 401 -> new UnauthorizedException("Non autorisé: " + errorMessage); - case 403 -> new ForbiddenException("Accès interdit: " + errorMessage); - case 404 -> new NotFoundException(errorMessage); - case 409 -> new ConflictException("Conflit: " + errorMessage); - case 422 -> new UnprocessableEntityException("Données non valides: " + errorMessage); - case 500 -> new InternalServerErrorException("Erreur serveur interne: " + errorMessage); - case 502 -> new BadGatewayException("Erreur de passerelle: " + errorMessage); - case 503 -> new ServiceUnavailableException("Service indisponible: " + errorMessage); - case 504 -> new GatewayTimeoutException("Timeout de passerelle: " + errorMessage); - default -> new UnknownHttpStatusException("Erreur HTTP " + status + ": " + errorMessage); - }; - } - - @Override - public boolean handles(int status, MultivaluedMap headers) { - // Gérer tous les codes d'erreur HTTP (>= 400) - return status >= 400; - } - - // Classes d'exception personnalisées - public static class BadRequestException extends RuntimeException { - public BadRequestException(String message) { super(message); } - } - - public static class UnauthorizedException extends RuntimeException { - public UnauthorizedException(String message) { super(message); } - } - - public static class ForbiddenException extends RuntimeException { - public ForbiddenException(String message) { super(message); } - } - - public static class NotFoundException extends RuntimeException { - public NotFoundException(String message) { super(message); } - } - - public static class ConflictException extends RuntimeException { - public ConflictException(String message) { super(message); } - } - - public static class UnprocessableEntityException extends RuntimeException { - public UnprocessableEntityException(String message) { super(message); } - } - - public static class InternalServerErrorException extends RuntimeException { - public InternalServerErrorException(String message) { super(message); } - } - - public static class BadGatewayException extends RuntimeException { - public BadGatewayException(String message) { super(message); } - } - - public static class ServiceUnavailableException extends RuntimeException { - public ServiceUnavailableException(String message) { super(message); } - } - - public static class GatewayTimeoutException extends RuntimeException { - public GatewayTimeoutException(String message) { super(message); } - } - - public static class UnknownHttpStatusException extends RuntimeException { - public UnknownHttpStatusException(String message) { super(message); } - } -} - +package dev.lions.user.manager.client.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper; + +/** + * Mapper d'exceptions pour les clients REST + * Convertit les réponses HTTP d'erreur en exceptions appropriées + */ +public class RestClientExceptionMapper implements ResponseExceptionMapper { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public RuntimeException toThrowable(Response response) { + int status = response.getStatus(); + String reasonPhrase = response.getStatusInfo().getReasonPhrase(); + + // Lire le corps de la réponse pour plus de détails + String errorMessage = reasonPhrase; + try { + if (response.hasEntity()) { + String body = response.readEntity(String.class); + if (body != null && !body.isEmpty()) { + // Essayer de parser le JSON pour extraire le message + try { + JsonNode jsonNode = objectMapper.readTree(body); + if (jsonNode.has("message")) { + errorMessage = jsonNode.get("message").asText(); + } else { + errorMessage = body; + } + } catch (Exception e) { + // Si ce n'est pas du JSON, utiliser le body tel quel + errorMessage = body; + } + } + } + } catch (Exception e) { + // Ignorer les erreurs de lecture du body + } + + return switch (status) { + case 400 -> new BadRequestException("Requête invalide: " + errorMessage); + case 401 -> new UnauthorizedException("Non autorisé: " + errorMessage); + case 403 -> new ForbiddenException("Accès interdit: " + errorMessage); + case 404 -> new NotFoundException(errorMessage); + case 409 -> new ConflictException("Conflit: " + errorMessage); + case 422 -> new UnprocessableEntityException("Données non valides: " + errorMessage); + case 500 -> new InternalServerErrorException("Erreur serveur interne: " + errorMessage); + case 502 -> new BadGatewayException("Erreur de passerelle: " + errorMessage); + case 503 -> new ServiceUnavailableException("Service indisponible: " + errorMessage); + case 504 -> new GatewayTimeoutException("Timeout de passerelle: " + errorMessage); + default -> new UnknownHttpStatusException("Erreur HTTP " + status + ": " + errorMessage); + }; + } + + @Override + public boolean handles(int status, MultivaluedMap headers) { + // Gérer tous les codes d'erreur HTTP (>= 400) + return status >= 400; + } + + // Classes d'exception personnalisées + public static class BadRequestException extends RuntimeException { + public BadRequestException(String message) { super(message); } + } + + public static class UnauthorizedException extends RuntimeException { + public UnauthorizedException(String message) { super(message); } + } + + public static class ForbiddenException extends RuntimeException { + public ForbiddenException(String message) { super(message); } + } + + public static class NotFoundException extends RuntimeException { + public NotFoundException(String message) { super(message); } + } + + public static class ConflictException extends RuntimeException { + public ConflictException(String message) { super(message); } + } + + public static class UnprocessableEntityException extends RuntimeException { + public UnprocessableEntityException(String message) { super(message); } + } + + public static class InternalServerErrorException extends RuntimeException { + public InternalServerErrorException(String message) { super(message); } + } + + public static class BadGatewayException extends RuntimeException { + public BadGatewayException(String message) { super(message); } + } + + public static class ServiceUnavailableException extends RuntimeException { + public ServiceUnavailableException(String message) { super(message); } + } + + public static class GatewayTimeoutException extends RuntimeException { + public GatewayTimeoutException(String message) { super(message); } + } + + public static class UnknownHttpStatusException extends RuntimeException { + public UnknownHttpStatusException(String message) { super(message); } + } +} + diff --git a/src/main/java/dev/lions/user/manager/client/service/RoleServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/RoleServiceClient.java index 3957b64..4e71af3 100644 --- a/src/main/java/dev/lions/user/manager/client/service/RoleServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/RoleServiceClient.java @@ -1,22 +1,22 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.RoleResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service de gestion des rôles. - * Étend maintenant l'interface API commune définie dans server-api. - */ -@Path("/api/roles") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -public interface RoleServiceClient extends RoleResourceApi { - - // Méthodes héritées de RoleResourceApi - // Note: Certaines méthodes de l'ancien client ont été restructurées (ex: - // assignRoleToUser -> assignRealmRoles/assignClientRoles) - // pour correspondre à l'implémentation serveur existante. -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.RoleResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service de gestion des rôles. + * Étend maintenant l'interface API commune définie dans server-api. + */ +@Path("/api/roles") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +public interface RoleServiceClient extends RoleResourceApi { + + // Méthodes héritées de RoleResourceApi + // Note: Certaines méthodes de l'ancien client ont été restructurées (ex: + // assignRoleToUser -> assignRealmRoles/assignClientRoles) + // pour correspondre à l'implémentation serveur existante. +} diff --git a/src/main/java/dev/lions/user/manager/client/service/SyncServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/SyncServiceClient.java index be5eb23..fa4375e 100644 --- a/src/main/java/dev/lions/user/manager/client/service/SyncServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/SyncServiceClient.java @@ -1,34 +1,34 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.SyncResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.*; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service de synchronisation. - * Étend l'interface API commune définie dans server-api pour garantir - * la cohérence du contrat client-serveur. - */ -@Path("/api/sync") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -public interface SyncServiceClient extends SyncResourceApi { - - // checkKeycloakHealth() hérité de SyncResourceApi → GET /api/sync/health/keycloak - - @GET - @Path("/exists/user/{username}") - Boolean userExists( - @PathParam("username") String username, - @QueryParam("realm") String realmName); - - @GET - @Path("/exists/role/{roleName}") - Boolean roleExists( - @PathParam("roleName") String roleName, - @QueryParam("realm") String realmName, - @QueryParam("typeRole") String typeRole, - @QueryParam("clientName") String clientName); -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.SyncResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.*; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service de synchronisation. + * Étend l'interface API commune définie dans server-api pour garantir + * la cohérence du contrat client-serveur. + */ +@Path("/api/sync") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +public interface SyncServiceClient extends SyncResourceApi { + + // checkKeycloakHealth() hérité de SyncResourceApi → GET /api/sync/health/keycloak + + @GET + @Path("/exists/user/{username}") + Boolean userExists( + @PathParam("username") String username, + @QueryParam("realm") String realmName); + + @GET + @Path("/exists/role/{roleName}") + Boolean roleExists( + @PathParam("roleName") String roleName, + @QueryParam("realm") String realmName, + @QueryParam("typeRole") String typeRole, + @QueryParam("clientName") String clientName); +} diff --git a/src/main/java/dev/lions/user/manager/client/service/UserMetricsServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/UserMetricsServiceClient.java index 09b5128..f7df6b4 100644 --- a/src/main/java/dev/lions/user/manager/client/service/UserMetricsServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/UserMetricsServiceClient.java @@ -1,21 +1,21 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.UserMetricsResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour l'API de métriques utilisateurs. - * Étend l'interface API commune définie dans server-api. - */ -@Path("/api/metrics/users") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@RegisterProvider(RestClientExceptionMapper.class) -public interface UserMetricsServiceClient extends UserMetricsResourceApi { - -} - +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.UserMetricsResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour l'API de métriques utilisateurs. + * Étend l'interface API commune définie dans server-api. + */ +@Path("/api/metrics/users") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@RegisterProvider(RestClientExceptionMapper.class) +public interface UserMetricsServiceClient extends UserMetricsResourceApi { + +} + diff --git a/src/main/java/dev/lions/user/manager/client/service/UserServiceClient.java b/src/main/java/dev/lions/user/manager/client/service/UserServiceClient.java index af5767e..b599e46 100644 --- a/src/main/java/dev/lions/user/manager/client/service/UserServiceClient.java +++ b/src/main/java/dev/lions/user/manager/client/service/UserServiceClient.java @@ -1,21 +1,21 @@ -package dev.lions.user.manager.client.service; - -import dev.lions.user.manager.api.UserResourceApi; -import dev.lions.user.manager.client.filter.AuthHeaderFactory; -import jakarta.ws.rs.Path; -import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; -import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -/** - * REST Client pour le service de gestion des utilisateurs - * Étend maintenant l'interface API commune définie dans server-api. - */ -@Path("/api/users") -@RegisterRestClient(configKey = "lions-user-manager-api") -@RegisterClientHeaders(AuthHeaderFactory.class) -@RegisterProvider(RestClientExceptionMapper.class) -public interface UserServiceClient extends UserResourceApi { - - // Méthodes héritées de UserResourceApi -} +package dev.lions.user.manager.client.service; + +import dev.lions.user.manager.api.UserResourceApi; +import dev.lions.user.manager.client.filter.AuthHeaderFactory; +import jakarta.ws.rs.Path; +import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +/** + * REST Client pour le service de gestion des utilisateurs + * Étend maintenant l'interface API commune définie dans server-api. + */ +@Path("/api/users") +@RegisterRestClient(configKey = "lions-user-manager-api") +@RegisterClientHeaders(AuthHeaderFactory.class) +@RegisterProvider(RestClientExceptionMapper.class) +public interface UserServiceClient extends UserResourceApi { + + // Méthodes héritées de UserResourceApi +} diff --git a/src/main/java/dev/lions/user/manager/client/view/AuditConsultationBean.java b/src/main/java/dev/lions/user/manager/client/view/AuditConsultationBean.java index b883791..fa00f11 100644 --- a/src/main/java/dev/lions/user/manager/client/view/AuditConsultationBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/AuditConsultationBean.java @@ -1,242 +1,242 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.AuditServiceClient; -import dev.lions.user.manager.client.service.RealmServiceClient; -import dev.lions.user.manager.dto.audit.AuditLogDTO; -import dev.lions.user.manager.dto.common.CountDTO; -import dev.lions.user.manager.enums.audit.TypeActionAudit; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.ExternalContext; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.OutputStream; -import java.io.Serializable; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -@Named("auditConsultationBean") -@ViewScoped -@Data -public class AuditConsultationBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(AuditConsultationBean.class.getName()); - private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); - - @Inject - @RestClient - private AuditServiceClient auditServiceClient; - - @Inject - @RestClient - private RealmServiceClient realmServiceClient; - - private List auditLogs = new ArrayList<>(); - private AuditLogDTO selectedLog; - - private String acteurUsername; - private LocalDateTime dateDebut; - private LocalDateTime dateFin; - private TypeActionAudit selectedTypeAction; - private String ressourceType; - private Boolean succes; - - private int currentPage = 0; - private int pageSize = 50; - private long totalRecords = 0; - - private Map actionStatistics; - private Map userActivityStatistics; - private long failureCount = 0; - private long successCount = 0; - - private List typeActionOptions = List.of(TypeActionAudit.values()); - private List availableRealms = new ArrayList<>(); - - @PostConstruct - public void init() { - loadRealms(); - loadStatistics(); - loadRecentLogs(); - } - - public void searchLogs() { - try { - String dateDebutStr = toIsoString(dateDebut); - String dateFinStr = toIsoString(dateFin); - - auditLogs = auditServiceClient.searchLogs( - acteurUsername, - dateDebutStr, - dateFinStr, - selectedTypeAction, - ressourceType, - succes, - currentPage, - pageSize); - - if (auditLogs == null) auditLogs = new ArrayList<>(); - totalRecords = auditLogs.size(); - addSuccessMessage("Recherche effectuée : " + totalRecords + " résultat(s)"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la recherche: " + e.getMessage()); - addErrorMessage("Erreur lors de la recherche : " + e.getMessage()); - } - } - - public void loadRecentLogs() { - try { - auditLogs = auditServiceClient.searchLogs( - null, null, null, null, null, null, 0, pageSize); - if (auditLogs == null) auditLogs = new ArrayList<>(); - totalRecords = successCount + failureCount; - if (totalRecords == 0) { - totalRecords = auditLogs.size(); - } - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement initial des logs: " + e.getMessage()); - auditLogs = new ArrayList<>(); - } - } - - public void loadStatistics() { - try { - String dateDebutStr = toIsoString(dateDebut); - String dateFinStr = toIsoString(dateFin); - - CountDTO failures = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr); - failureCount = failures != null ? failures.getCount() : 0; - - CountDTO successes = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr); - successCount = successes != null ? successes.getCount() : 0; - - totalRecords = successCount + failureCount; - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage()); - } - try { - String dateDebutStr = toIsoString(dateDebut); - String dateFinStr = toIsoString(dateFin); - actionStatistics = auditServiceClient.getActionStatistics(dateDebutStr, dateFinStr); - userActivityStatistics = auditServiceClient.getUserActivityStatistics(dateDebutStr, dateFinStr); - } catch (Exception e) { - LOGGER.warning("Statistiques détaillées non disponibles: " + e.getMessage()); - } - } - - public void exportToCSV() { - try { - String dateDebutStr = toIsoString(dateDebut); - String dateFinStr = toIsoString(dateFin); - - try (jakarta.ws.rs.core.Response response = auditServiceClient.exportLogsToCSV(dateDebutStr, dateFinStr)) { - String csv = response.readEntity(String.class); - - FacesContext facesContext = FacesContext.getCurrentInstance(); - ExternalContext externalContext = facesContext.getExternalContext(); - - String disposition = response.getHeaderString("Content-Disposition"); - String fileName = "audit-logs.csv"; - if (disposition != null && disposition.contains("filename=")) { - fileName = disposition.substring(disposition.indexOf("filename=") + 9).replace("\"", ""); - } - - byte[] contentBytes = csv.getBytes(java.nio.charset.StandardCharsets.UTF_8); - - externalContext.setResponseContentType("text/csv; charset=UTF-8"); - externalContext.setResponseContentLength(contentBytes.length); - externalContext.setResponseHeader("Content-Disposition", - "attachment; filename=\"" + fileName + "\""); - - try (OutputStream out = externalContext.getResponseOutputStream()) { - out.write(contentBytes); - out.flush(); - } - - facesContext.responseComplete(); - } - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'export: " + e.getMessage()); - addErrorMessage("Erreur lors de l'export : " + e.getMessage()); - } - } - - public void resetFilters() { - acteurUsername = null; - dateDebut = null; - dateFin = null; - selectedTypeAction = null; - ressourceType = null; - succes = null; - currentPage = 0; - loadStatistics(); - loadRecentLogs(); - } - - public void previousPage() { - if (currentPage > 0) { - currentPage--; - searchLogs(); - } - } - - public void nextPage() { - currentPage++; - searchLogs(); - } - - public long getSuccessRate() { - if (totalRecords == 0) return 0; - return (successCount * 100) / totalRecords; - } - - private void loadRealms() { - try { - List realms = realmServiceClient.getAllRealms(); - availableRealms = (realms != null && !realms.isEmpty()) ? new ArrayList<>(realms) : new ArrayList<>(); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); - availableRealms = new ArrayList<>(); - } - } - - public void loadLogsByActeur(String acteur) { - try { - List result = auditServiceClient.getLogsByActor(acteur, 100); - auditLogs = result != null ? result : new ArrayList<>(); - totalRecords = auditLogs.size(); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des logs par acteur: " + e.getMessage()); - addErrorMessage("Erreur lors du chargement : " + e.getMessage()); - } - } - - public void loadLogsByRealm(String realmName) { - LOGGER.warning("loadLogsByRealm non supporté côté serveur pour le realm : " + realmName); - } - - private String toIsoString(LocalDateTime ldt) { - if (ldt == null) return null; - return ldt.format(DATE_FORMATTER); - } - - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.AuditServiceClient; +import dev.lions.user.manager.client.service.RealmServiceClient; +import dev.lions.user.manager.dto.audit.AuditLogDTO; +import dev.lions.user.manager.dto.common.CountDTO; +import dev.lions.user.manager.enums.audit.TypeActionAudit; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.ExternalContext; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.OutputStream; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +@Named("auditConsultationBean") +@ViewScoped +@Data +public class AuditConsultationBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(AuditConsultationBean.class.getName()); + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + + @Inject + @RestClient + private AuditServiceClient auditServiceClient; + + @Inject + @RestClient + private RealmServiceClient realmServiceClient; + + private List auditLogs = new ArrayList<>(); + private AuditLogDTO selectedLog; + + private String acteurUsername; + private LocalDateTime dateDebut; + private LocalDateTime dateFin; + private TypeActionAudit selectedTypeAction; + private String ressourceType; + private Boolean succes; + + private int currentPage = 0; + private int pageSize = 50; + private long totalRecords = 0; + + private Map actionStatistics; + private Map userActivityStatistics; + private long failureCount = 0; + private long successCount = 0; + + private List typeActionOptions = List.of(TypeActionAudit.values()); + private List availableRealms = new ArrayList<>(); + + @PostConstruct + public void init() { + loadRealms(); + loadStatistics(); + loadRecentLogs(); + } + + public void searchLogs() { + try { + String dateDebutStr = toIsoString(dateDebut); + String dateFinStr = toIsoString(dateFin); + + auditLogs = auditServiceClient.searchLogs( + acteurUsername, + dateDebutStr, + dateFinStr, + selectedTypeAction, + ressourceType, + succes, + currentPage, + pageSize); + + if (auditLogs == null) auditLogs = new ArrayList<>(); + totalRecords = auditLogs.size(); + addSuccessMessage("Recherche effectuée : " + totalRecords + " résultat(s)"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la recherche: " + e.getMessage()); + addErrorMessage("Erreur lors de la recherche : " + e.getMessage()); + } + } + + public void loadRecentLogs() { + try { + auditLogs = auditServiceClient.searchLogs( + null, null, null, null, null, null, 0, pageSize); + if (auditLogs == null) auditLogs = new ArrayList<>(); + totalRecords = successCount + failureCount; + if (totalRecords == 0) { + totalRecords = auditLogs.size(); + } + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement initial des logs: " + e.getMessage()); + auditLogs = new ArrayList<>(); + } + } + + public void loadStatistics() { + try { + String dateDebutStr = toIsoString(dateDebut); + String dateFinStr = toIsoString(dateFin); + + CountDTO failures = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr); + failureCount = failures != null ? failures.getCount() : 0; + + CountDTO successes = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr); + successCount = successes != null ? successes.getCount() : 0; + + totalRecords = successCount + failureCount; + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage()); + } + try { + String dateDebutStr = toIsoString(dateDebut); + String dateFinStr = toIsoString(dateFin); + actionStatistics = auditServiceClient.getActionStatistics(dateDebutStr, dateFinStr); + userActivityStatistics = auditServiceClient.getUserActivityStatistics(dateDebutStr, dateFinStr); + } catch (Exception e) { + LOGGER.warning("Statistiques détaillées non disponibles: " + e.getMessage()); + } + } + + public void exportToCSV() { + try { + String dateDebutStr = toIsoString(dateDebut); + String dateFinStr = toIsoString(dateFin); + + try (jakarta.ws.rs.core.Response response = auditServiceClient.exportLogsToCSV(dateDebutStr, dateFinStr)) { + String csv = response.readEntity(String.class); + + FacesContext facesContext = FacesContext.getCurrentInstance(); + ExternalContext externalContext = facesContext.getExternalContext(); + + String disposition = response.getHeaderString("Content-Disposition"); + String fileName = "audit-logs.csv"; + if (disposition != null && disposition.contains("filename=")) { + fileName = disposition.substring(disposition.indexOf("filename=") + 9).replace("\"", ""); + } + + byte[] contentBytes = csv.getBytes(java.nio.charset.StandardCharsets.UTF_8); + + externalContext.setResponseContentType("text/csv; charset=UTF-8"); + externalContext.setResponseContentLength(contentBytes.length); + externalContext.setResponseHeader("Content-Disposition", + "attachment; filename=\"" + fileName + "\""); + + try (OutputStream out = externalContext.getResponseOutputStream()) { + out.write(contentBytes); + out.flush(); + } + + facesContext.responseComplete(); + } + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'export: " + e.getMessage()); + addErrorMessage("Erreur lors de l'export : " + e.getMessage()); + } + } + + public void resetFilters() { + acteurUsername = null; + dateDebut = null; + dateFin = null; + selectedTypeAction = null; + ressourceType = null; + succes = null; + currentPage = 0; + loadStatistics(); + loadRecentLogs(); + } + + public void previousPage() { + if (currentPage > 0) { + currentPage--; + searchLogs(); + } + } + + public void nextPage() { + currentPage++; + searchLogs(); + } + + public long getSuccessRate() { + if (totalRecords == 0) return 0; + return (successCount * 100) / totalRecords; + } + + private void loadRealms() { + try { + List realms = realmServiceClient.getAllRealms(); + availableRealms = (realms != null && !realms.isEmpty()) ? new ArrayList<>(realms) : new ArrayList<>(); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); + availableRealms = new ArrayList<>(); + } + } + + public void loadLogsByActeur(String acteur) { + try { + List result = auditServiceClient.getLogsByActor(acteur, 100); + auditLogs = result != null ? result : new ArrayList<>(); + totalRecords = auditLogs.size(); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des logs par acteur: " + e.getMessage()); + addErrorMessage("Erreur lors du chargement : " + e.getMessage()); + } + } + + public void loadLogsByRealm(String realmName) { + LOGGER.warning("loadLogsByRealm non supporté côté serveur pour le realm : " + realmName); + } + + private String toIsoString(LocalDateTime ldt) { + if (ldt == null) return null; + return ldt.format(DATE_FORMATTER); + } + + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/DashboardBean.java b/src/main/java/dev/lions/user/manager/client/view/DashboardBean.java index 7023985..1843390 100644 --- a/src/main/java/dev/lions/user/manager/client/view/DashboardBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/DashboardBean.java @@ -1,233 +1,233 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.AuditServiceClient; -import dev.lions.user.manager.client.service.RoleServiceClient; -import dev.lions.user.manager.client.service.UserMetricsServiceClient; -import dev.lions.user.manager.client.service.UserServiceClient; -import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; -import dev.lions.user.manager.dto.user.UserSearchResultDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; - -import java.io.Serializable; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.List; -import java.util.logging.Logger; - -/** - * Bean JSF pour le tableau de bord - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("dashboardBean") -@ViewScoped -@Data -public class DashboardBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(DashboardBean.class.getName()); - - @Inject - @RestClient - private UserServiceClient userServiceClient; - - @Inject - @RestClient - private RoleServiceClient roleServiceClient; - - @Inject - @RestClient - private AuditServiceClient auditServiceClient; - - @Inject - @RestClient - private UserMetricsServiceClient userMetricsServiceClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") - String defaultRealm; - - // Statistiques - private Long totalUsers = 0L; - private Long totalRoles = 0L; - private Long recentActions = 0L; - private Long activeSessions = 0L; - private Long onlineUsers = 0L; - - // Indicateur de chargement - private boolean loading = false; - - // Méthodes pour obtenir les valeurs formatées pour l'affichage - public String getTotalUsersDisplay() { - if (loading) - return "..."; - return totalUsers != null ? String.valueOf(totalUsers) : "0"; - } - - public String getTotalRolesDisplay() { - if (loading) - return "..."; - return totalRoles != null ? String.valueOf(totalRoles) : "0"; - } - - public String getRecentActionsDisplay() { - if (loading) - return "..."; - return recentActions != null ? String.valueOf(recentActions) : "0"; - } - - public String getActiveSessionsDisplay() { - if (loading) - return "..."; - return activeSessions != null ? String.valueOf(activeSessions) : "0"; - } - - public String getOnlineUsersDisplay() { - if (loading) - return "..."; - return onlineUsers != null ? String.valueOf(onlineUsers) : "0"; - } - - public boolean isLoading() { - return loading; - } - - // Realm par défaut (initialisé depuis la config en @PostConstruct) - private String realmName; - - private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); - - @PostConstruct - public void init() { - this.realmName = defaultRealm; - LOGGER.info("Initialisation DashboardBean pour realm: " + realmName); - loadStatistics(); - } - - /** - * Charger toutes les statistiques - */ - public void loadStatistics() { - loading = true; - try { - loadTotalUsers(); - loadTotalRoles(); - loadRecentActions(); - loadSessionStats(); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage()); - } finally { - loading = false; - } - } - - /** - * Charger le nombre total d'utilisateurs - */ - private void loadTotalUsers() { - try { - UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() - .realmName(realmName) - .page(0) - .pageSize(1) - .build(); - - UserSearchResultDTO result = userServiceClient.searchUsers(criteria); - totalUsers = (result != null && result.getTotalCount() != null) ? result.getTotalCount() : 0L; - } catch (Exception e) { - LOGGER.severe("Erreur chargement total utilisateurs: " + e.getMessage()); - totalUsers = 0L; - addErrorMessage("Impossible de charger le nombre d'utilisateurs: " + e.getMessage()); - } - } - - /** - * Charger le nombre total de rôles Realm - */ - private void loadTotalRoles() { - try { - List roles = roleServiceClient.getAllRealmRoles(realmName); - totalRoles = (roles != null) ? (long) roles.size() : 0L; - } catch (Exception e) { - LOGGER.severe("Erreur chargement total rôles: " + e.getMessage()); - totalRoles = 0L; - addErrorMessage("Impossible de charger le nombre de rôles: " + e.getMessage()); - } - } - - /** - * Charger le nombre d'actions récentes (dernières 24h) - */ - private void loadRecentActions() { - try { - String dateDebutStr = LocalDateTime.now().minusDays(1).format(DATE_FORMATTER); - String dateFinStr = LocalDateTime.now().format(DATE_FORMATTER); - - try { - dev.lions.user.manager.dto.common.CountDTO successDto = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr); - dev.lions.user.manager.dto.common.CountDTO failureDto = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr); - - long successCount = (successDto != null) ? successDto.getCount() : 0L; - long failureCount = (failureDto != null) ? failureDto.getCount() : 0L; - recentActions = successCount + failureCount; - } catch (Exception e2) { - LOGGER.warning("Fallback searchLogs pour actions récentes: " + e2.getMessage()); - List logs = auditServiceClient.searchLogs(null, dateDebutStr, dateFinStr, null, null, null, 0, 100); - recentActions = (logs != null) ? (long) logs.size() : 0L; - } - } catch (Exception e) { - LOGGER.severe("Erreur chargement actions récentes: " + e.getMessage()); - recentActions = 0L; - } - } - - /** - * Charger les statistiques de sessions / utilisateurs en ligne - */ - private void loadSessionStats() { - try { - dev.lions.user.manager.dto.common.UserSessionStatsDTO stats = userMetricsServiceClient - .getUserSessionStats(realmName); - - if (stats != null) { - this.activeSessions = stats.getActiveSessions(); - this.onlineUsers = stats.getOnlineUsers(); - } else { - this.activeSessions = 0L; - this.onlineUsers = 0L; - } - } catch (Exception e) { - LOGGER.severe("Erreur chargement stats sessions: " + e.getMessage()); - this.activeSessions = 0L; - this.onlineUsers = 0L; - } - } - - /** - * Rafraîchir les statistiques - */ - public void refreshStatistics() { - loadStatistics(); - addSuccessMessage("Statistiques rafraîchies avec succès"); - } - - // Méthodes utilitaires pour les messages - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.AuditServiceClient; +import dev.lions.user.manager.client.service.RoleServiceClient; +import dev.lions.user.manager.client.service.UserMetricsServiceClient; +import dev.lions.user.manager.client.service.UserServiceClient; +import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; +import dev.lions.user.manager.dto.user.UserSearchResultDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.logging.Logger; + +/** + * Bean JSF pour le tableau de bord + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("dashboardBean") +@ViewScoped +@Data +public class DashboardBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(DashboardBean.class.getName()); + + @Inject + @RestClient + private UserServiceClient userServiceClient; + + @Inject + @RestClient + private RoleServiceClient roleServiceClient; + + @Inject + @RestClient + private AuditServiceClient auditServiceClient; + + @Inject + @RestClient + private UserMetricsServiceClient userMetricsServiceClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") + String defaultRealm; + + // Statistiques + private Long totalUsers = 0L; + private Long totalRoles = 0L; + private Long recentActions = 0L; + private Long activeSessions = 0L; + private Long onlineUsers = 0L; + + // Indicateur de chargement + private boolean loading = false; + + // Méthodes pour obtenir les valeurs formatées pour l'affichage + public String getTotalUsersDisplay() { + if (loading) + return "..."; + return totalUsers != null ? String.valueOf(totalUsers) : "0"; + } + + public String getTotalRolesDisplay() { + if (loading) + return "..."; + return totalRoles != null ? String.valueOf(totalRoles) : "0"; + } + + public String getRecentActionsDisplay() { + if (loading) + return "..."; + return recentActions != null ? String.valueOf(recentActions) : "0"; + } + + public String getActiveSessionsDisplay() { + if (loading) + return "..."; + return activeSessions != null ? String.valueOf(activeSessions) : "0"; + } + + public String getOnlineUsersDisplay() { + if (loading) + return "..."; + return onlineUsers != null ? String.valueOf(onlineUsers) : "0"; + } + + public boolean isLoading() { + return loading; + } + + // Realm par défaut (initialisé depuis la config en @PostConstruct) + private String realmName; + + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + + @PostConstruct + public void init() { + this.realmName = defaultRealm; + LOGGER.info("Initialisation DashboardBean pour realm: " + realmName); + loadStatistics(); + } + + /** + * Charger toutes les statistiques + */ + public void loadStatistics() { + loading = true; + try { + loadTotalUsers(); + loadTotalRoles(); + loadRecentActions(); + loadSessionStats(); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage()); + } finally { + loading = false; + } + } + + /** + * Charger le nombre total d'utilisateurs + */ + private void loadTotalUsers() { + try { + UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() + .realmName(realmName) + .page(0) + .pageSize(1) + .build(); + + UserSearchResultDTO result = userServiceClient.searchUsers(criteria); + totalUsers = (result != null && result.getTotalCount() != null) ? result.getTotalCount() : 0L; + } catch (Exception e) { + LOGGER.severe("Erreur chargement total utilisateurs: " + e.getMessage()); + totalUsers = 0L; + addErrorMessage("Impossible de charger le nombre d'utilisateurs: " + e.getMessage()); + } + } + + /** + * Charger le nombre total de rôles Realm + */ + private void loadTotalRoles() { + try { + List roles = roleServiceClient.getAllRealmRoles(realmName); + totalRoles = (roles != null) ? (long) roles.size() : 0L; + } catch (Exception e) { + LOGGER.severe("Erreur chargement total rôles: " + e.getMessage()); + totalRoles = 0L; + addErrorMessage("Impossible de charger le nombre de rôles: " + e.getMessage()); + } + } + + /** + * Charger le nombre d'actions récentes (dernières 24h) + */ + private void loadRecentActions() { + try { + String dateDebutStr = LocalDateTime.now().minusDays(1).format(DATE_FORMATTER); + String dateFinStr = LocalDateTime.now().format(DATE_FORMATTER); + + try { + dev.lions.user.manager.dto.common.CountDTO successDto = auditServiceClient.getSuccessCount(dateDebutStr, dateFinStr); + dev.lions.user.manager.dto.common.CountDTO failureDto = auditServiceClient.getFailureCount(dateDebutStr, dateFinStr); + + long successCount = (successDto != null) ? successDto.getCount() : 0L; + long failureCount = (failureDto != null) ? failureDto.getCount() : 0L; + recentActions = successCount + failureCount; + } catch (Exception e2) { + LOGGER.warning("Fallback searchLogs pour actions récentes: " + e2.getMessage()); + List logs = auditServiceClient.searchLogs(null, dateDebutStr, dateFinStr, null, null, null, 0, 100); + recentActions = (logs != null) ? (long) logs.size() : 0L; + } + } catch (Exception e) { + LOGGER.severe("Erreur chargement actions récentes: " + e.getMessage()); + recentActions = 0L; + } + } + + /** + * Charger les statistiques de sessions / utilisateurs en ligne + */ + private void loadSessionStats() { + try { + dev.lions.user.manager.dto.common.UserSessionStatsDTO stats = userMetricsServiceClient + .getUserSessionStats(realmName); + + if (stats != null) { + this.activeSessions = stats.getActiveSessions(); + this.onlineUsers = stats.getOnlineUsers(); + } else { + this.activeSessions = 0L; + this.onlineUsers = 0L; + } + } catch (Exception e) { + LOGGER.severe("Erreur chargement stats sessions: " + e.getMessage()); + this.activeSessions = 0L; + this.onlineUsers = 0L; + } + } + + /** + * Rafraîchir les statistiques + */ + public void refreshStatistics() { + loadStatistics(); + addSuccessMessage("Statistiques rafraîchies avec succès"); + } + + // Méthodes utilitaires pour les messages + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/DashboardView.java b/src/main/java/dev/lions/user/manager/client/view/DashboardView.java index f4704ae..e3462cd 100644 --- a/src/main/java/dev/lions/user/manager/client/view/DashboardView.java +++ b/src/main/java/dev/lions/user/manager/client/view/DashboardView.java @@ -1,142 +1,133 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.api.AuditRestClient; -import dev.lions.user.manager.client.api.HealthRestClient; -import dev.lions.user.manager.client.api.UserRestClient; -import dev.lions.user.manager.enums.audit.TypeActionAudit; -import jakarta.annotation.PostConstruct; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.primefaces.model.charts.ChartData; -import org.primefaces.model.charts.axes.cartesian.CartesianScales; -import org.primefaces.model.charts.axes.cartesian.linear.CartesianLinearAxes; -import org.primefaces.model.charts.bar.BarChartDataSet; -import org.primefaces.model.charts.bar.BarChartModel; -import org.primefaces.model.charts.bar.BarChartOptions; -import org.primefaces.model.charts.optionconfig.title.Title; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -@Named -@ViewScoped -@Slf4j -@SuppressWarnings("deprecation") // ChartData API dépréciée - migration vers JSON prévue -public class DashboardView implements Serializable { - - @Inject - @RestClient - AuditRestClient auditRestClient; - - @Inject - @RestClient - HealthRestClient healthRestClient; - - @Inject - @RestClient - UserRestClient userRestClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") - String defaultRealm; - - @Getter - private long totalSuccesses; - - @Getter - private long totalFailures; - - @Getter - private long activeUsers; - - @Getter - private boolean systemHealthy; - - @Getter - private BarChartModel barModel; - - @PostConstruct - public void init() { - loadStats(); - createBarModel(); - } - - public void loadStats() { - try { - totalSuccesses = auditRestClient.getSuccessCount(null, null); - totalFailures = auditRestClient.getFailureCount(null, null); - - // Assuming we display active users for default realm - // Ideally we would have an endpoint for global stats - activeUsers = 0; // Placeholder until we have count endpoint in UserRestClient or general stats - - try { - Map health = healthRestClient.getServiceStatus(); - systemHealthy = "UP".equals(health.get("status")); - } catch (Exception e) { - systemHealthy = false; - } - - } catch (Exception e) { - log.error("Error loading stats", e); - } - } - - @SuppressWarnings("deprecation") // ChartData sera remplacé par une approche JSON moderne dans une version future - public void createBarModel() { - barModel = new BarChartModel(); - ChartData data = new ChartData(); - - BarChartDataSet barDataSet = new BarChartDataSet(); - barDataSet.setLabel("Activités par type"); - - List values = new ArrayList<>(); - List labels = new ArrayList<>(); - List bgColor = new ArrayList<>(); - List borderColor = new ArrayList<>(); - - try { - Map stats = auditRestClient.getActionStatistics(null, null); - - for (Map.Entry entry : stats.entrySet()) { - labels.add(entry.getKey().name()); - values.add(entry.getValue()); - bgColor.add("rgba(75, 192, 192, 0.2)"); - borderColor.add("rgb(75, 192, 192)"); - } - } catch (Exception e) { - log.error("Error loading chart data", e); - } - - barDataSet.setData(values); - barDataSet.setBackgroundColor(bgColor); - barDataSet.setBorderColor(borderColor); - barDataSet.setBorderWidth(1); - - data.addChartDataSet(barDataSet); - data.setLabels(labels); - - barModel.setData(data); - - // Options - BarChartOptions options = new BarChartOptions(); - CartesianScales cScales = new CartesianScales(); - CartesianLinearAxes linearAxes = new CartesianLinearAxes(); - linearAxes.setOffset(true); - cScales.addYAxesData(linearAxes); - options.setScales(cScales); - - Title title = new Title(); - title.setDisplay(true); - title.setText("Audit Actions"); - options.setTitle(title); - - barModel.setOptions(options); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.api.AuditRestClient; +import dev.lions.user.manager.client.api.HealthRestClient; +import dev.lions.user.manager.client.api.UserRestClient; +import dev.lions.user.manager.enums.audit.TypeActionAudit; +import jakarta.annotation.PostConstruct; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import software.xdev.chartjs.model.charts.BarChart; +import software.xdev.chartjs.model.data.BarData; +import software.xdev.chartjs.model.dataset.BarDataset; +import software.xdev.chartjs.model.options.BarOptions; +import software.xdev.chartjs.model.options.Plugins; +import software.xdev.chartjs.model.options.Title; +import software.xdev.chartjs.model.options.scale.Scales; +import software.xdev.chartjs.model.options.scale.cartesian.linear.LinearScaleOptions; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Named +@ViewScoped +@Slf4j +public class DashboardView implements Serializable { + + @Inject + @RestClient + AuditRestClient auditRestClient; + + @Inject + @RestClient + HealthRestClient healthRestClient; + + @Inject + @RestClient + UserRestClient userRestClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") + String defaultRealm; + + @Getter + private long totalSuccesses; + + @Getter + private long totalFailures; + + @Getter + private long activeUsers; + + @Getter + private boolean systemHealthy; + + @Getter + private String barModelJson; + + @PostConstruct + public void init() { + loadStats(); + createBarModel(); + } + + public void loadStats() { + try { + totalSuccesses = auditRestClient.getSuccessCount(null, null); + totalFailures = auditRestClient.getFailureCount(null, null); + + // Assuming we display active users for default realm + // Ideally we would have an endpoint for global stats + activeUsers = 0; // Placeholder until we have count endpoint in UserRestClient or general stats + + try { + Map health = healthRestClient.getServiceStatus(); + systemHealthy = "UP".equals(health.get("status")); + } catch (Exception e) { + systemHealthy = false; + } + + } catch (Exception e) { + log.error("Error loading stats", e); + } + } + + public void createBarModel() { + BarDataset barDataSet = new BarDataset() + .setLabel("Activités par type") + .setBorderWidth(1); + + BarData data = new BarData(); + + try { + Map stats = auditRestClient.getActionStatistics(null, null); + + for (Map.Entry entry : stats.entrySet()) { + data.addLabel(entry.getKey().name()); + barDataSet.addData(entry.getValue().intValue()); + barDataSet.addBackgroundColor("rgba(75, 192, 192, 0.2)"); + barDataSet.addBorderColor("rgb(75, 192, 192)"); + } + } catch (Exception e) { + log.error("Error loading chart data", e); + } + + data.addDataset(barDataSet); + + // Options + LinearScaleOptions linearScaleOptions = new LinearScaleOptions().setBeginAtZero(true); + + Scales scales = new Scales() + .addScale(Scales.ScaleAxis.Y, linearScaleOptions); + + Title title = new Title() + .setDisplay(true) + .setText("Audit Actions"); + + Plugins plugins = new Plugins() + .setTitle(title); + + BarOptions options = new BarOptions() + .setScales(scales) + .setPlugins(plugins); + + BarChart chart = new BarChart(data, options); + this.barModelJson = chart.toJson(); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/FreyaShowcaseBean.java b/src/main/java/dev/lions/user/manager/client/view/FreyaShowcaseBean.java index 0634769..2cbb316 100644 --- a/src/main/java/dev/lions/user/manager/client/view/FreyaShowcaseBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/FreyaShowcaseBean.java @@ -1,285 +1,285 @@ -package dev.lions.user.manager.client.view; - -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Named; -import lombok.Data; -import org.primefaces.model.TreeNode; - -import java.io.Serializable; -import java.time.LocalDate; -import java.util.*; -import java.util.logging.Logger; - -/** - * Bean JSF pour la showcase Freya Extension - * Démonstration complète des 46 composants personnalisés - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("demoBean") -@ViewScoped -@Data -public class FreyaShowcaseBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(FreyaShowcaseBean.class.getName()); - - // ============ DONNÉES UTILISATEUR EXEMPLE ============ - private User user = new User(); - private List sampleUsers; - private TreeNode treeRoot; - - // ============ DIALOGUES ============ - private FormDialogData dialogData = new FormDialogData(); - - // ============ COMPOSANTS ============ - private String requiredField; - private String inplaceText = "Texte éditable"; - private String chartData; - private Integer progressValue = 0; - - @PostConstruct - public void init() { - LOGGER.info("=== Initialisation du FreyaShowcaseBean ==="); - - // Initialiser les données d'exemple - initSampleUsers(); - initTreeData(); - initChartData(); - - // Valeurs par défaut pour les composants - user.setVolume(50); - user.setRating(4); - user.setQuantite(10); - } - - /** - * Initialiser les utilisateurs d'exemple pour dataTable et dataView - */ - private void initSampleUsers() { - sampleUsers = new ArrayList<>(); - sampleUsers.add(new SampleUser("Jean Dupont", "jean.dupont@example.com", true)); - sampleUsers.add(new SampleUser("Marie Martin", "marie.martin@example.com", true)); - sampleUsers.add(new SampleUser("Pierre Durand", "pierre.durand@example.com", false)); - sampleUsers.add(new SampleUser("Sophie Bernard", "sophie.bernard@example.com", true)); - sampleUsers.add(new SampleUser("Luc Petit", "luc.petit@example.com", false)); - sampleUsers.add(new SampleUser("Anne Dubois", "anne.dubois@example.com", true)); - sampleUsers.add(new SampleUser("Paul Thomas", "paul.thomas@example.com", true)); - sampleUsers.add(new SampleUser("Claire Robert", "claire.robert@example.com", false)); - } - - /** - * Initialiser l'arborescence pour tree et treeTable - */ - private void initTreeData() { - treeRoot = new org.primefaces.model.DefaultTreeNode<>(new NodeData("Racine", "Dossier"), null); - - TreeNode documents = new org.primefaces.model.DefaultTreeNode<>( - new NodeData("Documents", "Dossier"), treeRoot); - TreeNode images = new org.primefaces.model.DefaultTreeNode<>( - new NodeData("Images", "Dossier"), treeRoot); - - new org.primefaces.model.DefaultTreeNode<>(new NodeData("Rapport.pdf", "Fichier"), documents); - new org.primefaces.model.DefaultTreeNode<>(new NodeData("Facture.xlsx", "Fichier"), documents); - new org.primefaces.model.DefaultTreeNode<>(new NodeData("Photo1.jpg", "Fichier"), images); - new org.primefaces.model.DefaultTreeNode<>(new NodeData("Photo2.png", "Fichier"), images); - } - - /** - * Initialiser les données du graphique Chart.js (format JSON moderne) - */ - private void initChartData() { - // Utilisation de JSON direct pour Chart.js (API moderne, non dépréciée) - chartData = """ - { - "type": "bar", - "data": { - "labels": ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin"], - "datasets": [{ - "label": "Statistiques Mensuelles", - "data": [65, 59, 80, 81, 56, 55], - "backgroundColor": [ - "rgba(54, 162, 235, 0.2)", - "rgba(75, 192, 192, 0.2)", - "rgba(255, 206, 86, 0.2)", - "rgba(153, 102, 255, 0.2)", - "rgba(255, 99, 132, 0.2)", - "rgba(255, 159, 64, 0.2)" - ], - "borderColor": [ - "rgba(54, 162, 235, 1)", - "rgba(75, 192, 192, 1)", - "rgba(255, 206, 86, 1)", - "rgba(153, 102, 255, 1)", - "rgba(255, 99, 132, 1)", - "rgba(255, 159, 64, 1)" - ], - "borderWidth": 1 - }] - }, - "options": { - "responsive": true, - "maintainAspectRatio": false, - "plugins": { - "legend": { - "display": true, - "position": "top" - } - }, - "scales": { - "y": { - "beginAtZero": true - } - } - } - } - """; - } - - /** - * Autocomplétion pour fieldAutoComplete - */ - public List completeCities(String query) { - List allCities = Arrays.asList( - "Paris", "Lyon", "Marseille", "Toulouse", "Nice", "Nantes", - "Strasbourg", "Montpellier", "Bordeaux", "Lille", "Rennes", "Reims" - ); - - return allCities.stream() - .filter(city -> city.toLowerCase().startsWith(query.toLowerCase())) - .toList(); - } - - // ============ ACTIONS ============ - - public void saveAction() { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", "Données sauvegardées avec succès")); - LOGGER.info("Action Save executée"); - } - - public void cancelAction() { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_WARN, "Annulé", "Action annulée")); - LOGGER.info("Action Cancel executée"); - } - - public void refreshAction() { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Rafraîchi", "Données rafraîchies")); - LOGGER.info("Action Refresh executée"); - } - - public void confirmAction() { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Confirmé", "Action confirmée avec succès")); - LOGGER.info("Action Confirm executée (actionDialog)"); - } - - public void createUser() { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Utilisateur créé", - "Utilisateur " + dialogData.getNom() + " créé avec succès")); - LOGGER.info("Utilisateur créé: " + dialogData.getNom() + " - " + dialogData.getEmail()); - dialogData = new FormDialogData(); // Reset - } - - public void showSuccessMessage() { - FacesContext.getCurrentInstance().addMessage("growlDemo", - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", "Opération réussie avec succès")); - } - - public void showWarningMessage() { - FacesContext.getCurrentInstance().addMessage("growlDemo", - new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention", "Ceci est un avertissement")); - } - - public void startProgress() { - progressValue = 0; - Timer timer = new Timer(); - timer.schedule(new TimerTask() { - @Override - public void run() { - progressValue = Math.min(100, progressValue + 10); - if (progressValue >= 100) { - timer.cancel(); - } - } - }, 0, 500); - } - - public void resetProgress() { - progressValue = 0; - } - - // ============ CLASSES INTERNES ============ - - /** - * Classe User pour démonstration des champs de formulaire - */ - @Data - public static class User implements Serializable { - private String nom; - private String password; - private String description; - private Integer age; - private LocalDate dateNaissance; - private String pays; - private List competences; - private Boolean actif; - private String genre; - private Boolean newsletter; - private Boolean modeNuit; - private Integer volume; - private Integer rating; - private List tags; - private String couleur; - private String bio; - private String telephone; - private String ville; - private Integer quantite; - } - - /** - * Classe SampleUser pour dataTable et dataView - */ - @Data - public static class SampleUser implements Serializable { - private String nom; - private String email; - private Boolean actif; - - public SampleUser(String nom, String email, Boolean actif) { - this.nom = nom; - this.email = email; - this.actif = actif; - } - } - - /** - * Classe NodeData pour tree et treeTable - */ - @Data - public static class NodeData implements Serializable { - private String label; - private String type; - - public NodeData(String label, String type) { - this.label = label; - this.type = type; - } - } - - /** - * Classe FormDialogData pour formDialog - */ - @Data - public static class FormDialogData implements Serializable { - private String nom; - private String email; - } -} +package dev.lions.user.manager.client.view; + +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Named; +import lombok.Data; +import org.primefaces.model.TreeNode; + +import java.io.Serializable; +import java.time.LocalDate; +import java.util.*; +import java.util.logging.Logger; + +/** + * Bean JSF pour la showcase Freya Extension + * Démonstration complète des 46 composants personnalisés + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("demoBean") +@ViewScoped +@Data +public class FreyaShowcaseBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(FreyaShowcaseBean.class.getName()); + + // ============ DONNÉES UTILISATEUR EXEMPLE ============ + private User user = new User(); + private List sampleUsers; + private TreeNode treeRoot; + + // ============ DIALOGUES ============ + private FormDialogData dialogData = new FormDialogData(); + + // ============ COMPOSANTS ============ + private String requiredField; + private String inplaceText = "Texte éditable"; + private String chartData; + private Integer progressValue = 0; + + @PostConstruct + public void init() { + LOGGER.info("=== Initialisation du FreyaShowcaseBean ==="); + + // Initialiser les données d'exemple + initSampleUsers(); + initTreeData(); + initChartData(); + + // Valeurs par défaut pour les composants + user.setVolume(50); + user.setRating(4); + user.setQuantite(10); + } + + /** + * Initialiser les utilisateurs d'exemple pour dataTable et dataView + */ + private void initSampleUsers() { + sampleUsers = new ArrayList<>(); + sampleUsers.add(new SampleUser("Jean Dupont", "jean.dupont@example.com", true)); + sampleUsers.add(new SampleUser("Marie Martin", "marie.martin@example.com", true)); + sampleUsers.add(new SampleUser("Pierre Durand", "pierre.durand@example.com", false)); + sampleUsers.add(new SampleUser("Sophie Bernard", "sophie.bernard@example.com", true)); + sampleUsers.add(new SampleUser("Luc Petit", "luc.petit@example.com", false)); + sampleUsers.add(new SampleUser("Anne Dubois", "anne.dubois@example.com", true)); + sampleUsers.add(new SampleUser("Paul Thomas", "paul.thomas@example.com", true)); + sampleUsers.add(new SampleUser("Claire Robert", "claire.robert@example.com", false)); + } + + /** + * Initialiser l'arborescence pour tree et treeTable + */ + private void initTreeData() { + treeRoot = new org.primefaces.model.DefaultTreeNode<>(new NodeData("Racine", "Dossier"), null); + + TreeNode documents = new org.primefaces.model.DefaultTreeNode<>( + new NodeData("Documents", "Dossier"), treeRoot); + TreeNode images = new org.primefaces.model.DefaultTreeNode<>( + new NodeData("Images", "Dossier"), treeRoot); + + new org.primefaces.model.DefaultTreeNode<>(new NodeData("Rapport.pdf", "Fichier"), documents); + new org.primefaces.model.DefaultTreeNode<>(new NodeData("Facture.xlsx", "Fichier"), documents); + new org.primefaces.model.DefaultTreeNode<>(new NodeData("Photo1.jpg", "Fichier"), images); + new org.primefaces.model.DefaultTreeNode<>(new NodeData("Photo2.png", "Fichier"), images); + } + + /** + * Initialiser les données du graphique Chart.js (format JSON moderne) + */ + private void initChartData() { + // Utilisation de JSON direct pour Chart.js (API moderne, non dépréciée) + chartData = """ + { + "type": "bar", + "data": { + "labels": ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin"], + "datasets": [{ + "label": "Statistiques Mensuelles", + "data": [65, 59, 80, 81, 56, 55], + "backgroundColor": [ + "rgba(54, 162, 235, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(255, 206, 86, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(255, 99, 132, 0.2)", + "rgba(255, 159, 64, 0.2)" + ], + "borderColor": [ + "rgba(54, 162, 235, 1)", + "rgba(75, 192, 192, 1)", + "rgba(255, 206, 86, 1)", + "rgba(153, 102, 255, 1)", + "rgba(255, 99, 132, 1)", + "rgba(255, 159, 64, 1)" + ], + "borderWidth": 1 + }] + }, + "options": { + "responsive": true, + "maintainAspectRatio": false, + "plugins": { + "legend": { + "display": true, + "position": "top" + } + }, + "scales": { + "y": { + "beginAtZero": true + } + } + } + } + """; + } + + /** + * Autocomplétion pour fieldAutoComplete + */ + public List completeCities(String query) { + List allCities = Arrays.asList( + "Paris", "Lyon", "Marseille", "Toulouse", "Nice", "Nantes", + "Strasbourg", "Montpellier", "Bordeaux", "Lille", "Rennes", "Reims" + ); + + return allCities.stream() + .filter(city -> city.toLowerCase().startsWith(query.toLowerCase())) + .toList(); + } + + // ============ ACTIONS ============ + + public void saveAction() { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", "Données sauvegardées avec succès")); + LOGGER.info("Action Save executée"); + } + + public void cancelAction() { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_WARN, "Annulé", "Action annulée")); + LOGGER.info("Action Cancel executée"); + } + + public void refreshAction() { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Rafraîchi", "Données rafraîchies")); + LOGGER.info("Action Refresh executée"); + } + + public void confirmAction() { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Confirmé", "Action confirmée avec succès")); + LOGGER.info("Action Confirm executée (actionDialog)"); + } + + public void createUser() { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Utilisateur créé", + "Utilisateur " + dialogData.getNom() + " créé avec succès")); + LOGGER.info("Utilisateur créé: " + dialogData.getNom() + " - " + dialogData.getEmail()); + dialogData = new FormDialogData(); // Reset + } + + public void showSuccessMessage() { + FacesContext.getCurrentInstance().addMessage("growlDemo", + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", "Opération réussie avec succès")); + } + + public void showWarningMessage() { + FacesContext.getCurrentInstance().addMessage("growlDemo", + new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention", "Ceci est un avertissement")); + } + + public void startProgress() { + progressValue = 0; + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + progressValue = Math.min(100, progressValue + 10); + if (progressValue >= 100) { + timer.cancel(); + } + } + }, 0, 500); + } + + public void resetProgress() { + progressValue = 0; + } + + // ============ CLASSES INTERNES ============ + + /** + * Classe User pour démonstration des champs de formulaire + */ + @Data + public static class User implements Serializable { + private String nom; + private String password; + private String description; + private Integer age; + private LocalDate dateNaissance; + private String pays; + private List competences; + private Boolean actif; + private String genre; + private Boolean newsletter; + private Boolean modeNuit; + private Integer volume; + private Integer rating; + private List tags; + private String couleur; + private String bio; + private String telephone; + private String ville; + private Integer quantite; + } + + /** + * Classe SampleUser pour dataTable et dataView + */ + @Data + public static class SampleUser implements Serializable { + private String nom; + private String email; + private Boolean actif; + + public SampleUser(String nom, String email, Boolean actif) { + this.nom = nom; + this.email = email; + this.actif = actif; + } + } + + /** + * Classe NodeData pour tree et treeTable + */ + @Data + public static class NodeData implements Serializable { + private String label; + private String type; + + public NodeData(String label, String type) { + this.label = label; + this.type = type; + } + } + + /** + * Classe FormDialogData pour formDialog + */ + @Data + public static class FormDialogData implements Serializable { + private String nom; + private String email; + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/GuestPreferences.java b/src/main/java/dev/lions/user/manager/client/view/GuestPreferences.java deleted file mode 100644 index 3cbb110..0000000 --- a/src/main/java/dev/lions/user/manager/client/view/GuestPreferences.java +++ /dev/null @@ -1,147 +0,0 @@ -package dev.lions.user.manager.client.view; - -import jakarta.enterprise.context.SessionScoped; -import jakarta.inject.Named; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -@Named("guestPreferences") -@SessionScoped -public class GuestPreferences implements Serializable { - - private static final long serialVersionUID = 1L; - - private String theme = "blue-light"; - private String layout = "light"; - private String componentTheme = "blue-light"; - private String darkMode = "light"; - private String menuMode = "layout-sidebar"; - private String topbarTheme = "light"; - private String menuTheme = "light"; - private String inputStyle = "outlined"; - private boolean lightLogo = false; - - public String getTheme() { - return theme; - } - - public void setTheme(String theme) { - this.theme = theme; - } - - public String getLayout() { - return layout; - } - - public void setLayout(String layout) { - this.layout = layout; - } - - public String getComponentTheme() { - return componentTheme; - } - - public void setComponentTheme(String componentTheme) { - this.componentTheme = componentTheme; - } - - public String getDarkMode() { - return darkMode; - } - - public void setDarkMode(String darkMode) { - this.darkMode = darkMode; - this.lightLogo = "dark".equals(darkMode); - } - - public String getMenuMode() { - return menuMode; - } - - public void setMenuMode(String menuMode) { - this.menuMode = menuMode; - } - - public String getTopbarTheme() { - return topbarTheme; - } - - public void setTopbarTheme(String topbarTheme) { - this.topbarTheme = topbarTheme; - } - - public String getMenuTheme() { - return menuTheme; - } - - public void setMenuTheme(String menuTheme) { - this.menuTheme = menuTheme; - } - - public String getInputStyle() { - return inputStyle; - } - - public void setInputStyle(String inputStyle) { - this.inputStyle = inputStyle; - } - - public boolean isLightLogo() { - return lightLogo; - } - - public void setLightLogo(boolean lightLogo) { - this.lightLogo = lightLogo; - } - - public String getInputStyleClass() { - return "p-input-" + inputStyle; - } - - public String getLayoutClass() { - return "layout-" + layout + " layout-theme-" + theme; - } - - public List getComponentThemes() { - List themes = new ArrayList<>(); - themes.add(new ComponentTheme("blue-light", "Blue", "#007ad9")); - themes.add(new ComponentTheme("green-light", "Green", "#28a745")); - themes.add(new ComponentTheme("orange-light", "Orange", "#fd7e14")); - themes.add(new ComponentTheme("purple-light", "Purple", "#6f42c1")); - themes.add(new ComponentTheme("pink-light", "Pink", "#e83e8c")); - themes.add(new ComponentTheme("indigo-light", "Indigo", "#6610f2")); - themes.add(new ComponentTheme("teal-light", "Teal", "#20c997")); - themes.add(new ComponentTheme("cyan-light", "Cyan", "#17a2b8")); - return themes; - } - - public void onMenuTypeChange() { - // Called when menu type changes - } - - public static class ComponentTheme { - private String file; - private String name; - private String color; - - public ComponentTheme(String file, String name, String color) { - this.file = file; - this.name = name; - this.color = color; - } - - public String getFile() { - return file; - } - - public String getName() { - return name; - } - - public String getColor() { - return color; - } - } -} - diff --git a/src/main/java/dev/lions/user/manager/client/view/RealmAssignmentBean.java b/src/main/java/dev/lions/user/manager/client/view/RealmAssignmentBean.java index 37fff96..cf1a5a9 100644 --- a/src/main/java/dev/lions/user/manager/client/view/RealmAssignmentBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/RealmAssignmentBean.java @@ -1,401 +1,402 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.RealmAssignmentServiceClient; -import dev.lions.user.manager.client.service.RealmServiceClient; -import dev.lions.user.manager.client.service.UserServiceClient; -import dev.lions.user.manager.dto.realm.RealmAssignmentDTO; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.dto.user.UserSearchResultDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -/** - * Bean JSF pour la gestion des affectations de realms - * Permet d'assigner des realms aux utilisateurs pour le contrôle d'accès - * multi-tenant - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("realmAssignmentBean") -@ViewScoped -@Data -public class RealmAssignmentBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(RealmAssignmentBean.class.getName()); - - @Inject - @RestClient - private RealmAssignmentServiceClient realmAssignmentServiceClient; - - @Inject - @RestClient - private UserServiceClient userServiceClient; - - @Inject - @RestClient - private RealmServiceClient realmServiceClient; - - @Inject - private UserSessionBean userSessionBean; - - // Listes - private List assignments = new ArrayList<>(); - private List availableUsers = new ArrayList<>(); - private List availableRealms = new ArrayList<>(); - private RealmAssignmentDTO selectedAssignment; - - // Pour la création/édition - private RealmAssignmentDTO newAssignment = RealmAssignmentDTO.builder() - .active(true) - .temporaire(false) - .build(); - private String selectedUserId; - private String selectedRealmName; - - // Filtres - private String filterUserName; - private String filterRealmName; - - @PostConstruct - public void init() { - LOGGER.info("Initialisation de RealmAssignmentBean"); - - // Vérifier si l'utilisateur est admin - if (!userSessionBean.hasRole("admin")) { - addErrorMessage("Accès refusé: Cette fonctionnalité est réservée aux administrateurs"); - return; - } - - loadAssignments(); - loadAvailableUsers(); - loadAvailableRealms(); - } - - /** - * Charger toutes les affectations - */ - public void loadAssignments() { - try { - LOGGER.info("Chargement de toutes les affectations de realms"); - assignments = realmAssignmentServiceClient.getAllAssignments(); - LOGGER.info("Chargement réussi: " + assignments.size() + " affectation(s) trouvée(s)"); - - if (assignments.isEmpty()) { - addInfoMessage("Aucune affectation de realm configurée"); - } - } catch (Exception e) { - String errorMsg = "Erreur lors du chargement des affectations: " + e.getMessage(); - LOGGER.severe(errorMsg); - LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); - addErrorMessage(errorMsg); - assignments = new ArrayList<>(); - } - } - - /** - * Charger les utilisateurs disponibles - */ - public void loadAvailableUsers() { - try { - LOGGER.info("Chargement des utilisateurs disponibles"); - // Charger les utilisateurs du realm lions-user-manager (page 0, 100 - // utilisateurs max) - UserSearchResultDTO result = userServiceClient.getAllUsers("lions-user-manager", 0, 100); - availableUsers = result != null && result.getUsers() != null ? result.getUsers() : new ArrayList<>(); - LOGGER.info("Chargement réussi: " + availableUsers.size() + " utilisateur(s) disponible(s)"); - } catch (Exception e) { - String errorMsg = "Erreur lors du chargement des utilisateurs: " + e.getMessage(); - LOGGER.severe(errorMsg); - addErrorMessage(errorMsg); - availableUsers = new ArrayList<>(); - } - } - - /** - * Charger les realms disponibles depuis Keycloak - */ - public void loadAvailableRealms() { - try { - LOGGER.info("Chargement des realms disponibles depuis Keycloak"); - List realms = realmServiceClient.getAllRealms(); - - if (realms == null || realms.isEmpty()) { - LOGGER.warning("Aucun realm trouvé dans Keycloak"); - availableRealms = Collections.emptyList(); - addInfoMessage("Aucun realm disponible dans Keycloak"); - } else { - availableRealms = new ArrayList<>(realms); - LOGGER.info("Realms disponibles chargés depuis Keycloak: " + availableRealms.size()); - } - } catch (Exception e) { - String errorMsg = "Erreur lors du chargement des realms depuis Keycloak: " + e.getMessage(); - LOGGER.severe(errorMsg); - LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); - addErrorMessage(errorMsg); - // Fallback: liste vide plutôt que des données fictives - availableRealms = Collections.emptyList(); - } - } - - /** - * Assigner un realm à un utilisateur - */ - public void assignRealm() { - try { - if (selectedUserId == null || selectedUserId.isEmpty()) { - addErrorMessage("Veuillez sélectionner un utilisateur"); - return; - } - - if (selectedRealmName == null || selectedRealmName.isEmpty()) { - addErrorMessage("Veuillez sélectionner un realm"); - return; - } - - // Trouver l'utilisateur sélectionné - UserDTO selectedUser = availableUsers.stream() - .filter(u -> u.getId().equals(selectedUserId)) - .findFirst() - .orElse(null); - - if (selectedUser == null) { - addErrorMessage("Utilisateur introuvable"); - return; - } - - // Construire l'assignation - RealmAssignmentDTO assignment = RealmAssignmentDTO.builder() - .userId(selectedUserId) - .username(selectedUser.getUsername()) - .email(selectedUser.getEmail()) - .realmName(selectedRealmName) - .isSuperAdmin(false) - .assignedAt(LocalDateTime.now()) - .assignedBy(userSessionBean.getUsername()) - .raison(newAssignment.getRaison()) - .commentaires(newAssignment.getCommentaires()) - .temporaire(newAssignment.getTemporaire() != null && newAssignment.getTemporaire()) - .dateExpiration(newAssignment.getDateExpiration()) - .active(true) - .build(); - - LOGGER.info("Assignation du realm " + selectedRealmName + " à l'utilisateur " + selectedUser.getUsername()); - - jakarta.ws.rs.core.Response response = realmAssignmentServiceClient.assignRealmToUser(assignment); - response.readEntity(RealmAssignmentDTO.class); - - addSuccessMessage("Realm '" + selectedRealmName + "' assigné avec succès à " + selectedUser.getUsername()); - resetForm(); - loadAssignments(); - - } catch (Exception e) { - String errorMsg = "Erreur lors de l'assignation: " + e.getMessage(); - LOGGER.severe(errorMsg); - LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); - addErrorMessage(errorMsg); - } - } - - /** - * Révoquer l'accès d'un utilisateur à un realm - */ - public void revokeAssignment(RealmAssignmentDTO assignment) { - try { - if (assignment == null) { - addErrorMessage("Assignation invalide"); - return; - } - - LOGGER.info("Révocation du realm " + assignment.getRealmName() + " pour l'utilisateur " - + assignment.getUsername()); - - realmAssignmentServiceClient.revokeRealmFromUser(assignment.getUserId(), assignment.getRealmName()); - - addSuccessMessage( - "Accès révoqué pour " + assignment.getUsername() + " au realm '" + assignment.getRealmName() + "'"); - loadAssignments(); - - } catch (Exception e) { - String errorMsg = "Erreur lors de la révocation: " + e.getMessage(); - LOGGER.severe(errorMsg); - LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); - addErrorMessage(errorMsg); - } - } - - /** - * Désactiver une assignation - */ - public void deactivateAssignment(RealmAssignmentDTO assignment) { - try { - if (assignment == null || assignment.getId() == null) { - addErrorMessage("Assignation invalide"); - return; - } - - LOGGER.info("Désactivation de l'assignation " + assignment.getId()); - - realmAssignmentServiceClient.deactivateAssignment(assignment.getId()); - - addSuccessMessage("Assignation désactivée"); - loadAssignments(); - - } catch (Exception e) { - String errorMsg = "Erreur lors de la désactivation: " + e.getMessage(); - LOGGER.severe(errorMsg); - addErrorMessage(errorMsg); - } - } - - /** - * Activer une assignation - */ - public void activateAssignment(RealmAssignmentDTO assignment) { - try { - if (assignment == null || assignment.getId() == null) { - addErrorMessage("Assignation invalide"); - return; - } - - LOGGER.info("Activation de l'assignation " + assignment.getId()); - - realmAssignmentServiceClient.activateAssignment(assignment.getId()); - - addSuccessMessage("Assignation activée"); - loadAssignments(); - - } catch (Exception e) { - String errorMsg = "Erreur lors de l'activation: " + e.getMessage(); - LOGGER.severe(errorMsg); - addErrorMessage(errorMsg); - } - } - - /** - * Définir un utilisateur comme super admin - */ - public void setSuperAdmin(String userId, boolean superAdmin) { - try { - if (userId == null || userId.isEmpty()) { - addErrorMessage("Utilisateur invalide"); - return; - } - - UserDTO user = availableUsers.stream() - .filter(u -> u.getId().equals(userId)) - .findFirst() - .orElse(null); - - String username = user != null ? user.getUsername() : userId; - - LOGGER.info("Définition de " + username + " comme super admin: " + superAdmin); - - realmAssignmentServiceClient.setSuperAdmin(userId, superAdmin); - - if (superAdmin) { - addSuccessMessage(username + " est maintenant super admin (peut gérer tous les realms)"); - } else { - addSuccessMessage("Privilèges super admin retirés pour " + username); - } - - loadAssignments(); - - } catch (Exception e) { - String errorMsg = "Erreur lors de la modification du statut super admin: " + e.getMessage(); - LOGGER.severe(errorMsg); - addErrorMessage(errorMsg); - } - } - - /** - * Réinitialiser le formulaire - */ - public void resetForm() { - newAssignment = RealmAssignmentDTO.builder() - .active(true) - .temporaire(false) - .build(); - selectedUserId = null; - selectedRealmName = null; - } - - /** - * Obtenir les assignations filtrées - */ - public List getFilteredAssignments() { - if (filterUserName == null && filterRealmName == null) { - return assignments; - } - - return assignments.stream() - .filter(a -> { - boolean matchUser = filterUserName == null || filterUserName.isEmpty() || - (a.getUsername() != null - && a.getUsername().toLowerCase().contains(filterUserName.toLowerCase())); - - boolean matchRealm = filterRealmName == null || filterRealmName.isEmpty() || - (a.getRealmName() != null - && a.getRealmName().toLowerCase().contains(filterRealmName.toLowerCase())); - - return matchUser && matchRealm; - }) - .collect(Collectors.toList()); - } - - /** - * Obtenir le nombre total d'assignations - */ - public int getTotalAssignments() { - return assignments != null ? assignments.size() : 0; - } - - /** - * Obtenir le nombre d'assignations actives - */ - public long getActiveAssignmentsCount() { - return assignments.stream() - .filter(RealmAssignmentDTO::isActive) - .count(); - } - - /** - * Obtenir le nombre de super admins - */ - public long getSuperAdminsCount() { - return assignments.stream() - .filter(RealmAssignmentDTO::isSuperAdmin) - .count(); - } - - // Méthodes utilitaires pour les messages - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } - - private void addInfoMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Information", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.faces.layout.view.UserSessionBean; +import dev.lions.user.manager.client.service.RealmAssignmentServiceClient; +import dev.lions.user.manager.client.service.RealmServiceClient; +import dev.lions.user.manager.client.service.UserServiceClient; +import dev.lions.user.manager.dto.realm.RealmAssignmentDTO; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.dto.user.UserSearchResultDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * Bean JSF pour la gestion des affectations de realms + * Permet d'assigner des realms aux utilisateurs pour le contrôle d'accès + * multi-tenant + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("realmAssignmentBean") +@ViewScoped +@Data +public class RealmAssignmentBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(RealmAssignmentBean.class.getName()); + + @Inject + @RestClient + private RealmAssignmentServiceClient realmAssignmentServiceClient; + + @Inject + @RestClient + private UserServiceClient userServiceClient; + + @Inject + @RestClient + private RealmServiceClient realmServiceClient; + + @Inject + private UserSessionBean userSessionBean; + + // Listes + private List assignments = new ArrayList<>(); + private List availableUsers = new ArrayList<>(); + private List availableRealms = new ArrayList<>(); + private RealmAssignmentDTO selectedAssignment; + + // Pour la création/édition + private RealmAssignmentDTO newAssignment = RealmAssignmentDTO.builder() + .active(true) + .temporaire(false) + .build(); + private String selectedUserId; + private String selectedRealmName; + + // Filtres + private String filterUserName; + private String filterRealmName; + + @PostConstruct + public void init() { + LOGGER.info("Initialisation de RealmAssignmentBean"); + + // Vérifier si l'utilisateur est admin + if (!userSessionBean.hasRole("admin")) { + addErrorMessage("Accès refusé: Cette fonctionnalité est réservée aux administrateurs"); + return; + } + + loadAssignments(); + loadAvailableUsers(); + loadAvailableRealms(); + } + + /** + * Charger toutes les affectations + */ + public void loadAssignments() { + try { + LOGGER.info("Chargement de toutes les affectations de realms"); + assignments = realmAssignmentServiceClient.getAllAssignments(); + LOGGER.info("Chargement réussi: " + assignments.size() + " affectation(s) trouvée(s)"); + + if (assignments.isEmpty()) { + addInfoMessage("Aucune affectation de realm configurée"); + } + } catch (Exception e) { + String errorMsg = "Erreur lors du chargement des affectations: " + e.getMessage(); + LOGGER.severe(errorMsg); + LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); + addErrorMessage(errorMsg); + assignments = new ArrayList<>(); + } + } + + /** + * Charger les utilisateurs disponibles + */ + public void loadAvailableUsers() { + try { + LOGGER.info("Chargement des utilisateurs disponibles"); + // Charger les utilisateurs du realm lions-user-manager (page 0, 100 + // utilisateurs max) + UserSearchResultDTO result = userServiceClient.getAllUsers("lions-user-manager", 0, 100); + availableUsers = result != null && result.getUsers() != null ? result.getUsers() : new ArrayList<>(); + LOGGER.info("Chargement réussi: " + availableUsers.size() + " utilisateur(s) disponible(s)"); + } catch (Exception e) { + String errorMsg = "Erreur lors du chargement des utilisateurs: " + e.getMessage(); + LOGGER.severe(errorMsg); + addErrorMessage(errorMsg); + availableUsers = new ArrayList<>(); + } + } + + /** + * Charger les realms disponibles depuis Keycloak + */ + public void loadAvailableRealms() { + try { + LOGGER.info("Chargement des realms disponibles depuis Keycloak"); + List realms = realmServiceClient.getAllRealms(); + + if (realms == null || realms.isEmpty()) { + LOGGER.warning("Aucun realm trouvé dans Keycloak"); + availableRealms = Collections.emptyList(); + addInfoMessage("Aucun realm disponible dans Keycloak"); + } else { + availableRealms = new ArrayList<>(realms); + LOGGER.info("Realms disponibles chargés depuis Keycloak: " + availableRealms.size()); + } + } catch (Exception e) { + String errorMsg = "Erreur lors du chargement des realms depuis Keycloak: " + e.getMessage(); + LOGGER.severe(errorMsg); + LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); + addErrorMessage(errorMsg); + // Fallback: liste vide plutôt que des données fictives + availableRealms = Collections.emptyList(); + } + } + + /** + * Assigner un realm à un utilisateur + */ + public void assignRealm() { + try { + if (selectedUserId == null || selectedUserId.isEmpty()) { + addErrorMessage("Veuillez sélectionner un utilisateur"); + return; + } + + if (selectedRealmName == null || selectedRealmName.isEmpty()) { + addErrorMessage("Veuillez sélectionner un realm"); + return; + } + + // Trouver l'utilisateur sélectionné + UserDTO selectedUser = availableUsers.stream() + .filter(u -> u.getId().equals(selectedUserId)) + .findFirst() + .orElse(null); + + if (selectedUser == null) { + addErrorMessage("Utilisateur introuvable"); + return; + } + + // Construire l'assignation + RealmAssignmentDTO assignment = RealmAssignmentDTO.builder() + .userId(selectedUserId) + .username(selectedUser.getUsername()) + .email(selectedUser.getEmail()) + .realmName(selectedRealmName) + .isSuperAdmin(false) + .assignedAt(LocalDateTime.now()) + .assignedBy(userSessionBean.getUsername()) + .raison(newAssignment.getRaison()) + .commentaires(newAssignment.getCommentaires()) + .temporaire(newAssignment.getTemporaire() != null && newAssignment.getTemporaire()) + .dateExpiration(newAssignment.getDateExpiration()) + .active(true) + .build(); + + LOGGER.info("Assignation du realm " + selectedRealmName + " à l'utilisateur " + selectedUser.getUsername()); + + jakarta.ws.rs.core.Response response = realmAssignmentServiceClient.assignRealmToUser(assignment); + response.readEntity(RealmAssignmentDTO.class); + + addSuccessMessage("Realm '" + selectedRealmName + "' assigné avec succès à " + selectedUser.getUsername()); + resetForm(); + loadAssignments(); + + } catch (Exception e) { + String errorMsg = "Erreur lors de l'assignation: " + e.getMessage(); + LOGGER.severe(errorMsg); + LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); + addErrorMessage(errorMsg); + } + } + + /** + * Révoquer l'accès d'un utilisateur à un realm + */ + public void revokeAssignment(RealmAssignmentDTO assignment) { + try { + if (assignment == null) { + addErrorMessage("Assignation invalide"); + return; + } + + LOGGER.info("Révocation du realm " + assignment.getRealmName() + " pour l'utilisateur " + + assignment.getUsername()); + + realmAssignmentServiceClient.revokeRealmFromUser(assignment.getUserId(), assignment.getRealmName()); + + addSuccessMessage( + "Accès révoqué pour " + assignment.getUsername() + " au realm '" + assignment.getRealmName() + "'"); + loadAssignments(); + + } catch (Exception e) { + String errorMsg = "Erreur lors de la révocation: " + e.getMessage(); + LOGGER.severe(errorMsg); + LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); + addErrorMessage(errorMsg); + } + } + + /** + * Désactiver une assignation + */ + public void deactivateAssignment(RealmAssignmentDTO assignment) { + try { + if (assignment == null || assignment.getId() == null) { + addErrorMessage("Assignation invalide"); + return; + } + + LOGGER.info("Désactivation de l'assignation " + assignment.getId()); + + realmAssignmentServiceClient.deactivateAssignment(assignment.getId()); + + addSuccessMessage("Assignation désactivée"); + loadAssignments(); + + } catch (Exception e) { + String errorMsg = "Erreur lors de la désactivation: " + e.getMessage(); + LOGGER.severe(errorMsg); + addErrorMessage(errorMsg); + } + } + + /** + * Activer une assignation + */ + public void activateAssignment(RealmAssignmentDTO assignment) { + try { + if (assignment == null || assignment.getId() == null) { + addErrorMessage("Assignation invalide"); + return; + } + + LOGGER.info("Activation de l'assignation " + assignment.getId()); + + realmAssignmentServiceClient.activateAssignment(assignment.getId()); + + addSuccessMessage("Assignation activée"); + loadAssignments(); + + } catch (Exception e) { + String errorMsg = "Erreur lors de l'activation: " + e.getMessage(); + LOGGER.severe(errorMsg); + addErrorMessage(errorMsg); + } + } + + /** + * Définir un utilisateur comme super admin + */ + public void setSuperAdmin(String userId, boolean superAdmin) { + try { + if (userId == null || userId.isEmpty()) { + addErrorMessage("Utilisateur invalide"); + return; + } + + UserDTO user = availableUsers.stream() + .filter(u -> u.getId().equals(userId)) + .findFirst() + .orElse(null); + + String username = user != null ? user.getUsername() : userId; + + LOGGER.info("Définition de " + username + " comme super admin: " + superAdmin); + + realmAssignmentServiceClient.setSuperAdmin(userId, superAdmin); + + if (superAdmin) { + addSuccessMessage(username + " est maintenant super admin (peut gérer tous les realms)"); + } else { + addSuccessMessage("Privilèges super admin retirés pour " + username); + } + + loadAssignments(); + + } catch (Exception e) { + String errorMsg = "Erreur lors de la modification du statut super admin: " + e.getMessage(); + LOGGER.severe(errorMsg); + addErrorMessage(errorMsg); + } + } + + /** + * Réinitialiser le formulaire + */ + public void resetForm() { + newAssignment = RealmAssignmentDTO.builder() + .active(true) + .temporaire(false) + .build(); + selectedUserId = null; + selectedRealmName = null; + } + + /** + * Obtenir les assignations filtrées + */ + public List getFilteredAssignments() { + if (filterUserName == null && filterRealmName == null) { + return assignments; + } + + return assignments.stream() + .filter(a -> { + boolean matchUser = filterUserName == null || filterUserName.isEmpty() || + (a.getUsername() != null + && a.getUsername().toLowerCase().contains(filterUserName.toLowerCase())); + + boolean matchRealm = filterRealmName == null || filterRealmName.isEmpty() || + (a.getRealmName() != null + && a.getRealmName().toLowerCase().contains(filterRealmName.toLowerCase())); + + return matchUser && matchRealm; + }) + .collect(Collectors.toList()); + } + + /** + * Obtenir le nombre total d'assignations + */ + public int getTotalAssignments() { + return assignments != null ? assignments.size() : 0; + } + + /** + * Obtenir le nombre d'assignations actives + */ + public long getActiveAssignmentsCount() { + return assignments.stream() + .filter(RealmAssignmentDTO::isActive) + .count(); + } + + /** + * Obtenir le nombre de super admins + */ + public long getSuperAdminsCount() { + return assignments.stream() + .filter(RealmAssignmentDTO::isSuperAdmin) + .count(); + } + + // Méthodes utilitaires pour les messages + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } + + private void addInfoMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Information", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/RoleGestionBean.java b/src/main/java/dev/lions/user/manager/client/view/RoleGestionBean.java index 2815c88..ea363cb 100644 --- a/src/main/java/dev/lions/user/manager/client/view/RoleGestionBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/RoleGestionBean.java @@ -1,371 +1,371 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.RoleServiceClient; -import dev.lions.user.manager.client.service.RealmServiceClient; -import dev.lions.user.manager.dto.role.RoleAssignmentDTO; -import dev.lions.user.manager.dto.role.RoleDTO; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.enums.role.TypeRole; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -/** - * Bean JSF pour la gestion des rôles - */ -@Named("roleGestionBean") -@ViewScoped -@Data -public class RoleGestionBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(RoleGestionBean.class.getName()); - - @Inject - @RestClient - private RoleServiceClient roleServiceClient; - - @Inject - @RestClient - private RealmServiceClient realmServiceClient; - - // Liste des rôles - private List realmRoles = new ArrayList<>(); - private List clientRoles = new ArrayList<>(); - private List allRoles = new ArrayList<>(); - private RoleDTO selectedRole; - private String selectedRoleName; - - // Pour la création/édition - private RoleDTO newRole = RoleDTO.builder().build(); - private boolean editMode = false; - - // Filtres - private String realmName = "lions-user-manager"; - private String clientName; - private TypeRole selectedTypeRole; - private String roleSearchText; - - // Options - private List typeRoleOptions = List.of(TypeRole.values()); - private List availableRealms = new ArrayList<>(); - private List availableClients = new ArrayList<>(); - - @PostConstruct - public void init() { - loadRealms(); - loadRealmRoles(); - } - - /** - * Charger les rôles Realm - */ - public void loadRealmRoles() { - if (realmName == null || realmName.isEmpty()) { - LOGGER.warning("Realm non sélectionné, impossible de charger les rôles"); - addErrorMessage("Veuillez sélectionner un realm"); - return; - } - - try { - LOGGER.info("Chargement des rôles Realm pour le realm: " + realmName); - realmRoles = roleServiceClient.getAllRealmRoles(realmName); - updateAllRoles(); - loadClients(); - LOGGER.info("Chargement réussi: " + realmRoles.size() + " rôles Realm trouvés"); - if (realmRoles.isEmpty()) { - addErrorMessage("Aucun rôle Realm trouvé dans le realm: " + realmName); - } - } catch (Exception e) { - String errorMsg = "Erreur lors du chargement des rôles Realm pour le realm '" + realmName + "': " - + e.getMessage(); - LOGGER.severe(errorMsg); - LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); - addErrorMessage(errorMsg); - realmRoles = new ArrayList<>(); - updateAllRoles(); - } - } - - /** - * Charger les rôles Client - */ - public void loadClientRoles() { - if (clientName == null || clientName.isEmpty()) { - clientRoles = new ArrayList<>(); - updateAllRoles(); - return; - } - - try { - clientRoles = roleServiceClient.getAllClientRoles(clientName, realmName); - updateAllRoles(); - LOGGER.info("Chargement de " + clientRoles.size() + " rôles Client"); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des rôles Client: " + e.getMessage()); - addErrorMessage("Erreur lors du chargement des rôles Client"); - } - } - - /** - * Mettre à jour la liste complète des rôles - */ - private void updateAllRoles() { - allRoles = new ArrayList<>(); - allRoles.addAll(realmRoles); - allRoles.addAll(clientRoles); - } - - /** - * Obtenir les rôles Realm filtrés par type - */ - public List getFilteredRealmRoles() { - if (selectedTypeRole == null) { - return realmRoles; - } - return realmRoles.stream() - .filter(r -> selectedTypeRole.equals(r.getTypeRole())) - .collect(Collectors.toList()); - } - - /** - * Obtenir les rôles Client filtrés par type - */ - public List getFilteredClientRoles() { - if (selectedTypeRole == null) { - return clientRoles; - } - return clientRoles.stream() - .filter(r -> selectedTypeRole.equals(r.getTypeRole())) - .collect(Collectors.toList()); - } - - /** - * Appliquer le filtre type (appelé depuis p:ajax) - */ - public void applyTypeFilter() { - // Les getFilteredRealmRoles/getFilteredClientRoles font le filtrage - LOGGER.info("Filtre type appliqué: " + selectedTypeRole); - } - - /** - * Créer un nouveau rôle Realm - */ - public void createRealmRole() { - try { - jakarta.ws.rs.core.Response response = roleServiceClient.createRealmRole(newRole, realmName); - RoleDTO created = response.readEntity(RoleDTO.class); - addSuccessMessage("Rôle Realm créé avec succès: " + created.getName()); - resetForm(); - loadRealmRoles(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la création: " + e.getMessage()); - addErrorMessage("Erreur lors de la création: " + e.getMessage()); - } - } - - /** - * Créer un nouveau rôle Client - */ - public void createClientRole() { - if (clientName == null || clientName.isEmpty()) { - addErrorMessage("Le nom du client est obligatoire"); - return; - } - - try { - jakarta.ws.rs.core.Response response = roleServiceClient.createClientRole(clientName, newRole, realmName); - RoleDTO created = response.readEntity(RoleDTO.class); - addSuccessMessage("Rôle Client créé avec succès: " + created.getName()); - resetForm(); - loadClientRoles(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la création: " + e.getMessage()); - addErrorMessage("Erreur lors de la création: " + e.getMessage()); - } - } - - /** - * Supprimer un rôle Realm - */ - public void deleteRealmRole(String roleName) { - try { - roleServiceClient.deleteRealmRole(roleName, realmName); - addSuccessMessage("Rôle Realm supprimé avec succès: " + roleName); - loadRealmRoles(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); - addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); - } - } - - /** - * Supprimer un rôle Client - */ - public void deleteClientRole(String roleName) { - if (clientName == null || clientName.isEmpty()) { - addErrorMessage("Le nom du client est obligatoire"); - return; - } - - try { - roleServiceClient.deleteClientRole(clientName, roleName, realmName); - addSuccessMessage("Rôle Client supprimé avec succès: " + roleName); - loadClientRoles(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); - addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); - } - } - - /** - * Attribuer un rôle à un utilisateur - */ - public void assignRoleToUser(String userId, String roleName) { - try { - dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO request = new dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO( - List.of(roleName)); - - roleServiceClient.assignRealmRoles(userId, realmName, request); - addSuccessMessage("Rôle attribué avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'attribution: " + e.getMessage()); - addErrorMessage("Erreur lors de l'attribution: " + e.getMessage()); - } - } - - /** - * Révoquer un rôle d'un utilisateur - */ - public void revokeRoleFromUser(String userId, String roleName) { - try { - dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO request = new dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO( - List.of(roleName)); - - roleServiceClient.revokeRealmRoles(userId, realmName, request); - addSuccessMessage("Rôle révoqué avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la révocation: " + e.getMessage()); - addErrorMessage("Erreur lors de la révocation: " + e.getMessage()); - } - } - - /** - * Attribuer un rôle à un utilisateur (depuis les paramètres de requête) - */ - public void assignRoleFromParams() { - FacesContext context = FacesContext.getCurrentInstance(); - String userId = context.getExternalContext().getRequestParameterMap().get("userId"); - String roleName = context.getExternalContext().getRequestParameterMap().get("roleName"); - - if (userId != null && roleName != null) { - assignRoleToUser(userId, roleName); - } else { - addErrorMessage("Paramètres manquants: userId ou roleName"); - } - } - - /** - * Révoquer un rôle d'un utilisateur (depuis les paramètres de requête) - */ - public void revokeRoleFromParams() { - FacesContext context = FacesContext.getCurrentInstance(); - String userId = context.getExternalContext().getRequestParameterMap().get("userId"); - String roleName = context.getExternalContext().getRequestParameterMap().get("roleName"); - - if (userId != null && roleName != null) { - revokeRoleFromUser(userId, roleName); - } else { - addErrorMessage("Paramètres manquants: userId ou roleName"); - } - } - - /** - * Obtenir les rôles RoleDTO correspondant aux noms de rôles de l'utilisateur - */ - public List getUserRolesDTOs(UserDTO user) { - if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) { - return new ArrayList<>(); - } - - if (allRoles == null || allRoles.isEmpty()) { - return new ArrayList<>(); - } - - return allRoles.stream() - .filter(role -> user.getRealmRoles().contains(role.getName())) - .collect(Collectors.toList()); - } - - /** - * Réinitialiser le formulaire - */ - public void resetForm() { - newRole = RoleDTO.builder().build(); - editMode = false; - } - - /** - * Charger les realms disponibles depuis Keycloak - */ - private void loadRealms() { - try { - availableRealms = realmServiceClient.getAllRealms(); - LOGGER.info("Realms chargés: " + availableRealms); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); - availableRealms = List.of("master", "lions-user-manager", "btpxpress", "unionflow"); - } - } - - /** - * Charger les clients disponibles pour le realm sélectionné - */ - private void loadClients() { - if (realmName == null || realmName.isEmpty()) { - availableClients = new ArrayList<>(); - return; - } - - try { - availableClients = realmServiceClient.getRealmClients(realmName); - LOGGER.info("Clients chargés pour " + realmName + ": " + availableClients.size()); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des clients: " + e.getMessage()); - availableClients = new ArrayList<>(); - } - } - - /** - * Charger les rôles du realm spécifié. - */ - public void loadRolesForUser(String realm) { - if (realm != null && !realm.isEmpty()) { - this.realmName = realm; - loadRealmRoles(); - } else { - loadRealmRoles(); - } - } - - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.RoleServiceClient; +import dev.lions.user.manager.client.service.RealmServiceClient; +import dev.lions.user.manager.dto.role.RoleAssignmentDTO; +import dev.lions.user.manager.dto.role.RoleDTO; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.enums.role.TypeRole; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +/** + * Bean JSF pour la gestion des rôles + */ +@Named("roleGestionBean") +@ViewScoped +@Data +public class RoleGestionBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(RoleGestionBean.class.getName()); + + @Inject + @RestClient + private RoleServiceClient roleServiceClient; + + @Inject + @RestClient + private RealmServiceClient realmServiceClient; + + // Liste des rôles + private List realmRoles = new ArrayList<>(); + private List clientRoles = new ArrayList<>(); + private List allRoles = new ArrayList<>(); + private RoleDTO selectedRole; + private String selectedRoleName; + + // Pour la création/édition + private RoleDTO newRole = RoleDTO.builder().build(); + private boolean editMode = false; + + // Filtres + private String realmName = "lions-user-manager"; + private String clientName; + private TypeRole selectedTypeRole; + private String roleSearchText; + + // Options + private List typeRoleOptions = List.of(TypeRole.values()); + private List availableRealms = new ArrayList<>(); + private List availableClients = new ArrayList<>(); + + @PostConstruct + public void init() { + loadRealms(); + loadRealmRoles(); + } + + /** + * Charger les rôles Realm + */ + public void loadRealmRoles() { + if (realmName == null || realmName.isEmpty()) { + LOGGER.warning("Realm non sélectionné, impossible de charger les rôles"); + addErrorMessage("Veuillez sélectionner un realm"); + return; + } + + try { + LOGGER.info("Chargement des rôles Realm pour le realm: " + realmName); + realmRoles = roleServiceClient.getAllRealmRoles(realmName); + updateAllRoles(); + loadClients(); + LOGGER.info("Chargement réussi: " + realmRoles.size() + " rôles Realm trouvés"); + if (realmRoles.isEmpty()) { + addErrorMessage("Aucun rôle Realm trouvé dans le realm: " + realmName); + } + } catch (Exception e) { + String errorMsg = "Erreur lors du chargement des rôles Realm pour le realm '" + realmName + "': " + + e.getMessage(); + LOGGER.severe(errorMsg); + LOGGER.log(java.util.logging.Level.SEVERE, "Exception complète", e); + addErrorMessage(errorMsg); + realmRoles = new ArrayList<>(); + updateAllRoles(); + } + } + + /** + * Charger les rôles Client + */ + public void loadClientRoles() { + if (clientName == null || clientName.isEmpty()) { + clientRoles = new ArrayList<>(); + updateAllRoles(); + return; + } + + try { + clientRoles = roleServiceClient.getAllClientRoles(clientName, realmName); + updateAllRoles(); + LOGGER.info("Chargement de " + clientRoles.size() + " rôles Client"); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des rôles Client: " + e.getMessage()); + addErrorMessage("Erreur lors du chargement des rôles Client"); + } + } + + /** + * Mettre à jour la liste complète des rôles + */ + private void updateAllRoles() { + allRoles = new ArrayList<>(); + allRoles.addAll(realmRoles); + allRoles.addAll(clientRoles); + } + + /** + * Obtenir les rôles Realm filtrés par type + */ + public List getFilteredRealmRoles() { + if (selectedTypeRole == null) { + return realmRoles; + } + return realmRoles.stream() + .filter(r -> selectedTypeRole.equals(r.getTypeRole())) + .collect(Collectors.toList()); + } + + /** + * Obtenir les rôles Client filtrés par type + */ + public List getFilteredClientRoles() { + if (selectedTypeRole == null) { + return clientRoles; + } + return clientRoles.stream() + .filter(r -> selectedTypeRole.equals(r.getTypeRole())) + .collect(Collectors.toList()); + } + + /** + * Appliquer le filtre type (appelé depuis p:ajax) + */ + public void applyTypeFilter() { + // Les getFilteredRealmRoles/getFilteredClientRoles font le filtrage + LOGGER.info("Filtre type appliqué: " + selectedTypeRole); + } + + /** + * Créer un nouveau rôle Realm + */ + public void createRealmRole() { + try { + jakarta.ws.rs.core.Response response = roleServiceClient.createRealmRole(newRole, realmName); + RoleDTO created = response.readEntity(RoleDTO.class); + addSuccessMessage("Rôle Realm créé avec succès: " + created.getName()); + resetForm(); + loadRealmRoles(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la création: " + e.getMessage()); + addErrorMessage("Erreur lors de la création: " + e.getMessage()); + } + } + + /** + * Créer un nouveau rôle Client + */ + public void createClientRole() { + if (clientName == null || clientName.isEmpty()) { + addErrorMessage("Le nom du client est obligatoire"); + return; + } + + try { + jakarta.ws.rs.core.Response response = roleServiceClient.createClientRole(clientName, newRole, realmName); + RoleDTO created = response.readEntity(RoleDTO.class); + addSuccessMessage("Rôle Client créé avec succès: " + created.getName()); + resetForm(); + loadClientRoles(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la création: " + e.getMessage()); + addErrorMessage("Erreur lors de la création: " + e.getMessage()); + } + } + + /** + * Supprimer un rôle Realm + */ + public void deleteRealmRole(String roleName) { + try { + roleServiceClient.deleteRealmRole(roleName, realmName); + addSuccessMessage("Rôle Realm supprimé avec succès: " + roleName); + loadRealmRoles(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); + addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); + } + } + + /** + * Supprimer un rôle Client + */ + public void deleteClientRole(String roleName) { + if (clientName == null || clientName.isEmpty()) { + addErrorMessage("Le nom du client est obligatoire"); + return; + } + + try { + roleServiceClient.deleteClientRole(clientName, roleName, realmName); + addSuccessMessage("Rôle Client supprimé avec succès: " + roleName); + loadClientRoles(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); + addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); + } + } + + /** + * Attribuer un rôle à un utilisateur + */ + public void assignRoleToUser(String userId, String roleName) { + try { + dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO request = new dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO( + List.of(roleName)); + + roleServiceClient.assignRealmRoles(userId, realmName, request); + addSuccessMessage("Rôle attribué avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'attribution: " + e.getMessage()); + addErrorMessage("Erreur lors de l'attribution: " + e.getMessage()); + } + } + + /** + * Révoquer un rôle d'un utilisateur + */ + public void revokeRoleFromUser(String userId, String roleName) { + try { + dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO request = new dev.lions.user.manager.dto.role.RoleAssignmentRequestDTO( + List.of(roleName)); + + roleServiceClient.revokeRealmRoles(userId, realmName, request); + addSuccessMessage("Rôle révoqué avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la révocation: " + e.getMessage()); + addErrorMessage("Erreur lors de la révocation: " + e.getMessage()); + } + } + + /** + * Attribuer un rôle à un utilisateur (depuis les paramètres de requête) + */ + public void assignRoleFromParams() { + FacesContext context = FacesContext.getCurrentInstance(); + String userId = context.getExternalContext().getRequestParameterMap().get("userId"); + String roleName = context.getExternalContext().getRequestParameterMap().get("roleName"); + + if (userId != null && roleName != null) { + assignRoleToUser(userId, roleName); + } else { + addErrorMessage("Paramètres manquants: userId ou roleName"); + } + } + + /** + * Révoquer un rôle d'un utilisateur (depuis les paramètres de requête) + */ + public void revokeRoleFromParams() { + FacesContext context = FacesContext.getCurrentInstance(); + String userId = context.getExternalContext().getRequestParameterMap().get("userId"); + String roleName = context.getExternalContext().getRequestParameterMap().get("roleName"); + + if (userId != null && roleName != null) { + revokeRoleFromUser(userId, roleName); + } else { + addErrorMessage("Paramètres manquants: userId ou roleName"); + } + } + + /** + * Obtenir les rôles RoleDTO correspondant aux noms de rôles de l'utilisateur + */ + public List getUserRolesDTOs(UserDTO user) { + if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) { + return new ArrayList<>(); + } + + if (allRoles == null || allRoles.isEmpty()) { + return new ArrayList<>(); + } + + return allRoles.stream() + .filter(role -> user.getRealmRoles().contains(role.getName())) + .collect(Collectors.toList()); + } + + /** + * Réinitialiser le formulaire + */ + public void resetForm() { + newRole = RoleDTO.builder().build(); + editMode = false; + } + + /** + * Charger les realms disponibles depuis Keycloak + */ + private void loadRealms() { + try { + availableRealms = realmServiceClient.getAllRealms(); + LOGGER.info("Realms chargés: " + availableRealms); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); + availableRealms = List.of("master", "lions-user-manager", "btpxpress", "unionflow"); + } + } + + /** + * Charger les clients disponibles pour le realm sélectionné + */ + private void loadClients() { + if (realmName == null || realmName.isEmpty()) { + availableClients = new ArrayList<>(); + return; + } + + try { + availableClients = realmServiceClient.getRealmClients(realmName); + LOGGER.info("Clients chargés pour " + realmName + ": " + availableClients.size()); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des clients: " + e.getMessage()); + availableClients = new ArrayList<>(); + } + } + + /** + * Charger les rôles du realm spécifié. + */ + public void loadRolesForUser(String realm) { + if (realm != null && !realm.isEmpty()) { + this.realmName = realm; + loadRealmRoles(); + } else { + loadRealmRoles(); + } + } + + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/RoleView.java b/src/main/java/dev/lions/user/manager/client/view/RoleView.java index 98de8f8..22f0e15 100644 --- a/src/main/java/dev/lions/user/manager/client/view/RoleView.java +++ b/src/main/java/dev/lions/user/manager/client/view/RoleView.java @@ -1,98 +1,98 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.api.RoleRestClient; -import dev.lions.user.manager.dto.role.RoleDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -@Named -@ViewScoped -@Slf4j -public class RoleView implements Serializable { - - @Inject - @RestClient - RoleRestClient roleRestClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") - String defaultRealm; - - @Getter - @Setter - private List roles; - - @Getter - @Setter - private RoleDTO selectedRole; - - @Getter - @Setter - private String selectedRealm; - - @PostConstruct - public void init() { - this.selectedRealm = defaultRealm; - this.selectedRole = new RoleDTO(); - loadRoles(); - } - - public void loadRoles() { - try { - roles = roleRestClient.getAllRealmRoles(selectedRealm); - } catch (Exception e) { - log.error("Error loading roles", e); - roles = new ArrayList<>(); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Impossible de charger les rôles")); - } - } - - public void openNew() { - this.selectedRole = new RoleDTO(); - } - - public void saveRole() { - try { - if (this.selectedRole.getId() == null) { - // Create - roleRestClient.createRealmRole(selectedRealm, this.selectedRole); - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle créé")); - } else { - // Update - roleRestClient.updateRealmRole(this.selectedRole.getName(), selectedRealm, this.selectedRole); - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle mis à jour")); - } - loadRoles(); - } catch (Exception e) { - log.error("Error saving role", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); - } - } - - public void deleteRole() { - try { - roleRestClient.deleteRealmRole(this.selectedRole.getName(), selectedRealm); - this.selectedRole = null; - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle supprimé")); - loadRoles(); - } catch (Exception e) { - log.error("Error deleting role", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); - } - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.api.RoleRestClient; +import dev.lions.user.manager.dto.role.RoleDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Named +@ViewScoped +@Slf4j +public class RoleView implements Serializable { + + @Inject + @RestClient + RoleRestClient roleRestClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") + String defaultRealm; + + @Getter + @Setter + private List roles; + + @Getter + @Setter + private RoleDTO selectedRole; + + @Getter + @Setter + private String selectedRealm; + + @PostConstruct + public void init() { + this.selectedRealm = defaultRealm; + this.selectedRole = new RoleDTO(); + loadRoles(); + } + + public void loadRoles() { + try { + roles = roleRestClient.getAllRealmRoles(selectedRealm); + } catch (Exception e) { + log.error("Error loading roles", e); + roles = new ArrayList<>(); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Impossible de charger les rôles")); + } + } + + public void openNew() { + this.selectedRole = new RoleDTO(); + } + + public void saveRole() { + try { + if (this.selectedRole.getId() == null) { + // Create + roleRestClient.createRealmRole(selectedRealm, this.selectedRole); + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle créé")); + } else { + // Update + roleRestClient.updateRealmRole(this.selectedRole.getName(), selectedRealm, this.selectedRole); + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle mis à jour")); + } + loadRoles(); + } catch (Exception e) { + log.error("Error saving role", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); + } + } + + public void deleteRole() { + try { + roleRestClient.deleteRealmRole(this.selectedRole.getName(), selectedRealm); + this.selectedRole = null; + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Rôle supprimé")); + loadRoles(); + } catch (Exception e) { + log.error("Error deleting role", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); + } + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/SessionMonitorBean.java b/src/main/java/dev/lions/user/manager/client/view/SessionMonitorBean.java deleted file mode 100644 index 21f7c36..0000000 --- a/src/main/java/dev/lions/user/manager/client/view/SessionMonitorBean.java +++ /dev/null @@ -1,156 +0,0 @@ -package dev.lions.user.manager.client.view; - -import jakarta.enterprise.context.SessionScoped; -import jakarta.inject.Named; - -import java.io.Serializable; -import java.time.Instant; -import java.time.Duration; -import java.util.logging.Logger; - -/** - * Bean de monitoring de session utilisateur en temps réel - * Calcule le temps restant avant expiration du token JWT - * - * @author Lions User Manager Team - * @version 1.0 - */ -@Named("sessionMonitor") -@SessionScoped -public class SessionMonitorBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(SessionMonitorBean.class.getName()); - - // Temps d'inactivité maximum en secondes (30 minutes par défaut) - private static final long DEFAULT_INACTIVITY_TIMEOUT = 1800; - - private Instant lastActivityTime; - private long inactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT; - - public SessionMonitorBean() { - this.lastActivityTime = Instant.now(); - } - - /** - * Met à jour le timestamp de la dernière activité - */ - public void updateActivity() { - this.lastActivityTime = Instant.now(); - } - - /** - * Calcule le temps d'inactivité en secondes - */ - public long getInactivitySeconds() { - if (lastActivityTime == null) { - lastActivityTime = Instant.now(); - return 0; - } - return Duration.between(lastActivityTime, Instant.now()).getSeconds(); - } - - /** - * Calcule le temps restant avant expiration en minutes - */ - public long getRemainingMinutes() { - long inactivitySeconds = getInactivitySeconds(); - long remainingSeconds = inactivityTimeout - inactivitySeconds; - - if (remainingSeconds < 0) { - return 0; - } - - return remainingSeconds / 60; - } - - /** - * Calcule le temps restant avant expiration en secondes (pour le timer) - */ - public long getRemainingSeconds() { - long inactivitySeconds = getInactivitySeconds(); - long remainingSeconds = inactivityTimeout - inactivitySeconds; - - return Math.max(0, remainingSeconds); - } - - /** - * Formate le temps restant en format mm:ss - */ - public String getFormattedRemainingTime() { - long totalSeconds = getRemainingSeconds(); - long minutes = totalSeconds / 60; - long seconds = totalSeconds % 60; - return String.format("%02d:%02d", minutes, seconds); - } - - /** - * Retourne le pourcentage de temps écoulé (pour une barre de progression) - */ - public int getSessionProgressPercent() { - long inactivitySeconds = getInactivitySeconds(); - if (inactivityTimeout == 0) - return 0; - - int percent = (int) ((inactivitySeconds * 100) / inactivityTimeout); - return Math.min(100, Math.max(0, percent)); - } - - /** - * Vérifie si la session est proche de l'expiration (moins de 5 minutes) - */ - public boolean isSessionExpiringSoon() { - return getRemainingMinutes() <= 5; - } - - /** - * Vérifie si la session est expirée - */ - public boolean isSessionExpired() { - return getRemainingSeconds() == 0; - } - - /** - * Retourne la classe CSS pour l'indicateur de temps (couleur) - */ - public String getTimeIndicatorClass() { - long minutes = getRemainingMinutes(); - if (minutes <= 3) { - return "text-red-600 font-bold"; // Rouge critique - } else if (minutes <= 5) { - return "text-orange-600 font-semibold"; // Orange warning - } else if (minutes <= 10) { - return "text-yellow-600"; // Jaune attention - } else { - return "text-green-600"; // Vert OK - } - } - - /** - * Retourne l'icône appropriée selon le temps restant - */ - public String getTimeIndicatorIcon() { - long minutes = getRemainingMinutes(); - if (minutes <= 3) { - return "pi pi-exclamation-triangle"; - } else if (minutes <= 5) { - return "pi pi-clock"; - } else { - return "pi pi-check-circle"; - } - } - - // Getters et Setters - - public long getInactivityTimeout() { - return inactivityTimeout; - } - - public void setInactivityTimeout(long inactivityTimeout) { - this.inactivityTimeout = inactivityTimeout; - } - - public Instant getLastActivityTime() { - return lastActivityTime; - } -} diff --git a/src/main/java/dev/lions/user/manager/client/view/SettingsBean.java b/src/main/java/dev/lions/user/manager/client/view/SettingsBean.java index a7a314e..92c742a 100644 --- a/src/main/java/dev/lions/user/manager/client/view/SettingsBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/SettingsBean.java @@ -1,63 +1,65 @@ -package dev.lions.user.manager.client.view; - -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; - -import java.io.Serializable; -import java.util.logging.Logger; - -/** - * Bean JSF pour la page de paramètres - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("settingsBean") -@ViewScoped -@Data -public class SettingsBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(SettingsBean.class.getName()); - - @Inject - private UserSessionBean userSessionBean; - - @Inject - private GuestPreferences guestPreferences; - - @PostConstruct - public void init() { - LOGGER.info("Initialisation de SettingsBean"); - } - - /** - * Sauvegarder les préférences - */ - public void savePreferences() { - try { - // Les préférences sont déjà sauvegardées dans GuestPreferences (SessionScoped) - addSuccessMessage("Préférences sauvegardées avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la sauvegarde: " + e.getMessage()); - addErrorMessage("Erreur lors de la sauvegarde: " + e.getMessage()); - } - } - - // Méthodes utilitaires - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} - +package dev.lions.user.manager.client.view; + +import dev.lions.faces.layout.view.GuestPreferences; +import dev.lions.faces.layout.view.UserSessionBean; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; + +import java.io.Serializable; +import java.util.logging.Logger; + +/** + * Bean JSF pour la page de paramètres + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("settingsBean") +@ViewScoped +@Data +public class SettingsBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(SettingsBean.class.getName()); + + @Inject + private UserSessionBean userSessionBean; + + @Inject + private GuestPreferences guestPreferences; + + @PostConstruct + public void init() { + LOGGER.info("Initialisation de SettingsBean"); + } + + /** + * Sauvegarder les préférences + */ + public void savePreferences() { + try { + // Les préférences sont déjà sauvegardées dans GuestPreferences (SessionScoped) + addSuccessMessage("Préférences sauvegardées avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la sauvegarde: " + e.getMessage()); + addErrorMessage("Erreur lors de la sauvegarde: " + e.getMessage()); + } + } + + // Méthodes utilitaires + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} + diff --git a/src/main/java/dev/lions/user/manager/client/view/SyncDashboardBean.java b/src/main/java/dev/lions/user/manager/client/view/SyncDashboardBean.java index 8aa8b56..f07fdba 100644 --- a/src/main/java/dev/lions/user/manager/client/view/SyncDashboardBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/SyncDashboardBean.java @@ -1,215 +1,215 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.SyncServiceClient; -import dev.lions.user.manager.dto.sync.HealthStatusDTO; -import dev.lions.user.manager.dto.sync.SyncConsistencyDTO; -import dev.lions.user.manager.dto.sync.SyncHistoryDTO; -import dev.lions.user.manager.dto.sync.SyncResultDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.time.format.DateTimeFormatter; -import java.util.logging.Logger; - -@Named -@ViewScoped -public class SyncDashboardBean implements Serializable { - - private static final Logger LOGGER = Logger.getLogger(SyncDashboardBean.class.getName()); - - private static final DateTimeFormatter DISPLAY_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); - - @Inject - @RestClient - SyncServiceClient syncService; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") - String defaultRealm; - - private HealthStatusDTO keycloakStatus; - private SyncConsistencyDTO consistencyResult; - private SyncHistoryDTO lastSyncStatus; - private String syncMessage; - private String targetRealm; - - @PostConstruct - public void init() { - this.targetRealm = defaultRealm; - checkKeycloakStatus(); - loadLastSyncStatus(); - } - - public void checkKeycloakStatus() { - try { - this.keycloakStatus = syncService.checkKeycloakHealth(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la vérification de l'état de Keycloak: " + e.getMessage()); - this.keycloakStatus = new HealthStatusDTO(); - this.keycloakStatus.setOverallHealthy(false); - this.keycloakStatus.setErrorMessage("Erreur de connexion: " + e.getMessage()); - } - } - - public void syncUsers() { - try { - SyncResultDTO result = syncService.syncUsers(targetRealm); - handleSyncResult("Utilisateurs", result); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la synchronisation des utilisateurs: " + e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", - "Echec de la synchronisation des utilisateurs: " + e.getMessage()); - } - } - - public void syncRoles() { - try { - // Sychronize realm roles - SyncResultDTO result = syncService.syncRoles(targetRealm, null); - handleSyncResult("Rôles", result); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la synchronisation des rôles: " + e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", - "Echec de la synchronisation des rôles: " + e.getMessage()); - } - } - - public void checkDataConsistency() { - try { - this.consistencyResult = syncService.checkDataConsistency(targetRealm); - String status = consistencyResult.getStatus(); - if ("OK".equals(status)) { - addMessage(FacesMessage.SEVERITY_INFO, "Cohérence OK", - consistencyResult.getUsersKeycloakCount() + " utilisateurs, " - + consistencyResult.getRolesKeycloakCount() + " rôles — données cohérentes."); - } else { - int missingLocal = (consistencyResult.getMissingUsersInLocal() != null - ? consistencyResult.getMissingUsersInLocal().size() : 0) - + (consistencyResult.getMissingRolesInLocal() != null - ? consistencyResult.getMissingRolesInLocal().size() : 0); - addMessage(FacesMessage.SEVERITY_WARN, "Incohérence détectée", - missingLocal + " élément(s) manquant(s) localement. Lancez une synchronisation."); - } - } catch (Exception e) { - LOGGER.severe("Erreur vérification cohérence: " + e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Impossible de vérifier la cohérence: " + e.getMessage()); - } - } - - public void loadLastSyncStatus() { - try { - this.lastSyncStatus = syncService.getLastSyncStatus(targetRealm); - } catch (Exception e) { - LOGGER.warning("Impossible de charger le statut de sync: " + e.getMessage()); - } - } - - public void forceSyncRealm() { - try { - this.lastSyncStatus = syncService.forceSyncRealm(targetRealm); - String status = lastSyncStatus != null ? lastSyncStatus.getStatus() : "UNKNOWN"; - if ("SUCCESS".equals(status)) { - Integer items = lastSyncStatus.getItemsProcessed(); - addMessage(FacesMessage.SEVERITY_INFO, "Synchronisation forcée réussie", - (items != null ? items : 0) + " éléments traités."); - } else { - addMessage(FacesMessage.SEVERITY_WARN, "Synchronisation terminée avec avertissement", - lastSyncStatus != null ? lastSyncStatus.getErrorMessage() : "Statut inconnu"); - } - } catch (Exception e) { - LOGGER.severe("Erreur synchronisation forcée: " + e.getMessage()); - addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Echec de la synchronisation forcée: " + e.getMessage()); - } - } - - // Convenience methods for view - public String getLastSyncDate() { - if (lastSyncStatus == null || lastSyncStatus.getSyncDate() == null) return "Jamais synchronisé"; - return lastSyncStatus.getSyncDate().format(DISPLAY_FORMATTER); - } - - public String getLastSyncStatusLabel() { - if (lastSyncStatus == null) return "INCONNU"; - return lastSyncStatus.getStatus() != null ? lastSyncStatus.getStatus() : "INCONNU"; - } - - public String getLastSyncItemsProcessed() { - if (lastSyncStatus == null || lastSyncStatus.getItemsProcessed() == null) return "N/A"; - return String.valueOf(lastSyncStatus.getItemsProcessed()); - } - - public String getConsistencyStatusLabel() { - if (consistencyResult == null) return "Non vérifié"; - return consistencyResult.getStatus() != null ? consistencyResult.getStatus() : "N/A"; - } - - public int getConsistencyMissingCount() { - if (consistencyResult == null) return 0; - int missing = 0; - if (consistencyResult.getMissingUsersInLocal() != null) missing += consistencyResult.getMissingUsersInLocal().size(); - if (consistencyResult.getMissingRolesInLocal() != null) missing += consistencyResult.getMissingRolesInLocal().size(); - return missing; - } - - private void handleSyncResult(String type, SyncResultDTO result) { - String msg = result.isSuccess() - ? "Synchronisation réussie. " + type + " synchronisés : " - + ("Utilisateurs".equals(type) ? result.getUsersCount() : result.getRealmRolesCount()) - : result.getErrorMessage(); - - if (result.isSuccess()) { - addMessage(FacesMessage.SEVERITY_INFO, "Succès", msg); - } else { - addMessage(FacesMessage.SEVERITY_WARN, "Attention", type + ": " + msg); - } - this.syncMessage = msg; - } - - private void addMessage(FacesMessage.Severity severity, String summary, String detail) { - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail)); - } - - // Getters and Setters - public HealthStatusDTO getKeycloakStatus() { return keycloakStatus; } - public void setKeycloakStatus(HealthStatusDTO keycloakStatus) { this.keycloakStatus = keycloakStatus; } - public SyncConsistencyDTO getConsistencyResult() { return consistencyResult; } - public SyncHistoryDTO getLastSyncStatusDTO() { return lastSyncStatus; } - - public String getKeycloakStatusLabel() { - return (keycloakStatus != null && keycloakStatus.isOverallHealthy()) ? "UP" : "DOWN"; - } - - public String getKeycloakStatusMessage() { - if (keycloakStatus == null) - return "Unknown status"; - if (keycloakStatus.isOverallHealthy()) - return "Keycloak est accessible."; - return keycloakStatus.getErrorMessage() != null ? keycloakStatus.getErrorMessage() : "Erreur inconnue"; - } - - public String getKeycloakVersion() { - return (keycloakStatus != null) ? keycloakStatus.getKeycloakVersion() : "N/A"; - } - - public String getSyncMessage() { - return syncMessage; - } - - public void setSyncMessage(String syncMessage) { - this.syncMessage = syncMessage; - } - - public String getTargetRealm() { - return targetRealm; - } - - public void setTargetRealm(String targetRealm) { - this.targetRealm = targetRealm; - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.SyncServiceClient; +import dev.lions.user.manager.dto.sync.HealthStatusDTO; +import dev.lions.user.manager.dto.sync.SyncConsistencyDTO; +import dev.lions.user.manager.dto.sync.SyncHistoryDTO; +import dev.lions.user.manager.dto.sync.SyncResultDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.time.format.DateTimeFormatter; +import java.util.logging.Logger; + +@Named +@ViewScoped +public class SyncDashboardBean implements Serializable { + + private static final Logger LOGGER = Logger.getLogger(SyncDashboardBean.class.getName()); + + private static final DateTimeFormatter DISPLAY_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); + + @Inject + @RestClient + SyncServiceClient syncService; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") + String defaultRealm; + + private HealthStatusDTO keycloakStatus; + private SyncConsistencyDTO consistencyResult; + private SyncHistoryDTO lastSyncStatus; + private String syncMessage; + private String targetRealm; + + @PostConstruct + public void init() { + this.targetRealm = defaultRealm; + checkKeycloakStatus(); + loadLastSyncStatus(); + } + + public void checkKeycloakStatus() { + try { + this.keycloakStatus = syncService.checkKeycloakHealth(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la vérification de l'état de Keycloak: " + e.getMessage()); + this.keycloakStatus = new HealthStatusDTO(); + this.keycloakStatus.setOverallHealthy(false); + this.keycloakStatus.setErrorMessage("Erreur de connexion: " + e.getMessage()); + } + } + + public void syncUsers() { + try { + SyncResultDTO result = syncService.syncUsers(targetRealm); + handleSyncResult("Utilisateurs", result); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la synchronisation des utilisateurs: " + e.getMessage()); + addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", + "Echec de la synchronisation des utilisateurs: " + e.getMessage()); + } + } + + public void syncRoles() { + try { + // Sychronize realm roles + SyncResultDTO result = syncService.syncRoles(targetRealm, null); + handleSyncResult("Rôles", result); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la synchronisation des rôles: " + e.getMessage()); + addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", + "Echec de la synchronisation des rôles: " + e.getMessage()); + } + } + + public void checkDataConsistency() { + try { + this.consistencyResult = syncService.checkDataConsistency(targetRealm); + String status = consistencyResult.getStatus(); + if ("OK".equals(status)) { + addMessage(FacesMessage.SEVERITY_INFO, "Cohérence OK", + consistencyResult.getUsersKeycloakCount() + " utilisateurs, " + + consistencyResult.getRolesKeycloakCount() + " rôles — données cohérentes."); + } else { + int missingLocal = (consistencyResult.getMissingUsersInLocal() != null + ? consistencyResult.getMissingUsersInLocal().size() : 0) + + (consistencyResult.getMissingRolesInLocal() != null + ? consistencyResult.getMissingRolesInLocal().size() : 0); + addMessage(FacesMessage.SEVERITY_WARN, "Incohérence détectée", + missingLocal + " élément(s) manquant(s) localement. Lancez une synchronisation."); + } + } catch (Exception e) { + LOGGER.severe("Erreur vérification cohérence: " + e.getMessage()); + addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Impossible de vérifier la cohérence: " + e.getMessage()); + } + } + + public void loadLastSyncStatus() { + try { + this.lastSyncStatus = syncService.getLastSyncStatus(targetRealm); + } catch (Exception e) { + LOGGER.warning("Impossible de charger le statut de sync: " + e.getMessage()); + } + } + + public void forceSyncRealm() { + try { + this.lastSyncStatus = syncService.forceSyncRealm(targetRealm); + String status = lastSyncStatus != null ? lastSyncStatus.getStatus() : "UNKNOWN"; + if ("SUCCESS".equals(status)) { + Integer items = lastSyncStatus.getItemsProcessed(); + addMessage(FacesMessage.SEVERITY_INFO, "Synchronisation forcée réussie", + (items != null ? items : 0) + " éléments traités."); + } else { + addMessage(FacesMessage.SEVERITY_WARN, "Synchronisation terminée avec avertissement", + lastSyncStatus != null ? lastSyncStatus.getErrorMessage() : "Statut inconnu"); + } + } catch (Exception e) { + LOGGER.severe("Erreur synchronisation forcée: " + e.getMessage()); + addMessage(FacesMessage.SEVERITY_ERROR, "Erreur", "Echec de la synchronisation forcée: " + e.getMessage()); + } + } + + // Convenience methods for view + public String getLastSyncDate() { + if (lastSyncStatus == null || lastSyncStatus.getSyncDate() == null) return "Jamais synchronisé"; + return lastSyncStatus.getSyncDate().format(DISPLAY_FORMATTER); + } + + public String getLastSyncStatusLabel() { + if (lastSyncStatus == null) return "INCONNU"; + return lastSyncStatus.getStatus() != null ? lastSyncStatus.getStatus() : "INCONNU"; + } + + public String getLastSyncItemsProcessed() { + if (lastSyncStatus == null || lastSyncStatus.getItemsProcessed() == null) return "N/A"; + return String.valueOf(lastSyncStatus.getItemsProcessed()); + } + + public String getConsistencyStatusLabel() { + if (consistencyResult == null) return "Non vérifié"; + return consistencyResult.getStatus() != null ? consistencyResult.getStatus() : "N/A"; + } + + public int getConsistencyMissingCount() { + if (consistencyResult == null) return 0; + int missing = 0; + if (consistencyResult.getMissingUsersInLocal() != null) missing += consistencyResult.getMissingUsersInLocal().size(); + if (consistencyResult.getMissingRolesInLocal() != null) missing += consistencyResult.getMissingRolesInLocal().size(); + return missing; + } + + private void handleSyncResult(String type, SyncResultDTO result) { + String msg = result.isSuccess() + ? "Synchronisation réussie. " + type + " synchronisés : " + + ("Utilisateurs".equals(type) ? result.getUsersCount() : result.getRealmRolesCount()) + : result.getErrorMessage(); + + if (result.isSuccess()) { + addMessage(FacesMessage.SEVERITY_INFO, "Succès", msg); + } else { + addMessage(FacesMessage.SEVERITY_WARN, "Attention", type + ": " + msg); + } + this.syncMessage = msg; + } + + private void addMessage(FacesMessage.Severity severity, String summary, String detail) { + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail)); + } + + // Getters and Setters + public HealthStatusDTO getKeycloakStatus() { return keycloakStatus; } + public void setKeycloakStatus(HealthStatusDTO keycloakStatus) { this.keycloakStatus = keycloakStatus; } + public SyncConsistencyDTO getConsistencyResult() { return consistencyResult; } + public SyncHistoryDTO getLastSyncStatusDTO() { return lastSyncStatus; } + + public String getKeycloakStatusLabel() { + return (keycloakStatus != null && keycloakStatus.isOverallHealthy()) ? "UP" : "DOWN"; + } + + public String getKeycloakStatusMessage() { + if (keycloakStatus == null) + return "Unknown status"; + if (keycloakStatus.isOverallHealthy()) + return "Keycloak est accessible."; + return keycloakStatus.getErrorMessage() != null ? keycloakStatus.getErrorMessage() : "Erreur inconnue"; + } + + public String getKeycloakVersion() { + return (keycloakStatus != null) ? keycloakStatus.getKeycloakVersion() : "N/A"; + } + + public String getSyncMessage() { + return syncMessage; + } + + public void setSyncMessage(String syncMessage) { + this.syncMessage = syncMessage; + } + + public String getTargetRealm() { + return targetRealm; + } + + public void setTargetRealm(String targetRealm) { + this.targetRealm = targetRealm; + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserCreationBean.java b/src/main/java/dev/lions/user/manager/client/view/UserCreationBean.java index f4b52f2..d449f15 100644 --- a/src/main/java/dev/lions/user/manager/client/view/UserCreationBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/UserCreationBean.java @@ -1,161 +1,161 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.RealmServiceClient; -import dev.lions.user.manager.client.service.UserServiceClient; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.enums.user.StatutUser; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - -/** - * Bean JSF pour la création d'un nouvel utilisateur - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("userCreationBean") -@ViewScoped -@Data -public class UserCreationBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(UserCreationBean.class.getName()); - - @Inject - @RestClient - private UserServiceClient userServiceClient; - - @Inject - @RestClient - private RealmServiceClient realmServiceClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") - String defaultRealm; - - private UserDTO newUser = UserDTO.builder().build(); - private String realmName; - private String password; - private String passwordConfirm; - private boolean creationSuccess; - - // Options pour les selects - private List statutOptions = List.of(StatutUser.values()); - private List availableRealms = new ArrayList<>(); - - @PostConstruct - public void init() { - this.realmName = defaultRealm; - loadRealms(); - // Initialiser les valeurs par défaut - newUser.setEnabled(true); - newUser.setEmailVerified(false); - newUser.setStatut(StatutUser.ACTIF); - } - - /** - * Créer un nouvel utilisateur - */ - public void createUser() { - if (password == null || password.isEmpty()) { - addErrorMessage("Le mot de passe est obligatoire"); - return; - } - - if (!password.equals(passwordConfirm)) { - addErrorMessage("Les mots de passe ne correspondent pas"); - return; - } - - if (password.length() < 8) { - addErrorMessage("Le mot de passe doit contenir au moins 8 caractères"); - return; - } - - try { - jakarta.ws.rs.core.Response response = userServiceClient.createUser(newUser, realmName); - UserDTO createdUser = response.readEntity(UserDTO.class); - - dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( - password, false); - userServiceClient.resetPassword(createdUser.getId(), realmName, request); - - addSuccessMessage("Utilisateur '" + createdUser.getUsername() + "' créé avec succès !"); - creationSuccess = true; - resetForm(); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la création: " + e.getMessage()); - addErrorMessage("Erreur lors de la création : " + e.getMessage()); - } - } - - /** - * Réinitialiser le formulaire - */ - public void resetForm() { - newUser = UserDTO.builder().build(); - password = null; - passwordConfirm = null; - creationSuccess = false; - newUser.setEnabled(true); - newUser.setEmailVerified(false); - newUser.setStatut(StatutUser.ACTIF); - } - - /** - * Annuler la création — redirige vers la liste - */ - public void cancel() { - try { - FacesContext.getCurrentInstance().getExternalContext() - .redirect(FacesContext.getCurrentInstance().getExternalContext() - .getRequestContextPath() + "/pages/user-manager/users/list.xhtml"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la redirection: " + e.getMessage()); - } - } - - /** - * Charger les realms disponibles - */ - private void loadRealms() { - try { - LOGGER.info("Chargement des realms disponibles pour la création d'utilisateur"); - List realms = realmServiceClient.getAllRealms(); - - if (realms == null || realms.isEmpty()) { - LOGGER.warning("Aucun realm disponible lors du chargement des realms"); - availableRealms = new ArrayList<>(); - } else { - availableRealms = new ArrayList<>(realms); - } - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); - addErrorMessage("Erreur lors du chargement des realms: " + e.getMessage()); - // Fallback: liste vide plutôt que valeurs codées en dur - availableRealms = new ArrayList<>(); - } - } - - // Méthodes utilitaires - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.RealmServiceClient; +import dev.lions.user.manager.client.service.UserServiceClient; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.enums.user.StatutUser; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + +/** + * Bean JSF pour la création d'un nouvel utilisateur + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("userCreationBean") +@ViewScoped +@Data +public class UserCreationBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(UserCreationBean.class.getName()); + + @Inject + @RestClient + private UserServiceClient userServiceClient; + + @Inject + @RestClient + private RealmServiceClient realmServiceClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") + String defaultRealm; + + private UserDTO newUser = UserDTO.builder().build(); + private String realmName; + private String password; + private String passwordConfirm; + private boolean creationSuccess; + + // Options pour les selects + private List statutOptions = List.of(StatutUser.values()); + private List availableRealms = new ArrayList<>(); + + @PostConstruct + public void init() { + this.realmName = defaultRealm; + loadRealms(); + // Initialiser les valeurs par défaut + newUser.setEnabled(true); + newUser.setEmailVerified(false); + newUser.setStatut(StatutUser.ACTIF); + } + + /** + * Créer un nouvel utilisateur + */ + public void createUser() { + if (password == null || password.isEmpty()) { + addErrorMessage("Le mot de passe est obligatoire"); + return; + } + + if (!password.equals(passwordConfirm)) { + addErrorMessage("Les mots de passe ne correspondent pas"); + return; + } + + if (password.length() < 8) { + addErrorMessage("Le mot de passe doit contenir au moins 8 caractères"); + return; + } + + try { + jakarta.ws.rs.core.Response response = userServiceClient.createUser(newUser, realmName); + UserDTO createdUser = response.readEntity(UserDTO.class); + + dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( + password, false); + userServiceClient.resetPassword(createdUser.getId(), realmName, request); + + addSuccessMessage("Utilisateur '" + createdUser.getUsername() + "' créé avec succès !"); + creationSuccess = true; + resetForm(); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la création: " + e.getMessage()); + addErrorMessage("Erreur lors de la création : " + e.getMessage()); + } + } + + /** + * Réinitialiser le formulaire + */ + public void resetForm() { + newUser = UserDTO.builder().build(); + password = null; + passwordConfirm = null; + creationSuccess = false; + newUser.setEnabled(true); + newUser.setEmailVerified(false); + newUser.setStatut(StatutUser.ACTIF); + } + + /** + * Annuler la création — redirige vers la liste + */ + public void cancel() { + try { + FacesContext.getCurrentInstance().getExternalContext() + .redirect(FacesContext.getCurrentInstance().getExternalContext() + .getRequestContextPath() + "/pages/user-manager/users/list.xhtml"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la redirection: " + e.getMessage()); + } + } + + /** + * Charger les realms disponibles + */ + private void loadRealms() { + try { + LOGGER.info("Chargement des realms disponibles pour la création d'utilisateur"); + List realms = realmServiceClient.getAllRealms(); + + if (realms == null || realms.isEmpty()) { + LOGGER.warning("Aucun realm disponible lors du chargement des realms"); + availableRealms = new ArrayList<>(); + } else { + availableRealms = new ArrayList<>(realms); + } + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); + addErrorMessage("Erreur lors du chargement des realms: " + e.getMessage()); + // Fallback: liste vide plutôt que valeurs codées en dur + availableRealms = new ArrayList<>(); + } + } + + // Méthodes utilitaires + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserListBean.java b/src/main/java/dev/lions/user/manager/client/view/UserListBean.java index d36ed52..d3ab35e 100644 --- a/src/main/java/dev/lions/user/manager/client/view/UserListBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/UserListBean.java @@ -1,468 +1,468 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.RealmServiceClient; -import dev.lions.user.manager.client.service.UserServiceClient; -import dev.lions.user.manager.dto.importexport.ImportResultDTO; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; -import dev.lions.user.manager.dto.user.UserSearchResultDTO; -import dev.lions.user.manager.enums.user.StatutUser; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.ExternalContext; -import jakarta.faces.context.FacesContext; -import jakarta.faces.event.ActionEvent; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.ws.rs.core.Response; -import lombok.Data; -import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.primefaces.PrimeFaces; -import org.primefaces.model.FilterMeta; -import org.primefaces.model.LazyDataModel; -import org.primefaces.model.SortMeta; -import org.primefaces.model.file.UploadedFile; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import org.eclipse.microprofile.config.inject.ConfigProperty; - -/** - * Bean JSF pour la liste et la recherche d'utilisateurs - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("userListBean") -@ViewScoped -@Data -public class UserListBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(UserListBean.class.getName()); - - // Constantes de navigation outcomes (WOU/DRY - réutilisables) - private static final String OUTCOME_USER_PROFILE = "userProfilePage"; - private static final String OUTCOME_USER_EDIT = "userEditPage"; - private static final String OUTCOME_USER_CREATE = "userCreatePage"; - - @Inject - @RestClient - private UserServiceClient userServiceClient; - - @Inject - @RestClient - private RealmServiceClient realmServiceClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") - String defaultRealm; - - // Propriétés pour la liste - private LazyDataModel users; - private UserDTO selectedUser; - private List selectedUsers = new ArrayList<>(); - - // Propriétés pour la recherche - private UserSearchCriteriaDTO searchCriteria = UserSearchCriteriaDTO.builder().build(); - private String searchText; - private String realmName; - private StatutUser selectedStatut; - - // Propriétés pour la pagination - private int currentPage = 0; - private int pageSize = 20; - private long totalRecords = 0; - private int totalPages = 0; - - // KPIs chargés depuis le serveur (indépendants de la pagination/filtres) - private long kpiTotalUsers = 0; - private long activeUsersCount = 0; - private long disabledUsersCount = 0; - - // Options pour les selects - private List statutOptions = List.of(StatutUser.values()); - private List availableRealms = new ArrayList<>(); - - // Champs pour réinitialisation mot de passe - private String newPassword; - private String newPasswordConfirm; - - // Champ pour l'import CSV - private UploadedFile importedFile; - private ImportResultDTO lastImportResult; - - @PostConstruct - public void init() { - this.realmName = defaultRealm; - LOGGER.info("Initialisation de UserListBean - realm: " + realmName); - loadRealms(); - loadStats(); - - users = new LazyDataModel() { - @Override - public String getRowKey(UserDTO user) { - return user.getId(); - } - - @Override - public UserDTO getRowData(String rowKey) { - List list = (List) getWrappedData(); - if (list != null) { - for (UserDTO user : list) { - if (user.getId().equals(rowKey)) { - return user; - } - } - } - return null; - } - - @Override - public int count(Map filterBy) { - return (int) totalRecords; - } - - @Override - public List load(int first, int pageSize, Map sortBy, - Map filterBy) { - try { - int page = first / pageSize; - - UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() - .realmName(realmName) - .searchTerm(searchText) - .statut(selectedStatut) - .page(page) - .pageSize(pageSize) - .includeRoles(true) - .build(); - - UserSearchResultDTO result = userServiceClient.searchUsers(criteria); - List data = result.getUsers() != null ? result.getUsers() : new ArrayList<>(); - - long total = result.getTotalCount() != null ? result.getTotalCount() : 0; - this.setRowCount((int) total); - totalRecords = total; - - return data; - } catch (Exception e) { - LOGGER.severe("Erreur loading: " + e.getMessage()); - return new ArrayList<>(); - } - } - }; - } - - /** - * Charger la liste des utilisateurs - * (Deprecated: Utiliser LazyDataModel) - */ - public void loadUsers() { - // La méthode load du LazyDataModel est appelée automatiquement par le composant - } - - /** - * Rechercher des utilisateurs - */ - public void search() { - currentPage = 0; - if (PrimeFaces.current().isAjaxRequest()) { - PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); - } - } - - /** - * Réinitialiser la recherche - */ - public void resetSearch() { - searchText = null; - selectedStatut = null; - currentPage = 0; - if (PrimeFaces.current().isAjaxRequest()) { - PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); - } - } - - /** - * Réinitialiser le mot de passe - */ - public void resetPassword(String userId) { - if (newPassword != null && !newPassword.isEmpty() && newPassword.equals(newPasswordConfirm)) { - try { - // Utilisation du DTO pour la demande de réinitialisation - dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( - newPassword, false); - userServiceClient.resetPassword(userId, realmName, request); - addSuccessMessage("Mot de passe réinitialisé avec succès"); - // Clear fields - newPassword = null; - newPasswordConfirm = null; - } catch (Exception e) { - LOGGER.severe("Erreur lors de la réinitialisation du mot de passe: " + e.getMessage()); - addErrorMessage("Erreur lors de la réinitialisation: " + e.getMessage()); - } - } else { - addErrorMessage("Les mots de passe sont invalides ou ne correspondent pas"); - } - } - - /** - * Action pour activer un utilisateur (utilisé par le composant composite) - */ - public void activateUserAction(ActionEvent event) { - String userId = (String) event.getComponent().getAttributes().get("userId"); - if (userId != null) { - activateUser(userId); - } - } - - /** - * Action pour désactiver un utilisateur (utilisé par le composant composite) - */ - public void deactivateUserAction(ActionEvent event) { - String userId = (String) event.getComponent().getAttributes().get("userId"); - if (userId != null) { - deactivateUser(userId); - } - } - - /** - * Action pour supprimer un utilisateur (utilisé par le composant composite) - */ - public void deleteUserAction(ActionEvent event) { - String userId = (String) event.getComponent().getAttributes().get("userId"); - if (userId != null) { - deleteUser(userId); - } - } - - /** - * Activer un utilisateur - */ - public void activateUser(String userId) { - try { - userServiceClient.activateUser(userId, realmName); - activeUsersCount++; - disabledUsersCount = Math.max(0, disabledUsersCount - 1); - addSuccessMessage("Utilisateur activé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'activation: " + e.getMessage()); - addErrorMessage("Erreur lors de l'activation: " + e.getMessage()); - } - } - - /** - * Désactiver un utilisateur - */ - public void deactivateUser(String userId) { - try { - userServiceClient.deactivateUser(userId, realmName, "Désactivé par l'administrateur"); - activeUsersCount = Math.max(0, activeUsersCount - 1); - disabledUsersCount++; - addSuccessMessage("Utilisateur désactivé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage()); - addErrorMessage("Erreur lors de la désactivation: " + e.getMessage()); - } - } - - /** - * Supprimer un utilisateur - */ - public void deleteUser(String userId) { - try { - userServiceClient.deleteUser(userId, realmName, false); - kpiTotalUsers = Math.max(0, kpiTotalUsers - 1); - addSuccessMessage("Utilisateur supprimé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); - addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); - } - } - - /** - * Déconnecter toutes les sessions d'un utilisateur - */ - public void logoutAllSessions(String userId) { - try { - userServiceClient.logoutAllSessions(userId, realmName); - addSuccessMessage("Toutes les sessions ont été déconnectées"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage()); - addErrorMessage("Erreur lors de la déconnexion: " + e.getMessage()); - } - } - - /** - * Pourcentage d'utilisateurs actifs - */ - public int getActiveUsersPercentage() { - if (kpiTotalUsers == 0) return 0; - return (int) Math.round((double) activeUsersCount / kpiTotalUsers * 100); - } - - /** - * Pourcentage d'utilisateurs désactivés - */ - public int getDisabledUsersPercentage() { - if (kpiTotalUsers == 0) return 0; - return (int) Math.round((double) disabledUsersCount / kpiTotalUsers * 100); - } - - /** - * Rafraîchir les données et les KPIs - */ - public void refreshData() { - loadStats(); - addSuccessMessage("Données rafraîchies"); - } - - /** - * Changement de realm (filtre + rechargement des KPIs) - */ - public void onRealmChange() { - currentPage = 0; - loadStats(); - if (PrimeFaces.current().isAjaxRequest()) { - PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); - } - } - - /** - * Charger les statistiques KPI depuis le serveur - */ - private void loadStats() { - try { - UserSearchCriteriaDTO totalCriteria = UserSearchCriteriaDTO.builder() - .realmName(realmName).page(0).pageSize(1).build(); - UserSearchResultDTO totalResult = userServiceClient.searchUsers(totalCriteria); - kpiTotalUsers = totalResult.getTotalCount() != null ? totalResult.getTotalCount() : 0; - - UserSearchCriteriaDTO activeCriteria = UserSearchCriteriaDTO.builder() - .realmName(realmName).enabled(true).page(0).pageSize(1).build(); - UserSearchResultDTO activeResult = userServiceClient.searchUsers(activeCriteria); - activeUsersCount = activeResult.getTotalCount() != null ? activeResult.getTotalCount() : 0; - - disabledUsersCount = kpiTotalUsers - activeUsersCount; - } catch (Exception e) { - LOGGER.severe("Erreur chargement statistiques KPI: " + e.getMessage()); - } - } - - /** - * Exporter les utilisateurs vers un fichier CSV téléchargeable - */ - public void exportToCSV() { - try { - Response response = userServiceClient.exportUsersToCSV(realmName); - String csvContent = response.readEntity(String.class); - - FacesContext facesContext = FacesContext.getCurrentInstance(); - ExternalContext externalContext = facesContext.getExternalContext(); - externalContext.responseReset(); - externalContext.setResponseContentType("text/csv"); - externalContext.setResponseHeader("Content-Disposition", - "attachment; filename=\"utilisateurs-" + realmName + ".csv\""); - externalContext.setResponseCharacterEncoding("UTF-8"); - - OutputStream outputStream = externalContext.getResponseOutputStream(); - outputStream.write(csvContent.getBytes(StandardCharsets.UTF_8)); - outputStream.flush(); - - facesContext.responseComplete(); - } catch (IOException e) { - LOGGER.severe("Erreur I/O lors de l'export CSV: " + e.getMessage()); - addErrorMessage("Erreur lors de l'export CSV: " + e.getMessage()); - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'export CSV: " + e.getMessage()); - addErrorMessage("Erreur lors de l'export CSV: " + e.getMessage()); - } - } - - /** - * Importer des utilisateurs depuis un fichier CSV - */ - public void importUsers() { - if (importedFile == null) { - addErrorMessage("Veuillez sélectionner un fichier CSV à importer."); - return; - } - try { - String csvContent = new String(importedFile.getContent(), StandardCharsets.UTF_8); - this.lastImportResult = userServiceClient.importUsersFromCSV(realmName, csvContent); - - if (lastImportResult != null) { - String msg = lastImportResult.getSuccessCount() + " utilisateur(s) importé(s), " - + lastImportResult.getErrorCount() + " erreur(s)."; - if (lastImportResult.getErrorCount() == 0) { - addSuccessMessage(msg); - } else { - addMessage(FacesMessage.SEVERITY_WARN, "Import partiel", msg); - } - loadStats(); - } - importedFile = null; - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'import CSV: " + e.getMessage()); - addErrorMessage("Erreur lors de l'import: " + e.getMessage()); - } - } - - private void addMessage(FacesMessage.Severity severity, String summary, String detail) { - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail)); - } - - /** - * Charger les realms disponibles depuis Keycloak - */ - private void loadRealms() { - try { - availableRealms = realmServiceClient.getAllRealms(); - LOGGER.info("Realms chargés: " + availableRealms); - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); - // Fallback en cas d'erreur - availableRealms = List.of("master", "lions-user-manager", "btpxpress", "unionflow"); - } - } - - /** - * Navigation vers le profil utilisateur - */ - public String goToUserProfile() { - return OUTCOME_USER_PROFILE; - } - - /** - * Navigation vers l'édition utilisateur - */ - public String goToUserEdit() { - return OUTCOME_USER_EDIT; - } - - /** - * Navigation vers la création utilisateur - */ - public String goToUserCreate() { - return OUTCOME_USER_CREATE; - } - - // Méthodes utilitaires pour les messages - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.RealmServiceClient; +import dev.lions.user.manager.client.service.UserServiceClient; +import dev.lions.user.manager.dto.importexport.ImportResultDTO; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO; +import dev.lions.user.manager.dto.user.UserSearchResultDTO; +import dev.lions.user.manager.enums.user.StatutUser; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.ExternalContext; +import jakarta.faces.context.FacesContext; +import jakarta.faces.event.ActionEvent; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.ws.rs.core.Response; +import lombok.Data; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.primefaces.PrimeFaces; +import org.primefaces.model.FilterMeta; +import org.primefaces.model.LazyDataModel; +import org.primefaces.model.SortMeta; +import org.primefaces.model.file.UploadedFile; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +/** + * Bean JSF pour la liste et la recherche d'utilisateurs + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("userListBean") +@ViewScoped +@Data +public class UserListBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(UserListBean.class.getName()); + + // Constantes de navigation outcomes (WOU/DRY - réutilisables) + private static final String OUTCOME_USER_PROFILE = "userProfilePage"; + private static final String OUTCOME_USER_EDIT = "userEditPage"; + private static final String OUTCOME_USER_CREATE = "userCreatePage"; + + @Inject + @RestClient + private UserServiceClient userServiceClient; + + @Inject + @RestClient + private RealmServiceClient realmServiceClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "lions-user-manager") + String defaultRealm; + + // Propriétés pour la liste + private LazyDataModel users; + private UserDTO selectedUser; + private List selectedUsers = new ArrayList<>(); + + // Propriétés pour la recherche + private UserSearchCriteriaDTO searchCriteria = UserSearchCriteriaDTO.builder().build(); + private String searchText; + private String realmName; + private StatutUser selectedStatut; + + // Propriétés pour la pagination + private int currentPage = 0; + private int pageSize = 20; + private long totalRecords = 0; + private int totalPages = 0; + + // KPIs chargés depuis le serveur (indépendants de la pagination/filtres) + private long kpiTotalUsers = 0; + private long activeUsersCount = 0; + private long disabledUsersCount = 0; + + // Options pour les selects + private List statutOptions = List.of(StatutUser.values()); + private List availableRealms = new ArrayList<>(); + + // Champs pour réinitialisation mot de passe + private String newPassword; + private String newPasswordConfirm; + + // Champ pour l'import CSV + private UploadedFile importedFile; + private ImportResultDTO lastImportResult; + + @PostConstruct + public void init() { + this.realmName = defaultRealm; + LOGGER.info("Initialisation de UserListBean - realm: " + realmName); + loadRealms(); + loadStats(); + + users = new LazyDataModel() { + @Override + public String getRowKey(UserDTO user) { + return user.getId(); + } + + @Override + public UserDTO getRowData(String rowKey) { + List list = (List) getWrappedData(); + if (list != null) { + for (UserDTO user : list) { + if (user.getId().equals(rowKey)) { + return user; + } + } + } + return null; + } + + @Override + public int count(Map filterBy) { + return (int) totalRecords; + } + + @Override + public List load(int first, int pageSize, Map sortBy, + Map filterBy) { + try { + int page = first / pageSize; + + UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder() + .realmName(realmName) + .searchTerm(searchText) + .statut(selectedStatut) + .page(page) + .pageSize(pageSize) + .includeRoles(true) + .build(); + + UserSearchResultDTO result = userServiceClient.searchUsers(criteria); + List data = result.getUsers() != null ? result.getUsers() : new ArrayList<>(); + + long total = result.getTotalCount() != null ? result.getTotalCount() : 0; + this.setRowCount((int) total); + totalRecords = total; + + return data; + } catch (Exception e) { + LOGGER.severe("Erreur loading: " + e.getMessage()); + return new ArrayList<>(); + } + } + }; + } + + /** + * Charger la liste des utilisateurs + * (Deprecated: Utiliser LazyDataModel) + */ + public void loadUsers() { + // La méthode load du LazyDataModel est appelée automatiquement par le composant + } + + /** + * Rechercher des utilisateurs + */ + public void search() { + currentPage = 0; + if (PrimeFaces.current().isAjaxRequest()) { + PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); + } + } + + /** + * Réinitialiser la recherche + */ + public void resetSearch() { + searchText = null; + selectedStatut = null; + currentPage = 0; + if (PrimeFaces.current().isAjaxRequest()) { + PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); + } + } + + /** + * Réinitialiser le mot de passe + */ + public void resetPassword(String userId) { + if (newPassword != null && !newPassword.isEmpty() && newPassword.equals(newPasswordConfirm)) { + try { + // Utilisation du DTO pour la demande de réinitialisation + dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( + newPassword, false); + userServiceClient.resetPassword(userId, realmName, request); + addSuccessMessage("Mot de passe réinitialisé avec succès"); + // Clear fields + newPassword = null; + newPasswordConfirm = null; + } catch (Exception e) { + LOGGER.severe("Erreur lors de la réinitialisation du mot de passe: " + e.getMessage()); + addErrorMessage("Erreur lors de la réinitialisation: " + e.getMessage()); + } + } else { + addErrorMessage("Les mots de passe sont invalides ou ne correspondent pas"); + } + } + + /** + * Action pour activer un utilisateur (utilisé par le composant composite) + */ + public void activateUserAction(ActionEvent event) { + String userId = (String) event.getComponent().getAttributes().get("userId"); + if (userId != null) { + activateUser(userId); + } + } + + /** + * Action pour désactiver un utilisateur (utilisé par le composant composite) + */ + public void deactivateUserAction(ActionEvent event) { + String userId = (String) event.getComponent().getAttributes().get("userId"); + if (userId != null) { + deactivateUser(userId); + } + } + + /** + * Action pour supprimer un utilisateur (utilisé par le composant composite) + */ + public void deleteUserAction(ActionEvent event) { + String userId = (String) event.getComponent().getAttributes().get("userId"); + if (userId != null) { + deleteUser(userId); + } + } + + /** + * Activer un utilisateur + */ + public void activateUser(String userId) { + try { + userServiceClient.activateUser(userId, realmName); + activeUsersCount++; + disabledUsersCount = Math.max(0, disabledUsersCount - 1); + addSuccessMessage("Utilisateur activé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'activation: " + e.getMessage()); + addErrorMessage("Erreur lors de l'activation: " + e.getMessage()); + } + } + + /** + * Désactiver un utilisateur + */ + public void deactivateUser(String userId) { + try { + userServiceClient.deactivateUser(userId, realmName, "Désactivé par l'administrateur"); + activeUsersCount = Math.max(0, activeUsersCount - 1); + disabledUsersCount++; + addSuccessMessage("Utilisateur désactivé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage()); + addErrorMessage("Erreur lors de la désactivation: " + e.getMessage()); + } + } + + /** + * Supprimer un utilisateur + */ + public void deleteUser(String userId) { + try { + userServiceClient.deleteUser(userId, realmName, false); + kpiTotalUsers = Math.max(0, kpiTotalUsers - 1); + addSuccessMessage("Utilisateur supprimé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); + addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); + } + } + + /** + * Déconnecter toutes les sessions d'un utilisateur + */ + public void logoutAllSessions(String userId) { + try { + userServiceClient.logoutAllSessions(userId, realmName); + addSuccessMessage("Toutes les sessions ont été déconnectées"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage()); + addErrorMessage("Erreur lors de la déconnexion: " + e.getMessage()); + } + } + + /** + * Pourcentage d'utilisateurs actifs + */ + public int getActiveUsersPercentage() { + if (kpiTotalUsers == 0) return 0; + return (int) Math.round((double) activeUsersCount / kpiTotalUsers * 100); + } + + /** + * Pourcentage d'utilisateurs désactivés + */ + public int getDisabledUsersPercentage() { + if (kpiTotalUsers == 0) return 0; + return (int) Math.round((double) disabledUsersCount / kpiTotalUsers * 100); + } + + /** + * Rafraîchir les données et les KPIs + */ + public void refreshData() { + loadStats(); + addSuccessMessage("Données rafraîchies"); + } + + /** + * Changement de realm (filtre + rechargement des KPIs) + */ + public void onRealmChange() { + currentPage = 0; + loadStats(); + if (PrimeFaces.current().isAjaxRequest()) { + PrimeFaces.current().executeScript("PF('userTableWidget').getPaginator().setPage(0);"); + } + } + + /** + * Charger les statistiques KPI depuis le serveur + */ + private void loadStats() { + try { + UserSearchCriteriaDTO totalCriteria = UserSearchCriteriaDTO.builder() + .realmName(realmName).page(0).pageSize(1).build(); + UserSearchResultDTO totalResult = userServiceClient.searchUsers(totalCriteria); + kpiTotalUsers = totalResult.getTotalCount() != null ? totalResult.getTotalCount() : 0; + + UserSearchCriteriaDTO activeCriteria = UserSearchCriteriaDTO.builder() + .realmName(realmName).enabled(true).page(0).pageSize(1).build(); + UserSearchResultDTO activeResult = userServiceClient.searchUsers(activeCriteria); + activeUsersCount = activeResult.getTotalCount() != null ? activeResult.getTotalCount() : 0; + + disabledUsersCount = kpiTotalUsers - activeUsersCount; + } catch (Exception e) { + LOGGER.severe("Erreur chargement statistiques KPI: " + e.getMessage()); + } + } + + /** + * Exporter les utilisateurs vers un fichier CSV téléchargeable + */ + public void exportToCSV() { + try { + Response response = userServiceClient.exportUsersToCSV(realmName); + String csvContent = response.readEntity(String.class); + + FacesContext facesContext = FacesContext.getCurrentInstance(); + ExternalContext externalContext = facesContext.getExternalContext(); + externalContext.responseReset(); + externalContext.setResponseContentType("text/csv"); + externalContext.setResponseHeader("Content-Disposition", + "attachment; filename=\"utilisateurs-" + realmName + ".csv\""); + externalContext.setResponseCharacterEncoding("UTF-8"); + + OutputStream outputStream = externalContext.getResponseOutputStream(); + outputStream.write(csvContent.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + + facesContext.responseComplete(); + } catch (IOException e) { + LOGGER.severe("Erreur I/O lors de l'export CSV: " + e.getMessage()); + addErrorMessage("Erreur lors de l'export CSV: " + e.getMessage()); + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'export CSV: " + e.getMessage()); + addErrorMessage("Erreur lors de l'export CSV: " + e.getMessage()); + } + } + + /** + * Importer des utilisateurs depuis un fichier CSV + */ + public void importUsers() { + if (importedFile == null) { + addErrorMessage("Veuillez sélectionner un fichier CSV à importer."); + return; + } + try { + String csvContent = new String(importedFile.getContent(), StandardCharsets.UTF_8); + this.lastImportResult = userServiceClient.importUsersFromCSV(realmName, csvContent); + + if (lastImportResult != null) { + String msg = lastImportResult.getSuccessCount() + " utilisateur(s) importé(s), " + + lastImportResult.getErrorCount() + " erreur(s)."; + if (lastImportResult.getErrorCount() == 0) { + addSuccessMessage(msg); + } else { + addMessage(FacesMessage.SEVERITY_WARN, "Import partiel", msg); + } + loadStats(); + } + importedFile = null; + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'import CSV: " + e.getMessage()); + addErrorMessage("Erreur lors de l'import: " + e.getMessage()); + } + } + + private void addMessage(FacesMessage.Severity severity, String summary, String detail) { + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(severity, summary, detail)); + } + + /** + * Charger les realms disponibles depuis Keycloak + */ + private void loadRealms() { + try { + availableRealms = realmServiceClient.getAllRealms(); + LOGGER.info("Realms chargés: " + availableRealms); + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement des realms: " + e.getMessage()); + // Fallback en cas d'erreur + availableRealms = List.of("master", "lions-user-manager", "btpxpress", "unionflow"); + } + } + + /** + * Navigation vers le profil utilisateur + */ + public String goToUserProfile() { + return OUTCOME_USER_PROFILE; + } + + /** + * Navigation vers l'édition utilisateur + */ + public String goToUserEdit() { + return OUTCOME_USER_EDIT; + } + + /** + * Navigation vers la création utilisateur + */ + public String goToUserCreate() { + return OUTCOME_USER_CREATE; + } + + // Méthodes utilitaires pour les messages + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserManagerMenuModel.java b/src/main/java/dev/lions/user/manager/client/view/UserManagerMenuModel.java new file mode 100644 index 0000000..f8e9bd6 --- /dev/null +++ b/src/main/java/dev/lions/user/manager/client/view/UserManagerMenuModel.java @@ -0,0 +1,98 @@ +package dev.lions.user.manager.client.view; + +import dev.lions.faces.layout.view.AbstractMenuModel; +import jakarta.enterprise.context.SessionScoped; +import jakarta.inject.Named; + +import java.util.List; + +/** + * UserManagerMenuModel — Navigation de lions-user-manager. + * + *

Étend {@link AbstractMenuModel} pour fournir les entrées de menu + * spécifiques à l'application de gestion des utilisateurs.

+ * + *

Ce bean est injecté automatiquement dans {@code menu.xhtml} + * (lions-faces-layout) via la référence EL {@code #{menuModel.model}}.

+ */ +@Named("menuModel") +@SessionScoped +public class UserManagerMenuModel extends AbstractMenuModel { + + private static final long serialVersionUID = 1L; + + @Override + protected List buildMenuItems() { + return List.of( + + // ── Dashboard ──────────────────────────────────────────── + MenuEntry.item("m_dashboard", + "Tableau de Bord", + "pi pi-home", + "/pages/user-manager/dashboard.xhtml"), + + // ── Gestion des Utilisateurs ───────────────────────────── + MenuEntry.submenu("m_users", + "Utilisateurs", + "pi pi-users", + List.of( + MenuEntry.item("m_user_list", + "Liste des utilisateurs", + "pi pi-list", + "/pages/user-manager/users/list.xhtml"), + MenuEntry.item("m_user_create", + "Créer un utilisateur", + "pi pi-user-plus", + "/pages/user-manager/users/create.xhtml"), + MenuEntry.item("m_user_profile", + "Mon profil", + "pi pi-id-card", + "/pages/user-manager/users/profile.xhtml") + )), + + // ── Gestion des Rôles ──────────────────────────────────── + MenuEntry.submenu("m_roles", + "Rôles", + "pi pi-shield", + List.of( + MenuEntry.item("m_role_list", + "Liste des rôles", + "pi pi-list", + "/pages/user-manager/roles/list.xhtml"), + MenuEntry.item("m_role_assign", + "Attribuer des rôles", + "pi pi-sitemap", + "/pages/user-manager/roles/assign.xhtml") + )), + + // ── Synchronisation Keycloak ────────────────────────────── + MenuEntry.submenu("m_sync", + "Synchronisation", + "pi pi-sync", + List.of( + MenuEntry.item("m_sync_dashboard", + "Dashboard Sync", + "pi pi-chart-bar", + "/pages/user-manager/sync/dashboard.xhtml") + )), + + // ── Audit ──────────────────────────────────────────────── + MenuEntry.submenu("m_audit", + "Audit", + "pi pi-book", + List.of( + MenuEntry.item("m_audit_logs", + "Journal d'audit", + "pi pi-file-o", + "/pages/user-manager/audit/logs.xhtml") + )), + + // ── Paramètres ─────────────────────────────────────────── + MenuEntry.item("m_settings", + "Paramètres", + "pi pi-cog", + "/pages/user-manager/settings.xhtml") + + ); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserProfilBean.java b/src/main/java/dev/lions/user/manager/client/view/UserProfilBean.java index 9889663..b4f9042 100644 --- a/src/main/java/dev/lions/user/manager/client/view/UserProfilBean.java +++ b/src/main/java/dev/lions/user/manager/client/view/UserProfilBean.java @@ -1,268 +1,268 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.service.UserServiceClient; -import dev.lions.user.manager.dto.user.UserDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.rest.client.inject.RestClient; - -import java.io.Serializable; -import java.util.logging.Logger; - -/** - * Bean JSF pour le profil et l'édition d'un utilisateur - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("userProfilBean") -@ViewScoped -@Data -public class UserProfilBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(UserProfilBean.class.getName()); - - @Inject - @RestClient - private UserServiceClient userServiceClient; - - private UserDTO user; - private String userId; - // Le realm "lions-user-manager" est le realm par défaut - private String realmName = "lions-user-manager"; - private boolean editMode = false; - - // Pour la réinitialisation de mot de passe - private String newPassword; - private String newPasswordConfirm; - - @PostConstruct - public void init() { - // Récupérer l'ID depuis les paramètres de requête - userId = FacesContext.getCurrentInstance().getExternalContext() - .getRequestParameterMap().get("userId"); - - // Récupérer le realm depuis les paramètres de requête (si présent) - String realmParam = FacesContext.getCurrentInstance().getExternalContext() - .getRequestParameterMap().get("realm"); - if (realmParam != null && !realmParam.isEmpty()) { - this.realmName = realmParam; - } - - if (userId != null && !userId.isEmpty()) { - loadUser(); - } else { - LOGGER.warning("Aucun userId fourni dans les paramètres"); - } - } - - /** - * Charger l'utilisateur - */ - public void loadUser() { - try { - user = userServiceClient.getUserById(userId, realmName); - if (user != null) { - LOGGER.info("Utilisateur chargé: " + user.getUsername()); - } - } catch (dev.lions.user.manager.client.service.RestClientExceptionMapper.NotFoundException e) { - LOGGER.warning("Utilisateur non trouvé: " + userId); - addErrorMessage("Utilisateur non trouvé dans le realm " + realmName); - user = null; - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement de l'utilisateur: " + e.getMessage()); - addErrorMessage("Erreur lors du chargement de l'utilisateur: " + e.getMessage()); - } - } - - /** - * Activer le mode édition - */ - public void enableEditMode() { - editMode = true; - } - - /** - * Désactiver le mode édition - */ - public void cancelEdit() { - editMode = false; - loadUser(); // Recharger les données originales - } - - /** - * Mettre à jour l'utilisateur - */ - public void updateUser() { - try { - user = userServiceClient.updateUser(userId, user, realmName); - editMode = false; - addSuccessMessage("Utilisateur mis à jour avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la mise à jour: " + e.getMessage()); - addErrorMessage("Erreur lors de la mise à jour: " + e.getMessage()); - } - } - - /** - * Réinitialiser le mot de passe - */ - public void resetPassword() { - if (newPassword == null || newPassword.isEmpty()) { - addErrorMessage("Le mot de passe ne peut pas être vide"); - return; - } - - if (!newPassword.equals(newPasswordConfirm)) { - addErrorMessage("Les mots de passe ne correspondent pas"); - return; - } - - try { - dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( - newPassword, false); - userServiceClient.resetPassword(userId, realmName, request); - newPassword = null; - newPasswordConfirm = null; - addSuccessMessage("Mot de passe réinitialisé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la réinitialisation: " + e.getMessage()); - addErrorMessage("Erreur lors de la réinitialisation: " + e.getMessage()); - } - } - - /** - * Activer l'utilisateur - */ - public void activateUser() { - try { - userServiceClient.activateUser(userId, realmName); - loadUser(); // Recharger pour mettre à jour le statut - addSuccessMessage("Utilisateur activé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'activation: " + e.getMessage()); - addErrorMessage("Erreur lors de l'activation: " + e.getMessage()); - } - } - - /** - * Désactiver l'utilisateur - */ - public void deactivateUser() { - try { - userServiceClient.deactivateUser(userId, realmName, "Désactivé depuis le profil utilisateur"); - loadUser(); // Recharger pour mettre à jour le statut - addSuccessMessage("Utilisateur désactivé avec succès"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage()); - addErrorMessage("Erreur lors de la désactivation: " + e.getMessage()); - } - } - - /** - * Envoyer un email de vérification - */ - public void sendVerificationEmail() { - try { - userServiceClient.sendVerificationEmail(userId, realmName); - addSuccessMessage("Email de vérification envoyé"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de l'envoi: " + e.getMessage()); - addErrorMessage("Erreur lors de l'envoi: " + e.getMessage()); - } - } - - /** - * Supprimer l'utilisateur - */ - public void deleteUser() { - try { - userServiceClient.deleteUser(userId, realmName, false); - addSuccessMessage("Utilisateur supprimé avec succès"); - FacesContext.getCurrentInstance().getExternalContext().redirect("list.xhtml"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); - addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); - } - } - - /** - * Obtenir les initiales de l'utilisateur pour l'avatar - */ - public String getUserInitials() { - if (user == null) return "?"; - String p = (user.getPrenom() != null && !user.getPrenom().isEmpty()) - ? user.getPrenom().substring(0, 1) : ""; - String n = (user.getNom() != null && !user.getNom().isEmpty()) - ? user.getNom().substring(0, 1) : ""; - String initials = (p + n).toUpperCase(); - return initials.isEmpty() ? "?" : initials; - } - - /** - * Obtenir le nom du rôle principal (libellé lisible) - */ - public String getPrimaryRoleName() { - if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) { - return "Utilisateur"; - } - java.util.List roles = user.getRealmRoles(); - if (roles.contains("admin")) return "Administrateur"; - if (roles.contains("user_manager")) return "Gestionnaire"; - if (roles.contains("user_viewer")) return "Consultant"; - if (roles.contains("auditor")) return "Auditeur"; - return roles.get(0); - } - - // Méthodes compatibles avec user-actions.xhtml (qui passe l'ID en paramètre) - - public void activateUser(String userId) { - activateUser(); - } - - public void deactivateUser(String userId) { - deactivateUser(); - } - - public void resetPassword(String userId) { - resetPassword(); - } - - public void deleteUser(String userId) { - deleteUser(); - } - - /** - * Déconnecter toutes les sessions - */ - public void logoutAllSessions() { - try { - userServiceClient.logoutAllSessions(userId, realmName); - addSuccessMessage("Toutes les sessions ont été déconnectées"); - } catch (Exception e) { - LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage()); - addErrorMessage("Erreur lors de la déconnexion: " + e.getMessage()); - } - } - - public void logoutAllSessions(String userId) { - logoutAllSessions(); - } - - // Méthodes utilitaires - private void addSuccessMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); - } - - private void addErrorMessage(String message) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.service.UserServiceClient; +import dev.lions.user.manager.dto.user.UserDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Data; +import org.eclipse.microprofile.rest.client.inject.RestClient; + +import java.io.Serializable; +import java.util.logging.Logger; + +/** + * Bean JSF pour le profil et l'édition d'un utilisateur + * + * @author Lions User Manager + * @version 1.0.0 + */ +@Named("userProfilBean") +@ViewScoped +@Data +public class UserProfilBean implements Serializable { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = Logger.getLogger(UserProfilBean.class.getName()); + + @Inject + @RestClient + private UserServiceClient userServiceClient; + + private UserDTO user; + private String userId; + // Le realm "lions-user-manager" est le realm par défaut + private String realmName = "lions-user-manager"; + private boolean editMode = false; + + // Pour la réinitialisation de mot de passe + private String newPassword; + private String newPasswordConfirm; + + @PostConstruct + public void init() { + // Récupérer l'ID depuis les paramètres de requête + userId = FacesContext.getCurrentInstance().getExternalContext() + .getRequestParameterMap().get("userId"); + + // Récupérer le realm depuis les paramètres de requête (si présent) + String realmParam = FacesContext.getCurrentInstance().getExternalContext() + .getRequestParameterMap().get("realm"); + if (realmParam != null && !realmParam.isEmpty()) { + this.realmName = realmParam; + } + + if (userId != null && !userId.isEmpty()) { + loadUser(); + } else { + LOGGER.warning("Aucun userId fourni dans les paramètres"); + } + } + + /** + * Charger l'utilisateur + */ + public void loadUser() { + try { + user = userServiceClient.getUserById(userId, realmName); + if (user != null) { + LOGGER.info("Utilisateur chargé: " + user.getUsername()); + } + } catch (dev.lions.user.manager.client.service.RestClientExceptionMapper.NotFoundException e) { + LOGGER.warning("Utilisateur non trouvé: " + userId); + addErrorMessage("Utilisateur non trouvé dans le realm " + realmName); + user = null; + } catch (Exception e) { + LOGGER.severe("Erreur lors du chargement de l'utilisateur: " + e.getMessage()); + addErrorMessage("Erreur lors du chargement de l'utilisateur: " + e.getMessage()); + } + } + + /** + * Activer le mode édition + */ + public void enableEditMode() { + editMode = true; + } + + /** + * Désactiver le mode édition + */ + public void cancelEdit() { + editMode = false; + loadUser(); // Recharger les données originales + } + + /** + * Mettre à jour l'utilisateur + */ + public void updateUser() { + try { + user = userServiceClient.updateUser(userId, user, realmName); + editMode = false; + addSuccessMessage("Utilisateur mis à jour avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la mise à jour: " + e.getMessage()); + addErrorMessage("Erreur lors de la mise à jour: " + e.getMessage()); + } + } + + /** + * Réinitialiser le mot de passe + */ + public void resetPassword() { + if (newPassword == null || newPassword.isEmpty()) { + addErrorMessage("Le mot de passe ne peut pas être vide"); + return; + } + + if (!newPassword.equals(newPasswordConfirm)) { + addErrorMessage("Les mots de passe ne correspondent pas"); + return; + } + + try { + dev.lions.user.manager.dto.user.PasswordResetRequestDTO request = new dev.lions.user.manager.dto.user.PasswordResetRequestDTO( + newPassword, false); + userServiceClient.resetPassword(userId, realmName, request); + newPassword = null; + newPasswordConfirm = null; + addSuccessMessage("Mot de passe réinitialisé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la réinitialisation: " + e.getMessage()); + addErrorMessage("Erreur lors de la réinitialisation: " + e.getMessage()); + } + } + + /** + * Activer l'utilisateur + */ + public void activateUser() { + try { + userServiceClient.activateUser(userId, realmName); + loadUser(); // Recharger pour mettre à jour le statut + addSuccessMessage("Utilisateur activé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'activation: " + e.getMessage()); + addErrorMessage("Erreur lors de l'activation: " + e.getMessage()); + } + } + + /** + * Désactiver l'utilisateur + */ + public void deactivateUser() { + try { + userServiceClient.deactivateUser(userId, realmName, "Désactivé depuis le profil utilisateur"); + loadUser(); // Recharger pour mettre à jour le statut + addSuccessMessage("Utilisateur désactivé avec succès"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage()); + addErrorMessage("Erreur lors de la désactivation: " + e.getMessage()); + } + } + + /** + * Envoyer un email de vérification + */ + public void sendVerificationEmail() { + try { + userServiceClient.sendVerificationEmail(userId, realmName); + addSuccessMessage("Email de vérification envoyé"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de l'envoi: " + e.getMessage()); + addErrorMessage("Erreur lors de l'envoi: " + e.getMessage()); + } + } + + /** + * Supprimer l'utilisateur + */ + public void deleteUser() { + try { + userServiceClient.deleteUser(userId, realmName, false); + addSuccessMessage("Utilisateur supprimé avec succès"); + FacesContext.getCurrentInstance().getExternalContext().redirect("list.xhtml"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la suppression: " + e.getMessage()); + addErrorMessage("Erreur lors de la suppression: " + e.getMessage()); + } + } + + /** + * Obtenir les initiales de l'utilisateur pour l'avatar + */ + public String getUserInitials() { + if (user == null) return "?"; + String p = (user.getPrenom() != null && !user.getPrenom().isEmpty()) + ? user.getPrenom().substring(0, 1) : ""; + String n = (user.getNom() != null && !user.getNom().isEmpty()) + ? user.getNom().substring(0, 1) : ""; + String initials = (p + n).toUpperCase(); + return initials.isEmpty() ? "?" : initials; + } + + /** + * Obtenir le nom du rôle principal (libellé lisible) + */ + public String getPrimaryRoleName() { + if (user == null || user.getRealmRoles() == null || user.getRealmRoles().isEmpty()) { + return "Utilisateur"; + } + java.util.List roles = user.getRealmRoles(); + if (roles.contains("admin")) return "Administrateur"; + if (roles.contains("user_manager")) return "Gestionnaire"; + if (roles.contains("user_viewer")) return "Consultant"; + if (roles.contains("auditor")) return "Auditeur"; + return roles.get(0); + } + + // Méthodes compatibles avec user-actions.xhtml (qui passe l'ID en paramètre) + + public void activateUser(String userId) { + activateUser(); + } + + public void deactivateUser(String userId) { + deactivateUser(); + } + + public void resetPassword(String userId) { + resetPassword(); + } + + public void deleteUser(String userId) { + deleteUser(); + } + + /** + * Déconnecter toutes les sessions + */ + public void logoutAllSessions() { + try { + userServiceClient.logoutAllSessions(userId, realmName); + addSuccessMessage("Toutes les sessions ont été déconnectées"); + } catch (Exception e) { + LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage()); + addErrorMessage("Erreur lors de la déconnexion: " + e.getMessage()); + } + } + + public void logoutAllSessions(String userId) { + logoutAllSessions(); + } + + // Méthodes utilitaires + private void addSuccessMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message)); + } + + private void addErrorMessage(String message) { + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message)); + } +} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserSessionBean.java b/src/main/java/dev/lions/user/manager/client/view/UserSessionBean.java deleted file mode 100644 index 4c8732d..0000000 --- a/src/main/java/dev/lions/user/manager/client/view/UserSessionBean.java +++ /dev/null @@ -1,357 +0,0 @@ -package dev.lions.user.manager.client.view; - -import io.quarkus.oidc.IdToken; -import io.quarkus.oidc.OidcSession; -import io.quarkus.security.identity.SecurityIdentity; -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.SessionScoped; -import jakarta.faces.context.ExternalContext; -import jakarta.faces.context.FacesContext; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Data; -import org.eclipse.microprofile.jwt.JsonWebToken; - -import java.io.Serializable; -import java.util.logging.Logger; - -/** - * Bean de session pour gérer les informations de l'utilisateur connecté - * - * @author Lions User Manager - * @version 1.0.0 - */ -@Named("userSessionBean") -@SessionScoped -@Data -public class UserSessionBean implements Serializable { - - private static final long serialVersionUID = 1L; - private static final Logger LOGGER = Logger.getLogger(UserSessionBean.class.getName()); - - @Inject - SecurityIdentity securityIdentity; - - @Inject - @IdToken - JsonWebToken idToken; - - @Inject - OidcSession oidcSession; - - // Informations utilisateur - private String username; - private String email; - private String firstName; - private String lastName; - private String fullName; - private String initials; - - @PostConstruct - public void init() { - loadUserInfo(); - } - - /** - * Charger les informations utilisateur depuis le token OIDC - */ - public void loadUserInfo() { - try { - if (idToken != null && securityIdentity != null && !securityIdentity.isAnonymous()) { - // Username - username = idToken.getClaim("preferred_username"); - if (username == null || username.trim().isEmpty()) { - username = securityIdentity.getPrincipal().getName(); - } - - // Email - email = idToken.getClaim("email"); - if (email == null || email.trim().isEmpty()) { - email = username + "@lions.dev"; - } - - // Prénom et nom - firstName = idToken.getClaim("given_name"); - lastName = idToken.getClaim("family_name"); - - // Nom complet - fullName = idToken.getClaim("name"); - if (fullName == null || fullName.trim().isEmpty()) { - if (firstName != null && lastName != null) { - fullName = firstName + " " + lastName; - } else if (firstName != null) { - fullName = firstName; - } else if (lastName != null) { - fullName = lastName; - } else { - fullName = username; - } - } - - // Initiales pour l'avatar - initials = generateInitials(fullName); - - LOGGER.info("Informations utilisateur chargées: " + fullName + " (" + email + ")"); - } else { - // Valeurs par défaut si non authentifié - username = "Utilisateur"; - email = "utilisateur@lions.dev"; - fullName = "Utilisateur"; - initials = "U"; - } - } catch (Exception e) { - LOGGER.severe("Erreur lors du chargement des informations utilisateur: " + e.getMessage()); - username = "Utilisateur"; - email = "utilisateur@lions.dev"; - fullName = "Utilisateur"; - initials = "U"; - } - } - - /** - * Générer les initiales depuis le nom complet - */ - private String generateInitials(String name) { - if (name == null || name.trim().isEmpty()) { - return "U"; - } - - String[] parts = name.trim().split("\\s+"); - if (parts.length >= 2) { - return String.valueOf(parts[0].charAt(0)).toUpperCase() + - String.valueOf(parts[1].charAt(0)).toUpperCase(); - } else if (parts.length == 1) { - String part = parts[0]; - if (part.length() >= 2) { - return part.substring(0, 2).toUpperCase(); - } else { - return part.substring(0, 1).toUpperCase(); - } - } - return "U"; - } - - // Rôles - private java.util.Set roles; - private String primaryRole; - - /** - * Obtenir le rôle principal de l'utilisateur - */ - public String getPrimaryRole() { - if (primaryRole == null) { - primaryRole = getMainRole(); - } - return primaryRole; - } - - /** - * Obtenir tous les rôles de l'utilisateur - */ - public java.util.Set getRoles() { - if (roles == null) { - roles = new java.util.HashSet<>(); - try { - if (securityIdentity != null && securityIdentity.getRoles() != null) { - roles.addAll(securityIdentity.getRoles()); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération des rôles: " + e.getMessage()); - } - if (roles.isEmpty()) { - roles.add("Utilisateur"); - } - } - return roles; - } - - /** - * Obtenir le rôle principal de l'utilisateur (méthode interne) - */ - private String getMainRole() { - try { - if (securityIdentity != null && securityIdentity.getRoles() != null - && !securityIdentity.getRoles().isEmpty()) { - // Prioriser certains rôles - java.util.Set roleSet = securityIdentity.getRoles(); - if (roleSet.contains("admin")) { - return "Administrateur"; - } else if (roleSet.contains("user_manager")) { - return "Gestionnaire"; - } else if (roleSet.contains("user_viewer")) { - return "Consultant"; - } else { - return roleSet.iterator().next(); - } - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération du rôle: " + e.getMessage()); - } - return "Utilisateur"; - } - - /** - * Vérifier si l'utilisateur est authentifié - */ - public boolean isAuthenticated() { - return securityIdentity != null && !securityIdentity.isAnonymous(); - } - - /** - * Vérifier si l'utilisateur a un rôle spécifique - */ - public boolean hasRole(String role) { - try { - if (securityIdentity != null && securityIdentity.getRoles() != null) { - return securityIdentity.getRoles().contains(role); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la vérification du rôle: " + e.getMessage()); - } - return false; - } - - /** - * Obtenir l'issuer du token OIDC - */ - public String getIssuer() { - try { - if (idToken != null) { - return idToken.getIssuer(); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération de l'issuer: " + e.getMessage()); - } - return "Non disponible"; - } - - /** - * Obtenir le subject du token OIDC - */ - public String getSubject() { - try { - if (idToken != null) { - return idToken.getSubject(); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération du subject: " + e.getMessage()); - } - return "Non disponible"; - } - - /** - * Obtenir le session ID - */ - public String getSessionId() { - try { - if (idToken != null) { - Object sid = idToken.getClaim("sid"); - if (sid != null) { - return sid.toString(); - } - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération du session ID: " + e.getMessage()); - } - return "Non disponible"; - } - - /** - * Obtenir le temps d'expiration du token - */ - public java.util.Date getExpirationTime() { - try { - if (idToken != null && idToken.getExpirationTime() > 0) { - return new java.util.Date(idToken.getExpirationTime() * 1000L); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération de l'expiration: " + e.getMessage()); - } - return null; - } - - /** - * Obtenir le temps d'émission du token - */ - public java.util.Date getIssuedAt() { - try { - if (idToken != null && idToken.getIssuedAtTime() > 0) { - return new java.util.Date(idToken.getIssuedAtTime() * 1000L); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération de l'émission: " + e.getMessage()); - } - return null; - } - - /** - * Obtenir l'audience du token - */ - public String getAudience() { - try { - if (idToken != null && idToken.getAudience() != null && !idToken.getAudience().isEmpty()) { - return String.join(", ", idToken.getAudience()); - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération de l'audience: " + e.getMessage()); - } - return "Non disponible"; - } - - /** - * Obtenir l'authorized party (azp) - */ - public String getAuthorizedParty() { - try { - if (idToken != null) { - Object azp = idToken.getClaim("azp"); - if (azp != null) { - return azp.toString(); - } - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la récupération de l'authorized party: " + e.getMessage()); - } - return "Non disponible"; - } - - /** - * Vérifier si l'email est vérifié - */ - public boolean isEmailVerified() { - try { - if (idToken != null) { - Boolean emailVerified = idToken.getClaim("email_verified"); - return emailVerified != null && emailVerified; - } - } catch (Exception e) { - LOGGER.warning("Erreur lors de la vérification de l'email: " + e.getMessage()); - } - return false; - } - - /** - * Déconnexion OIDC - * Redirige vers l'endpoint de logout Quarkus qui gère la déconnexion Keycloak - */ - public String logout() { - try { - LOGGER.info("Déconnexion de l'utilisateur: " + fullName); - - FacesContext facesContext = FacesContext.getCurrentInstance(); - ExternalContext externalContext = facesContext.getExternalContext(); - - // NE PAS invalider la session ici — Quarkus OIDC a besoin des tokens - // (stockés en session) pour construire l'URL end_session_endpoint de Keycloak - // avec id_token_hint. La session sera invalidée par Quarkus après le logout. - String contextPath = externalContext.getRequestContextPath(); - externalContext.redirect(contextPath + "/auth/logout"); - facesContext.responseComplete(); - - return null; - } catch (Exception e) { - LOGGER.severe("Erreur lors de la déconnexion: " + e.getMessage()); - return "/?faces-redirect=true"; - } - } -} diff --git a/src/main/java/dev/lions/user/manager/client/view/UserView.java b/src/main/java/dev/lions/user/manager/client/view/UserView.java index 61c834c..ef6aa1b 100644 --- a/src/main/java/dev/lions/user/manager/client/view/UserView.java +++ b/src/main/java/dev/lions/user/manager/client/view/UserView.java @@ -1,177 +1,177 @@ -package dev.lions.user.manager.client.view; - -import dev.lions.user.manager.client.api.UserRestClient; -import dev.lions.user.manager.dto.user.UserDTO; -import dev.lions.user.manager.dto.user.UserSearchResultDTO; -import jakarta.annotation.PostConstruct; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.ExternalContext; -import jakarta.faces.context.FacesContext; -import jakarta.faces.view.ViewScoped; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import lombok.Getter; -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import org.eclipse.microprofile.config.inject.ConfigProperty; -import org.eclipse.microprofile.rest.client.inject.RestClient; -import org.primefaces.model.FilterMeta; -import org.primefaces.model.LazyDataModel; -import org.primefaces.model.SortMeta; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.Serializable; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; - -@Named -@ViewScoped -@Slf4j -public class UserView implements Serializable { - - @Inject - @RestClient - UserRestClient userRestClient; - - @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") - String defaultRealm; - - @Getter - @Setter - private LazyDataModel users; - - @Getter - @Setter - private UserDTO selectedUser; - - @Getter - @Setter - private String selectedRealm; - - @Getter - @Setter - private String searchTerm; - - @PostConstruct - public void init() { - this.selectedRealm = defaultRealm; - this.selectedUser = new UserDTO(); // Initialize to avoid NPE in dialogs before selection - - users = new LazyDataModel() { - @Override - public int count(Map filterBy) { - // Simplified count logic reusing search API - try { - return (int) userRestClient - .searchUsers(selectedRealm, searchTerm, null, null, null, null, null, 0, 1).getTotalCount() - .intValue(); - } catch (Exception e) { - log.error("Error counting users", e); - return 0; - } - } - - @Override - public List load(int first, int pageSize, Map sortBy, - Map filterBy) { - try { - int page = first / pageSize; - UserSearchResultDTO result = userRestClient.searchUsers(selectedRealm, searchTerm, null, null, null, - null, null, page, pageSize); - setRowCount(result.getTotalCount().intValue()); - return result.getUsers(); - } catch (Exception e) { - log.error("Error loading users", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de chargement", e.getMessage())); - return List.of(); - } - } - - @Override - public UserDTO getRowData(String rowKey) { - // Not ideal for lazy model, but needed for selection sometimes if not using - // rowDataWrapper - // Assuming ID is rowKey - try { - return userRestClient.getUserById(rowKey, selectedRealm); - } catch (Exception e) { - return null; - } - } - - @Override - public String getRowKey(UserDTO user) { - return user.getId(); - } - }; - } - - public void openNew() { - this.selectedUser = new UserDTO(); - this.selectedUser.setEnabled(true); - } - - public void saveUser() { - try { - if (this.selectedUser.getId() == null) { - // Create - // Password handling: assume temporary password is set in UI - if (this.selectedUser.getTemporaryPassword() == null - || this.selectedUser.getTemporaryPassword().isBlank()) { - // Generate or require password logic here. For now, let's assume UI requires - // it. - } - userRestClient.createUser(selectedRealm, this.selectedUser); - FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Utilisateur créé")); - } else { - // Update - userRestClient.updateUser(this.selectedUser.getId(), selectedRealm, this.selectedUser); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage("Succès", "Utilisateur mis à jour")); - } - // PrimeFaces.current().executeScript("PF('manageUserDialog').hide()"); // - // Handled in xhtml via oncomplete - } catch (Exception e) { - log.error("Error saving user", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); - } - } - - public void deleteUser() { - try { - userRestClient.deleteUser(this.selectedUser.getId(), selectedRealm, false); - this.selectedUser = null; - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage("Succès", "Utilisateur supprimé (soft delete)")); - } catch (Exception e) { - log.error("Error deleting user", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); - } - } - - public void downloadCSV() { - try { - String csvContent = userRestClient.exportUsersToCSV(selectedRealm); - - FacesContext facesContext = FacesContext.getCurrentInstance(); - ExternalContext externalContext = facesContext.getExternalContext(); - - externalContext.setResponseContentType("text/csv"); - externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"users_export.csv\""); - - OutputStream output = externalContext.getResponseOutputStream(); - output.write(csvContent.getBytes(StandardCharsets.UTF_8)); - - facesContext.responseComplete(); - } catch (IOException e) { - log.error("Error exporting CSV", e); - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur Export", e.getMessage())); - } - } -} +package dev.lions.user.manager.client.view; + +import dev.lions.user.manager.client.api.UserRestClient; +import dev.lions.user.manager.dto.user.UserDTO; +import dev.lions.user.manager.dto.user.UserSearchResultDTO; +import jakarta.annotation.PostConstruct; +import jakarta.faces.application.FacesMessage; +import jakarta.faces.context.ExternalContext; +import jakarta.faces.context.FacesContext; +import jakarta.faces.view.ViewScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.primefaces.model.FilterMeta; +import org.primefaces.model.LazyDataModel; +import org.primefaces.model.SortMeta; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; + +@Named +@ViewScoped +@Slf4j +public class UserView implements Serializable { + + @Inject + @RestClient + UserRestClient userRestClient; + + @ConfigProperty(name = "lions.user.manager.default.realm", defaultValue = "test-realm") + String defaultRealm; + + @Getter + @Setter + private LazyDataModel users; + + @Getter + @Setter + private UserDTO selectedUser; + + @Getter + @Setter + private String selectedRealm; + + @Getter + @Setter + private String searchTerm; + + @PostConstruct + public void init() { + this.selectedRealm = defaultRealm; + this.selectedUser = new UserDTO(); // Initialize to avoid NPE in dialogs before selection + + users = new LazyDataModel() { + @Override + public int count(Map filterBy) { + // Simplified count logic reusing search API + try { + return (int) userRestClient + .searchUsers(selectedRealm, searchTerm, null, null, null, null, null, 0, 1).getTotalCount() + .intValue(); + } catch (Exception e) { + log.error("Error counting users", e); + return 0; + } + } + + @Override + public List load(int first, int pageSize, Map sortBy, + Map filterBy) { + try { + int page = first / pageSize; + UserSearchResultDTO result = userRestClient.searchUsers(selectedRealm, searchTerm, null, null, null, + null, null, page, pageSize); + setRowCount(result.getTotalCount().intValue()); + return result.getUsers(); + } catch (Exception e) { + log.error("Error loading users", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de chargement", e.getMessage())); + return List.of(); + } + } + + @Override + public UserDTO getRowData(String rowKey) { + // Not ideal for lazy model, but needed for selection sometimes if not using + // rowDataWrapper + // Assuming ID is rowKey + try { + return userRestClient.getUserById(rowKey, selectedRealm); + } catch (Exception e) { + return null; + } + } + + @Override + public String getRowKey(UserDTO user) { + return user.getId(); + } + }; + } + + public void openNew() { + this.selectedUser = new UserDTO(); + this.selectedUser.setEnabled(true); + } + + public void saveUser() { + try { + if (this.selectedUser.getId() == null) { + // Create + // Password handling: assume temporary password is set in UI + if (this.selectedUser.getTemporaryPassword() == null + || this.selectedUser.getTemporaryPassword().isBlank()) { + // Generate or require password logic here. For now, let's assume UI requires + // it. + } + userRestClient.createUser(selectedRealm, this.selectedUser); + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Succès", "Utilisateur créé")); + } else { + // Update + userRestClient.updateUser(this.selectedUser.getId(), selectedRealm, this.selectedUser); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage("Succès", "Utilisateur mis à jour")); + } + // PrimeFaces.current().executeScript("PF('manageUserDialog').hide()"); // + // Handled in xhtml via oncomplete + } catch (Exception e) { + log.error("Error saving user", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); + } + } + + public void deleteUser() { + try { + userRestClient.deleteUser(this.selectedUser.getId(), selectedRealm, false); + this.selectedUser = null; + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage("Succès", "Utilisateur supprimé (soft delete)")); + } catch (Exception e) { + log.error("Error deleting user", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", e.getMessage())); + } + } + + public void downloadCSV() { + try { + String csvContent = userRestClient.exportUsersToCSV(selectedRealm); + + FacesContext facesContext = FacesContext.getCurrentInstance(); + ExternalContext externalContext = facesContext.getExternalContext(); + + externalContext.setResponseContentType("text/csv"); + externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"users_export.csv\""); + + OutputStream output = externalContext.getResponseOutputStream(); + output.write(csvContent.getBytes(StandardCharsets.UTF_8)); + + facesContext.responseComplete(); + } catch (IOException e) { + log.error("Error exporting CSV", e); + FacesContext.getCurrentInstance().addMessage(null, + new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur Export", e.getMessage())); + } + } +} diff --git a/src/main/resources/META-INF/faces-config.xml b/src/main/resources/META-INF/faces-config.xml index 25ac10e..a8c71a7 100644 --- a/src/main/resources/META-INF/faces-config.xml +++ b/src/main/resources/META-INF/faces-config.xml @@ -1,185 +1,186 @@ - - - - Lions User Manager - - - dev.lions.user.manager.client.exception.ViewExpiredExceptionHandlerFactory - - - - - fr - fr - en - - - - - * - - - - Page d'accueil / Dashboard - userManagerDashboardPage - /pages/user-manager/dashboard.xhtml - - - - - Navigation directe vers dashboard - /pages/user-manager/dashboard - /pages/user-manager/dashboard.xhtml - - - - - - Page de liste des utilisateurs - userListPage - /pages/user-manager/users/list.xhtml - - - - - Navigation directe vers liste utilisateurs - /pages/user-manager/users/list - /pages/user-manager/users/list.xhtml - - - - - Page de création d'utilisateur - userCreatePage - /pages/user-manager/users/create.xhtml - - - - - Navigation directe vers création utilisateur - /pages/user-manager/users/create - /pages/user-manager/users/create.xhtml - - - - - Page de profil utilisateur - userProfilePage - /pages/user-manager/users/profile.xhtml - - - - - Navigation directe vers profil utilisateur - /pages/user-manager/users/profile - /pages/user-manager/users/profile.xhtml - - - - - Page d'édition utilisateur - userEditPage - /pages/user-manager/users/edit.xhtml - - - - - Navigation directe vers édition utilisateur - /pages/user-manager/users/edit - /pages/user-manager/users/edit.xhtml - - - - - - Page de liste des rôles - roleListPage - /pages/user-manager/roles/list.xhtml - - - - - Navigation directe vers liste rôles - /pages/user-manager/roles/list - /pages/user-manager/roles/list.xhtml - - - - - Page d'attribution de rôles - roleAssignPage - /pages/user-manager/roles/assign.xhtml - - - - - Navigation directe vers attribution rôles - /pages/user-manager/roles/assign - /pages/user-manager/roles/assign.xhtml - - - - - - Page de journal d'audit - auditLogsPage - /pages/user-manager/audit/logs.xhtml - - - - - Navigation directe vers journal d'audit - /pages/user-manager/audit/logs - /pages/user-manager/audit/logs.xhtml - - - - - - Page de dashboard synchronisation - syncDashboardPage - /pages/user-manager/sync/dashboard.xhtml - - - - - Navigation directe vers dashboard synchronisation - /pages/user-manager/sync/dashboard - /pages/user-manager/sync/dashboard.xhtml - - - - - - Page de paramètres utilisateur - settingsPage - /pages/user-manager/settings.xhtml - - - - - Navigation directe vers paramètres - /pages/user-manager/settings - /pages/user-manager/settings.xhtml - - - - - - + + + + Lions User Manager + + + + + + fr + fr + en + + + + + * + + + + Page d'accueil / Dashboard + userManagerDashboardPage + /pages/user-manager/dashboard.xhtml + + + + + Navigation directe vers dashboard + /pages/user-manager/dashboard + /pages/user-manager/dashboard.xhtml + + + + + + Page de liste des utilisateurs + userListPage + /pages/user-manager/users/list.xhtml + + + + + Navigation directe vers liste utilisateurs + /pages/user-manager/users/list + /pages/user-manager/users/list.xhtml + + + + + Page de création d'utilisateur + userCreatePage + /pages/user-manager/users/create.xhtml + + + + + Navigation directe vers création utilisateur + /pages/user-manager/users/create + /pages/user-manager/users/create.xhtml + + + + + Page de profil utilisateur + userProfilePage + /pages/user-manager/users/profile.xhtml + + + + + Navigation directe vers profil utilisateur + /pages/user-manager/users/profile + /pages/user-manager/users/profile.xhtml + + + + + Page d'édition utilisateur + userEditPage + /pages/user-manager/users/edit.xhtml + + + + + Navigation directe vers édition utilisateur + /pages/user-manager/users/edit + /pages/user-manager/users/edit.xhtml + + + + + + Page de liste des rôles + roleListPage + /pages/user-manager/roles/list.xhtml + + + + + Navigation directe vers liste rôles + /pages/user-manager/roles/list + /pages/user-manager/roles/list.xhtml + + + + + Page d'attribution de rôles + roleAssignPage + /pages/user-manager/roles/assign.xhtml + + + + + Navigation directe vers attribution rôles + /pages/user-manager/roles/assign + /pages/user-manager/roles/assign.xhtml + + + + + + Page de journal d'audit + auditLogsPage + /pages/user-manager/audit/logs.xhtml + + + + + Navigation directe vers journal d'audit + /pages/user-manager/audit/logs + /pages/user-manager/audit/logs.xhtml + + + + + + Page de dashboard synchronisation + syncDashboardPage + /pages/user-manager/sync/dashboard.xhtml + + + + + Navigation directe vers dashboard synchronisation + /pages/user-manager/sync/dashboard + /pages/user-manager/sync/dashboard.xhtml + + + + + + Page de paramètres utilisateur + settingsPage + /pages/user-manager/settings.xhtml + + + + + Navigation directe vers paramètres + /pages/user-manager/settings + /pages/user-manager/settings.xhtml + + + + + + diff --git a/src/main/resources/META-INF/quarkus-config.properties b/src/main/resources/META-INF/quarkus-config.properties index 9953ae1..0e30588 100644 --- a/src/main/resources/META-INF/quarkus-config.properties +++ b/src/main/resources/META-INF/quarkus-config.properties @@ -1,3 +1,3 @@ -# Configuration Quarkus pour PrimeFaces -# Exclusion de classes obsolètes de PrimeFaces 14.0.5 - +# Configuration Quarkus pour PrimeFaces +# Exclusion de classes obsolètes de PrimeFaces 14.0.5 + diff --git a/src/main/resources/META-INF/resources/index.html b/src/main/resources/META-INF/resources/index.html index d0135e0..221bed4 100644 --- a/src/main/resources/META-INF/resources/index.html +++ b/src/main/resources/META-INF/resources/index.html @@ -1,315 +1,295 @@ - - - - - - Lions User Manager - Plateforme de Gestion IAM Centralisée - - - - - - - - - - - - - - - - - -
-
- - -
- - Plateforme IAM Centralisée - -
- -

- Gérez vos utilisateurs Keycloak
en toute simplicité -

-

- Une interface moderne et intuitive pour administrer vos identités, rôles et permissions à travers tous vos royaumes Keycloak. -

- - - - - -
-
- - -
-
-
-
10K+
-
Utilisateurs gérés
-
-
-
50+
-
Royaumes actifs
-
-
-
99.9%
-
Disponibilité
-
-
-
24/7
-
Supervision
-
-
-
- - -
-
-
- - Fonctionnalités Métier - -
-

Tout pour gérer vos identités

-

- Une suite complète d'outils pour simplifier l'administration de votre infrastructure IAM. -

-
- -
- -
-
-
- -
-

Gestion des utilisateurs

-

- Créez, modifiez et supprimez des utilisateurs. Recherche avancée et filtrage en temps réel. -

-
    -
  • Import/Export CSV massif
  • -
  • Recherche multi-critères
  • -
  • Modification par lot
  • -
-
-
- - -
-
-
- -
-

Attribution des rôles

-

- Permissions granulaires avec un système RBAC flexible et sécurisé. -

-
    -
  • Gestion RBAC complète
  • -
  • Hiérarchie de rôles
  • -
  • Permissions dynamiques
  • -
-
-
- - -
-
-
- -
-

Audit & Analytics

-

- Tableaux de bord interactifs et rapports détaillés en temps réel. -

-
    -
  • Logs d'authentification
  • -
  • Rapports personnalisés
  • -
  • Alertes de sécurité
  • -
-
-
- - -
-
-
- -
-

Synchronisation

-

- Intégration transparente via API RESTful sécurisée et webhooks. -

-
    -
  • API REST complète
  • -
  • Webhooks événementiels
  • -
  • Connecteurs pré-configurés
  • -
-
-
- - -
-
-
- -
-

Sécurité avancée

-

- Protection multi-niveaux avec MFA et audit de sécurité complet. -

-
    -
  • MFA/2FA obligatoire
  • -
  • Chiffrement end-to-end
  • -
  • Audit de conformité
  • -
-
-
- - -
-
-
- -
-

Multi-tenant

-

- Gérez plusieurs organisations depuis une seule interface. -

-
    -
  • Isolation par royaume
  • -
  • Personnalisation par org
  • -
  • Délégation d'administration
  • -
-
-
-
-
- - -
-
-

- Prêt à transformer votre gestion IAM ? -

-

- Rejoignez les entreprises qui font confiance à Lions User Manager pour sécuriser leur infrastructure d'identité. -

- - - Accéder à la plateforme - -
-
- - -
-
-
- Lions - Lions User Manager -
-

- Plateforme professionnelle de gestion IAM propulsée par Keycloak Admin API -

-
-
- © 2026 Lions User Manager - - Sécurisé par OpenID Connect - - Powered by Quarkus & PrimeFaces Freya -
-
-
-
- - - - - + + + + + + Lions User Manager - Plateforme de Gestion IAM Centralisée + + + + + + + + + + + + + + + + + +
+
+ + +
+ + Plateforme IAM Centralisée + +
+ +

+ Gérez vos utilisateurs Keycloak
en toute simplicité +

+

+ Une interface moderne et intuitive pour administrer vos identités, rôles et permissions à travers tous vos royaumes Keycloak. +

+ + + + + +
+
+ + + + +
+
+
+ + Fonctionnalités Métier + +
+

Tout pour gérer vos identités

+

+ Une suite complète d'outils pour simplifier l'administration de votre infrastructure IAM. +

+
+ +
+ +
+
+
+ +
+

Gestion des utilisateurs

+

+ Créez, modifiez et supprimez des utilisateurs. Recherche avancée et filtrage en temps réel. +

+
    +
  • Import/Export CSV massif
  • +
  • Recherche multi-critères
  • +
  • Modification par lot
  • +
+
+
+ + +
+
+
+ +
+

Attribution des rôles

+

+ Permissions granulaires avec un système RBAC flexible et sécurisé. +

+
    +
  • Gestion RBAC complète
  • +
  • Hiérarchie de rôles
  • +
  • Permissions dynamiques
  • +
+
+
+ + +
+
+
+ +
+

Audit & Analytics

+

+ Tableaux de bord interactifs et rapports détaillés en temps réel. +

+
    +
  • Logs d'authentification
  • +
  • Rapports personnalisés
  • +
  • Alertes de sécurité
  • +
+
+
+ + +
+
+
+ +
+

Synchronisation

+

+ Intégration transparente via API RESTful sécurisée et webhooks. +

+
    +
  • API REST complète
  • +
  • Webhooks événementiels
  • +
  • Connecteurs pré-configurés
  • +
+
+
+ + +
+
+
+ +
+

Sécurité avancée

+

+ Protection multi-niveaux avec MFA et audit de sécurité complet. +

+
    +
  • MFA/2FA obligatoire
  • +
  • Chiffrement end-to-end
  • +
  • Audit de conformité
  • +
+
+
+ + +
+
+
+ +
+

Multi-tenant

+

+ Gérez plusieurs organisations depuis une seule interface. +

+
    +
  • Isolation par royaume
  • +
  • Personnalisation par org
  • +
  • Délégation d'administration
  • +
+
+
+
+
+ + +
+
+

+ Prêt à transformer votre gestion IAM ? +

+

+ Rejoignez les entreprises qui font confiance à Lions User Manager pour sécuriser leur infrastructure d'identité. +

+ + + Accéder à la plateforme + +
+
+ + +
+
+
+ Lions + Lions User Manager +
+

+ Plateforme professionnelle de gestion IAM propulsée par Keycloak Admin API +

+
+
+ © 2026 Lions User Manager + + Sécurisé par OpenID Connect + + Powered by Quarkus & PrimeFaces Freya +
+
+
+
+ + + + + diff --git a/src/main/resources/META-INF/resources/index.xhtml b/src/main/resources/META-INF/resources/index.xhtml index 3283827..66973e2 100644 --- a/src/main/resources/META-INF/resources/index.xhtml +++ b/src/main/resources/META-INF/resources/index.xhtml @@ -1,191 +1,111 @@ - - - - Accueil - Lions User Manager - - -
- -
-
-
- - -

- Bienvenue, #{userSessionBean.fullName} -

-

- Gestion centralisée des utilisateurs Keycloak -

- -
- - - Connecté - - - #{userSessionBean.primaryRole} - -
-
-
-
- - -
-
-

- - Accès Rapide -

- -
- -
- -
-
-
- -
- -
-

Utilisateurs

-

Gérer les comptes utilisateurs

-
-
-
- - -
- -
-
-
- -
- -
-

Rôles

-

Configurer les rôles et permissions

-
-
-
- - -
- -
-
-
- -
- -
-

Audit

-

Consulter le journal d'activité

-
-
-
- - -
- -
-
-
- -
- -
-

Synchronisation

-

Synchroniser avec Keycloak

-
-
-
-
-
-
- - -
-
-

- - Informations Système -

-
-
- Application - Lions User Manager -
-
- Version - 1.0.0 -
-
- Realm Keycloak - lions-user-manager -
-
- Statut - -
-
-
-
- -
-
-

- - Ma Session -

-
-
- Utilisateur - #{userSessionBean.username} -
-
- Email - #{userSessionBean.email} -
-
- Rôle principal - -
-
- Actions -
- - Mon Profil - - - Dashboard - -
-
-
-
-
-
-
- -
+ + + + Accueil - Lions User Manager + + +
+ +
+
+
+ + +

+ Bienvenue, #{userSessionBean.fullName} +

+

+ Gestion centralisée des utilisateurs Keycloak +

+ +
+ + + Connecté + + + #{userSessionBean.primaryRole} + +
+
+
+
+ + + + +
+
+

+ + Informations Système +

+
+
+ Application + Lions User Manager +
+
+ Version + 1.0.0 +
+
+ Realm Keycloak + lions-user-manager +
+
+ Statut + +
+
+
+
+ +
+
+

+ + Ma Session +

+
+
+ Utilisateur + #{userSessionBean.username} +
+
+ Email + #{userSessionBean.email} +
+
+ Rôle principal + +
+
+ Actions +
+ + Mon Profil + + + Dashboard + +
+
+
+
+
+
+
+ +
diff --git a/src/main/resources/META-INF/resources/pages/admin/realm-assignments.xhtml b/src/main/resources/META-INF/resources/pages/admin/realm-assignments.xhtml index d851c91..368c49a 100644 --- a/src/main/resources/META-INF/resources/pages/admin/realm-assignments.xhtml +++ b/src/main/resources/META-INF/resources/pages/admin/realm-assignments.xhtml @@ -1,351 +1,351 @@ - - - - Affectation des Realms - Lions User Manager - - - -
- -
-
-
-
- -
-

Affectation des Realms

-

Gérer les permissions d'administration par realm (contrôle multi-tenant)

-
-
- -
-
-
- - -
-
-
-
-
Total Affectations
-
#{realmAssignmentBean.totalAssignments}
-
-
- -
-
- Assignations configurées -
-
- -
-
-
-
-
Affectations Actives
-
#{realmAssignmentBean.activeAssignmentsCount}
-
-
- -
-
- En cours de validité -
-
- -
-
-
-
-
Super Admins
-
#{realmAssignmentBean.superAdminsCount}
-
-
- -
-
- Peuvent gérer tous les realms -
-
- - -
-
-
-
Affectations Actuelles
- -
- - - - - - - - - -
-
- -
-
-
#{assignment.username}
- #{assignment.email} -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
-
-
-
-
-
-
- - - - -
-
- - - - -
- -
- - - - -
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
-
- -
-
Information
- - L'utilisateur pourra administrer uniquement le realm assigné. - Pour accorder l'accès à tous les realms, utilisez le statut Super Admin. - -
-
-
-
- -
-
- - -
-
-
-
-
- - - - - - - -
- -
+ + + + Affectation des Realms - Lions User Manager + + + +
+ +
+
+
+
+ +
+

Affectation des Realms

+

Gérer les permissions d'administration par realm (contrôle multi-tenant)

+
+
+ +
+
+
+ + +
+
+
+
+
Total Affectations
+
#{realmAssignmentBean.totalAssignments}
+
+
+ +
+
+ Assignations configurées +
+
+ +
+
+
+
+
Affectations Actives
+
#{realmAssignmentBean.activeAssignmentsCount}
+
+
+ +
+
+ En cours de validité +
+
+ +
+
+
+
+
Super Admins
+
#{realmAssignmentBean.superAdminsCount}
+
+
+ +
+
+ Peuvent gérer tous les realms +
+
+ + +
+
+
+
Affectations Actuelles
+ +
+ + + + + + + + + +
+
+ +
+
+
#{assignment.username}
+ #{assignment.email} +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+
+
+
+
+
+
+ + + + +
+
+ + + + +
+ +
+ + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+ +
+
Information
+ + L'utilisateur pourra administrer uniquement le realm assigné. + Pour accorder l'accès à tous les realms, utilisez le statut Super Admin. + +
+
+
+
+ +
+
+ + +
+
+
+
+
+ + + + + + + +
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/audit/logs.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/audit/logs.xhtml index 95859d6..16e410f 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/audit/logs.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/audit/logs.xhtml @@ -1,353 +1,353 @@ - - - - - Journal d'Audit - Lions User Manager - - -
- -
- - - - - - -
- - - - - - - -
-
-
-
-
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- -
-
- Filtres de recherche -
-
-
-
- - -
- -
- - - - - -
- -
- - - - - - -
- -
- - -
- -
- - -
- -
- - -
-
- -
- - -
-
-
-
- - -
- -
- - -
-
- -
-
- Logs d'Audit -
- -
- - - - - - - - - - - - - - - - #{log.typeAction} - - - - -
- - #{log.acteurUsername} -
-
- - - - - - - - - - - - - - -
- - - - -
-
- - - - - #{log.description} - - - - - - - - - - - #{log.ipAddress} - - - - - - - - - - - - - -
-
-
-
-
- - - - - -
- - -
- - - - - - - - - - - -
- - -
- Type d'action - - #{auditConsultationBean.selectedLog.typeAction} - -
- - -
- Acteur -
- - - #{auditConsultationBean.selectedLog.acteurUsername} - -
-
- - -
- Ressource - - #{auditConsultationBean.selectedLog.ressourceType} - - — #{auditConsultationBean.selectedLog.ressourceId} - - -
- - - - Description - #{auditConsultationBean.selectedLog.description} - - - - - Adresse IP - #{auditConsultationBean.selectedLog.ipAddress} - - - - - User Agent - #{auditConsultationBean.selectedLog.userAgent} - - - - -
- - Message d'erreur - - - #{auditConsultationBean.selectedLog.errorMessage} - -
-
- - - - Realm - - -
-
- - -
- - Sélectionnez un log pour voir ses détails. -
-
-
-
-
- -
+ + + + + Journal d'Audit - Lions User Manager + + +
+ +
+ + + + + + +
+ + + + + + + +
+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ +
+
+ Filtres de recherche +
+
+
+
+ + +
+ +
+ + + + + +
+ +
+ + + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
+
+
+ + +
+ +
+ + +
+
+ +
+
+ Logs d'Audit +
+ +
+ + + + + + + + + + + + + + + + #{log.typeAction} + + + + +
+ + #{log.acteurUsername} +
+
+ + + + + + + + - + + + + + +
+ + + + +
+
+ + + + + #{log.description} + + + - + + + + + + + #{log.ipAddress} + + + - + + + + + + + + + +
+
+
+
+
+ + + + + +
+ + +
+ + + + + + + + + + + +
+ + +
+ Type d'action + + #{auditConsultationBean.selectedLog.typeAction} + +
+ + +
+ Acteur +
+ + + #{auditConsultationBean.selectedLog.acteurUsername} + +
+
+ + +
+ Ressource + + #{auditConsultationBean.selectedLog.ressourceType} + + — #{auditConsultationBean.selectedLog.ressourceId} + + +
+ + + + Description + #{auditConsultationBean.selectedLog.description} + + + + + Adresse IP + #{auditConsultationBean.selectedLog.ipAddress} + + + + + User Agent + #{auditConsultationBean.selectedLog.userAgent} + + + + +
+ + Message d'erreur + + + #{auditConsultationBean.selectedLog.errorMessage} + +
+
+ + + + Realm + + +
+
+ + +
+ + Sélectionnez un log pour voir ses détails. +
+
+
+
+
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/dashboard.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/dashboard.xhtml index 0ed9b84..63b50eb 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/dashboard.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/dashboard.xhtml @@ -1,146 +1,146 @@ - - - - Tableau de Bord - Lions User Manager - - - -
- -
- - - - - - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - - - - -
-
- Version - 1.0.0 -
-
- Realm Keycloak - #{dashboardBean.realmName} -
-
- Statut - -
-
- Application - Lions User Manager -
-
- Environnement - Développement -
-
- Base de données - Keycloak Admin API -
-
- Framework - Quarkus, PrimeFaces Freya -
-
-
-
-
-
-
- + + + + Tableau de Bord - Lions User Manager + + + +
+ +
+ + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + + +
+
+ Version + 1.0.0 +
+
+ Realm Keycloak + #{dashboardBean.realmName} +
+
+ Statut + +
+
+ Application + Lions User Manager +
+
+ Environnement + Développement +
+
+ Base de données + Keycloak Admin API +
+
+ Framework + Quarkus, PrimeFaces Freya +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/freya-showcase.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/freya-showcase.xhtml index de9c587..31c31a5 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/freya-showcase.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/freya-showcase.xhtml @@ -1,918 +1,918 @@ - - - - Freya Extension Showcase - Lions User Manager - - - -
- -
-
-
-
- -
-

PrimeFaces Freya Extension Showcase

-

Démonstration complète des 46 composants personnalisés

-
- - - -
-
-
- -
-
-
- - -
-

- - Composants de Formulaire (Field Pattern) - -

-
- - -
-
-
fr:fieldInput
-

Champ de saisie texte avec label et message de validation

- - -
-
- - -
-
-
fr:fieldPassword
-

Champ mot de passe avec validation de force

- - -
-
- - -
-
-
fr:fieldTextarea
-

Zone de texte multiligne pour descriptions

- - -
-
- - -
-
-
fr:fieldNumber
-

Champ numérique avec contrôles + / -

- - -
-
- - -
-
-
fr:fieldCalendar
-

Sélecteur de date avec calendrier popup

- - -
-
- - -
-
-
fr:fieldSelect
-

Liste déroulante simple sélection

- - - - - - - - -
-
- - -
-
-
fr:fieldMultiSelect
-

Sélection multiple avec chips

- - - - - - - - -
-
- - -
-
-
fr:fieldCheckbox
-

Case à cocher pour valeurs booléennes

- - -
-
- - -
-
-
fr:fieldRadio
-

Boutons radio pour choix exclusif

- - - - - - -
-
- - -
-
-
fr:fieldSwitch
-

Interrupteur on/off moderne

- - -
-
- - -
-
-
fr:fieldToggle
-

Bouton toggle avec états on/off

- - -
-
- - -
-
-
fr:fieldSlider
-

Curseur pour sélection de valeur numérique

- - -

Valeur sélectionnée: #{demoBean.user.volume != null ? demoBean.user.volume : 50}%

-
-
- - -
-
-
fr:fieldRating
-

Évaluation par étoiles

- - -
-
- - -
-
-
fr:fieldChips
-

Saisie de tags/mots-clés multiples

- - -
-
- - -
-
-
fr:fieldColor
-

Sélecteur de couleur avec palette

- - -
-
- - -
-
-
fr:fieldEditor
-

Éditeur de texte riche WYSIWYG

- - -
-
- - -
-
-
fr:fieldMask
-

Champ avec masque de saisie (téléphone, etc.)

- - -
-
- - -
-
-
fr:fieldAutoComplete
-

Saisie avec suggestions automatiques

- - -
-
- - -
-
-
fr:fieldSpinner
-

Compteur numérique avec incréments

- - -
-
- - -
-
-
fr:fieldFileUpload
-

Upload de fichiers avec contraintes

- - -

Formats acceptés: PDF, DOC, DOCX (max 3 fichiers)

-
-
- - -
-

- - Composants d'Action - -

-
- - -
-
-
fr:button
-

Bouton de navigation simple (sans Ajax)

- -
- - - - - - - -
-
-
- - -
-
-
fr:commandButton
-

Bouton avec action Ajax

- -
- - - -
-
-
- - -
-
-
fr:linkButton
-

Bouton sous forme de lien

- -
- - - -
-
-
- - -
-
-
fr:splitButton
-

Bouton avec menu déroulant d'actions

- - - - - - - -
-
- - -
-
-
fr:actionDialog
-

Dialogue modal pour confirmation d'action

- - - - -
-
- - -
-

- - Composants de Layout - -

-
- - -
- -

- Ceci est le contenu de la carte. Les cartes sont utilisées pour regrouper - des informations connexes dans un conteneur visuellement distinct. -

- - -
- - -
-
-
-
- - -
- -

- Panel pliable/dépliable pour organiser le contenu en sections. - Cliquez sur l'icône pour replier/déplier. -

-
-
- - -
-
-
fr:divider
-

Séparateur visuel horizontal ou vertical

- -
-

Contenu avant le divider

- -

Contenu après le divider

-
- - - Divider avec texte aligné à gauche - - - - - -
-
- - -
-
-
fr:spacer
-

Espace vide pour ajuster la mise en page

- -
- Élément gauche - - Élément droite -
-
-
- - -
-

- - Composants de Navigation - -

-
- - -
-
-
fr:breadcrumb
-

Fil d'Ariane pour navigation hiérarchique

- - - - - - -
-
- - -
-
-
fr:steps
-

Indicateur de progression par étapes

- - - - - - -
-
- - -
- - -

- Contenu du premier onglet. Les onglets permettent d'organiser le contenu en sections - accessibles via des onglets cliquables. -

-
- -

- Contenu du deuxième onglet avec informations différentes. -

-
- -

- Troisième onglet pour démonstration complète. -

-
-
-
- - -
-

- - Composants de Données - -

-
- - -
-
-
fr:dataTable
-

Tableau de données avec tri, filtrage et pagination

- - - - - - - - - - - - -
-
- - -
-
-
fr:dataView
-

Affichage de données en grille/liste avec templates

- - - -
-
- - #{user.nom} -
-

#{user.email}

-
-
-
-
-
- - -
-
-
fr:tree
-

Arborescence hiérarchique navigable

- - - - - - -
-
- - -
-
-
fr:treeTable
-

Tableau arborescent avec colonnes

- - - - - - - - - -
-
- - -
-
-
fr:inplace
-

Édition en ligne activable au clic

- - - - -
-
- - -
-

- - Composants de Feedback - -

-
- - -
-
-
fr:message
-

Message de validation pour champ spécifique

- - - -
-
- - -
-
-
fr:growl
-

Notifications toast en coin d'écran

- - - - -
-
- - -
-
-
fr:progressBar
-

Barre de progression pour opérations longues

- - -
- - -
-
-
- - -
-

- - Composants Utilitaires - -

-
- - -
-
-
fr:avatar
-

Avatar utilisateur avec image ou initiales

- -
- - - - -
-
-
- - -
-
-
fr:badge
-

Badge de notification avec compteur

- -
- - - - - - - - - -
-
-
- - -
-
-
fr:tag
-

Tags colorés pour statuts et catégories

- -
- - - - - - - -
-
-
- - -
-

- - Composants Avancés - -

-
- - -
-
-
fr:chart
-

Graphique avec Chart.js (bar, line, pie, etc.)

- - - - #{demoBean.chartData} - - -
-
- - -
-
-
fr:formDialog
-

Dialogue modal avec formulaire intégré

- - - - - - - -
-
- - -
-
-
fr:themeSelector
-

Sélecteur de thème Freya (16 variantes)

- - -

- - Ce composant permet de changer dynamiquement le thème de l'application parmi - les 16 variantes Freya (8 couleurs × 2 modes dark/light) -

-
-
- - -
-
-
- -

Intégration Complète Réussie

-

- Les 46 composants PrimeFaces Freya Extension sont maintenant disponibles dans Lions User Manager -

-
- - - - - - - - -
-
-
-
-
-
-
- -
+ + + + Freya Extension Showcase - Lions User Manager + + + +
+ +
+
+
+
+ +
+

PrimeFaces Freya Extension Showcase

+

Démonstration complète des 46 composants personnalisés

+
+ + + +
+
+
+ +
+
+
+ + +
+

+ + Composants de Formulaire (Field Pattern) + +

+
+ + +
+
+
fr:fieldInput
+

Champ de saisie texte avec label et message de validation

+ + +
+
+ + +
+
+
fr:fieldPassword
+

Champ mot de passe avec validation de force

+ + +
+
+ + +
+
+
fr:fieldTextarea
+

Zone de texte multiligne pour descriptions

+ + +
+
+ + +
+
+
fr:fieldNumber
+

Champ numérique avec contrôles + / -

+ + +
+
+ + +
+
+
fr:fieldCalendar
+

Sélecteur de date avec calendrier popup

+ + +
+
+ + +
+
+
fr:fieldSelect
+

Liste déroulante simple sélection

+ + + + + + + + +
+
+ + +
+
+
fr:fieldMultiSelect
+

Sélection multiple avec chips

+ + + + + + + + +
+
+ + +
+
+
fr:fieldCheckbox
+

Case à cocher pour valeurs booléennes

+ + +
+
+ + +
+
+
fr:fieldRadio
+

Boutons radio pour choix exclusif

+ + + + + + +
+
+ + +
+
+
fr:fieldSwitch
+

Interrupteur on/off moderne

+ + +
+
+ + +
+
+
fr:fieldToggle
+

Bouton toggle avec états on/off

+ + +
+
+ + +
+
+
fr:fieldSlider
+

Curseur pour sélection de valeur numérique

+ + +

Valeur sélectionnée: #{demoBean.user.volume != null ? demoBean.user.volume : 50}%

+
+
+ + +
+
+
fr:fieldRating
+

Évaluation par étoiles

+ + +
+
+ + +
+
+
fr:fieldChips
+

Saisie de tags/mots-clés multiples

+ + +
+
+ + +
+
+
fr:fieldColor
+

Sélecteur de couleur avec palette

+ + +
+
+ + +
+
+
fr:fieldEditor
+

Éditeur de texte riche WYSIWYG

+ + +
+
+ + +
+
+
fr:fieldMask
+

Champ avec masque de saisie (téléphone, etc.)

+ + +
+
+ + +
+
+
fr:fieldAutoComplete
+

Saisie avec suggestions automatiques

+ + +
+
+ + +
+
+
fr:fieldSpinner
+

Compteur numérique avec incréments

+ + +
+
+ + +
+
+
fr:fieldFileUpload
+

Upload de fichiers avec contraintes

+ + +

Formats acceptés: PDF, DOC, DOCX (max 3 fichiers)

+
+
+ + +
+

+ + Composants d'Action + +

+
+ + +
+
+
fr:button
+

Bouton de navigation simple (sans Ajax)

+ +
+ + + + + + + +
+
+
+ + +
+
+
fr:commandButton
+

Bouton avec action Ajax

+ +
+ + + +
+
+
+ + +
+
+
fr:linkButton
+

Bouton sous forme de lien

+ +
+ + + +
+
+
+ + +
+
+
fr:splitButton
+

Bouton avec menu déroulant d'actions

+ + + + + + + +
+
+ + +
+
+
fr:actionDialog
+

Dialogue modal pour confirmation d'action

+ + + + +
+
+ + +
+

+ + Composants de Layout + +

+
+ + +
+ +

+ Ceci est le contenu de la carte. Les cartes sont utilisées pour regrouper + des informations connexes dans un conteneur visuellement distinct. +

+ + +
+ + +
+
+
+
+ + +
+ +

+ Panel pliable/dépliable pour organiser le contenu en sections. + Cliquez sur l'icône pour replier/déplier. +

+
+
+ + +
+
+
fr:divider
+

Séparateur visuel horizontal ou vertical

+ +
+

Contenu avant le divider

+ +

Contenu après le divider

+
+ + + Divider avec texte aligné à gauche + + + + + +
+
+ + +
+
+
fr:spacer
+

Espace vide pour ajuster la mise en page

+ +
+ Élément gauche + + Élément droite +
+
+
+ + +
+

+ + Composants de Navigation + +

+
+ + +
+
+
fr:breadcrumb
+

Fil d'Ariane pour navigation hiérarchique

+ + + + + + +
+
+ + +
+
+
fr:steps
+

Indicateur de progression par étapes

+ + + + + + +
+
+ + +
+ + +

+ Contenu du premier onglet. Les onglets permettent d'organiser le contenu en sections + accessibles via des onglets cliquables. +

+
+ +

+ Contenu du deuxième onglet avec informations différentes. +

+
+ +

+ Troisième onglet pour démonstration complète. +

+
+
+
+ + +
+

+ + Composants de Données + +

+
+ + +
+
+
fr:dataTable
+

Tableau de données avec tri, filtrage et pagination

+ + + + + + + + + + + + +
+
+ + +
+
+
fr:dataView
+

Affichage de données en grille/liste avec templates

+ + + +
+
+ + #{user.nom} +
+

#{user.email}

+
+
+
+
+
+ + +
+
+
fr:tree
+

Arborescence hiérarchique navigable

+ + + + + + +
+
+ + +
+
+
fr:treeTable
+

Tableau arborescent avec colonnes

+ + + + + + + + + +
+
+ + +
+
+
fr:inplace
+

Édition en ligne activable au clic

+ + + + +
+
+ + +
+

+ + Composants de Feedback + +

+
+ + +
+
+
fr:message
+

Message de validation pour champ spécifique

+ + + +
+
+ + +
+
+
fr:growl
+

Notifications toast en coin d'écran

+ + + + +
+
+ + +
+
+
fr:progressBar
+

Barre de progression pour opérations longues

+ + +
+ + +
+
+
+ + +
+

+ + Composants Utilitaires + +

+
+ + +
+
+
fr:avatar
+

Avatar utilisateur avec image ou initiales

+ +
+ + + + +
+
+
+ + +
+
+
fr:badge
+

Badge de notification avec compteur

+ +
+ + + + + + + + + +
+
+
+ + +
+
+
fr:tag
+

Tags colorés pour statuts et catégories

+ +
+ + + + + + + +
+
+
+ + +
+

+ + Composants Avancés + +

+
+ + +
+
+
fr:chart
+

Graphique avec Chart.js (bar, line, pie, etc.)

+ + + + #{demoBean.chartData} + + +
+
+ + +
+
+
fr:formDialog
+

Dialogue modal avec formulaire intégré

+ + + + + + + +
+
+ + +
+
+
fr:themeSelector
+

Sélecteur de thème Freya (16 variantes)

+ + +

+ + Ce composant permet de changer dynamiquement le thème de l'application parmi + les 16 variantes Freya (8 couleurs × 2 modes dark/light) +

+
+
+ + +
+
+
+ +

Intégration Complète Réussie

+

+ Les 46 composants PrimeFaces Freya Extension sont maintenant disponibles dans Lions User Manager +

+
+ + + + + + + + +
+
+
+
+
+
+
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/roles.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/roles.xhtml index 8a3fa51..9ee939f 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/roles.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/roles.xhtml @@ -1,90 +1,90 @@ - - - Gestion Rôles - - - -
- - - - - - - - - -
- Rôles -
-
- - - - - - - - - - - - - - - - - - - - -
-
-
- - - - - -
- Nom - -
-
- Description - -
-
-
- - - - - -
- - - - - -
-
- + + + Gestion Rôles + + + +
+ + + + + + + + + +
+ Rôles +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + +
+ Nom + +
+
+ Description + +
+
+
+ + + + + +
+ + + + + +
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/roles/assign.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/roles/assign.xhtml index fb148e0..a27bcbb 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/roles/assign.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/roles/assign.xhtml @@ -1,14 +1,14 @@ - - - - - - - Redirecting... - - - Redirecting to user list... - - + + + + + + + Redirecting... + + + Redirecting to user list... + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/roles/list.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/roles/list.xhtml index 860524a..9567ad5 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/roles/list.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/roles/list.xhtml @@ -1,205 +1,205 @@ - - - - - Gestion des Rôles - Lions User Manager - - - - - - - - - -
- - -
-
-
-
- - - - - -
- -
- -
Filtres
-
-
-
-
- - - - - - -
-
- -
-
- - - - - - -
-
- -
-
- - - - - - -
-
-
-
-
- - -
- - - -
-
- - Rôles Realm -
- -
-
-
- -
- - - - - - - - -
-
- -
- - Aucun rôle Realm trouvé -
-
-
- -
-
-
- - -
- - - -
-
- - Rôles Client -
- -
-
-
- -
- - - - - - - - -
-
- -
- - - Sélectionnez un client pour voir ses rôles - - - Aucun rôle Client trouvé - -
-
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
+ + + + + Gestion des Rôles - Lions User Manager + + + + + + + + + +
+ + +
+
+
+
+ + + + + +
+ +
+ +
Filtres
+
+
+
+
+ + + + + + +
+
+ +
+
+ + + + + + +
+
+ +
+
+ + + + + + +
+
+
+
+
+ + +
+ + + +
+
+ + Rôles Realm +
+ +
+
+
+ +
+ + + + + + + + +
+
+ +
+ + Aucun rôle Realm trouvé +
+
+
+ +
+
+
+ + +
+ + + +
+
+ + Rôles Client +
+ +
+
+
+ +
+ + + + + + + + +
+
+ +
+ + + Sélectionnez un client pour voir ses rôles + + + Aucun rôle Client trouvé + +
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/settings.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/settings.xhtml index 109f651..a64ef56 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/settings.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/settings.xhtml @@ -1,131 +1,131 @@ - - - - - Paramètres - Lions User Manager - - - - - - - - - -
- -
-
-
Informations du compte
- - - - - - - - - - - - - - - -
-
- - -
-
-
Préférences
- -
-
- Thème des composants - - - - -
-
- Mode sombre - - - - - -
-
- Style d'input - - - - - -
-
-
-
-
- - -
-
-
Actions
-
- - - - - - - - - -
-
-
-
-
- -
- + + + + + Paramètres - Lions User Manager + + + + + + + + + +
+ +
+
+
Informations du compte
+ + + + + + + + + + + + + + + +
+
+ + +
+
+
Préférences
+ +
+
+ Thème des composants + + + + +
+
+ Mode sombre + + + + + +
+
+ Style d'input + + + + + +
+
+
+
+
+ + +
+
+
Actions
+
+ + + + + + + + + +
+
+
+
+
+ +
+ diff --git a/src/main/resources/META-INF/resources/pages/user-manager/sync/dashboard.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/sync/dashboard.xhtml index 5e6e220..42e71b0 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/sync/dashboard.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/sync/dashboard.xhtml @@ -1,171 +1,171 @@ - - - - Synchronisation Keycloak - Lions User Manager - - - - - - -
- - - - - - - - -
- -
- -
-
-
État de Keycloak
-
-
- -
-
- - #{syncDashboardBean.keycloakStatusLabel eq 'UP' ? 'En Ligne' : 'Hors Ligne'} - - Statut du service -
- - - -
- - - -
-
- Message: - #{syncDashboardBean.keycloakStatusMessage} -
-
- Version: - #{syncDashboardBean.keycloakVersion} -
-
-
-
- - -
-
-
Actions de Synchronisation
-

Lancez la synchronisation des données depuis Keycloak vers la base - locale.

- -
-
-
- - Utilisateurs -
- -
- -
-
- - Rôles -
- -
-
-
-
- - -
-
-
-
Dernière Synchronisation
- -
- -
-
- Date: - #{syncDashboardBean.lastSyncDate} -
-
- Statut: - -
-
- Éléments traités: - #{syncDashboardBean.lastSyncItemsProcessed} -
-
-
-
- - -
-
-
-
Cohérence des Données
- -
- - -
- Résultat: - -
-
- Utilisateurs Keycloak: - #{syncDashboardBean.consistencyResult.usersKeycloakCount} -
-
- Utilisateurs locaux: - #{syncDashboardBean.consistencyResult.usersLocalCount} -
-
- Éléments manquants: - - #{syncDashboardBean.consistencyMissingCount} - -
-
- - -
- - Cliquez sur "Vérifier" pour analyser la cohérence des données. -
-
-
-
-
-
-
- + + + + Synchronisation Keycloak - Lions User Manager + + + + + + +
+ + + + + + + + +
+ +
+ +
+
+
État de Keycloak
+
+
+ +
+
+ + #{syncDashboardBean.keycloakStatusLabel eq 'UP' ? 'En Ligne' : 'Hors Ligne'} + + Statut du service +
+ + + +
+ + + +
+
+ Message: + #{syncDashboardBean.keycloakStatusMessage} +
+
+ Version: + #{syncDashboardBean.keycloakVersion} +
+
+
+
+ + +
+
+
Actions de Synchronisation
+

Lancez la synchronisation des données depuis Keycloak vers la base + locale.

+ +
+
+
+ + Utilisateurs +
+ +
+ +
+
+ + Rôles +
+ +
+
+
+
+ + +
+
+
+
Dernière Synchronisation
+ +
+ +
+
+ Date: + #{syncDashboardBean.lastSyncDate} +
+
+ Statut: + +
+
+ Éléments traités: + #{syncDashboardBean.lastSyncItemsProcessed} +
+
+
+
+ + +
+
+
+
Cohérence des Données
+ +
+ + +
+ Résultat: + +
+
+ Utilisateurs Keycloak: + #{syncDashboardBean.consistencyResult.usersKeycloakCount} +
+
+ Utilisateurs locaux: + #{syncDashboardBean.consistencyResult.usersLocalCount} +
+
+ Éléments manquants: + + #{syncDashboardBean.consistencyMissingCount} + +
+
+ + +
+ + Cliquez sur "Vérifier" pour analyser la cohérence des données. +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users.xhtml index 0cf546d..e7809c0 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users.xhtml @@ -1,132 +1,132 @@ - - - Gestion Utilisateurs - - - -
- - - - - - - - - - - -
- Utilisateurs - - - - - - -
-
- - - - - - - - - - - - - - - - #{user.enabled ? 'ACTIF' : 'INACTIF'} - - - - - - - - - - - - -
-
-
- - - - - -
- Username - -
-
- Email - -
-
- Prénom - -
-
- Nom - -
-
- Actif - -
- - -
- Mot de passe (Temporaire) - -
-
-
-
- - - - - -
- - - - - -
-
- + + + Gestion Utilisateurs + + + +
+ + + + + + + + + + + +
+ Utilisateurs + + + + + + +
+
+ + + + + + + + + + + + + + + + #{user.enabled ? 'ACTIF' : 'INACTIF'} + + + + + + + + + + + + +
+
+
+ + + + + +
+ Username + +
+
+ Email + +
+
+ Prénom + +
+
+ Nom + +
+
+ Actif + +
+ + +
+ Mot de passe (Temporaire) + +
+
+
+
+ + + + + +
+ + + + + +
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users/create.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users/create.xhtml index 2cb1bbb..726908e 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users/create.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users/create.xhtml @@ -1,272 +1,272 @@ - - - - - Nouvel Utilisateur - Lions User Manager - - -
- -
- - - - - - - - - Retour à la liste - - - -
- - - - - - -
-
- -
- Utilisateur créé avec succès ! -

- Vous pouvez créer un autre utilisateur ou retourner à la liste. -

-
- - Voir la liste - -
-
-
- -
-
-

- - Informations de l'Utilisateur -

- -
- -
-
-

- - Informations de Base -

- -
- - * - - - - - Identifiant unique de connexion -
- -
- - * - - - - -
- -
- - * - - - - -
- -
- - * - - - - -
-
-
- - -
-
-

- - Mot de Passe -

- -
- - * - - - - - Au moins 8 caractères -
- -
- - * - - -
-
- -
-

- - Configuration -

- -
- - - - -
- -
-
- - -
-
- - -
-
-
-
-
-
-
- - -
-
-
- - - - - - - - - -
- - -
- - - - -
-
-
-
- - - -
-
-

- - Informations Requises -

-
    -
  • Nom d'utilisateur : Identifiant unique (3-50 caractères)
  • -
  • Email : Adresse email valide
  • -
  • Prénom / Nom : Au moins 2 caractères chacun
  • -
  • Mot de passe : Au moins 8 caractères
  • -
- -

- - Sécurité -

-
    -
  • Le mot de passe doit contenir au moins 8 caractères
  • -
  • Utilisez une combinaison de lettres, chiffres et caractères spéciaux
  • -
  • L'utilisateur pourra modifier son mot de passe après la première connexion
  • -
- -

- - Configuration -

-
    -
  • Compte activé : L'utilisateur peut se connecter immédiatement
  • -
  • Email vérifié : L'email est considéré comme vérifié
  • -
  • Realm : Espace d'administration Keycloak
  • -
-
-
- - - - -
-
- -
+ + + + + Nouvel Utilisateur - Lions User Manager + + +
+ +
+ + + + + + + + + Retour à la liste + + + +
+ + + + + + +
+
+ +
+ Utilisateur créé avec succès ! +

+ Vous pouvez créer un autre utilisateur ou retourner à la liste. +

+
+ + Voir la liste + +
+
+
+ +
+
+

+ + Informations de l'Utilisateur +

+ +
+ +
+
+

+ + Informations de Base +

+ +
+ + * + + + + + Identifiant unique de connexion +
+ +
+ + * + + + + +
+ +
+ + * + + + + +
+ +
+ + * + + + + +
+
+
+ + +
+
+

+ + Mot de Passe +

+ +
+ + * + + + + + Au moins 8 caractères +
+ +
+ + * + + +
+
+ +
+

+ + Configuration +

+ +
+ + + + +
+ +
+
+ + +
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+ + + + + + + + + +
+ + +
+ + + + +
+
+
+
+ + + +
+
+

+ + Informations Requises +

+
    +
  • Nom d'utilisateur : Identifiant unique (3-50 caractères)
  • +
  • Email : Adresse email valide
  • +
  • Prénom / Nom : Au moins 2 caractères chacun
  • +
  • Mot de passe : Au moins 8 caractères
  • +
+ +

+ + Sécurité +

+
    +
  • Le mot de passe doit contenir au moins 8 caractères
  • +
  • Utilisez une combinaison de lettres, chiffres et caractères spéciaux
  • +
  • L'utilisateur pourra modifier son mot de passe après la première connexion
  • +
+ +

+ + Configuration +

+
    +
  • Compte activé : L'utilisateur peut se connecter immédiatement
  • +
  • Email vérifié : L'email est considéré comme vérifié
  • +
  • Realm : Espace d'administration Keycloak
  • +
+
+
+ + + + +
+
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users/edit.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users/edit.xhtml index c7fd547..23310e9 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users/edit.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users/edit.xhtml @@ -1,49 +1,49 @@ - - - - - - - - - - - Modifier Utilisateur - Lions User Manager - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - -
-
- + + + + + + + + + + + Modifier Utilisateur - Lions User Manager + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users/list.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users/list.xhtml index 53dc3e7..670800b 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users/list.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users/list.xhtml @@ -1,257 +1,259 @@ - - - - - Liste des Utilisateurs - Lions User Manager - - - - - - - - - -
- - -
-
-
-
- - - - - - - -
- - -
-
Statistiques des Utilisateurs
-
- - -
-
-
-
-
Total Utilisateurs
-
#{userListBean.kpiTotalUsers}
-
-
- -
-
-
- - Utilisateurs dans le realm -
-
-
- - -
-
-
-
-
Utilisateurs Actifs
-
#{userListBean.activeUsersCount}
-
-
- -
-
-
- - - #{userListBean.activeUsersPercentage}% - - Taux d'activation -
- -
-
- - -
-
-
-
-
Utilisateurs Désactivés
-
#{userListBean.disabledUsersCount}
-
-
- -
-
-
- - - #{userListBean.disabledUsersPercentage}% - - Taux de désactivation -
- -
-
- - -
-
-
-
-
Realm Actuel
-
- #{userListBean.realmName}
-
-
- -
-
-
- - Realm Keycloak -
-
-
- - -
-
-
- -
Recherche et Filtres
-
- -
-
- - - - -
- -
- - - - - -
- -
- - - - - - -
- -
- -
-
-
-
- - -
- - - - - - - - - - - - -
- - -
-
-
- -
Actions Rapides
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
-
-
- - - - -
-

- Importez des utilisateurs depuis un fichier CSV ou JSON. -

- -
- - -
-
-
-
-
- + + + + + Liste des Utilisateurs - Lions User Manager + + + + + + + + + +
+ + +
+
+
+
+ + + + + + + +
+ + +
+
Statistiques des Utilisateurs
+
+ + +
+
+
+
+
Total Utilisateurs
+
#{userListBean.kpiTotalUsers}
+
+
+ +
+
+
+ + Utilisateurs dans le realm +
+
+
+ + +
+
+
+
+
Utilisateurs Actifs
+
#{userListBean.activeUsersCount}
+
+
+ +
+
+
+ + + #{userListBean.activeUsersPercentage}% + + Taux d'activation +
+ +
+
+ + +
+
+
+
+
Utilisateurs Désactivés
+
#{userListBean.disabledUsersCount}
+
+
+ +
+
+
+ + + #{userListBean.disabledUsersPercentage}% + + Taux de désactivation +
+ +
+
+ + +
+
+
+
+
Realm Actuel
+
+ #{userListBean.realmName}
+
+
+ +
+
+
+ + Realm Keycloak +
+
+
+ + +
+
+
+ +
Recherche et Filtres
+
+ +
+
+ + + + +
+ +
+ + + + + +
+ +
+ + + + + + +
+ +
+ +
+
+
+
+ + +
+ + + + + + + + + + + + + + +
+ + +
+
+
+ +
Actions Rapides
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + + + +
+

+ Importez des utilisateurs depuis un fichier CSV ou JSON. +

+ +
+ + +
+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users/profile.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users/profile.xhtml index 4687bdc..ea534fd 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users/profile.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users/profile.xhtml @@ -1,411 +1,411 @@ - - - - - Mon Profil - Lions User Manager - - -
- -
-
-
-

- - Mon Profil -

- - - Retour au tableau de bord - -
-
-
- - -
-
-
- -
-
- -
- #{userSessionBean.initials} -
- - -

#{userSessionBean.fullName}

- - -

- - #{userSessionBean.email} -

- - -
- - - Connecté - -
- - -
- - #{userSessionBean.primaryRole} - -
-
-
- - -
-
- -
-

- - Informations Personnelles -

- -
- -

#{userSessionBean.username}

-
- -
- -

#{userSessionBean.fullName}

-
- -
- -
-

#{userSessionBean.email}

- -
-
- -
- -

#{userSessionBean.firstName}

-
- -
- -

#{userSessionBean.lastName}

-
-
- - -
-

- - Rôles et Permissions -

- -
- -
- - - -
-
- -
- -
- - -
-
- -
- -

- - - - - -

-
- -
- -
- -
-
-
-
-
-
-
-
- - -
-
-

- - Informations de Session OIDC -

- -
- -
-

Informations du Token

- -
- -

- #{userSessionBean.issuer} -

-
- -
- -

- #{userSessionBean.subject} -

-
- -
- -

- account -

-
- -
- -
- -
-
-
- - -
-

Détails de la Session

- -
- -
- -

- - - -

-
-
- -
- -
- -

- - - -

-
-
- -
- -
- -

- lions-user-manager -

-
-
- -
- -
- -

- Session active -

-
-
-
-
-
-
- - -
-
-

- - Statistiques d'Activité -

- -
-
-
-
- Connexions - -
-

--

- Total des connexions -
-
- -
-
-
- Dernière connexion - -
-

Aujourd'hui

- Session en cours -
-
- -
-
-
- Actions - -
-

--

- Actions effectuées -
-
- -
-
-
- Sessions - -
-

1

- Session active -
-
-
-
-
- - -
-
-

- - Actions Rapides -

- - -
- -
-
-

- - Gestion du Profil -

-
- - - - - - - - - - - -
-
-
- - -
-
-

- - Sessions et Sécurité -

-
- - - - - - - - - - - -
-
-
-
-
-
-
-
- - - - -
- -
+ + + + + Mon Profil - Lions User Manager + + +
+ +
+
+
+

+ + Mon Profil +

+ + + Retour au tableau de bord + +
+
+
+ + +
+
+
+ +
+
+ +
+ #{userSessionBean.initials} +
+ + +

#{userSessionBean.fullName}

+ + +

+ + #{userSessionBean.email} +

+ + +
+ + + Connecté + +
+ + +
+ + #{userSessionBean.primaryRole} + +
+
+
+ + +
+
+ +
+

+ + Informations Personnelles +

+ +
+ +

#{userSessionBean.username}

+
+ +
+ +

#{userSessionBean.fullName}

+
+ +
+ +
+

#{userSessionBean.email}

+ +
+
+ +
+ +

#{userSessionBean.firstName}

+
+ +
+ +

#{userSessionBean.lastName}

+
+
+ + +
+

+ + Rôles et Permissions +

+ +
+ +
+ + + +
+
+ +
+ +
+ + +
+
+ +
+ +

+ + + + + +

+
+ +
+ +
+ +
+
+
+
+
+
+
+
+ + +
+
+

+ + Informations de Session OIDC +

+ +
+ +
+

Informations du Token

+ +
+ +

+ #{userSessionBean.issuer} +

+
+ +
+ +

+ #{userSessionBean.subject} +

+
+ +
+ +

+ account +

+
+ +
+ +
+ +
+
+
+ + +
+

Détails de la Session

+ +
+ +
+ +

+ + + +

+
+
+ +
+ +
+ +

+ + + +

+
+
+ +
+ +
+ +

+ lions-user-manager +

+
+
+ +
+ +
+ +

+ Session active +

+
+
+
+
+
+
+ + +
+
+

+ + Statistiques d'Activité +

+ +
+
+
+
+ Connexions + +
+

--

+ Total des connexions +
+
+ +
+
+
+ Dernière connexion + +
+

Aujourd'hui

+ Session en cours +
+
+ +
+
+
+ Actions + +
+

--

+ Actions effectuées +
+
+ +
+
+
+ Sessions + +
+

1

+ Session active +
+
+
+
+
+ + +
+
+

+ + Actions Rapides +

+ + +
+ +
+
+

+ + Gestion du Profil +

+
+ + + + + + + + + + + +
+
+
+ + +
+
+

+ + Sessions et Sécurité +

+
+ + + + + + + + + + + +
+
+
+
+
+
+
+
+ + + + +
+ +
diff --git a/src/main/resources/META-INF/resources/pages/user-manager/users/view.xhtml b/src/main/resources/META-INF/resources/pages/user-manager/users/view.xhtml index 2b265ac..88565a7 100644 --- a/src/main/resources/META-INF/resources/pages/user-manager/users/view.xhtml +++ b/src/main/resources/META-INF/resources/pages/user-manager/users/view.xhtml @@ -1,458 +1,458 @@ - - - - - - - - - - Profil Utilisateur - Lions User Manager - - -
- -
-
-
-

- - Profil Utilisateur -

- - - Retour à la liste - -
-
-
- - - - - -
-
-
- -
-
- -
- #{userProfilBean.userInitials} -
- - -

- #{userProfilBean.user.prenom} #{userProfilBean.user.nom} -

- - -

@#{userProfilBean.user.username}

- - -

- - #{userProfilBean.user.email} - - - -

- - -
- - - - Actif - - - - - - Inactif - - -
- - -
- - #{userProfilBean.primaryRoleName} - -
-
-
- - -
-
- -
-

- - Informations Personnelles -

- -
- -

#{userProfilBean.user.username}

-
- -
- -

#{userProfilBean.user.prenom}

-
- -
- -

#{userProfilBean.user.nom}

-
- -
- -
-

#{userProfilBean.user.email}

- - - - - - -
-
- - -
- -

#{userProfilBean.user.telephone}

-
-
- - -
- -

#{userProfilBean.user.langue}

-
-
-
- - -
-

- - Rôles et Permissions -

- -
- -
- - - - - - - - Aucun rôle attribué - - -
-
- -
- -
- - -
-
- -
- -

#{userProfilBean.primaryRoleName}

-
- -
- -
- - - - - - -
-
-
-
-
-
-
-
- - -
-
-

- - Informations du Compte -

- -
-
-

Contact et Organisation

- - -
- -
- -

#{userProfilBean.user.organisation}

-
-
-
- - -
- -

#{userProfilBean.user.departement}

-
-
- - -
- -

#{userProfilBean.user.fonction}

-
-
- - -
- -
- -

#{userProfilBean.user.pays}

-
-
-
- - -
- -

#{userProfilBean.user.ville}

-
-
-
- -
-

Activité et Sécurité

- -
- -
- -

- #{userProfilBean.realmName} -

-
-
- - -
- -
- -

- - - -

-
-
-
- - -
- -
- -

#{userProfilBean.user.activeSessions}

-
-
-
- - -
- -
- - - -
-
-
-
-
-
-
- - -
-
-

- - Actions -

- - -
- -
-
-

- - Gestion du Profil -

-
- - - - - Modifier l'utilisateur - - - - - - - - -
-
-
- - -
-
-

- - Gestion du Compte -

-
- - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
- -

Utilisateur non trouvé

-

L'utilisateur demandé n'existe pas ou n'a pas pu être chargé.

- - - Retour à la liste - -
-
-
-
-
- - - - - - - - -
- -
+ + + + + + + + + + Profil Utilisateur - Lions User Manager + + +
+ +
+
+
+

+ + Profil Utilisateur +

+ + + Retour à la liste + +
+
+
+ + + + + +
+
+
+ +
+
+ +
+ #{userProfilBean.userInitials} +
+ + +

+ #{userProfilBean.user.prenom} #{userProfilBean.user.nom} +

+ + +

@#{userProfilBean.user.username}

+ + +

+ + #{userProfilBean.user.email} + + + +

+ + +
+ + + + Actif + + + + + + Inactif + + +
+ + +
+ + #{userProfilBean.primaryRoleName} + +
+
+
+ + +
+
+ +
+

+ + Informations Personnelles +

+ +
+ +

#{userProfilBean.user.username}

+
+ +
+ +

#{userProfilBean.user.prenom}

+
+ +
+ +

#{userProfilBean.user.nom}

+
+ +
+ +
+

#{userProfilBean.user.email}

+ + + + + + +
+
+ + +
+ +

#{userProfilBean.user.telephone}

+
+
+ + +
+ +

#{userProfilBean.user.langue}

+
+
+
+ + +
+

+ + Rôles et Permissions +

+ +
+ +
+ + + + + + + + Aucun rôle attribué + + +
+
+ +
+ +
+ + +
+
+ +
+ +

#{userProfilBean.primaryRoleName}

+
+ +
+ +
+ + + + + + +
+
+
+
+
+
+
+
+ + +
+
+

+ + Informations du Compte +

+ +
+
+

Contact et Organisation

+ + +
+ +
+ +

#{userProfilBean.user.organisation}

+
+
+
+ + +
+ +

#{userProfilBean.user.departement}

+
+
+ + +
+ +

#{userProfilBean.user.fonction}

+
+
+ + +
+ +
+ +

#{userProfilBean.user.pays}

+
+
+
+ + +
+ +

#{userProfilBean.user.ville}

+
+
+
+ +
+

Activité et Sécurité

+ +
+ +
+ +

+ #{userProfilBean.realmName} +

+
+
+ + +
+ +
+ +

+ + + +

+
+
+
+ + +
+ +
+ +

#{userProfilBean.user.activeSessions}

+
+
+
+ + +
+ +
+ + + +
+
+
+
+
+
+
+ + +
+
+

+ + Actions +

+ + +
+ +
+
+

+ + Gestion du Profil +

+
+ + + + + Modifier l'utilisateur + + + + + + + + +
+
+
+ + +
+
+

+ + Gestion du Compte +

+
+ + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+ +

Utilisateur non trouvé

+

L'utilisateur demandé n'existe pas ou n'a pas pu être chargé.

+ + + Retour à la liste + +
+
+
+
+
+ + + + + + + + +
+ +
diff --git a/src/main/resources/META-INF/resources/resources/components/user-action-dropdown.xhtml b/src/main/resources/META-INF/resources/resources/components/user-action-dropdown.xhtml index 1ae248a..1ddd08d 100644 --- a/src/main/resources/META-INF/resources/resources/components/user-action-dropdown.xhtml +++ b/src/main/resources/META-INF/resources/resources/components/user-action-dropdown.xhtml @@ -1,110 +1,110 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/resources/css/custom-topbar.css b/src/main/resources/META-INF/resources/resources/css/custom-topbar.css index aa01c86..9c36149 100644 --- a/src/main/resources/META-INF/resources/resources/css/custom-topbar.css +++ b/src/main/resources/META-INF/resources/resources/css/custom-topbar.css @@ -1,625 +1,625 @@ -/* ============================================================================ - Lions User Manager - Enhanced Custom Topbar Styles - - Auteur: Lions User Manager - Version: 2.0.0 - Description: Styles améliorés pour la topbar avec intégration intelligente - des patterns Freya layout pour un rendu parfait - - Intégrations: - - Freya Layout Variables & Patterns - - Support Dark/Light Theme - - Animations fluides (fadeInDown, modal-in) - - PrimeFlex utility classes - - Responsive design - ============================================================================ */ - -/* ---------------------------------------------------------------------------- - BASE TOPBAR LAYOUT OVERRIDES - Améliore la structure de base de la topbar Freya - ---------------------------------------------------------------------------- */ - -.layout-topbar { - position: fixed; - top: 0; - z-index: 999; - width: 100%; - height: 62px; - transition: width 0.2s, box-shadow 0.3s ease; -} - -.layout-topbar .layout-topbar-wrapper { - height: 100%; - display: flex; - align-items: center; -} - -.layout-topbar .layout-topbar-wrapper .layout-topbar-right { - height: 100%; - flex-grow: 1; - padding: 0 16px 0 12px; - display: flex; - align-items: center; - justify-content: space-between; -} - -.layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { - display: flex; - align-items: center; - justify-content: flex-end; - flex-grow: 1; - list-style-type: none; - margin: 0; - padding: 0; - height: 100%; -} - -.layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { - position: relative; - display: flex; - align-items: center; - justify-content: center; - height: 100%; -} - -/* ---------------------------------------------------------------------------- - USER PROFILE LINK - Enhanced with Freya patterns - ---------------------------------------------------------------------------- */ - -.layout-topbar .user-profile-link { - display: flex !important; - align-items: center; - gap: 0.75rem; - padding: 0.5rem 0.75rem; - border-radius: 6px; - transition: all 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); - text-decoration: none; - cursor: pointer; - position: relative; - overflow: hidden; -} - -.layout-topbar .user-profile-link::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05)); - opacity: 0; - transition: opacity 0.2s ease; -} - -.layout-topbar .user-profile-link:hover::before { - opacity: 1; -} - -.layout-topbar .user-profile-link:hover { - background-color: rgba(255, 255, 255, 0.12); - transform: translateY(-1px); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); -} - -/* User Avatar - Integration with Freya avatar patterns */ -.layout-topbar .user-profile-link .user-avatar { - width: 36px; - height: 36px; - border-radius: 50%; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - font-size: 14px; - font-weight: 600; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); - transition: transform 0.2s ease, box-shadow 0.2s ease; -} - -.layout-topbar .user-profile-link:hover .user-avatar { - transform: scale(1.05); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); -} - -/* User Info Container */ -.layout-topbar .user-info { - display: flex; - flex-direction: column; - align-items: flex-start; - line-height: 1.2; - min-width: 0; -} - -/* User Name - Enhanced typography */ -.layout-topbar .user-name { - font-weight: 600; - font-size: 0.875rem; - color: var(--text-color); - margin-bottom: 0.125rem; - display: flex; - align-items: center; - gap: 0.5rem; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 200px; -} - -/* User Email */ -.layout-topbar .user-email { - font-size: 0.75rem; - color: var(--text-color-secondary); - opacity: 0.85; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 200px; -} - -/* User Role Badge */ -.layout-topbar .user-role { - font-size: 0.7rem; - color: var(--primary-color); - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.6px; - background: rgba(var(--primary-color-rgb, 79, 142, 236), 0.1); - padding: 0.125rem 0.375rem; - border-radius: 4px; - white-space: nowrap; -} - -.layout-topbar .user-separator { - color: var(--text-color-secondary); - opacity: 0.5; - font-weight: 300; - margin: 0 0.25rem; -} - -/* Online Status Indicator */ -.layout-topbar .user-status { - width: 8px; - height: 8px; - border-radius: 50%; - display: inline-block; - position: relative; -} - -.layout-topbar .user-status.online { - background-color: #4CAF50; - box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3); - animation: pulse-online 2s ease-in-out infinite; -} - -@keyframes pulse-online { - 0%, 100% { - box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3); - } - 50% { - box-shadow: 0 0 0 4px rgba(76, 175, 80, 0.2); - } -} - -/* ---------------------------------------------------------------------------- - USER DROPDOWN MENU - Enhanced with Freya dropdown patterns - ---------------------------------------------------------------------------- */ - -.layout-topbar .user-dropdown-menu { - display: none; - position: absolute; - top: 62px; - right: 0; - min-width: 280px; - max-width: 320px; - padding: 0; - margin: 0; - list-style-type: none; - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08); - border: 1px solid var(--surface-border); - background: var(--surface-card); - overflow: hidden; - z-index: 1000; - animation-duration: 0.2s; - animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); - animation-fill-mode: forwards; -} - -/* Show dropdown when parent is active */ -.layout-topbar .user-profile.active-topmenuitem > .user-dropdown-menu { - display: block; - animation-name: fadeInDown; -} - -/* Dropdown Header - Integration with Freya gradient patterns */ -.user-dropdown-header { - padding: 1.25rem 1rem; - background: linear-gradient(135deg, var(--primary-color), var(--primary-600, #387FE9)); - color: white; - display: flex; - align-items: center; - gap: 0.75rem; - position: relative; - overflow: hidden; -} - -.user-dropdown-header::before { - content: ''; - position: absolute; - top: -50%; - right: -50%; - width: 200%; - height: 200%; - background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); - animation: shimmer 3s ease-in-out infinite; -} - -@keyframes shimmer { - 0%, 100% { transform: translate(0, 0); } - 50% { transform: translate(-20%, -20%); } -} - -/* Dropdown Avatar */ -.user-dropdown-avatar { - position: relative; - flex-shrink: 0; -} - -.user-dropdown-avatar > div { - width: 48px; - height: 48px; - border-radius: 50%; - border: 2px solid rgba(255, 255, 255, 0.3); - display: flex; - align-items: center; - justify-content: center; - font-size: 20px; - font-weight: 700; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); -} - -.user-status-indicator { - position: absolute; - bottom: 2px; - right: 2px; - width: 10px; - height: 10px; - border-radius: 50%; - border: 2px solid white; -} - -.user-status-indicator.online { - background-color: #4CAF50; - animation: pulse-indicator 2s ease-in-out infinite; -} - -@keyframes pulse-indicator { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.1); } -} - -/* Dropdown User Info */ -.user-dropdown-info { - flex: 1; - min-width: 0; -} - -.user-dropdown-name { - font-weight: 600; - font-size: 1rem; - margin-bottom: 0.25rem; - color: white; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.user-dropdown-email { - font-size: 0.875rem; - opacity: 0.95; - margin-bottom: 0.25rem; - color: rgba(255, 255, 255, 0.95); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.user-dropdown-role { - font-size: 0.75rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - background: rgba(255, 255, 255, 0.25); - padding: 0.25rem 0.5rem; - border-radius: 12px; - display: inline-block; - color: white; - backdrop-filter: blur(10px); -} - -/* Dividers */ -.user-dropdown-divider { - height: 1px; - background-color: var(--surface-border); - margin: 0; -} - -/* Menu Sections */ -.user-dropdown-section { - padding: 0.75rem 0; -} - -.section-title { - font-size: 0.75rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - color: var(--text-color-secondary); - padding: 0 1rem 0.5rem 1rem; - margin-bottom: 0.25rem; -} - -.section-items { - display: flex; - flex-direction: column; -} - -/* Dropdown Items - Enhanced with Freya interaction patterns */ -.dropdown-item { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.75rem 1rem; - color: var(--text-color); - text-decoration: none; - transition: all 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); - border: none; - background: none; - width: 100%; - text-align: left; - cursor: pointer; - font-size: 0.875rem; - font-weight: 500; - position: relative; - overflow: hidden; -} - -.dropdown-item::before { - content: ''; - position: absolute; - left: 0; - top: 0; - width: 3px; - height: 100%; - background: var(--primary-color); - transform: scaleX(0); - transition: transform 0.2s ease; -} - -.dropdown-item:hover::before { - transform: scaleX(1); -} - -.dropdown-item:hover { - background-color: var(--surface-hover); - color: var(--primary-color); - padding-left: 1.25rem; -} - -.dropdown-item:active { - background-color: var(--surface-ground); - transform: scale(0.98); -} - -.dropdown-item i { - width: 1.25rem; - text-align: center; - color: var(--text-color-secondary); - transition: all 0.2s ease; - font-size: 1rem; -} - -.dropdown-item:hover i { - color: var(--primary-color); - transform: scale(1.1); -} - -.dropdown-item span { - flex: 1; -} - -.item-arrow { - margin-left: auto; - opacity: 0; - transition: opacity 0.2s ease, transform 0.2s ease; - font-size: 0.75rem; -} - -.dropdown-item:hover .item-arrow { - opacity: 1; - transform: translateX(4px); -} - -/* Logout Item - Enhanced danger state */ -.logout-item { - color: var(--red-500) !important; - margin-top: 0.25rem; -} - -.logout-item:hover { - background-color: var(--red-50) !important; - color: var(--red-600) !important; -} - -.logout-item i { - color: var(--red-500) !important; -} - -.logout-item:hover i { - color: var(--red-600) !important; - transform: scale(1.1) rotate(-5deg); -} - -/* ---------------------------------------------------------------------------- - ANIMATIONS - Integration with Freya animation patterns - ---------------------------------------------------------------------------- */ - -@keyframes dropdownFadeIn { - 0% { - opacity: 0; - transform: translateY(-10px) scale(0.95); - } - 100% { - opacity: 1; - transform: translateY(0) scale(1); - } -} - -.user-dropdown-menu { - animation: dropdownFadeIn 0.3s ease-out; - transform-origin: top right; -} - -/* ---------------------------------------------------------------------------- - DARK MODE SUPPORT - Integration with Freya dark theme - ---------------------------------------------------------------------------- */ - -.layout-wrapper.layout-topbar-dark .layout-topbar { - background-color: #293241; - box-shadow: 0 10px 40px 0 rgba(0, 0, 0, 0.2); -} - -.layout-wrapper.layout-topbar-dark .user-profile-link:hover { - background-color: rgba(255, 255, 255, 0.08); -} - -.layout-wrapper.layout-topbar-dark .user-dropdown-menu { - background: var(--surface-900, #1E1E1E); - border-color: var(--surface-700, #383838); - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3); -} - -.layout-wrapper.layout-topbar-dark .user-dropdown-divider { - background-color: var(--surface-700, #383838); -} - -.layout-wrapper.layout-topbar-dark .section-title { - color: var(--text-color-secondary); - opacity: 0.8; -} - -.layout-wrapper.layout-topbar-dark .dropdown-item { - color: var(--text-color); -} - -.layout-wrapper.layout-topbar-dark .dropdown-item:hover { - background-color: var(--surface-800, #2A2A2A); -} - -.layout-wrapper.layout-topbar-dark .logout-item:hover { - background-color: rgba(211, 47, 47, 0.1) !important; -} - -/* ---------------------------------------------------------------------------- - RESPONSIVE DESIGN - Integration with Freya responsive patterns - ---------------------------------------------------------------------------- */ - -@media (max-width: 991px) { - .layout-topbar .user-dropdown-menu { - left: 10px; - right: 10px; - position: fixed; - top: 62px; - max-width: none; - } -} - -@media (max-width: 768px) { - .layout-topbar .user-dropdown-menu { - min-width: 260px; - max-width: 280px; - } - - .user-dropdown-header { - padding: 1rem 0.75rem; - } - - .dropdown-item { - padding: 0.625rem 0.75rem; - font-size: 0.8125rem; - } - - .section-title { - padding: 0 0.75rem 0.5rem 0.75rem; - } - - /* Hide user info on mobile */ - .layout-topbar .user-info { - display: none; - } - - .layout-topbar .user-profile-link { - padding: 0.5rem; - } -} - -@media (max-width: 576px) { - .layout-topbar .user-dropdown-menu { - left: 8px; - right: 8px; - border-radius: 12px; - } -} - -/* ---------------------------------------------------------------------------- - ACCESSIBILITY ENHANCEMENTS - ---------------------------------------------------------------------------- */ - -.dropdown-item:focus, -.user-profile-link:focus { - outline: 2px solid var(--primary-color); - outline-offset: 2px; -} - -@media (prefers-reduced-motion: reduce) { - .layout-topbar .user-profile-link, - .dropdown-item, - .user-dropdown-menu, - .user-avatar, - .item-arrow { - animation: none; - transition: none; - } -} - -/* ---------------------------------------------------------------------------- - UTILITY CLASSES - PrimeFlex integration - ---------------------------------------------------------------------------- */ - -.layout-topbar .flex { - display: flex !important; -} - -.layout-topbar .align-items-center { - align-items: center !important; -} - -.layout-topbar .justify-content-center { - justify-content: center !important; -} - -.layout-topbar .gap-2 { - gap: 0.5rem !important; -} - -.layout-topbar .text-white { - color: white !important; -} - -.layout-topbar .border-circle { - border-radius: 50% !important; -} - -.layout-topbar .bg-primary { - background-color: var(--primary-color) !important; -} +/* ============================================================================ + Lions User Manager - Enhanced Custom Topbar Styles + + Auteur: Lions User Manager + Version: 2.0.0 + Description: Styles améliorés pour la topbar avec intégration intelligente + des patterns Freya layout pour un rendu parfait + + Intégrations: + - Freya Layout Variables & Patterns + - Support Dark/Light Theme + - Animations fluides (fadeInDown, modal-in) + - PrimeFlex utility classes + - Responsive design + ============================================================================ */ + +/* ---------------------------------------------------------------------------- + BASE TOPBAR LAYOUT OVERRIDES + Améliore la structure de base de la topbar Freya + ---------------------------------------------------------------------------- */ + +.layout-topbar { + position: fixed; + top: 0; + z-index: 999; + width: 100%; + height: 62px; + transition: width 0.2s, box-shadow 0.3s ease; +} + +.layout-topbar .layout-topbar-wrapper { + height: 100%; + display: flex; + align-items: center; +} + +.layout-topbar .layout-topbar-wrapper .layout-topbar-right { + height: 100%; + flex-grow: 1; + padding: 0 16px 0 12px; + display: flex; + align-items: center; + justify-content: space-between; +} + +.layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { + display: flex; + align-items: center; + justify-content: flex-end; + flex-grow: 1; + list-style-type: none; + margin: 0; + padding: 0; + height: 100%; +} + +.layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { + position: relative; + display: flex; + align-items: center; + justify-content: center; + height: 100%; +} + +/* ---------------------------------------------------------------------------- + USER PROFILE LINK - Enhanced with Freya patterns + ---------------------------------------------------------------------------- */ + +.layout-topbar .user-profile-link { + display: flex !important; + align-items: center; + gap: 0.75rem; + padding: 0.5rem 0.75rem; + border-radius: 6px; + transition: all 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); + text-decoration: none; + cursor: pointer; + position: relative; + overflow: hidden; +} + +.layout-topbar .user-profile-link::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05)); + opacity: 0; + transition: opacity 0.2s ease; +} + +.layout-topbar .user-profile-link:hover::before { + opacity: 1; +} + +.layout-topbar .user-profile-link:hover { + background-color: rgba(255, 255, 255, 0.12); + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +/* User Avatar - Integration with Freya avatar patterns */ +.layout-topbar .user-profile-link .user-avatar { + width: 36px; + height: 36px; + border-radius: 50%; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 14px; + font-weight: 600; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.layout-topbar .user-profile-link:hover .user-avatar { + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +/* User Info Container */ +.layout-topbar .user-info { + display: flex; + flex-direction: column; + align-items: flex-start; + line-height: 1.2; + min-width: 0; +} + +/* User Name - Enhanced typography */ +.layout-topbar .user-name { + font-weight: 600; + font-size: 0.875rem; + color: var(--text-color); + margin-bottom: 0.125rem; + display: flex; + align-items: center; + gap: 0.5rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; +} + +/* User Email */ +.layout-topbar .user-email { + font-size: 0.75rem; + color: var(--text-color-secondary); + opacity: 0.85; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; +} + +/* User Role Badge */ +.layout-topbar .user-role { + font-size: 0.7rem; + color: var(--primary-color); + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.6px; + background: rgba(var(--primary-color-rgb, 79, 142, 236), 0.1); + padding: 0.125rem 0.375rem; + border-radius: 4px; + white-space: nowrap; +} + +.layout-topbar .user-separator { + color: var(--text-color-secondary); + opacity: 0.5; + font-weight: 300; + margin: 0 0.25rem; +} + +/* Online Status Indicator */ +.layout-topbar .user-status { + width: 8px; + height: 8px; + border-radius: 50%; + display: inline-block; + position: relative; +} + +.layout-topbar .user-status.online { + background-color: #4CAF50; + box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3); + animation: pulse-online 2s ease-in-out infinite; +} + +@keyframes pulse-online { + 0%, 100% { + box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.3); + } + 50% { + box-shadow: 0 0 0 4px rgba(76, 175, 80, 0.2); + } +} + +/* ---------------------------------------------------------------------------- + USER DROPDOWN MENU - Enhanced with Freya dropdown patterns + ---------------------------------------------------------------------------- */ + +.layout-topbar .user-dropdown-menu { + display: none; + position: absolute; + top: 62px; + right: 0; + min-width: 280px; + max-width: 320px; + padding: 0; + margin: 0; + list-style-type: none; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 6px rgba(0, 0, 0, 0.08); + border: 1px solid var(--surface-border); + background: var(--surface-card); + overflow: hidden; + z-index: 1000; + animation-duration: 0.2s; + animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); + animation-fill-mode: forwards; +} + +/* Show dropdown when parent is active */ +.layout-topbar .user-profile.active-topmenuitem > .user-dropdown-menu { + display: block; + animation-name: fadeInDown; +} + +/* Dropdown Header - Integration with Freya gradient patterns */ +.user-dropdown-header { + padding: 1.25rem 1rem; + background: linear-gradient(135deg, var(--primary-color), var(--primary-600, #387FE9)); + color: white; + display: flex; + align-items: center; + gap: 0.75rem; + position: relative; + overflow: hidden; +} + +.user-dropdown-header::before { + content: ''; + position: absolute; + top: -50%; + right: -50%; + width: 200%; + height: 200%; + background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%); + animation: shimmer 3s ease-in-out infinite; +} + +@keyframes shimmer { + 0%, 100% { transform: translate(0, 0); } + 50% { transform: translate(-20%, -20%); } +} + +/* Dropdown Avatar */ +.user-dropdown-avatar { + position: relative; + flex-shrink: 0; +} + +.user-dropdown-avatar > div { + width: 48px; + height: 48px; + border-radius: 50%; + border: 2px solid rgba(255, 255, 255, 0.3); + display: flex; + align-items: center; + justify-content: center; + font-size: 20px; + font-weight: 700; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.user-status-indicator { + position: absolute; + bottom: 2px; + right: 2px; + width: 10px; + height: 10px; + border-radius: 50%; + border: 2px solid white; +} + +.user-status-indicator.online { + background-color: #4CAF50; + animation: pulse-indicator 2s ease-in-out infinite; +} + +@keyframes pulse-indicator { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.1); } +} + +/* Dropdown User Info */ +.user-dropdown-info { + flex: 1; + min-width: 0; +} + +.user-dropdown-name { + font-weight: 600; + font-size: 1rem; + margin-bottom: 0.25rem; + color: white; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.user-dropdown-email { + font-size: 0.875rem; + opacity: 0.95; + margin-bottom: 0.25rem; + color: rgba(255, 255, 255, 0.95); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.user-dropdown-role { + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + background: rgba(255, 255, 255, 0.25); + padding: 0.25rem 0.5rem; + border-radius: 12px; + display: inline-block; + color: white; + backdrop-filter: blur(10px); +} + +/* Dividers */ +.user-dropdown-divider { + height: 1px; + background-color: var(--surface-border); + margin: 0; +} + +/* Menu Sections */ +.user-dropdown-section { + padding: 0.75rem 0; +} + +.section-title { + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + color: var(--text-color-secondary); + padding: 0 1rem 0.5rem 1rem; + margin-bottom: 0.25rem; +} + +.section-items { + display: flex; + flex-direction: column; +} + +/* Dropdown Items - Enhanced with Freya interaction patterns */ +.dropdown-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + color: var(--text-color); + text-decoration: none; + transition: all 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); + border: none; + background: none; + width: 100%; + text-align: left; + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + position: relative; + overflow: hidden; +} + +.dropdown-item::before { + content: ''; + position: absolute; + left: 0; + top: 0; + width: 3px; + height: 100%; + background: var(--primary-color); + transform: scaleX(0); + transition: transform 0.2s ease; +} + +.dropdown-item:hover::before { + transform: scaleX(1); +} + +.dropdown-item:hover { + background-color: var(--surface-hover); + color: var(--primary-color); + padding-left: 1.25rem; +} + +.dropdown-item:active { + background-color: var(--surface-ground); + transform: scale(0.98); +} + +.dropdown-item i { + width: 1.25rem; + text-align: center; + color: var(--text-color-secondary); + transition: all 0.2s ease; + font-size: 1rem; +} + +.dropdown-item:hover i { + color: var(--primary-color); + transform: scale(1.1); +} + +.dropdown-item span { + flex: 1; +} + +.item-arrow { + margin-left: auto; + opacity: 0; + transition: opacity 0.2s ease, transform 0.2s ease; + font-size: 0.75rem; +} + +.dropdown-item:hover .item-arrow { + opacity: 1; + transform: translateX(4px); +} + +/* Logout Item - Enhanced danger state */ +.logout-item { + color: var(--red-500) !important; + margin-top: 0.25rem; +} + +.logout-item:hover { + background-color: var(--red-50) !important; + color: var(--red-600) !important; +} + +.logout-item i { + color: var(--red-500) !important; +} + +.logout-item:hover i { + color: var(--red-600) !important; + transform: scale(1.1) rotate(-5deg); +} + +/* ---------------------------------------------------------------------------- + ANIMATIONS - Integration with Freya animation patterns + ---------------------------------------------------------------------------- */ + +@keyframes dropdownFadeIn { + 0% { + opacity: 0; + transform: translateY(-10px) scale(0.95); + } + 100% { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.user-dropdown-menu { + animation: dropdownFadeIn 0.3s ease-out; + transform-origin: top right; +} + +/* ---------------------------------------------------------------------------- + DARK MODE SUPPORT - Integration with Freya dark theme + ---------------------------------------------------------------------------- */ + +.layout-wrapper.layout-topbar-dark .layout-topbar { + background-color: #293241; + box-shadow: 0 10px 40px 0 rgba(0, 0, 0, 0.2); +} + +.layout-wrapper.layout-topbar-dark .user-profile-link:hover { + background-color: rgba(255, 255, 255, 0.08); +} + +.layout-wrapper.layout-topbar-dark .user-dropdown-menu { + background: var(--surface-900, #1E1E1E); + border-color: var(--surface-700, #383838); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3); +} + +.layout-wrapper.layout-topbar-dark .user-dropdown-divider { + background-color: var(--surface-700, #383838); +} + +.layout-wrapper.layout-topbar-dark .section-title { + color: var(--text-color-secondary); + opacity: 0.8; +} + +.layout-wrapper.layout-topbar-dark .dropdown-item { + color: var(--text-color); +} + +.layout-wrapper.layout-topbar-dark .dropdown-item:hover { + background-color: var(--surface-800, #2A2A2A); +} + +.layout-wrapper.layout-topbar-dark .logout-item:hover { + background-color: rgba(211, 47, 47, 0.1) !important; +} + +/* ---------------------------------------------------------------------------- + RESPONSIVE DESIGN - Integration with Freya responsive patterns + ---------------------------------------------------------------------------- */ + +@media (max-width: 991px) { + .layout-topbar .user-dropdown-menu { + left: 10px; + right: 10px; + position: fixed; + top: 62px; + max-width: none; + } +} + +@media (max-width: 768px) { + .layout-topbar .user-dropdown-menu { + min-width: 260px; + max-width: 280px; + } + + .user-dropdown-header { + padding: 1rem 0.75rem; + } + + .dropdown-item { + padding: 0.625rem 0.75rem; + font-size: 0.8125rem; + } + + .section-title { + padding: 0 0.75rem 0.5rem 0.75rem; + } + + /* Hide user info on mobile */ + .layout-topbar .user-info { + display: none; + } + + .layout-topbar .user-profile-link { + padding: 0.5rem; + } +} + +@media (max-width: 576px) { + .layout-topbar .user-dropdown-menu { + left: 8px; + right: 8px; + border-radius: 12px; + } +} + +/* ---------------------------------------------------------------------------- + ACCESSIBILITY ENHANCEMENTS + ---------------------------------------------------------------------------- */ + +.dropdown-item:focus, +.user-profile-link:focus { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +@media (prefers-reduced-motion: reduce) { + .layout-topbar .user-profile-link, + .dropdown-item, + .user-dropdown-menu, + .user-avatar, + .item-arrow { + animation: none; + transition: none; + } +} + +/* ---------------------------------------------------------------------------- + UTILITY CLASSES - PrimeFlex integration + ---------------------------------------------------------------------------- */ + +.layout-topbar .flex { + display: flex !important; +} + +.layout-topbar .align-items-center { + align-items: center !important; +} + +.layout-topbar .justify-content-center { + justify-content: center !important; +} + +.layout-topbar .gap-2 { + gap: 0.5rem !important; +} + +.layout-topbar .text-white { + color: white !important; +} + +.layout-topbar .border-circle { + border-radius: 50% !important; +} + +.layout-topbar .bg-primary { + background-color: var(--primary-color) !important; +} diff --git a/src/main/resources/META-INF/resources/resources/css/topbar-elite.css b/src/main/resources/META-INF/resources/resources/css/topbar-elite.css index f257f28..786a963 100644 --- a/src/main/resources/META-INF/resources/resources/css/topbar-elite.css +++ b/src/main/resources/META-INF/resources/resources/css/topbar-elite.css @@ -1,795 +1,795 @@ -/* - * ╔════════════════════════════════════════════════════════════╗ - * ║ Lions Platform Elite Topbar Styles (Freya Design System) ║ - * ║ Modern, Professional, Responsive ║ - * ╚════════════════════════════════════════════════════════════╝ - */ - -/* ═══════════════════════════════════════════════════════════ */ -/* BASE TOPBAR */ -/* ═══════════════════════════════════════════════════════════ */ - -.unionflow-elite, -.lions-elite { - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-600) 100%); - box-shadow: 0 2px 12px rgba(0,0,0,0.08); - position: relative; - z-index: 1000; -} - -.unionflow-elite::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - right: 0; - height: 2px; - background: linear-gradient(90deg, - transparent 0%, - var(--primary-300) 50%, - transparent 100%); - opacity: 0.5; -} - -/* App Version Badge */ -.app-version { - display: inline-flex; - align-items: center; - padding: 0.25rem 0.625rem; - background: rgba(255,255,255,0.15); - border-radius: 12px; - font-size: 0.75rem; - font-weight: 600; - color: rgba(255,255,255,0.9); - margin-left: 0.75rem; - backdrop-filter: blur(10px); - border: 1px solid rgba(255,255,255,0.2); -} - -/* ═══════════════════════════════════════════════════════════ */ -/* SEARCH */ -/* ═══════════════════════════════════════════════════════════ */ - -.search-item .topbar-icon { - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); -} - -.search-item:hover .topbar-icon { - transform: scale(1.1); - color: var(--primary-100); -} - -.search-dropdown { - position: absolute; - top: calc(100% + 0.5rem); - right: 0; - min-width: 400px; - background: white; - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0,0,0,0.12); - padding: 1rem; - opacity: 0; - visibility: hidden; - transform: translateY(-10px); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid var(--surface-border); -} - -.search-item:hover .search-dropdown { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -.search-wrapper-elite { - display: flex; - align-items: center; - gap: 0.75rem; - background: var(--surface-50); - border-radius: 8px; - padding: 0.5rem 1rem; - border: 1px solid var(--surface-border); - transition: all 0.3s ease; -} - -.search-wrapper-elite:focus-within { - background: white; - border-color: var(--primary-color); - box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1); -} - -.search-wrapper-elite .pi-search { - color: var(--text-color-secondary); - font-size: 1rem; -} - -.search-wrapper-elite .search-input { - flex: 1; - border: none; - background: transparent; - padding: 0.5rem 0; - font-size: 0.875rem; -} - -.search-wrapper-elite .search-input:focus { - outline: none; - box-shadow: none; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* NOTIFICATIONS */ -/* ═══════════════════════════════════════════════════════════ */ - -.notifications-item { - position: relative; -} - -.badge-count { - position: absolute; - top: -4px; - right: -4px; - background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); - color: white; - font-size: 0.625rem; - font-weight: 700; - padding: 0.125rem 0.375rem; - border-radius: 10px; - min-width: 18px; - height: 18px; - display: flex; - align-items: center; - justify-content: center; - box-shadow: 0 2px 8px rgba(239, 68, 68, 0.4); - animation: pulse-badge 2s infinite; -} - -@keyframes pulse-badge { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.1); } -} - -.notifications-dropdown { - position: absolute; - top: calc(100% + 0.5rem); - right: 0; - min-width: 360px; - max-width: 400px; - background: white; - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0,0,0,0.12); - opacity: 0; - visibility: hidden; - transform: translateY(-10px); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid var(--surface-border); - overflow: hidden; -} - -.notifications-item:hover .notifications-dropdown { - opacity: 1; - visibility: visible; - transform: translateY(0); -} - -.notif-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 1rem 1.25rem; - background: var(--surface-50); - border-bottom: 1px solid var(--surface-border); -} - -.count-label { - font-size: 0.75rem; - color: var(--text-color-secondary); - background: var(--primary-color); - color: white; - padding: 0.25rem 0.625rem; - border-radius: 12px; - font-weight: 600; -} - -.notif-item { - display: flex; - align-items: flex-start; - gap: 0.875rem; - padding: 0.875rem 1.25rem; - transition: all 0.2s ease; - cursor: pointer; -} - -.notif-item:hover { - background: var(--surface-50); -} - -.notif-item i { - font-size: 1.25rem; - margin-top: 0.25rem; -} - -.notif-title { - font-weight: 600; - color: var(--text-color); - font-size: 0.875rem; - margin-bottom: 0.25rem; -} - -.notif-time { - font-size: 0.75rem; - color: var(--text-color-secondary); -} - -.notif-footer { - padding: 0.75rem 1.25rem; - text-align: center; - border-top: 1px solid var(--surface-border); - background: var(--surface-50); -} - -.notif-footer a { - font-size: 0.875rem; - font-weight: 600; - text-decoration: none; - transition: color 0.2s ease; -} - -.notif-footer a:hover { - color: var(--primary-600); -} - -/* ═══════════════════════════════════════════════════════════ */ -/* USER PROFILE */ -/* ═══════════════════════════════════════════════════════════ */ - -.elite-user .profile-trigger { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.5rem 0.875rem; - border-radius: 10px; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - background: rgba(255,255,255,0.1); - backdrop-filter: blur(10px); -} - -.elite-user .profile-trigger:hover { - background: rgba(255,255,255,0.2); - transform: translateY(-1px); -} - -.avatar-container { - position: relative; -} - -.avatar { - width: 38px; - height: 38px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 0.875rem; - font-weight: 700; - color: white; - box-shadow: 0 4px 12px rgba(0,0,0,0.15); - border: 2px solid rgba(255,255,255,0.3); -} - -.bg-gradient-primary { - background: linear-gradient(135deg, var(--primary-400) 0%, var(--primary-600) 100%); -} - -.status-dot { - position: absolute; - bottom: 0; - right: 0; - width: 10px; - height: 10px; - border-radius: 50%; - border: 2px solid white; -} - -.status-dot.online { - background: linear-gradient(135deg, #10b981 0%, #059669 100%); - box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2); - animation: pulse-dot 2s infinite; -} - -@keyframes pulse-dot { - 0%, 100% { box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2); } - 50% { box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.4); } -} - -.user-info { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -.user-header { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.user-name { - font-size: 0.875rem; - font-weight: 600; - color: white; - line-height: 1.2; -} - -.role-badge { - font-size: 0.625rem; - padding: 0.125rem 0.5rem; - background: rgba(255,255,255,0.25); - border-radius: 8px; - font-weight: 600; - color: white; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.session-timer { - display: flex; - align-items: center; - gap: 0.375rem; -} - -.icon-sm { - font-size: 0.7rem; -} - -.timer-text { - font-size: 0.75rem; - font-weight: 600; - font-family: 'Courier New', monospace; -} - -.arrow { - font-size: 0.75rem; - color: rgba(255,255,255,0.8); - transition: transform 0.3s ease; -} - -.elite-user:hover .arrow { - transform: rotate(180deg); -} - -/* ═══════════════════════════════════════════════════════════ */ -/* USER DROPDOWN MENU */ -/* ═══════════════════════════════════════════════════════════ */ - -.elite-dropdown { - position: absolute; - top: calc(100% + 0.5rem); - right: 0; - min-width: 340px; - background: white; - border-radius: 16px; - box-shadow: 0 12px 48px rgba(0,0,0,0.15); - opacity: 0; - visibility: hidden; - transform: translateY(-10px) scale(0.95); - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid var(--surface-border); - overflow: hidden; -} - -.elite-user:hover .elite-dropdown { - opacity: 1; - visibility: visible; - transform: translateY(0) scale(1); -} - -/* Dropdown Header */ -.dropdown-header { - padding: 1.25rem; - background: linear-gradient(135deg, var(--primary-50) 0%, var(--surface-50) 100%); - border-bottom: 1px solid var(--surface-border); -} - -.header-content { - display: flex; - gap: 1rem; -} - -.header-avatar { - position: relative; -} - -.avatar-lg { - width: 56px; - height: 56px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.25rem; - font-weight: 700; - color: white; - box-shadow: 0 6px 16px rgba(0,0,0,0.15); -} - -.status-indicator { - position: absolute; - bottom: 2px; - right: 2px; - width: 14px; - height: 14px; - border-radius: 50%; - border: 3px solid white; - display: flex; - align-items: center; - justify-content: center; -} - -.status-indicator.online { - background: linear-gradient(135deg, #10b981 0%, #059669 100%); -} - -.status-indicator i { - font-size: 6px; - color: white; -} - -.header-info { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.25rem; - justify-content: center; -} - -.header-info .name { - font-size: 1rem; - font-weight: 700; - color: var(--text-color); - line-height: 1.3; -} - -.header-info .email { - font-size: 0.75rem; - color: var(--text-color-secondary); - line-height: 1.3; -} - -.role-tag { - display: inline-flex; - align-items: center; - font-size: 0.625rem; - padding: 0.25rem 0.625rem; - background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-600) 100%); - color: white; - border-radius: 8px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.5px; - align-self: flex-start; - margin-top: 0.25rem; -} - -/* Session Card */ -.session-card { - padding: 1rem 1.25rem; - background: var(--surface-50); - border-bottom: 1px solid var(--surface-border); -} - -.card-content { - display: flex; - flex-direction: column; - gap: 0.625rem; -} - -.info-row { - display: flex; - justify-content: space-between; - align-items: center; -} - -.info-row .label { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.75rem; - color: var(--text-color-secondary); - font-weight: 500; -} - -.info-row .label i { - font-size: 0.875rem; -} - -.info-row .value { - font-size: 0.875rem; - font-weight: 600; - color: var(--text-color); -} - -/* Progress Bar */ -.progress-container { - margin-top: 0.5rem; -} - -.progress-bar { - height: 6px; - background: var(--surface-200); - border-radius: 10px; - overflow: hidden; - position: relative; -} - -.progress-fill { - height: 100%; - background: linear-gradient(90deg, var(--green-400) 0%, var(--green-500) 100%); - border-radius: 10px; - transition: width 1s ease, background 0.3s ease; -} - -.progress-fill[style*="width: 0%"], -.progress-fill[style*="width: 1%"], -.progress-fill[style*="width: 2%"], -.progress-fill[style*="width: 3%"], -.progress-fill[style*="width: 4%"], -.progress-fill[style*="width: 5%"] { - background: linear-gradient(90deg, var(--red-400) 0%, var(--red-500) 100%); -} - -.progress-label { - font-size: 0.625rem; - color: var(--text-color-secondary); - margin-top: 0.375rem; - text-align: right; - font-weight: 500; -} - -/* Menu Sections */ -.divider { - height: 1px; - background: var(--surface-border); - margin: 0; -} - -.menu-section { - padding: 0.75rem 0; -} - -.menu-section.compact { - padding: 0.5rem 0; -} - -.section-title { - display: flex; - align-items: center; - gap: 0.5rem; - font-size: 0.75rem; - font-weight: 700; - color: var(--text-color-secondary); - text-transform: uppercase; - letter-spacing: 0.5px; - padding: 0.5rem 1.25rem 0.75rem; -} - -.section-items { - display: flex; - flex-direction: column; -} - -.menu-item { - display: flex; - align-items: center; - gap: 0.875rem; - padding: 0.75rem 1.25rem; - color: var(--text-color); - text-decoration: none; - transition: all 0.2s ease; - font-size: 0.875rem; - cursor: pointer; - border: none; - background: transparent; - width: 100%; - text-align: left; -} - -.menu-item:hover { - background: var(--surface-100); -} - -.menu-item i:first-child { - font-size: 1rem; - color: var(--text-color-secondary); - transition: all 0.2s ease; -} - -.menu-item:hover i:first-child { - color: var(--primary-color); - transform: translateX(2px); -} - -.menu-item span { - flex: 1; - font-weight: 500; -} - -.arrow-right { - font-size: 0.75rem; - color: var(--text-color-secondary); - margin-left: auto; - transition: transform 0.2s ease; -} - -.menu-item:hover .arrow-right { - transform: translateX(3px); -} - -.item-badge { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 20px; - height: 20px; - padding: 0 0.375rem; - background: var(--primary-color); - color: white; - font-size: 0.625rem; - font-weight: 700; - border-radius: 10px; - margin-left: auto; -} - -.value-badge { - font-size: 0.75rem; - color: var(--text-color-secondary); - background: var(--surface-100); - padding: 0.25rem 0.625rem; - border-radius: 8px; - font-weight: 600; - margin-left: auto; -} - -/* Logout Section */ -.logout-divider { - background: linear-gradient(90deg, - transparent 0%, - var(--red-200) 50%, - transparent 100%); - height: 2px; -} - -.logout-section { - padding: 0.75rem 0; - background: linear-gradient(to bottom, white 0%, var(--red-50) 100%); -} - -.logout-btn { - display: flex; - align-items: center; - gap: 0.875rem; - padding: 0.875rem 1.25rem; - color: var(--red-600); - font-weight: 600; - font-size: 0.875rem; - text-decoration: none; - transition: all 0.3s ease; - cursor: pointer; - border: none; - background: transparent; - width: 100%; - text-align: left; -} - -.logout-btn:hover { - background: var(--red-100); - color: var(--red-700); -} - -.logout-btn i:first-child { - font-size: 1rem; - transition: transform 0.3s ease; -} - -.logout-btn:hover i:first-child { - transform: scale(1.1) rotate(-10deg); -} - -.logout-btn .pi-lock { - font-size: 0.875rem; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* LOGOUT DIALOG */ -/* ═══════════════════════════════════════════════════════════ */ - -.elite-dialog .dialog-content { - text-align: center; - padding: 1.5rem 1rem; -} - -.icon-wrapper { - display: inline-flex; - align-items: center; - justify-content: center; - width: 80px; - height: 80px; - border-radius: 50%; - background: linear-gradient(135deg, var(--red-50) 0%, var(--red-100) 100%); - margin-bottom: 1.5rem; -} - -.icon-lg { - font-size: 2.5rem; - color: var(--red-500); -} - -.dialog-title { - font-size: 1.25rem; - font-weight: 700; - color: var(--text-color); - margin-bottom: 1.5rem; - line-height: 1.4; -} - -.info-box { - background: var(--surface-50); - border-radius: 12px; - padding: 1rem; - margin-bottom: 1rem; - border: 1px solid var(--surface-border); -} - -.info-item { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 0.625rem; - color: var(--text-color); - font-size: 0.875rem; -} - -.info-item i { - color: var(--primary-color); - font-size: 1rem; -} - -.warning-text { - display: flex; - align-items: center; - justify-content: center; - gap: 0.5rem; - font-size: 0.875rem; - color: var(--text-color-secondary); - margin: 0; -} - -.warning-text i { - color: var(--blue-500); -} - -.dialog-footer { - display: flex; - gap: 0.75rem; - justify-content: flex-end; - padding-top: 1rem; -} - -/* ═══════════════════════════════════════════════════════════ */ -/* UTILITY CLASSES */ -/* ═══════════════════════════════════════════════════════════ */ - -.text-green-600 { color: #059669 !important; } -.text-yellow-600 { color: #d97706 !important; } -.text-orange-600 { color: #ea580c !important; } -.text-red-600 { color: #dc2626 !important; } - -/* ═══════════════════════════════════════════════════════════ */ -/* RESPONSIVE */ -/* ═══════════════════════════════════════════════════════════ */ - -@media (max-width: 768px) { - .app-version { display: none; } - .user-info { display: none; } - .elite-dropdown { min-width: 300px; } - .search-dropdown { min-width: 280px; } -} +/* + * ╔════════════════════════════════════════════════════════════╗ + * ║ Lions Platform Elite Topbar Styles (Freya Design System) ║ + * ║ Modern, Professional, Responsive ║ + * ╚════════════════════════════════════════════════════════════╝ + */ + +/* ═══════════════════════════════════════════════════════════ */ +/* BASE TOPBAR */ +/* ═══════════════════════════════════════════════════════════ */ + +.unionflow-elite, +.lions-elite { + background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-600) 100%); + box-shadow: 0 2px 12px rgba(0,0,0,0.08); + position: relative; + z-index: 1000; +} + +.unionflow-elite::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent 0%, + var(--primary-300) 50%, + transparent 100%); + opacity: 0.5; +} + +/* App Version Badge */ +.app-version { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.625rem; + background: rgba(255,255,255,0.15); + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; + color: rgba(255,255,255,0.9); + margin-left: 0.75rem; + backdrop-filter: blur(10px); + border: 1px solid rgba(255,255,255,0.2); +} + +/* ═══════════════════════════════════════════════════════════ */ +/* SEARCH */ +/* ═══════════════════════════════════════════════════════════ */ + +.search-item .topbar-icon { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.search-item:hover .topbar-icon { + transform: scale(1.1); + color: var(--primary-100); +} + +.search-dropdown { + position: absolute; + top: calc(100% + 0.5rem); + right: 0; + min-width: 400px; + background: white; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0,0,0,0.12); + padding: 1rem; + opacity: 0; + visibility: hidden; + transform: translateY(-10px); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid var(--surface-border); +} + +.search-item:hover .search-dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.search-wrapper-elite { + display: flex; + align-items: center; + gap: 0.75rem; + background: var(--surface-50); + border-radius: 8px; + padding: 0.5rem 1rem; + border: 1px solid var(--surface-border); + transition: all 0.3s ease; +} + +.search-wrapper-elite:focus-within { + background: white; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1); +} + +.search-wrapper-elite .pi-search { + color: var(--text-color-secondary); + font-size: 1rem; +} + +.search-wrapper-elite .search-input { + flex: 1; + border: none; + background: transparent; + padding: 0.5rem 0; + font-size: 0.875rem; +} + +.search-wrapper-elite .search-input:focus { + outline: none; + box-shadow: none; +} + +/* ═══════════════════════════════════════════════════════════ */ +/* NOTIFICATIONS */ +/* ═══════════════════════════════════════════════════════════ */ + +.notifications-item { + position: relative; +} + +.badge-count { + position: absolute; + top: -4px; + right: -4px; + background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + color: white; + font-size: 0.625rem; + font-weight: 700; + padding: 0.125rem 0.375rem; + border-radius: 10px; + min-width: 18px; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(239, 68, 68, 0.4); + animation: pulse-badge 2s infinite; +} + +@keyframes pulse-badge { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.1); } +} + +.notifications-dropdown { + position: absolute; + top: calc(100% + 0.5rem); + right: 0; + min-width: 360px; + max-width: 400px; + background: white; + border-radius: 12px; + box-shadow: 0 8px 32px rgba(0,0,0,0.12); + opacity: 0; + visibility: hidden; + transform: translateY(-10px); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid var(--surface-border); + overflow: hidden; +} + +.notifications-item:hover .notifications-dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.notif-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 1.25rem; + background: var(--surface-50); + border-bottom: 1px solid var(--surface-border); +} + +.count-label { + font-size: 0.75rem; + color: var(--text-color-secondary); + background: var(--primary-color); + color: white; + padding: 0.25rem 0.625rem; + border-radius: 12px; + font-weight: 600; +} + +.notif-item { + display: flex; + align-items: flex-start; + gap: 0.875rem; + padding: 0.875rem 1.25rem; + transition: all 0.2s ease; + cursor: pointer; +} + +.notif-item:hover { + background: var(--surface-50); +} + +.notif-item i { + font-size: 1.25rem; + margin-top: 0.25rem; +} + +.notif-title { + font-weight: 600; + color: var(--text-color); + font-size: 0.875rem; + margin-bottom: 0.25rem; +} + +.notif-time { + font-size: 0.75rem; + color: var(--text-color-secondary); +} + +.notif-footer { + padding: 0.75rem 1.25rem; + text-align: center; + border-top: 1px solid var(--surface-border); + background: var(--surface-50); +} + +.notif-footer a { + font-size: 0.875rem; + font-weight: 600; + text-decoration: none; + transition: color 0.2s ease; +} + +.notif-footer a:hover { + color: var(--primary-600); +} + +/* ═══════════════════════════════════════════════════════════ */ +/* USER PROFILE */ +/* ═══════════════════════════════════════════════════════════ */ + +.elite-user .profile-trigger { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.5rem 0.875rem; + border-radius: 10px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + background: rgba(255,255,255,0.1); + backdrop-filter: blur(10px); +} + +.elite-user .profile-trigger:hover { + background: rgba(255,255,255,0.2); + transform: translateY(-1px); +} + +.avatar-container { + position: relative; +} + +.avatar { + width: 38px; + height: 38px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.875rem; + font-weight: 700; + color: white; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + border: 2px solid rgba(255,255,255,0.3); +} + +.bg-gradient-primary { + background: linear-gradient(135deg, var(--primary-400) 0%, var(--primary-600) 100%); +} + +.status-dot { + position: absolute; + bottom: 0; + right: 0; + width: 10px; + height: 10px; + border-radius: 50%; + border: 2px solid white; +} + +.status-dot.online { + background: linear-gradient(135deg, #10b981 0%, #059669 100%); + box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2); + animation: pulse-dot 2s infinite; +} + +@keyframes pulse-dot { + 0%, 100% { box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.2); } + 50% { box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.4); } +} + +.user-info { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.user-header { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.user-name { + font-size: 0.875rem; + font-weight: 600; + color: white; + line-height: 1.2; +} + +.role-badge { + font-size: 0.625rem; + padding: 0.125rem 0.5rem; + background: rgba(255,255,255,0.25); + border-radius: 8px; + font-weight: 600; + color: white; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.session-timer { + display: flex; + align-items: center; + gap: 0.375rem; +} + +.icon-sm { + font-size: 0.7rem; +} + +.timer-text { + font-size: 0.75rem; + font-weight: 600; + font-family: 'Courier New', monospace; +} + +.arrow { + font-size: 0.75rem; + color: rgba(255,255,255,0.8); + transition: transform 0.3s ease; +} + +.elite-user:hover .arrow { + transform: rotate(180deg); +} + +/* ═══════════════════════════════════════════════════════════ */ +/* USER DROPDOWN MENU */ +/* ═══════════════════════════════════════════════════════════ */ + +.elite-dropdown { + position: absolute; + top: calc(100% + 0.5rem); + right: 0; + min-width: 340px; + background: white; + border-radius: 16px; + box-shadow: 0 12px 48px rgba(0,0,0,0.15); + opacity: 0; + visibility: hidden; + transform: translateY(-10px) scale(0.95); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: 1px solid var(--surface-border); + overflow: hidden; +} + +.elite-user:hover .elite-dropdown { + opacity: 1; + visibility: visible; + transform: translateY(0) scale(1); +} + +/* Dropdown Header */ +.dropdown-header { + padding: 1.25rem; + background: linear-gradient(135deg, var(--primary-50) 0%, var(--surface-50) 100%); + border-bottom: 1px solid var(--surface-border); +} + +.header-content { + display: flex; + gap: 1rem; +} + +.header-avatar { + position: relative; +} + +.avatar-lg { + width: 56px; + height: 56px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.25rem; + font-weight: 700; + color: white; + box-shadow: 0 6px 16px rgba(0,0,0,0.15); +} + +.status-indicator { + position: absolute; + bottom: 2px; + right: 2px; + width: 14px; + height: 14px; + border-radius: 50%; + border: 3px solid white; + display: flex; + align-items: center; + justify-content: center; +} + +.status-indicator.online { + background: linear-gradient(135deg, #10b981 0%, #059669 100%); +} + +.status-indicator i { + font-size: 6px; + color: white; +} + +.header-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.25rem; + justify-content: center; +} + +.header-info .name { + font-size: 1rem; + font-weight: 700; + color: var(--text-color); + line-height: 1.3; +} + +.header-info .email { + font-size: 0.75rem; + color: var(--text-color-secondary); + line-height: 1.3; +} + +.role-tag { + display: inline-flex; + align-items: center; + font-size: 0.625rem; + padding: 0.25rem 0.625rem; + background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-600) 100%); + color: white; + border-radius: 8px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + align-self: flex-start; + margin-top: 0.25rem; +} + +/* Session Card */ +.session-card { + padding: 1rem 1.25rem; + background: var(--surface-50); + border-bottom: 1px solid var(--surface-border); +} + +.card-content { + display: flex; + flex-direction: column; + gap: 0.625rem; +} + +.info-row { + display: flex; + justify-content: space-between; + align-items: center; +} + +.info-row .label { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.75rem; + color: var(--text-color-secondary); + font-weight: 500; +} + +.info-row .label i { + font-size: 0.875rem; +} + +.info-row .value { + font-size: 0.875rem; + font-weight: 600; + color: var(--text-color); +} + +/* Progress Bar */ +.progress-container { + margin-top: 0.5rem; +} + +.progress-bar { + height: 6px; + background: var(--surface-200); + border-radius: 10px; + overflow: hidden; + position: relative; +} + +.progress-fill { + height: 100%; + background: linear-gradient(90deg, var(--green-400) 0%, var(--green-500) 100%); + border-radius: 10px; + transition: width 1s ease, background 0.3s ease; +} + +.progress-fill[style*="width: 0%"], +.progress-fill[style*="width: 1%"], +.progress-fill[style*="width: 2%"], +.progress-fill[style*="width: 3%"], +.progress-fill[style*="width: 4%"], +.progress-fill[style*="width: 5%"] { + background: linear-gradient(90deg, var(--red-400) 0%, var(--red-500) 100%); +} + +.progress-label { + font-size: 0.625rem; + color: var(--text-color-secondary); + margin-top: 0.375rem; + text-align: right; + font-weight: 500; +} + +/* Menu Sections */ +.divider { + height: 1px; + background: var(--surface-border); + margin: 0; +} + +.menu-section { + padding: 0.75rem 0; +} + +.menu-section.compact { + padding: 0.5rem 0; +} + +.section-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.75rem; + font-weight: 700; + color: var(--text-color-secondary); + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 0.5rem 1.25rem 0.75rem; +} + +.section-items { + display: flex; + flex-direction: column; +} + +.menu-item { + display: flex; + align-items: center; + gap: 0.875rem; + padding: 0.75rem 1.25rem; + color: var(--text-color); + text-decoration: none; + transition: all 0.2s ease; + font-size: 0.875rem; + cursor: pointer; + border: none; + background: transparent; + width: 100%; + text-align: left; +} + +.menu-item:hover { + background: var(--surface-100); +} + +.menu-item i:first-child { + font-size: 1rem; + color: var(--text-color-secondary); + transition: all 0.2s ease; +} + +.menu-item:hover i:first-child { + color: var(--primary-color); + transform: translateX(2px); +} + +.menu-item span { + flex: 1; + font-weight: 500; +} + +.arrow-right { + font-size: 0.75rem; + color: var(--text-color-secondary); + margin-left: auto; + transition: transform 0.2s ease; +} + +.menu-item:hover .arrow-right { + transform: translateX(3px); +} + +.item-badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + height: 20px; + padding: 0 0.375rem; + background: var(--primary-color); + color: white; + font-size: 0.625rem; + font-weight: 700; + border-radius: 10px; + margin-left: auto; +} + +.value-badge { + font-size: 0.75rem; + color: var(--text-color-secondary); + background: var(--surface-100); + padding: 0.25rem 0.625rem; + border-radius: 8px; + font-weight: 600; + margin-left: auto; +} + +/* Logout Section */ +.logout-divider { + background: linear-gradient(90deg, + transparent 0%, + var(--red-200) 50%, + transparent 100%); + height: 2px; +} + +.logout-section { + padding: 0.75rem 0; + background: linear-gradient(to bottom, white 0%, var(--red-50) 100%); +} + +.logout-btn { + display: flex; + align-items: center; + gap: 0.875rem; + padding: 0.875rem 1.25rem; + color: var(--red-600); + font-weight: 600; + font-size: 0.875rem; + text-decoration: none; + transition: all 0.3s ease; + cursor: pointer; + border: none; + background: transparent; + width: 100%; + text-align: left; +} + +.logout-btn:hover { + background: var(--red-100); + color: var(--red-700); +} + +.logout-btn i:first-child { + font-size: 1rem; + transition: transform 0.3s ease; +} + +.logout-btn:hover i:first-child { + transform: scale(1.1) rotate(-10deg); +} + +.logout-btn .pi-lock { + font-size: 0.875rem; +} + +/* ═══════════════════════════════════════════════════════════ */ +/* LOGOUT DIALOG */ +/* ═══════════════════════════════════════════════════════════ */ + +.elite-dialog .dialog-content { + text-align: center; + padding: 1.5rem 1rem; +} + +.icon-wrapper { + display: inline-flex; + align-items: center; + justify-content: center; + width: 80px; + height: 80px; + border-radius: 50%; + background: linear-gradient(135deg, var(--red-50) 0%, var(--red-100) 100%); + margin-bottom: 1.5rem; +} + +.icon-lg { + font-size: 2.5rem; + color: var(--red-500); +} + +.dialog-title { + font-size: 1.25rem; + font-weight: 700; + color: var(--text-color); + margin-bottom: 1.5rem; + line-height: 1.4; +} + +.info-box { + background: var(--surface-50); + border-radius: 12px; + padding: 1rem; + margin-bottom: 1rem; + border: 1px solid var(--surface-border); +} + +.info-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.625rem; + color: var(--text-color); + font-size: 0.875rem; +} + +.info-item i { + color: var(--primary-color); + font-size: 1rem; +} + +.warning-text { + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + font-size: 0.875rem; + color: var(--text-color-secondary); + margin: 0; +} + +.warning-text i { + color: var(--blue-500); +} + +.dialog-footer { + display: flex; + gap: 0.75rem; + justify-content: flex-end; + padding-top: 1rem; +} + +/* ═══════════════════════════════════════════════════════════ */ +/* UTILITY CLASSES */ +/* ═══════════════════════════════════════════════════════════ */ + +.text-green-600 { color: #059669 !important; } +.text-yellow-600 { color: #d97706 !important; } +.text-orange-600 { color: #ea580c !important; } +.text-red-600 { color: #dc2626 !important; } + +/* ═══════════════════════════════════════════════════════════ */ +/* RESPONSIVE */ +/* ═══════════════════════════════════════════════════════════ */ + +@media (max-width: 768px) { + .app-version { display: none; } + .user-info { display: none; } + .elite-dropdown { min-width: 300px; } + .search-dropdown { min-width: 280px; } +} diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.css b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.css index ca9fac2..be98d39 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.css +++ b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.css @@ -1,4257 +1,4257 @@ -/* Add your customizations of the layout variables here */ -@-webkit-keyframes fadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - -webkit-transform: none; - transform: none; - } -} -@keyframes fadeInDown { - from { - opacity: 0; - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - transform: none; - } -} -@-webkit-keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} -@keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} -@keyframes fadeinmask { - from { - opacity: 0; - } - to { - opacity: 0.8; - } -} -.fadeInDown { - -webkit-animation-name: fadeInDown; - animation-name: fadeInDown; -} - -.fadeOutUp { - -webkit-animation-name: fadeOutUp; - animation-name: fadeOutUp; -} - -@-webkit-keyframes modal-in { - from { - background-color: transparent; - } - to { - background-color: rgba(0, 0, 0, 0.6); - } -} -@keyframes modal-in { - from { - background-color: transparent; - } - to { - background-color: rgba(0, 0, 0, 0.6); - } -} -.modal-in { - -webkit-animation-name: modal-in; - animation-name: modal-in; -} - -h1, h2, h3, h4, h5, h6 { - margin: 1.5rem 0 1rem 0; - font-family: inherit; - font-weight: 600; - line-height: 1.2; - color: inherit; -} -h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { - margin-top: 0; -} - -h1 { - font-size: 2.5rem; -} - -h2 { - font-size: 2rem; -} - -h3 { - font-size: 1.75rem; -} - -h4 { - font-size: 1.5rem; -} - -h5 { - font-size: 1.25rem; -} - -h6 { - font-size: 1rem; -} - -mark { - background: #FFF8E1; - padding: 0.25rem 0.4rem; - border-radius: 24px; - font-family: monospace; -} - -blockquote { - margin: 1rem 0; - padding: 0 2rem; - border-left: 4px solid #90A4AE; -} - -hr { - border-top: solid #383838; - border-width: 1px 0 0 0; - margin: 1rem 0; -} - -p { - margin: 0 0 1rem 0; - line-height: 1.5; -} -p:last-child { - margin-bottom: 0; -} - -html { - height: 100%; - font-size: 14px; -} - -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 14px; - font-weight: 400; - color: #EAEBEC; - padding: 0; - margin: 0; - min-height: 100%; - background-color: #3E4754; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -body.blocked-scroll { - overflow: auto; -} - -a { - text-decoration: none; - color: #669cee; - color: var(--primary-color); -} - -.ajax-loader { - font-size: 32px; - color: #387fe9; - color: var(--primary-color); -} - -.layout-main { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - min-height: 100vh; - padding-top: 82px; - -moz-transition: padding-left 0.2s; - -o-transition: padding-left 0.2s; - -webkit-transition: padding-left 0.2s; - transition: padding-left 0.2s; -} - -.layout-mask { - display: none; - position: fixed; - top: 0; - left: 0; - z-index: 998; - width: 100%; - height: 100%; - animation-duration: 0.2s; - animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); - animation-fill-mode: forwards; -} - -.layout-content { - padding: 30px 36px; - flex: 1 1 auto; -} - -@media (max-width: 991px) { - .layout-content { - padding: 32px 14px; - } -} -.layout-topbar-light .layout-topbar { - position: fixed; - top: 0; - z-index: 999; - width: 100%; - -moz-transition: width 0.2s; - -o-transition: width 0.2s; - -webkit-transition: width 0.2s; - transition: width 0.2s; - height: 62px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper { - height: 100%; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left { - height: 100%; - padding: 0 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - z-index: 999; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - height: 15px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { - height: 15px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - padding: 6px; - margin-right: 16px; - border-radius: 4px; - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { - font-size: 18px; - width: 18px; - height: 18px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right { - height: 100%; - flex-grow: 1; - padding: 0 16px 0 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - border-right: solid 1px transparent; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; - list-style-type: none; - margin: 0; - padding: 0; - height: 100%; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - height: 100%; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { - width: 100%; - padding: 6px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - display: none; - position: absolute; - top: 62px; - right: 0px; - list-style-type: none; - margin: 0; - padding: 7px 0 8px; - z-index: 1000; - -moz-border-radius-bottomleft: 2px; - -webkit-border-bottom-left-radius: 2px; - border-bottom-left-radius: 2px; - -moz-border-radius-bottomright: 2px; - -webkit-border-bottom-right-radius: 2px; - border-bottom-right-radius: 2px; - min-width: 250px; - animation-duration: 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { - padding: 10px 15px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - cursor: pointer; - list-style: none; - margin-bottom: 4px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - margin-right: 10px; - padding: 6px; - border-radius: 2px; - width: 26px; - height: 26px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { - height: 36px; - width: 36px; - margin-right: 10px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { - width: auto; - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { - position: relative; - width: 0; - opacity: 0; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { - background: #303A48; - width: 100%; - position: relative; - padding: 9px; - padding-left: 37px; - border: none; - color: #FFFFFF; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { - position: absolute; - left: 9px; - font-size: 18px; - top: 50%; - margin-top: -9px; - display: none; - z-index: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { - margin-left: 16px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { - height: 28px; - width: 28px; - border-radius: 10px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { - width: 200px; - opacity: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - margin-left: 26px; - z-index: 1; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -@media (max-width: 991px) { - .layout-topbar-light .layout-topbar .layout-topbar-wrapper { - -ms-flex-align: start; - align-items: flex-start; - position: relative; - padding: 0 6px; - } -} -@media (max-width: 576px) { - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - left: 10px; - right: 10px; - position: fixed; - top: 62px; - } -} -.layout-topbar-light .layout-topbar { - background-color: #ffffff; - box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { - color: #293241; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - color: #293241; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { - background-color: #f8fafc; - border: 1px solid #ebedef; - color: #669cee; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { - color: #669cee; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { - color: #293241; - opacity: 0.5; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); - background-color: white; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { - background-color: #5d97ed; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { - color: #ffffff; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { - background-color: #5d97ed; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - color: #EAEBEC; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - background-color: rgba(56, 127, 233, 0.8); - color: #ffffff; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { - color: #BFC2C6; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { - color: #EAEBEC; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { - color: #BFC2C6; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - color: #293241; - background-color: transparent; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} - -.layout-topbar-dark .layout-topbar { - position: fixed; - top: 0; - z-index: 999; - width: 100%; - -moz-transition: width 0.2s; - -o-transition: width 0.2s; - -webkit-transition: width 0.2s; - transition: width 0.2s; - height: 62px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper { - height: 100%; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left { - height: 100%; - padding: 0 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - z-index: 999; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - height: 15px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { - height: 15px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - padding: 6px; - margin-right: 16px; - border-radius: 4px; - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { - font-size: 18px; - width: 18px; - height: 18px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right { - height: 100%; - flex-grow: 1; - padding: 0 16px 0 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - border-right: solid 1px transparent; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; - list-style-type: none; - margin: 0; - padding: 0; - height: 100%; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - height: 100%; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { - width: 100%; - padding: 6px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - display: none; - position: absolute; - top: 62px; - right: 0px; - list-style-type: none; - margin: 0; - padding: 7px 0 8px; - z-index: 1000; - -moz-border-radius-bottomleft: 2px; - -webkit-border-bottom-left-radius: 2px; - border-bottom-left-radius: 2px; - -moz-border-radius-bottomright: 2px; - -webkit-border-bottom-right-radius: 2px; - border-bottom-right-radius: 2px; - min-width: 250px; - animation-duration: 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { - padding: 10px 15px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - cursor: pointer; - list-style: none; - margin-bottom: 4px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - margin-right: 10px; - padding: 6px; - border-radius: 2px; - width: 26px; - height: 26px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { - height: 36px; - width: 36px; - margin-right: 10px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { - width: auto; - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { - position: relative; - width: 0; - opacity: 0; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { - background: #303A48; - width: 100%; - position: relative; - padding: 9px; - padding-left: 37px; - border: none; - color: #FFFFFF; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { - position: absolute; - left: 9px; - font-size: 18px; - top: 50%; - margin-top: -9px; - display: none; - z-index: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { - margin-left: 16px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { - height: 28px; - width: 28px; - border-radius: 10px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { - width: 200px; - opacity: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - margin-left: 26px; - z-index: 1; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -@media (max-width: 991px) { - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper { - -ms-flex-align: start; - align-items: flex-start; - position: relative; - padding: 0 6px; - } -} -@media (max-width: 576px) { - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - left: 10px; - right: 10px; - position: fixed; - top: 62px; - } -} -.layout-topbar-dark .layout-topbar { - background-color: #293241; - box-shadow: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { - background-color: #333e51; - border: 1px solid #333e51; - color: #94baf3; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { - color: #94baf3; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { - color: #E9E9E9; - opacity: 0.5; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); - background-color: #333e51; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { - background-color: #5d97ed; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { - color: #ffffff; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { - background-color: #5d97ed; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - background-color: rgba(56, 127, 233, 0.8); - color: #ffffff; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { - color: #C2C2C2; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { - color: #C2C2C2; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - color: #E9E9E9; - background-color: transparent; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} - -.menu-wrapper { - height: 100%; - position: fixed; - top: 0; - z-index: 999; - left: 0; -} -.menu-wrapper .sidebar-logo { - height: 62px; - display: -ms-flexbox; - display: flex; - -ms-flex-pack: start; - justify-content: flex-start; - -ms-flex-align: center; - align-items: center; - padding: 0 22px; - padding-right: 20px; -} -.menu-wrapper .sidebar-logo .sidebar-pin { - display: none; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.menu-wrapper .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #383838; -} -.menu-wrapper .sidebar-logo img { - width: 17px; - height: 20px; - border: 0 none; -} -.menu-wrapper .layout-menu-container { - height: calc(100% - 62px); -} -.menu-wrapper .layout-menu-container .layout-menu { - list-style-type: none; - margin: 0; - padding: 0; - max-width: 62px; - overflow: hidden; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.menu-wrapper .layout-menu-container .layout-menu > li > a { - position: relative; -} -.menu-wrapper .layout-menu-container .layout-menu > li > a::before { - content: ""; - width: 4px; - height: 12px; - display: block; - border-radius: 0px 3px 3px 0px; - position: absolute; - left: 0; -} -.menu-wrapper .layout-menu-container .layout-menu > li > ul > li { - margin-left: 6px; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; -} -.menu-wrapper .layout-menu-container .layout-menu li { - padding: 10px 0; -} -.menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { - -webkit-transform: rotate(-180deg); - -moz-transform: rotate(-180deg); - -o-transform: rotate(-180deg); - -ms-transform: rotate(-180deg); - transform: rotate(-180deg); -} -.menu-wrapper .layout-menu-container .layout-menu li .layout-menu-tooltip { - display: none; -} -.menu-wrapper .layout-menu-container .layout-menu li > a { - margin: 0px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - font-size: 13px; - padding: 6px 20px; - user-select: none; - cursor: pointer; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > span { - margin: 0 8px; - margin-left: 14px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - visibility: hidden; - white-space: nowrap; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > i { - font-size: 24px; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > i.layout-submenu-toggler { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - margin-left: auto; - font-size: 12px; - visibility: hidden; -} -.menu-wrapper .layout-menu-container .layout-menu li > a.rotated-icon i { - transform: rotate(90deg); -} -.menu-wrapper .layout-menu-container .layout-menu li > ul { - display: none; - list-style-type: none; - overflow: hidden; - padding: 0; - margin: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul li ul { - display: none; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li { - padding: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li > a { - padding: 10px 18px; - margin-left: 0px; - padding-right: 8px; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li i { - font-size: 14px; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li ul li { - padding: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li.layout-root-menuitem > a { - display: -ms-flexbox; - display: flex; -} - -@media (min-width: 992px) { - .layout-wrapper.layout-sidebar .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - display: none; - } - .layout-wrapper.layout-sidebar .layout-main { - padding-left: 62px; - } - .layout-wrapper.layout-static .menu-wrapper { - transform: translate3d(0px, 0px, 0px); - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo { - justify-content: space-between; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo img { - display: inline; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .app-name { - display: inline; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin { - display: inline-block; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #383838; - border: 2px solid var(--primary-light-color); - background-color: #383838; - background-color: var(--primary-lighter-color); - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu > li { - min-width: 230px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-static .layout-main { - padding-left: 230px; - -moz-transition: padding-left 0.2s; - -o-transition: padding-left 0.2s; - -webkit-transition: padding-left 0.2s; - transition: padding-left 0.2s; - } - - .menu-wrapper.layout-sidebar-active { - transform: translate3d(0px, 0px, 0px); - } - .menu-wrapper.layout-sidebar-active .sidebar-logo { - justify-content: space-between; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo img { - display: inline; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .app-name { - display: inline; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin { - display: inline-block; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #383838; - } - .menu-wrapper.layout-sidebar-active .layout-menu { - max-width: 230px; - } - .menu-wrapper.layout-sidebar-active .layout-menu > li { - min-width: 230px; - } - .menu-wrapper.layout-sidebar-active .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li a { - padding-left: 20px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li a { - padding-left: 30px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .menu-wrapper.layout-sidebar-active .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .menu-wrapper.layout-sidebar-active .layout-menu-container { - overflow: auto; - } -} -@media (max-width: 991px) { - .layout-wrapper .menu-wrapper { - top: 62px; - z-index: 1010; - -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); - transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); - transform: translate3d(-230px, 0px, 0px); - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - } - .layout-wrapper .menu-wrapper .sidebar-logo { - display: none; - } - .layout-wrapper .menu-wrapper .layout-menu-container .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-mobile-active { - overflow: hidden; - height: 100vh; - } - .layout-wrapper.layout-mobile-active .menu-wrapper { - transform: translate3d(0px, 0px, 0px); - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li { - min-width: 230px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu-container { - overflow: auto; - } - .layout-wrapper.layout-mobile-active .layout-mask { - display: block; - } - .layout-wrapper .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - display: block; - } -} -@media (min-width: 992px) { - .layout-wrapper.layout-horizontal .menu-wrapper { - top: 0px; - width: 100%; - height: 62px; - position: relative; - } - .layout-wrapper.layout-horizontal .menu-wrapper .sidebar-logo { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container { - height: 100%; - display: flex; - align-items: center; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu { - list-style-type: none; - margin: 0px 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: row; - flex-direction: row; - max-width: 100%; - overflow: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { - -webkit-transform: rotate(-180deg); - -moz-transform: rotate(-180deg); - -o-transform: rotate(-180deg); - -ms-transform: rotate(-180deg); - transform: rotate(-180deg); - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li { - padding: 0; - position: relative; - margin: 0 9px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li .layout-menu-tooltip { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a { - margin: 0px; - padding: 10px 5px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a:before { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > span { - margin: 0 8px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - visibility: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i { - font-size: 14px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i.layout-submenu-toggler { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - margin-left: auto; - font-size: 12px; - visibility: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.layout-root-menuitem > div { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - display: none; - list-style-type: none; - top: 44px; - left: 0px; - width: 230px; - position: absolute; - padding: 10px; - margin: 0; - z-index: 100; - overflow: auto; - max-height: 460px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li { - border: 0 none; - margin: 0; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button-wrapper .menu-button { - display: none; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } -} -@media (min-width: 992px) { - .layout-wrapper.layout-slim .menu-wrapper { - width: 62px; - overflow: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container { - padding: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu { - overflow: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - display: none; - padding: 0 0.412px; - position: absolute; - left: 72px; - top: 16px; - line-height: 1; - border-radius: 2px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - padding: 6px 8px; - font-weight: 500; - min-width: 75px; - white-space: nowrap; - text-align: center; - -webkit-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - -moz-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - top: 50%; - left: -4px; - margin-top: -5px; - border-width: 5px 5px 5px 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li { - position: relative; - padding: 10px 12px 10px 14px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a { - margin: 0px; - padding: 6px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - position: relative; - border: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:before { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a span { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i { - margin-right: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i.layout-submenu-toggler { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a .menuitem-badge { - display: none; - margin-left: auto; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:hover + .layout-menu-tooltip { - display: block; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - position: absolute; - top: 0; - left: 62px; - min-width: 250px; - max-height: 450px; - display: none; - padding: 10px; - overflow: auto; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li { - margin: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - padding: 10px 5px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > span { - visibility: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover + .layout-menu-tooltip { - display: none; - } - .layout-wrapper.layout-slim .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - display: none; - } - .layout-wrapper.layout-slim .layout-main { - padding-left: 62px; - } -} -.layout-menu-dark .menu-wrapper { - background-color: #293241; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: #293241; -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: #293241; - color: #387fe9; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-light-color); -} -@media (min-width: 992px) { - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-horizontal .menu-wrapper { - box-shadow: none; - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - background-color: #293241; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - background-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - color: #ffffff; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - border-right-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - background-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); - } -} -@media (max-width: 991px) { - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } -} - -.layout-menu-light .menu-wrapper { - background-color: #ffffff; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: #ffffff; -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: #ffffff; - color: #387fe9; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-color); -} -@media (min-width: 992px) { - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } - .layout-menu-light.layout-horizontal .menu-wrapper { - box-shadow: none; - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - background-color: #ffffff; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - background-color: #293241; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - color: #ffffff; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - border-right-color: #293241; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - background-color: #ffffff; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); - } -} -@media (max-width: 991px) { - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #387fe9; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #387fe9; - background-color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(56, 127, 233, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(56, 127, 233, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } -} - -.layout-rightpanel { - position: fixed; - z-index: 1000; - right: 0; - top: 62px; - height: calc(100% - 62px); - padding: 0; - width: 418px; - overflow: auto; - background-color: #303A48; - transform: translate3d(418px, 0px, 0px); - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - -webkit-backface-visibility: hidden; - -moz-backface-visibility: hidden; - backface-visibility: hidden; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-rightpanel .rightpanel-wrapper { - padding: 22px 20px 40px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section { - padding: 16px 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - margin-bottom: 16px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header > h6 { - margin: 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 14px 16px; - background-image: url("#{resource['demo:images/rightpanel/asset-weather.png']}"); - background-position: center; - background-repeat: no-repeat; - background-size: cover; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - -moz-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - color: rgba(41, 50, 65, 0.8); -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather > img { - height: 60px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info { - margin-left: 16px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h6 { - margin: 0 0 2px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h1 { - margin: 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul { - padding: 0; - margin: 0; - list-style: none; - overflow: auto; - max-height: 320px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li { - padding: 16px; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - background-color: #293241; - margin-bottom: 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info h6 { - color: #FFFFFF; - margin: 0 0 4px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info > span { - display: block; - font-weight: 500; - font-size: 14px; - line-height: 140%; - color: #BFC2C6; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done { - opacity: 0.5; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done .task-info h6 { - text-decoration: line-through; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-wrap: wrap; - margin: -7px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - width: 80px; - height: 80px; - background-color: #293241; - margin: 7px; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item:hover { - background-color: #3E4754; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - width: 80px; - height: 80px; - margin: 7px; - border: 1px dashed #383838; - color: #383838; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item:hover { - background-color: #3E4754; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section { - margin-top: 40px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { - height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { - height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { - background-image: linear-gradient(180deg, #303A48 0%, rgba(234, 237, 243, 0) 100%); -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { - max-height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - background-color: #293241; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { - max-height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { - background-color: #293241; -} - -.layout-wrapper.layout-rightpanel-active .layout-rightpanel { - transform: translate3d(0px, 0px, 0px); -} - -@media (max-width: 576px) { - .layout-rightpanel { - width: 100%; - transform: translate3d(100%, 0px, 0px); - } -} -.layout-footer { - padding: 30px 36px; -} -.layout-footer .footer-menutitle { - color: #BFC2C6; - font-weight: 600; - font-size: 12px; - line-height: 14px; - min-height: 15px; - display: block; - margin-bottom: 9px; -} -.layout-footer .footer-subtitle { - font-weight: 500; - font-size: 14px; - display: block; - color: #BFC2C6; -} -.layout-footer ul { - padding: 0; - margin: 0; - list-style: none; -} -.layout-footer ul > li { - padding: 7px 0; -} -.layout-footer ul > li > a { - color: #EAEBEC; - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.layout-footer ul > li > a:hover { - color: #BFC2C6; -} -.layout-footer .newsletter-input { - margin-top: 16px; - background-color: #293241; - position: relative; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.layout-footer .newsletter-input > input { - width: 100%; - background-color: transparent; - border: none; - padding: 11px 16px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - font-size: 14px; - line-height: 200%; -} -.layout-footer .newsletter-input > button { - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - position: absolute; - right: 6px; - top: 50%; - margin-top: -16px; -} -.layout-footer .newsletter-input > button > span { - display: block; - padding: 0; - width: 100%; - font-weight: 600; - font-size: 14px; -} -.layout-footer .footer-bottom { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-footer .footer-bottom h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.layout-footer .footer-bottom h6 { - line-height: 17px; - margin: 0; - color: #BFC2C6; - font-weight: 500; -} - -/* Utils */ -.clearfix:after { - content: " "; - display: block; - clear: both; -} - -.card { - background: #293241; - padding: 20px; - box-sizing: border-box; - box-shadow: 0 10px 40px rgba(41, 50, 65, 0.06); - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - margin-bottom: 2rem; -} -.card:last-child { - margin-bottom: 0; -} -.card .card-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - padding-bottom: 16px; -} -.card .card-header h6 { - margin-bottom: 2px; -} -.card .card-header .subtitle { - font-weight: 600; - color: #BFC2C6; -} -.card .card-subtitle { - color: #BFC2C6; - font-weight: 600; - margin: -1rem 0 1rem 0; -} -.card.no-gutter { - margin-bottom: 0; -} - -.sr-only { - border: 0; - clip: rect(1px, 1px, 1px, 1px); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - word-wrap: normal !important; -} - -.ui-text-secondary { - color: #BFC2C6; -} - -.layout-wrapper .layout-ajax-loader { - position: absolute; - right: 15px; - bottom: 70px; -} -.layout-wrapper .layout-ajax-loader .layout-ajax-loader-icon { - color: red; - font-size: 32px; -} - -.layout-dashboard .chart { - overflow: auto; - position: relative; -} -.layout-dashboard .mobile-teams { - display: none; -} - -@media (max-width: 1200px) { - .layout-dashboard .desktop-teams { - display: none; - } - .layout-dashboard .mobile-teams { - display: block; - } - .layout-dashboard .mobile-teams .team { - height: 100%; - flex-direction: column; - -ms-flex-pack: start; - justify-content: flex-start; - -ms-flex-align: start; - align-items: flex-start; - } - .layout-dashboard .mobile-teams .team .peoples { - margin: 12px -8px; - } -} -.overview-box { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - padding-top: 24px; - height: 100%; - min-width: 200px; -} -.overview-box .overview-info > h6 { - margin: 0 0 2px; -} -.overview-box .overview-info > h1 { - margin: 0; -} -.overview-box > i { - font-size: 24px; -} -.overview-box.white { - background: #FFFFFF; - color: rgba(41, 50, 65, 0.8); -} -.overview-box.blue { - background: #69B7FF; - color: #FFFFFF; -} -.overview-box.gray { - background: rgba(41, 50, 65, 0.4); - color: #FFFFFF; -} -.overview-box.darkgray { - background: rgba(41, 50, 65, 0.8); - color: #FFFFFF; -} -.overview-box.orange { - background: linear-gradient(90deg, #FFB340 0%, #FFA740 100%); - color: #FFFFFF; -} - -.timeline { - padding-right: 4px; -} -.timeline > ul { - padding: 0; - margin: 0; - list-style: none; - max-height: 372px; - overflow: auto; - margin-bottom: 1em; -} -.timeline > ul > li { - display: -ms-flexbox; - display: flex; - margin-bottom: 16px; -} -.timeline > ul > li > i { - font-size: 8px; - margin-right: 10px; - margin-top: 4px; -} -.timeline > ul > li .event-content span { - display: block; - margin-bottom: 4px; - font-weight: 600; - font-size: 12px; - color: #BFC2C6; -} -.timeline > ul > li .event-content span.event-title { - color: #FFFFFF; -} -.timeline > ul > li .event-content span.time { - font-size: 10px; - font-weight: 400; - color: #BFC2C6; -} -.timeline > ul > li.blue > i { - color: #297FFF; -} -.timeline > ul > li.green > i { - color: #34B56F; -} -.timeline > ul > li.orange > i { - color: #FFA928; -} - -.device-status .content { - color: #BFC2C6; - line-height: 1.4; - margin-bottom: 20px; -} -.device-status .progress { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 10px 0; - color: #BFC2C6; -} -.device-status .progress > span { - min-width: 40px; -} -.device-status .progress .ui-progressbar { - width: 100%; - margin: 0 12px; - background: rgba(41, 127, 255, 0.2); - background: var(--primary-lighter-color); -} -.device-status .progress .ui-progressbar .ui-progressbar-value { - background: rgba(41, 127, 255, 0.2); - background: var(--primary-color); - opacity: 0.8; - border-radius: 24px; -} -.device-status .progress.active .ui-progressbar { - width: 100%; - margin: 0 12px; - background: rgba(41, 127, 255, 0.2); - background: var(--primary-lighter-color); -} -.device-status .progress.active .ui-progressbar .ui-progressbar-value { - background: linear-gradient(270deg, #42BBFF 0%, #6129FF 100%); - background: linear-gradient(270deg, var(--primary-lighter-color) 0%, var(--primary-color) 100%); - opacity: 0.8; -} -.device-status .device { - margin-bottom: 16px; -} -.device-status .device span { - color: #387fe9; - color: var(--primary-color); - font-size: 14px; - font-weight: 600; -} -.device-status .device span > span { - font-size: 8px; - font-weight: normal; -} -.device-status .device span.status { - font-size: 12px; - color: #BFC2C6; - margin-top: 4px; - display: block; -} - -.team { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; -} -.team .card-header { - padding: 0; - min-width: 70px; -} -.team .peoples { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-wrap: wrap; -} -.team .peoples > img { - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - border-radius: 10px; - margin: 8px 8px; - width: 32px; - height: 32px; -} -.team .peoples .no-picture { - cursor: pointer; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - border-radius: 10px; - margin: 8px 8px; - width: 32px; - height: 32px; - background: rgba(41, 50, 65, 0.1); - color: #EAEBEC; - font-size: 12px; - -moz-transition: background 0.2s; - -o-transition: background 0.2s; - -webkit-transition: background 0.2s; - transition: background 0.2s; -} -.team .peoples .no-picture:hover { - background: rgba(41, 50, 65, 0.2); -} - -.map { - padding: 0; -} -.map > img { - width: 100%; - height: auto; - border-radius: 24px 24px 12px 12px; -} -.map .map-content { - padding: 50px 20px 28px; -} -.map .map-content h6 { - margin: 0 0 16px; -} -.map .map-content .city { - margin-bottom: 16px; -} -.map .map-content .city span { - color: #387fe9; - color: var(--primary-color); - font-size: 14px; - font-weight: 600; -} -.map .map-content .city span > span { - font-size: 8px; - font-weight: normal; -} -.map .map-content .city span.status { - font-size: 12px; - color: #BFC2C6; - margin-top: 4px; - display: block; -} - -.schedule > p { - color: #BFC2C6; -} -.schedule > ul { - list-style: none; - padding: 0; - margin: 0; -} -.schedule > ul > li { - background: #3E4754; - border-radius: 8px; - margin-bottom: 10px; - padding: 5px 16px 12px; -} -.schedule > ul > li .schedule-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; -} -.schedule > ul > li .schedule-header h6 { - line-height: 24px; - margin: 0; -} -.schedule > ul > li .schedule-header span { - color: #BFC2C6; - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.schedule > ul > li > span { - margin-top: 4px; - color: #BFC2C6; - display: block; - font-size: 12px; - line-height: 14px; -} - -.statistics .statistic-item .item-title { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 4px; -} -.statistics .statistic-item .item-title span { - display: block; - margin-right: 12px; -} -.statistics .statistic-item .item-title h5 { - margin: 0; - font-weight: 700; -} -.statistics .statistic-item h6 { - margin: 0; - font-weight: 600; - color: #BFC2C6; -} - -.stocks ul { - list-style: none; - padding: 0; - margin: 0; -} -.stocks ul > li { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - background-color: #303A48; - padding: 0; - margin: 0 0 12px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - overflow: hidden; -} -.stocks ul > li .stock-name { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: #374250; - padding: 18px 10px; - min-width: 70px; - margin-right: 4px; -} -.stocks ul > li .stock-name h6 { - margin: 0; - color: #EAEBEC; - line-height: 17px; - font-weight: 600; -} -.stocks ul > li > img { - margin: 0 4px; - height: 25px; -} -.stocks ul > li .stock-price { - padding: 0 10px; - color: #34B56F; - margin: 0 4px; -} -.stocks ul > li .stock-price h6 { - line-height: 17px; - font-weight: 600; - display: inline-block; -} -.stocks ul > li .stock-price i { - display: inline-block; -} -.stocks ul > li .stock-status { - margin-left: 4px; - padding: 0 20px; -} -.stocks ul > li .stock-status span { - display: block; - font-weight: 600; - font-size: 10px; - line-height: 12px; - color: #BFC2C6; -} -.stocks ul > li.down .stock-price { - color: #FF6E49; -} -.stocks ul > li.same .stock-price { - color: #FFA928; -} -.stocks > .ui-button { - width: 100%; - margin-top: 30px; -} - -.operations { - overflow: auto; - position: relative; -} -.operations .insights { - padding: 16px 15px; - background-color: rgba(41, 127, 255, 0.04); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - margin: 12px 0 16px; -} -.operations .insights .insight-header { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 5px; -} -.operations .insights .insight-header h6 { - margin: 0 6px; -} -.operations .insights > ul { - list-style: none; - padding: 0; - margin: 0; -} -.operations .insights > ul > li { - margin: 8px 0; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - color: #BFC2C6; -} -.operations .insights > ul > li span { - font-weight: 600; -} -.operations .insights > ul > li span > span { - font-size: 8px; - line-height: 10px; - font-weight: normal; -} -.operations > button { - width: 100%; -} - -.notification { - padding: 30px 24px; - background-color: #293241; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.notification > h6 { - margin: 0; - color: #EAEBEC; -} -.notification > h6 > a { - margin-left: 10px; -} -.notification > h6 > a i { - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -o-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); -} - -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav { - background-color: transparent; - margin: 0 -10px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav:before { - display: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header { - padding: 9px 0 0; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: transparent; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - margin: 0 10px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a { - position: relative; - width: 52px; - height: 52px; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: #D0D6DD; - cursor: pointer; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - color: #387fe9; - color: var(--primary-color); - border: 0 none; - overflow: visible; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a img { - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a .ui-badge { - position: absolute; - bottom: -5px; - right: -5px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active { - padding: 0 0 9px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active a { - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.16), 0px 1px 2px rgba(41, 50, 65, 0.04), 0px 6px 12px rgba(41, 50, 65, 0.24); - border: 0 none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active:before { - content: ""; - width: 12px; - height: 2px; - background: #387fe9; - background: var(--primary-color); - border-radius: 3px; - position: absolute; - bottom: -10px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-hover { - border: none; - padding: 0 0 9px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels { - background-color: transparent; - border: none; - padding: 16px 0 0; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { - padding: 0; - height: 350px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - height: 350px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { - position: absolute; - top: 0; - left: 0; - display: block; - width: 100%; - height: 44px; - background-image: linear-gradient(180deg, #293241 0%, rgba(234, 237, 243, 0) 100%); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { - max-height: 400px; - overflow: auto; - padding: 30px 6px 12px; - flex: 1 1 auto; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message { - display: -ms-flexbox; - display: flex; - flex-direction: column; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .name { - display: block; - color: #BFC2C6; - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - max-width: 250px; - padding: 8px 10px; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - background-color: #303A48; - margin-bottom: 8px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message p { - padding: 0; - margin: 0 0 2px; - color: #EAEBEC; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message span { - display: block; - font-weight: 600; - font-size: 10px; - line-height: 14px; - color: #BFC2C6; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send { - -ms-flex-align: end; - align-items: flex-end; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send .message span { - text-align: right; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message h4 { - color: #BFC2C6; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { - flex: 1 1 auto; - max-height: 400px; - overflow: auto; - padding: 0px 0 12px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul { - padding: 0; - margin: 0; - list-style: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 6px; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - cursor: pointer; - padding: 8px 10px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li img { - margin-right: 12px; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li h6 { - margin: 0 0 2px; - color: #EAEBEC; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li span { - display: block; - color: #BFC2C6; - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { - background-color: #303A48; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input { - margin-top: 30px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { - width: 100%; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - padding: 20px 19px; - background-color: #3E4754; - border: none; -} - -.image-card { - padding: 0; - position: relative; -} -.image-card > span { - position: absolute; - right: 20px; - top: 20px; -} -.image-card > img { - width: 100%; - height: auto; - border-radius: 24px 24px 12px 12px; -} -.image-card .image-content { - padding: 32px 20px 28px; -} -.image-card .image-content h6 { - margin: 0 0 8px; -} -.image-card .image-content > p { - color: #BFC2C6; -} -.image-card .image-content > button { - margin-top: 32px; - width: 100%; -} - -.login-body { - background: #FFFFFF; -} -.login-body .login-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - flex-direction: column; - height: 100vh; -} -.login-body .login-wrapper .login-panel { - width: 30%; - height: 100%; - text-align: center; - padding: 40px 20px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - flex: 1 1 100%; -} -.login-body .login-wrapper .login-panel .logo { - margin-bottom: 50px; -} -.login-body .login-wrapper .login-panel .logo img { - width: 45px; - height: 53px; -} -.login-body .login-wrapper .login-panel > a { - font-weight: 500; - font-size: 10px; - line-height: 12px; - color: rgba(41, 50, 65, 0.3); -} -.login-body .login-wrapper .login-panel > p { - font-weight: 500; - margin: 0; - color: rgba(41, 50, 65, 0.5); - margin-top: 40px; -} -.login-body .login-wrapper .login-panel > p > a { - color: #387fe9; - cursor: pointer; -} -.login-body .login-wrapper .login-panel > input { - width: 85%; - max-width: 247px; - margin-bottom: 10px; - background-color: #F6F7F7; - border: 1.2px solid #D4D6D9; - color: #515C66; - padding: 12px 10px; -} -.login-body .login-wrapper .login-panel > input::placeholder { - color: gba(41, 50, 65, 0.3); -} -.login-body .login-wrapper .login-panel > button { - width: 85%; - max-width: 247px; - margin-bottom: 10px; - padding: 0; -} -.login-body .login-wrapper .login-panel > button > span { - padding: 15px 20px; - display: block; - font-weight: 600; - font-size: 14px; - line-height: 16px; -} -.login-body .login-wrapper .login-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 70px; -} -.login-body .login-wrapper .login-footer h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.login-body .login-wrapper .login-footer h6 { - line-height: 17px; - margin: 0; - color: #BFC2C6; - font-weight: 500; -} - -@media (max-width: 992px) { - .login-body .login-wrapper .login-panel { - width: 100%; - } -} -.exception-body .exception-topbar { - height: 62px; - background-color: #293241; - box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 0 16px; -} -.exception-body .exception-topbar .layout-topbar-logo > img { - height: 15px; -} -.exception-body .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); -} -.exception-body .exception-wrapper .exception-content { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: center; - justify-content: center; - flex: 1 1 auto; -} -.exception-body .exception-wrapper .exception-content > span { - font-weight: normal; - font-size: 60px; - line-height: 73px; - text-align: center; - display: block; -} -.exception-body .exception-wrapper .exception-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 70px; -} -.exception-body .exception-wrapper .exception-footer h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.exception-body .exception-wrapper .exception-footer h6 { - line-height: 17px; - margin: 0; - color: #BFC2C6; - font-weight: 500; -} -.exception-body.notfound .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); -} -.exception-body.notfound .exception-wrapper .exception-content { - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: center; - justify-content: center; - -ms-flex-align: center; - align-items: center; - flex: 1 1 auto; -} -.exception-body.notfound .exception-wrapper .exception-content img { - width: 332px; - height: 271px; - margin-bottom: -150px; -} -.exception-body.notfound .exception-wrapper .exception-content > span { - font-size: 140px; - line-height: 171px; -} -.exception-body.notfound .exception-wrapper .exception-content > span.exception-subtitle { - font-weight: 500; - font-size: 14px; - line-height: 17px; - color: #BFC2C6; -} -.exception-body.notfound .exception-wrapper .exception-content > button { - padding: 0; - margin-top: 20px; - width: 155px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.exception-body.notfound .exception-wrapper .exception-content > button > span { - padding: 18px; - font-weight: 600; -} - -@media (max-width: 991px) { - .exception-body .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); - } - .exception-body .exception-wrapper .exception-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 20px; - } -} -.landing-body { - background-color: #E5E5E5; -} -.landing-body .landing-topbar { - height: 83px; - background-color: #FFFFFF; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - width: 100%; - z-index: 999; - padding: 20px 40px; - position: relative; -} -.landing-body .landing-topbar .landing-topbar-left { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.landing-body .landing-topbar .landing-topbar-left .logo { - margin-right: 40px; -} -.landing-body .landing-topbar .landing-topbar-left .logo img { - height: 16px; - width: auto; -} -.landing-body .landing-topbar .landing-topbar-left > ul { - list-style-type: none; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin: 0; - padding: 0; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li #landing-menu-close { - display: none; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li > a { - font-weight: 600; - font-size: 12px; - line-height: 14px; - color: rgba(41, 50, 65, 0.9); - padding: 14px 10px; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - margin: 0 10px; - min-width: 100px; - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li > a:hover { - color: #387fe9; -} -.landing-body .landing-topbar .landing-topbar-right .second-menubutton { - margin-right: 20px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - color: rgba(41, 50, 65, 0.9); - padding: 14px 10px; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - min-width: 100px; - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.landing-body .landing-topbar .landing-topbar-right .second-menubutton:hover { - color: #387fe9; -} -.landing-body .landing-topbar .landing-topbar-right .landing-button span { - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.landing-body .landing-topbar .landing-topbar-right #landing-menu-button { - display: none; - padding: 0 8px; - cursor: pointer; -} -.landing-body .landing-topbar .landing-topbar-right #landing-menu-button i { - font-size: 20px; -} -.landing-body .landing-button { - background: linear-gradient(108.43deg, #297FFF 12.5%, #7A0EE7 96.32%); - border: none; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.landing-body .landing-button.ui-button { - padding: 0; -} -.landing-body .landing-button.ui-button > .ui-button-text { - padding: 14px 10px; - min-width: 121px; - font-weight: 600; - font-size: 16px; - line-height: 19px; - display: block; -} -.landing-body .landing-button > a .ui-button-text { - padding: 14px 10px; - min-width: 87px; - font-weight: 600; - font-size: 16px; - line-height: 19px; - display: block; -} -.landing-body .landing-button:hover { - background: linear-gradient(108.43deg, #2f79e7 12.5%, #781cd4 96.32%); -} -.landing-body .landing-banner { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - padding: 303px 30px 218px; - position: relative; - transform-style: inherit; - background: url("#{resource['freya-layout:images/pages/asset-landing-header.jpg']}"); - background-size: cover; - height: 80vh; -} -.landing-body .landing-banner .landing-banner-content { - text-align: center; - position: relative; -} -.landing-body .landing-banner .landing-banner-content .title { - display: block; - font-weight: 500; - font-size: 70px; - line-height: 84px; - color: #FFFFFF; -} -.landing-body .landing-banner .landing-banner-content h3 { - margin: 40px 0 30px; - color: #FFFFFF; - font-weight: 500; - line-height: 29px; -} -.landing-body .section-header { - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-direction: column; -} -.landing-body .section-header .title { - display: block; - font-weight: 500; - font-size: 70px; - line-height: 84px; - color: rgba(41, 50, 65, 0.9); -} -.landing-body .section-header h3 { - margin: 15px 0 100px; - color: rgba(41, 50, 65, 0.9); - font-weight: 500; - line-height: 29px; - max-width: 800px; -} -.landing-body .landing-features { - background-color: #FFFFFF; - position: relative; - display: -ms-flexbox; - display: flex; - flex-wrap: wrap; - padding: 36px 6% 125px; -} -.landing-body .landing-features .lg\:col-3 { - transition: transform 250ms linear; - -webkit-transition: transform 250ms linear; -} -.landing-body .landing-features .feature { - display: -ms-flexbox; - display: flex; -} -.landing-body .landing-features .feature > span { - font-weight: 500; - font-size: 20px; - line-height: 20px; - color: rgba(41, 50, 65, 0.8); - margin-top: 30px; - margin-right: 12px; -} -.landing-body .landing-features .feature .feature-card { - -moz-border-radius: 36px; - -webkit-border-radius: 36px; - border-radius: 36px; - padding: 28px 30px; - display: -ms-flexbox; - display: flex; - width: 100%; -} -.landing-body .landing-features .feature .feature-card > span { - display: none; -} -.landing-body .landing-features .feature .feature-card h3 { - font-weight: 500; - line-height: 36px; - margin: 0 0 20px; - color: rgba(41, 50, 65, 0.8); -} -.landing-body .landing-features .feature .feature-card h5 { - margin: 0; - font-weight: normal; - line-height: 150%; - color: rgba(41, 50, 65, 0.9); - opacity: 0.8; -} -.landing-body .landing-features .feature.yellow .feature-card { - padding-bottom: 128px; - background: linear-gradient(197.55deg, #FFD37D -1.02%, #FFDB7D 46.53%); -} -.landing-body .landing-features .feature.blue .feature-card { - padding-bottom: 67px; - background: linear-gradient(156.18deg, #DAF4FF 38.02%, #CEDFFF 95.69%); -} -.landing-body .landing-features .feature.darker-blue .feature-card { - padding-bottom: 164px; - background: linear-gradient(165.84deg, #C1E9FF 42.24%, rgba(219, 242, 255, 0.23) 97.17%); -} -.landing-body .landing-features .feature.darker-gray .feature-card { - padding-bottom: 109px; - background: linear-gradient(176.91deg, rgba(41, 50, 65, 0.6) 50%, rgba(41, 50, 65, 0.282) 115.03%); -} -.landing-body .landing-features .feature.darker-gray .feature-card h3 { - color: #FFFFFF; -} -.landing-body .landing-features .feature.darker-gray .feature-card h5 { - color: #FFFFFF; - opacity: 0.8; -} -.landing-body .landing-features .feature.gray .feature-card { - padding-bottom: 50px; - background: linear-gradient(11.49deg, rgba(41, 50, 65, 0.1) 60.37%, rgba(41, 50, 65, 0.026) 98.03%); -} -.landing-body .landing-pricing { - background-color: #FFFFFF; - position: relative; - padding: 125px 15% 260px; - text-align: center; -} -.landing-body .landing-pricing .pricing-card { - background: #FFFFFF; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - padding: 30px 20px 33px; - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-direction: column; - position: relative; - margin-bottom: 60px; -} -.landing-body .landing-pricing .pricing-card .preferred-tag { - padding: 14px 24px; - background: linear-gradient(112.58deg, #FFD029 22.19%, #F1AF60 100%); - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - transform: rotate(-7.18deg); - position: absolute; - top: -32px; - color: #FFFFFF; - font-weight: bold; - font-size: 20px; - line-height: 24px; -} -.landing-body .landing-pricing .pricing-card h2 { - margin: 0 0 14px; - color: rgba(41, 50, 65, 0.9); -} -.landing-body .landing-pricing .pricing-card .price { - display: block; - color: #2170E7; - font-weight: bold; - font-size: 80px; - line-height: 95px; -} -.landing-body .landing-pricing .pricing-card .time { - color: rgba(41, 50, 65, 0.5); - font-size: 12px; - line-height: 14px; - display: block; - margin-bottom: 32px; -} -.landing-body .landing-pricing .pricing-card > ul { - padding: 42px 0 0; - width: 100%; - margin: 0; - list-style: none; - border-top: 1px solid rgba(41, 50, 65, 0.1); -} -.landing-body .landing-pricing .pricing-card > ul > li { - font-size: 16px; - line-height: 205.34%; - color: rgba(41, 50, 65, 0.5); -} -.landing-body .landing-pricing .pricing-card.pro { - background: linear-gradient(333.31deg, #EFF3FB 6.36%, #FFFFFF 72.79%); -} -.landing-body .landing-pricing .pricing-card.enterprise { - background: linear-gradient(156.19deg, rgba(41, 50, 65, 0.8) 10.28%, rgba(35, 40, 49, 0.496) 87.74%); -} -.landing-body .landing-pricing .pricing-card.enterprise h2 { - margin: 0 0 14px; - color: #FFFFFF; -} -.landing-body .landing-pricing .pricing-card.enterprise .price { - color: #FFFFFF; -} -.landing-body .landing-pricing .pricing-card.enterprise .time { - color: #FFFFFF; - opacity: 0.6; -} -.landing-body .landing-pricing .pricing-card.enterprise > ul { - border-top: 1px solid rgba(255, 255, 255, 0.2); -} -.landing-body .landing-pricing .pricing-card.enterprise > ul > li { - color: #FFFFFF; -} -.landing-body .landing-pricing > a { - font-size: 24px; - line-height: 29px; - display: block; -} -.landing-body .layout-footer { - background-color: #FFFFFF; - position: relative; -} -.landing-body .layout-footer .footer-menutitle { - color: rgba(41, 50, 65, 0.2); -} -.landing-body .layout-footer .footer-subtitle { - color: rgba(41, 50, 65, 0.3); -} -.landing-body .layout-footer ul > li { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .layout-footer ul > li > a { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .layout-footer ul > li > a:hover { - color: rgba(41, 50, 65, 0.3); -} -.landing-body .layout-footer .newsletter-input { - background-color: rgba(41, 50, 65, 0.04); -} -.landing-body .layout-footer .footer-bottom { - color: rgba(41, 50, 65, 0.7); -} -.landing-body .layout-footer .footer-bottom h6 { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .landing-mask { - display: none; - width: 100%; - height: 100vh; - position: fixed; - top: 0; - left: 0; - background-color: rgba(0, 0, 0, 0.2); - z-index: 998; -} - -@media (max-width: 991px) { - .landing-body.block-scroll { - overflow: hidden; - } - .landing-body.block-scroll .landing-wrapper .landing-mask { - display: block; - } - .landing-body .landing-wrapper.landing-menu-active .landing-topbar .landing-menu { - transform: translate3d(0px, 0px, 0px); - } - .landing-body .landing-wrapper .landing-topbar { - padding: 0 13px; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu { - position: fixed; - flex-direction: column; - -ms-flex-align: end; - align-items: flex-end; - right: 0; - top: 0; - padding: 28px 15px; - z-index: 999; - width: 220px; - height: 100%; - background-color: #EEF5FF; - box-shadow: 0 24px 64px -2px rgba(0, 0, 0, 0.02), 0 6px 16px -2px rgba(0, 0, 0, 0.06), 0 2px 6px -2px rgba(0, 0, 0, 0.08); - transform: translate3d(260px, 0px, 0px); - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li { - margin: 0; - width: 100%; - margin-bottom: 12px; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a { - padding: 6px 16px; - font-size: 14px; - text-align: right; - background-color: #EEF5FF; - display: block; - color: rgba(41, 50, 65, 0.9); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a:hover { - color: rgba(41, 50, 65, 0.6); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close { - display: block; - font-size: 20px; - text-align: right; - color: rgba(41, 50, 65, 0.9); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close:hover { - color: rgba(41, 50, 65, 0.6); - } - .landing-body .landing-wrapper .landing-topbar #landing-menu-button { - display: block; - color: rgba(41, 50, 65, 0.9); - font-size: 20px; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .second-menubutton { - display: none; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .landing-button { - margin-right: 20px; - } - .landing-body .landing-wrapper .landing-banner { - background-position: top; - padding: 80px 23px; - -ms-flex-pack: start; - justify-content: flex-start; - height: auto; - top: auto !important; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content { - text-align: left; - max-width: 262px; - top: auto !important; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content > span { - font-size: 60px; - line-height: 91.84%; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content > h3 { - font-size: 18px; - line-height: 130%; - } - .landing-body .landing-wrapper .landing-features { - padding: 36px 20px 30px; - } - .landing-body .landing-wrapper .landing-features .lg\:col-3 { - transform: translateY(0) !important; - margin-top: auto !important; - } - .landing-body .landing-wrapper .landing-features .feature-empty { - display: none; - } - .landing-body .landing-wrapper .landing-features .feature-3 { - margin-top: auto; - } - .landing-body .landing-wrapper .landing-features .feature-4 { - margin-top: auto; - } - .landing-body .landing-wrapper .landing-features .feature > span { - display: none; - } - .landing-body .landing-wrapper .landing-features .feature .feature-card { - padding-bottom: 28px !important; - } - .landing-body .landing-wrapper .landing-features .feature .feature-card > span { - font-weight: 500; - font-size: 20px; - line-height: 20px; - color: rgba(41, 50, 65, 0.8); - margin-right: 12px; - margin-top: 8px; - display: block; - } - .landing-body .landing-wrapper .landing-features .feature.blue .feature-card { - flex-direction: row-reverse; - text-align: right; - } - .landing-body .landing-wrapper .landing-features .feature.blue .feature-card > span { - margin-right: 0px; - margin-left: 12px; - } - .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card { - flex-direction: row-reverse; - text-align: right; - } - .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card > span { - color: #FFFFFF; - float: right; - margin-right: 0px; - margin-left: 12px; - } - .landing-body .landing-wrapper .section-header .title { - font-size: 60px; - line-height: 72px; - } - .landing-body .landing-wrapper .section-header h3 { - font-size: 18px; - line-height: 130%; - } - .landing-body .landing-wrapper .landing-pricing { - padding: 30px 20px 97px; - } - .landing-body .landing-wrapper .landing-pricing .pricing-card { - margin-bottom: 20px; - } - .landing-body .landing-wrapper .landing-pricing .pricing-card > ul { - display: none; - } - .landing-body .landing-wrapper .landing-pricing .preferred { - order: -1 !important; - } - .landing-body .landing-wrapper .landing-pricing .preferred .pricing-card > ul { - display: block; - } -} -.help-page p { - margin: 0; -} -.help-page .help-search { - background-image: url("#{resource['freya-layout:images/pages/search.png']}"); - padding: 0; - text-align: center; -} -.help-page .help-search .help-search-content { - padding: 5rem 12rem; -} -.help-page .help-search .help-search-content h3 { - color: #EAEBEC; - font-weight: 500; -} -.help-page .help-search .search-container { - font-size: 1rem; - padding: 1rem; - position: relative; -} -.help-page .help-search .search-container input { - appearance: none; - font-size: 1rem; - text-indent: 2rem; - padding: 1rem; - width: 100%; -} -.help-page .help-search .search-container i { - width: 1rem; - position: absolute; - margin-left: 1rem; - top: 50%; - margin-top: -0.5rem; -} -.help-page .status-bars { - margin-top: 1rem; - display: -ms-flexbox; - display: flex; -} -.help-page .status-bars .status-bar { - flex: 1 1 0; - -ms-flex: 1 1 0px; - background: #6EC180; - height: 50px; - margin-right: 0.25rem; - transition: transform 0.2s; -} -.help-page .status-bars .status-bar:last-child { - margin-right: 0; -} -.help-page .status-bars .status-bar.status-bar-failure { - background: #FF6E49; -} -.help-page .status-bars .status-bar:hover { - transform: scale(1.1); -} -.help-page .status-bar-footer { - padding: 1rem 0 0 0; - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; -} -.help-page .blog-post { - border-radius: 4px; - padding: 20px; - margin: 3rem 2rem; - border: 1px solid #383838; - background-color: #293241; - position: relative; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.help-page .blog-post:last-child { - margin-bottom: 1rem; -} -.help-page .blog-post img { - width: 100%; - position: absolute; - left: 0; - top: 0; -} -.help-page .blog-post .blog-text h1 { - color: #EAEBEC; - margin-bottom: 1rem; - font-weight: 500; -} -.help-page .blog-post .blog-text span { - color: #BFC2C6; - line-height: 1.4; -} -.help-page .blog-post .blog-profile { - position: absolute; - top: -25px; - left: -25px; -} -.help-page .blog-post .blog-profile img { - width: 50px; - height: 50px; - border-radius: 50%; -} - -@media screen and (max-width: 991px) { - .help-page .help-search .help-search-content { - padding: 6rem 2rem; - } -} -.invoice { - padding: 2rem; -} -.invoice .invoice-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; -} -.invoice .invoice-company .logo-image { - height: 50px; - margin-bottom: 0.5rem; -} -.invoice .invoice-company div { - margin-bottom: 0.5rem; -} -.invoice .invoice-company .company-name { - font-weight: 500; - font-size: 1.5rem; -} -.invoice .invoice-title { - font-size: 2rem; - margin-bottom: 2rem; - text-align: right; - font-weight: 300; -} -.invoice .invoice-details { - width: 15rem; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} -.invoice .invoice-details > div { - width: 50%; - margin-bottom: 0.5rem; -} -.invoice .invoice-details .invoice-label { - text-align: left; - font-weight: 500; -} -.invoice .invoice-details .invoice-value { - text-align: right; -} -.invoice .invoice-to { - margin-top: 1.5rem; - padding-top: 2rem; - border-top: 1px solid #3E4754; -} -.invoice .invoice-to .bill-to { - font-size: 1.25rem; - font-weight: 500; - margin-bottom: 0.5rem; -} -.invoice .invoice-to .invoice-to-info div { - margin-bottom: 0.5rem; -} -.invoice .invoice-items { - margin-top: 2rem; - padding-top: 2rem; -} -.invoice .invoice-items table { - width: 100%; - border-collapse: collapse; -} -.invoice .invoice-items table tr { - border-bottom: 1px solid #3E4754; -} -.invoice .invoice-items table th { - font-weight: 500; -} -.invoice .invoice-items table th, .invoice .invoice-items table td { - padding: 1rem; - text-align: right; -} -.invoice .invoice-items table th:first-child, .invoice .invoice-items table td:first-child { - text-align: left; -} -.invoice .invoice-summary { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - margin-top: 2.5rem; - padding-top: 2.5rem; -} -.invoice .invoice-summary .invoice-value { - font-weight: 500; -} - -@media print { - body * { - visibility: hidden; - } - - #invoice-content * { - visibility: visible; - } - - #invoice-content { - width: 100%; - position: absolute; - left: 0; - top: 0; - padding: 0; - margin: 0; - background: #ffffff; - color: rgba(41, 50, 65, 0.8); - } - - .invoice .invoice-to { - border-top: 1px solid #F2F4F6; - } - .invoice .invoice-items table tr { - border-bottom: 1px solid #F2F4F6; - } -} -.layout-config { - width: 16rem; - height: 100%; - position: fixed; - right: 0; - top: 0; - padding: 1rem; - overflow: auto; - background: #1e1e1e; - z-index: 999; - border-left: 1px solid #383838; - transform: translateX(100%); - transition: transform 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); -} -.layout-config.layout-config-active { - transform: translateX(0); - box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); -} -.layout-config.layout-config-active .layout-config-content .layout-config-button i { - transform: rotate(360deg); -} -.layout-config .ui-selectoneradio td { - padding: 0.5rem; -} -.layout-config p { - line-height: 1.5rem; - color: rgba(255, 255, 255, 0.6); -} -.layout-config .layout-themes { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} -.layout-config .layout-themes > div { - padding: 0.25rem; -} -.layout-config .layout-themes a { - width: 2rem; - height: 2rem; - border-radius: 24px; - display: block; - position: relative; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - transition: transform 0.2s; - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); -} -.layout-config .layout-themes a i { - font-size: 1rem; - position: absolute; - top: 50%; - left: 50%; - margin-left: -0.5rem; - margin-top: -0.5rem; -} -.layout-config .layout-themes a:hover { - transform: scale(1.1); -} - -.layout-config-button { - display: block; - position: fixed; - width: 3rem; - height: 3rem; - line-height: 3rem; - background: #90CAF9; - color: #121212; - text-align: center; - top: 50%; - right: 0; - margin-top: -1.5rem; - border-top-left-radius: 24px; - border-bottom-left-radius: 24px; - transition: background-color 0.2s; - overflow: hidden; - cursor: pointer; - z-index: 999; - box-shadow: -0.25rem 0 1rem rgba(0, 0, 0, 0.15); -} -.layout-config-button i { - font-size: 2rem; - line-height: inherit; - transform: rotate(0deg); - transition: transform 1s; -} -.layout-config-button:hover { - background: #a8d6fa; -} - -/* Add your customizations of the layout styles here */ -.layout-wrapper .layout-rightpanel .rightpanel-wrapper { - position: relative; - height: 100%; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header { - text-align: center; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header .profile { - padding: 12px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions { - padding: 12px 6px 36px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .col-6, .layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .md\:col-4 { - padding: 0.2em; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav { - background-color: #384454; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header { - padding: 1rem; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header a { - font-size: 12px; - font-weight: 500; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header > span { - font-size: 10px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header.ui-state-active { - background-color: #303A48; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels { - background-color: #384454; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel { - padding: 0; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - width: 80%; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { - width: 105px; - margin-right: 7px; -} +/* Add your customizations of the layout variables here */ +@-webkit-keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} +@keyframes fadeInDown { + from { + opacity: 0; + transform: translate3d(0, -20px, 0); + } + to { + opacity: 1; + transform: none; + } +} +@-webkit-keyframes fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } +} +@keyframes fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } +} +@keyframes fadeinmask { + from { + opacity: 0; + } + to { + opacity: 0.8; + } +} +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes modal-in { + from { + background-color: transparent; + } + to { + background-color: rgba(0, 0, 0, 0.6); + } +} +@keyframes modal-in { + from { + background-color: transparent; + } + to { + background-color: rgba(0, 0, 0, 0.6); + } +} +.modal-in { + -webkit-animation-name: modal-in; + animation-name: modal-in; +} + +h1, h2, h3, h4, h5, h6 { + margin: 1.5rem 0 1rem 0; + font-family: inherit; + font-weight: 600; + line-height: 1.2; + color: inherit; +} +h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { + margin-top: 0; +} + +h1 { + font-size: 2.5rem; +} + +h2 { + font-size: 2rem; +} + +h3 { + font-size: 1.75rem; +} + +h4 { + font-size: 1.5rem; +} + +h5 { + font-size: 1.25rem; +} + +h6 { + font-size: 1rem; +} + +mark { + background: #FFF8E1; + padding: 0.25rem 0.4rem; + border-radius: 24px; + font-family: monospace; +} + +blockquote { + margin: 1rem 0; + padding: 0 2rem; + border-left: 4px solid #90A4AE; +} + +hr { + border-top: solid #383838; + border-width: 1px 0 0 0; + margin: 1rem 0; +} + +p { + margin: 0 0 1rem 0; + line-height: 1.5; +} +p:last-child { + margin-bottom: 0; +} + +html { + height: 100%; + font-size: 14px; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; + color: #EAEBEC; + padding: 0; + margin: 0; + min-height: 100%; + background-color: #3E4754; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +body.blocked-scroll { + overflow: auto; +} + +a { + text-decoration: none; + color: #669cee; + color: var(--primary-color); +} + +.ajax-loader { + font-size: 32px; + color: #387fe9; + color: var(--primary-color); +} + +.layout-main { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + min-height: 100vh; + padding-top: 82px; + -moz-transition: padding-left 0.2s; + -o-transition: padding-left 0.2s; + -webkit-transition: padding-left 0.2s; + transition: padding-left 0.2s; +} + +.layout-mask { + display: none; + position: fixed; + top: 0; + left: 0; + z-index: 998; + width: 100%; + height: 100%; + animation-duration: 0.2s; + animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); + animation-fill-mode: forwards; +} + +.layout-content { + padding: 30px 36px; + flex: 1 1 auto; +} + +@media (max-width: 991px) { + .layout-content { + padding: 32px 14px; + } +} +.layout-topbar-light .layout-topbar { + position: fixed; + top: 0; + z-index: 999; + width: 100%; + -moz-transition: width 0.2s; + -o-transition: width 0.2s; + -webkit-transition: width 0.2s; + transition: width 0.2s; + height: 62px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper { + height: 100%; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left { + height: 100%; + padding: 0 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + z-index: 999; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + height: 15px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { + height: 15px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + padding: 6px; + margin-right: 16px; + border-radius: 4px; + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { + font-size: 18px; + width: 18px; + height: 18px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right { + height: 100%; + flex-grow: 1; + padding: 0 16px 0 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + border-right: solid 1px transparent; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; + list-style-type: none; + margin: 0; + padding: 0; + height: 100%; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { + width: 100%; + padding: 6px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + display: none; + position: absolute; + top: 62px; + right: 0px; + list-style-type: none; + margin: 0; + padding: 7px 0 8px; + z-index: 1000; + -moz-border-radius-bottomleft: 2px; + -webkit-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; + -moz-border-radius-bottomright: 2px; + -webkit-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; + min-width: 250px; + animation-duration: 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { + padding: 10px 15px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + list-style: none; + margin-bottom: 4px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + margin-right: 10px; + padding: 6px; + border-radius: 2px; + width: 26px; + height: 26px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { + height: 36px; + width: 36px; + margin-right: 10px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { + width: auto; + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { + position: relative; + width: 0; + opacity: 0; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { + background: #303A48; + width: 100%; + position: relative; + padding: 9px; + padding-left: 37px; + border: none; + color: #FFFFFF; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { + position: absolute; + left: 9px; + font-size: 18px; + top: 50%; + margin-top: -9px; + display: none; + z-index: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { + margin-left: 16px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { + height: 28px; + width: 28px; + border-radius: 10px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { + width: 200px; + opacity: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + margin-left: 26px; + z-index: 1; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +@media (max-width: 991px) { + .layout-topbar-light .layout-topbar .layout-topbar-wrapper { + -ms-flex-align: start; + align-items: flex-start; + position: relative; + padding: 0 6px; + } +} +@media (max-width: 576px) { + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + left: 10px; + right: 10px; + position: fixed; + top: 62px; + } +} +.layout-topbar-light .layout-topbar { + background-color: #ffffff; + box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { + color: #293241; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + color: #293241; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { + background-color: #f8fafc; + border: 1px solid #ebedef; + color: #669cee; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { + color: #669cee; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { + color: #293241; + opacity: 0.5; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); + background-color: white; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { + background-color: #5d97ed; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { + color: #ffffff; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { + background-color: #5d97ed; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + color: #EAEBEC; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + background-color: rgba(56, 127, 233, 0.8); + color: #ffffff; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { + color: #BFC2C6; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { + color: #EAEBEC; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { + color: #BFC2C6; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + color: #293241; + background-color: transparent; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} + +.layout-topbar-dark .layout-topbar { + position: fixed; + top: 0; + z-index: 999; + width: 100%; + -moz-transition: width 0.2s; + -o-transition: width 0.2s; + -webkit-transition: width 0.2s; + transition: width 0.2s; + height: 62px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper { + height: 100%; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left { + height: 100%; + padding: 0 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + z-index: 999; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + height: 15px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { + height: 15px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + padding: 6px; + margin-right: 16px; + border-radius: 4px; + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { + font-size: 18px; + width: 18px; + height: 18px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right { + height: 100%; + flex-grow: 1; + padding: 0 16px 0 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + border-right: solid 1px transparent; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; + list-style-type: none; + margin: 0; + padding: 0; + height: 100%; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { + width: 100%; + padding: 6px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + display: none; + position: absolute; + top: 62px; + right: 0px; + list-style-type: none; + margin: 0; + padding: 7px 0 8px; + z-index: 1000; + -moz-border-radius-bottomleft: 2px; + -webkit-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; + -moz-border-radius-bottomright: 2px; + -webkit-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; + min-width: 250px; + animation-duration: 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { + padding: 10px 15px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + list-style: none; + margin-bottom: 4px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + margin-right: 10px; + padding: 6px; + border-radius: 2px; + width: 26px; + height: 26px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { + height: 36px; + width: 36px; + margin-right: 10px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { + width: auto; + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { + position: relative; + width: 0; + opacity: 0; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { + background: #303A48; + width: 100%; + position: relative; + padding: 9px; + padding-left: 37px; + border: none; + color: #FFFFFF; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { + position: absolute; + left: 9px; + font-size: 18px; + top: 50%; + margin-top: -9px; + display: none; + z-index: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { + margin-left: 16px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { + height: 28px; + width: 28px; + border-radius: 10px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { + width: 200px; + opacity: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + margin-left: 26px; + z-index: 1; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +@media (max-width: 991px) { + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper { + -ms-flex-align: start; + align-items: flex-start; + position: relative; + padding: 0 6px; + } +} +@media (max-width: 576px) { + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + left: 10px; + right: 10px; + position: fixed; + top: 62px; + } +} +.layout-topbar-dark .layout-topbar { + background-color: #293241; + box-shadow: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { + background-color: #333e51; + border: 1px solid #333e51; + color: #94baf3; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { + color: #94baf3; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { + color: #E9E9E9; + opacity: 0.5; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); + background-color: #333e51; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { + background-color: #5d97ed; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { + color: #ffffff; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { + background-color: #5d97ed; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + background-color: rgba(56, 127, 233, 0.8); + color: #ffffff; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { + color: #C2C2C2; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { + color: #C2C2C2; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + color: #E9E9E9; + background-color: transparent; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} + +.menu-wrapper { + height: 100%; + position: fixed; + top: 0; + z-index: 999; + left: 0; +} +.menu-wrapper .sidebar-logo { + height: 62px; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: start; + justify-content: flex-start; + -ms-flex-align: center; + align-items: center; + padding: 0 22px; + padding-right: 20px; +} +.menu-wrapper .sidebar-logo .sidebar-pin { + display: none; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.menu-wrapper .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #383838; +} +.menu-wrapper .sidebar-logo img { + width: 17px; + height: 20px; + border: 0 none; +} +.menu-wrapper .layout-menu-container { + height: calc(100% - 62px); +} +.menu-wrapper .layout-menu-container .layout-menu { + list-style-type: none; + margin: 0; + padding: 0; + max-width: 62px; + overflow: hidden; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.menu-wrapper .layout-menu-container .layout-menu > li > a { + position: relative; +} +.menu-wrapper .layout-menu-container .layout-menu > li > a::before { + content: ""; + width: 4px; + height: 12px; + display: block; + border-radius: 0px 3px 3px 0px; + position: absolute; + left: 0; +} +.menu-wrapper .layout-menu-container .layout-menu > li > ul > li { + margin-left: 6px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} +.menu-wrapper .layout-menu-container .layout-menu li { + padding: 10px 0; +} +.menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -o-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); +} +.menu-wrapper .layout-menu-container .layout-menu li .layout-menu-tooltip { + display: none; +} +.menu-wrapper .layout-menu-container .layout-menu li > a { + margin: 0px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + font-size: 13px; + padding: 6px 20px; + user-select: none; + cursor: pointer; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > span { + margin: 0 8px; + margin-left: 14px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + visibility: hidden; + white-space: nowrap; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > i { + font-size: 24px; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > i.layout-submenu-toggler { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + margin-left: auto; + font-size: 12px; + visibility: hidden; +} +.menu-wrapper .layout-menu-container .layout-menu li > a.rotated-icon i { + transform: rotate(90deg); +} +.menu-wrapper .layout-menu-container .layout-menu li > ul { + display: none; + list-style-type: none; + overflow: hidden; + padding: 0; + margin: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul li ul { + display: none; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li { + padding: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li > a { + padding: 10px 18px; + margin-left: 0px; + padding-right: 8px; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li i { + font-size: 14px; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li ul li { + padding: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li.layout-root-menuitem > a { + display: -ms-flexbox; + display: flex; +} + +@media (min-width: 992px) { + .layout-wrapper.layout-sidebar .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + display: none; + } + .layout-wrapper.layout-sidebar .layout-main { + padding-left: 62px; + } + .layout-wrapper.layout-static .menu-wrapper { + transform: translate3d(0px, 0px, 0px); + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo { + justify-content: space-between; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo img { + display: inline; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .app-name { + display: inline; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin { + display: inline-block; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #383838; + border: 2px solid var(--primary-light-color); + background-color: #383838; + background-color: var(--primary-lighter-color); + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu > li { + min-width: 230px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-static .layout-main { + padding-left: 230px; + -moz-transition: padding-left 0.2s; + -o-transition: padding-left 0.2s; + -webkit-transition: padding-left 0.2s; + transition: padding-left 0.2s; + } + + .menu-wrapper.layout-sidebar-active { + transform: translate3d(0px, 0px, 0px); + } + .menu-wrapper.layout-sidebar-active .sidebar-logo { + justify-content: space-between; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo img { + display: inline; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .app-name { + display: inline; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin { + display: inline-block; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #383838; + } + .menu-wrapper.layout-sidebar-active .layout-menu { + max-width: 230px; + } + .menu-wrapper.layout-sidebar-active .layout-menu > li { + min-width: 230px; + } + .menu-wrapper.layout-sidebar-active .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li a { + padding-left: 20px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li a { + padding-left: 30px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .menu-wrapper.layout-sidebar-active .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .menu-wrapper.layout-sidebar-active .layout-menu-container { + overflow: auto; + } +} +@media (max-width: 991px) { + .layout-wrapper .menu-wrapper { + top: 62px; + z-index: 1010; + -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transform: translate3d(-230px, 0px, 0px); + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + } + .layout-wrapper .menu-wrapper .sidebar-logo { + display: none; + } + .layout-wrapper .menu-wrapper .layout-menu-container .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-mobile-active { + overflow: hidden; + height: 100vh; + } + .layout-wrapper.layout-mobile-active .menu-wrapper { + transform: translate3d(0px, 0px, 0px); + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li { + min-width: 230px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu-container { + overflow: auto; + } + .layout-wrapper.layout-mobile-active .layout-mask { + display: block; + } + .layout-wrapper .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + display: block; + } +} +@media (min-width: 992px) { + .layout-wrapper.layout-horizontal .menu-wrapper { + top: 0px; + width: 100%; + height: 62px; + position: relative; + } + .layout-wrapper.layout-horizontal .menu-wrapper .sidebar-logo { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container { + height: 100%; + display: flex; + align-items: center; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu { + list-style-type: none; + margin: 0px 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: row; + flex-direction: row; + max-width: 100%; + overflow: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -o-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li { + padding: 0; + position: relative; + margin: 0 9px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li .layout-menu-tooltip { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a { + margin: 0px; + padding: 10px 5px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a:before { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > span { + margin: 0 8px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + visibility: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i { + font-size: 14px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i.layout-submenu-toggler { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + margin-left: auto; + font-size: 12px; + visibility: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.layout-root-menuitem > div { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + display: none; + list-style-type: none; + top: 44px; + left: 0px; + width: 230px; + position: absolute; + padding: 10px; + margin: 0; + z-index: 100; + overflow: auto; + max-height: 460px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li { + border: 0 none; + margin: 0; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button-wrapper .menu-button { + display: none; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } +} +@media (min-width: 992px) { + .layout-wrapper.layout-slim .menu-wrapper { + width: 62px; + overflow: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container { + padding: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu { + overflow: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + display: none; + padding: 0 0.412px; + position: absolute; + left: 72px; + top: 16px; + line-height: 1; + border-radius: 2px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + padding: 6px 8px; + font-weight: 500; + min-width: 75px; + white-space: nowrap; + text-align: center; + -webkit-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + -moz-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: -4px; + margin-top: -5px; + border-width: 5px 5px 5px 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li { + position: relative; + padding: 10px 12px 10px 14px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a { + margin: 0px; + padding: 6px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + position: relative; + border: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:before { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a span { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i { + margin-right: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i.layout-submenu-toggler { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a .menuitem-badge { + display: none; + margin-left: auto; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:hover + .layout-menu-tooltip { + display: block; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + position: absolute; + top: 0; + left: 62px; + min-width: 250px; + max-height: 450px; + display: none; + padding: 10px; + overflow: auto; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li { + margin: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + padding: 10px 5px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > span { + visibility: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover + .layout-menu-tooltip { + display: none; + } + .layout-wrapper.layout-slim .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + display: none; + } + .layout-wrapper.layout-slim .layout-main { + padding-left: 62px; + } +} +.layout-menu-dark .menu-wrapper { + background-color: #293241; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: #293241; +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: #293241; + color: #387fe9; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-light-color); +} +@media (min-width: 992px) { + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-horizontal .menu-wrapper { + box-shadow: none; + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + background-color: #293241; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + background-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + color: #ffffff; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + border-right-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + background-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); + } +} +@media (max-width: 991px) { + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } +} + +.layout-menu-light .menu-wrapper { + background-color: #ffffff; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: #ffffff; +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: #ffffff; + color: #387fe9; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-color); +} +@media (min-width: 992px) { + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } + .layout-menu-light.layout-horizontal .menu-wrapper { + box-shadow: none; + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + background-color: #ffffff; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + background-color: #293241; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + color: #ffffff; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + border-right-color: #293241; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + background-color: #ffffff; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); + } +} +@media (max-width: 991px) { + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #387fe9; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #387fe9; + background-color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(56, 127, 233, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(56, 127, 233, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } +} + +.layout-rightpanel { + position: fixed; + z-index: 1000; + right: 0; + top: 62px; + height: calc(100% - 62px); + padding: 0; + width: 418px; + overflow: auto; + background-color: #303A48; + transform: translate3d(418px, 0px, 0px); + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-rightpanel .rightpanel-wrapper { + padding: 22px 20px 40px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section { + padding: 16px 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + margin-bottom: 16px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header > h6 { + margin: 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 14px 16px; + background-image: url("#{resource['demo:images/rightpanel/asset-weather.png']}"); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + -moz-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + color: rgba(41, 50, 65, 0.8); +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather > img { + height: 60px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info { + margin-left: 16px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h6 { + margin: 0 0 2px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h1 { + margin: 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul { + padding: 0; + margin: 0; + list-style: none; + overflow: auto; + max-height: 320px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li { + padding: 16px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + background-color: #293241; + margin-bottom: 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info h6 { + color: #FFFFFF; + margin: 0 0 4px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info > span { + display: block; + font-weight: 500; + font-size: 14px; + line-height: 140%; + color: #BFC2C6; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done { + opacity: 0.5; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done .task-info h6 { + text-decoration: line-through; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-wrap: wrap; + margin: -7px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + width: 80px; + height: 80px; + background-color: #293241; + margin: 7px; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item:hover { + background-color: #3E4754; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + width: 80px; + height: 80px; + margin: 7px; + border: 1px dashed #383838; + color: #383838; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item:hover { + background-color: #3E4754; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section { + margin-top: 40px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { + height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { + height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { + background-image: linear-gradient(180deg, #303A48 0%, rgba(234, 237, 243, 0) 100%); +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { + max-height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + background-color: #293241; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { + max-height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { + background-color: #293241; +} + +.layout-wrapper.layout-rightpanel-active .layout-rightpanel { + transform: translate3d(0px, 0px, 0px); +} + +@media (max-width: 576px) { + .layout-rightpanel { + width: 100%; + transform: translate3d(100%, 0px, 0px); + } +} +.layout-footer { + padding: 30px 36px; +} +.layout-footer .footer-menutitle { + color: #BFC2C6; + font-weight: 600; + font-size: 12px; + line-height: 14px; + min-height: 15px; + display: block; + margin-bottom: 9px; +} +.layout-footer .footer-subtitle { + font-weight: 500; + font-size: 14px; + display: block; + color: #BFC2C6; +} +.layout-footer ul { + padding: 0; + margin: 0; + list-style: none; +} +.layout-footer ul > li { + padding: 7px 0; +} +.layout-footer ul > li > a { + color: #EAEBEC; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.layout-footer ul > li > a:hover { + color: #BFC2C6; +} +.layout-footer .newsletter-input { + margin-top: 16px; + background-color: #293241; + position: relative; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.layout-footer .newsletter-input > input { + width: 100%; + background-color: transparent; + border: none; + padding: 11px 16px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + font-size: 14px; + line-height: 200%; +} +.layout-footer .newsletter-input > button { + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + position: absolute; + right: 6px; + top: 50%; + margin-top: -16px; +} +.layout-footer .newsletter-input > button > span { + display: block; + padding: 0; + width: 100%; + font-weight: 600; + font-size: 14px; +} +.layout-footer .footer-bottom { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-footer .footer-bottom h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.layout-footer .footer-bottom h6 { + line-height: 17px; + margin: 0; + color: #BFC2C6; + font-weight: 500; +} + +/* Utils */ +.clearfix:after { + content: " "; + display: block; + clear: both; +} + +.card { + background: #293241; + padding: 20px; + box-sizing: border-box; + box-shadow: 0 10px 40px rgba(41, 50, 65, 0.06); + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + margin-bottom: 2rem; +} +.card:last-child { + margin-bottom: 0; +} +.card .card-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + padding-bottom: 16px; +} +.card .card-header h6 { + margin-bottom: 2px; +} +.card .card-header .subtitle { + font-weight: 600; + color: #BFC2C6; +} +.card .card-subtitle { + color: #BFC2C6; + font-weight: 600; + margin: -1rem 0 1rem 0; +} +.card.no-gutter { + margin-bottom: 0; +} + +.sr-only { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + word-wrap: normal !important; +} + +.ui-text-secondary { + color: #BFC2C6; +} + +.layout-wrapper .layout-ajax-loader { + position: absolute; + right: 15px; + bottom: 70px; +} +.layout-wrapper .layout-ajax-loader .layout-ajax-loader-icon { + color: red; + font-size: 32px; +} + +.layout-dashboard .chart { + overflow: auto; + position: relative; +} +.layout-dashboard .mobile-teams { + display: none; +} + +@media (max-width: 1200px) { + .layout-dashboard .desktop-teams { + display: none; + } + .layout-dashboard .mobile-teams { + display: block; + } + .layout-dashboard .mobile-teams .team { + height: 100%; + flex-direction: column; + -ms-flex-pack: start; + justify-content: flex-start; + -ms-flex-align: start; + align-items: flex-start; + } + .layout-dashboard .mobile-teams .team .peoples { + margin: 12px -8px; + } +} +.overview-box { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + padding-top: 24px; + height: 100%; + min-width: 200px; +} +.overview-box .overview-info > h6 { + margin: 0 0 2px; +} +.overview-box .overview-info > h1 { + margin: 0; +} +.overview-box > i { + font-size: 24px; +} +.overview-box.white { + background: #FFFFFF; + color: rgba(41, 50, 65, 0.8); +} +.overview-box.blue { + background: #69B7FF; + color: #FFFFFF; +} +.overview-box.gray { + background: rgba(41, 50, 65, 0.4); + color: #FFFFFF; +} +.overview-box.darkgray { + background: rgba(41, 50, 65, 0.8); + color: #FFFFFF; +} +.overview-box.orange { + background: linear-gradient(90deg, #FFB340 0%, #FFA740 100%); + color: #FFFFFF; +} + +.timeline { + padding-right: 4px; +} +.timeline > ul { + padding: 0; + margin: 0; + list-style: none; + max-height: 372px; + overflow: auto; + margin-bottom: 1em; +} +.timeline > ul > li { + display: -ms-flexbox; + display: flex; + margin-bottom: 16px; +} +.timeline > ul > li > i { + font-size: 8px; + margin-right: 10px; + margin-top: 4px; +} +.timeline > ul > li .event-content span { + display: block; + margin-bottom: 4px; + font-weight: 600; + font-size: 12px; + color: #BFC2C6; +} +.timeline > ul > li .event-content span.event-title { + color: #FFFFFF; +} +.timeline > ul > li .event-content span.time { + font-size: 10px; + font-weight: 400; + color: #BFC2C6; +} +.timeline > ul > li.blue > i { + color: #297FFF; +} +.timeline > ul > li.green > i { + color: #34B56F; +} +.timeline > ul > li.orange > i { + color: #FFA928; +} + +.device-status .content { + color: #BFC2C6; + line-height: 1.4; + margin-bottom: 20px; +} +.device-status .progress { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 10px 0; + color: #BFC2C6; +} +.device-status .progress > span { + min-width: 40px; +} +.device-status .progress .ui-progressbar { + width: 100%; + margin: 0 12px; + background: rgba(41, 127, 255, 0.2); + background: var(--primary-lighter-color); +} +.device-status .progress .ui-progressbar .ui-progressbar-value { + background: rgba(41, 127, 255, 0.2); + background: var(--primary-color); + opacity: 0.8; + border-radius: 24px; +} +.device-status .progress.active .ui-progressbar { + width: 100%; + margin: 0 12px; + background: rgba(41, 127, 255, 0.2); + background: var(--primary-lighter-color); +} +.device-status .progress.active .ui-progressbar .ui-progressbar-value { + background: linear-gradient(270deg, #42BBFF 0%, #6129FF 100%); + background: linear-gradient(270deg, var(--primary-lighter-color) 0%, var(--primary-color) 100%); + opacity: 0.8; +} +.device-status .device { + margin-bottom: 16px; +} +.device-status .device span { + color: #387fe9; + color: var(--primary-color); + font-size: 14px; + font-weight: 600; +} +.device-status .device span > span { + font-size: 8px; + font-weight: normal; +} +.device-status .device span.status { + font-size: 12px; + color: #BFC2C6; + margin-top: 4px; + display: block; +} + +.team { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} +.team .card-header { + padding: 0; + min-width: 70px; +} +.team .peoples { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-wrap: wrap; +} +.team .peoples > img { + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + margin: 8px 8px; + width: 32px; + height: 32px; +} +.team .peoples .no-picture { + cursor: pointer; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + margin: 8px 8px; + width: 32px; + height: 32px; + background: rgba(41, 50, 65, 0.1); + color: #EAEBEC; + font-size: 12px; + -moz-transition: background 0.2s; + -o-transition: background 0.2s; + -webkit-transition: background 0.2s; + transition: background 0.2s; +} +.team .peoples .no-picture:hover { + background: rgba(41, 50, 65, 0.2); +} + +.map { + padding: 0; +} +.map > img { + width: 100%; + height: auto; + border-radius: 24px 24px 12px 12px; +} +.map .map-content { + padding: 50px 20px 28px; +} +.map .map-content h6 { + margin: 0 0 16px; +} +.map .map-content .city { + margin-bottom: 16px; +} +.map .map-content .city span { + color: #387fe9; + color: var(--primary-color); + font-size: 14px; + font-weight: 600; +} +.map .map-content .city span > span { + font-size: 8px; + font-weight: normal; +} +.map .map-content .city span.status { + font-size: 12px; + color: #BFC2C6; + margin-top: 4px; + display: block; +} + +.schedule > p { + color: #BFC2C6; +} +.schedule > ul { + list-style: none; + padding: 0; + margin: 0; +} +.schedule > ul > li { + background: #3E4754; + border-radius: 8px; + margin-bottom: 10px; + padding: 5px 16px 12px; +} +.schedule > ul > li .schedule-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; +} +.schedule > ul > li .schedule-header h6 { + line-height: 24px; + margin: 0; +} +.schedule > ul > li .schedule-header span { + color: #BFC2C6; + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.schedule > ul > li > span { + margin-top: 4px; + color: #BFC2C6; + display: block; + font-size: 12px; + line-height: 14px; +} + +.statistics .statistic-item .item-title { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 4px; +} +.statistics .statistic-item .item-title span { + display: block; + margin-right: 12px; +} +.statistics .statistic-item .item-title h5 { + margin: 0; + font-weight: 700; +} +.statistics .statistic-item h6 { + margin: 0; + font-weight: 600; + color: #BFC2C6; +} + +.stocks ul { + list-style: none; + padding: 0; + margin: 0; +} +.stocks ul > li { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + background-color: #303A48; + padding: 0; + margin: 0 0 12px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + overflow: hidden; +} +.stocks ul > li .stock-name { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: #374250; + padding: 18px 10px; + min-width: 70px; + margin-right: 4px; +} +.stocks ul > li .stock-name h6 { + margin: 0; + color: #EAEBEC; + line-height: 17px; + font-weight: 600; +} +.stocks ul > li > img { + margin: 0 4px; + height: 25px; +} +.stocks ul > li .stock-price { + padding: 0 10px; + color: #34B56F; + margin: 0 4px; +} +.stocks ul > li .stock-price h6 { + line-height: 17px; + font-weight: 600; + display: inline-block; +} +.stocks ul > li .stock-price i { + display: inline-block; +} +.stocks ul > li .stock-status { + margin-left: 4px; + padding: 0 20px; +} +.stocks ul > li .stock-status span { + display: block; + font-weight: 600; + font-size: 10px; + line-height: 12px; + color: #BFC2C6; +} +.stocks ul > li.down .stock-price { + color: #FF6E49; +} +.stocks ul > li.same .stock-price { + color: #FFA928; +} +.stocks > .ui-button { + width: 100%; + margin-top: 30px; +} + +.operations { + overflow: auto; + position: relative; +} +.operations .insights { + padding: 16px 15px; + background-color: rgba(41, 127, 255, 0.04); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + margin: 12px 0 16px; +} +.operations .insights .insight-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 5px; +} +.operations .insights .insight-header h6 { + margin: 0 6px; +} +.operations .insights > ul { + list-style: none; + padding: 0; + margin: 0; +} +.operations .insights > ul > li { + margin: 8px 0; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + color: #BFC2C6; +} +.operations .insights > ul > li span { + font-weight: 600; +} +.operations .insights > ul > li span > span { + font-size: 8px; + line-height: 10px; + font-weight: normal; +} +.operations > button { + width: 100%; +} + +.notification { + padding: 30px 24px; + background-color: #293241; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.notification > h6 { + margin: 0; + color: #EAEBEC; +} +.notification > h6 > a { + margin-left: 10px; +} +.notification > h6 > a i { + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav { + background-color: transparent; + margin: 0 -10px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav:before { + display: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header { + padding: 9px 0 0; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: transparent; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + margin: 0 10px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a { + position: relative; + width: 52px; + height: 52px; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: #D0D6DD; + cursor: pointer; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + color: #387fe9; + color: var(--primary-color); + border: 0 none; + overflow: visible; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a img { + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a .ui-badge { + position: absolute; + bottom: -5px; + right: -5px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active { + padding: 0 0 9px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active a { + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.16), 0px 1px 2px rgba(41, 50, 65, 0.04), 0px 6px 12px rgba(41, 50, 65, 0.24); + border: 0 none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active:before { + content: ""; + width: 12px; + height: 2px; + background: #387fe9; + background: var(--primary-color); + border-radius: 3px; + position: absolute; + bottom: -10px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-hover { + border: none; + padding: 0 0 9px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels { + background-color: transparent; + border: none; + padding: 16px 0 0; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { + padding: 0; + height: 350px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + height: 350px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 44px; + background-image: linear-gradient(180deg, #293241 0%, rgba(234, 237, 243, 0) 100%); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { + max-height: 400px; + overflow: auto; + padding: 30px 6px 12px; + flex: 1 1 auto; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message { + display: -ms-flexbox; + display: flex; + flex-direction: column; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .name { + display: block; + color: #BFC2C6; + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + max-width: 250px; + padding: 8px 10px; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + background-color: #303A48; + margin-bottom: 8px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message p { + padding: 0; + margin: 0 0 2px; + color: #EAEBEC; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message span { + display: block; + font-weight: 600; + font-size: 10px; + line-height: 14px; + color: #BFC2C6; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send { + -ms-flex-align: end; + align-items: flex-end; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send .message span { + text-align: right; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message h4 { + color: #BFC2C6; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { + flex: 1 1 auto; + max-height: 400px; + overflow: auto; + padding: 0px 0 12px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul { + padding: 0; + margin: 0; + list-style: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 6px; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + cursor: pointer; + padding: 8px 10px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li img { + margin-right: 12px; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li h6 { + margin: 0 0 2px; + color: #EAEBEC; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li span { + display: block; + color: #BFC2C6; + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { + background-color: #303A48; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input { + margin-top: 30px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { + width: 100%; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + padding: 20px 19px; + background-color: #3E4754; + border: none; +} + +.image-card { + padding: 0; + position: relative; +} +.image-card > span { + position: absolute; + right: 20px; + top: 20px; +} +.image-card > img { + width: 100%; + height: auto; + border-radius: 24px 24px 12px 12px; +} +.image-card .image-content { + padding: 32px 20px 28px; +} +.image-card .image-content h6 { + margin: 0 0 8px; +} +.image-card .image-content > p { + color: #BFC2C6; +} +.image-card .image-content > button { + margin-top: 32px; + width: 100%; +} + +.login-body { + background: #FFFFFF; +} +.login-body .login-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + flex-direction: column; + height: 100vh; +} +.login-body .login-wrapper .login-panel { + width: 30%; + height: 100%; + text-align: center; + padding: 40px 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + flex: 1 1 100%; +} +.login-body .login-wrapper .login-panel .logo { + margin-bottom: 50px; +} +.login-body .login-wrapper .login-panel .logo img { + width: 45px; + height: 53px; +} +.login-body .login-wrapper .login-panel > a { + font-weight: 500; + font-size: 10px; + line-height: 12px; + color: rgba(41, 50, 65, 0.3); +} +.login-body .login-wrapper .login-panel > p { + font-weight: 500; + margin: 0; + color: rgba(41, 50, 65, 0.5); + margin-top: 40px; +} +.login-body .login-wrapper .login-panel > p > a { + color: #387fe9; + cursor: pointer; +} +.login-body .login-wrapper .login-panel > input { + width: 85%; + max-width: 247px; + margin-bottom: 10px; + background-color: #F6F7F7; + border: 1.2px solid #D4D6D9; + color: #515C66; + padding: 12px 10px; +} +.login-body .login-wrapper .login-panel > input::placeholder { + color: gba(41, 50, 65, 0.3); +} +.login-body .login-wrapper .login-panel > button { + width: 85%; + max-width: 247px; + margin-bottom: 10px; + padding: 0; +} +.login-body .login-wrapper .login-panel > button > span { + padding: 15px 20px; + display: block; + font-weight: 600; + font-size: 14px; + line-height: 16px; +} +.login-body .login-wrapper .login-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 70px; +} +.login-body .login-wrapper .login-footer h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.login-body .login-wrapper .login-footer h6 { + line-height: 17px; + margin: 0; + color: #BFC2C6; + font-weight: 500; +} + +@media (max-width: 992px) { + .login-body .login-wrapper .login-panel { + width: 100%; + } +} +.exception-body .exception-topbar { + height: 62px; + background-color: #293241; + box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0 16px; +} +.exception-body .exception-topbar .layout-topbar-logo > img { + height: 15px; +} +.exception-body .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); +} +.exception-body .exception-wrapper .exception-content { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + flex: 1 1 auto; +} +.exception-body .exception-wrapper .exception-content > span { + font-weight: normal; + font-size: 60px; + line-height: 73px; + text-align: center; + display: block; +} +.exception-body .exception-wrapper .exception-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 70px; +} +.exception-body .exception-wrapper .exception-footer h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.exception-body .exception-wrapper .exception-footer h6 { + line-height: 17px; + margin: 0; + color: #BFC2C6; + font-weight: 500; +} +.exception-body.notfound .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); +} +.exception-body.notfound .exception-wrapper .exception-content { + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-align: center; + align-items: center; + flex: 1 1 auto; +} +.exception-body.notfound .exception-wrapper .exception-content img { + width: 332px; + height: 271px; + margin-bottom: -150px; +} +.exception-body.notfound .exception-wrapper .exception-content > span { + font-size: 140px; + line-height: 171px; +} +.exception-body.notfound .exception-wrapper .exception-content > span.exception-subtitle { + font-weight: 500; + font-size: 14px; + line-height: 17px; + color: #BFC2C6; +} +.exception-body.notfound .exception-wrapper .exception-content > button { + padding: 0; + margin-top: 20px; + width: 155px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.exception-body.notfound .exception-wrapper .exception-content > button > span { + padding: 18px; + font-weight: 600; +} + +@media (max-width: 991px) { + .exception-body .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); + } + .exception-body .exception-wrapper .exception-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 20px; + } +} +.landing-body { + background-color: #E5E5E5; +} +.landing-body .landing-topbar { + height: 83px; + background-color: #FFFFFF; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + width: 100%; + z-index: 999; + padding: 20px 40px; + position: relative; +} +.landing-body .landing-topbar .landing-topbar-left { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.landing-body .landing-topbar .landing-topbar-left .logo { + margin-right: 40px; +} +.landing-body .landing-topbar .landing-topbar-left .logo img { + height: 16px; + width: auto; +} +.landing-body .landing-topbar .landing-topbar-left > ul { + list-style-type: none; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin: 0; + padding: 0; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li #landing-menu-close { + display: none; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li > a { + font-weight: 600; + font-size: 12px; + line-height: 14px; + color: rgba(41, 50, 65, 0.9); + padding: 14px 10px; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + margin: 0 10px; + min-width: 100px; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li > a:hover { + color: #387fe9; +} +.landing-body .landing-topbar .landing-topbar-right .second-menubutton { + margin-right: 20px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + color: rgba(41, 50, 65, 0.9); + padding: 14px 10px; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + min-width: 100px; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.landing-body .landing-topbar .landing-topbar-right .second-menubutton:hover { + color: #387fe9; +} +.landing-body .landing-topbar .landing-topbar-right .landing-button span { + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.landing-body .landing-topbar .landing-topbar-right #landing-menu-button { + display: none; + padding: 0 8px; + cursor: pointer; +} +.landing-body .landing-topbar .landing-topbar-right #landing-menu-button i { + font-size: 20px; +} +.landing-body .landing-button { + background: linear-gradient(108.43deg, #297FFF 12.5%, #7A0EE7 96.32%); + border: none; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.landing-body .landing-button.ui-button { + padding: 0; +} +.landing-body .landing-button.ui-button > .ui-button-text { + padding: 14px 10px; + min-width: 121px; + font-weight: 600; + font-size: 16px; + line-height: 19px; + display: block; +} +.landing-body .landing-button > a .ui-button-text { + padding: 14px 10px; + min-width: 87px; + font-weight: 600; + font-size: 16px; + line-height: 19px; + display: block; +} +.landing-body .landing-button:hover { + background: linear-gradient(108.43deg, #2f79e7 12.5%, #781cd4 96.32%); +} +.landing-body .landing-banner { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + padding: 303px 30px 218px; + position: relative; + transform-style: inherit; + background: url("#{resource['freya-layout:images/pages/asset-landing-header.jpg']}"); + background-size: cover; + height: 80vh; +} +.landing-body .landing-banner .landing-banner-content { + text-align: center; + position: relative; +} +.landing-body .landing-banner .landing-banner-content .title { + display: block; + font-weight: 500; + font-size: 70px; + line-height: 84px; + color: #FFFFFF; +} +.landing-body .landing-banner .landing-banner-content h3 { + margin: 40px 0 30px; + color: #FFFFFF; + font-weight: 500; + line-height: 29px; +} +.landing-body .section-header { + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-direction: column; +} +.landing-body .section-header .title { + display: block; + font-weight: 500; + font-size: 70px; + line-height: 84px; + color: rgba(41, 50, 65, 0.9); +} +.landing-body .section-header h3 { + margin: 15px 0 100px; + color: rgba(41, 50, 65, 0.9); + font-weight: 500; + line-height: 29px; + max-width: 800px; +} +.landing-body .landing-features { + background-color: #FFFFFF; + position: relative; + display: -ms-flexbox; + display: flex; + flex-wrap: wrap; + padding: 36px 6% 125px; +} +.landing-body .landing-features .lg\:col-3 { + transition: transform 250ms linear; + -webkit-transition: transform 250ms linear; +} +.landing-body .landing-features .feature { + display: -ms-flexbox; + display: flex; +} +.landing-body .landing-features .feature > span { + font-weight: 500; + font-size: 20px; + line-height: 20px; + color: rgba(41, 50, 65, 0.8); + margin-top: 30px; + margin-right: 12px; +} +.landing-body .landing-features .feature .feature-card { + -moz-border-radius: 36px; + -webkit-border-radius: 36px; + border-radius: 36px; + padding: 28px 30px; + display: -ms-flexbox; + display: flex; + width: 100%; +} +.landing-body .landing-features .feature .feature-card > span { + display: none; +} +.landing-body .landing-features .feature .feature-card h3 { + font-weight: 500; + line-height: 36px; + margin: 0 0 20px; + color: rgba(41, 50, 65, 0.8); +} +.landing-body .landing-features .feature .feature-card h5 { + margin: 0; + font-weight: normal; + line-height: 150%; + color: rgba(41, 50, 65, 0.9); + opacity: 0.8; +} +.landing-body .landing-features .feature.yellow .feature-card { + padding-bottom: 128px; + background: linear-gradient(197.55deg, #FFD37D -1.02%, #FFDB7D 46.53%); +} +.landing-body .landing-features .feature.blue .feature-card { + padding-bottom: 67px; + background: linear-gradient(156.18deg, #DAF4FF 38.02%, #CEDFFF 95.69%); +} +.landing-body .landing-features .feature.darker-blue .feature-card { + padding-bottom: 164px; + background: linear-gradient(165.84deg, #C1E9FF 42.24%, rgba(219, 242, 255, 0.23) 97.17%); +} +.landing-body .landing-features .feature.darker-gray .feature-card { + padding-bottom: 109px; + background: linear-gradient(176.91deg, rgba(41, 50, 65, 0.6) 50%, rgba(41, 50, 65, 0.282) 115.03%); +} +.landing-body .landing-features .feature.darker-gray .feature-card h3 { + color: #FFFFFF; +} +.landing-body .landing-features .feature.darker-gray .feature-card h5 { + color: #FFFFFF; + opacity: 0.8; +} +.landing-body .landing-features .feature.gray .feature-card { + padding-bottom: 50px; + background: linear-gradient(11.49deg, rgba(41, 50, 65, 0.1) 60.37%, rgba(41, 50, 65, 0.026) 98.03%); +} +.landing-body .landing-pricing { + background-color: #FFFFFF; + position: relative; + padding: 125px 15% 260px; + text-align: center; +} +.landing-body .landing-pricing .pricing-card { + background: #FFFFFF; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + padding: 30px 20px 33px; + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-direction: column; + position: relative; + margin-bottom: 60px; +} +.landing-body .landing-pricing .pricing-card .preferred-tag { + padding: 14px 24px; + background: linear-gradient(112.58deg, #FFD029 22.19%, #F1AF60 100%); + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + transform: rotate(-7.18deg); + position: absolute; + top: -32px; + color: #FFFFFF; + font-weight: bold; + font-size: 20px; + line-height: 24px; +} +.landing-body .landing-pricing .pricing-card h2 { + margin: 0 0 14px; + color: rgba(41, 50, 65, 0.9); +} +.landing-body .landing-pricing .pricing-card .price { + display: block; + color: #2170E7; + font-weight: bold; + font-size: 80px; + line-height: 95px; +} +.landing-body .landing-pricing .pricing-card .time { + color: rgba(41, 50, 65, 0.5); + font-size: 12px; + line-height: 14px; + display: block; + margin-bottom: 32px; +} +.landing-body .landing-pricing .pricing-card > ul { + padding: 42px 0 0; + width: 100%; + margin: 0; + list-style: none; + border-top: 1px solid rgba(41, 50, 65, 0.1); +} +.landing-body .landing-pricing .pricing-card > ul > li { + font-size: 16px; + line-height: 205.34%; + color: rgba(41, 50, 65, 0.5); +} +.landing-body .landing-pricing .pricing-card.pro { + background: linear-gradient(333.31deg, #EFF3FB 6.36%, #FFFFFF 72.79%); +} +.landing-body .landing-pricing .pricing-card.enterprise { + background: linear-gradient(156.19deg, rgba(41, 50, 65, 0.8) 10.28%, rgba(35, 40, 49, 0.496) 87.74%); +} +.landing-body .landing-pricing .pricing-card.enterprise h2 { + margin: 0 0 14px; + color: #FFFFFF; +} +.landing-body .landing-pricing .pricing-card.enterprise .price { + color: #FFFFFF; +} +.landing-body .landing-pricing .pricing-card.enterprise .time { + color: #FFFFFF; + opacity: 0.6; +} +.landing-body .landing-pricing .pricing-card.enterprise > ul { + border-top: 1px solid rgba(255, 255, 255, 0.2); +} +.landing-body .landing-pricing .pricing-card.enterprise > ul > li { + color: #FFFFFF; +} +.landing-body .landing-pricing > a { + font-size: 24px; + line-height: 29px; + display: block; +} +.landing-body .layout-footer { + background-color: #FFFFFF; + position: relative; +} +.landing-body .layout-footer .footer-menutitle { + color: rgba(41, 50, 65, 0.2); +} +.landing-body .layout-footer .footer-subtitle { + color: rgba(41, 50, 65, 0.3); +} +.landing-body .layout-footer ul > li { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .layout-footer ul > li > a { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .layout-footer ul > li > a:hover { + color: rgba(41, 50, 65, 0.3); +} +.landing-body .layout-footer .newsletter-input { + background-color: rgba(41, 50, 65, 0.04); +} +.landing-body .layout-footer .footer-bottom { + color: rgba(41, 50, 65, 0.7); +} +.landing-body .layout-footer .footer-bottom h6 { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .landing-mask { + display: none; + width: 100%; + height: 100vh; + position: fixed; + top: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.2); + z-index: 998; +} + +@media (max-width: 991px) { + .landing-body.block-scroll { + overflow: hidden; + } + .landing-body.block-scroll .landing-wrapper .landing-mask { + display: block; + } + .landing-body .landing-wrapper.landing-menu-active .landing-topbar .landing-menu { + transform: translate3d(0px, 0px, 0px); + } + .landing-body .landing-wrapper .landing-topbar { + padding: 0 13px; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu { + position: fixed; + flex-direction: column; + -ms-flex-align: end; + align-items: flex-end; + right: 0; + top: 0; + padding: 28px 15px; + z-index: 999; + width: 220px; + height: 100%; + background-color: #EEF5FF; + box-shadow: 0 24px 64px -2px rgba(0, 0, 0, 0.02), 0 6px 16px -2px rgba(0, 0, 0, 0.06), 0 2px 6px -2px rgba(0, 0, 0, 0.08); + transform: translate3d(260px, 0px, 0px); + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li { + margin: 0; + width: 100%; + margin-bottom: 12px; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a { + padding: 6px 16px; + font-size: 14px; + text-align: right; + background-color: #EEF5FF; + display: block; + color: rgba(41, 50, 65, 0.9); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a:hover { + color: rgba(41, 50, 65, 0.6); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close { + display: block; + font-size: 20px; + text-align: right; + color: rgba(41, 50, 65, 0.9); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close:hover { + color: rgba(41, 50, 65, 0.6); + } + .landing-body .landing-wrapper .landing-topbar #landing-menu-button { + display: block; + color: rgba(41, 50, 65, 0.9); + font-size: 20px; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .second-menubutton { + display: none; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .landing-button { + margin-right: 20px; + } + .landing-body .landing-wrapper .landing-banner { + background-position: top; + padding: 80px 23px; + -ms-flex-pack: start; + justify-content: flex-start; + height: auto; + top: auto !important; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content { + text-align: left; + max-width: 262px; + top: auto !important; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content > span { + font-size: 60px; + line-height: 91.84%; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content > h3 { + font-size: 18px; + line-height: 130%; + } + .landing-body .landing-wrapper .landing-features { + padding: 36px 20px 30px; + } + .landing-body .landing-wrapper .landing-features .lg\:col-3 { + transform: translateY(0) !important; + margin-top: auto !important; + } + .landing-body .landing-wrapper .landing-features .feature-empty { + display: none; + } + .landing-body .landing-wrapper .landing-features .feature-3 { + margin-top: auto; + } + .landing-body .landing-wrapper .landing-features .feature-4 { + margin-top: auto; + } + .landing-body .landing-wrapper .landing-features .feature > span { + display: none; + } + .landing-body .landing-wrapper .landing-features .feature .feature-card { + padding-bottom: 28px !important; + } + .landing-body .landing-wrapper .landing-features .feature .feature-card > span { + font-weight: 500; + font-size: 20px; + line-height: 20px; + color: rgba(41, 50, 65, 0.8); + margin-right: 12px; + margin-top: 8px; + display: block; + } + .landing-body .landing-wrapper .landing-features .feature.blue .feature-card { + flex-direction: row-reverse; + text-align: right; + } + .landing-body .landing-wrapper .landing-features .feature.blue .feature-card > span { + margin-right: 0px; + margin-left: 12px; + } + .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card { + flex-direction: row-reverse; + text-align: right; + } + .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card > span { + color: #FFFFFF; + float: right; + margin-right: 0px; + margin-left: 12px; + } + .landing-body .landing-wrapper .section-header .title { + font-size: 60px; + line-height: 72px; + } + .landing-body .landing-wrapper .section-header h3 { + font-size: 18px; + line-height: 130%; + } + .landing-body .landing-wrapper .landing-pricing { + padding: 30px 20px 97px; + } + .landing-body .landing-wrapper .landing-pricing .pricing-card { + margin-bottom: 20px; + } + .landing-body .landing-wrapper .landing-pricing .pricing-card > ul { + display: none; + } + .landing-body .landing-wrapper .landing-pricing .preferred { + order: -1 !important; + } + .landing-body .landing-wrapper .landing-pricing .preferred .pricing-card > ul { + display: block; + } +} +.help-page p { + margin: 0; +} +.help-page .help-search { + background-image: url("#{resource['freya-layout:images/pages/search.png']}"); + padding: 0; + text-align: center; +} +.help-page .help-search .help-search-content { + padding: 5rem 12rem; +} +.help-page .help-search .help-search-content h3 { + color: #EAEBEC; + font-weight: 500; +} +.help-page .help-search .search-container { + font-size: 1rem; + padding: 1rem; + position: relative; +} +.help-page .help-search .search-container input { + appearance: none; + font-size: 1rem; + text-indent: 2rem; + padding: 1rem; + width: 100%; +} +.help-page .help-search .search-container i { + width: 1rem; + position: absolute; + margin-left: 1rem; + top: 50%; + margin-top: -0.5rem; +} +.help-page .status-bars { + margin-top: 1rem; + display: -ms-flexbox; + display: flex; +} +.help-page .status-bars .status-bar { + flex: 1 1 0; + -ms-flex: 1 1 0px; + background: #6EC180; + height: 50px; + margin-right: 0.25rem; + transition: transform 0.2s; +} +.help-page .status-bars .status-bar:last-child { + margin-right: 0; +} +.help-page .status-bars .status-bar.status-bar-failure { + background: #FF6E49; +} +.help-page .status-bars .status-bar:hover { + transform: scale(1.1); +} +.help-page .status-bar-footer { + padding: 1rem 0 0 0; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; +} +.help-page .blog-post { + border-radius: 4px; + padding: 20px; + margin: 3rem 2rem; + border: 1px solid #383838; + background-color: #293241; + position: relative; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.help-page .blog-post:last-child { + margin-bottom: 1rem; +} +.help-page .blog-post img { + width: 100%; + position: absolute; + left: 0; + top: 0; +} +.help-page .blog-post .blog-text h1 { + color: #EAEBEC; + margin-bottom: 1rem; + font-weight: 500; +} +.help-page .blog-post .blog-text span { + color: #BFC2C6; + line-height: 1.4; +} +.help-page .blog-post .blog-profile { + position: absolute; + top: -25px; + left: -25px; +} +.help-page .blog-post .blog-profile img { + width: 50px; + height: 50px; + border-radius: 50%; +} + +@media screen and (max-width: 991px) { + .help-page .help-search .help-search-content { + padding: 6rem 2rem; + } +} +.invoice { + padding: 2rem; +} +.invoice .invoice-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; +} +.invoice .invoice-company .logo-image { + height: 50px; + margin-bottom: 0.5rem; +} +.invoice .invoice-company div { + margin-bottom: 0.5rem; +} +.invoice .invoice-company .company-name { + font-weight: 500; + font-size: 1.5rem; +} +.invoice .invoice-title { + font-size: 2rem; + margin-bottom: 2rem; + text-align: right; + font-weight: 300; +} +.invoice .invoice-details { + width: 15rem; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.invoice .invoice-details > div { + width: 50%; + margin-bottom: 0.5rem; +} +.invoice .invoice-details .invoice-label { + text-align: left; + font-weight: 500; +} +.invoice .invoice-details .invoice-value { + text-align: right; +} +.invoice .invoice-to { + margin-top: 1.5rem; + padding-top: 2rem; + border-top: 1px solid #3E4754; +} +.invoice .invoice-to .bill-to { + font-size: 1.25rem; + font-weight: 500; + margin-bottom: 0.5rem; +} +.invoice .invoice-to .invoice-to-info div { + margin-bottom: 0.5rem; +} +.invoice .invoice-items { + margin-top: 2rem; + padding-top: 2rem; +} +.invoice .invoice-items table { + width: 100%; + border-collapse: collapse; +} +.invoice .invoice-items table tr { + border-bottom: 1px solid #3E4754; +} +.invoice .invoice-items table th { + font-weight: 500; +} +.invoice .invoice-items table th, .invoice .invoice-items table td { + padding: 1rem; + text-align: right; +} +.invoice .invoice-items table th:first-child, .invoice .invoice-items table td:first-child { + text-align: left; +} +.invoice .invoice-summary { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + margin-top: 2.5rem; + padding-top: 2.5rem; +} +.invoice .invoice-summary .invoice-value { + font-weight: 500; +} + +@media print { + body * { + visibility: hidden; + } + + #invoice-content * { + visibility: visible; + } + + #invoice-content { + width: 100%; + position: absolute; + left: 0; + top: 0; + padding: 0; + margin: 0; + background: #ffffff; + color: rgba(41, 50, 65, 0.8); + } + + .invoice .invoice-to { + border-top: 1px solid #F2F4F6; + } + .invoice .invoice-items table tr { + border-bottom: 1px solid #F2F4F6; + } +} +.layout-config { + width: 16rem; + height: 100%; + position: fixed; + right: 0; + top: 0; + padding: 1rem; + overflow: auto; + background: #1e1e1e; + z-index: 999; + border-left: 1px solid #383838; + transform: translateX(100%); + transition: transform 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); +} +.layout-config.layout-config-active { + transform: translateX(0); + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); +} +.layout-config.layout-config-active .layout-config-content .layout-config-button i { + transform: rotate(360deg); +} +.layout-config .ui-selectoneradio td { + padding: 0.5rem; +} +.layout-config p { + line-height: 1.5rem; + color: rgba(255, 255, 255, 0.6); +} +.layout-config .layout-themes { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.layout-config .layout-themes > div { + padding: 0.25rem; +} +.layout-config .layout-themes a { + width: 2rem; + height: 2rem; + border-radius: 24px; + display: block; + position: relative; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + transition: transform 0.2s; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); +} +.layout-config .layout-themes a i { + font-size: 1rem; + position: absolute; + top: 50%; + left: 50%; + margin-left: -0.5rem; + margin-top: -0.5rem; +} +.layout-config .layout-themes a:hover { + transform: scale(1.1); +} + +.layout-config-button { + display: block; + position: fixed; + width: 3rem; + height: 3rem; + line-height: 3rem; + background: #90CAF9; + color: #121212; + text-align: center; + top: 50%; + right: 0; + margin-top: -1.5rem; + border-top-left-radius: 24px; + border-bottom-left-radius: 24px; + transition: background-color 0.2s; + overflow: hidden; + cursor: pointer; + z-index: 999; + box-shadow: -0.25rem 0 1rem rgba(0, 0, 0, 0.15); +} +.layout-config-button i { + font-size: 2rem; + line-height: inherit; + transform: rotate(0deg); + transition: transform 1s; +} +.layout-config-button:hover { + background: #a8d6fa; +} + +/* Add your customizations of the layout styles here */ +.layout-wrapper .layout-rightpanel .rightpanel-wrapper { + position: relative; + height: 100%; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header { + text-align: center; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header .profile { + padding: 12px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions { + padding: 12px 6px 36px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .col-6, .layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .md\:col-4 { + padding: 0.2em; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav { + background-color: #384454; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header { + padding: 1rem; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header a { + font-size: 12px; + font-weight: 500; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header > span { + font-size: 10px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header.ui-state-active { + background-color: #303A48; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels { + background-color: #384454; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel { + padding: 0; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + width: 80%; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { + width: 105px; + margin-right: 7px; +} diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.scss b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.scss index 1a4faa1..bf4e4a6 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.scss +++ b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-dark.scss @@ -1,5 +1,5 @@ -$primaryColor:lighten(#2170E7, 5%); -$primaryTextColor:#ffffff; - -@import '../../sass/variables/layout/_layout_dark'; +$primaryColor:lighten(#2170E7, 5%); +$primaryTextColor:#ffffff; + +@import '../../sass/variables/layout/_layout_dark'; @import '../../sass/layout/_layout'; \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.css b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.css index 258f85f..3de8fc9 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.css +++ b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.css @@ -1,4257 +1,4257 @@ -/* Add your customizations of the layout variables here */ -@-webkit-keyframes fadeInDown { - from { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - -webkit-transform: none; - transform: none; - } -} -@keyframes fadeInDown { - from { - opacity: 0; - transform: translate3d(0, -20px, 0); - } - to { - opacity: 1; - transform: none; - } -} -@-webkit-keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} -@keyframes fadeOutUp { - from { - opacity: 1; - } - to { - opacity: 0; - -webkit-transform: translate3d(0, -20px, 0); - transform: translate3d(0, -20px, 0); - } -} -@keyframes fadeinmask { - from { - opacity: 0; - } - to { - opacity: 0.8; - } -} -.fadeInDown { - -webkit-animation-name: fadeInDown; - animation-name: fadeInDown; -} - -.fadeOutUp { - -webkit-animation-name: fadeOutUp; - animation-name: fadeOutUp; -} - -@-webkit-keyframes modal-in { - from { - background-color: transparent; - } - to { - background-color: rgba(0, 0, 0, 0.6); - } -} -@keyframes modal-in { - from { - background-color: transparent; - } - to { - background-color: rgba(0, 0, 0, 0.6); - } -} -.modal-in { - -webkit-animation-name: modal-in; - animation-name: modal-in; -} - -h1, h2, h3, h4, h5, h6 { - margin: 1.5rem 0 1rem 0; - font-family: inherit; - font-weight: 600; - line-height: 1.2; - color: inherit; -} -h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { - margin-top: 0; -} - -h1 { - font-size: 2.5rem; -} - -h2 { - font-size: 2rem; -} - -h3 { - font-size: 1.75rem; -} - -h4 { - font-size: 1.5rem; -} - -h5 { - font-size: 1.25rem; -} - -h6 { - font-size: 1rem; -} - -mark { - background: #FFF8E1; - padding: 0.25rem 0.4rem; - border-radius: 24px; - font-family: monospace; -} - -blockquote { - margin: 1rem 0; - padding: 0 2rem; - border-left: 4px solid #90A4AE; -} - -hr { - border-top: solid #dee2e6; - border-width: 1px 0 0 0; - margin: 1rem 0; -} - -p { - margin: 0 0 1rem 0; - line-height: 1.5; -} -p:last-child { - margin-bottom: 0; -} - -html { - height: 100%; - font-size: 14px; -} - -body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: 14px; - font-weight: 400; - color: rgba(41, 50, 65, 0.8); - padding: 0; - margin: 0; - min-height: 100%; - background-color: #F2F4F6; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -body.blocked-scroll { - overflow: auto; -} - -a { - text-decoration: none; - color: #4f8eec; - color: var(--primary-color); -} - -.ajax-loader { - font-size: 32px; - color: #2170E7; - color: var(--primary-color); -} - -.layout-main { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - min-height: 100vh; - padding-top: 82px; - -moz-transition: padding-left 0.2s; - -o-transition: padding-left 0.2s; - -webkit-transition: padding-left 0.2s; - transition: padding-left 0.2s; -} - -.layout-mask { - display: none; - position: fixed; - top: 0; - left: 0; - z-index: 998; - width: 100%; - height: 100%; - animation-duration: 0.2s; - animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); - animation-fill-mode: forwards; -} - -.layout-content { - padding: 30px 36px; - flex: 1 1 auto; -} - -@media (max-width: 991px) { - .layout-content { - padding: 32px 14px; - } -} -.layout-topbar-light .layout-topbar { - position: fixed; - top: 0; - z-index: 999; - width: 100%; - -moz-transition: width 0.2s; - -o-transition: width 0.2s; - -webkit-transition: width 0.2s; - transition: width 0.2s; - height: 62px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper { - height: 100%; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left { - height: 100%; - padding: 0 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - z-index: 999; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - height: 15px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { - height: 15px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - padding: 6px; - margin-right: 16px; - border-radius: 4px; - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { - font-size: 18px; - width: 18px; - height: 18px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right { - height: 100%; - flex-grow: 1; - padding: 0 16px 0 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - border-right: solid 1px transparent; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; - list-style-type: none; - margin: 0; - padding: 0; - height: 100%; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - height: 100%; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { - width: 100%; - padding: 6px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - display: none; - position: absolute; - top: 62px; - right: 0px; - list-style-type: none; - margin: 0; - padding: 7px 0 8px; - z-index: 1000; - -moz-border-radius-bottomleft: 2px; - -webkit-border-bottom-left-radius: 2px; - border-bottom-left-radius: 2px; - -moz-border-radius-bottomright: 2px; - -webkit-border-bottom-right-radius: 2px; - border-bottom-right-radius: 2px; - min-width: 250px; - animation-duration: 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { - padding: 10px 15px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - cursor: pointer; - list-style: none; - margin-bottom: 4px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - margin-right: 10px; - padding: 6px; - border-radius: 2px; - width: 26px; - height: 26px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { - height: 36px; - width: 36px; - margin-right: 10px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { - width: auto; - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { - position: relative; - width: 0; - opacity: 0; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { - background: #F7FAFF; - width: 100%; - position: relative; - padding: 9px; - padding-left: 37px; - border: none; - color: #3E4754; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { - position: absolute; - left: 9px; - font-size: 18px; - top: 50%; - margin-top: -9px; - display: none; - z-index: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { - margin-left: 16px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { - height: 28px; - width: 28px; - border-radius: 10px; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { - width: 200px; - opacity: 1; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: none; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { - display: block; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - margin-left: 26px; - z-index: 1; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -@media (max-width: 991px) { - .layout-topbar-light .layout-topbar .layout-topbar-wrapper { - -ms-flex-align: start; - align-items: flex-start; - position: relative; - padding: 0 6px; - } -} -@media (max-width: 576px) { - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } - .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - left: 10px; - right: 10px; - position: fixed; - top: 62px; - } -} -.layout-topbar-light .layout-topbar { - background-color: #ffffff; - box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { - color: #293241; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - color: #293241; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { - background-color: #f8fafc; - border: 1px solid #ebedef; - color: #4f8eec; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { - color: #4f8eec; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { - color: #293241; - opacity: 0.5; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); - background-color: white; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { - background-color: #4688eb; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { - color: #ffffff; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { - background-color: #4688eb; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - color: rgba(41, 50, 65, 0.8); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - background-color: rgba(33, 112, 231, 0.8); - color: #ffffff; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { - color: rgba(41, 50, 65, 0.5); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { - color: rgba(41, 50, 65, 0.8); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { - color: rgba(41, 50, 65, 0.5); -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - color: #293241; - background-color: transparent; -} -.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { - background-color: #E8EDF0; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} - -.layout-topbar-dark .layout-topbar { - position: fixed; - top: 0; - z-index: 999; - width: 100%; - -moz-transition: width 0.2s; - -o-transition: width 0.2s; - -webkit-transition: width 0.2s; - transition: width 0.2s; - height: 62px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper { - height: 100%; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left { - height: 100%; - padding: 0 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - z-index: 999; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - height: 15px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { - height: 15px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - padding: 6px; - margin-right: 16px; - border-radius: 4px; - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { - font-size: 18px; - width: 18px; - height: 18px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right { - height: 100%; - flex-grow: 1; - padding: 0 16px 0 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - border-right: solid 1px transparent; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; - list-style-type: none; - margin: 0; - padding: 0; - height: 100%; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - height: 100%; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { - width: 100%; - padding: 6px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - background-color: transparent; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - display: none; - position: absolute; - top: 62px; - right: 0px; - list-style-type: none; - margin: 0; - padding: 7px 0 8px; - z-index: 1000; - -moz-border-radius-bottomleft: 2px; - -webkit-border-bottom-left-radius: 2px; - border-bottom-left-radius: 2px; - -moz-border-radius-bottomright: 2px; - -webkit-border-bottom-right-radius: 2px; - border-bottom-right-radius: 2px; - min-width: 250px; - animation-duration: 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: end; - justify-content: flex-end; - flex-grow: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { - padding: 10px 15px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - cursor: pointer; - list-style: none; - margin-bottom: 4px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - margin-right: 10px; - padding: 6px; - border-radius: 2px; - width: 26px; - height: 26px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { - height: 36px; - width: 36px; - margin-right: 10px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { - width: auto; - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { - position: relative; - width: 0; - opacity: 0; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { - background: #F7FAFF; - width: 100%; - position: relative; - padding: 9px; - padding-left: 37px; - border: none; - color: #3E4754; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { - position: absolute; - left: 9px; - font-size: 18px; - top: 50%; - margin-top: -9px; - display: none; - z-index: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { - margin-left: 16px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { - height: 28px; - width: 28px; - border-radius: 10px; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { - width: 200px; - opacity: 1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { - display: block; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - font-size: 18px; - border-radius: 6px; - width: 30px; - height: 30px; - margin-left: 26px; - z-index: 1; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -@media (max-width: 991px) { - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper { - -ms-flex-align: start; - align-items: flex-start; - position: relative; - padding: 0 6px; - } -} -@media (max-width: 576px) { - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } - .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - left: 10px; - right: 10px; - position: fixed; - top: 62px; - } -} -.layout-topbar-dark .layout-topbar { - background-color: #293241; - box-shadow: none; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { - background-color: #333e51; - border: 1px solid #333e51; - color: #7dabf1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { - color: #7dabf1; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { - color: #E9E9E9; - opacity: 0.5; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { - box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); - background-color: #333e51; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { - background-color: #4688eb; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { - color: #ffffff; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { - background-color: #4688eb; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { - background-color: rgba(33, 112, 231, 0.8); - color: #ffffff; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { - color: #C2C2C2; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { - color: #E9E9E9; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { - color: #C2C2C2; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { - color: #E9E9E9; - background-color: transparent; -} -.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { - background-color: #333e51; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} - -.menu-wrapper { - height: 100%; - position: fixed; - top: 0; - z-index: 999; - left: 0; -} -.menu-wrapper .sidebar-logo { - height: 62px; - display: -ms-flexbox; - display: flex; - -ms-flex-pack: start; - justify-content: flex-start; - -ms-flex-align: center; - align-items: center; - padding: 0 22px; - padding-right: 20px; -} -.menu-wrapper .sidebar-logo .sidebar-pin { - display: none; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.menu-wrapper .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #dee2e6; -} -.menu-wrapper .sidebar-logo img { - width: 17px; - height: 20px; - border: 0 none; -} -.menu-wrapper .layout-menu-container { - height: calc(100% - 62px); -} -.menu-wrapper .layout-menu-container .layout-menu { - list-style-type: none; - margin: 0; - padding: 0; - max-width: 62px; - overflow: hidden; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.menu-wrapper .layout-menu-container .layout-menu > li > a { - position: relative; -} -.menu-wrapper .layout-menu-container .layout-menu > li > a::before { - content: ""; - width: 4px; - height: 12px; - display: block; - border-radius: 0px 3px 3px 0px; - position: absolute; - left: 0; -} -.menu-wrapper .layout-menu-container .layout-menu > li > ul > li { - margin-left: 6px; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; -} -.menu-wrapper .layout-menu-container .layout-menu li { - padding: 10px 0; -} -.menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { - -webkit-transform: rotate(-180deg); - -moz-transform: rotate(-180deg); - -o-transform: rotate(-180deg); - -ms-transform: rotate(-180deg); - transform: rotate(-180deg); -} -.menu-wrapper .layout-menu-container .layout-menu li .layout-menu-tooltip { - display: none; -} -.menu-wrapper .layout-menu-container .layout-menu li > a { - margin: 0px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - font-size: 13px; - padding: 6px 20px; - user-select: none; - cursor: pointer; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > span { - margin: 0 8px; - margin-left: 14px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - visibility: hidden; - white-space: nowrap; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > i { - font-size: 24px; -} -.menu-wrapper .layout-menu-container .layout-menu li > a > i.layout-submenu-toggler { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - margin-left: auto; - font-size: 12px; - visibility: hidden; -} -.menu-wrapper .layout-menu-container .layout-menu li > a.rotated-icon i { - transform: rotate(90deg); -} -.menu-wrapper .layout-menu-container .layout-menu li > ul { - display: none; - list-style-type: none; - overflow: hidden; - padding: 0; - margin: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul li ul { - display: none; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li { - padding: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li > a { - padding: 10px 18px; - margin-left: 0px; - padding-right: 8px; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li i { - font-size: 14px; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li ul li { - padding: 0; -} -.menu-wrapper .layout-menu-container .layout-menu li > ul > li.layout-root-menuitem > a { - display: -ms-flexbox; - display: flex; -} - -@media (min-width: 992px) { - .layout-wrapper.layout-sidebar .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - display: none; - } - .layout-wrapper.layout-sidebar .layout-main { - padding-left: 62px; - } - .layout-wrapper.layout-static .menu-wrapper { - transform: translate3d(0px, 0px, 0px); - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo { - justify-content: space-between; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo img { - display: inline; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .app-name { - display: inline; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin { - display: inline-block; - } - .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #dee2e6; - border: 2px solid var(--primary-light-color); - background-color: #dee2e6; - background-color: var(--primary-lighter-color); - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu > li { - min-width: 230px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-static .layout-main { - padding-left: 230px; - -moz-transition: padding-left 0.2s; - -o-transition: padding-left 0.2s; - -webkit-transition: padding-left 0.2s; - transition: padding-left 0.2s; - } - - .menu-wrapper.layout-sidebar-active { - transform: translate3d(0px, 0px, 0px); - } - .menu-wrapper.layout-sidebar-active .sidebar-logo { - justify-content: space-between; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo img { - display: inline; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .app-name { - display: inline; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin { - display: inline-block; - } - .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin > span { - display: block; - height: 16px; - width: 16px; - -moz-border-radius: 50%; - -webkit-border-radius: 50%; - border-radius: 50%; - border: 2px solid #dee2e6; - } - .menu-wrapper.layout-sidebar-active .layout-menu { - max-width: 230px; - } - .menu-wrapper.layout-sidebar-active .layout-menu > li { - min-width: 230px; - } - .menu-wrapper.layout-sidebar-active .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li a { - padding-left: 20px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li a { - padding-left: 30px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .menu-wrapper.layout-sidebar-active .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .menu-wrapper.layout-sidebar-active .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .menu-wrapper.layout-sidebar-active .layout-menu-container { - overflow: auto; - } -} -@media (max-width: 991px) { - .layout-wrapper .menu-wrapper { - top: 62px; - z-index: 1010; - -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); - transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); - transform: translate3d(-230px, 0px, 0px); - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - } - .layout-wrapper .menu-wrapper .sidebar-logo { - display: none; - } - .layout-wrapper .menu-wrapper .layout-menu-container .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-mobile-active { - overflow: hidden; - height: 100vh; - } - .layout-wrapper.layout-mobile-active .menu-wrapper { - transform: translate3d(0px, 0px, 0px); - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu { - max-width: 230px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li { - min-width: 230px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li > ul > li { - margin-left: 10px; - margin-right: 12px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a > span { - visibility: visible; - white-space: normal; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu-container { - overflow: auto; - } - .layout-wrapper.layout-mobile-active .layout-mask { - display: block; - } - .layout-wrapper .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { - display: block; - } -} -@media (min-width: 992px) { - .layout-wrapper.layout-horizontal .menu-wrapper { - top: 0px; - width: 100%; - height: 62px; - position: relative; - } - .layout-wrapper.layout-horizontal .menu-wrapper .sidebar-logo { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container { - height: 100%; - display: flex; - align-items: center; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu { - list-style-type: none; - margin: 0px 16px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: row; - flex-direction: row; - max-width: 100%; - overflow: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { - -webkit-transform: rotate(-180deg); - -moz-transform: rotate(-180deg); - -o-transform: rotate(-180deg); - -ms-transform: rotate(-180deg); - transform: rotate(-180deg); - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li { - padding: 0; - position: relative; - margin: 0 9px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li .layout-menu-tooltip { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a { - margin: 0px; - padding: 10px 5px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a:before { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > span { - margin: 0 8px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - visibility: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i { - font-size: 14px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i.layout-submenu-toggler { - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - margin-left: auto; - font-size: 12px; - visibility: visible; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.layout-root-menuitem > div { - display: none; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - display: none; - list-style-type: none; - top: 44px; - left: 0px; - width: 230px; - position: absolute; - padding: 10px; - margin: 0; - z-index: 100; - overflow: auto; - max-height: 460px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li { - border: 0 none; - margin: 0; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button-wrapper .menu-button { - display: none; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { - display: block; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { - display: none; - } - .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { - display: block; - padding: 0; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - } -} -@media (min-width: 992px) { - .layout-wrapper.layout-slim .menu-wrapper { - width: 62px; - overflow: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container { - padding: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu { - overflow: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - display: none; - padding: 0 0.412px; - position: absolute; - left: 72px; - top: 16px; - line-height: 1; - border-radius: 2px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - padding: 6px 8px; - font-weight: 500; - min-width: 75px; - white-space: nowrap; - text-align: center; - -webkit-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - -moz-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - top: 50%; - left: -4px; - margin-top: -5px; - border-width: 5px 5px 5px 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li { - position: relative; - padding: 10px 12px 10px 14px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a { - margin: 0px; - padding: 6px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - position: relative; - border: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:before { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a span { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i { - margin-right: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i.layout-submenu-toggler { - display: none; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a .menuitem-badge { - display: none; - margin-left: auto; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:hover + .layout-menu-tooltip { - display: block; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - position: absolute; - top: 0; - left: 62px; - min-width: 250px; - max-height: 450px; - display: none; - padding: 10px; - overflow: auto; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li { - margin: 0; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - padding: 10px 5px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > span { - visibility: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > i.layout-submenu-toggler { - visibility: visible; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li a { - padding-left: 20px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li a { - padding-left: 30px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li a { - padding-left: 40px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li a { - padding-left: 50px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li a { - padding-left: 60px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 70px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 80px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 90px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { - padding-left: 100px; - } - .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover + .layout-menu-tooltip { - display: none; - } - .layout-wrapper.layout-slim .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { - display: none; - } - .layout-wrapper.layout-slim .layout-main { - padding-left: 62px; - } -} -.layout-menu-dark .menu-wrapper { - background-color: #293241; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: #293241; -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: #293241; - color: #2170E7; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); -} -.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-light-color); -} -@media (min-width: 992px) { - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-light-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-horizontal .menu-wrapper { - box-shadow: none; - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - background-color: #293241; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - background-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - color: #ffffff; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - border-right-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - background-color: #293241; - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); - } -} -@media (max-width: 991px) { - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-light-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #E9E9E9; - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(233, 233, 233, 0.8); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #E9E9E9; - } -} - -.layout-menu-light .menu-wrapper { - background-color: #ffffff; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: #ffffff; -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: #ffffff; - color: #2170E7; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); -} -.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-color); -} -@media (min-width: 992px) { - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } - .layout-menu-light.layout-horizontal .menu-wrapper { - box-shadow: none; - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { - background-color: #ffffff; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { - background-color: #293241; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { - color: #ffffff; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { - border-right-color: #293241; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - background-color: #ffffff; - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); - } -} -@media (max-width: 991px) { - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { - color: #293241; - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { - color: #2170E7; - color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { - background-color: #2170E7; - background-color: var(--primary-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { - background-color: rgba(33, 112, 231, 0.2); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - color: #293241; - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { - color: rgba(41, 50, 65, 0.7); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { - background-color: rgba(33, 112, 231, 0.1); - background-color: var(--primary-lighter-color); - } - .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { - color: #293241; - } -} - -.layout-rightpanel { - position: fixed; - z-index: 1000; - right: 0; - top: 62px; - height: calc(100% - 62px); - padding: 0; - width: 418px; - overflow: auto; - background-color: #F7FAFF; - transform: translate3d(418px, 0px, 0px); - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - -webkit-backface-visibility: hidden; - -moz-backface-visibility: hidden; - backface-visibility: hidden; - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); -} -.layout-rightpanel .rightpanel-wrapper { - padding: 22px 20px 40px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section { - padding: 16px 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - margin-bottom: 16px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header > h6 { - margin: 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 14px 16px; - background-image: url("#{resource['demo:images/rightpanel/asset-weather.png']}"); - background-position: center; - background-repeat: no-repeat; - background-size: cover; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - -webkit-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - -moz-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); - color: rgba(41, 50, 65, 0.8); -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather > img { - height: 60px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info { - margin-left: 16px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h6 { - margin: 0 0 2px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h1 { - margin: 0; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul { - padding: 0; - margin: 0; - list-style: none; - overflow: auto; - max-height: 320px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li { - padding: 16px; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - background-color: #ffffff; - margin-bottom: 12px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info h6 { - color: #3E4754; - margin: 0 0 4px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info > span { - display: block; - font-weight: 500; - font-size: 14px; - line-height: 140%; - color: rgba(41, 50, 65, 0.5); -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done { - opacity: 0.5; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done .task-info h6 { - text-decoration: line-through; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-wrap: wrap; - margin: -7px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - width: 80px; - height: 80px; - background-color: #ffffff; - margin: 7px; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item:hover { - background-color: #F7F7F8; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - width: 80px; - height: 80px; - margin: 7px; - border: 1px dashed #dee2e6; - color: #dee2e6; - -moz-transition: background-color 0.2s; - -o-transition: background-color 0.2s; - -webkit-transition: background-color 0.2s; - transition: background-color 0.2s; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item:hover { - background-color: #F7F7F8; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section { - margin-top: 40px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { - height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { - height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { - background-image: linear-gradient(180deg, #F7FAFF 0%, rgba(234, 237, 243, 0) 100%); -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { - max-height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - background-color: #ffffff; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { - max-height: 400px; -} -.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { - background-color: #ffffff; -} - -.layout-wrapper.layout-rightpanel-active .layout-rightpanel { - transform: translate3d(0px, 0px, 0px); -} - -@media (max-width: 576px) { - .layout-rightpanel { - width: 100%; - transform: translate3d(100%, 0px, 0px); - } -} -.layout-footer { - padding: 30px 36px; -} -.layout-footer .footer-menutitle { - color: rgba(41, 50, 65, 0.5); - font-weight: 600; - font-size: 12px; - line-height: 14px; - min-height: 15px; - display: block; - margin-bottom: 9px; -} -.layout-footer .footer-subtitle { - font-weight: 500; - font-size: 14px; - display: block; - color: rgba(41, 50, 65, 0.5); -} -.layout-footer ul { - padding: 0; - margin: 0; - list-style: none; -} -.layout-footer ul > li { - padding: 7px 0; -} -.layout-footer ul > li > a { - color: rgba(41, 50, 65, 0.8); - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.layout-footer ul > li > a:hover { - color: rgba(41, 50, 65, 0.5); -} -.layout-footer .newsletter-input { - margin-top: 16px; - background-color: #ffffff; - position: relative; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.layout-footer .newsletter-input > input { - width: 100%; - background-color: transparent; - border: none; - padding: 11px 16px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - font-size: 14px; - line-height: 200%; -} -.layout-footer .newsletter-input > button { - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - position: absolute; - right: 6px; - top: 50%; - margin-top: -16px; -} -.layout-footer .newsletter-input > button > span { - display: block; - padding: 0; - width: 100%; - font-weight: 600; - font-size: 14px; -} -.layout-footer .footer-bottom { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.layout-footer .footer-bottom h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.layout-footer .footer-bottom h6 { - line-height: 17px; - margin: 0; - color: rgba(41, 50, 65, 0.5); - font-weight: 500; -} - -/* Utils */ -.clearfix:after { - content: " "; - display: block; - clear: both; -} - -.card { - background: #ffffff; - padding: 20px; - box-sizing: border-box; - box-shadow: 0 10px 40px rgba(41, 50, 65, 0.06); - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - margin-bottom: 2rem; -} -.card:last-child { - margin-bottom: 0; -} -.card .card-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - padding-bottom: 16px; -} -.card .card-header h6 { - margin-bottom: 2px; -} -.card .card-header .subtitle { - font-weight: 600; - color: rgba(41, 50, 65, 0.5); -} -.card .card-subtitle { - color: rgba(41, 50, 65, 0.5); - font-weight: 600; - margin: -1rem 0 1rem 0; -} -.card.no-gutter { - margin-bottom: 0; -} - -.sr-only { - border: 0; - clip: rect(1px, 1px, 1px, 1px); - clip-path: inset(50%); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; - word-wrap: normal !important; -} - -.ui-text-secondary { - color: rgba(41, 50, 65, 0.5); -} - -.layout-wrapper .layout-ajax-loader { - position: absolute; - right: 15px; - bottom: 70px; -} -.layout-wrapper .layout-ajax-loader .layout-ajax-loader-icon { - color: red; - font-size: 32px; -} - -.layout-dashboard .chart { - overflow: auto; - position: relative; -} -.layout-dashboard .mobile-teams { - display: none; -} - -@media (max-width: 1200px) { - .layout-dashboard .desktop-teams { - display: none; - } - .layout-dashboard .mobile-teams { - display: block; - } - .layout-dashboard .mobile-teams .team { - height: 100%; - flex-direction: column; - -ms-flex-pack: start; - justify-content: flex-start; - -ms-flex-align: start; - align-items: flex-start; - } - .layout-dashboard .mobile-teams .team .peoples { - margin: 12px -8px; - } -} -.overview-box { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - padding-top: 24px; - height: 100%; - min-width: 200px; -} -.overview-box .overview-info > h6 { - margin: 0 0 2px; -} -.overview-box .overview-info > h1 { - margin: 0; -} -.overview-box > i { - font-size: 24px; -} -.overview-box.white { - background: #FFFFFF; - color: rgba(41, 50, 65, 0.8); -} -.overview-box.blue { - background: #69B7FF; - color: #FFFFFF; -} -.overview-box.gray { - background: rgba(41, 50, 65, 0.4); - color: #FFFFFF; -} -.overview-box.darkgray { - background: rgba(41, 50, 65, 0.8); - color: #FFFFFF; -} -.overview-box.orange { - background: linear-gradient(90deg, #FFB340 0%, #FFA740 100%); - color: #FFFFFF; -} - -.timeline { - padding-right: 4px; -} -.timeline > ul { - padding: 0; - margin: 0; - list-style: none; - max-height: 372px; - overflow: auto; - margin-bottom: 1em; -} -.timeline > ul > li { - display: -ms-flexbox; - display: flex; - margin-bottom: 16px; -} -.timeline > ul > li > i { - font-size: 8px; - margin-right: 10px; - margin-top: 4px; -} -.timeline > ul > li .event-content span { - display: block; - margin-bottom: 4px; - font-weight: 600; - font-size: 12px; - color: rgba(41, 50, 65, 0.5); -} -.timeline > ul > li .event-content span.event-title { - color: #3E4754; -} -.timeline > ul > li .event-content span.time { - font-size: 10px; - font-weight: 400; - color: rgba(41, 50, 65, 0.5); -} -.timeline > ul > li.blue > i { - color: #297FFF; -} -.timeline > ul > li.green > i { - color: #34B56F; -} -.timeline > ul > li.orange > i { - color: #FFA928; -} - -.device-status .content { - color: rgba(41, 50, 65, 0.5); - line-height: 1.4; - margin-bottom: 20px; -} -.device-status .progress { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 10px 0; - color: rgba(41, 50, 65, 0.5); -} -.device-status .progress > span { - min-width: 40px; -} -.device-status .progress .ui-progressbar { - width: 100%; - margin: 0 12px; - background: rgba(41, 127, 255, 0.2); - background: var(--primary-lighter-color); -} -.device-status .progress .ui-progressbar .ui-progressbar-value { - background: rgba(41, 127, 255, 0.2); - background: var(--primary-color); - opacity: 0.8; - border-radius: 24px; -} -.device-status .progress.active .ui-progressbar { - width: 100%; - margin: 0 12px; - background: rgba(41, 127, 255, 0.2); - background: var(--primary-lighter-color); -} -.device-status .progress.active .ui-progressbar .ui-progressbar-value { - background: linear-gradient(270deg, #42BBFF 0%, #6129FF 100%); - background: linear-gradient(270deg, var(--primary-lighter-color) 0%, var(--primary-color) 100%); - opacity: 0.8; -} -.device-status .device { - margin-bottom: 16px; -} -.device-status .device span { - color: #2170E7; - color: var(--primary-color); - font-size: 14px; - font-weight: 600; -} -.device-status .device span > span { - font-size: 8px; - font-weight: normal; -} -.device-status .device span.status { - font-size: 12px; - color: rgba(41, 50, 65, 0.5); - margin-top: 4px; - display: block; -} - -.team { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; -} -.team .card-header { - padding: 0; - min-width: 70px; -} -.team .peoples { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-wrap: wrap; -} -.team .peoples > img { - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - border-radius: 10px; - margin: 8px 8px; - width: 32px; - height: 32px; -} -.team .peoples .no-picture { - cursor: pointer; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - -moz-border-radius: 10px; - -webkit-border-radius: 10px; - border-radius: 10px; - margin: 8px 8px; - width: 32px; - height: 32px; - background: rgba(41, 50, 65, 0.1); - color: rgba(41, 50, 65, 0.8); - font-size: 12px; - -moz-transition: background 0.2s; - -o-transition: background 0.2s; - -webkit-transition: background 0.2s; - transition: background 0.2s; -} -.team .peoples .no-picture:hover { - background: rgba(41, 50, 65, 0.2); -} - -.map { - padding: 0; -} -.map > img { - width: 100%; - height: auto; - border-radius: 24px 24px 12px 12px; -} -.map .map-content { - padding: 50px 20px 28px; -} -.map .map-content h6 { - margin: 0 0 16px; -} -.map .map-content .city { - margin-bottom: 16px; -} -.map .map-content .city span { - color: #2170E7; - color: var(--primary-color); - font-size: 14px; - font-weight: 600; -} -.map .map-content .city span > span { - font-size: 8px; - font-weight: normal; -} -.map .map-content .city span.status { - font-size: 12px; - color: rgba(41, 50, 65, 0.5); - margin-top: 4px; - display: block; -} - -.schedule > p { - color: rgba(41, 50, 65, 0.5); -} -.schedule > ul { - list-style: none; - padding: 0; - margin: 0; -} -.schedule > ul > li { - background: #F7F7F8; - border-radius: 8px; - margin-bottom: 10px; - padding: 5px 16px 12px; -} -.schedule > ul > li .schedule-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; -} -.schedule > ul > li .schedule-header h6 { - line-height: 24px; - margin: 0; -} -.schedule > ul > li .schedule-header span { - color: rgba(41, 50, 65, 0.5); - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.schedule > ul > li > span { - margin-top: 4px; - color: rgba(41, 50, 65, 0.5); - display: block; - font-size: 12px; - line-height: 14px; -} - -.statistics .statistic-item .item-title { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 4px; -} -.statistics .statistic-item .item-title span { - display: block; - margin-right: 12px; -} -.statistics .statistic-item .item-title h5 { - margin: 0; - font-weight: 700; -} -.statistics .statistic-item h6 { - margin: 0; - font-weight: 600; - color: rgba(41, 50, 65, 0.5); -} - -.stocks ul { - list-style: none; - padding: 0; - margin: 0; -} -.stocks ul > li { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - background-color: #F7FAFF; - padding: 0; - margin: 0 0 12px; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - overflow: hidden; -} -.stocks ul > li .stock-name { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: #EEF5FF; - padding: 18px 10px; - min-width: 70px; - margin-right: 4px; -} -.stocks ul > li .stock-name h6 { - margin: 0; - color: rgba(41, 50, 65, 0.8); - line-height: 17px; - font-weight: 600; -} -.stocks ul > li > img { - margin: 0 4px; - height: 25px; -} -.stocks ul > li .stock-price { - padding: 0 10px; - color: #34B56F; - margin: 0 4px; -} -.stocks ul > li .stock-price h6 { - line-height: 17px; - font-weight: 600; - display: inline-block; -} -.stocks ul > li .stock-price i { - display: inline-block; -} -.stocks ul > li .stock-status { - margin-left: 4px; - padding: 0 20px; -} -.stocks ul > li .stock-status span { - display: block; - font-weight: 600; - font-size: 10px; - line-height: 12px; - color: rgba(41, 50, 65, 0.5); -} -.stocks ul > li.down .stock-price { - color: #FF6E49; -} -.stocks ul > li.same .stock-price { - color: #FFA928; -} -.stocks > .ui-button { - width: 100%; - margin-top: 30px; -} - -.operations { - overflow: auto; - position: relative; -} -.operations .insights { - padding: 16px 15px; - background-color: rgba(41, 127, 255, 0.04); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - margin: 12px 0 16px; -} -.operations .insights .insight-header { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 5px; -} -.operations .insights .insight-header h6 { - margin: 0 6px; -} -.operations .insights > ul { - list-style: none; - padding: 0; - margin: 0; -} -.operations .insights > ul > li { - margin: 8px 0; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - color: rgba(41, 50, 65, 0.5); -} -.operations .insights > ul > li span { - font-weight: 600; -} -.operations .insights > ul > li span > span { - font-size: 8px; - line-height: 10px; - font-weight: normal; -} -.operations > button { - width: 100%; -} - -.notification { - padding: 30px 24px; - background-color: #ffffff; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.notification > h6 { - margin: 0; - color: rgba(41, 50, 65, 0.8); -} -.notification > h6 > a { - margin-left: 10px; -} -.notification > h6 > a i { - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -o-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); -} - -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav { - background-color: transparent; - margin: 0 -10px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav:before { - display: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header { - padding: 9px 0 0; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: transparent; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - margin: 0 10px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a { - position: relative; - width: 52px; - height: 52px; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - background-color: #D0D6DD; - cursor: pointer; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - color: #2170E7; - color: var(--primary-color); - border: 0 none; - overflow: visible; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a img { - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a .ui-badge { - position: absolute; - bottom: -5px; - right: -5px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active { - padding: 0 0 9px; - border: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active a { - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.16), 0px 1px 2px rgba(41, 50, 65, 0.04), 0px 6px 12px rgba(41, 50, 65, 0.24); - border: 0 none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active:before { - content: ""; - width: 12px; - height: 2px; - background: #2170E7; - background: var(--primary-color); - border-radius: 3px; - position: absolute; - bottom: -10px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-hover { - border: none; - padding: 0 0 9px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels { - background-color: transparent; - border: none; - padding: 16px 0 0; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { - padding: 0; - height: 350px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { - position: relative; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - height: 350px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { - position: absolute; - top: 0; - left: 0; - display: block; - width: 100%; - height: 44px; - background-image: linear-gradient(180deg, #ffffff 0%, rgba(234, 237, 243, 0) 100%); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { - max-height: 400px; - overflow: auto; - padding: 30px 6px 12px; - flex: 1 1 auto; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message { - display: -ms-flexbox; - display: flex; - flex-direction: column; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .name { - display: block; - color: rgba(41, 50, 65, 0.5); - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - max-width: 250px; - padding: 8px 10px; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - background-color: #F7FAFF; - margin-bottom: 8px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message p { - padding: 0; - margin: 0 0 2px; - color: rgba(41, 50, 65, 0.8); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message span { - display: block; - font-weight: 600; - font-size: 10px; - line-height: 14px; - color: rgba(41, 50, 65, 0.5); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send { - -ms-flex-align: end; - align-items: flex-end; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send .message span { - text-align: right; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message h4 { - color: rgba(41, 50, 65, 0.5); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { - flex: 1 1 auto; - max-height: 400px; - overflow: auto; - padding: 0px 0 12px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul { - padding: 0; - margin: 0; - list-style: none; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin-bottom: 6px; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; - cursor: pointer; - padding: 8px 10px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li img { - margin-right: 12px; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li h6 { - margin: 0 0 2px; - color: rgba(41, 50, 65, 0.8); -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li span { - display: block; - color: rgba(41, 50, 65, 0.5); - font-weight: 600; - font-size: 10px; - line-height: 14px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { - background-color: #F7FAFF; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input { - margin-top: 30px; -} -.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { - width: 100%; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - padding: 20px 19px; - background-color: #F7F7F8; - border: none; -} - -.image-card { - padding: 0; - position: relative; -} -.image-card > span { - position: absolute; - right: 20px; - top: 20px; -} -.image-card > img { - width: 100%; - height: auto; - border-radius: 24px 24px 12px 12px; -} -.image-card .image-content { - padding: 32px 20px 28px; -} -.image-card .image-content h6 { - margin: 0 0 8px; -} -.image-card .image-content > p { - color: rgba(41, 50, 65, 0.5); -} -.image-card .image-content > button { - margin-top: 32px; - width: 100%; -} - -.login-body { - background: #FFFFFF; -} -.login-body .login-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - flex-direction: column; - height: 100vh; -} -.login-body .login-wrapper .login-panel { - width: 30%; - height: 100%; - text-align: center; - padding: 40px 20px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - flex: 1 1 100%; -} -.login-body .login-wrapper .login-panel .logo { - margin-bottom: 50px; -} -.login-body .login-wrapper .login-panel .logo img { - width: 45px; - height: 53px; -} -.login-body .login-wrapper .login-panel > a { - font-weight: 500; - font-size: 10px; - line-height: 12px; - color: rgba(41, 50, 65, 0.3); -} -.login-body .login-wrapper .login-panel > p { - font-weight: 500; - margin: 0; - color: rgba(41, 50, 65, 0.5); - margin-top: 40px; -} -.login-body .login-wrapper .login-panel > p > a { - color: #2170E7; - cursor: pointer; -} -.login-body .login-wrapper .login-panel > input { - width: 85%; - max-width: 247px; - margin-bottom: 10px; - background-color: #F6F7F7; - border: 1.2px solid #D4D6D9; - color: #515C66; - padding: 12px 10px; -} -.login-body .login-wrapper .login-panel > input::placeholder { - color: gba(41, 50, 65, 0.3); -} -.login-body .login-wrapper .login-panel > button { - width: 85%; - max-width: 247px; - margin-bottom: 10px; - padding: 0; -} -.login-body .login-wrapper .login-panel > button > span { - padding: 15px 20px; - display: block; - font-weight: 600; - font-size: 14px; - line-height: 16px; -} -.login-body .login-wrapper .login-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 70px; -} -.login-body .login-wrapper .login-footer h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.login-body .login-wrapper .login-footer h6 { - line-height: 17px; - margin: 0; - color: rgba(41, 50, 65, 0.5); - font-weight: 500; -} - -@media (max-width: 992px) { - .login-body .login-wrapper .login-panel { - width: 100%; - } -} -.exception-body .exception-topbar { - height: 62px; - background-color: #ffffff; - box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding: 0 16px; -} -.exception-body .exception-topbar .layout-topbar-logo > img { - height: 15px; -} -.exception-body .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); -} -.exception-body .exception-wrapper .exception-content { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: center; - justify-content: center; - flex: 1 1 auto; -} -.exception-body .exception-wrapper .exception-content > span { - font-weight: normal; - font-size: 60px; - line-height: 73px; - text-align: center; - display: block; -} -.exception-body .exception-wrapper .exception-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 70px; -} -.exception-body .exception-wrapper .exception-footer h4 { - line-height: 22px; - margin: 0; - margin-right: 32px; -} -.exception-body .exception-wrapper .exception-footer h6 { - line-height: 17px; - margin: 0; - color: rgba(41, 50, 65, 0.5); - font-weight: 500; -} -.exception-body.notfound .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); -} -.exception-body.notfound .exception-wrapper .exception-content { - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: center; - justify-content: center; - -ms-flex-align: center; - align-items: center; - flex: 1 1 auto; -} -.exception-body.notfound .exception-wrapper .exception-content img { - width: 332px; - height: 271px; - margin-bottom: -150px; -} -.exception-body.notfound .exception-wrapper .exception-content > span { - font-size: 140px; - line-height: 171px; -} -.exception-body.notfound .exception-wrapper .exception-content > span.exception-subtitle { - font-weight: 500; - font-size: 14px; - line-height: 17px; - color: rgba(41, 50, 65, 0.5); -} -.exception-body.notfound .exception-wrapper .exception-content > button { - padding: 0; - margin-top: 20px; - width: 155px; - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; -} -.exception-body.notfound .exception-wrapper .exception-content > button > span { - padding: 18px; - font-weight: 600; -} - -@media (max-width: 991px) { - .exception-body .exception-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-align: center; - align-items: center; - min-height: calc(100vh - 62px); - } - .exception-body .exception-wrapper .exception-footer { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - padding-bottom: 20px; - } -} -.landing-body { - background-color: #E5E5E5; -} -.landing-body .landing-topbar { - height: 83px; - background-color: #FFFFFF; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: justify; - justify-content: space-between; - width: 100%; - z-index: 999; - padding: 20px 40px; - position: relative; -} -.landing-body .landing-topbar .landing-topbar-left { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} -.landing-body .landing-topbar .landing-topbar-left .logo { - margin-right: 40px; -} -.landing-body .landing-topbar .landing-topbar-left .logo img { - height: 16px; - width: auto; -} -.landing-body .landing-topbar .landing-topbar-left > ul { - list-style-type: none; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - margin: 0; - padding: 0; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li #landing-menu-close { - display: none; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li > a { - font-weight: 600; - font-size: 12px; - line-height: 14px; - color: rgba(41, 50, 65, 0.9); - padding: 14px 10px; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - margin: 0 10px; - min-width: 100px; - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.landing-body .landing-topbar .landing-topbar-left > ul > li > a:hover { - color: #2170E7; -} -.landing-body .landing-topbar .landing-topbar-right .second-menubutton { - margin-right: 20px; - font-weight: 600; - font-size: 12px; - line-height: 14px; - color: rgba(41, 50, 65, 0.9); - padding: 14px 10px; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - min-width: 100px; - -moz-transition: color 0.2s; - -o-transition: color 0.2s; - -webkit-transition: color 0.2s; - transition: color 0.2s; -} -.landing-body .landing-topbar .landing-topbar-right .second-menubutton:hover { - color: #2170E7; -} -.landing-body .landing-topbar .landing-topbar-right .landing-button span { - font-weight: 600; - font-size: 12px; - line-height: 14px; -} -.landing-body .landing-topbar .landing-topbar-right #landing-menu-button { - display: none; - padding: 0 8px; - cursor: pointer; -} -.landing-body .landing-topbar .landing-topbar-right #landing-menu-button i { - font-size: 20px; -} -.landing-body .landing-button { - background: linear-gradient(108.43deg, #297FFF 12.5%, #7A0EE7 96.32%); - border: none; - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - -moz-transition: all 0.2s; - -o-transition: all 0.2s; - -webkit-transition: all 0.2s; - transition: all 0.2s; -} -.landing-body .landing-button.ui-button { - padding: 0; -} -.landing-body .landing-button.ui-button > .ui-button-text { - padding: 14px 10px; - min-width: 121px; - font-weight: 600; - font-size: 16px; - line-height: 19px; - display: block; -} -.landing-body .landing-button > a .ui-button-text { - padding: 14px 10px; - min-width: 87px; - font-weight: 600; - font-size: 16px; - line-height: 19px; - display: block; -} -.landing-body .landing-button:hover { - background: linear-gradient(108.43deg, #2f79e7 12.5%, #781cd4 96.32%); -} -.landing-body .landing-banner { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - padding: 303px 30px 218px; - position: relative; - transform-style: inherit; - background: url("#{resource['freya-layout:images/pages/asset-landing-header.jpg']}"); - background-size: cover; - height: 80vh; -} -.landing-body .landing-banner .landing-banner-content { - text-align: center; - position: relative; -} -.landing-body .landing-banner .landing-banner-content .title { - display: block; - font-weight: 500; - font-size: 70px; - line-height: 84px; - color: #FFFFFF; -} -.landing-body .landing-banner .landing-banner-content h3 { - margin: 40px 0 30px; - color: #FFFFFF; - font-weight: 500; - line-height: 29px; -} -.landing-body .section-header { - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-direction: column; -} -.landing-body .section-header .title { - display: block; - font-weight: 500; - font-size: 70px; - line-height: 84px; - color: rgba(41, 50, 65, 0.9); -} -.landing-body .section-header h3 { - margin: 15px 0 100px; - color: rgba(41, 50, 65, 0.9); - font-weight: 500; - line-height: 29px; - max-width: 800px; -} -.landing-body .landing-features { - background-color: #FFFFFF; - position: relative; - display: -ms-flexbox; - display: flex; - flex-wrap: wrap; - padding: 36px 6% 125px; -} -.landing-body .landing-features .lg\:col-3 { - transition: transform 250ms linear; - -webkit-transition: transform 250ms linear; -} -.landing-body .landing-features .feature { - display: -ms-flexbox; - display: flex; -} -.landing-body .landing-features .feature > span { - font-weight: 500; - font-size: 20px; - line-height: 20px; - color: rgba(41, 50, 65, 0.8); - margin-top: 30px; - margin-right: 12px; -} -.landing-body .landing-features .feature .feature-card { - -moz-border-radius: 36px; - -webkit-border-radius: 36px; - border-radius: 36px; - padding: 28px 30px; - display: -ms-flexbox; - display: flex; - width: 100%; -} -.landing-body .landing-features .feature .feature-card > span { - display: none; -} -.landing-body .landing-features .feature .feature-card h3 { - font-weight: 500; - line-height: 36px; - margin: 0 0 20px; - color: rgba(41, 50, 65, 0.8); -} -.landing-body .landing-features .feature .feature-card h5 { - margin: 0; - font-weight: normal; - line-height: 150%; - color: rgba(41, 50, 65, 0.9); - opacity: 0.8; -} -.landing-body .landing-features .feature.yellow .feature-card { - padding-bottom: 128px; - background: linear-gradient(197.55deg, #FFD37D -1.02%, #FFDB7D 46.53%); -} -.landing-body .landing-features .feature.blue .feature-card { - padding-bottom: 67px; - background: linear-gradient(156.18deg, #DAF4FF 38.02%, #CEDFFF 95.69%); -} -.landing-body .landing-features .feature.darker-blue .feature-card { - padding-bottom: 164px; - background: linear-gradient(165.84deg, #C1E9FF 42.24%, rgba(219, 242, 255, 0.23) 97.17%); -} -.landing-body .landing-features .feature.darker-gray .feature-card { - padding-bottom: 109px; - background: linear-gradient(176.91deg, rgba(41, 50, 65, 0.6) 50%, rgba(41, 50, 65, 0.282) 115.03%); -} -.landing-body .landing-features .feature.darker-gray .feature-card h3 { - color: #FFFFFF; -} -.landing-body .landing-features .feature.darker-gray .feature-card h5 { - color: #FFFFFF; - opacity: 0.8; -} -.landing-body .landing-features .feature.gray .feature-card { - padding-bottom: 50px; - background: linear-gradient(11.49deg, rgba(41, 50, 65, 0.1) 60.37%, rgba(41, 50, 65, 0.026) 98.03%); -} -.landing-body .landing-pricing { - background-color: #FFFFFF; - position: relative; - padding: 125px 15% 260px; - text-align: center; -} -.landing-body .landing-pricing .pricing-card { - background: #FFFFFF; - box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); - -moz-border-radius: 24px; - -webkit-border-radius: 24px; - border-radius: 24px; - padding: 30px 20px 33px; - text-align: center; - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - flex-direction: column; - position: relative; - margin-bottom: 60px; -} -.landing-body .landing-pricing .pricing-card .preferred-tag { - padding: 14px 24px; - background: linear-gradient(112.58deg, #FFD029 22.19%, #F1AF60 100%); - box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); - -moz-border-radius: 12px; - -webkit-border-radius: 12px; - border-radius: 12px; - transform: rotate(-7.18deg); - position: absolute; - top: -32px; - color: #FFFFFF; - font-weight: bold; - font-size: 20px; - line-height: 24px; -} -.landing-body .landing-pricing .pricing-card h2 { - margin: 0 0 14px; - color: rgba(41, 50, 65, 0.9); -} -.landing-body .landing-pricing .pricing-card .price { - display: block; - color: #2170E7; - font-weight: bold; - font-size: 80px; - line-height: 95px; -} -.landing-body .landing-pricing .pricing-card .time { - color: rgba(41, 50, 65, 0.5); - font-size: 12px; - line-height: 14px; - display: block; - margin-bottom: 32px; -} -.landing-body .landing-pricing .pricing-card > ul { - padding: 42px 0 0; - width: 100%; - margin: 0; - list-style: none; - border-top: 1px solid rgba(41, 50, 65, 0.1); -} -.landing-body .landing-pricing .pricing-card > ul > li { - font-size: 16px; - line-height: 205.34%; - color: rgba(41, 50, 65, 0.5); -} -.landing-body .landing-pricing .pricing-card.pro { - background: linear-gradient(333.31deg, #EFF3FB 6.36%, #FFFFFF 72.79%); -} -.landing-body .landing-pricing .pricing-card.enterprise { - background: linear-gradient(156.19deg, rgba(41, 50, 65, 0.8) 10.28%, rgba(35, 40, 49, 0.496) 87.74%); -} -.landing-body .landing-pricing .pricing-card.enterprise h2 { - margin: 0 0 14px; - color: #FFFFFF; -} -.landing-body .landing-pricing .pricing-card.enterprise .price { - color: #FFFFFF; -} -.landing-body .landing-pricing .pricing-card.enterprise .time { - color: #FFFFFF; - opacity: 0.6; -} -.landing-body .landing-pricing .pricing-card.enterprise > ul { - border-top: 1px solid rgba(255, 255, 255, 0.2); -} -.landing-body .landing-pricing .pricing-card.enterprise > ul > li { - color: #FFFFFF; -} -.landing-body .landing-pricing > a { - font-size: 24px; - line-height: 29px; - display: block; -} -.landing-body .layout-footer { - background-color: #FFFFFF; - position: relative; -} -.landing-body .layout-footer .footer-menutitle { - color: rgba(41, 50, 65, 0.2); -} -.landing-body .layout-footer .footer-subtitle { - color: rgba(41, 50, 65, 0.3); -} -.landing-body .layout-footer ul > li { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .layout-footer ul > li > a { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .layout-footer ul > li > a:hover { - color: rgba(41, 50, 65, 0.3); -} -.landing-body .layout-footer .newsletter-input { - background-color: rgba(41, 50, 65, 0.04); -} -.landing-body .layout-footer .footer-bottom { - color: rgba(41, 50, 65, 0.7); -} -.landing-body .layout-footer .footer-bottom h6 { - color: rgba(41, 50, 65, 0.5); -} -.landing-body .landing-mask { - display: none; - width: 100%; - height: 100vh; - position: fixed; - top: 0; - left: 0; - background-color: rgba(0, 0, 0, 0.2); - z-index: 998; -} - -@media (max-width: 991px) { - .landing-body.block-scroll { - overflow: hidden; - } - .landing-body.block-scroll .landing-wrapper .landing-mask { - display: block; - } - .landing-body .landing-wrapper.landing-menu-active .landing-topbar .landing-menu { - transform: translate3d(0px, 0px, 0px); - } - .landing-body .landing-wrapper .landing-topbar { - padding: 0 13px; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu { - position: fixed; - flex-direction: column; - -ms-flex-align: end; - align-items: flex-end; - right: 0; - top: 0; - padding: 28px 15px; - z-index: 999; - width: 220px; - height: 100%; - background-color: #EEF5FF; - box-shadow: 0 24px 64px -2px rgba(0, 0, 0, 0.02), 0 6px 16px -2px rgba(0, 0, 0, 0.06), 0 2px 6px -2px rgba(0, 0, 0, 0.08); - transform: translate3d(260px, 0px, 0px); - -moz-transition: transform 0.2s; - -o-transition: transform 0.2s; - -webkit-transition: transform 0.2s; - transition: transform 0.2s; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li { - margin: 0; - width: 100%; - margin-bottom: 12px; - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a { - padding: 6px 16px; - font-size: 14px; - text-align: right; - background-color: #EEF5FF; - display: block; - color: rgba(41, 50, 65, 0.9); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a:hover { - color: rgba(41, 50, 65, 0.6); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close { - display: block; - font-size: 20px; - text-align: right; - color: rgba(41, 50, 65, 0.9); - } - .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close:hover { - color: rgba(41, 50, 65, 0.6); - } - .landing-body .landing-wrapper .landing-topbar #landing-menu-button { - display: block; - color: rgba(41, 50, 65, 0.9); - font-size: 20px; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .second-menubutton { - display: none; - } - .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .landing-button { - margin-right: 20px; - } - .landing-body .landing-wrapper .landing-banner { - background-position: top; - padding: 80px 23px; - -ms-flex-pack: start; - justify-content: flex-start; - height: auto; - top: auto !important; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content { - text-align: left; - max-width: 262px; - top: auto !important; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content > span { - font-size: 60px; - line-height: 91.84%; - } - .landing-body .landing-wrapper .landing-banner .landing-banner-content > h3 { - font-size: 18px; - line-height: 130%; - } - .landing-body .landing-wrapper .landing-features { - padding: 36px 20px 30px; - } - .landing-body .landing-wrapper .landing-features .lg\:col-3 { - transform: translateY(0) !important; - margin-top: auto !important; - } - .landing-body .landing-wrapper .landing-features .feature-empty { - display: none; - } - .landing-body .landing-wrapper .landing-features .feature-3 { - margin-top: auto; - } - .landing-body .landing-wrapper .landing-features .feature-4 { - margin-top: auto; - } - .landing-body .landing-wrapper .landing-features .feature > span { - display: none; - } - .landing-body .landing-wrapper .landing-features .feature .feature-card { - padding-bottom: 28px !important; - } - .landing-body .landing-wrapper .landing-features .feature .feature-card > span { - font-weight: 500; - font-size: 20px; - line-height: 20px; - color: rgba(41, 50, 65, 0.8); - margin-right: 12px; - margin-top: 8px; - display: block; - } - .landing-body .landing-wrapper .landing-features .feature.blue .feature-card { - flex-direction: row-reverse; - text-align: right; - } - .landing-body .landing-wrapper .landing-features .feature.blue .feature-card > span { - margin-right: 0px; - margin-left: 12px; - } - .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card { - flex-direction: row-reverse; - text-align: right; - } - .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card > span { - color: #FFFFFF; - float: right; - margin-right: 0px; - margin-left: 12px; - } - .landing-body .landing-wrapper .section-header .title { - font-size: 60px; - line-height: 72px; - } - .landing-body .landing-wrapper .section-header h3 { - font-size: 18px; - line-height: 130%; - } - .landing-body .landing-wrapper .landing-pricing { - padding: 30px 20px 97px; - } - .landing-body .landing-wrapper .landing-pricing .pricing-card { - margin-bottom: 20px; - } - .landing-body .landing-wrapper .landing-pricing .pricing-card > ul { - display: none; - } - .landing-body .landing-wrapper .landing-pricing .preferred { - order: -1 !important; - } - .landing-body .landing-wrapper .landing-pricing .preferred .pricing-card > ul { - display: block; - } -} -.help-page p { - margin: 0; -} -.help-page .help-search { - background-image: url("#{resource['freya-layout:images/pages/search.png']}"); - padding: 0; - text-align: center; -} -.help-page .help-search .help-search-content { - padding: 5rem 12rem; -} -.help-page .help-search .help-search-content h3 { - color: rgba(41, 50, 65, 0.8); - font-weight: 500; -} -.help-page .help-search .search-container { - font-size: 1rem; - padding: 1rem; - position: relative; -} -.help-page .help-search .search-container input { - appearance: none; - font-size: 1rem; - text-indent: 2rem; - padding: 1rem; - width: 100%; -} -.help-page .help-search .search-container i { - width: 1rem; - position: absolute; - margin-left: 1rem; - top: 50%; - margin-top: -0.5rem; -} -.help-page .status-bars { - margin-top: 1rem; - display: -ms-flexbox; - display: flex; -} -.help-page .status-bars .status-bar { - flex: 1 1 0; - -ms-flex: 1 1 0px; - background: #6EC180; - height: 50px; - margin-right: 0.25rem; - transition: transform 0.2s; -} -.help-page .status-bars .status-bar:last-child { - margin-right: 0; -} -.help-page .status-bars .status-bar.status-bar-failure { - background: #FF6E49; -} -.help-page .status-bars .status-bar:hover { - transform: scale(1.1); -} -.help-page .status-bar-footer { - padding: 1rem 0 0 0; - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; -} -.help-page .blog-post { - border-radius: 4px; - padding: 20px; - margin: 3rem 2rem; - border: 1px solid #dee2e6; - background-color: #ffffff; - position: relative; - -moz-border-radius: 20px; - -webkit-border-radius: 20px; - border-radius: 20px; -} -.help-page .blog-post:last-child { - margin-bottom: 1rem; -} -.help-page .blog-post img { - width: 100%; - position: absolute; - left: 0; - top: 0; -} -.help-page .blog-post .blog-text h1 { - color: rgba(41, 50, 65, 0.8); - margin-bottom: 1rem; - font-weight: 500; -} -.help-page .blog-post .blog-text span { - color: rgba(41, 50, 65, 0.5); - line-height: 1.4; -} -.help-page .blog-post .blog-profile { - position: absolute; - top: -25px; - left: -25px; -} -.help-page .blog-post .blog-profile img { - width: 50px; - height: 50px; - border-radius: 50%; -} - -@media screen and (max-width: 991px) { - .help-page .help-search .help-search-content { - padding: 6rem 2rem; - } -} -.invoice { - padding: 2rem; -} -.invoice .invoice-header { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; -} -.invoice .invoice-company .logo-image { - height: 50px; - margin-bottom: 0.5rem; -} -.invoice .invoice-company div { - margin-bottom: 0.5rem; -} -.invoice .invoice-company .company-name { - font-weight: 500; - font-size: 1.5rem; -} -.invoice .invoice-title { - font-size: 2rem; - margin-bottom: 2rem; - text-align: right; - font-weight: 300; -} -.invoice .invoice-details { - width: 15rem; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} -.invoice .invoice-details > div { - width: 50%; - margin-bottom: 0.5rem; -} -.invoice .invoice-details .invoice-label { - text-align: left; - font-weight: 500; -} -.invoice .invoice-details .invoice-value { - text-align: right; -} -.invoice .invoice-to { - margin-top: 1.5rem; - padding-top: 2rem; - border-top: 1px solid #F2F4F6; -} -.invoice .invoice-to .bill-to { - font-size: 1.25rem; - font-weight: 500; - margin-bottom: 0.5rem; -} -.invoice .invoice-to .invoice-to-info div { - margin-bottom: 0.5rem; -} -.invoice .invoice-items { - margin-top: 2rem; - padding-top: 2rem; -} -.invoice .invoice-items table { - width: 100%; - border-collapse: collapse; -} -.invoice .invoice-items table tr { - border-bottom: 1px solid #F2F4F6; -} -.invoice .invoice-items table th { - font-weight: 500; -} -.invoice .invoice-items table th, .invoice .invoice-items table td { - padding: 1rem; - text-align: right; -} -.invoice .invoice-items table th:first-child, .invoice .invoice-items table td:first-child { - text-align: left; -} -.invoice .invoice-summary { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - margin-top: 2.5rem; - padding-top: 2.5rem; -} -.invoice .invoice-summary .invoice-value { - font-weight: 500; -} - -@media print { - body * { - visibility: hidden; - } - - #invoice-content * { - visibility: visible; - } - - #invoice-content { - width: 100%; - position: absolute; - left: 0; - top: 0; - padding: 0; - margin: 0; - background: #ffffff; - color: rgba(41, 50, 65, 0.8); - } - - .invoice .invoice-to { - border-top: 1px solid #F2F4F6; - } - .invoice .invoice-items table tr { - border-bottom: 1px solid #F2F4F6; - } -} -.layout-config { - width: 16rem; - height: 100%; - position: fixed; - right: 0; - top: 0; - padding: 1rem; - overflow: auto; - background: #ffffff; - z-index: 999; - border-left: 0 none; - transform: translateX(100%); - transition: transform 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); -} -.layout-config.layout-config-active { - transform: translateX(0); - box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); -} -.layout-config.layout-config-active .layout-config-content .layout-config-button i { - transform: rotate(360deg); -} -.layout-config .ui-selectoneradio td { - padding: 0.5rem; -} -.layout-config p { - line-height: 1.5rem; - color: #6c757d; -} -.layout-config .layout-themes { - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} -.layout-config .layout-themes > div { - padding: 0.25rem; -} -.layout-config .layout-themes a { - width: 2rem; - height: 2rem; - border-radius: 24px; - display: block; - position: relative; - -ms-flex-align: center; - align-items: center; - -ms-flex-pack: center; - justify-content: center; - transition: transform 0.2s; - box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); -} -.layout-config .layout-themes a i { - font-size: 1rem; - position: absolute; - top: 50%; - left: 50%; - margin-left: -0.5rem; - margin-top: -0.5rem; -} -.layout-config .layout-themes a:hover { - transform: scale(1.1); -} - -.layout-config-button { - display: block; - position: fixed; - width: 3rem; - height: 3rem; - line-height: 3rem; - background: #1976D2; - color: #ffffff; - text-align: center; - top: 50%; - right: 0; - margin-top: -1.5rem; - border-top-left-radius: 24px; - border-bottom-left-radius: 24px; - transition: background-color 0.2s; - overflow: hidden; - cursor: pointer; - z-index: 999; - box-shadow: -0.25rem 0 1rem rgba(0, 0, 0, 0.15); -} -.layout-config-button i { - font-size: 2rem; - line-height: inherit; - transform: rotate(0deg); - transition: transform 1s; -} -.layout-config-button:hover { - background: #2083e4; -} - -/* Add your customizations of the layout styles here */ -.layout-wrapper .layout-rightpanel .rightpanel-wrapper { - position: relative; - height: 100%; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header { - text-align: center; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header .profile { - padding: 12px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions { - padding: 12px 6px 36px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .col-6, .layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .md\:col-4 { - padding: 0.2em; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav { - background-color: white; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header { - padding: 1rem; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header a { - font-size: 12px; - font-weight: 500; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header > span { - font-size: 10px; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header.ui-state-active { - background-color: #F7FAFF; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels { - background-color: white; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel { - padding: 0; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { - width: 80%; -} -.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { - width: 105px; - margin-right: 7px; -} +/* Add your customizations of the layout variables here */ +@-webkit-keyframes fadeInDown { + from { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } + to { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} +@keyframes fadeInDown { + from { + opacity: 0; + transform: translate3d(0, -20px, 0); + } + to { + opacity: 1; + transform: none; + } +} +@-webkit-keyframes fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } +} +@keyframes fadeOutUp { + from { + opacity: 1; + } + to { + opacity: 0; + -webkit-transform: translate3d(0, -20px, 0); + transform: translate3d(0, -20px, 0); + } +} +@keyframes fadeinmask { + from { + opacity: 0; + } + to { + opacity: 0.8; + } +} +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} + +@-webkit-keyframes modal-in { + from { + background-color: transparent; + } + to { + background-color: rgba(0, 0, 0, 0.6); + } +} +@keyframes modal-in { + from { + background-color: transparent; + } + to { + background-color: rgba(0, 0, 0, 0.6); + } +} +.modal-in { + -webkit-animation-name: modal-in; + animation-name: modal-in; +} + +h1, h2, h3, h4, h5, h6 { + margin: 1.5rem 0 1rem 0; + font-family: inherit; + font-weight: 600; + line-height: 1.2; + color: inherit; +} +h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child, h6:first-child { + margin-top: 0; +} + +h1 { + font-size: 2.5rem; +} + +h2 { + font-size: 2rem; +} + +h3 { + font-size: 1.75rem; +} + +h4 { + font-size: 1.5rem; +} + +h5 { + font-size: 1.25rem; +} + +h6 { + font-size: 1rem; +} + +mark { + background: #FFF8E1; + padding: 0.25rem 0.4rem; + border-radius: 24px; + font-family: monospace; +} + +blockquote { + margin: 1rem 0; + padding: 0 2rem; + border-left: 4px solid #90A4AE; +} + +hr { + border-top: solid #dee2e6; + border-width: 1px 0 0 0; + margin: 1rem 0; +} + +p { + margin: 0 0 1rem 0; + line-height: 1.5; +} +p:last-child { + margin-bottom: 0; +} + +html { + height: 100%; + font-size: 14px; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 14px; + font-weight: 400; + color: rgba(41, 50, 65, 0.8); + padding: 0; + margin: 0; + min-height: 100%; + background-color: #F2F4F6; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +body.blocked-scroll { + overflow: auto; +} + +a { + text-decoration: none; + color: #4f8eec; + color: var(--primary-color); +} + +.ajax-loader { + font-size: 32px; + color: #2170E7; + color: var(--primary-color); +} + +.layout-main { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + min-height: 100vh; + padding-top: 82px; + -moz-transition: padding-left 0.2s; + -o-transition: padding-left 0.2s; + -webkit-transition: padding-left 0.2s; + transition: padding-left 0.2s; +} + +.layout-mask { + display: none; + position: fixed; + top: 0; + left: 0; + z-index: 998; + width: 100%; + height: 100%; + animation-duration: 0.2s; + animation-timing-function: cubic-bezier(0.05, 0.74, 0.2, 0.99); + animation-fill-mode: forwards; +} + +.layout-content { + padding: 30px 36px; + flex: 1 1 auto; +} + +@media (max-width: 991px) { + .layout-content { + padding: 32px 14px; + } +} +.layout-topbar-light .layout-topbar { + position: fixed; + top: 0; + z-index: 999; + width: 100%; + -moz-transition: width 0.2s; + -o-transition: width 0.2s; + -webkit-transition: width 0.2s; + transition: width 0.2s; + height: 62px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper { + height: 100%; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left { + height: 100%; + padding: 0 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + z-index: 999; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + height: 15px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { + height: 15px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + padding: 6px; + margin-right: 16px; + border-radius: 4px; + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { + font-size: 18px; + width: 18px; + height: 18px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right { + height: 100%; + flex-grow: 1; + padding: 0 16px 0 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + border-right: solid 1px transparent; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; + list-style-type: none; + margin: 0; + padding: 0; + height: 100%; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { + width: 100%; + padding: 6px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + display: none; + position: absolute; + top: 62px; + right: 0px; + list-style-type: none; + margin: 0; + padding: 7px 0 8px; + z-index: 1000; + -moz-border-radius-bottomleft: 2px; + -webkit-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; + -moz-border-radius-bottomright: 2px; + -webkit-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; + min-width: 250px; + animation-duration: 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { + padding: 10px 15px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + list-style: none; + margin-bottom: 4px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + margin-right: 10px; + padding: 6px; + border-radius: 2px; + width: 26px; + height: 26px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { + height: 36px; + width: 36px; + margin-right: 10px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { + width: auto; + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { + position: relative; + width: 0; + opacity: 0; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { + background: #F7FAFF; + width: 100%; + position: relative; + padding: 9px; + padding-left: 37px; + border: none; + color: #3E4754; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { + position: absolute; + left: 9px; + font-size: 18px; + top: 50%; + margin-top: -9px; + display: none; + z-index: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { + margin-left: 16px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { + height: 28px; + width: 28px; + border-radius: 10px; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { + width: 200px; + opacity: 1; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: none; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { + display: block; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + margin-left: 26px; + z-index: 1; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +@media (max-width: 991px) { + .layout-topbar-light .layout-topbar .layout-topbar-wrapper { + -ms-flex-align: start; + align-items: flex-start; + position: relative; + padding: 0 6px; + } +} +@media (max-width: 576px) { + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } + .layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + left: 10px; + right: 10px; + position: fixed; + top: 62px; + } +} +.layout-topbar-light .layout-topbar { + background-color: #ffffff; + box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { + color: #293241; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + color: #293241; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { + background-color: #f8fafc; + border: 1px solid #ebedef; + color: #4f8eec; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { + color: #4f8eec; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { + color: #293241; + opacity: 0.5; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); + background-color: white; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { + background-color: #4688eb; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { + color: #ffffff; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { + background-color: #4688eb; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + color: rgba(41, 50, 65, 0.8); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + background-color: rgba(33, 112, 231, 0.8); + color: #ffffff; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { + color: rgba(41, 50, 65, 0.5); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { + color: rgba(41, 50, 65, 0.8); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { + color: rgba(41, 50, 65, 0.5); +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + color: #293241; + background-color: transparent; +} +.layout-topbar-light .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { + background-color: #E8EDF0; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} + +.layout-topbar-dark .layout-topbar { + position: fixed; + top: 0; + z-index: 999; + width: 100%; + -moz-transition: width 0.2s; + -o-transition: width 0.2s; + -webkit-transition: width 0.2s; + transition: width 0.2s; + height: 62px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper { + height: 100%; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left { + height: 100%; + padding: 0 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + z-index: 999; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + height: 15px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo > img { + height: 15px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + padding: 6px; + margin-right: 16px; + border-radius: 4px; + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button i { + font-size: 18px; + width: 18px; + height: 18px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right { + height: 100%; + flex-grow: 1; + padding: 0 16px 0 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + border-right: solid 1px transparent; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; + list-style-type: none; + margin: 0; + padding: 0; + height: 100%; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a { + width: 100%; + padding: 6px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + background-color: transparent; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a.layout-rightpanel-button i { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + display: none; + position: absolute; + top: 62px; + right: 0px; + list-style-type: none; + margin: 0; + padding: 7px 0 8px; + z-index: 1000; + -moz-border-radius-bottomleft: 2px; + -webkit-border-bottom-left-radius: 2px; + border-bottom-left-radius: 2px; + -moz-border-radius-bottomright: 2px; + -webkit-border-bottom-right-radius: 2px; + border-bottom-right-radius: 2px; + min-width: 250px; + animation-duration: 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .angle-icon { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: end; + justify-content: flex-end; + flex-grow: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li { + padding: 10px 15px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + cursor: pointer; + list-style: none; + margin-bottom: 4px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + margin-right: 10px; + padding: 6px; + border-radius: 2px; + width: 26px; + height: 26px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a img { + height: 36px; + width: 36px; + margin-right: 10px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item a { + width: auto; + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper { + position: relative; + width: 0; + opacity: 0; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper .ui-inputfield { + background: #F7FAFF; + width: 100%; + position: relative; + padding: 9px; + padding-left: 37px; + border: none; + color: #3E4754; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item .search-input-wrapper i { + position: absolute; + left: 9px; + font-size: 18px; + top: 50%; + margin-top: -9px; + display: none; + z-index: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a { + margin-left: 16px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.user-profile > a > img { + height: 28px; + width: 28px; + border-radius: 10px; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper { + width: 200px; + opacity: 1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item .search-input-wrapper i { + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem > ul { + display: block; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + font-size: 18px; + border-radius: 6px; + width: 30px; + height: 30px; + margin-left: 26px; + z-index: 1; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +@media (max-width: 991px) { + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper { + -ms-flex-align: start; + align-items: flex-start; + position: relative; + padding: 0 6px; + } +} +@media (max-width: 576px) { + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } + .layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + left: 10px; + right: 10px; + position: fixed; + top: 62px; + } +} +.layout-topbar-dark .layout-topbar { + background-color: #293241; + box-shadow: none; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button > i { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button:hover { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a > .topbar-icon { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > a:hover i { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input { + background-color: #333e51; + border: 1px solid #333e51; + color: #7dabf1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper input::placeholder { + color: #7dabf1; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.search-item > form > .search-input-wrapper i { + color: #E9E9E9; + opacity: 0.5; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul { + box-shadow: 0 2px 8px 0 rgba(25, 26, 28, 0.12); + background-color: #333e51; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header { + background-color: #4688eb; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header h6 { + color: #ffffff; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul .layout-submenu-header:hover { + background-color: #4688eb; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a i { + background-color: rgba(33, 112, 231, 0.8); + color: #ffffff; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li > a .notification-detail { + color: #C2C2C2; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text p { + color: #E9E9E9; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li .menu-text span { + color: #C2C2C2; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li > ul > li:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button { + color: #E9E9E9; + background-color: transparent; +} +.layout-topbar-dark .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-rightpanel-button:hover { + background-color: #333e51; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} + +.menu-wrapper { + height: 100%; + position: fixed; + top: 0; + z-index: 999; + left: 0; +} +.menu-wrapper .sidebar-logo { + height: 62px; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: start; + justify-content: flex-start; + -ms-flex-align: center; + align-items: center; + padding: 0 22px; + padding-right: 20px; +} +.menu-wrapper .sidebar-logo .sidebar-pin { + display: none; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.menu-wrapper .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #dee2e6; +} +.menu-wrapper .sidebar-logo img { + width: 17px; + height: 20px; + border: 0 none; +} +.menu-wrapper .layout-menu-container { + height: calc(100% - 62px); +} +.menu-wrapper .layout-menu-container .layout-menu { + list-style-type: none; + margin: 0; + padding: 0; + max-width: 62px; + overflow: hidden; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.menu-wrapper .layout-menu-container .layout-menu > li > a { + position: relative; +} +.menu-wrapper .layout-menu-container .layout-menu > li > a::before { + content: ""; + width: 4px; + height: 12px; + display: block; + border-radius: 0px 3px 3px 0px; + position: absolute; + left: 0; +} +.menu-wrapper .layout-menu-container .layout-menu > li > ul > li { + margin-left: 6px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} +.menu-wrapper .layout-menu-container .layout-menu li { + padding: 10px 0; +} +.menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -o-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); +} +.menu-wrapper .layout-menu-container .layout-menu li .layout-menu-tooltip { + display: none; +} +.menu-wrapper .layout-menu-container .layout-menu li > a { + margin: 0px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + font-size: 13px; + padding: 6px 20px; + user-select: none; + cursor: pointer; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > span { + margin: 0 8px; + margin-left: 14px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + visibility: hidden; + white-space: nowrap; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > i { + font-size: 24px; +} +.menu-wrapper .layout-menu-container .layout-menu li > a > i.layout-submenu-toggler { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + margin-left: auto; + font-size: 12px; + visibility: hidden; +} +.menu-wrapper .layout-menu-container .layout-menu li > a.rotated-icon i { + transform: rotate(90deg); +} +.menu-wrapper .layout-menu-container .layout-menu li > ul { + display: none; + list-style-type: none; + overflow: hidden; + padding: 0; + margin: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul li ul { + display: none; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li { + padding: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li > a { + padding: 10px 18px; + margin-left: 0px; + padding-right: 8px; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li i { + font-size: 14px; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li ul li { + padding: 0; +} +.menu-wrapper .layout-menu-container .layout-menu li > ul > li.layout-root-menuitem > a { + display: -ms-flexbox; + display: flex; +} + +@media (min-width: 992px) { + .layout-wrapper.layout-sidebar .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + display: none; + } + .layout-wrapper.layout-sidebar .layout-main { + padding-left: 62px; + } + .layout-wrapper.layout-static .menu-wrapper { + transform: translate3d(0px, 0px, 0px); + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo { + justify-content: space-between; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo img { + display: inline; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .app-name { + display: inline; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin { + display: inline-block; + } + .layout-wrapper.layout-static .menu-wrapper .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #dee2e6; + border: 2px solid var(--primary-light-color); + background-color: #dee2e6; + background-color: var(--primary-lighter-color); + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu > li { + min-width: 230px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .layout-wrapper.layout-static .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-static .layout-main { + padding-left: 230px; + -moz-transition: padding-left 0.2s; + -o-transition: padding-left 0.2s; + -webkit-transition: padding-left 0.2s; + transition: padding-left 0.2s; + } + + .menu-wrapper.layout-sidebar-active { + transform: translate3d(0px, 0px, 0px); + } + .menu-wrapper.layout-sidebar-active .sidebar-logo { + justify-content: space-between; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo img { + display: inline; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .app-name { + display: inline; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin { + display: inline-block; + } + .menu-wrapper.layout-sidebar-active .sidebar-logo .sidebar-pin > span { + display: block; + height: 16px; + width: 16px; + -moz-border-radius: 50%; + -webkit-border-radius: 50%; + border-radius: 50%; + border: 2px solid #dee2e6; + } + .menu-wrapper.layout-sidebar-active .layout-menu { + max-width: 230px; + } + .menu-wrapper.layout-sidebar-active .layout-menu > li { + min-width: 230px; + } + .menu-wrapper.layout-sidebar-active .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li a { + padding-left: 20px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li a { + padding-left: 30px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .menu-wrapper.layout-sidebar-active .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .menu-wrapper.layout-sidebar-active .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .menu-wrapper.layout-sidebar-active .layout-menu-container { + overflow: auto; + } +} +@media (max-width: 991px) { + .layout-wrapper .menu-wrapper { + top: 62px; + z-index: 1010; + -webkit-transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transition-timing-function: cubic-bezier(0.86, 0, 0.07, 1); + transform: translate3d(-230px, 0px, 0px); + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + } + .layout-wrapper .menu-wrapper .sidebar-logo { + display: none; + } + .layout-wrapper .menu-wrapper .layout-menu-container .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-mobile-active { + overflow: hidden; + height: 100vh; + } + .layout-wrapper.layout-mobile-active .menu-wrapper { + transform: translate3d(0px, 0px, 0px); + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu { + max-width: 230px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li { + min-width: 230px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu > li > ul > li { + margin-left: 10px; + margin-right: 12px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a > span { + visibility: visible; + white-space: normal; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu li > a i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-mobile-active .menu-wrapper .layout-menu-container { + overflow: auto; + } + .layout-wrapper.layout-mobile-active .layout-mask { + display: block; + } + .layout-wrapper .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button { + display: block; + } +} +@media (min-width: 992px) { + .layout-wrapper.layout-horizontal .menu-wrapper { + top: 0px; + width: 100%; + height: 62px; + position: relative; + } + .layout-wrapper.layout-horizontal .menu-wrapper .sidebar-logo { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container { + height: 100%; + display: flex; + align-items: center; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu { + list-style-type: none; + margin: 0px 16px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: row; + flex-direction: row; + max-width: 100%; + overflow: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu li.active-menuitem > a i.layout-submenu-toggler { + -webkit-transform: rotate(-180deg); + -moz-transform: rotate(-180deg); + -o-transform: rotate(-180deg); + -ms-transform: rotate(-180deg); + transform: rotate(-180deg); + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li { + padding: 0; + position: relative; + margin: 0 9px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li .layout-menu-tooltip { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a { + margin: 0px; + padding: 10px 5px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a:before { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > span { + margin: 0 8px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + visibility: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i { + font-size: 14px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li a > i.layout-submenu-toggler { + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + margin-left: auto; + font-size: 12px; + visibility: visible; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.layout-root-menuitem > div { + display: none; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + display: none; + list-style-type: none; + top: 44px; + left: 0px; + width: 230px; + position: absolute; + padding: 10px; + margin: 0; + z-index: 100; + overflow: auto; + max-height: 460px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li { + border: 0 none; + margin: 0; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul > li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-left .menu-button-wrapper .menu-button { + display: none; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item a { + display: block; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > .search-input-wrapper { + display: none; + } + .layout-wrapper.layout-horizontal .layout-topbar .layout-topbar-wrapper .layout-topbar-right .layout-topbar-actions > li.active-topmenuitem.search-item > ul { + display: block; + padding: 0; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + } +} +@media (min-width: 992px) { + .layout-wrapper.layout-slim .menu-wrapper { + width: 62px; + overflow: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container { + padding: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu { + overflow: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + display: none; + padding: 0 0.412px; + position: absolute; + left: 72px; + top: 16px; + line-height: 1; + border-radius: 2px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + padding: 6px 8px; + font-weight: 500; + min-width: 75px; + white-space: nowrap; + text-align: center; + -webkit-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + -moz-box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + box-shadow: 0 2px 10px 0 rgba(0, 3, 6, 0.16); + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + top: 50%; + left: -4px; + margin-top: -5px; + border-width: 5px 5px 5px 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li { + position: relative; + padding: 10px 12px 10px 14px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a { + margin: 0px; + padding: 6px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + position: relative; + border: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:before { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a span { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i { + margin-right: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a i.layout-submenu-toggler { + display: none; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a .menuitem-badge { + display: none; + margin-left: auto; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > a:hover + .layout-menu-tooltip { + display: block; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + position: absolute; + top: 0; + left: 62px; + min-width: 250px; + max-height: 450px; + display: none; + padding: 10px; + overflow: auto; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li { + margin: 0; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + padding: 10px 5px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > span { + visibility: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a > i.layout-submenu-toggler { + visibility: visible; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li a { + padding-left: 20px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li a { + padding-left: 30px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li a { + padding-left: 40px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li a { + padding-left: 50px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li a { + padding-left: 60px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 70px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 80px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 90px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li ul li ul li ul li ul li ul li ul li ul li ul li ul li a { + padding-left: 100px; + } + .layout-wrapper.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover + .layout-menu-tooltip { + display: none; + } + .layout-wrapper.layout-slim .layout-topbar .layout-topbar-wrapper .layout-topbar-left .layout-topbar-logo { + display: none; + } + .layout-wrapper.layout-slim .layout-main { + padding-left: 62px; + } +} +.layout-menu-dark .menu-wrapper { + background-color: #293241; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: #293241; +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: #293241; + color: #2170E7; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); +} +.layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-light-color); +} +@media (min-width: 992px) { + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-light-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-horizontal .menu-wrapper { + box-shadow: none; + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + background-color: #293241; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + background-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + color: #ffffff; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + border-right-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + background-color: #293241; + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); + } +} +@media (max-width: 991px) { + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-light-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #E9E9E9; + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(233, 233, 233, 0.8); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-dark .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #E9E9E9; + } +} + +.layout-menu-light .menu-wrapper { + background-color: #ffffff; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: #ffffff; +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: #ffffff; + color: #2170E7; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); +} +.layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-color); +} +@media (min-width: 992px) { + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper.layout-sidebar-active .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-static .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } + .layout-menu-light.layout-horizontal .menu-wrapper { + box-shadow: none; + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul { + background-color: #ffffff; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-horizontal .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip { + background-color: #293241; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-text { + color: #ffffff; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu .layout-menu-tooltip .layout-menu-tooltip-arrow { + border-right-color: #293241; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a i { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul { + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + background-color: #ffffff; + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li > a:hover { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light.layout-slim .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); + } +} +@media (max-width: 991px) { + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a { + color: #293241; + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > a:hover { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a { + color: #2170E7; + color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li.active-menuitem > a::before { + background-color: #2170E7; + background-color: var(--primary-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem { + background-color: rgba(33, 112, 231, 0.2); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul > li.active-menuitem > a { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + color: #293241; + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a { + color: rgba(41, 50, 65, 0.7); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li a:hover { + background-color: rgba(33, 112, 231, 0.1); + background-color: var(--primary-lighter-color); + } + .layout-menu-light .menu-wrapper .layout-menu-container .layout-menu > li > ul li.active-menuitem > a { + color: #293241; + } +} + +.layout-rightpanel { + position: fixed; + z-index: 1000; + right: 0; + top: 62px; + height: calc(100% - 62px); + padding: 0; + width: 418px; + overflow: auto; + background-color: #F7FAFF; + transform: translate3d(418px, 0px, 0px); + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + -webkit-backface-visibility: hidden; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); +} +.layout-rightpanel .rightpanel-wrapper { + padding: 22px 20px 40px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section { + padding: 16px 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + margin-bottom: 16px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section .section-header > h6 { + margin: 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 14px 16px; + background-image: url("#{resource['demo:images/rightpanel/asset-weather.png']}"); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + -moz-box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + box-shadow: 0px 10px 40 rgba(41, 50, 65, 0.06); + color: rgba(41, 50, 65, 0.8); +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather > img { + height: 60px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info { + margin-left: 16px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h6 { + margin: 0 0 2px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.weather-section .weather .weather-info h1 { + margin: 0; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul { + padding: 0; + margin: 0; + list-style: none; + overflow: auto; + max-height: 320px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li { + padding: 16px; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + background-color: #ffffff; + margin-bottom: 12px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info h6 { + color: #3E4754; + margin: 0 0 4px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li .task-info > span { + display: block; + font-weight: 500; + font-size: 14px; + line-height: 140%; + color: rgba(41, 50, 65, 0.5); +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done { + opacity: 0.5; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.tasks-section > ul > li.done .task-info h6 { + text-decoration: line-through; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-wrap: wrap; + margin: -7px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + width: 80px; + height: 80px; + background-color: #ffffff; + margin: 7px; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .favorite-item:hover { + background-color: #F7F7F8; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + width: 80px; + height: 80px; + margin: 7px; + border: 1px dashed #dee2e6; + color: #dee2e6; + -moz-transition: background-color 0.2s; + -o-transition: background-color 0.2s; + -webkit-transition: background-color 0.2s; + transition: background-color 0.2s; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.favorites-section .favorite-items .add-item:hover { + background-color: #F7F7F8; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section { + margin-top: 40px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { + height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { + height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { + background-image: linear-gradient(180deg, #F7FAFF 0%, rgba(234, 237, 243, 0) 100%); +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { + max-height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + background-color: #ffffff; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { + max-height: 400px; +} +.layout-rightpanel .rightpanel-wrapper .rightpanel-section.chat-section .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { + background-color: #ffffff; +} + +.layout-wrapper.layout-rightpanel-active .layout-rightpanel { + transform: translate3d(0px, 0px, 0px); +} + +@media (max-width: 576px) { + .layout-rightpanel { + width: 100%; + transform: translate3d(100%, 0px, 0px); + } +} +.layout-footer { + padding: 30px 36px; +} +.layout-footer .footer-menutitle { + color: rgba(41, 50, 65, 0.5); + font-weight: 600; + font-size: 12px; + line-height: 14px; + min-height: 15px; + display: block; + margin-bottom: 9px; +} +.layout-footer .footer-subtitle { + font-weight: 500; + font-size: 14px; + display: block; + color: rgba(41, 50, 65, 0.5); +} +.layout-footer ul { + padding: 0; + margin: 0; + list-style: none; +} +.layout-footer ul > li { + padding: 7px 0; +} +.layout-footer ul > li > a { + color: rgba(41, 50, 65, 0.8); + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.layout-footer ul > li > a:hover { + color: rgba(41, 50, 65, 0.5); +} +.layout-footer .newsletter-input { + margin-top: 16px; + background-color: #ffffff; + position: relative; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.layout-footer .newsletter-input > input { + width: 100%; + background-color: transparent; + border: none; + padding: 11px 16px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + font-size: 14px; + line-height: 200%; +} +.layout-footer .newsletter-input > button { + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + position: absolute; + right: 6px; + top: 50%; + margin-top: -16px; +} +.layout-footer .newsletter-input > button > span { + display: block; + padding: 0; + width: 100%; + font-weight: 600; + font-size: 14px; +} +.layout-footer .footer-bottom { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.layout-footer .footer-bottom h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.layout-footer .footer-bottom h6 { + line-height: 17px; + margin: 0; + color: rgba(41, 50, 65, 0.5); + font-weight: 500; +} + +/* Utils */ +.clearfix:after { + content: " "; + display: block; + clear: both; +} + +.card { + background: #ffffff; + padding: 20px; + box-sizing: border-box; + box-shadow: 0 10px 40px rgba(41, 50, 65, 0.06); + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + margin-bottom: 2rem; +} +.card:last-child { + margin-bottom: 0; +} +.card .card-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + padding-bottom: 16px; +} +.card .card-header h6 { + margin-bottom: 2px; +} +.card .card-header .subtitle { + font-weight: 600; + color: rgba(41, 50, 65, 0.5); +} +.card .card-subtitle { + color: rgba(41, 50, 65, 0.5); + font-weight: 600; + margin: -1rem 0 1rem 0; +} +.card.no-gutter { + margin-bottom: 0; +} + +.sr-only { + border: 0; + clip: rect(1px, 1px, 1px, 1px); + clip-path: inset(50%); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + word-wrap: normal !important; +} + +.ui-text-secondary { + color: rgba(41, 50, 65, 0.5); +} + +.layout-wrapper .layout-ajax-loader { + position: absolute; + right: 15px; + bottom: 70px; +} +.layout-wrapper .layout-ajax-loader .layout-ajax-loader-icon { + color: red; + font-size: 32px; +} + +.layout-dashboard .chart { + overflow: auto; + position: relative; +} +.layout-dashboard .mobile-teams { + display: none; +} + +@media (max-width: 1200px) { + .layout-dashboard .desktop-teams { + display: none; + } + .layout-dashboard .mobile-teams { + display: block; + } + .layout-dashboard .mobile-teams .team { + height: 100%; + flex-direction: column; + -ms-flex-pack: start; + justify-content: flex-start; + -ms-flex-align: start; + align-items: flex-start; + } + .layout-dashboard .mobile-teams .team .peoples { + margin: 12px -8px; + } +} +.overview-box { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + padding-top: 24px; + height: 100%; + min-width: 200px; +} +.overview-box .overview-info > h6 { + margin: 0 0 2px; +} +.overview-box .overview-info > h1 { + margin: 0; +} +.overview-box > i { + font-size: 24px; +} +.overview-box.white { + background: #FFFFFF; + color: rgba(41, 50, 65, 0.8); +} +.overview-box.blue { + background: #69B7FF; + color: #FFFFFF; +} +.overview-box.gray { + background: rgba(41, 50, 65, 0.4); + color: #FFFFFF; +} +.overview-box.darkgray { + background: rgba(41, 50, 65, 0.8); + color: #FFFFFF; +} +.overview-box.orange { + background: linear-gradient(90deg, #FFB340 0%, #FFA740 100%); + color: #FFFFFF; +} + +.timeline { + padding-right: 4px; +} +.timeline > ul { + padding: 0; + margin: 0; + list-style: none; + max-height: 372px; + overflow: auto; + margin-bottom: 1em; +} +.timeline > ul > li { + display: -ms-flexbox; + display: flex; + margin-bottom: 16px; +} +.timeline > ul > li > i { + font-size: 8px; + margin-right: 10px; + margin-top: 4px; +} +.timeline > ul > li .event-content span { + display: block; + margin-bottom: 4px; + font-weight: 600; + font-size: 12px; + color: rgba(41, 50, 65, 0.5); +} +.timeline > ul > li .event-content span.event-title { + color: #3E4754; +} +.timeline > ul > li .event-content span.time { + font-size: 10px; + font-weight: 400; + color: rgba(41, 50, 65, 0.5); +} +.timeline > ul > li.blue > i { + color: #297FFF; +} +.timeline > ul > li.green > i { + color: #34B56F; +} +.timeline > ul > li.orange > i { + color: #FFA928; +} + +.device-status .content { + color: rgba(41, 50, 65, 0.5); + line-height: 1.4; + margin-bottom: 20px; +} +.device-status .progress { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 10px 0; + color: rgba(41, 50, 65, 0.5); +} +.device-status .progress > span { + min-width: 40px; +} +.device-status .progress .ui-progressbar { + width: 100%; + margin: 0 12px; + background: rgba(41, 127, 255, 0.2); + background: var(--primary-lighter-color); +} +.device-status .progress .ui-progressbar .ui-progressbar-value { + background: rgba(41, 127, 255, 0.2); + background: var(--primary-color); + opacity: 0.8; + border-radius: 24px; +} +.device-status .progress.active .ui-progressbar { + width: 100%; + margin: 0 12px; + background: rgba(41, 127, 255, 0.2); + background: var(--primary-lighter-color); +} +.device-status .progress.active .ui-progressbar .ui-progressbar-value { + background: linear-gradient(270deg, #42BBFF 0%, #6129FF 100%); + background: linear-gradient(270deg, var(--primary-lighter-color) 0%, var(--primary-color) 100%); + opacity: 0.8; +} +.device-status .device { + margin-bottom: 16px; +} +.device-status .device span { + color: #2170E7; + color: var(--primary-color); + font-size: 14px; + font-weight: 600; +} +.device-status .device span > span { + font-size: 8px; + font-weight: normal; +} +.device-status .device span.status { + font-size: 12px; + color: rgba(41, 50, 65, 0.5); + margin-top: 4px; + display: block; +} + +.team { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} +.team .card-header { + padding: 0; + min-width: 70px; +} +.team .peoples { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-wrap: wrap; +} +.team .peoples > img { + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + margin: 8px 8px; + width: 32px; + height: 32px; +} +.team .peoples .no-picture { + cursor: pointer; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + border-radius: 10px; + margin: 8px 8px; + width: 32px; + height: 32px; + background: rgba(41, 50, 65, 0.1); + color: rgba(41, 50, 65, 0.8); + font-size: 12px; + -moz-transition: background 0.2s; + -o-transition: background 0.2s; + -webkit-transition: background 0.2s; + transition: background 0.2s; +} +.team .peoples .no-picture:hover { + background: rgba(41, 50, 65, 0.2); +} + +.map { + padding: 0; +} +.map > img { + width: 100%; + height: auto; + border-radius: 24px 24px 12px 12px; +} +.map .map-content { + padding: 50px 20px 28px; +} +.map .map-content h6 { + margin: 0 0 16px; +} +.map .map-content .city { + margin-bottom: 16px; +} +.map .map-content .city span { + color: #2170E7; + color: var(--primary-color); + font-size: 14px; + font-weight: 600; +} +.map .map-content .city span > span { + font-size: 8px; + font-weight: normal; +} +.map .map-content .city span.status { + font-size: 12px; + color: rgba(41, 50, 65, 0.5); + margin-top: 4px; + display: block; +} + +.schedule > p { + color: rgba(41, 50, 65, 0.5); +} +.schedule > ul { + list-style: none; + padding: 0; + margin: 0; +} +.schedule > ul > li { + background: #F7F7F8; + border-radius: 8px; + margin-bottom: 10px; + padding: 5px 16px 12px; +} +.schedule > ul > li .schedule-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; +} +.schedule > ul > li .schedule-header h6 { + line-height: 24px; + margin: 0; +} +.schedule > ul > li .schedule-header span { + color: rgba(41, 50, 65, 0.5); + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.schedule > ul > li > span { + margin-top: 4px; + color: rgba(41, 50, 65, 0.5); + display: block; + font-size: 12px; + line-height: 14px; +} + +.statistics .statistic-item .item-title { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 4px; +} +.statistics .statistic-item .item-title span { + display: block; + margin-right: 12px; +} +.statistics .statistic-item .item-title h5 { + margin: 0; + font-weight: 700; +} +.statistics .statistic-item h6 { + margin: 0; + font-weight: 600; + color: rgba(41, 50, 65, 0.5); +} + +.stocks ul { + list-style: none; + padding: 0; + margin: 0; +} +.stocks ul > li { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + background-color: #F7FAFF; + padding: 0; + margin: 0 0 12px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + overflow: hidden; +} +.stocks ul > li .stock-name { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: #EEF5FF; + padding: 18px 10px; + min-width: 70px; + margin-right: 4px; +} +.stocks ul > li .stock-name h6 { + margin: 0; + color: rgba(41, 50, 65, 0.8); + line-height: 17px; + font-weight: 600; +} +.stocks ul > li > img { + margin: 0 4px; + height: 25px; +} +.stocks ul > li .stock-price { + padding: 0 10px; + color: #34B56F; + margin: 0 4px; +} +.stocks ul > li .stock-price h6 { + line-height: 17px; + font-weight: 600; + display: inline-block; +} +.stocks ul > li .stock-price i { + display: inline-block; +} +.stocks ul > li .stock-status { + margin-left: 4px; + padding: 0 20px; +} +.stocks ul > li .stock-status span { + display: block; + font-weight: 600; + font-size: 10px; + line-height: 12px; + color: rgba(41, 50, 65, 0.5); +} +.stocks ul > li.down .stock-price { + color: #FF6E49; +} +.stocks ul > li.same .stock-price { + color: #FFA928; +} +.stocks > .ui-button { + width: 100%; + margin-top: 30px; +} + +.operations { + overflow: auto; + position: relative; +} +.operations .insights { + padding: 16px 15px; + background-color: rgba(41, 127, 255, 0.04); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + margin: 12px 0 16px; +} +.operations .insights .insight-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 5px; +} +.operations .insights .insight-header h6 { + margin: 0 6px; +} +.operations .insights > ul { + list-style: none; + padding: 0; + margin: 0; +} +.operations .insights > ul > li { + margin: 8px 0; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + color: rgba(41, 50, 65, 0.5); +} +.operations .insights > ul > li span { + font-weight: 600; +} +.operations .insights > ul > li span > span { + font-size: 8px; + line-height: 10px; + font-weight: normal; +} +.operations > button { + width: 100%; +} + +.notification { + padding: 30px 24px; + background-color: #ffffff; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.notification > h6 { + margin: 0; + color: rgba(41, 50, 65, 0.8); +} +.notification > h6 > a { + margin-left: 10px; +} +.notification > h6 > a i { + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -o-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); +} + +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav { + background-color: transparent; + margin: 0 -10px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav:before { + display: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header { + padding: 9px 0 0; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: transparent; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + margin: 0 10px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a { + position: relative; + width: 52px; + height: 52px; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + background-color: #D0D6DD; + cursor: pointer; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + color: #2170E7; + color: var(--primary-color); + border: 0 none; + overflow: visible; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a img { + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header a .ui-badge { + position: absolute; + bottom: -5px; + right: -5px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active { + padding: 0 0 9px; + border: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active a { + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.16), 0px 1px 2px rgba(41, 50, 65, 0.04), 0px 6px 12px rgba(41, 50, 65, 0.24); + border: 0 none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-active:before { + content: ""; + width: 12px; + height: 2px; + background: #2170E7; + background: var(--primary-color); + border-radius: 3px; + position: absolute; + bottom: -10px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-nav .ui-tabs-header.ui-state-hover { + border: none; + padding: 0 0 9px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels { + background-color: transparent; + border: none; + padding: 16px 0 0; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel { + padding: 0; + height: 350px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + height: 350px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .fade { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 44px; + background-image: linear-gradient(180deg, #ffffff 0%, rgba(234, 237, 243, 0) 100%); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content { + max-height: 400px; + overflow: auto; + padding: 30px 6px 12px; + flex: 1 1 auto; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message { + display: -ms-flexbox; + display: flex; + flex-direction: column; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .name { + display: block; + color: rgba(41, 50, 65, 0.5); + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + max-width: 250px; + padding: 8px 10px; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + background-color: #F7FAFF; + margin-bottom: 8px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message p { + padding: 0; + margin: 0 0 2px; + color: rgba(41, 50, 65, 0.8); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message span { + display: block; + font-weight: 600; + font-size: 10px; + line-height: 14px; + color: rgba(41, 50, 65, 0.5); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send { + -ms-flex-align: end; + align-items: flex-end; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message.send .message span { + text-align: right; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-content.no-message h4 { + color: rgba(41, 50, 65, 0.5); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts { + flex: 1 1 auto; + max-height: 400px; + overflow: auto; + padding: 0px 0 12px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul { + padding: 0; + margin: 0; + list-style: none; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin-bottom: 6px; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; + cursor: pointer; + padding: 8px 10px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li img { + margin-right: 12px; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li h6 { + margin: 0 0 2px; + color: rgba(41, 50, 65, 0.8); +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li span { + display: block; + color: rgba(41, 50, 65, 0.5); + font-weight: 600; + font-size: 10px; + line-height: 14px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .contacts ul > li:hover { + background-color: #F7FAFF; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input { + margin-top: 30px; +} +.chat .ui-tabs.ui-tabs-top .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { + width: 100%; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + padding: 20px 19px; + background-color: #F7F7F8; + border: none; +} + +.image-card { + padding: 0; + position: relative; +} +.image-card > span { + position: absolute; + right: 20px; + top: 20px; +} +.image-card > img { + width: 100%; + height: auto; + border-radius: 24px 24px 12px 12px; +} +.image-card .image-content { + padding: 32px 20px 28px; +} +.image-card .image-content h6 { + margin: 0 0 8px; +} +.image-card .image-content > p { + color: rgba(41, 50, 65, 0.5); +} +.image-card .image-content > button { + margin-top: 32px; + width: 100%; +} + +.login-body { + background: #FFFFFF; +} +.login-body .login-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + flex-direction: column; + height: 100vh; +} +.login-body .login-wrapper .login-panel { + width: 30%; + height: 100%; + text-align: center; + padding: 40px 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + flex: 1 1 100%; +} +.login-body .login-wrapper .login-panel .logo { + margin-bottom: 50px; +} +.login-body .login-wrapper .login-panel .logo img { + width: 45px; + height: 53px; +} +.login-body .login-wrapper .login-panel > a { + font-weight: 500; + font-size: 10px; + line-height: 12px; + color: rgba(41, 50, 65, 0.3); +} +.login-body .login-wrapper .login-panel > p { + font-weight: 500; + margin: 0; + color: rgba(41, 50, 65, 0.5); + margin-top: 40px; +} +.login-body .login-wrapper .login-panel > p > a { + color: #2170E7; + cursor: pointer; +} +.login-body .login-wrapper .login-panel > input { + width: 85%; + max-width: 247px; + margin-bottom: 10px; + background-color: #F6F7F7; + border: 1.2px solid #D4D6D9; + color: #515C66; + padding: 12px 10px; +} +.login-body .login-wrapper .login-panel > input::placeholder { + color: gba(41, 50, 65, 0.3); +} +.login-body .login-wrapper .login-panel > button { + width: 85%; + max-width: 247px; + margin-bottom: 10px; + padding: 0; +} +.login-body .login-wrapper .login-panel > button > span { + padding: 15px 20px; + display: block; + font-weight: 600; + font-size: 14px; + line-height: 16px; +} +.login-body .login-wrapper .login-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 70px; +} +.login-body .login-wrapper .login-footer h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.login-body .login-wrapper .login-footer h6 { + line-height: 17px; + margin: 0; + color: rgba(41, 50, 65, 0.5); + font-weight: 500; +} + +@media (max-width: 992px) { + .login-body .login-wrapper .login-panel { + width: 100%; + } +} +.exception-body .exception-topbar { + height: 62px; + background-color: #ffffff; + box-shadow: 0 10px 40px 0 rgba(41, 50, 65, 0.06); + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0 16px; +} +.exception-body .exception-topbar .layout-topbar-logo > img { + height: 15px; +} +.exception-body .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); +} +.exception-body .exception-wrapper .exception-content { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + flex: 1 1 auto; +} +.exception-body .exception-wrapper .exception-content > span { + font-weight: normal; + font-size: 60px; + line-height: 73px; + text-align: center; + display: block; +} +.exception-body .exception-wrapper .exception-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 70px; +} +.exception-body .exception-wrapper .exception-footer h4 { + line-height: 22px; + margin: 0; + margin-right: 32px; +} +.exception-body .exception-wrapper .exception-footer h6 { + line-height: 17px; + margin: 0; + color: rgba(41, 50, 65, 0.5); + font-weight: 500; +} +.exception-body.notfound .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); +} +.exception-body.notfound .exception-wrapper .exception-content { + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + -ms-flex-align: center; + align-items: center; + flex: 1 1 auto; +} +.exception-body.notfound .exception-wrapper .exception-content img { + width: 332px; + height: 271px; + margin-bottom: -150px; +} +.exception-body.notfound .exception-wrapper .exception-content > span { + font-size: 140px; + line-height: 171px; +} +.exception-body.notfound .exception-wrapper .exception-content > span.exception-subtitle { + font-weight: 500; + font-size: 14px; + line-height: 17px; + color: rgba(41, 50, 65, 0.5); +} +.exception-body.notfound .exception-wrapper .exception-content > button { + padding: 0; + margin-top: 20px; + width: 155px; + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; +} +.exception-body.notfound .exception-wrapper .exception-content > button > span { + padding: 18px; + font-weight: 600; +} + +@media (max-width: 991px) { + .exception-body .exception-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-align: center; + align-items: center; + min-height: calc(100vh - 62px); + } + .exception-body .exception-wrapper .exception-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding-bottom: 20px; + } +} +.landing-body { + background-color: #E5E5E5; +} +.landing-body .landing-topbar { + height: 83px; + background-color: #FFFFFF; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + width: 100%; + z-index: 999; + padding: 20px 40px; + position: relative; +} +.landing-body .landing-topbar .landing-topbar-left { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} +.landing-body .landing-topbar .landing-topbar-left .logo { + margin-right: 40px; +} +.landing-body .landing-topbar .landing-topbar-left .logo img { + height: 16px; + width: auto; +} +.landing-body .landing-topbar .landing-topbar-left > ul { + list-style-type: none; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + margin: 0; + padding: 0; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li #landing-menu-close { + display: none; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li > a { + font-weight: 600; + font-size: 12px; + line-height: 14px; + color: rgba(41, 50, 65, 0.9); + padding: 14px 10px; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + margin: 0 10px; + min-width: 100px; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.landing-body .landing-topbar .landing-topbar-left > ul > li > a:hover { + color: #2170E7; +} +.landing-body .landing-topbar .landing-topbar-right .second-menubutton { + margin-right: 20px; + font-weight: 600; + font-size: 12px; + line-height: 14px; + color: rgba(41, 50, 65, 0.9); + padding: 14px 10px; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + min-width: 100px; + -moz-transition: color 0.2s; + -o-transition: color 0.2s; + -webkit-transition: color 0.2s; + transition: color 0.2s; +} +.landing-body .landing-topbar .landing-topbar-right .second-menubutton:hover { + color: #2170E7; +} +.landing-body .landing-topbar .landing-topbar-right .landing-button span { + font-weight: 600; + font-size: 12px; + line-height: 14px; +} +.landing-body .landing-topbar .landing-topbar-right #landing-menu-button { + display: none; + padding: 0 8px; + cursor: pointer; +} +.landing-body .landing-topbar .landing-topbar-right #landing-menu-button i { + font-size: 20px; +} +.landing-body .landing-button { + background: linear-gradient(108.43deg, #297FFF 12.5%, #7A0EE7 96.32%); + border: none; + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + -moz-transition: all 0.2s; + -o-transition: all 0.2s; + -webkit-transition: all 0.2s; + transition: all 0.2s; +} +.landing-body .landing-button.ui-button { + padding: 0; +} +.landing-body .landing-button.ui-button > .ui-button-text { + padding: 14px 10px; + min-width: 121px; + font-weight: 600; + font-size: 16px; + line-height: 19px; + display: block; +} +.landing-body .landing-button > a .ui-button-text { + padding: 14px 10px; + min-width: 87px; + font-weight: 600; + font-size: 16px; + line-height: 19px; + display: block; +} +.landing-body .landing-button:hover { + background: linear-gradient(108.43deg, #2f79e7 12.5%, #781cd4 96.32%); +} +.landing-body .landing-banner { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + padding: 303px 30px 218px; + position: relative; + transform-style: inherit; + background: url("#{resource['freya-layout:images/pages/asset-landing-header.jpg']}"); + background-size: cover; + height: 80vh; +} +.landing-body .landing-banner .landing-banner-content { + text-align: center; + position: relative; +} +.landing-body .landing-banner .landing-banner-content .title { + display: block; + font-weight: 500; + font-size: 70px; + line-height: 84px; + color: #FFFFFF; +} +.landing-body .landing-banner .landing-banner-content h3 { + margin: 40px 0 30px; + color: #FFFFFF; + font-weight: 500; + line-height: 29px; +} +.landing-body .section-header { + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-direction: column; +} +.landing-body .section-header .title { + display: block; + font-weight: 500; + font-size: 70px; + line-height: 84px; + color: rgba(41, 50, 65, 0.9); +} +.landing-body .section-header h3 { + margin: 15px 0 100px; + color: rgba(41, 50, 65, 0.9); + font-weight: 500; + line-height: 29px; + max-width: 800px; +} +.landing-body .landing-features { + background-color: #FFFFFF; + position: relative; + display: -ms-flexbox; + display: flex; + flex-wrap: wrap; + padding: 36px 6% 125px; +} +.landing-body .landing-features .lg\:col-3 { + transition: transform 250ms linear; + -webkit-transition: transform 250ms linear; +} +.landing-body .landing-features .feature { + display: -ms-flexbox; + display: flex; +} +.landing-body .landing-features .feature > span { + font-weight: 500; + font-size: 20px; + line-height: 20px; + color: rgba(41, 50, 65, 0.8); + margin-top: 30px; + margin-right: 12px; +} +.landing-body .landing-features .feature .feature-card { + -moz-border-radius: 36px; + -webkit-border-radius: 36px; + border-radius: 36px; + padding: 28px 30px; + display: -ms-flexbox; + display: flex; + width: 100%; +} +.landing-body .landing-features .feature .feature-card > span { + display: none; +} +.landing-body .landing-features .feature .feature-card h3 { + font-weight: 500; + line-height: 36px; + margin: 0 0 20px; + color: rgba(41, 50, 65, 0.8); +} +.landing-body .landing-features .feature .feature-card h5 { + margin: 0; + font-weight: normal; + line-height: 150%; + color: rgba(41, 50, 65, 0.9); + opacity: 0.8; +} +.landing-body .landing-features .feature.yellow .feature-card { + padding-bottom: 128px; + background: linear-gradient(197.55deg, #FFD37D -1.02%, #FFDB7D 46.53%); +} +.landing-body .landing-features .feature.blue .feature-card { + padding-bottom: 67px; + background: linear-gradient(156.18deg, #DAF4FF 38.02%, #CEDFFF 95.69%); +} +.landing-body .landing-features .feature.darker-blue .feature-card { + padding-bottom: 164px; + background: linear-gradient(165.84deg, #C1E9FF 42.24%, rgba(219, 242, 255, 0.23) 97.17%); +} +.landing-body .landing-features .feature.darker-gray .feature-card { + padding-bottom: 109px; + background: linear-gradient(176.91deg, rgba(41, 50, 65, 0.6) 50%, rgba(41, 50, 65, 0.282) 115.03%); +} +.landing-body .landing-features .feature.darker-gray .feature-card h3 { + color: #FFFFFF; +} +.landing-body .landing-features .feature.darker-gray .feature-card h5 { + color: #FFFFFF; + opacity: 0.8; +} +.landing-body .landing-features .feature.gray .feature-card { + padding-bottom: 50px; + background: linear-gradient(11.49deg, rgba(41, 50, 65, 0.1) 60.37%, rgba(41, 50, 65, 0.026) 98.03%); +} +.landing-body .landing-pricing { + background-color: #FFFFFF; + position: relative; + padding: 125px 15% 260px; + text-align: center; +} +.landing-body .landing-pricing .pricing-card { + background: #FFFFFF; + box-shadow: 0px 0px 1px rgba(41, 50, 65, 0.5), 0px 1px 1px rgba(41, 50, 65, 0.2); + -moz-border-radius: 24px; + -webkit-border-radius: 24px; + border-radius: 24px; + padding: 30px 20px 33px; + text-align: center; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + flex-direction: column; + position: relative; + margin-bottom: 60px; +} +.landing-body .landing-pricing .pricing-card .preferred-tag { + padding: 14px 24px; + background: linear-gradient(112.58deg, #FFD029 22.19%, #F1AF60 100%); + box-shadow: 0px 10px 40px rgba(41, 50, 65, 0.06); + -moz-border-radius: 12px; + -webkit-border-radius: 12px; + border-radius: 12px; + transform: rotate(-7.18deg); + position: absolute; + top: -32px; + color: #FFFFFF; + font-weight: bold; + font-size: 20px; + line-height: 24px; +} +.landing-body .landing-pricing .pricing-card h2 { + margin: 0 0 14px; + color: rgba(41, 50, 65, 0.9); +} +.landing-body .landing-pricing .pricing-card .price { + display: block; + color: #2170E7; + font-weight: bold; + font-size: 80px; + line-height: 95px; +} +.landing-body .landing-pricing .pricing-card .time { + color: rgba(41, 50, 65, 0.5); + font-size: 12px; + line-height: 14px; + display: block; + margin-bottom: 32px; +} +.landing-body .landing-pricing .pricing-card > ul { + padding: 42px 0 0; + width: 100%; + margin: 0; + list-style: none; + border-top: 1px solid rgba(41, 50, 65, 0.1); +} +.landing-body .landing-pricing .pricing-card > ul > li { + font-size: 16px; + line-height: 205.34%; + color: rgba(41, 50, 65, 0.5); +} +.landing-body .landing-pricing .pricing-card.pro { + background: linear-gradient(333.31deg, #EFF3FB 6.36%, #FFFFFF 72.79%); +} +.landing-body .landing-pricing .pricing-card.enterprise { + background: linear-gradient(156.19deg, rgba(41, 50, 65, 0.8) 10.28%, rgba(35, 40, 49, 0.496) 87.74%); +} +.landing-body .landing-pricing .pricing-card.enterprise h2 { + margin: 0 0 14px; + color: #FFFFFF; +} +.landing-body .landing-pricing .pricing-card.enterprise .price { + color: #FFFFFF; +} +.landing-body .landing-pricing .pricing-card.enterprise .time { + color: #FFFFFF; + opacity: 0.6; +} +.landing-body .landing-pricing .pricing-card.enterprise > ul { + border-top: 1px solid rgba(255, 255, 255, 0.2); +} +.landing-body .landing-pricing .pricing-card.enterprise > ul > li { + color: #FFFFFF; +} +.landing-body .landing-pricing > a { + font-size: 24px; + line-height: 29px; + display: block; +} +.landing-body .layout-footer { + background-color: #FFFFFF; + position: relative; +} +.landing-body .layout-footer .footer-menutitle { + color: rgba(41, 50, 65, 0.2); +} +.landing-body .layout-footer .footer-subtitle { + color: rgba(41, 50, 65, 0.3); +} +.landing-body .layout-footer ul > li { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .layout-footer ul > li > a { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .layout-footer ul > li > a:hover { + color: rgba(41, 50, 65, 0.3); +} +.landing-body .layout-footer .newsletter-input { + background-color: rgba(41, 50, 65, 0.04); +} +.landing-body .layout-footer .footer-bottom { + color: rgba(41, 50, 65, 0.7); +} +.landing-body .layout-footer .footer-bottom h6 { + color: rgba(41, 50, 65, 0.5); +} +.landing-body .landing-mask { + display: none; + width: 100%; + height: 100vh; + position: fixed; + top: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.2); + z-index: 998; +} + +@media (max-width: 991px) { + .landing-body.block-scroll { + overflow: hidden; + } + .landing-body.block-scroll .landing-wrapper .landing-mask { + display: block; + } + .landing-body .landing-wrapper.landing-menu-active .landing-topbar .landing-menu { + transform: translate3d(0px, 0px, 0px); + } + .landing-body .landing-wrapper .landing-topbar { + padding: 0 13px; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu { + position: fixed; + flex-direction: column; + -ms-flex-align: end; + align-items: flex-end; + right: 0; + top: 0; + padding: 28px 15px; + z-index: 999; + width: 220px; + height: 100%; + background-color: #EEF5FF; + box-shadow: 0 24px 64px -2px rgba(0, 0, 0, 0.02), 0 6px 16px -2px rgba(0, 0, 0, 0.06), 0 2px 6px -2px rgba(0, 0, 0, 0.08); + transform: translate3d(260px, 0px, 0px); + -moz-transition: transform 0.2s; + -o-transition: transform 0.2s; + -webkit-transition: transform 0.2s; + transition: transform 0.2s; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li { + margin: 0; + width: 100%; + margin-bottom: 12px; + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a { + padding: 6px 16px; + font-size: 14px; + text-align: right; + background-color: #EEF5FF; + display: block; + color: rgba(41, 50, 65, 0.9); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li > a:hover { + color: rgba(41, 50, 65, 0.6); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close { + display: block; + font-size: 20px; + text-align: right; + color: rgba(41, 50, 65, 0.9); + } + .landing-body .landing-wrapper .landing-topbar .landing-menu > li #landing-menu-close:hover { + color: rgba(41, 50, 65, 0.6); + } + .landing-body .landing-wrapper .landing-topbar #landing-menu-button { + display: block; + color: rgba(41, 50, 65, 0.9); + font-size: 20px; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .second-menubutton { + display: none; + } + .landing-body .landing-wrapper .landing-topbar .landing-topbar-right .landing-button { + margin-right: 20px; + } + .landing-body .landing-wrapper .landing-banner { + background-position: top; + padding: 80px 23px; + -ms-flex-pack: start; + justify-content: flex-start; + height: auto; + top: auto !important; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content { + text-align: left; + max-width: 262px; + top: auto !important; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content > span { + font-size: 60px; + line-height: 91.84%; + } + .landing-body .landing-wrapper .landing-banner .landing-banner-content > h3 { + font-size: 18px; + line-height: 130%; + } + .landing-body .landing-wrapper .landing-features { + padding: 36px 20px 30px; + } + .landing-body .landing-wrapper .landing-features .lg\:col-3 { + transform: translateY(0) !important; + margin-top: auto !important; + } + .landing-body .landing-wrapper .landing-features .feature-empty { + display: none; + } + .landing-body .landing-wrapper .landing-features .feature-3 { + margin-top: auto; + } + .landing-body .landing-wrapper .landing-features .feature-4 { + margin-top: auto; + } + .landing-body .landing-wrapper .landing-features .feature > span { + display: none; + } + .landing-body .landing-wrapper .landing-features .feature .feature-card { + padding-bottom: 28px !important; + } + .landing-body .landing-wrapper .landing-features .feature .feature-card > span { + font-weight: 500; + font-size: 20px; + line-height: 20px; + color: rgba(41, 50, 65, 0.8); + margin-right: 12px; + margin-top: 8px; + display: block; + } + .landing-body .landing-wrapper .landing-features .feature.blue .feature-card { + flex-direction: row-reverse; + text-align: right; + } + .landing-body .landing-wrapper .landing-features .feature.blue .feature-card > span { + margin-right: 0px; + margin-left: 12px; + } + .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card { + flex-direction: row-reverse; + text-align: right; + } + .landing-body .landing-wrapper .landing-features .feature.darker-gray .feature-card > span { + color: #FFFFFF; + float: right; + margin-right: 0px; + margin-left: 12px; + } + .landing-body .landing-wrapper .section-header .title { + font-size: 60px; + line-height: 72px; + } + .landing-body .landing-wrapper .section-header h3 { + font-size: 18px; + line-height: 130%; + } + .landing-body .landing-wrapper .landing-pricing { + padding: 30px 20px 97px; + } + .landing-body .landing-wrapper .landing-pricing .pricing-card { + margin-bottom: 20px; + } + .landing-body .landing-wrapper .landing-pricing .pricing-card > ul { + display: none; + } + .landing-body .landing-wrapper .landing-pricing .preferred { + order: -1 !important; + } + .landing-body .landing-wrapper .landing-pricing .preferred .pricing-card > ul { + display: block; + } +} +.help-page p { + margin: 0; +} +.help-page .help-search { + background-image: url("#{resource['freya-layout:images/pages/search.png']}"); + padding: 0; + text-align: center; +} +.help-page .help-search .help-search-content { + padding: 5rem 12rem; +} +.help-page .help-search .help-search-content h3 { + color: rgba(41, 50, 65, 0.8); + font-weight: 500; +} +.help-page .help-search .search-container { + font-size: 1rem; + padding: 1rem; + position: relative; +} +.help-page .help-search .search-container input { + appearance: none; + font-size: 1rem; + text-indent: 2rem; + padding: 1rem; + width: 100%; +} +.help-page .help-search .search-container i { + width: 1rem; + position: absolute; + margin-left: 1rem; + top: 50%; + margin-top: -0.5rem; +} +.help-page .status-bars { + margin-top: 1rem; + display: -ms-flexbox; + display: flex; +} +.help-page .status-bars .status-bar { + flex: 1 1 0; + -ms-flex: 1 1 0px; + background: #6EC180; + height: 50px; + margin-right: 0.25rem; + transition: transform 0.2s; +} +.help-page .status-bars .status-bar:last-child { + margin-right: 0; +} +.help-page .status-bars .status-bar.status-bar-failure { + background: #FF6E49; +} +.help-page .status-bars .status-bar:hover { + transform: scale(1.1); +} +.help-page .status-bar-footer { + padding: 1rem 0 0 0; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; +} +.help-page .blog-post { + border-radius: 4px; + padding: 20px; + margin: 3rem 2rem; + border: 1px solid #dee2e6; + background-color: #ffffff; + position: relative; + -moz-border-radius: 20px; + -webkit-border-radius: 20px; + border-radius: 20px; +} +.help-page .blog-post:last-child { + margin-bottom: 1rem; +} +.help-page .blog-post img { + width: 100%; + position: absolute; + left: 0; + top: 0; +} +.help-page .blog-post .blog-text h1 { + color: rgba(41, 50, 65, 0.8); + margin-bottom: 1rem; + font-weight: 500; +} +.help-page .blog-post .blog-text span { + color: rgba(41, 50, 65, 0.5); + line-height: 1.4; +} +.help-page .blog-post .blog-profile { + position: absolute; + top: -25px; + left: -25px; +} +.help-page .blog-post .blog-profile img { + width: 50px; + height: 50px; + border-radius: 50%; +} + +@media screen and (max-width: 991px) { + .help-page .help-search .help-search-content { + padding: 6rem 2rem; + } +} +.invoice { + padding: 2rem; +} +.invoice .invoice-header { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; +} +.invoice .invoice-company .logo-image { + height: 50px; + margin-bottom: 0.5rem; +} +.invoice .invoice-company div { + margin-bottom: 0.5rem; +} +.invoice .invoice-company .company-name { + font-weight: 500; + font-size: 1.5rem; +} +.invoice .invoice-title { + font-size: 2rem; + margin-bottom: 2rem; + text-align: right; + font-weight: 300; +} +.invoice .invoice-details { + width: 15rem; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.invoice .invoice-details > div { + width: 50%; + margin-bottom: 0.5rem; +} +.invoice .invoice-details .invoice-label { + text-align: left; + font-weight: 500; +} +.invoice .invoice-details .invoice-value { + text-align: right; +} +.invoice .invoice-to { + margin-top: 1.5rem; + padding-top: 2rem; + border-top: 1px solid #F2F4F6; +} +.invoice .invoice-to .bill-to { + font-size: 1.25rem; + font-weight: 500; + margin-bottom: 0.5rem; +} +.invoice .invoice-to .invoice-to-info div { + margin-bottom: 0.5rem; +} +.invoice .invoice-items { + margin-top: 2rem; + padding-top: 2rem; +} +.invoice .invoice-items table { + width: 100%; + border-collapse: collapse; +} +.invoice .invoice-items table tr { + border-bottom: 1px solid #F2F4F6; +} +.invoice .invoice-items table th { + font-weight: 500; +} +.invoice .invoice-items table th, .invoice .invoice-items table td { + padding: 1rem; + text-align: right; +} +.invoice .invoice-items table th:first-child, .invoice .invoice-items table td:first-child { + text-align: left; +} +.invoice .invoice-summary { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + margin-top: 2.5rem; + padding-top: 2.5rem; +} +.invoice .invoice-summary .invoice-value { + font-weight: 500; +} + +@media print { + body * { + visibility: hidden; + } + + #invoice-content * { + visibility: visible; + } + + #invoice-content { + width: 100%; + position: absolute; + left: 0; + top: 0; + padding: 0; + margin: 0; + background: #ffffff; + color: rgba(41, 50, 65, 0.8); + } + + .invoice .invoice-to { + border-top: 1px solid #F2F4F6; + } + .invoice .invoice-items table tr { + border-bottom: 1px solid #F2F4F6; + } +} +.layout-config { + width: 16rem; + height: 100%; + position: fixed; + right: 0; + top: 0; + padding: 1rem; + overflow: auto; + background: #ffffff; + z-index: 999; + border-left: 0 none; + transform: translateX(100%); + transition: transform 0.2s cubic-bezier(0.05, 0.74, 0.2, 0.99); +} +.layout-config.layout-config-active { + transform: translateX(0); + box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); +} +.layout-config.layout-config-active .layout-config-content .layout-config-button i { + transform: rotate(360deg); +} +.layout-config .ui-selectoneradio td { + padding: 0.5rem; +} +.layout-config p { + line-height: 1.5rem; + color: #6c757d; +} +.layout-config .layout-themes { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +.layout-config .layout-themes > div { + padding: 0.25rem; +} +.layout-config .layout-themes a { + width: 2rem; + height: 2rem; + border-radius: 24px; + display: block; + position: relative; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + transition: transform 0.2s; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); +} +.layout-config .layout-themes a i { + font-size: 1rem; + position: absolute; + top: 50%; + left: 50%; + margin-left: -0.5rem; + margin-top: -0.5rem; +} +.layout-config .layout-themes a:hover { + transform: scale(1.1); +} + +.layout-config-button { + display: block; + position: fixed; + width: 3rem; + height: 3rem; + line-height: 3rem; + background: #1976D2; + color: #ffffff; + text-align: center; + top: 50%; + right: 0; + margin-top: -1.5rem; + border-top-left-radius: 24px; + border-bottom-left-radius: 24px; + transition: background-color 0.2s; + overflow: hidden; + cursor: pointer; + z-index: 999; + box-shadow: -0.25rem 0 1rem rgba(0, 0, 0, 0.15); +} +.layout-config-button i { + font-size: 2rem; + line-height: inherit; + transform: rotate(0deg); + transition: transform 1s; +} +.layout-config-button:hover { + background: #2083e4; +} + +/* Add your customizations of the layout styles here */ +.layout-wrapper .layout-rightpanel .rightpanel-wrapper { + position: relative; + height: 100%; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header { + text-align: center; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-header .profile { + padding: 12px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions { + padding: 12px 6px 36px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .col-6, .layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-actions .actions .action-buttons .md\:col-4 { + padding: 0.2em; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav { + background-color: white; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header { + padding: 1rem; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header a { + font-size: 12px; + font-weight: 500; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header > span { + font-size: 10px; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-nav li.ui-tabs-header.ui-state-active { + background-color: #F7FAFF; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels { + background-color: white; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel { + padding: 0; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-content .chat-message .message { + width: 80%; +} +.layout-wrapper .layout-rightpanel .rightpanel-wrapper .rightpanel-chat .ui-tabs .ui-tabs-panels .ui-tabs-panel .chat .chat-input input { + width: 105px; + margin-right: 7px; +} diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.scss b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.scss index ed65b45..e54fc00 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.scss +++ b/src/main/resources/META-INF/resources/resources/freya-layout/css/layout-light.scss @@ -1,5 +1,5 @@ -$primaryColor:#2170E7; -$primaryTextColor:#ffffff; - -@import '../../sass/variables/layout/_layout_light'; +$primaryColor:#2170E7; +$primaryTextColor:#ffffff; + +@import '../../sass/variables/layout/_layout_light'; @import '../../sass/layout/_layout'; \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/css/primeicons.css b/src/main/resources/META-INF/resources/resources/freya-layout/css/primeicons.css index 397a28e..697658c 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/css/primeicons.css +++ b/src/main/resources/META-INF/resources/resources/freya-layout/css/primeicons.css @@ -1,1017 +1,1017 @@ -@font-face { - font-family: 'primeicons'; - font-display: block; - src: url("#{resource['freya-layout:icons/primeicons.eot']}"); - src: url("#{resource['freya-layout:icons/primeicons.eot']}#iefix") format('embedded-opentype'), - url("#{resource['freya-layout:icons/primeicons.ttf']}") format('truetype'), - url("#{resource['freya-layout:icons/primeicons.woff']}") format('woff'), - url("#{resource['freya-layout:icons/primeicons.svg']}#primeicons") format('svg'); - font-weight: normal; - font-style: normal; -} - -.pi { - font-family: 'primeicons'; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - display: inline-block; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.pi:before { - --webkit-backface-visibility:hidden; - backface-visibility: hidden; -} - -.pi-fw { - width: 1.28571429em; - text-align: center; -} - -.pi-spin { - -webkit-animation: fa-spin 2s infinite linear; - animation: fa-spin 2s infinite linear; -} - -@-webkit-keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -@keyframes fa-spin { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -.pi-sort-alt-slash:before { - content: "\e9ee"; -} - -.pi-arrows-h:before { - content: "\e9ec"; -} - -.pi-arrows-v:before { - content: "\e9ed"; -} - -.pi-pound:before { - content: "\e9eb"; -} - -.pi-prime:before { - content: "\e9ea"; -} - -.pi-chart-pie:before { - content: "\e9e9"; -} - -.pi-reddit:before { - content: "\e9e8"; -} - -.pi-code:before { - content: "\e9e7"; -} - -.pi-sync:before { - content: "\e9e6"; -} - -.pi-shopping-bag:before { - content: "\e9e5"; -} - -.pi-server:before { - content: "\e9e4"; -} - -.pi-database:before { - content: "\e9e3"; -} - -.pi-hashtag:before { - content: "\e9e2"; -} - -.pi-bookmark-fill:before { - content: "\e9df"; -} - -.pi-filter-fill:before { - content: "\e9e0"; -} - -.pi-heart-fill:before { - content: "\e9e1"; -} - -.pi-flag-fill:before { - content: "\e9de"; -} - -.pi-circle:before { - content: "\e9dc"; -} - -.pi-circle-fill:before { - content: "\e9dd"; -} - -.pi-bolt:before { - content: "\e9db"; -} - -.pi-history:before { - content: "\e9da"; -} - -.pi-box:before { - content: "\e9d9"; -} - -.pi-at:before { - content: "\e9d8"; -} - -.pi-arrow-up-right:before { - content: "\e9d4"; -} - -.pi-arrow-up-left:before { - content: "\e9d5"; -} - -.pi-arrow-down-left:before { - content: "\e9d6"; -} - -.pi-arrow-down-right:before { - content: "\e9d7"; -} - -.pi-telegram:before { - content: "\e9d3"; -} - -.pi-stop-circle:before { - content: "\e9d2"; -} - -.pi-stop:before { - content: "\e9d1"; -} - -.pi-whatsapp:before { - content: "\e9d0"; -} - -.pi-building:before { - content: "\e9cf"; -} - -.pi-qrcode:before { - content: "\e9ce"; -} - -.pi-car:before { - content: "\e9cd"; -} - -.pi-instagram:before { - content: "\e9cc"; -} - -.pi-linkedin:before { - content: "\e9cb"; -} - -.pi-send:before { - content: "\e9ca"; -} - -.pi-slack:before { - content: "\e9c9"; -} - -.pi-sun:before { - content: "\e9c8"; -} - -.pi-moon:before { - content: "\e9c7"; -} - -.pi-vimeo:before { - content: "\e9c6"; -} - -.pi-youtube:before { - content: "\e9c5"; -} - -.pi-flag:before { - content: "\e9c4"; -} - -.pi-wallet:before { - content: "\e9c3"; -} - -.pi-map:before { - content: "\e9c2"; -} - -.pi-link:before { - content: "\e9c1"; -} - -.pi-credit-card:before { - content: "\e9bf"; -} - -.pi-discord:before { - content: "\e9c0"; -} - -.pi-percentage:before { - content: "\e9be"; -} - -.pi-euro:before { - content: "\e9bd"; -} - -.pi-book:before { - content: "\e9ba"; -} - -.pi-shield:before { - content: "\e9b9"; -} - -.pi-paypal:before { - content: "\e9bb"; -} - -.pi-amazon:before { - content: "\e9bc"; -} - -.pi-phone:before { - content: "\e9b8"; -} - -.pi-filter-slash:before { - content: "\e9b7"; -} - -.pi-facebook:before { - content: "\e9b4"; -} - -.pi-github:before { - content: "\e9b5"; -} - -.pi-twitter:before { - content: "\e9b6"; -} - -.pi-step-backward-alt:before { - content: "\e9ac"; -} - -.pi-step-forward-alt:before { - content: "\e9ad"; -} - -.pi-forward:before { - content: "\e9ae"; -} - -.pi-backward:before { - content: "\e9af"; -} - -.pi-fast-backward:before { - content: "\e9b0"; -} - -.pi-fast-forward:before { - content: "\e9b1"; -} - -.pi-pause:before { - content: "\e9b2"; -} - -.pi-play:before { - content: "\e9b3"; -} - -.pi-compass:before { - content: "\e9ab"; -} - -.pi-id-card:before { - content: "\e9aa"; -} - -.pi-ticket:before { - content: "\e9a9"; -} - -.pi-file-o:before { - content: "\e9a8"; -} - -.pi-reply:before { - content: "\e9a7"; -} - -.pi-directions-alt:before { - content: "\e9a5"; -} - -.pi-directions:before { - content: "\e9a6"; -} - -.pi-thumbs-up:before { - content: "\e9a3"; -} - -.pi-thumbs-down:before { - content: "\e9a4"; -} - -.pi-sort-numeric-down-alt:before { - content: "\e996"; -} - -.pi-sort-numeric-up-alt:before { - content: "\e997"; -} - -.pi-sort-alpha-down-alt:before { - content: "\e998"; -} - -.pi-sort-alpha-up-alt:before { - content: "\e999"; -} - -.pi-sort-numeric-down:before { - content: "\e99a"; -} - -.pi-sort-numeric-up:before { - content: "\e99b"; -} - -.pi-sort-alpha-down:before { - content: "\e99c"; -} - -.pi-sort-alpha-up:before { - content: "\e99d"; -} - -.pi-sort-alt:before { - content: "\e99e"; -} - -.pi-sort-amount-up:before { - content: "\e99f"; -} - -.pi-sort-amount-down:before { - content: "\e9a0"; -} - -.pi-sort-amount-down-alt:before { - content: "\e9a1"; -} - -.pi-sort-amount-up-alt:before { - content: "\e9a2"; -} - -.pi-palette:before { - content: "\e995"; -} - -.pi-undo:before { - content: "\e994"; -} - -.pi-desktop:before { - content: "\e993"; -} - -.pi-sliders-v:before { - content: "\e991"; -} - -.pi-sliders-h:before { - content: "\e992"; -} - -.pi-search-plus:before { - content: "\e98f"; -} - -.pi-search-minus:before { - content: "\e990"; -} - -.pi-file-excel:before { - content: "\e98e"; -} - -.pi-file-pdf:before { - content: "\e98d"; -} - -.pi-check-square:before { - content: "\e98c"; -} - -.pi-chart-line:before { - content: "\e98b"; -} - -.pi-user-edit:before { - content: "\e98a"; -} - -.pi-exclamation-circle:before { - content: "\e989"; -} - -.pi-android:before { - content: "\e985"; -} - -.pi-google:before { - content: "\e986"; -} - -.pi-apple:before { - content: "\e987"; -} - -.pi-microsoft:before { - content: "\e988"; -} - -.pi-heart:before { - content: "\e984"; -} - -.pi-mobile:before { - content: "\e982"; -} - -.pi-tablet:before { - content: "\e983"; -} - -.pi-key:before { - content: "\e981"; -} - -.pi-shopping-cart:before { - content: "\e980"; -} - -.pi-comments:before { - content: "\e97e"; -} - -.pi-comment:before { - content: "\e97f"; -} - -.pi-briefcase:before { - content: "\e97d"; -} - -.pi-bell:before { - content: "\e97c"; -} - -.pi-paperclip:before { - content: "\e97b"; -} - -.pi-share-alt:before { - content: "\e97a"; -} - -.pi-envelope:before { - content: "\e979"; -} - -.pi-volume-down:before { - content: "\e976"; -} - -.pi-volume-up:before { - content: "\e977"; -} - -.pi-volume-off:before { - content: "\e978"; -} - -.pi-eject:before { - content: "\e975"; -} - -.pi-money-bill:before { - content: "\e974"; -} - -.pi-images:before { - content: "\e973"; -} - -.pi-image:before { - content: "\e972"; -} - -.pi-sign-in:before { - content: "\e970"; -} - -.pi-sign-out:before { - content: "\e971"; -} - -.pi-wifi:before { - content: "\e96f"; -} - -.pi-sitemap:before { - content: "\e96e"; -} - -.pi-chart-bar:before { - content: "\e96d"; -} - -.pi-camera:before { - content: "\e96c"; -} - -.pi-dollar:before { - content: "\e96b"; -} - -.pi-lock-open:before { - content: "\e96a"; -} - -.pi-table:before { - content: "\e969"; -} - -.pi-map-marker:before { - content: "\e968"; -} - -.pi-list:before { - content: "\e967"; -} - -.pi-eye-slash:before { - content: "\e965"; -} - -.pi-eye:before { - content: "\e966"; -} - -.pi-folder-open:before { - content: "\e964"; -} - -.pi-folder:before { - content: "\e963"; -} - -.pi-video:before { - content: "\e962"; -} - -.pi-inbox:before { - content: "\e961"; -} - -.pi-lock:before { - content: "\e95f"; -} - -.pi-unlock:before { - content: "\e960"; -} - -.pi-tags:before { - content: "\e95d"; -} - -.pi-tag:before { - content: "\e95e"; -} - -.pi-power-off:before { - content: "\e95c"; -} - -.pi-save:before { - content: "\e95b"; -} - -.pi-question-circle:before { - content: "\e959"; -} - -.pi-question:before { - content: "\e95a"; -} - -.pi-copy:before { - content: "\e957"; -} - -.pi-file:before { - content: "\e958"; -} - -.pi-clone:before { - content: "\e955"; -} - -.pi-calendar-times:before { - content: "\e952"; -} - -.pi-calendar-minus:before { - content: "\e953"; -} - -.pi-calendar-plus:before { - content: "\e954"; -} - -.pi-ellipsis-v:before { - content: "\e950"; -} - -.pi-ellipsis-h:before { - content: "\e951"; -} - -.pi-bookmark:before { - content: "\e94e"; -} - -.pi-globe:before { - content: "\e94f"; -} - -.pi-replay:before { - content: "\e94d"; -} - -.pi-filter:before { - content: "\e94c"; -} - -.pi-print:before { - content: "\e94b"; -} - -.pi-align-right:before { - content: "\e946"; -} - -.pi-align-left:before { - content: "\e947"; -} - -.pi-align-center:before { - content: "\e948"; -} - -.pi-align-justify:before { - content: "\e949"; -} - -.pi-cog:before { - content: "\e94a"; -} - -.pi-cloud-download:before { - content: "\e943"; -} - -.pi-cloud-upload:before { - content: "\e944"; -} - -.pi-cloud:before { - content: "\e945"; -} - -.pi-pencil:before { - content: "\e942"; -} - -.pi-users:before { - content: "\e941"; -} - -.pi-clock:before { - content: "\e940"; -} - -.pi-user-minus:before { - content: "\e93e"; -} - -.pi-user-plus:before { - content: "\e93f"; -} - -.pi-trash:before { - content: "\e93d"; -} - -.pi-external-link:before { - content: "\e93c"; -} - -.pi-window-maximize:before { - content: "\e93b"; -} - -.pi-window-minimize:before { - content: "\e93a"; -} - -.pi-refresh:before { - content: "\e938"; -} - -.pi-user:before { - content: "\e939"; -} - -.pi-exclamation-triangle:before { - content: "\e922"; -} - -.pi-calendar:before { - content: "\e927"; -} - -.pi-chevron-circle-left:before { - content: "\e928"; -} - -.pi-chevron-circle-down:before { - content: "\e929"; -} - -.pi-chevron-circle-right:before { - content: "\e92a"; -} - -.pi-chevron-circle-up:before { - content: "\e92b"; -} - -.pi-angle-double-down:before { - content: "\e92c"; -} - -.pi-angle-double-left:before { - content: "\e92d"; -} - -.pi-angle-double-right:before { - content: "\e92e"; -} - -.pi-angle-double-up:before { - content: "\e92f"; -} - -.pi-angle-down:before { - content: "\e930"; -} - -.pi-angle-left:before { - content: "\e931"; -} - -.pi-angle-right:before { - content: "\e932"; -} - -.pi-angle-up:before { - content: "\e933"; -} - -.pi-upload:before { - content: "\e934"; -} - -.pi-download:before { - content: "\e956"; -} - -.pi-ban:before { - content: "\e935"; -} - -.pi-star-fill:before { - content: "\e936"; -} - -.pi-star:before { - content: "\e937"; -} - -.pi-chevron-left:before { - content: "\e900"; -} - -.pi-chevron-right:before { - content: "\e901"; -} - -.pi-chevron-down:before { - content: "\e902"; -} - -.pi-chevron-up:before { - content: "\e903"; -} - -.pi-caret-left:before { - content: "\e904"; -} - -.pi-caret-right:before { - content: "\e905"; -} - -.pi-caret-down:before { - content: "\e906"; -} - -.pi-caret-up:before { - content: "\e907"; -} - -.pi-search:before { - content: "\e908"; -} - -.pi-check:before { - content: "\e909"; -} - -.pi-check-circle:before { - content: "\e90a"; -} - -.pi-times:before { - content: "\e90b"; -} - -.pi-times-circle:before { - content: "\e90c"; -} - -.pi-plus:before { - content: "\e90d"; -} - -.pi-plus-circle:before { - content: "\e90e"; -} - -.pi-minus:before { - content: "\e90f"; -} - -.pi-minus-circle:before { - content: "\e910"; -} - -.pi-circle-on:before { - content: "\e911"; -} - -.pi-circle-off:before { - content: "\e912"; -} - -.pi-sort-down:before { - content: "\e913"; -} - -.pi-sort-up:before { - content: "\e914"; -} - -.pi-sort:before { - content: "\e915"; -} - -.pi-step-backward:before { - content: "\e916"; -} - -.pi-step-forward:before { - content: "\e917"; -} - -.pi-th-large:before { - content: "\e918"; -} - -.pi-arrow-down:before { - content: "\e919"; -} - -.pi-arrow-left:before { - content: "\e91a"; -} - -.pi-arrow-right:before { - content: "\e91b"; -} - -.pi-arrow-up:before { - content: "\e91c"; -} - -.pi-bars:before { - content: "\e91d"; -} - -.pi-arrow-circle-down:before { - content: "\e91e"; -} - -.pi-arrow-circle-left:before { - content: "\e91f"; -} - -.pi-arrow-circle-right:before { - content: "\e920"; -} - -.pi-arrow-circle-up:before { - content: "\e921"; -} - -.pi-info:before { - content: "\e923"; -} - -.pi-info-circle:before { - content: "\e924"; -} - -.pi-home:before { - content: "\e925"; -} - -.pi-spinner:before { - content: "\e926"; -} +@font-face { + font-family: 'primeicons'; + font-display: block; + src: url("#{resource['freya-layout:icons/primeicons.eot']}"); + src: url("#{resource['freya-layout:icons/primeicons.eot']}#iefix") format('embedded-opentype'), + url("#{resource['freya-layout:icons/primeicons.ttf']}") format('truetype'), + url("#{resource['freya-layout:icons/primeicons.woff']}") format('woff'), + url("#{resource['freya-layout:icons/primeicons.svg']}#primeicons") format('svg'); + font-weight: normal; + font-style: normal; +} + +.pi { + font-family: 'primeicons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + display: inline-block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.pi:before { + --webkit-backface-visibility:hidden; + backface-visibility: hidden; +} + +.pi-fw { + width: 1.28571429em; + text-align: center; +} + +.pi-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.pi-sort-alt-slash:before { + content: "\e9ee"; +} + +.pi-arrows-h:before { + content: "\e9ec"; +} + +.pi-arrows-v:before { + content: "\e9ed"; +} + +.pi-pound:before { + content: "\e9eb"; +} + +.pi-prime:before { + content: "\e9ea"; +} + +.pi-chart-pie:before { + content: "\e9e9"; +} + +.pi-reddit:before { + content: "\e9e8"; +} + +.pi-code:before { + content: "\e9e7"; +} + +.pi-sync:before { + content: "\e9e6"; +} + +.pi-shopping-bag:before { + content: "\e9e5"; +} + +.pi-server:before { + content: "\e9e4"; +} + +.pi-database:before { + content: "\e9e3"; +} + +.pi-hashtag:before { + content: "\e9e2"; +} + +.pi-bookmark-fill:before { + content: "\e9df"; +} + +.pi-filter-fill:before { + content: "\e9e0"; +} + +.pi-heart-fill:before { + content: "\e9e1"; +} + +.pi-flag-fill:before { + content: "\e9de"; +} + +.pi-circle:before { + content: "\e9dc"; +} + +.pi-circle-fill:before { + content: "\e9dd"; +} + +.pi-bolt:before { + content: "\e9db"; +} + +.pi-history:before { + content: "\e9da"; +} + +.pi-box:before { + content: "\e9d9"; +} + +.pi-at:before { + content: "\e9d8"; +} + +.pi-arrow-up-right:before { + content: "\e9d4"; +} + +.pi-arrow-up-left:before { + content: "\e9d5"; +} + +.pi-arrow-down-left:before { + content: "\e9d6"; +} + +.pi-arrow-down-right:before { + content: "\e9d7"; +} + +.pi-telegram:before { + content: "\e9d3"; +} + +.pi-stop-circle:before { + content: "\e9d2"; +} + +.pi-stop:before { + content: "\e9d1"; +} + +.pi-whatsapp:before { + content: "\e9d0"; +} + +.pi-building:before { + content: "\e9cf"; +} + +.pi-qrcode:before { + content: "\e9ce"; +} + +.pi-car:before { + content: "\e9cd"; +} + +.pi-instagram:before { + content: "\e9cc"; +} + +.pi-linkedin:before { + content: "\e9cb"; +} + +.pi-send:before { + content: "\e9ca"; +} + +.pi-slack:before { + content: "\e9c9"; +} + +.pi-sun:before { + content: "\e9c8"; +} + +.pi-moon:before { + content: "\e9c7"; +} + +.pi-vimeo:before { + content: "\e9c6"; +} + +.pi-youtube:before { + content: "\e9c5"; +} + +.pi-flag:before { + content: "\e9c4"; +} + +.pi-wallet:before { + content: "\e9c3"; +} + +.pi-map:before { + content: "\e9c2"; +} + +.pi-link:before { + content: "\e9c1"; +} + +.pi-credit-card:before { + content: "\e9bf"; +} + +.pi-discord:before { + content: "\e9c0"; +} + +.pi-percentage:before { + content: "\e9be"; +} + +.pi-euro:before { + content: "\e9bd"; +} + +.pi-book:before { + content: "\e9ba"; +} + +.pi-shield:before { + content: "\e9b9"; +} + +.pi-paypal:before { + content: "\e9bb"; +} + +.pi-amazon:before { + content: "\e9bc"; +} + +.pi-phone:before { + content: "\e9b8"; +} + +.pi-filter-slash:before { + content: "\e9b7"; +} + +.pi-facebook:before { + content: "\e9b4"; +} + +.pi-github:before { + content: "\e9b5"; +} + +.pi-twitter:before { + content: "\e9b6"; +} + +.pi-step-backward-alt:before { + content: "\e9ac"; +} + +.pi-step-forward-alt:before { + content: "\e9ad"; +} + +.pi-forward:before { + content: "\e9ae"; +} + +.pi-backward:before { + content: "\e9af"; +} + +.pi-fast-backward:before { + content: "\e9b0"; +} + +.pi-fast-forward:before { + content: "\e9b1"; +} + +.pi-pause:before { + content: "\e9b2"; +} + +.pi-play:before { + content: "\e9b3"; +} + +.pi-compass:before { + content: "\e9ab"; +} + +.pi-id-card:before { + content: "\e9aa"; +} + +.pi-ticket:before { + content: "\e9a9"; +} + +.pi-file-o:before { + content: "\e9a8"; +} + +.pi-reply:before { + content: "\e9a7"; +} + +.pi-directions-alt:before { + content: "\e9a5"; +} + +.pi-directions:before { + content: "\e9a6"; +} + +.pi-thumbs-up:before { + content: "\e9a3"; +} + +.pi-thumbs-down:before { + content: "\e9a4"; +} + +.pi-sort-numeric-down-alt:before { + content: "\e996"; +} + +.pi-sort-numeric-up-alt:before { + content: "\e997"; +} + +.pi-sort-alpha-down-alt:before { + content: "\e998"; +} + +.pi-sort-alpha-up-alt:before { + content: "\e999"; +} + +.pi-sort-numeric-down:before { + content: "\e99a"; +} + +.pi-sort-numeric-up:before { + content: "\e99b"; +} + +.pi-sort-alpha-down:before { + content: "\e99c"; +} + +.pi-sort-alpha-up:before { + content: "\e99d"; +} + +.pi-sort-alt:before { + content: "\e99e"; +} + +.pi-sort-amount-up:before { + content: "\e99f"; +} + +.pi-sort-amount-down:before { + content: "\e9a0"; +} + +.pi-sort-amount-down-alt:before { + content: "\e9a1"; +} + +.pi-sort-amount-up-alt:before { + content: "\e9a2"; +} + +.pi-palette:before { + content: "\e995"; +} + +.pi-undo:before { + content: "\e994"; +} + +.pi-desktop:before { + content: "\e993"; +} + +.pi-sliders-v:before { + content: "\e991"; +} + +.pi-sliders-h:before { + content: "\e992"; +} + +.pi-search-plus:before { + content: "\e98f"; +} + +.pi-search-minus:before { + content: "\e990"; +} + +.pi-file-excel:before { + content: "\e98e"; +} + +.pi-file-pdf:before { + content: "\e98d"; +} + +.pi-check-square:before { + content: "\e98c"; +} + +.pi-chart-line:before { + content: "\e98b"; +} + +.pi-user-edit:before { + content: "\e98a"; +} + +.pi-exclamation-circle:before { + content: "\e989"; +} + +.pi-android:before { + content: "\e985"; +} + +.pi-google:before { + content: "\e986"; +} + +.pi-apple:before { + content: "\e987"; +} + +.pi-microsoft:before { + content: "\e988"; +} + +.pi-heart:before { + content: "\e984"; +} + +.pi-mobile:before { + content: "\e982"; +} + +.pi-tablet:before { + content: "\e983"; +} + +.pi-key:before { + content: "\e981"; +} + +.pi-shopping-cart:before { + content: "\e980"; +} + +.pi-comments:before { + content: "\e97e"; +} + +.pi-comment:before { + content: "\e97f"; +} + +.pi-briefcase:before { + content: "\e97d"; +} + +.pi-bell:before { + content: "\e97c"; +} + +.pi-paperclip:before { + content: "\e97b"; +} + +.pi-share-alt:before { + content: "\e97a"; +} + +.pi-envelope:before { + content: "\e979"; +} + +.pi-volume-down:before { + content: "\e976"; +} + +.pi-volume-up:before { + content: "\e977"; +} + +.pi-volume-off:before { + content: "\e978"; +} + +.pi-eject:before { + content: "\e975"; +} + +.pi-money-bill:before { + content: "\e974"; +} + +.pi-images:before { + content: "\e973"; +} + +.pi-image:before { + content: "\e972"; +} + +.pi-sign-in:before { + content: "\e970"; +} + +.pi-sign-out:before { + content: "\e971"; +} + +.pi-wifi:before { + content: "\e96f"; +} + +.pi-sitemap:before { + content: "\e96e"; +} + +.pi-chart-bar:before { + content: "\e96d"; +} + +.pi-camera:before { + content: "\e96c"; +} + +.pi-dollar:before { + content: "\e96b"; +} + +.pi-lock-open:before { + content: "\e96a"; +} + +.pi-table:before { + content: "\e969"; +} + +.pi-map-marker:before { + content: "\e968"; +} + +.pi-list:before { + content: "\e967"; +} + +.pi-eye-slash:before { + content: "\e965"; +} + +.pi-eye:before { + content: "\e966"; +} + +.pi-folder-open:before { + content: "\e964"; +} + +.pi-folder:before { + content: "\e963"; +} + +.pi-video:before { + content: "\e962"; +} + +.pi-inbox:before { + content: "\e961"; +} + +.pi-lock:before { + content: "\e95f"; +} + +.pi-unlock:before { + content: "\e960"; +} + +.pi-tags:before { + content: "\e95d"; +} + +.pi-tag:before { + content: "\e95e"; +} + +.pi-power-off:before { + content: "\e95c"; +} + +.pi-save:before { + content: "\e95b"; +} + +.pi-question-circle:before { + content: "\e959"; +} + +.pi-question:before { + content: "\e95a"; +} + +.pi-copy:before { + content: "\e957"; +} + +.pi-file:before { + content: "\e958"; +} + +.pi-clone:before { + content: "\e955"; +} + +.pi-calendar-times:before { + content: "\e952"; +} + +.pi-calendar-minus:before { + content: "\e953"; +} + +.pi-calendar-plus:before { + content: "\e954"; +} + +.pi-ellipsis-v:before { + content: "\e950"; +} + +.pi-ellipsis-h:before { + content: "\e951"; +} + +.pi-bookmark:before { + content: "\e94e"; +} + +.pi-globe:before { + content: "\e94f"; +} + +.pi-replay:before { + content: "\e94d"; +} + +.pi-filter:before { + content: "\e94c"; +} + +.pi-print:before { + content: "\e94b"; +} + +.pi-align-right:before { + content: "\e946"; +} + +.pi-align-left:before { + content: "\e947"; +} + +.pi-align-center:before { + content: "\e948"; +} + +.pi-align-justify:before { + content: "\e949"; +} + +.pi-cog:before { + content: "\e94a"; +} + +.pi-cloud-download:before { + content: "\e943"; +} + +.pi-cloud-upload:before { + content: "\e944"; +} + +.pi-cloud:before { + content: "\e945"; +} + +.pi-pencil:before { + content: "\e942"; +} + +.pi-users:before { + content: "\e941"; +} + +.pi-clock:before { + content: "\e940"; +} + +.pi-user-minus:before { + content: "\e93e"; +} + +.pi-user-plus:before { + content: "\e93f"; +} + +.pi-trash:before { + content: "\e93d"; +} + +.pi-external-link:before { + content: "\e93c"; +} + +.pi-window-maximize:before { + content: "\e93b"; +} + +.pi-window-minimize:before { + content: "\e93a"; +} + +.pi-refresh:before { + content: "\e938"; +} + +.pi-user:before { + content: "\e939"; +} + +.pi-exclamation-triangle:before { + content: "\e922"; +} + +.pi-calendar:before { + content: "\e927"; +} + +.pi-chevron-circle-left:before { + content: "\e928"; +} + +.pi-chevron-circle-down:before { + content: "\e929"; +} + +.pi-chevron-circle-right:before { + content: "\e92a"; +} + +.pi-chevron-circle-up:before { + content: "\e92b"; +} + +.pi-angle-double-down:before { + content: "\e92c"; +} + +.pi-angle-double-left:before { + content: "\e92d"; +} + +.pi-angle-double-right:before { + content: "\e92e"; +} + +.pi-angle-double-up:before { + content: "\e92f"; +} + +.pi-angle-down:before { + content: "\e930"; +} + +.pi-angle-left:before { + content: "\e931"; +} + +.pi-angle-right:before { + content: "\e932"; +} + +.pi-angle-up:before { + content: "\e933"; +} + +.pi-upload:before { + content: "\e934"; +} + +.pi-download:before { + content: "\e956"; +} + +.pi-ban:before { + content: "\e935"; +} + +.pi-star-fill:before { + content: "\e936"; +} + +.pi-star:before { + content: "\e937"; +} + +.pi-chevron-left:before { + content: "\e900"; +} + +.pi-chevron-right:before { + content: "\e901"; +} + +.pi-chevron-down:before { + content: "\e902"; +} + +.pi-chevron-up:before { + content: "\e903"; +} + +.pi-caret-left:before { + content: "\e904"; +} + +.pi-caret-right:before { + content: "\e905"; +} + +.pi-caret-down:before { + content: "\e906"; +} + +.pi-caret-up:before { + content: "\e907"; +} + +.pi-search:before { + content: "\e908"; +} + +.pi-check:before { + content: "\e909"; +} + +.pi-check-circle:before { + content: "\e90a"; +} + +.pi-times:before { + content: "\e90b"; +} + +.pi-times-circle:before { + content: "\e90c"; +} + +.pi-plus:before { + content: "\e90d"; +} + +.pi-plus-circle:before { + content: "\e90e"; +} + +.pi-minus:before { + content: "\e90f"; +} + +.pi-minus-circle:before { + content: "\e910"; +} + +.pi-circle-on:before { + content: "\e911"; +} + +.pi-circle-off:before { + content: "\e912"; +} + +.pi-sort-down:before { + content: "\e913"; +} + +.pi-sort-up:before { + content: "\e914"; +} + +.pi-sort:before { + content: "\e915"; +} + +.pi-step-backward:before { + content: "\e916"; +} + +.pi-step-forward:before { + content: "\e917"; +} + +.pi-th-large:before { + content: "\e918"; +} + +.pi-arrow-down:before { + content: "\e919"; +} + +.pi-arrow-left:before { + content: "\e91a"; +} + +.pi-arrow-right:before { + content: "\e91b"; +} + +.pi-arrow-up:before { + content: "\e91c"; +} + +.pi-bars:before { + content: "\e91d"; +} + +.pi-arrow-circle-down:before { + content: "\e91e"; +} + +.pi-arrow-circle-left:before { + content: "\e91f"; +} + +.pi-arrow-circle-right:before { + content: "\e920"; +} + +.pi-arrow-circle-up:before { + content: "\e921"; +} + +.pi-info:before { + content: "\e923"; +} + +.pi-info-circle:before { + content: "\e924"; +} + +.pi-home:before { + content: "\e925"; +} + +.pi-spinner:before { + content: "\e926"; +} diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/icons/primeicons.svg b/src/main/resources/META-INF/resources/resources/freya-layout/icons/primeicons.svg index c4e81e7..5101f7b 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/icons/primeicons.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/icons/primeicons.svg @@ -1,270 +1,270 @@ - - - - - - -{ - "fontFamily": "primeicons", - "majorVersion": 1, - "minorVersion": 0, - "copyright": "PrimeTek Informatics", - "designer": "", - "description": "Icon Library for Prime UI Libraries\nFont generated by IcoMoon.", - "fontURL": "https://github.com/primefaces/primeicons", - "license": "MIT", - "licenseURL": "https://opensource.org/licenses/MIT", - "version": "Version 1.0", - "fontId": "primeicons", - "psName": "primeicons", - "subFamily": "Regular", - "fullName": "primeicons" -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + +{ + "fontFamily": "primeicons", + "majorVersion": 1, + "minorVersion": 0, + "copyright": "PrimeTek Informatics", + "designer": "", + "description": "Icon Library for Prime UI Libraries\nFont generated by IcoMoon.", + "fontURL": "https://github.com/primefaces/primeicons", + "license": "MIT", + "licenseURL": "https://opensource.org/licenses/MIT", + "version": "Version 1.0", + "fontId": "primeicons", + "psName": "primeicons", + "subFamily": "Regular", + "fullName": "primeicons" +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-badge.png b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-badge.png new file mode 100644 index 0000000..2d56452 Binary files /dev/null and b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-badge.png differ diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-single.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-single.svg index 025c4dd..0803b51 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-single.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-single.svg @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-white.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-white.svg index d5be8c1..0270dfd 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-white.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya-white.svg @@ -1,14 +1,14 @@ - - - logo-freya-white - - - - - - - - - - + + + logo-freya-white + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya.svg index 9813483..360b563 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/logo-freya.svg @@ -1,40 +1,40 @@ - - - logo-freya - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + logo-freya + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-404.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-404.svg index 3feeed6..afd488b 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-404.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-404.svg @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-access.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-access.svg index e1dfca1..68fba5b 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-access.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-access.svg @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-error.svg b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-error.svg index 673f0f6..928b1a2 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-error.svg +++ b/src/main/resources/META-INF/resources/resources/freya-layout/images/pages/asset-error.svg @@ -1,9 +1,9 @@ - - - - - - - - - + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/js/layout.js b/src/main/resources/META-INF/resources/resources/freya-layout/js/layout.js index b7c812e..e3e6a90 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/js/layout.js +++ b/src/main/resources/META-INF/resources/resources/freya-layout/js/layout.js @@ -1,879 +1,879 @@ -/** - * PrimeFaces Freya Layout - */ -PrimeFaces.widget.Freya = PrimeFaces.widget.BaseWidget.extend({ - - init: function(cfg) { - this._super(cfg); - this.wrapper = $(document.body).children('.layout-wrapper'); - var $this = this; - - $(function() { - $this._init(); - }); - - this.restoreMenuState(); - this.expandedMenuitems = this.expandedMenuitems||[]; - }, - - _init: function() { - this.contentWrapper = this.wrapper.children('.layout-main'); - this.topbar = this.wrapper.find('.layout-topbar'); - this.topbarItems = this.topbar.find('.layout-topbar-actions > li.topbar-item'); - this.topbarLinks = this.topbarItems.children('a'); - this.topbarSearchItemMenu = this.topbar.find('.search-item'); - - this.menuWrapper = this.wrapper.find('.menu-wrapper'); - this.sidebarPin = this.menuWrapper.find('.sidebar-logo > .sidebar-pin'); - this.menu = this.menuWrapper.find('.layout-menu'); - this.menuButton = this.topbar.find('.menu-button'); - this.menulinks = this.menu.find('a'); - - this.rightpanel = this.wrapper.find('.layout-rightpanel'); - this.rightpanelButton = this.topbar.find('.layout-rightpanel-button'); - this.rightpanelExitButton = this.rightpanel.find('.rightpanel-exit-button'); - - this.configButton = $('#layout-config-button'); - this.configurator = this.wrapper.children('.layout-config'); - - this.bindEvents(); - }, - - toggleClass: function(el, className) { - if (el.hasClass(className)) { - el.removeClass(className); - } - else { - el.addClass(className); - } - }, - - bindEvents: function() { - var $this = this; - - this.bindTopbarEvents(); - this.bindMenuEvents(); - this.bindRightPanelEvents(); - this.bindConfigEvents(); - - $(document.body).off('click.layoutBody').on('click.layoutBody', function() { - if (!$this.menuClick) { - $this.wrapper.removeClass('layout-sidebar-active layout-mobile-active'); - $(document.body).removeClass('blocked-scroll'); - - if ($this.isHorizontal() || $this.isSlim()) { - $this.menu.find('.active-menuitem').removeClass('active-menuitem'); - $this.menu.find('ul:visible').hide(); - $this.menuActive = false; - } - } - - if (!$this.topbarItemClicked) { - $this.removeTopbarClassFromAllItems(null, 'active-topmenuitem', $this.topbarItems.filter('.active-topmenuitem')); - } - - if (!$this.rightpanelClicked) { - $this.wrapper.removeClass('layout-rightpanel-active'); - } - - if (!$this.configClicked && $this.configurator.hasClass('layout-config-active')) { - $this.configurator.removeClass('layout-config-active'); - } - - $this.horizontalMenuClick = false; - $this.topbarItemClicked = false; - $this.rightpanelClicked = false; - $this.menuClick = false; - $this.configClicked = false; - }); - }, - - bindConfigEvents: function() { - var $this = this; - - this.configButton.off('click.configbutton').on('click.configbutton', function(e) { - $this.configurator.toggleClass('layout-config-active'); - $this.configClicked = true; - }); - - this.configurator.off('click.config').on('click.config', function() { - $this.configClicked = true; - }); - }, - - bindMenuEvents: function() { - var $this = this; - - this.menuButton.off('click.menu').on('click.menu', function(e) { - $this.menuClick = true; - - if ($this.isMobile()) { - if ($this.wrapper.hasClass('layout-mobile-active')) { - $this.wrapper.removeClass('layout-mobile-active'); - $(document.body).removeClass('blocked-scroll'); - } - else { - $this.wrapper.addClass('layout-mobile-active'); - $(document.body).addClass('blocked-scroll'); - } - } - - e.preventDefault(); - }); - - this.menuWrapper.off('click.menuWrapper mouseenter.menuWrapper mouseleave.menuWrapper') - .on('click.menuWrapper', function() { - $this.menuClick = true; - }) - .on('mouseenter.menuWrapper', function(e) { - if(!$this.wrapper.hasClass('layout-sidebar-static')) { - if($this.hideTimeout) { - clearTimeout($this.hideTimeout); - } - - $this.menuWrapper.addClass('layout-sidebar-active'); - } - if(!$this.wrapper.hasClass('layout-sidebar')) { - if($this.hideTimeout) { - clearTimeout($this.hideTimeout); - } - - $this.menuWrapper.removeClass('layout-sidebar-active'); - } - }) - .on('mouseleave.menuWrapper', function(e) { - if(!$this.wrapper.hasClass('layout-sidebar-static')) { - $this.hideTimeout = setTimeout(function() { - $this.menuWrapper.removeClass('layout-sidebar-active'); - }, $this.cfg.closeDelay); - } - }); - - this.sidebarPin.off('click.menuWrapper').on('click.menuWrapper', function(e) { - $this.wrapper.removeClass('layout-static-restore'); - $this.wrapper.toggleClass('layout-static'); - $this.saveMenuState(); - e.preventDefault(); - }); - - this.menulinks.off('click.menuWrapper').on('click.menuWrapper', function(e) { - var link = $(this), - item = link.parent(), - submenu = item.children('ul'); - horizontal = $this.isHorizontal(); - slim = $this.isSlim(); - $this.menuClick = true; - - if (horizontal) { - $this.horizontalMenuClick = true; - } - - if(item.hasClass('active-menuitem')) { - if(submenu.length) { - $this.removeMenuitem(item.attr('id')); - item.removeClass('active-menuitem'); - - if(horizontal || slim) { - if(item.parent().is($this.jq)) { - $this.menuActive = false; - } - - submenu.hide(); - $this.removeMenuitem(item.attr('id')); - item.removeClass('active-menuitem'); - } - else { - submenu.slideUp(function() { - $this.removeMenuitem(item.attr('id')); - item.removeClass('active-menuitem'); - }); - } - } - } - else { - $this.addMenuitem(item.attr('id')); - - if(horizontal || slim) { - $this.deactivateItems(item.siblings()); - item.addClass('active-menuitem'); - $this.menuActive = true; - submenu.show(); - } - else { - $this.deactivateItems(item.siblings(), true); - $this.activate(item); - } - } - - if(submenu.length) { - e.preventDefault(); - } - }); - - this.menu.find('> li').off('mouseenter.menu').on('mouseenter.menu', function(e) { - if ($this.isHorizontal() || $this.isSlim()) { - var item = $(this); - - if(!item.hasClass('active-menuitem')) { - $this.menu.find('.active-menuitem').removeClass('active-menuitem'); - $this.menu.find('ul:visible').hide(); - - if($this.menuActive) { - item.addClass('active-menuitem'); - item.children('ul').show(); - } - } - } - }); - }, - - bindTopbarEvents: function() { - var $this = this; - - this.topbarLinks.off('click.topbar').on('click.topbar', function(e) { - var link = $(this), - item = link.parent(), - submenu = item.children('ul'); - - if ($this.isMobile()) { - $this.removeTopbarClassFromAllItems(null, 'active-topmenuitem', $this.topbarItems.filter('.active-topmenuitem').not(item)); - } - else { - $this.removeTopbarClassFromAllItems(item, 'active-topmenuitem'); - } - $this.addTopbarClass(item, 'active-topmenuitem'); - - $this.topbarItemClicked = true; - - if (submenu.length) { - e.preventDefault(); - } - }); - - this.topbarSearchItemMenu.off('click.topbar').on('click.topbar', function(e) { - $this.topbarItemClicked = true; - }); - }, - - bindRightPanelEvents: function() { - var $this = this; - var changeRightpanelState = function(e) { - this.toggleClass(this.wrapper, 'layout-rightpanel-active'); - - this.rightpanelClicked = true; - e.preventDefault(); - }; - - this.rightpanelButton.off('click.rightpanel').on('click.rightpanel', changeRightpanelState.bind(this)); - this.rightpanelExitButton.off('click.rightpanel').on('click.rightpanel', changeRightpanelState.bind(this)); - - this.rightpanel.off('click.rightpanel').on('click.rightpanel', function() { - $this.rightpanelClicked = true; - }); - }, - - activate: function(item) { - var submenu = item.children('ul'); - item.addClass('active-menuitem'); - - if(submenu.length) { - submenu.slideDown(); - } - }, - - deactivate: function(item) { - var submenu = item.children('ul'); - item.removeClass('active-menuitem'); - - if(submenu.length) { - submenu.hide(); - } - }, - - deactivateItems: function(items, animate) { - var $this = this; - - for(var i = 0; i < items.length; i++) { - var item = items.eq(i), - submenu = item.children('ul'); - - if(submenu.length) { - if(item.hasClass('active-menuitem')) { - var activeSubItems = item.find('.active-menuitem'); - item.removeClass('active-menuitem'); - - if(animate) { - submenu.slideUp('normal', function() { - $(this).parent().find('.active-menuitem').each(function() { - $this.deactivate($(this)); - }); - }); - } - else { - item.find('.active-menuitem').each(function() { - $this.deactivate($(this)); - }); - } - - $this.removeMenuitem(item.attr('id')); - activeSubItems.each(function() { - $this.removeMenuitem($(this).attr('id')); - }); - } - else { - item.find('.active-menuitem').each(function() { - var subItem = $(this); - $this.deactivate(subItem); - $this.removeMenuitem(subItem.attr('id')); - }); - } - } - else if(item.hasClass('active-menuitem')) { - $this.deactivate(item); - $this.removeMenuitem(item.attr('id')); - } - } - }, - - removeMenuitem: function (id) { - this.expandedMenuitems = $.grep(this.expandedMenuitems, function (value) { - return value !== id; - }); - this.saveMenuState(); - }, - - addMenuitem: function (id) { - if ($.inArray(id, this.expandedMenuitems) === -1) { - this.expandedMenuitems.push(id); - } - this.saveMenuState(); - }, - - saveMenuState: function() { - if(this.wrapper.hasClass('layout-static')) - $.cookie('freya_menu_static', 'freya_menu_static', {path: '/'}); - else - $.removeCookie('freya_menu_static', {path: '/'}); - - $.cookie('freya_expandeditems', this.expandedMenuitems.join(','), {path: '/'}); - }, - - clearMenuState: function() { - this.expandedMenuitems = []; - $.removeCookie('freya_expandeditems', {path: '/'}); - $.removeCookie('freya_menu_static', {path: '/'}); - }, - - clearActiveItems: function() { - var activeItems = this.jq.find('li.active-menuitem'), - subContainers = activeItems.children('ul'); - - activeItems.removeClass('active-menuitem'); - if(subContainers && subContainers.length) { - subContainers.hide(); - } - }, - - clearLayoutState: function() { - this.clearMenuState(); - this.clearActiveItems(); - }, - - restoreMenuState: function() { - var menuCookie = $.cookie('freya_expandeditems'); - if (!this.isSlim() && !this.isHorizontal() && menuCookie) { - this.expandedMenuitems = menuCookie.split(','); - for (var i = 0; i < this.expandedMenuitems.length; i++) { - var id = this.expandedMenuitems[i]; - if (id) { - var menuitem = $("#" + this.expandedMenuitems[i].replace(/:/g, "\\:")); - menuitem.addClass('active-menuitem'); - - var submenu = menuitem.children('ul'); - if(submenu.length) { - submenu.show(); - } - } - } - } - - var sidebarCookie = $.cookie('freya_menu_static'); - if(sidebarCookie) { - this.wrapper.addClass('layout-static'); - } - - }, - - removeTopbarClassFromAllItems: function(item, className, items) { - var activeItems = item != null ? item.siblings('.' + className) : items; - - activeItems.removeClass(className); - activeItems.children('ul').removeClass('fadeInDown'); - }, - - addTopbarClass: function(item, className) { - var submenu = item.children('ul'); - - if (submenu.length) { - if (item.hasClass(className)) { - submenu.removeClass('fadeInDown').addClass('fadeOutUp'); - - setTimeout(function() { - item.removeClass(className); - submenu.removeClass('fadeOutUp'); - }, 100); - } - else { - item.addClass(className); - submenu.addClass('fadeInDown'); - } - } - }, - - hideTopBar: function() { - var $this = this; - this.topbarMenu.addClass('fadeOutUp'); - - setTimeout(function() { - $this.topbarMenu.removeClass('fadeOutUp topbar-menu-visible'); - },500); - }, - - isMobile: function() { - return window.innerWidth < 992; - }, - isHorizontal: function() { - return this.wrapper.hasClass('layout-horizontal') && !this.isMobile(); - }, - isSlim: function() { - return this.wrapper.hasClass('layout-slim') && !this.isMobile(); - }, - isStatic: function() { - return this.wrapper.hasClass('layout-static') && !this.isMobile(); - } -}); - -PrimeFaces.FreyaConfigurator = { - - changeLayout: function( componentTheme, darkMode ) { - this.changeLayoutsTheme(darkMode); - this.changeDemo(darkMode); - this.changeComponentsTheme(componentTheme, darkMode); - this.changeSectionTheme( darkMode, 'layout-menu'); - this.changeSectionTheme( darkMode , 'layout-topbar'); - }, - - changeLayoutsTheme: function(darkMode) { - newLayout = '-' + darkMode; - var linkElement = $('link[href*="layout-"]'); - var href = linkElement.attr('href'); - var startIndexOf = href.indexOf('layout-') + 6; - var endIndexOf = href.indexOf('.css'); - var currentColor = href.substring(startIndexOf, endIndexOf); - this.replaceLink(linkElement, href.replace(currentColor, newLayout)); - }, - - changeDemo: function(darkMode) { - newLayout = '-' + darkMode; - var linkElement = $('link[href*="demo-"]'); - var href = linkElement.attr('href'); - var startIndexOf = href.indexOf('demo-') + 4; - var endIndexOf = href.indexOf('.css'); - var currentColor = href.substring(startIndexOf, endIndexOf); - - this.replaceLink(linkElement, href.replace(currentColor, newLayout)); - }, - - changeComponentsTheme: function(themeColor, darkMode) { - theme = this.getColor(themeColor, darkMode); - var library = 'primefaces-freya'; - var linkElement = $('link[href*="theme.css"]'); - var href = linkElement.attr('href'); - var index = href.indexOf(library) + 1; - var currentTheme = href.substring(index + library.length); - - this.replaceLink(linkElement, href.replace(currentTheme, theme)); - }, - - changeSectionTheme: function(theme, section) { - var wrapperElement = $('.layout-wrapper'); - - var styleClass = wrapperElement.attr('class'); - var tokens = styleClass.split(' '); - var sectionClass; - for (var i = 0; i < tokens.length; i++) { - if (tokens[i].indexOf(section + '-') > -1) { - sectionClass = tokens[i]; - break; - } - } - - wrapperElement.attr('class', styleClass.replace(sectionClass, section + '-' + theme)); - }, - - changeMenuMode: function(menuMode) { - var wrapper = $(document.body).children('.layout-wrapper'); - switch (menuMode) { - case 'layout-sidebar': - wrapper.addClass('layout-sidebar').removeClass('layout-slim layout-horizontal '); - this.clearLayoutState(); - break; - - case 'layout-horizontal': - wrapper.addClass('layout-horizontal').removeClass('layout-static layout-slim layout-sidebar'); - this.clearLayoutState(); - break; - - case 'layout-slim': - wrapper.addClass('layout-slim').removeClass('layout-static layout-horizontal layout-sidebar'); - this.clearLayoutState(); - break; - - default: - wrapper.addClass('layout-sidebar').removeClass('layout-slim layout-horizontal '); - this.clearLayoutState(); - break; - } - }, - - beforeResourceChange: function() { - PrimeFaces.ajax.RESOURCE = null; //prevent resource append - }, - - replaceLink: function(linkElement, href) { - PrimeFaces.ajax.RESOURCE = 'javax.faces.Resource'; - - var isIE = this.isIE(); - - if (isIE) { - linkElement.attr('href', href); - } - else { - var cloneLinkElement = linkElement.clone(false); - - cloneLinkElement.attr('href', href); - linkElement.after(cloneLinkElement); - - cloneLinkElement.off('load').on('load', function() { - linkElement.remove(); - }); - - // for dashboard - setTimeout(function() { - if (window['redrawChart']) { - window.redrawChart(); - } - }, 100); - } - }, - - getColor: function(name, darkMode) { - return name + '-' + darkMode; - }, - - isIE: function() { - return /(MSIE|Trident\/|Edge\/)/i.test(navigator.userAgent); - }, - - clearLayoutState: function() { - var menu = PF('FreyaMenuWidget'); - - if (menu) { - menu.clearLayoutState(); - } - }, - - updateInputStyle: function(value) { - if (value === 'filled') - $(document.body).addClass('ui-input-filled'); - else - $(document.body).removeClass('ui-input-filled'); - } -}; - -/*! - * jQuery Cookie Plugin v1.4.1 - * https://github.com/carhartl/jquery-cookie - * - * Copyright 2006, 2014 Klaus Hartl - * Released under the MIT license - */ -(function (factory) { - if (typeof define === 'function' && define.amd) { - // AMD (Register as an anonymous module) - define(['jquery'], factory); - } else if (typeof exports === 'object') { - // Node/CommonJS - module.exports = factory(require('jquery')); - } else { - // Browser globals - factory(jQuery); - } -}(function ($) { - - var pluses = /\+/g; - - function encode(s) { - return config.raw ? s : encodeURIComponent(s); - } - - function decode(s) { - return config.raw ? s : decodeURIComponent(s); - } - - function stringifyCookieValue(value) { - return encode(config.json ? JSON.stringify(value) : String(value)); - } - - function parseCookieValue(s) { - if (s.indexOf('"') === 0) { - // This is a quoted cookie as according to RFC2068, unescape... - s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); - } - - try { - // Replace server-side written pluses with spaces. - // If we can't decode the cookie, ignore it, it's unusable. - // If we can't parse the cookie, ignore it, it's unusable. - s = decodeURIComponent(s.replace(pluses, ' ')); - return config.json ? JSON.parse(s) : s; - } catch (e) { } - } - - function read(s, converter) { - var value = config.raw ? s : parseCookieValue(s); - return $.isFunction(converter) ? converter(value) : value; - } - - var config = $.cookie = function (key, value, options) { - - // Write - - if (arguments.length > 1 && !$.isFunction(value)) { - options = $.extend({}, config.defaults, options); - - if (typeof options.expires === 'number') { - var days = options.expires, t = options.expires = new Date(); - t.setMilliseconds(t.getMilliseconds() + days * 864e+5); - } - - return (document.cookie = [ - encode(key), '=', stringifyCookieValue(value), - options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE - options.path ? '; path=' + options.path : '', - options.domain ? '; domain=' + options.domain : '', - options.secure ? '; secure' : '' - ].join('')); - } - - // Read - - var result = key ? undefined : {}, - // To prevent the for loop in the first place assign an empty array - // in case there are no cookies at all. Also prevents odd result when - // calling $.cookie(). - cookies = document.cookie ? document.cookie.split('; ') : [], - i = 0, - l = cookies.length; - - for (; i < l; i++) { - var parts = cookies[i].split('='), - name = decode(parts.shift()), - cookie = parts.join('='); - - if (key === name) { - // If second argument (value) is a function it's a converter... - result = read(cookie, value); - break; - } - - // Prevent storing a cookie that we couldn't decode. - if (!key && (cookie = read(cookie)) !== undefined) { - result[name] = cookie; - } - } - - return result; - }; - - config.defaults = {}; - - $.removeCookie = function (key, options) { - // Must not alter options, thus extending a fresh object... - $.cookie(key, '', $.extend({}, options, { expires: -1 })); - return !$.cookie(key); - }; - -})); - -if (PrimeFaces.widget.InputSwitch) { - PrimeFaces.widget.InputSwitch = PrimeFaces.widget.InputSwitch.extend({ - - init: function (cfg) { - this._super(cfg); - - if (this.input.prop('checked')) { - this.jq.addClass('ui-inputswitch-checked'); - } - }, - - check: function () { - var $this = this; - - this.input.prop('checked', true).trigger('change'); - setTimeout(function () { - $this.jq.addClass('ui-inputswitch-checked'); - }, 100); - }, - - uncheck: function () { - var $this = this; - - this.input.prop('checked', false).trigger('change'); - setTimeout(function () { - $this.jq.removeClass('ui-inputswitch-checked'); - }, 100); - } - }); -} - -if (PrimeFaces.widget.AccordionPanel) { - PrimeFaces.widget.AccordionPanel = PrimeFaces.widget.AccordionPanel.extend({ - - init: function (cfg) { - this._super(cfg); - - this.headers.last().addClass('ui-accordion-header-last'); - } - }); -} - -/* Issue #924 is fixed for 5.3+ and 6.0. (compatibility with 5.3) */ -if(window['PrimeFaces'] && window['PrimeFaces'].widget.Dialog) { - PrimeFaces.widget.Dialog = PrimeFaces.widget.Dialog.extend({ - - enableModality: function() { - this._super(); - $(document.body).children(this.jqId + '_modal').addClass('ui-dialog-mask'); - }, - - syncWindowResize: function() {} - }); -} - -if (PrimeFaces.widget.SelectOneMenu) { - PrimeFaces.widget.SelectOneMenu = PrimeFaces.widget.SelectOneMenu.extend({ - init: function (cfg) { - this._super(cfg); - - var $this = this; - if (this.jq.parent().hasClass('ui-float-label')) { - this.m_panel = $(this.jqId + '_panel'); - this.m_focusInput = $(this.jqId + '_focus'); - - this.m_panel.addClass('ui-input-overlay-panel'); - this.jq.addClass('ui-inputwrapper'); - - if (this.input.val() != '') { - this.jq.addClass('ui-inputwrapper-filled'); - } - - this.input.off('change').on('change', function () { - $this.inputValueControl($(this)); - }); - - this.m_focusInput.on('focus.ui-selectonemenu', function () { - $this.jq.addClass('ui-inputwrapper-focus'); - }) - .on('blur.ui-selectonemenu', function () { - $this.jq.removeClass('ui-inputwrapper-focus'); - }); - - if (this.cfg.editable) { - this.label.on('input', function (e) { - $this.inputValueControl($(this)); - }).on('focus', function () { - $this.jq.addClass('ui-inputwrapper-focus'); - }).on('blur', function () { - $this.jq.removeClass('ui-inputwrapper-focus'); - $this.inputValueControl($(this)); - }); - } - } - }, - - inputValueControl: function (input) { - if (input.val() != '') - this.jq.addClass('ui-inputwrapper-filled'); - else - this.jq.removeClass('ui-inputwrapper-filled'); - } - }); -} - -if (PrimeFaces.widget.Chips) { - PrimeFaces.widget.Chips = PrimeFaces.widget.Chips.extend({ - init: function (cfg) { - this._super(cfg); - - var $this = this; - if (this.jq.parent().hasClass('ui-float-label')) { - this.jq.addClass('ui-inputwrapper'); - - if ($this.jq.find('.ui-chips-token').length !== 0) { - this.jq.addClass('ui-inputwrapper-filled'); - } - - this.input.on('focus.ui-chips', function () { - $this.jq.addClass('ui-inputwrapper-focus'); - }).on('input.ui-chips', function () { - $this.inputValueControl(); - }).on('blur.ui-chips', function () { - $this.jq.removeClass('ui-inputwrapper-focus'); - $this.inputValueControl(); - }); - - } - }, - - inputValueControl: function () { - if (this.jq.find('.ui-chips-token').length !== 0 || this.input.val() != '') - this.jq.addClass('ui-inputwrapper-filled'); - else - this.jq.removeClass('ui-inputwrapper-filled'); - } - }); -} - -if (PrimeFaces.widget.DatePicker) { - PrimeFaces.widget.DatePicker = PrimeFaces.widget.DatePicker.extend({ - init: function (cfg) { - this._super(cfg); - - var $this = this; - if (this.jq.parent().hasClass('ui-float-label') && !this.cfg.inline) { - if (this.input.val() != '') { - this.jq.addClass('ui-inputwrapper-filled'); - } - - this.jqEl.off('focus.ui-datepicker blur.ui-datepicker change.ui-datepicker') - .on('focus.ui-datepicker', function () { - $this.jq.addClass('ui-inputwrapper-focus'); - }) - .on('blur.ui-datepicker', function () { - $this.jq.removeClass('ui-inputwrapper-focus'); - }) - .on('change.ui-datepicker', function () { - $this.inputValueControl($(this)); - }); - } - }, - - inputValueControl: function (input) { - if (input.val() != '') - this.jq.addClass('ui-inputwrapper-filled'); - else - this.jq.removeClass('ui-inputwrapper-filled'); - } - }); +/** + * PrimeFaces Freya Layout + */ +PrimeFaces.widget.Freya = PrimeFaces.widget.BaseWidget.extend({ + + init: function(cfg) { + this._super(cfg); + this.wrapper = $(document.body).children('.layout-wrapper'); + var $this = this; + + $(function() { + $this._init(); + }); + + this.restoreMenuState(); + this.expandedMenuitems = this.expandedMenuitems||[]; + }, + + _init: function() { + this.contentWrapper = this.wrapper.children('.layout-main'); + this.topbar = this.wrapper.find('.layout-topbar'); + this.topbarItems = this.topbar.find('.layout-topbar-actions > li.topbar-item'); + this.topbarLinks = this.topbarItems.children('a'); + this.topbarSearchItemMenu = this.topbar.find('.search-item'); + + this.menuWrapper = this.wrapper.find('.menu-wrapper'); + this.sidebarPin = this.menuWrapper.find('.sidebar-logo > .sidebar-pin'); + this.menu = this.menuWrapper.find('.layout-menu'); + this.menuButton = this.topbar.find('.menu-button'); + this.menulinks = this.menu.find('a'); + + this.rightpanel = this.wrapper.find('.layout-rightpanel'); + this.rightpanelButton = this.topbar.find('.layout-rightpanel-button'); + this.rightpanelExitButton = this.rightpanel.find('.rightpanel-exit-button'); + + this.configButton = $('#layout-config-button'); + this.configurator = this.wrapper.children('.layout-config'); + + this.bindEvents(); + }, + + toggleClass: function(el, className) { + if (el.hasClass(className)) { + el.removeClass(className); + } + else { + el.addClass(className); + } + }, + + bindEvents: function() { + var $this = this; + + this.bindTopbarEvents(); + this.bindMenuEvents(); + this.bindRightPanelEvents(); + this.bindConfigEvents(); + + $(document.body).off('click.layoutBody').on('click.layoutBody', function() { + if (!$this.menuClick) { + $this.wrapper.removeClass('layout-sidebar-active layout-mobile-active'); + $(document.body).removeClass('blocked-scroll'); + + if ($this.isHorizontal() || $this.isSlim()) { + $this.menu.find('.active-menuitem').removeClass('active-menuitem'); + $this.menu.find('ul:visible').hide(); + $this.menuActive = false; + } + } + + if (!$this.topbarItemClicked) { + $this.removeTopbarClassFromAllItems(null, 'active-topmenuitem', $this.topbarItems.filter('.active-topmenuitem')); + } + + if (!$this.rightpanelClicked) { + $this.wrapper.removeClass('layout-rightpanel-active'); + } + + if (!$this.configClicked && $this.configurator.hasClass('layout-config-active')) { + $this.configurator.removeClass('layout-config-active'); + } + + $this.horizontalMenuClick = false; + $this.topbarItemClicked = false; + $this.rightpanelClicked = false; + $this.menuClick = false; + $this.configClicked = false; + }); + }, + + bindConfigEvents: function() { + var $this = this; + + this.configButton.off('click.configbutton').on('click.configbutton', function(e) { + $this.configurator.toggleClass('layout-config-active'); + $this.configClicked = true; + }); + + this.configurator.off('click.config').on('click.config', function() { + $this.configClicked = true; + }); + }, + + bindMenuEvents: function() { + var $this = this; + + this.menuButton.off('click.menu').on('click.menu', function(e) { + $this.menuClick = true; + + if ($this.isMobile()) { + if ($this.wrapper.hasClass('layout-mobile-active')) { + $this.wrapper.removeClass('layout-mobile-active'); + $(document.body).removeClass('blocked-scroll'); + } + else { + $this.wrapper.addClass('layout-mobile-active'); + $(document.body).addClass('blocked-scroll'); + } + } + + e.preventDefault(); + }); + + this.menuWrapper.off('click.menuWrapper mouseenter.menuWrapper mouseleave.menuWrapper') + .on('click.menuWrapper', function() { + $this.menuClick = true; + }) + .on('mouseenter.menuWrapper', function(e) { + if(!$this.wrapper.hasClass('layout-sidebar-static')) { + if($this.hideTimeout) { + clearTimeout($this.hideTimeout); + } + + $this.menuWrapper.addClass('layout-sidebar-active'); + } + if(!$this.wrapper.hasClass('layout-sidebar')) { + if($this.hideTimeout) { + clearTimeout($this.hideTimeout); + } + + $this.menuWrapper.removeClass('layout-sidebar-active'); + } + }) + .on('mouseleave.menuWrapper', function(e) { + if(!$this.wrapper.hasClass('layout-sidebar-static')) { + $this.hideTimeout = setTimeout(function() { + $this.menuWrapper.removeClass('layout-sidebar-active'); + }, $this.cfg.closeDelay); + } + }); + + this.sidebarPin.off('click.menuWrapper').on('click.menuWrapper', function(e) { + $this.wrapper.removeClass('layout-static-restore'); + $this.wrapper.toggleClass('layout-static'); + $this.saveMenuState(); + e.preventDefault(); + }); + + this.menulinks.off('click.menuWrapper').on('click.menuWrapper', function(e) { + var link = $(this), + item = link.parent(), + submenu = item.children('ul'); + horizontal = $this.isHorizontal(); + slim = $this.isSlim(); + $this.menuClick = true; + + if (horizontal) { + $this.horizontalMenuClick = true; + } + + if(item.hasClass('active-menuitem')) { + if(submenu.length) { + $this.removeMenuitem(item.attr('id')); + item.removeClass('active-menuitem'); + + if(horizontal || slim) { + if(item.parent().is($this.jq)) { + $this.menuActive = false; + } + + submenu.hide(); + $this.removeMenuitem(item.attr('id')); + item.removeClass('active-menuitem'); + } + else { + submenu.slideUp(function() { + $this.removeMenuitem(item.attr('id')); + item.removeClass('active-menuitem'); + }); + } + } + } + else { + $this.addMenuitem(item.attr('id')); + + if(horizontal || slim) { + $this.deactivateItems(item.siblings()); + item.addClass('active-menuitem'); + $this.menuActive = true; + submenu.show(); + } + else { + $this.deactivateItems(item.siblings(), true); + $this.activate(item); + } + } + + if(submenu.length) { + e.preventDefault(); + } + }); + + this.menu.find('> li').off('mouseenter.menu').on('mouseenter.menu', function(e) { + if ($this.isHorizontal() || $this.isSlim()) { + var item = $(this); + + if(!item.hasClass('active-menuitem')) { + $this.menu.find('.active-menuitem').removeClass('active-menuitem'); + $this.menu.find('ul:visible').hide(); + + if($this.menuActive) { + item.addClass('active-menuitem'); + item.children('ul').show(); + } + } + } + }); + }, + + bindTopbarEvents: function() { + var $this = this; + + this.topbarLinks.off('click.topbar').on('click.topbar', function(e) { + var link = $(this), + item = link.parent(), + submenu = item.children('ul'); + + if ($this.isMobile()) { + $this.removeTopbarClassFromAllItems(null, 'active-topmenuitem', $this.topbarItems.filter('.active-topmenuitem').not(item)); + } + else { + $this.removeTopbarClassFromAllItems(item, 'active-topmenuitem'); + } + $this.addTopbarClass(item, 'active-topmenuitem'); + + $this.topbarItemClicked = true; + + if (submenu.length) { + e.preventDefault(); + } + }); + + this.topbarSearchItemMenu.off('click.topbar').on('click.topbar', function(e) { + $this.topbarItemClicked = true; + }); + }, + + bindRightPanelEvents: function() { + var $this = this; + var changeRightpanelState = function(e) { + this.toggleClass(this.wrapper, 'layout-rightpanel-active'); + + this.rightpanelClicked = true; + e.preventDefault(); + }; + + this.rightpanelButton.off('click.rightpanel').on('click.rightpanel', changeRightpanelState.bind(this)); + this.rightpanelExitButton.off('click.rightpanel').on('click.rightpanel', changeRightpanelState.bind(this)); + + this.rightpanel.off('click.rightpanel').on('click.rightpanel', function() { + $this.rightpanelClicked = true; + }); + }, + + activate: function(item) { + var submenu = item.children('ul'); + item.addClass('active-menuitem'); + + if(submenu.length) { + submenu.slideDown(); + } + }, + + deactivate: function(item) { + var submenu = item.children('ul'); + item.removeClass('active-menuitem'); + + if(submenu.length) { + submenu.hide(); + } + }, + + deactivateItems: function(items, animate) { + var $this = this; + + for(var i = 0; i < items.length; i++) { + var item = items.eq(i), + submenu = item.children('ul'); + + if(submenu.length) { + if(item.hasClass('active-menuitem')) { + var activeSubItems = item.find('.active-menuitem'); + item.removeClass('active-menuitem'); + + if(animate) { + submenu.slideUp('normal', function() { + $(this).parent().find('.active-menuitem').each(function() { + $this.deactivate($(this)); + }); + }); + } + else { + item.find('.active-menuitem').each(function() { + $this.deactivate($(this)); + }); + } + + $this.removeMenuitem(item.attr('id')); + activeSubItems.each(function() { + $this.removeMenuitem($(this).attr('id')); + }); + } + else { + item.find('.active-menuitem').each(function() { + var subItem = $(this); + $this.deactivate(subItem); + $this.removeMenuitem(subItem.attr('id')); + }); + } + } + else if(item.hasClass('active-menuitem')) { + $this.deactivate(item); + $this.removeMenuitem(item.attr('id')); + } + } + }, + + removeMenuitem: function (id) { + this.expandedMenuitems = $.grep(this.expandedMenuitems, function (value) { + return value !== id; + }); + this.saveMenuState(); + }, + + addMenuitem: function (id) { + if ($.inArray(id, this.expandedMenuitems) === -1) { + this.expandedMenuitems.push(id); + } + this.saveMenuState(); + }, + + saveMenuState: function() { + if(this.wrapper.hasClass('layout-static')) + $.cookie('freya_menu_static', 'freya_menu_static', {path: '/'}); + else + $.removeCookie('freya_menu_static', {path: '/'}); + + $.cookie('freya_expandeditems', this.expandedMenuitems.join(','), {path: '/'}); + }, + + clearMenuState: function() { + this.expandedMenuitems = []; + $.removeCookie('freya_expandeditems', {path: '/'}); + $.removeCookie('freya_menu_static', {path: '/'}); + }, + + clearActiveItems: function() { + var activeItems = this.jq.find('li.active-menuitem'), + subContainers = activeItems.children('ul'); + + activeItems.removeClass('active-menuitem'); + if(subContainers && subContainers.length) { + subContainers.hide(); + } + }, + + clearLayoutState: function() { + this.clearMenuState(); + this.clearActiveItems(); + }, + + restoreMenuState: function() { + var menuCookie = $.cookie('freya_expandeditems'); + if (!this.isSlim() && !this.isHorizontal() && menuCookie) { + this.expandedMenuitems = menuCookie.split(','); + for (var i = 0; i < this.expandedMenuitems.length; i++) { + var id = this.expandedMenuitems[i]; + if (id) { + var menuitem = $("#" + this.expandedMenuitems[i].replace(/:/g, "\\:")); + menuitem.addClass('active-menuitem'); + + var submenu = menuitem.children('ul'); + if(submenu.length) { + submenu.show(); + } + } + } + } + + var sidebarCookie = $.cookie('freya_menu_static'); + if(sidebarCookie) { + this.wrapper.addClass('layout-static'); + } + + }, + + removeTopbarClassFromAllItems: function(item, className, items) { + var activeItems = item != null ? item.siblings('.' + className) : items; + + activeItems.removeClass(className); + activeItems.children('ul').removeClass('fadeInDown'); + }, + + addTopbarClass: function(item, className) { + var submenu = item.children('ul'); + + if (submenu.length) { + if (item.hasClass(className)) { + submenu.removeClass('fadeInDown').addClass('fadeOutUp'); + + setTimeout(function() { + item.removeClass(className); + submenu.removeClass('fadeOutUp'); + }, 100); + } + else { + item.addClass(className); + submenu.addClass('fadeInDown'); + } + } + }, + + hideTopBar: function() { + var $this = this; + this.topbarMenu.addClass('fadeOutUp'); + + setTimeout(function() { + $this.topbarMenu.removeClass('fadeOutUp topbar-menu-visible'); + },500); + }, + + isMobile: function() { + return window.innerWidth < 992; + }, + isHorizontal: function() { + return this.wrapper.hasClass('layout-horizontal') && !this.isMobile(); + }, + isSlim: function() { + return this.wrapper.hasClass('layout-slim') && !this.isMobile(); + }, + isStatic: function() { + return this.wrapper.hasClass('layout-static') && !this.isMobile(); + } +}); + +PrimeFaces.FreyaConfigurator = { + + changeLayout: function( componentTheme, darkMode ) { + this.changeLayoutsTheme(darkMode); + this.changeDemo(darkMode); + this.changeComponentsTheme(componentTheme, darkMode); + this.changeSectionTheme( darkMode, 'layout-menu'); + this.changeSectionTheme( darkMode , 'layout-topbar'); + }, + + changeLayoutsTheme: function(darkMode) { + newLayout = '-' + darkMode; + var linkElement = $('link[href*="layout-"]'); + var href = linkElement.attr('href'); + var startIndexOf = href.indexOf('layout-') + 6; + var endIndexOf = href.indexOf('.css'); + var currentColor = href.substring(startIndexOf, endIndexOf); + this.replaceLink(linkElement, href.replace(currentColor, newLayout)); + }, + + changeDemo: function(darkMode) { + newLayout = '-' + darkMode; + var linkElement = $('link[href*="demo-"]'); + var href = linkElement.attr('href'); + var startIndexOf = href.indexOf('demo-') + 4; + var endIndexOf = href.indexOf('.css'); + var currentColor = href.substring(startIndexOf, endIndexOf); + + this.replaceLink(linkElement, href.replace(currentColor, newLayout)); + }, + + changeComponentsTheme: function(themeColor, darkMode) { + theme = this.getColor(themeColor, darkMode); + var library = 'primefaces-freya'; + var linkElement = $('link[href*="theme.css"]'); + var href = linkElement.attr('href'); + var index = href.indexOf(library) + 1; + var currentTheme = href.substring(index + library.length); + + this.replaceLink(linkElement, href.replace(currentTheme, theme)); + }, + + changeSectionTheme: function(theme, section) { + var wrapperElement = $('.layout-wrapper'); + + var styleClass = wrapperElement.attr('class'); + var tokens = styleClass.split(' '); + var sectionClass; + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].indexOf(section + '-') > -1) { + sectionClass = tokens[i]; + break; + } + } + + wrapperElement.attr('class', styleClass.replace(sectionClass, section + '-' + theme)); + }, + + changeMenuMode: function(menuMode) { + var wrapper = $(document.body).children('.layout-wrapper'); + switch (menuMode) { + case 'layout-sidebar': + wrapper.addClass('layout-sidebar').removeClass('layout-slim layout-horizontal '); + this.clearLayoutState(); + break; + + case 'layout-horizontal': + wrapper.addClass('layout-horizontal').removeClass('layout-static layout-slim layout-sidebar'); + this.clearLayoutState(); + break; + + case 'layout-slim': + wrapper.addClass('layout-slim').removeClass('layout-static layout-horizontal layout-sidebar'); + this.clearLayoutState(); + break; + + default: + wrapper.addClass('layout-sidebar').removeClass('layout-slim layout-horizontal '); + this.clearLayoutState(); + break; + } + }, + + beforeResourceChange: function() { + PrimeFaces.ajax.RESOURCE = null; //prevent resource append + }, + + replaceLink: function(linkElement, href) { + PrimeFaces.ajax.RESOURCE = 'javax.faces.Resource'; + + var isIE = this.isIE(); + + if (isIE) { + linkElement.attr('href', href); + } + else { + var cloneLinkElement = linkElement.clone(false); + + cloneLinkElement.attr('href', href); + linkElement.after(cloneLinkElement); + + cloneLinkElement.off('load').on('load', function() { + linkElement.remove(); + }); + + // for dashboard + setTimeout(function() { + if (window['redrawChart']) { + window.redrawChart(); + } + }, 100); + } + }, + + getColor: function(name, darkMode) { + return name + '-' + darkMode; + }, + + isIE: function() { + return /(MSIE|Trident\/|Edge\/)/i.test(navigator.userAgent); + }, + + clearLayoutState: function() { + var menu = PF('FreyaMenuWidget'); + + if (menu) { + menu.clearLayoutState(); + } + }, + + updateInputStyle: function(value) { + if (value === 'filled') + $(document.body).addClass('ui-input-filled'); + else + $(document.body).removeClass('ui-input-filled'); + } +}; + +/*! + * jQuery Cookie Plugin v1.4.1 + * https://github.com/carhartl/jquery-cookie + * + * Copyright 2006, 2014 Klaus Hartl + * Released under the MIT license + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD (Register as an anonymous module) + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + module.exports = factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + var pluses = /\+/g; + + function encode(s) { + return config.raw ? s : encodeURIComponent(s); + } + + function decode(s) { + return config.raw ? s : decodeURIComponent(s); + } + + function stringifyCookieValue(value) { + return encode(config.json ? JSON.stringify(value) : String(value)); + } + + function parseCookieValue(s) { + if (s.indexOf('"') === 0) { + // This is a quoted cookie as according to RFC2068, unescape... + s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); + } + + try { + // Replace server-side written pluses with spaces. + // If we can't decode the cookie, ignore it, it's unusable. + // If we can't parse the cookie, ignore it, it's unusable. + s = decodeURIComponent(s.replace(pluses, ' ')); + return config.json ? JSON.parse(s) : s; + } catch (e) { } + } + + function read(s, converter) { + var value = config.raw ? s : parseCookieValue(s); + return $.isFunction(converter) ? converter(value) : value; + } + + var config = $.cookie = function (key, value, options) { + + // Write + + if (arguments.length > 1 && !$.isFunction(value)) { + options = $.extend({}, config.defaults, options); + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setMilliseconds(t.getMilliseconds() + days * 864e+5); + } + + return (document.cookie = [ + encode(key), '=', stringifyCookieValue(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // Read + + var result = key ? undefined : {}, + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling $.cookie(). + cookies = document.cookie ? document.cookie.split('; ') : [], + i = 0, + l = cookies.length; + + for (; i < l; i++) { + var parts = cookies[i].split('='), + name = decode(parts.shift()), + cookie = parts.join('='); + + if (key === name) { + // If second argument (value) is a function it's a converter... + result = read(cookie, value); + break; + } + + // Prevent storing a cookie that we couldn't decode. + if (!key && (cookie = read(cookie)) !== undefined) { + result[name] = cookie; + } + } + + return result; + }; + + config.defaults = {}; + + $.removeCookie = function (key, options) { + // Must not alter options, thus extending a fresh object... + $.cookie(key, '', $.extend({}, options, { expires: -1 })); + return !$.cookie(key); + }; + +})); + +if (PrimeFaces.widget.InputSwitch) { + PrimeFaces.widget.InputSwitch = PrimeFaces.widget.InputSwitch.extend({ + + init: function (cfg) { + this._super(cfg); + + if (this.input.prop('checked')) { + this.jq.addClass('ui-inputswitch-checked'); + } + }, + + check: function () { + var $this = this; + + this.input.prop('checked', true).trigger('change'); + setTimeout(function () { + $this.jq.addClass('ui-inputswitch-checked'); + }, 100); + }, + + uncheck: function () { + var $this = this; + + this.input.prop('checked', false).trigger('change'); + setTimeout(function () { + $this.jq.removeClass('ui-inputswitch-checked'); + }, 100); + } + }); +} + +if (PrimeFaces.widget.AccordionPanel) { + PrimeFaces.widget.AccordionPanel = PrimeFaces.widget.AccordionPanel.extend({ + + init: function (cfg) { + this._super(cfg); + + this.headers.last().addClass('ui-accordion-header-last'); + } + }); +} + +/* Issue #924 is fixed for 5.3+ and 6.0. (compatibility with 5.3) */ +if(window['PrimeFaces'] && window['PrimeFaces'].widget.Dialog) { + PrimeFaces.widget.Dialog = PrimeFaces.widget.Dialog.extend({ + + enableModality: function() { + this._super(); + $(document.body).children(this.jqId + '_modal').addClass('ui-dialog-mask'); + }, + + syncWindowResize: function() {} + }); +} + +if (PrimeFaces.widget.SelectOneMenu) { + PrimeFaces.widget.SelectOneMenu = PrimeFaces.widget.SelectOneMenu.extend({ + init: function (cfg) { + this._super(cfg); + + var $this = this; + if (this.jq.parent().hasClass('ui-float-label')) { + this.m_panel = $(this.jqId + '_panel'); + this.m_focusInput = $(this.jqId + '_focus'); + + this.m_panel.addClass('ui-input-overlay-panel'); + this.jq.addClass('ui-inputwrapper'); + + if (this.input.val() != '') { + this.jq.addClass('ui-inputwrapper-filled'); + } + + this.input.off('change').on('change', function () { + $this.inputValueControl($(this)); + }); + + this.m_focusInput.on('focus.ui-selectonemenu', function () { + $this.jq.addClass('ui-inputwrapper-focus'); + }) + .on('blur.ui-selectonemenu', function () { + $this.jq.removeClass('ui-inputwrapper-focus'); + }); + + if (this.cfg.editable) { + this.label.on('input', function (e) { + $this.inputValueControl($(this)); + }).on('focus', function () { + $this.jq.addClass('ui-inputwrapper-focus'); + }).on('blur', function () { + $this.jq.removeClass('ui-inputwrapper-focus'); + $this.inputValueControl($(this)); + }); + } + } + }, + + inputValueControl: function (input) { + if (input.val() != '') + this.jq.addClass('ui-inputwrapper-filled'); + else + this.jq.removeClass('ui-inputwrapper-filled'); + } + }); +} + +if (PrimeFaces.widget.Chips) { + PrimeFaces.widget.Chips = PrimeFaces.widget.Chips.extend({ + init: function (cfg) { + this._super(cfg); + + var $this = this; + if (this.jq.parent().hasClass('ui-float-label')) { + this.jq.addClass('ui-inputwrapper'); + + if ($this.jq.find('.ui-chips-token').length !== 0) { + this.jq.addClass('ui-inputwrapper-filled'); + } + + this.input.on('focus.ui-chips', function () { + $this.jq.addClass('ui-inputwrapper-focus'); + }).on('input.ui-chips', function () { + $this.inputValueControl(); + }).on('blur.ui-chips', function () { + $this.jq.removeClass('ui-inputwrapper-focus'); + $this.inputValueControl(); + }); + + } + }, + + inputValueControl: function () { + if (this.jq.find('.ui-chips-token').length !== 0 || this.input.val() != '') + this.jq.addClass('ui-inputwrapper-filled'); + else + this.jq.removeClass('ui-inputwrapper-filled'); + } + }); +} + +if (PrimeFaces.widget.DatePicker) { + PrimeFaces.widget.DatePicker = PrimeFaces.widget.DatePicker.extend({ + init: function (cfg) { + this._super(cfg); + + var $this = this; + if (this.jq.parent().hasClass('ui-float-label') && !this.cfg.inline) { + if (this.input.val() != '') { + this.jq.addClass('ui-inputwrapper-filled'); + } + + this.jqEl.off('focus.ui-datepicker blur.ui-datepicker change.ui-datepicker') + .on('focus.ui-datepicker', function () { + $this.jq.addClass('ui-inputwrapper-focus'); + }) + .on('blur.ui-datepicker', function () { + $this.jq.removeClass('ui-inputwrapper-focus'); + }) + .on('change.ui-datepicker', function () { + $this.inputValueControl($(this)); + }); + } + }, + + inputValueControl: function (input) { + if (input.val() != '') + this.jq.addClass('ui-inputwrapper-filled'); + else + this.jq.removeClass('ui-inputwrapper-filled'); + } + }); } \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/resources/freya-layout/js/prism.js b/src/main/resources/META-INF/resources/resources/freya-layout/js/prism.js index 4cbeb12..c1abade 100644 --- a/src/main/resources/META-INF/resources/resources/freya-layout/js/prism.js +++ b/src/main/resources/META-INF/resources/resources/freya-layout/js/prism.js @@ -1,10 +1,10 @@ -/* PrismJS 1.22.0 -https://prismjs.com/download.html#themes=prism-coy&languages=markup+css+clike+javascript+bash+java&plugins=line-numbers */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,_={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof M?new M(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);y+=m.value.length,m=m.next){var k=m.value;if(t.length>n.length)return;if(!(k instanceof M)){var b,x=1;if(h){if(!(b=W(p,y,n,f)))break;var w=b.index,A=b.index+b[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof M)continue;for(var S=m;S!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=z(t,j,O),y+=O.length),I(t,j,x);var C=new M(o,g?_.tokenize(E,g):E,d,E);m=z(t,j,C),L&&z(t,m,L),1"+a.content+""},!u.document)return u.addEventListener&&(_.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(_.highlight(r,_.languages[t],t)),a&&u.close()},!1)),_;var e=_.util.currentScript();function t(){_.manual||_.highlightAll()}if(e&&(_.filename=e.src,e.hasAttribute("data-manual")&&(_.manual=!0)),!_.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return _}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; -!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,lookbehind:!0,inside:{"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{style:{pattern:/(["'])[\s\S]+(?=["']$)/,lookbehind:!0,alias:"language-css",inside:s.languages.css},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},"attr-name":/^style/i}}},t.tag))}(Prism); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-flags":/[a-z]+$/,"regex-delimiter":/^\/|\/$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; -!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|(?!\2)[^\\`$])*\2/,lookbehind:!0,greedy:!0,inside:a}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],i=a.variable[1].inside,o=0;o>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); -!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows");if(t){var i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=t(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1=l.reach);y+=m.value.length,m=m.next){var k=m.value;if(t.length>n.length)return;if(!(k instanceof M)){var b,x=1;if(h){if(!(b=W(p,y,n,f)))break;var w=b.index,A=b.index+b[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof M)continue;for(var S=m;S!==t.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=z(t,j,O),y+=O.length),I(t,j,x);var C=new M(o,g?_.tokenize(E,g):E,d,E);m=z(t,j,C),L&&z(t,m,L),1"+a.content+""},!u.document)return u.addEventListener&&(_.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(_.highlight(r,_.languages[t],t)),a&&u.close()},!1)),_;var e=_.util.currentScript();function t(){_.manual||_.highlightAll()}if(e&&(_.filename=e.src,e.hasAttribute("data-manual")&&(_.manual=!0)),!_.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return _}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,lookbehind:!0,inside:{"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{style:{pattern:/(["'])[\s\S]+(?=["']$)/,lookbehind:!0,alias:"language-css",inside:s.languages.css},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},"attr-name":/^style/i}}},t.tag))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-flags":/[a-z]+$/,"regex-delimiter":/^\/|\/$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|(?!\2)[^\\`$])*\2/,lookbehind:!0,greedy:!0,inside:a}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],i=a.variable[1].inside,o=0;o>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +!function(){if("undefined"!=typeof self&&self.Prism&&self.document){var o="line-numbers",a=/\n(?!$)/g,e=Prism.plugins.lineNumbers={getLine:function(e,n){if("PRE"===e.tagName&&e.classList.contains(o)){var t=e.querySelector(".line-numbers-rows");if(t){var i=parseInt(e.getAttribute("data-start"),10)||1,r=i+(t.children.length-1);n");(i=document.createElement("span")).setAttribute("aria-hidden","true"),i.className="line-numbers-rows",i.innerHTML=l,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(i),u([t]),Prism.hooks.run("line-numbers",e)}}}),Prism.hooks.add("line-numbers",function(e){e.plugins=e.plugins||{},e.plugins.lineNumbers=!0})}function u(e){if(0!=(e=e.filter(function(e){var n=t(e)["white-space"];return"pre-wrap"===n||"pre-line"===n})).length){var n=e.map(function(e){var n=e.querySelector("code"),t=e.querySelector(".line-numbers-rows");if(n&&t){var i=e.querySelector(".line-numbers-sizer"),r=n.textContent.split(a);i||((i=document.createElement("span")).className="line-numbers-sizer",n.appendChild(i)),i.innerHTML="0",i.style.display="block";var s=i.getBoundingClientRect().height;return i.innerHTML="",{element:e,lines:r,lineHeights:[],oneLinerHeight:s,sizer:i}}}).filter(Boolean);n.forEach(function(e){var i=e.sizer,n=e.lines,r=e.lineHeights,s=e.oneLinerHeight;r[n.length-1]=void 0,n.forEach(function(e,n){if(e&&1 - - - - - - - - - - <ui:insert name="title">Lions User Manager</ui:insert> - - - - - - -
-
- - 🦁 Lions User Manager - - - - - - - - - - -
- -
- -
- - -
- - - - - - - - - -
- - + + + + + + + + + + + <ui:insert name="title">Lions User Manager</ui:insert> + + + + + + +
+
+ + 🦁 Lions User Manager + + + + + + + + + + +
+ +
+ +
+ + +
+ + + + + + + + + +
+ + diff --git a/src/main/resources/META-INF/resources/templates/components/README.md b/src/main/resources/META-INF/resources/templates/components/README.md index fdc5170..6d59488 100644 --- a/src/main/resources/META-INF/resources/templates/components/README.md +++ b/src/main/resources/META-INF/resources/templates/components/README.md @@ -1,399 +1,399 @@ -# 📦 Composants Réutilisables - Lions User Manager - -**Version**: 1.0.0 -**Date**: 2025-01-29 -**Pattern**: WOU/DRY (Write Once Use / Don't Repeat Yourself) - ---- - -## 🎯 Vue d'Ensemble - -Ce répertoire contient tous les composants UI réutilisables pour le module **lions-user-manager**. Ces composants suivent les patterns établis dans **unionflow** et peuvent être utilisés dans n'importe quel projet de l'écosystème **lionsdev**. - ---- - -## 📂 Structure des Composants - -``` -templates/components/ -├── user-management/ # Composants spécifiques utilisateurs -│ ├── user-card.xhtml -│ ├── user-form.xhtml -│ ├── user-search-bar.xhtml -│ ├── user-actions.xhtml -│ └── user-role-badge.xhtml -├── role-management/ # Composants spécifiques rôles -│ ├── role-card.xhtml -│ ├── role-form.xhtml -│ └── role-assignment.xhtml -├── audit/ # Composants audit -│ ├── audit-log-row.xhtml -│ └── audit-stats-card.xhtml -└── shared/ # Composants génériques réutilisables - ├── buttons/ - │ └── button-user-action.xhtml - ├── cards/ - │ └── user-stat-card.xhtml - ├── forms/ - │ └── user-form-field.xhtml - └── tables/ - └── user-data-table.xhtml -``` - ---- - -## 📋 Liste Complète des Composants - -### 👤 User Management (5 composants) - -#### 1. `user-card.xhtml` -**Description**: Carte utilisateur avec informations principales et actions - -**Paramètres principaux**: -- `user`: UserDTO (requis) -- `showActions`: Boolean (défaut: true) -- `showRoles`: Boolean (défaut: true) -- `clickable`: Boolean (défaut: true) -- `outcome`: String (optionnel) - -**Exemple**: -```xhtml - - - - -``` - -#### 2. `user-form.xhtml` -**Description**: Formulaire complet pour créer/modifier un utilisateur - -**Paramètres principaux**: -- `user`: UserDTO (requis) -- `mode`: String (défaut: "create") - "create" ou "edit" -- `showRealmSelector`: Boolean (défaut: false) -- `showPasswordFields`: Boolean (défaut: true) -- `readonly`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - - -``` - -#### 3. `user-search-bar.xhtml` -**Description**: Barre de recherche avancée pour utilisateurs - -**Paramètres principaux**: -- `searchCriteria`: UserSearchCriteriaDTO (requis) -- `searchAction`: String (requis) -- `showAdvanced`: Boolean (défaut: false) -- `showRealmFilter`: Boolean (défaut: true) -- `showStatusFilter`: Boolean (défaut: true) - -**Exemple**: -```xhtml - - - - - -``` - -#### 4. `user-actions.xhtml` -**Description**: Boutons d'action pour un utilisateur - -**Paramètres principaux**: -- `user`: UserDTO (requis) -- `showView`: Boolean (défaut: true) -- `showEdit`: Boolean (défaut: true) -- `showDelete`: Boolean (défaut: true) -- `showActivate`: Boolean (défaut: true) -- `layout`: String (défaut: "horizontal") - "horizontal", "vertical" ou "dropdown" - -**Exemple**: -```xhtml - - - - - -``` - -#### 5. `user-role-badge.xhtml` -**Description**: Badge pour un rôle utilisateur - -**Paramètres principaux**: -- `roleName`: String (requis) -- `roleType`: String (optionnel) - "REALM_ROLE", "CLIENT_ROLE", "COMPOSITE_ROLE" -- `severity`: String (optionnel) - "success", "info", "warning", "danger" -- `clickable`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - -``` - ---- - -### 🛡️ Role Management (3 composants) - -#### 6. `role-card.xhtml` -**Description**: Carte rôle avec informations principales - -**Paramètres principaux**: -- `role`: RoleDTO (requis) -- `showActions`: Boolean (défaut: true) -- `showDescription`: Boolean (défaut: true) -- `showCompositeInfo`: Boolean (défaut: true) - -**Exemple**: -```xhtml - - - -``` - -#### 7. `role-form.xhtml` -**Description**: Formulaire pour créer/modifier un rôle - -**Paramètres principaux**: -- `role`: RoleDTO (requis) -- `mode`: String (défaut: "create") -- `showRealmSelector`: Boolean (défaut: true) -- `showClientSelector`: Boolean (défaut: false) -- `showCompositeOptions`: Boolean (défaut: true) - -**Exemple**: -```xhtml - - - - - -``` - -#### 8. `role-assignment.xhtml` -**Description**: Interface pour attribuer/révoquer des rôles - -**Paramètres principaux**: -- `user`: UserDTO (requis) -- `availableRoles`: List (requis) -- `userRoles`: List (requis) -- `assignAction`: String (requis) -- `revokeAction`: String (requis) - -**Exemple**: -```xhtml - - - - - - - -``` - ---- - -### 📊 Audit (2 composants) - -#### 9. `audit-log-row.xhtml` -**Description**: Ligne de log d'audit avec informations détaillées - -**Paramètres principaux**: -- `auditLog`: AuditLogDTO (requis) -- `showDetails`: Boolean (défaut: false) -- `showActions`: Boolean (défaut: false) -- `compact`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - -``` - -#### 10. `audit-stats-card.xhtml` -**Description**: Carte statistiques d'audit - -**Paramètres principaux**: -- `title`: String (requis) -- `value`: Number (requis) -- `icon`: String (requis) -- `iconColor`: String (requis) -- `trend`: Number (optionnel) -- `trendLabel`: String (optionnel) - -**Exemple**: -```xhtml - - - - - - -``` - ---- - -### 🔧 Shared Components (4 composants) - -#### 11. `button-user-action.xhtml` -**Description**: Bouton générique pour actions utilisateur - -**Paramètres principaux**: -- `value`: String (requis) -- `icon`: String (optionnel) -- `action`: String (optionnel) -- `outcome`: String (optionnel) -- `severity`: String (défaut: "primary") -- `size`: String (défaut: "normal") - -**Exemple**: -```xhtml - - - - - -``` - -#### 12. `user-stat-card.xhtml` -**Description**: Carte statistique utilisateur - -**Paramètres principaux**: -- `title`: String (requis) -- `value`: String/Number (requis) -- `icon`: String (requis) -- `iconColor`: String (requis) -- `trend`: Number (optionnel) -- `clickable`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - - - -``` - -#### 13. `user-form-field.xhtml` -**Description**: Champ de formulaire générique - -**Paramètres principaux**: -- `id`: String (requis) -- `label`: String (requis) -- `value`: Object (requis) -- `type`: String (défaut: "text") - "text", "email", "password", "number", "textarea", "select", "checkbox", "calendar" -- `required`: Boolean (défaut: false) -- `readonly`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - - - -``` - -#### 14. `user-data-table.xhtml` -**Description**: Tableau de données pour utilisateurs - -**Paramètres principaux**: -- `users`: List (requis) -- `var`: String (défaut: "user") -- `paginator`: Boolean (défaut: true) -- `rows`: Number (défaut: 20) -- `showActions`: Boolean (défaut: true) -- `showRoles`: Boolean (défaut: true) -- `showSelection`: Boolean (défaut: false) - -**Exemple**: -```xhtml - - - - -``` - ---- - -## 🎨 Patterns et Conventions - -### Documentation Inline -Chaque composant contient une documentation complète en commentaire avec: -- Description du composant -- Liste des paramètres avec types et valeurs par défaut -- Exemples d'utilisation - -### Paramètres Optionnels -Tous les paramètres optionnels ont des valeurs par défaut définies avec ``. - -### Pattern WOU/DRY -- **Write Once Use**: Chaque composant est écrit une fois et réutilisé partout -- **Don't Repeat Yourself**: Pas de duplication de code - -### Naming Convention -- Noms de fichiers en `kebab-case` -- Paramètres en `camelCase` -- IDs de composants avec préfixe cohérent - ---- - -## 🚀 Utilisation dans d'Autres Projets - -Ces composants peuvent être utilisés dans n'importe quel projet de l'écosystème **lionsdev** en ajoutant la dépendance Maven: - -```xml - - dev.lions.user.manager - lions-user-manager-client-quarkus-primefaces-freya - 1.0.0 - -``` - -Puis inclure les composants dans vos pages XHTML: - -```xhtml - - - -``` - ---- - -## 📝 Notes Importantes - -1. **Dépendances**: Tous les composants nécessitent PrimeFaces 14.0.5+ et Quarkus PrimeFaces 3.13.3+ -2. **Thème**: Les composants utilisent le thème Freya (compatible avec unionflow) -3. **Validation**: Les composants de formulaire incluent la validation JSF -4. **Accessibilité**: Les composants suivent les bonnes pratiques d'accessibilité - ---- - -## 🔄 Maintenance - -Pour ajouter un nouveau composant: - -1. Créer le fichier dans le répertoire approprié -2. Suivre le pattern de documentation inline -3. Ajouter des exemples d'utilisation -4. Mettre à jour ce README - ---- - -**Dernière mise à jour**: 2025-01-29 -**Version**: 1.0.0 -**Auteur**: Lions User Manager Team - +# 📦 Composants Réutilisables - Lions User Manager + +**Version**: 1.0.0 +**Date**: 2025-01-29 +**Pattern**: WOU/DRY (Write Once Use / Don't Repeat Yourself) + +--- + +## 🎯 Vue d'Ensemble + +Ce répertoire contient tous les composants UI réutilisables pour le module **lions-user-manager**. Ces composants suivent les patterns établis dans **unionflow** et peuvent être utilisés dans n'importe quel projet de l'écosystème **lionsdev**. + +--- + +## 📂 Structure des Composants + +``` +templates/components/ +├── user-management/ # Composants spécifiques utilisateurs +│ ├── user-card.xhtml +│ ├── user-form.xhtml +│ ├── user-search-bar.xhtml +│ ├── user-actions.xhtml +│ └── user-role-badge.xhtml +├── role-management/ # Composants spécifiques rôles +│ ├── role-card.xhtml +│ ├── role-form.xhtml +│ └── role-assignment.xhtml +├── audit/ # Composants audit +│ ├── audit-log-row.xhtml +│ └── audit-stats-card.xhtml +└── shared/ # Composants génériques réutilisables + ├── buttons/ + │ └── button-user-action.xhtml + ├── cards/ + │ └── user-stat-card.xhtml + ├── forms/ + │ └── user-form-field.xhtml + └── tables/ + └── user-data-table.xhtml +``` + +--- + +## 📋 Liste Complète des Composants + +### 👤 User Management (5 composants) + +#### 1. `user-card.xhtml` +**Description**: Carte utilisateur avec informations principales et actions + +**Paramètres principaux**: +- `user`: UserDTO (requis) +- `showActions`: Boolean (défaut: true) +- `showRoles`: Boolean (défaut: true) +- `clickable`: Boolean (défaut: true) +- `outcome`: String (optionnel) + +**Exemple**: +```xhtml + + + + +``` + +#### 2. `user-form.xhtml` +**Description**: Formulaire complet pour créer/modifier un utilisateur + +**Paramètres principaux**: +- `user`: UserDTO (requis) +- `mode`: String (défaut: "create") - "create" ou "edit" +- `showRealmSelector`: Boolean (défaut: false) +- `showPasswordFields`: Boolean (défaut: true) +- `readonly`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + + +``` + +#### 3. `user-search-bar.xhtml` +**Description**: Barre de recherche avancée pour utilisateurs + +**Paramètres principaux**: +- `searchCriteria`: UserSearchCriteriaDTO (requis) +- `searchAction`: String (requis) +- `showAdvanced`: Boolean (défaut: false) +- `showRealmFilter`: Boolean (défaut: true) +- `showStatusFilter`: Boolean (défaut: true) + +**Exemple**: +```xhtml + + + + + +``` + +#### 4. `user-actions.xhtml` +**Description**: Boutons d'action pour un utilisateur + +**Paramètres principaux**: +- `user`: UserDTO (requis) +- `showView`: Boolean (défaut: true) +- `showEdit`: Boolean (défaut: true) +- `showDelete`: Boolean (défaut: true) +- `showActivate`: Boolean (défaut: true) +- `layout`: String (défaut: "horizontal") - "horizontal", "vertical" ou "dropdown" + +**Exemple**: +```xhtml + + + + + +``` + +#### 5. `user-role-badge.xhtml` +**Description**: Badge pour un rôle utilisateur + +**Paramètres principaux**: +- `roleName`: String (requis) +- `roleType`: String (optionnel) - "REALM_ROLE", "CLIENT_ROLE", "COMPOSITE_ROLE" +- `severity`: String (optionnel) - "success", "info", "warning", "danger" +- `clickable`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + +``` + +--- + +### 🛡️ Role Management (3 composants) + +#### 6. `role-card.xhtml` +**Description**: Carte rôle avec informations principales + +**Paramètres principaux**: +- `role`: RoleDTO (requis) +- `showActions`: Boolean (défaut: true) +- `showDescription`: Boolean (défaut: true) +- `showCompositeInfo`: Boolean (défaut: true) + +**Exemple**: +```xhtml + + + +``` + +#### 7. `role-form.xhtml` +**Description**: Formulaire pour créer/modifier un rôle + +**Paramètres principaux**: +- `role`: RoleDTO (requis) +- `mode`: String (défaut: "create") +- `showRealmSelector`: Boolean (défaut: true) +- `showClientSelector`: Boolean (défaut: false) +- `showCompositeOptions`: Boolean (défaut: true) + +**Exemple**: +```xhtml + + + + + +``` + +#### 8. `role-assignment.xhtml` +**Description**: Interface pour attribuer/révoquer des rôles + +**Paramètres principaux**: +- `user`: UserDTO (requis) +- `availableRoles`: List (requis) +- `userRoles`: List (requis) +- `assignAction`: String (requis) +- `revokeAction`: String (requis) + +**Exemple**: +```xhtml + + + + + + + +``` + +--- + +### 📊 Audit (2 composants) + +#### 9. `audit-log-row.xhtml` +**Description**: Ligne de log d'audit avec informations détaillées + +**Paramètres principaux**: +- `auditLog`: AuditLogDTO (requis) +- `showDetails`: Boolean (défaut: false) +- `showActions`: Boolean (défaut: false) +- `compact`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + +``` + +#### 10. `audit-stats-card.xhtml` +**Description**: Carte statistiques d'audit + +**Paramètres principaux**: +- `title`: String (requis) +- `value`: Number (requis) +- `icon`: String (requis) +- `iconColor`: String (requis) +- `trend`: Number (optionnel) +- `trendLabel`: String (optionnel) + +**Exemple**: +```xhtml + + + + + + +``` + +--- + +### 🔧 Shared Components (4 composants) + +#### 11. `button-user-action.xhtml` +**Description**: Bouton générique pour actions utilisateur + +**Paramètres principaux**: +- `value`: String (requis) +- `icon`: String (optionnel) +- `action`: String (optionnel) +- `outcome`: String (optionnel) +- `severity`: String (défaut: "primary") +- `size`: String (défaut: "normal") + +**Exemple**: +```xhtml + + + + + +``` + +#### 12. `user-stat-card.xhtml` +**Description**: Carte statistique utilisateur + +**Paramètres principaux**: +- `title`: String (requis) +- `value`: String/Number (requis) +- `icon`: String (requis) +- `iconColor`: String (requis) +- `trend`: Number (optionnel) +- `clickable`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + + + +``` + +#### 13. `user-form-field.xhtml` +**Description**: Champ de formulaire générique + +**Paramètres principaux**: +- `id`: String (requis) +- `label`: String (requis) +- `value`: Object (requis) +- `type`: String (défaut: "text") - "text", "email", "password", "number", "textarea", "select", "checkbox", "calendar" +- `required`: Boolean (défaut: false) +- `readonly`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + + + +``` + +#### 14. `user-data-table.xhtml` +**Description**: Tableau de données pour utilisateurs + +**Paramètres principaux**: +- `users`: List (requis) +- `var`: String (défaut: "user") +- `paginator`: Boolean (défaut: true) +- `rows`: Number (défaut: 20) +- `showActions`: Boolean (défaut: true) +- `showRoles`: Boolean (défaut: true) +- `showSelection`: Boolean (défaut: false) + +**Exemple**: +```xhtml + + + + +``` + +--- + +## 🎨 Patterns et Conventions + +### Documentation Inline +Chaque composant contient une documentation complète en commentaire avec: +- Description du composant +- Liste des paramètres avec types et valeurs par défaut +- Exemples d'utilisation + +### Paramètres Optionnels +Tous les paramètres optionnels ont des valeurs par défaut définies avec ``. + +### Pattern WOU/DRY +- **Write Once Use**: Chaque composant est écrit une fois et réutilisé partout +- **Don't Repeat Yourself**: Pas de duplication de code + +### Naming Convention +- Noms de fichiers en `kebab-case` +- Paramètres en `camelCase` +- IDs de composants avec préfixe cohérent + +--- + +## 🚀 Utilisation dans d'Autres Projets + +Ces composants peuvent être utilisés dans n'importe quel projet de l'écosystème **lionsdev** en ajoutant la dépendance Maven: + +```xml + + dev.lions.user.manager + lions-user-manager-client-quarkus-primefaces-freya + 1.0.0 + +``` + +Puis inclure les composants dans vos pages XHTML: + +```xhtml + + + +``` + +--- + +## 📝 Notes Importantes + +1. **Dépendances**: Tous les composants nécessitent PrimeFaces 14.0.5+ et Quarkus PrimeFaces 3.13.3+ +2. **Thème**: Les composants utilisent le thème Freya (compatible avec unionflow) +3. **Validation**: Les composants de formulaire incluent la validation JSF +4. **Accessibilité**: Les composants suivent les bonnes pratiques d'accessibilité + +--- + +## 🔄 Maintenance + +Pour ajouter un nouveau composant: + +1. Créer le fichier dans le répertoire approprié +2. Suivre le pattern de documentation inline +3. Ajouter des exemples d'utilisation +4. Mettre à jour ce README + +--- + +**Dernière mise à jour**: 2025-01-29 +**Version**: 1.0.0 +**Auteur**: Lions User Manager Team + diff --git a/src/main/resources/META-INF/resources/templates/components/audit/audit-log-row.xhtml b/src/main/resources/META-INF/resources/templates/components/audit/audit-log-row.xhtml index d722251..ed2581d 100644 --- a/src/main/resources/META-INF/resources/templates/components/audit/audit-log-row.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/audit/audit-log-row.xhtml @@ -1,139 +1,139 @@ - - - - - - - - - - - - - - -
- - -
- -
- - -
-
- #{auditLog.typeAction} - -
- -
- - - - #{auditLog.acteurUsername} - - - - - - #{auditLog.ressourceType} - - - - - - #{auditLog.dateAction} - - - - - - #{auditLog.realmName} - - -
- - - -
-
- -
- Ressource ID: - #{auditLog.ressourceId} -
-
- -
- Adresse IP: - #{auditLog.adresseIp} -
-
- -
- Détails: - #{auditLog.details} -
-
- -
- User Agent: - - #{auditLog.userAgent} - -
-
- -
- Erreur: - #{auditLog.messageErreur} -
-
-
-
-
-
- - - -
- -
-
-
- + + + + + + + + + + + + + + +
+ + +
+ +
+ + +
+
+ #{auditLog.typeAction} + +
+ +
+ + + + #{auditLog.acteurUsername} + + + + + + #{auditLog.ressourceType} + + + + + + #{auditLog.dateAction} + + + + + + #{auditLog.realmName} + + +
+ + + +
+
+ +
+ Ressource ID: + #{auditLog.ressourceId} +
+
+ +
+ Adresse IP: + #{auditLog.adresseIp} +
+
+ +
+ Détails: + #{auditLog.details} +
+
+ +
+ User Agent: + + #{auditLog.userAgent} + +
+
+ +
+ Erreur: + #{auditLog.messageErreur} +
+
+
+
+
+
+ + + +
+ +
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/audit/audit-stats-card.xhtml b/src/main/resources/META-INF/resources/templates/components/audit/audit-stats-card.xhtml index 3a57e37..d9eeb1a 100644 --- a/src/main/resources/META-INF/resources/templates/components/audit/audit-stats-card.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/audit/audit-stats-card.xhtml @@ -1,71 +1,71 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/layout/footer.xhtml b/src/main/resources/META-INF/resources/templates/components/layout/footer.xhtml index 440d19a..8bd7649 100644 --- a/src/main/resources/META-INF/resources/templates/components/layout/footer.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/layout/footer.xhtml @@ -1,28 +1,28 @@ - - - - - - - - + + + + + + + + diff --git a/src/main/resources/META-INF/resources/templates/components/layout/menu.xhtml b/src/main/resources/META-INF/resources/templates/components/layout/menu.xhtml index aa2ef5c..8d6b04d 100644 --- a/src/main/resources/META-INF/resources/templates/components/layout/menu.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/layout/menu.xhtml @@ -1,59 +1,59 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/layout/page-header.xhtml b/src/main/resources/META-INF/resources/templates/components/layout/page-header.xhtml index e2837a9..3195218 100644 --- a/src/main/resources/META-INF/resources/templates/components/layout/page-header.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/layout/page-header.xhtml @@ -1,93 +1,93 @@ - - - - -
-
- - -
- - - - #{breadcrumbParent} - - - - #{breadcrumbParent} - - - - #{title} -
-
- -
-
- -
- -
- -
-
-
-

#{title}

- -

#{description}

-
-
-
- - -
- -
-
-
-
-
+ + + + +
+
+ + +
+ + + + #{breadcrumbParent} + + + + #{breadcrumbParent} + + + + #{title} +
+
+ +
+
+ +
+ +
+ +
+
+
+

#{title}

+ +

#{description}

+
+
+
+ + +
+ +
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/layout/topbar.xhtml b/src/main/resources/META-INF/resources/templates/components/layout/topbar.xhtml deleted file mode 100644 index aef6876..0000000 --- a/src/main/resources/META-INF/resources/templates/components/layout/topbar.xhtml +++ /dev/null @@ -1,118 +0,0 @@ - - - - -
-
-
- - - - - - -
- - - -
- - - - -
-
-
- -
- diff --git a/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment-content.xhtml b/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment-content.xhtml index a2ead00..c1a4a7c 100644 --- a/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment-content.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment-content.xhtml @@ -1,170 +1,170 @@ - - - - - - - - -
- - Attribution de rôles - - - #{user.username} - -
-
- - -

- Rôles actuels -

-
- - - -
- - #{userRole.name} - - - - - - - - -
-
-
- -
- - Aucun rôle attribué à cet utilisateur -
-
-
-
- - - - -

- Rôles disponibles -

- - -
-
- - - - - - -
-
- - - - -
- - - - - - - - - - -
- - - - #{role.name} - - - - #{role.name} - - - - - - -
-
-
-
-
-
- - - - -
- - - - - - - - - -
- - - - #{role.name} - - - - #{role.name} - - - - - - -
-
-
-
-
-
- -
- + + + + + + + + +
+ + Attribution de rôles + + - #{user.username} + +
+
+ + +

+ Rôles actuels +

+
+ + + +
+ + #{userRole.name} + + + + + + + + +
+
+
+ +
+ + Aucun rôle attribué à cet utilisateur +
+
+
+
+ + + + +

+ Rôles disponibles +

+ + +
+
+ + + + + + +
+
+ + + + +
+ + + + + + + + + + +
+ + + + #{role.name} + + + + #{role.name} + + + + + + +
+
+
+
+
+
+ + + + +
+ + + + + + + + + +
+ + + + #{role.name} + + + + #{role.name} + + + + + + +
+
+
+
+
+
+ +
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment.xhtml b/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment.xhtml index 5da9cdd..7db64ac 100644 --- a/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/role-management/role-assignment.xhtml @@ -1,76 +1,76 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/role-management/role-card.xhtml b/src/main/resources/META-INF/resources/templates/components/role-management/role-card.xhtml index a7d55f6..686cbdb 100644 --- a/src/main/resources/META-INF/resources/templates/components/role-management/role-card.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/role-management/role-card.xhtml @@ -1,174 +1,174 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- -
-
- - - - - #{role.name} - - - - #{role.name} - - - #{typeLabel} -
-
- - - - -
-
- -
- - -
- - -

- #{role.description} -

-
- - Aucune description - -
-
-
- - -
- -
- - #{role.realmName} -
-
- - -
- - Client: #{role.clientId} -
-
-
-
- - - - -
- - - - - - - - - - - -
-
-
-
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+ + + + + #{role.name} + + + + #{role.name} + + + #{typeLabel} +
+
+ + + + +
+
+ +
+ + +
+ + +

+ #{role.description} +

+
+ + Aucune description + +
+
+
+ + +
+ +
+ + #{role.realmName} +
+
+ + +
+ + Client: #{role.clientId} +
+
+
+
+ + + + +
+ + + + + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/role-management/role-form-content.xhtml b/src/main/resources/META-INF/resources/templates/components/role-management/role-form-content.xhtml index 47eb9c1..7c9d8c7 100644 --- a/src/main/resources/META-INF/resources/templates/components/role-management/role-form-content.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/role-management/role-form-content.xhtml @@ -1,176 +1,176 @@ - - - - - - - - - -

- Informations du rôle -

- -
- -
-
- - * - - - - - - - Lettres, chiffres, underscores et tirets (ex: admin, user_manager) - -
-
- - -
-
- - * - - - - - - - -
-
- - -
-
- - -
-
-
- - - - -

- Configuration -

- -
- - -
-
- - * - - - - - -
-
-
- - - -
-
- - * - - - - - -
-
-
- - - -
-
-
- - -
- - Un rôle composite regroupe plusieurs sous-rôles - -
-
-
-
- - - -
- - - - - - - - - - - - - - - - - - - - - -
-
-
- + + + + + + + + + +

+ Informations du rôle +

+ +
+ +
+
+ + * + + + + + + + Lettres, chiffres, underscores et tirets (ex: admin, user_manager) + +
+
+ + +
+
+ + * + + + + + + + +
+
+ + +
+
+ + +
+
+
+ + + + +

+ Configuration +

+ +
+ + +
+
+ + * + + + + + +
+
+
+ + + +
+
+ + * + + + + + +
+
+
+ + + +
+
+
+ + +
+ + Un rôle composite regroupe plusieurs sous-rôles + +
+
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/role-management/role-form.xhtml b/src/main/resources/META-INF/resources/templates/components/role-management/role-form.xhtml index f111031..e52679d 100644 --- a/src/main/resources/META-INF/resources/templates/components/role-management/role-form.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/role-management/role-form.xhtml @@ -1,94 +1,94 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/templates/components/shared/README_KPI.md b/src/main/resources/META-INF/resources/templates/components/shared/README_KPI.md index 6b27a0d..6ee9705 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/README_KPI.md +++ b/src/main/resources/META-INF/resources/templates/components/shared/README_KPI.md @@ -1,240 +1,240 @@ -# 📊 Composants KPI Réutilisables - Écosystème LionsDev - -**Version**: 2.0.0 -**Date**: 2025-01-29 -**Pattern**: WOU/DRY (Write Once Use / Don't Repeat Yourself) - ---- - -## 🎯 Vue d'Ensemble - -Ces composants KPI (Indicateurs de Performance) sont conçus pour être **100% réutilisables** dans tous les projets de l'écosystème **lionsdev**. Ils suivent les meilleures pratiques de PrimeFaces Freya et offrent une expérience utilisateur cohérente. - ---- - -## 📦 Composants Disponibles - -### 1. **kpi-card.xhtml** - Carte KPI Individuelle - -Composant principal pour afficher un indicateur de performance unique. - -**Localisation**: `/templates/components/shared/cards/kpi-card.xhtml` - -**Paramètres principaux**: -- `title` (requis) - Titre du KPI -- `value` (requis) - Valeur à afficher -- `icon` (requis) - Icône PrimeIcons -- `iconColor` (requis) - Couleur de l'icône -- `growthValue` (optionnel) - Valeur de croissance -- `growthLabel` (optionnel) - Libellé de croissance -- `progressValue` (optionnel) - Barre de progression 0-100 -- `statusIcon`, `statusLabel`, `statusValue` (optionnel) - Mode statut -- `clickable` (défaut: false) - Rendre cliquable -- `clickOutcome` (optionnel) - Redirection au clic - -**Exemple simple**: -```xhtml - - - - - - -``` - -**Exemple avec croissance**: -```xhtml - - - - - - - - - -``` - -**Exemple avec statut**: -```xhtml - - - - - - - - - -``` - ---- - -### 2. **kpi-group.xhtml** - Groupe de KPI - -Composant composite pour organiser plusieurs KPI dans une grille. - -**Localisation**: `/templates/components/shared/dashboard/kpi-group.xhtml` - -**Paramètres**: -- `title` (optionnel) - Titre de la section -- `columns` (défaut: 4) - Nombre de colonnes (1-6) -- `colSize` (optionnel) - Taille personnalisée - -**Exemple**: -```xhtml - - - - - - - - - - - - - - -``` - ---- - -### 3. **dashboard-section.xhtml** - Section Dashboard - -Composant composite pour créer des sections de dashboard réutilisables. - -**Localisation**: `/templates/components/shared/dashboard/dashboard-section.xhtml` - -**Paramètres**: -- `title` (requis) - Titre de la section -- `description` (optionnel) - Description -- `icon` (optionnel) - Icône -- `colSize` (défaut: "col-12") - Taille de colonne -- `showCard` (défaut: true) - Envelopper dans une carte - -**Exemple**: -```xhtml - - - - - - -
-
- -
-
-
-
-``` - ---- - -### 4. **user-stat-card.xhtml** - Wrapper de Compatibilité - -Wrapper de compatibilité ascendante qui délègue à `kpi-card.xhtml`. - -**Note**: Pour de nouvelles implémentations, utilisez directement `kpi-card.xhtml`. - ---- - -## 🎨 Couleurs Disponibles - -Utilisez les couleurs PrimeFlex pour `iconColor`: -- `blue-600`, `blue-500`, `blue-400` -- `green-600`, `green-500`, `green-400` -- `purple-600`, `purple-500`, `purple-400` -- `orange-600`, `orange-500`, `orange-400` -- `red-600`, `red-500`, `red-400` -- `cyan-600`, `cyan-500`, `cyan-400` -- `pink-600`, `pink-500`, `pink-400` - ---- - -## 📐 Tailles de Colonnes - -Utilisez les classes PrimeFlex pour `colSize`: -- `col-12` - Pleine largeur -- `col-12 md:col-6` - 2 colonnes sur tablette+ -- `col-12 md:col-6 lg:col-3` - 4 colonnes sur desktop (défaut) -- `col-12 md:col-4` - 3 colonnes -- `col-12 md:col-6 lg:col-2` - 6 colonnes - ---- - -## 🔄 Réutilisabilité dans l'Écosystème LionsDev - -Ces composants peuvent être utilisés dans: -- ✅ **lions-user-manager** (module actuel) -- ✅ **unionflow** (via dépendance Maven) -- ✅ **btpxpress** (via dépendance Maven) -- ✅ **Tout autre projet lionsdev** (via dépendance Maven) - -**Avantages**: -- Code DRY (Don't Repeat Yourself) -- Interface utilisateur cohérente -- Maintenance centralisée -- Évolutivité garantie - ---- - -## 📝 Bonnes Pratiques - -1. **Toujours utiliser `kpi-card.xhtml`** pour de nouveaux KPI -2. **Utiliser `kpi-group.xhtml`** pour organiser plusieurs KPI -3. **Utiliser `dashboard-section.xhtml`** pour structurer les dashboards -4. **Respecter les conventions de couleurs** PrimeFlex -5. **Documenter les paramètres personnalisés** dans votre code - ---- - -## 🚀 Exemple Complet de Dashboard - -```xhtml -
- -
- - - -
- - -
-
- - - - - - - -
-
- - - - - - - - -
-``` - ---- - -## 📚 Documentation Complète - -Pour plus de détails, consultez: -- `/templates/components/README.md` - Documentation générale -- Code source des composants avec commentaires JSDoc - ---- - -**Auteur**: Lions User Manager Team -**Licence**: Écosystème LionsDev - +# 📊 Composants KPI Réutilisables - Écosystème LionsDev + +**Version**: 2.0.0 +**Date**: 2025-01-29 +**Pattern**: WOU/DRY (Write Once Use / Don't Repeat Yourself) + +--- + +## 🎯 Vue d'Ensemble + +Ces composants KPI (Indicateurs de Performance) sont conçus pour être **100% réutilisables** dans tous les projets de l'écosystème **lionsdev**. Ils suivent les meilleures pratiques de PrimeFaces Freya et offrent une expérience utilisateur cohérente. + +--- + +## 📦 Composants Disponibles + +### 1. **kpi-card.xhtml** - Carte KPI Individuelle + +Composant principal pour afficher un indicateur de performance unique. + +**Localisation**: `/templates/components/shared/cards/kpi-card.xhtml` + +**Paramètres principaux**: +- `title` (requis) - Titre du KPI +- `value` (requis) - Valeur à afficher +- `icon` (requis) - Icône PrimeIcons +- `iconColor` (requis) - Couleur de l'icône +- `growthValue` (optionnel) - Valeur de croissance +- `growthLabel` (optionnel) - Libellé de croissance +- `progressValue` (optionnel) - Barre de progression 0-100 +- `statusIcon`, `statusLabel`, `statusValue` (optionnel) - Mode statut +- `clickable` (défaut: false) - Rendre cliquable +- `clickOutcome` (optionnel) - Redirection au clic + +**Exemple simple**: +```xhtml + + + + + + +``` + +**Exemple avec croissance**: +```xhtml + + + + + + + + + +``` + +**Exemple avec statut**: +```xhtml + + + + + + + + + +``` + +--- + +### 2. **kpi-group.xhtml** - Groupe de KPI + +Composant composite pour organiser plusieurs KPI dans une grille. + +**Localisation**: `/templates/components/shared/dashboard/kpi-group.xhtml` + +**Paramètres**: +- `title` (optionnel) - Titre de la section +- `columns` (défaut: 4) - Nombre de colonnes (1-6) +- `colSize` (optionnel) - Taille personnalisée + +**Exemple**: +```xhtml + + + + + + + + + + + + + + +``` + +--- + +### 3. **dashboard-section.xhtml** - Section Dashboard + +Composant composite pour créer des sections de dashboard réutilisables. + +**Localisation**: `/templates/components/shared/dashboard/dashboard-section.xhtml` + +**Paramètres**: +- `title` (requis) - Titre de la section +- `description` (optionnel) - Description +- `icon` (optionnel) - Icône +- `colSize` (défaut: "col-12") - Taille de colonne +- `showCard` (défaut: true) - Envelopper dans une carte + +**Exemple**: +```xhtml + + + + + + +
+
+ +
+
+
+
+``` + +--- + +### 4. **user-stat-card.xhtml** - Wrapper de Compatibilité + +Wrapper de compatibilité ascendante qui délègue à `kpi-card.xhtml`. + +**Note**: Pour de nouvelles implémentations, utilisez directement `kpi-card.xhtml`. + +--- + +## 🎨 Couleurs Disponibles + +Utilisez les couleurs PrimeFlex pour `iconColor`: +- `blue-600`, `blue-500`, `blue-400` +- `green-600`, `green-500`, `green-400` +- `purple-600`, `purple-500`, `purple-400` +- `orange-600`, `orange-500`, `orange-400` +- `red-600`, `red-500`, `red-400` +- `cyan-600`, `cyan-500`, `cyan-400` +- `pink-600`, `pink-500`, `pink-400` + +--- + +## 📐 Tailles de Colonnes + +Utilisez les classes PrimeFlex pour `colSize`: +- `col-12` - Pleine largeur +- `col-12 md:col-6` - 2 colonnes sur tablette+ +- `col-12 md:col-6 lg:col-3` - 4 colonnes sur desktop (défaut) +- `col-12 md:col-4` - 3 colonnes +- `col-12 md:col-6 lg:col-2` - 6 colonnes + +--- + +## 🔄 Réutilisabilité dans l'Écosystème LionsDev + +Ces composants peuvent être utilisés dans: +- ✅ **lions-user-manager** (module actuel) +- ✅ **unionflow** (via dépendance Maven) +- ✅ **btpxpress** (via dépendance Maven) +- ✅ **Tout autre projet lionsdev** (via dépendance Maven) + +**Avantages**: +- Code DRY (Don't Repeat Yourself) +- Interface utilisateur cohérente +- Maintenance centralisée +- Évolutivité garantie + +--- + +## 📝 Bonnes Pratiques + +1. **Toujours utiliser `kpi-card.xhtml`** pour de nouveaux KPI +2. **Utiliser `kpi-group.xhtml`** pour organiser plusieurs KPI +3. **Utiliser `dashboard-section.xhtml`** pour structurer les dashboards +4. **Respecter les conventions de couleurs** PrimeFlex +5. **Documenter les paramètres personnalisés** dans votre code + +--- + +## 🚀 Exemple Complet de Dashboard + +```xhtml +
+ +
+ + + +
+ + +
+
+ + + + + + + +
+
+ + + + + + + + +
+``` + +--- + +## 📚 Documentation Complète + +Pour plus de détails, consultez: +- `/templates/components/README.md` - Documentation générale +- Code source des composants avec commentaires JSDoc + +--- + +**Auteur**: Lions User Manager Team +**Licence**: Écosystème LionsDev + diff --git a/src/main/resources/META-INF/resources/templates/components/shared/buttons/button-user-action.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/buttons/button-user-action.xhtml index 567fd2c..5c20711 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/buttons/button-user-action.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/buttons/button-user-action.xhtml @@ -1,141 +1,141 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card-content.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card-content.xhtml index 2f2116c..05ad791 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card-content.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card-content.xhtml @@ -1,122 +1,122 @@ - - - - -
- -
- #{title} -
- -
-
- - -
- - - - - 0 - #{value} - - - 0 - -
- - - -
#{subtitle}
-
- - - - - - - -
- - #{statusLabel} - #{statusValue} -
-
- - -
- - Aucun #{statusLabel} - #{noDataLabel} - -
-
-
-
-
- - - - -
- - - - - - +#{growthValue}#{growthType == 'number' ? '' : '%'} - - - - - - - #{growthValue}#{growthType == 'number' ? '' : '%'} - - - - - #{growthLabel} - -
-
- - -
#{noDataLabel}
-
-
-
-
-
- - - -
- -
-
-
- + + + + +
+ +
+ #{title} +
+ +
+
+ + +
+ + + + + 0 + #{value} + + + 0 + +
+ + + +
#{subtitle}
+
+ + + + + + + +
+ + #{statusLabel} + #{statusValue} +
+
+ + +
+ + Aucun #{statusLabel} + #{noDataLabel} + +
+
+
+
+
+ + + + +
+ + + + + + +#{growthValue}#{growthType == 'number' ? '' : '%'} + + + + + + + #{growthValue}#{growthType == 'number' ? '' : '%'} + + + + + #{growthLabel} + +
+
+ + +
#{noDataLabel}
+
+
+
+
+
+ + + +
+ +
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card.xhtml index 76635b4..724a78c 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/cards/kpi-card.xhtml @@ -1,73 +1,73 @@ - - - - - - - - - - - -
- - - -
- - - - - - - - - - - - - - - - - -
-
-
- -
- - - - - - - - - - - - - - - - - -
-
-
-
- -
+ + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + +
+
+
+
+ +
diff --git a/src/main/resources/META-INF/resources/templates/components/shared/cards/user-stat-card.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/cards/user-stat-card.xhtml index d278915..b16bdbd 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/cards/user-stat-card.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/cards/user-stat-card.xhtml @@ -1,67 +1,67 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/templates/components/shared/dashboard/dashboard-section.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/dashboard/dashboard-section.xhtml index 48dab69..e3423b5 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/dashboard/dashboard-section.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/dashboard/dashboard-section.xhtml @@ -1,77 +1,77 @@ - - - - - - - -
- - -
- -
- - - -
#{title}
-
-
- -

#{description}

-
- - - -
-
- - -
- - - -
#{title}
-
-
- -

#{description}

-
- - - -
-
-
- -
- + + + + + + + +
+ + +
+ +
+ + + +
#{title}
+
+
+ +

#{description}

+
+ + + +
+
+ + +
+ + + +
#{title}
+
+
+ +

#{description}

+
+ + + +
+
+
+ +
+ diff --git a/src/main/resources/META-INF/resources/templates/components/shared/dashboard/kpi-group.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/dashboard/kpi-group.xhtml index 73187d7..0c81e99 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/dashboard/kpi-group.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/dashboard/kpi-group.xhtml @@ -1,78 +1,78 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
#{title}
-
-
- - - -
-
- -
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
#{title}
+
+
+ + + +
+
+ +
+ diff --git a/src/main/resources/META-INF/resources/templates/components/shared/forms/user-form-field.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/forms/user-form-field.xhtml index ce035b8..d5f0550 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/forms/user-form-field.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/forms/user-form-field.xhtml @@ -1,190 +1,190 @@ - - - - - - - - - - - -
- - - - - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
-
- - - -
- - -
-
- - - - - - - - - - -
- - - - - - - - - #{helpText} - -
- + + + + + + + + + + + +
+ + + + + * + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + +
+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + #{helpText} + +
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/shared/tables/user-data-table.xhtml b/src/main/resources/META-INF/resources/templates/components/shared/tables/user-data-table.xhtml index af9a723..64bd04d 100644 --- a/src/main/resources/META-INF/resources/templates/components/shared/tables/user-data-table.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/shared/tables/user-data-table.xhtml @@ -1,198 +1,198 @@ - - - - - - - - - - - - - - - - - - - - - -
- - #{headerTitle} - -
- - - -
-
-
- - - - - - - - - - - - - -
-
- - #{user.prenom != null and user.prenom.length() > 0 ? user.prenom.substring(0,1) : 'U'}#{user.nom - != null and user.nom.length() > 0 ? user.nom.substring(0,1) : ''} - -
- #{user.username} -
-
- - - -
- #{user.prenom} #{user.nom} - - #{user.fonction} - -
-
- - - - -
- - #{user.email} - - - -
-
-
- - - - -
- -
-
-
- - - - -
- - - - - - - - - - - - - Aucun rôle - - -
-
-
- - - - -
- - - - - - - - - -
-
-
-
- + + + + + + + + + + + + + + + + + + + + + +
+ + #{headerTitle} + +
+ + + +
+
+
+ + + + + + + + + + + + + +
+
+ + #{user.prenom != null and user.prenom.length() > 0 ? user.prenom.substring(0,1) : 'U'}#{user.nom + != null and user.nom.length() > 0 ? user.nom.substring(0,1) : ''} + +
+ #{user.username} +
+
+ + + +
+ #{user.prenom} #{user.nom} + + #{user.fonction} + +
+
+ + + + +
+ + #{user.email} + + + +
+
+
+ + + + +
+ +
+
+
+ + + + +
+ + + + + + + + + + + + + Aucun rôle + + +
+
+
+ + + + +
+ + + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-actions.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-actions.xhtml index 8fb6250..f16370c 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-actions.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-actions.xhtml @@ -1,197 +1,197 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- - - - -
- - -
-
- - -
-
- - -
-
-
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + +
+ + +
+
+ + +
+
+ + +
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-card.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-card.xhtml index 29deabe..c4bf09a 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-card.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-card.xhtml @@ -1,155 +1,155 @@ - - - - - - - - - - - - - - -
- - - - -
-

#{user.prenom} #{user.nom}

- @#{user.username} -
- - - -
-
- -
- -
- -
- - #{user.email} - - - -
- - - -
- - #{user.telephone} -
-
- - - -
- - #{user.organisation} - - - #{user.fonction} - -
-
-
- - - -
- Rôles -
- - - - - - - - - - - - - Aucun rôle attribué - - -
-
-
-
- - - - -
- - - - - - - - - - - - - - - -
-
-
-
- + + + + + + + + + + + + + + +
+ + + + +
+

#{user.prenom} #{user.nom}

+ @#{user.username} +
+ + + +
+
+ +
+ +
+ +
+ + #{user.email} + + + +
+ + + +
+ + #{user.telephone} +
+
+ + + +
+ + #{user.organisation} + + - #{user.fonction} + +
+
+
+ + + +
+ Rôles +
+ + + + + + + + + + + + + Aucun rôle attribué + + +
+
+
+
+ + + + +
+ + + + + + + + + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-form-content.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-form-content.xhtml index 63d3c42..9baba9a 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-form-content.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-form-content.xhtml @@ -1,283 +1,283 @@ - - - - - - - - - -

- Identité -

- -
- -
-
- - * - - - - - -
-
- - -
-
- - * - - - - -
-
- - -
-
- - * - - - - -
-
- - -
-
- - * - - - - -
-
-
- - - - -

- Coordonnées -

- -
- -
-
- - - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - - - -

- Organisation -

- -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - - - -

- Statut et Paramètres -

- -
- -
-
- - - - - -
-
- - - -
-
- - * - - - - - -
-
-
- - -
-
-
- - -
-
-
- - -
-
-
- - -
-
-
-
- - - - - -

- Mot de passe -

- -
-
-
- - * - - - - -
-
- -
-
- - * - - -
-
-
-
- - - -
- - - - - - - - - - - - - - -
-
-
- + + + + + + + + + +

+ Identité +

+ +
+ +
+
+ + * + + + + + +
+
+ + +
+
+ + * + + + + +
+
+ + +
+
+ + * + + + + +
+
+ + +
+
+ + * + + + + +
+
+
+ + + + +

+ Coordonnées +

+ +
+ +
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + + +

+ Organisation +

+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + + +

+ Statut et Paramètres +

+ +
+ +
+
+ + + + + +
+
+ + + +
+
+ + * + + + + + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
+ + + + + +

+ Mot de passe +

+ +
+
+
+ + * + + + + +
+
+ +
+
+ + * + + +
+
+
+
+ + + +
+ + + + + + + + + + + + + + +
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-form.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-form.xhtml index 7de20d0..3edb5b1 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-form.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-form.xhtml @@ -1,95 +1,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-role-badge.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-role-badge.xhtml index 14e4c09..7006a52 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-role-badge.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-role-badge.xhtml @@ -1,55 +1,55 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-roles-manager.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-roles-manager.xhtml index 8a36cc4..9999c74 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-roles-manager.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-roles-manager.xhtml @@ -1,81 +1,81 @@ - - - - - - - - - - -
-
- -

- Rôles Assignés -

- - - - #{roleName} - - - - - - - -
- -
- -

- Ajouter un Rôle -

- -
-
- - - - - -
- - -
- -
-
- - Information -
-

- Les rôles définissent les permissions de l'utilisateur dans l'application. - Certains rôles peuvent donner accès à des fonctionnalités administratives sensibles. -

-
-
-
-
- + + + + + + + + + + +
+
+ +

+ Rôles Assignés +

+ + + + #{roleName} + + + + + + + +
+ +
+ +

+ Ajouter un Rôle +

+ +
+
+ + + + + +
+ + +
+ +
+
+ + Information +
+

+ Les rôles définissent les permissions de l'utilisateur dans l'application. + Certains rôles peuvent donner accès à des fonctionnalités administratives sensibles. +

+
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar-content.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar-content.xhtml index 0199da7..f293310 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar-content.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar-content.xhtml @@ -1,184 +1,184 @@ - - - - - - -
- - - Recherche d'utilisateurs - - - - -
-
- - -
-
- -
- - - - - - -
-
- - - -
- - - - - - -
-
- - - -
- - - - - - -
-
- - -
- - - -
-
-
- - - - - -
- -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - -
-
- - - - -
-
-
- - -
-
- - - - - - -
-
- - -
-
- - -
-
- - -
-
- - -
-
-
- - -
- - -
-
-
-
- + + + + + + +
+ + + Recherche d'utilisateurs + + + + +
+
+ + +
+
+ +
+ + + + + + +
+
+ + + +
+ + + + + + +
+
+ + + +
+ + + + + + +
+
+ + +
+ + + +
+
+
+ + + + + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ + + + +
+
+
+ + +
+
+ + + + + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+ + +
+
+
+
+
\ No newline at end of file diff --git a/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar.xhtml b/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar.xhtml index 836e92e..909b661 100644 --- a/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar.xhtml +++ b/src/main/resources/META-INF/resources/templates/components/user-management/user-search-bar.xhtml @@ -1,83 +1,83 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/META-INF/resources/templates/main-template.xhtml b/src/main/resources/META-INF/resources/templates/main-template.xhtml deleted file mode 100644 index 82d66eb..0000000 --- a/src/main/resources/META-INF/resources/templates/main-template.xhtml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - <ui:insert name="title">Lions User Manager</ui:insert> - - - - - - - -
- - -
-
- - -
- -
- - - -