fix error regisster page

This commit is contained in:
Serreau Jovann
2025-11-16 19:41:07 +01:00
parent fd5e60800a
commit 3ade1f4635
722 changed files with 2303 additions and 38736 deletions

28
.env
View File

@@ -50,31 +50,3 @@ SENTRY_DSN=
VITE_LOAD=0
REDIS_DSN="redis://redis:6379"
REAL_MAIL=0
VAULT_ADDR=http://vault:8200
VAULT_TOKEN=myroot
INSEE_KEYAPI=f941bdf0-b8a3-4e4c-81bd-f0b8a35e4cc8
OVH_KEY=34bc2c2eb416b67d
OVH_SECRET=12239d273975b5ab53318907fb66d355
OVH_CUSTOMER=56c387eb9ca4b9a2de4d4d97fd3d7f22
DOCUSIGN_URL=https://signature.esy-web.dev/api
DOCUSIGN_KEY=pgAU116mCFmeF7WQSezHqxtZW8V1fgo31u5d2FXoaKe
STANCER_PRIVATE_KEY=stest_Rv4Hz8ae2wQdjnBVCays7wPo
STANCER_PUBLIC_KEY=ptest_raV5vZ51Lnp2DfBtu5TVs5o0
STANCER_ENV=test
AMAZON_SES_PUBLIC=AKIAWTT2T22CTKQWCMNA
AMAZON_SES_SECRET=BD63dADmgFJJPnjlT9utRDlvcOh8pRH3eOZXsyhNL/F3
###> symfony/amazon-mailer ###
# MAILER_DSN=ses://ACCESS_KEY:SECRET_KEY@default?region=eu-west-1
# MAILER_DSN=ses+smtp://ACCESS_KEY:SECRET_KEY@default?region=eu-west-1
###< symfony/amazon-mailer ###
CLOUDFLARE_TOKEN=oSpqBIuiKc3waClbo3si4Y8dXZSVt8anijQiHY9N
MAILCOW_KEY=DF0E7E-0FD059-16226F-8ECFF1-E558B3
DEV_URL=https://086e682e904b.ngrok-free.app
SENTRY_BACKEND=https://dcf4ed12f5844686f088838f26082bf0@o4510197735948288.ingest.de.sentry.io/4510197737979984
GITEA_APIKEY=725c434effbf467b1f056c738fd450a6befaff6c

View File

@@ -31,4 +31,4 @@ jobs:
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: 22
script: |
cd /var/www/mainframe/app && git pull && nohup sh ./update.sh
cd /var/www/e-cosplay && git pull && nohup sh ./update.sh

View File

@@ -1,116 +0,0 @@
image: tools-registry.esy-web.dev/mainframe/mainframe:php # Utilisation de l'image Docker spécifiée
stages:
- install
- test
- build
- analyse
- deploy
variables:
POSTGRES_DB: "mainframe"
POSTGRES_USER: "mainframe"
POSTGRES_PASSWORD: "mainframe"
POSTGRES_HOST_AUTH_METHOD: trust
# Services Docker définis globalement, disponibles pour tous les jobs
services:
- redis:7-alpine
- postgres:16-alpine
before_script:
- echo "Starting environment setup..."
- echo "Creating .env.local file..."
- echo "APP_ENV=test" > .env.local
- echo "APP_ENV=test" > .env.test
- echo "KERNEL_CLASS=App\Kernel" > .env.test
- echo "APP_SECRET='$ecretf0rt3st'" > .env.test
- echo 'DATABASE_URL="postgresql://symfony_user:ChangeMeInProd!@postgres:5432/app_db_test?serverVersion=16&charset=utf8"' > .env.test
- echo "XDEBUG_MODE=coverage" > .env.test
- echo ".env.local created successfully."
install_dependencies:
stage: install
script:
- echo "Starting installation stage..."
- curl -fsSL https://bun.sh/install | bash
- source /root/.bashrc
- composer install # Ajout de la commande composer install
- bun install # Ajout de la commande bun install
- echo "Dependencies installed successfully."
artifacts:
paths:
- vendor/
- node_modules/
expire_in: 1 day
run_tests:
stage: test
variables:
XDEBUG_MODE: coverage
script:
- echo "Starting testing stage..."
- cat .env.test
- cat .env.local
- php bin/console doctrine:database:create
- php bin/console -no-interaction doctrine:migrations:migrate
- vendor/bin/phpunit -c phpunit.dist.xml
- echo "Tests completed successfully."
needs:
- job: install_dependencies # Ce job dépend du job 'install_dependencies'
artifacts: true
artifacts:
paths:
- .coverage/
expire_in: 1 day
build_application:
stage: build
script:
- echo "Starting build stage..."
- curl -fsSL https://bun.sh/install | bash
- source /root/.bashrc
- echo "Application built successfully."
needs:
- run_tests
- job: install_dependencies # Ce job dépend du job 'install_dependencies'
artifacts: true
analyse_code:
stage: analyse
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [ "" ]
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
allow_failure: true
script:
- echo "Starting analysis stage..."
- sonar-scanner
- echo "Code analysis completed."
needs:
- job: run_tests # Ce job dépend du job 'build_application'
artifacts: true
deploy_application:
stage: deploy
before_script:
- apt-get update --fix-missing
- apt-get install -qq git
# Setup SSH deploy keys
- 'which ssh-agent || ( apt-get install -qq openssh-client )'
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
script:
- echo "Starting deployment stage..."
- ssh bot@35.204.191.160 "cd /var/www/mainframe/app && git pull && nohup sh ./update.sh"
- echo "Application deployed successfully."
needs:
- analyse_code # Ce job dépend maintenant du job 'analyse_code'

View File

@@ -1,57 +0,0 @@
# Changelog
## 1.0.0 (2025-07-16)
### Features
* **Initialisation du Projet:**
* Initialise le projet mainframe avec les contrôleurs, services, assets et la configuration initiale.
* Ajoute la configuration Docker et GitLab CI, ainsi que d'autres fichiers nécessaires. Supprime les fichiers `compose` et `importmap` obsolètes.
* Ajoute l'ensemble initial des fichiers du projet et un `CHANGELOG` (renommé plus tard en `CHANGELOG.md`).
* Ajoute les packages de l'application web.
* **Améliorations CI/CD (.gitlab-ci.yml):**
* Initialise le pipeline CI/CD avec les étapes de base.
* Ajoute les variables PostgreSQL au pipeline CI/CD.
* Met à jour l'image Docker utilisée dans le pipeline.
* Configure SonarQube et les installations CI.
* Ajoute la mise en cache des dépendances Composer et Bun pour améliorer les performances.
* Inclut l'exécution des tests dans GitLab CI.
* Améliore la mise en cache et les dépendances au sein du pipeline CI/CD.
* Ajoute le cache Composer/Bun.
* Source `bashrc` dans GitLab CI.
* **Génération du Sitemap:**
* Ajoute l'URL de la page d'accueil au sitemap.
* Corrige la génération d'URL absolue dans `SitemapSubscriber` (deux commits distincts pour ce correctif).
* **Ansible et Déploiement:**
* Ajoute les fichiers Ansible initiaux.
* Inclut l'installation de PHP 8.3 et les dépendances pour le déploiement.
* Met en place le déploiement via SSH dans `.gitlab-ci.yml`.
* Ajoute un script de mise à jour et la configuration de Supervisor.
* Configure les variables Ansible et ajoute Composer/Bun.
* Ajoute la configuration Caddy et des améliorations générales au playbook Ansible.
* Commente la tâche `liip:imagine:cache:remove` dans Ansible.
* **Attribut Mainframe et Écouteur d'Événements:**
* Ajoute l'attribut `Mainframe` et ses tests.
* Ajoute l'écouteur d'événements `MainframeAttribute` et son test unitaire. Cet écouteur gère l'ajout de l'en-tête `X-Robots-Tag`.
* **Fonctionnalités de Base:**
* Ajoute `HomeController` et son test.
* Ajoute la configuration et les dépendances initiales.
### Refactor
* **Renommage/Déplacement de Fichiers:**
* Renomme `deploy.yml` en `playbook.yml`.
* Déplace `.gitlab-ci.yml` à la racine du projet.
* Remplace `CHANGELOG` par `CHANGELOG.md`.
### Chore
* **Gestion du Cache:**
* Supprime le cache inutilisé dans `.gitlab-ci.yml`.
* **Gestion des Dépendances:**
* Supprime les dépendances Stimulus, Turbo et AssetMapper.
* Supprime les fichiers inutilisés associés à ces dépendances.
* **SonarQube:**
* Configure SonarQube et les tests associés.
* **Global:**
* Un commit générique "global", probablement pour des ajustements mineurs à travers le projet.

View File

@@ -1,2 +1,2 @@
[webservers]
127.0.0.1 ansible_connection=local ansible_python_interpreter=/usr/bin/python3 path=/var/www/mainframe/app
127.0.0.1 ansible_connection=local ansible_python_interpreter=/usr/bin/python3 path=/var/www/e-cosplay

View File

@@ -1,4 +1,4 @@
# Fichier: install_php_83_symfony_pgsql.yml
# Fichier: install_php_83_symfony_pgsql.yml
- name: Deploy application
hosts: webservers
@@ -6,21 +6,12 @@
gather_facts: true
vars:
db_name: "mainframe"
db_user: "mainframe"
db_password: "mainframe"
redis_password: "mainframe"
redis_port: "20100"
# Assurez-vous que 'path' est définie dans votre inventaire ou comme extra-var
# Exemple: path: /var/www/mainframe/app
db_name: "e-cosplay"
db_user: "e-cosplay"
db_password: "e-cosplay"
redis_password: "e-cosplay"
redis_port: "20101"
tasks:
- name: Send a message to the Discord channel
community.general.discord:
webhook_id: "1421437443688890500"
webhook_token: "DPSuS00Ian6O0lQw-1aDQPkVB19so4AA5zaLN_nALs3fDGah1KSLBWys_CYpsc33PGIG"
content: "Mise à jour du mainframe"
- name: Installer le support ACL pour corriger les permissions de 'become_user'
ansible.builtin.apt:
name: acl
@@ -107,8 +98,6 @@
- "{{ path }}/var"
- "{{ path }}/var/log" # Specific for log, though var/log might be created by composer later
- "{{ path }}/public/media" # For uploads
- "{{ path }}/public/storage" # For uploads
- "{{ path }}/public/tmp-sign" # For uploads
- name: Exécuter 'composer install' dans le répertoire de l'application
ansible.builtin.command: composer install --no-dev --optimize-autoloader
@@ -167,7 +156,7 @@
- name: Supervisor config
ansible.builtin.template:
src: supervisor.j2
dest: "/etc/supervisor/conf.d/mainframe.conf"
dest: "/etc/supervisor/conf.d/e-cosplay.conf"
mode: '0644'
- name: Reread Supervisor configuration
@@ -185,7 +174,7 @@
- name: Generate Caddy site configuration
ansible.builtin.template:
src: caddy.j2
dest: "/etc/caddy/sites/mainframe.conf"
dest: "/etc/caddy/sites/e-cosplay.conf"
mode: '0644'
- name: Reload Caddy to apply new configuration
@@ -211,82 +200,6 @@
become: false
args:
chdir: "{{ path }}"
when: ansible_os_family == "Debian" # Added a when condition here, often missed
- name: "Execute created subcriber link"
cron:
name: "Mainframe - subcriber link"
minute: "0"
hour: "*"
job: "sh {{ path }}/script/demande/run.sh"
user: root
- name: "Cron Task purge customer delete"
cron:
name: "Mainframe - Purge customer"
minute: "0"
hour: "21"
job: "php {{ path }}/bin/console mainframe:cron:customer"
user: root
- name: "Cron Task purge customer delete"
cron:
name: "Mainframe - Check Server mail"
minute: "0"
hour: "6"
job: "php {{ path }}/bin/console mainframe:mailserver:check"
user: root
- name: "Cron Task purge email delete"
cron:
name: "Mainframe - Purge customer"
minute: "0"
hour: "21"
job: "php {{ path }}/bin/console mainframe:cron:email"
user: root
- name: "Cron Task check avis de payment"
cron:
name: "Mainframe - Check Avis"
minute: "0"
hour: "6"
job: "php {{ path }}/bin/console mainframe:check:avispayment"
user: root
- name: "Cron Task check Auto de payment"
cron:
name: "Mainframe - Auto Avis"
minute: "0"
hour: "7"
job: "php {{ path }}/bin/console mainframe:auto:avispayment"
user: root
- name: "Cron Task sync"
ansible.builtin.cron:
name: "Mainframe - Sync"
minute: "0"
hour: "*"
user: "root"
job: "php {{ path }}/bin/console mainframe:cron:sync"
state: present
- name: "Cron Task sync"
ansible.builtin.cron:
name: "Mainframe - Delete tmp"
minute: "30"
hour: "*"
user: "root"
job: "php {{ path }}/bin/console mainframe:tempfile:delete"
state: present
- name: "Mail event today"
ansible.builtin.cron:
name: "Mainframe - Event Today"
minute: "50"
hour: "23"
user: "root"
job: "php {{ path }}/bin/console mainframe:event:today"
state: present
- name: "Backup - Mainframe"
ansible.builtin.cron:
name: "Mainframe - Event Today"
minute: "0"
hour: "7,14,17"
user: "root"
job: "php {{ path }}/bin/console mainframe:backup"
state: present
- name: Set correct permissions for Symfony cache and logs directories
ansible.builtin.file:
path: "{{ item }}"
@@ -299,15 +212,3 @@
- "{{ path }}/var/cache"
- "{{ path }}/var/log"
- "{{ path }}/public/media"
- "{{ path }}/public/storage" # For uploads
- "{{ path }}/public/tmp-sign" # For uploads
- name: Maintenance mode artemis off
ansible.builtin.command: php bin/console mainframe:maintenance artemis false
become: false
args:
chdir: "{{ path }}"
- name: Maintenance mode api off
ansible.builtin.command: php bin/console mainframe:maintenance api false
become: false
args:
chdir: "{{ path }}"

View File

@@ -1,6 +1,6 @@
x-api.esy-web.dev, commande.siteconseil.fr, tutoriel.esy-web.dev, mainframe.esy-web.dev, partage.siteconseil.fr {
www.e-cosplay.fr {
tls {
dns cloudflare bnbe6SmF2kYBnDi4rEeoPI0wNXeFDWn0xZv7Dnfp
dns cloudflare Kq_hpaH_ng-hAeGsJo6KhQb2TxYW1v6lRGE84aOR
}
root * {{ path }}/public
@@ -19,3 +19,10 @@ x-api.esy-web.dev, commande.siteconseil.fr, tutoriel.esy-web.dev, mainframe.esy-
env HTTP_PROXY ""
}
}
e-coslay.fr {
tls {
dns cloudflare Kq_hpaH_ng-hAeGsJo6KhQb2TxYW1v6lRGE84aOR
}
redir https://www.{host}{uri}
}

View File

@@ -1,85 +0,0 @@
import './admin.scss'
import * as Turbo from "@hotwired/turbo"
import {AutoSubmit} from './class/AutoSubmit'
import {ServerCard} from './class/ServerCard'
import {AutoCustomer} from './class/AutoCustomer'
import {RepeatLine} from './class/RepeatLine'
import {RegisterPayment} from './class/RegisterPayment'
import {OrderCtrl} from './class/OrderCtrl'
import {LockdownWall} from './class/LockdownWall'
import {SecurityWall} from './class/SecurityWall'
import {IpWall} from './class/IpWall'
import {ConfirmModal} from './class/ConfirmModal'
import {SearchCustomer} from './class/SearchCustomer'
import preactCustomElement from './functions/preact'
import * as Sentry from "@sentry/browser";
function script() {
customElements.define('confirm-modal',ConfirmModal,{extends:'a'})
customElements.define('auto-submit',AutoSubmit,{extends:'form'})
customElements.define('server-card',ServerCard,{extends:'div'})
customElements.define('auto-customer',AutoCustomer,{extends:'button'})
customElements.define('repeat-line',RepeatLine,{extends:'div'})
customElements.define('lockdown-wall',LockdownWall,{})
customElements.define('security-wall',SecurityWall,{})
customElements.define('ip-wall',IpWall,{})
customElements.define('order-ctrl',OrderCtrl,{extends:'div'})
customElements.define("register-payment",RegisterPayment,{extends:'button'})
customElements.define("search-customer",SearchCustomer,{extends:'select'})
}
function full() {
const sidebar = document.getElementById('sidebar');
const sidebarToggle = document.getElementById('sidebar-toggle');
sidebarToggle.addEventListener('click', function () {
sidebar.classList.toggle('-translate-x-full');
});
const submenuToggles = document.querySelectorAll('[data-submenu-toggle]');
submenuToggles.forEach(button => {
button.addEventListener('click', function () {
const targetId = this.dataset.submenuToggle;
const submenu = document.getElementById(`submenu-${targetId}`);
const arrowIcon = this.querySelector('.arrow-icon');
if (submenu && arrowIcon) {
// Toggle the 'active' class on the submenu
submenu.classList.toggle('active');
// Toggle the 'rotate' class on the arrow icon
arrowIcon.classList.toggle('rotate');
}
});
});
let metaSentry = document.querySelector('meta[name="sentry"]');
if(metaSentry != undefined) {
Sentry.init({
dsn: "https://f134747cc727471fefb197ab5fd4b1b0@o4510197735948288.ingest.de.sentry.io/4510197772320848",
// Setting this option to true will send default PII data to Sentry.
// For example, automatic IP address collection on events
sendDefaultPii: true,
tunnel: "/tunnel",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration()
],
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0 // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
}
}
document.addEventListener('DOMContentLoaded', ()=>{
script();
});
document.addEventListener("turbo:load", ()=> {
full()
});

View File

@@ -1,486 +0,0 @@
@import "tailwindcss";
@import "editor/ckeditor5.css";
@import "editor/tom-select.scss";
@import url('https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&display=swap');
h1,h2,h3,h4,h5,h6,
label,span,input,{
font-family: 'Intel One Mono', monospace;
}
.bg-RUNNING{
color:var(--color-green-700);
}
.bg-STOPPED{
color:var(--color-red-700);
}
select,
input {
background: oklch(21% 0.034 264.665);
color: white;
&::placeholder {
opacity: 0.5;
}
}
.bg-opacity-70{
opacity: .7;
}
.card-contact{
border: 1px solid #1a202c;
background: var(--color-gray-600);
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
.flex{
padding: 0.5rem;
}
}
.loader-item{
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.7);
backdrop-filter: blur(5px);
z-index: 500;
width: 100%;
height: 100%;
span {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 2rem;
}
}
.email-builder-modal{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #ffffff;
z-index: 500;
.md-ctrl{
border: 1px solid black;
display: flex;
padding: 0.5rem;
justify-content: space-between;
color: black;
background: white;
margin: 0.25rem;
}
.side-editor{
overflow-y: auto;
height: 100%;
position: absolute;
background: white;
width: 80vw;
top: 0;
right: 0;
border-left: 1px solid #cdcdcd;
.closed-btn-m{
width: 100%;
background: var(--color-blue-900);
color: white;
padding: 0.25rem;
text-align: center;
font-weight: bold;
}
}
.side-modal{
overflow-y: auto;
height: 100%;
position: absolute;
background: white;
width: 30vw;
top: 0;
right: 0;
border-left: 1px solid #cdcdcd;
.col{
border-top: 1px solid #cdcdcd;
margin-top: 0.5rem;
span {
color: black;
font-weight: bold;
text-align: center;
text-transform: uppercase;
width: 100%;
font-size: 1.25rem;
display: block;
}
}
.td {
font-weight: bold;
color: black;
width: 100%;
margin-left: auto;
margin-right: auto;
display: block;
margin-top: 1rem;
padding-left: 1.5rem;
border-top: 1px solid black;
}
.input-padding{
.display {
height: 150px;
position: relative;
color: black;
margin-top: 0.5rem;
border: 1px solid black;
width: 90%;
margin-left: auto;
margin-right: auto;
}
.center{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-weight: bold;
}
.top1,
.top2,
.top3,
.top {
position: absolute;
left: 50%;
top: 10px;
transform: translate(-50%,15px);
}
.left1,
.left2,
.left3,
.left {
position: absolute;
left: 30%;
top: 50%;
transform: translateY(-50%);
}
.right1,
.right2,
.right3,
.right {
position: absolute;
right: 30%;
top: 50%;
transform: translateY(-50%);
}
.bottom1,
.bottom2,
.bottom3,
.bottom {
position: absolute;
left: 50%;
bottom: 10px;
transform: translate(-50%,-15px);
}
}
.vl {
padding: 0.5rem;
label {
color: black;
font-weight: bold;
padding-left: 1.5rem;
}
}
.input-background{
width: 90%;
margin-left: auto;
margin-right: auto;
display: block;
label {
font-weight: bold;
color: black;
}
input {
display: block;
width: 100%;
border: 1px solid black;
background: none;
}
}
.closed-btn{
width: 100%;
background: var(--color-blue-900);
color: white;
padding: 0.25rem;
text-align: center;
font-weight: bold;
}
}
.area-block{
width: 100%;
margin-bottom: 0.5rem;
.area-name{
margin-left:0.5rem;
display: block;
font-weight: bold;
}
.area-settings{
margin-right:0.5rem;
display: block;
font-weight: bold;
}
.area-block-header{
width: 100%;
background: #cdcdcd;
display: flex;
justify-content: space-between;
border: 1px solid black;
}
.area-block-body{
min-height: 30px;
width: 100%;
display: block;
border-left: 1px solid black;
border-bottom: 1px solid black;
border-right: 1px solid black;
padding: 0.5rem;
ul {
display: block;
min-height: 50px;
padding-bottom: 1rem;
}
}
}
.email-content {
.module{
margin: 0.5rem;
color: black;
.module-item{
cursor: pointer;
border: 1px solid black;
text-align: center;
font-weight: bold;
display: block;
padding: 0.25rem;
margin-bottom: 0.5rem;
}
}
.content{
margin: 0.5rem;
color: black;
padding-bottom: 2rem;
}
.area{
margin: 0.5rem;
color: black;
.area-item{
cursor: pointer;
border: 1px solid black;
text-align: center;
font-weight: bold;
display: block;
padding: 0.25rem;
margin-bottom: 0.5rem;
}
}
}
.email-builder-toolbar{
display: flex;
width: 100%;
border-bottom: 1px solid #cdcdcd;
background: #cdcdcd;
h2 {
color: black;
font-weight: bold;
width: 25%;
font-size: 1.75rem;
margin: auto;
padding-left: 1rem;
}
.email-builder-actions{
display: flex;
width: 100%;
justify-content: end;
}
}
}
.editor-container{
border: 1px solid #cdcdcd !important;
margin: 0.25rem;
height: 90%;
}
.modal-payment{
z-index: 9000;
position: fixed;
top: 0;
left: 0;
background: rgba(0,0,0,0.5);
backdrop-filter: blur(5px);
width: 100%;
height: 100%;
.modal-payment-content{
position: fixed;
top: 50%;
left: 50%;
background: #1a202c;
width: 50%;
transform: translate(-50%,-50%);
h2{
text-align: center;
font-size: 1.25rem;
padding: 0.5rem;
border-bottom: 1px solid #cdcdcd;
}
a {
width: fit-content !important;
position: absolute;
top: 5px;
right: 5px;
}
}
}
security-wall-item{
background: black;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 5000;
.content{
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
span {
text-align: center;
display: block;
margin-top: 2rem;
}
h2 {
font-size: 2rem;
warn {
color: red;
font-weight: bolder;
}
}
}
}
lockdown-wall-item{
background: repeating-linear-gradient(
45deg,
black,
black 20px,
red 20px,
red 40px
);
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 5000;
.content{
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.8); /* Fond noir semi-transparent */
color: white; /* Texte blanc */
padding: 2rem 3rem;
border-radius: 10px;
text-align: center;
font-family: Arial, sans-serif;
box-shadow: 0 0 15px rgba(255, 0, 0, 0.7); /* Ombre rouge pour souligner */
span {
text-align: center;
display: block;
margin-top: 2rem;
}
h2 {
font-size: 1.5rem;
warn {
color: red;
font-weight: bolder;
}
}
}
}
confirm-modal{
position: fixed;
top: 0;
left: 0;
z-index: 9000;
background: rgba(0,0,0,0.5);
backdrop-filter: blur(5px);
width: 100%;
height: 100%;
.confirm-modal-content{
width: 50%;
padding: 0.5rem;
background: #1a202c;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
h2 {
text-align: center;
font-size: 2rem;
margin-bottom: 2rem;
}
}
.ech-created{
color: orange;
font-weight: bolder;
}
.ts-control {
padding: 0;
}
.ts-wrapper,
.ts-control{
border: unset;
background: oklch(21% 0.034 264.665deg) !important;
.item {
color: white;
font-weight: bolder;
}
input {
color: white;
font-weight: bolder;
}
}
.ts-dropdown {
background: var(--color-gray-800) !important;
border: unset !important;
.option{
&:hover {
background: var(--color-gray-600) !important;
}
background: var(--color-gray-800) !important;
color: white;
&.selected {
background: var(--color-gray-600) !important;
}
}
}
.position-relative {
position: relative !important;
max-width: 50vw;
h3 {
text-align: center;
display: block;
strong {
display: block;
}
}
}

View File

@@ -1 +0,0 @@
import './api.scss'

View File

@@ -1,18 +0,0 @@
header {
&:before {
background: purple;
}
}
.title{
color: purple !important;
}
.opblock-summary-method{
background: purple !important;
}
.opblock-section-header{
background: #f8adf8 !important;
}

View File

@@ -1,97 +1,25 @@
import './app.scss'
import * as Turbo from "@hotwired/turbo"
import {PaymentChaque, PaymentPage, PaymentSepa, PaymentVirement} from "./class/PaymentPage.js";
import * as Sentry from "@sentry/browser";
customElements.define('payment-page',PaymentPage,{extends:'button'})
customElements.define('payment-cheque',PaymentChaque,{extends:'button'})
customElements.define('payment-sepa',PaymentSepa,{extends:'button'})
customElements.define('payment-virement',PaymentVirement,{extends:'button'})
document.addEventListener('DOMContentLoaded', () => {
const button = document.querySelector('[aria-controls="mobile-menu"]');
const menu = document.getElementById('mobile-menu');
let metaSentry = document.querySelector('meta[name="sentry"]');
if(metaSentry != undefined) {
Sentry.init({
dsn: "https://f134747cc727471fefb197ab5fd4b1b0@o4510197735948288.ingest.de.sentry.io/4510197772320848",
// Setting this option to true will send default PII data to Sentry.
// For example, automatic IP address collection on events
sendDefaultPii: true,
tunnel: "/tunnel",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration()
],
// Tracing
tracesSampleRate: 1.0, // Capture 100% of the transactions
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0 // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
}
function createSvgIconPassword(paths, classes) {
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute("fill", "none");
svg.setAttribute("stroke", "currentColor");
svg.setAttribute("viewBox", "0 0 24 24");
svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
svg.classList.add(...classes); // Ajoute les classes CSS
paths.forEach(d => {
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("stroke-linecap", "round");
path.setAttribute("stroke-linejoin", "round");
path.setAttribute("stroke-width", "2");
path.setAttribute("d", d);
svg.appendChild(path);
});
return svg;
// Assurez-vous que le menu est initialement caché
if (menu) {
menu.classList.add('hidden');
}
document.querySelectorAll('input[type="password"]').forEach(input=>{
// Crée un conteneur div pour l'input et l'icône
const wrapperDiv = document.createElement('div');
wrapperDiv.classList.add('relative'); // Ajoute la classe Tailwind pour le positionnement
if (button && menu) {
button.addEventListener('click', function() {
// Bascule la classe 'hidden' pour afficher/masquer le menu
menu.classList.toggle('hidden');
// Insère le wrapper avant l'input
input.parentNode.insertBefore(wrapperDiv, input);
// Déplace l'input à l'intérieur du wrapper
wrapperDiv.appendChild(input);
// Crée l'icône de bascule (span)
const toggleIcon = document.createElement('span');
toggleIcon.classList.add('password-toggle-icon');
// Crée les icônes SVG (œil ouvert et œil fermé)
const eyeOpenPaths = [
"M15 12a3 3 0 11-6 0 3 3 0 016 0z",
"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
];
const eyeClosedPaths = [
"M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.542-7 1.274-4.057 5.064-7 9.542-7 .965 0 1.902.13 2.799.375m-4.502 12.15A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.542-7 1.274-4.057 5.064-7 9.542-7 .965 0 1.902.13 2.799.375m-4.502 12.15L21 21"
];
const eyeOpenIcon = createSvgIconPassword(eyeOpenPaths, ['eye-open']);
const eyeClosedIcon = createSvgIconPassword(eyeClosedPaths, ['eye-closed', 'hidden']); // Caché par défaut
toggleIcon.appendChild(eyeOpenIcon);
toggleIcon.appendChild(eyeClosedIcon);
// Ajoute l'icône de bascule au wrapper
wrapperDiv.appendChild(toggleIcon);
// Ajoute l'écouteur d'événements pour la bascule de visibilité
toggleIcon.addEventListener('click', () => {
if (input.type === 'password') {
input.type = 'text';
eyeOpenIcon.classList.add('hidden');
eyeClosedIcon.classList.remove('hidden');
} else {
input.type = 'password';
eyeOpenIcon.classList.remove('hidden');
eyeClosedIcon.classList.add('hidden');
}
// Bascule l'état ARIA pour l'accessibilité
const isExpanded = this.getAttribute('aria-expanded') === 'true' || false;
this.setAttribute('aria-expanded', !isExpanded);
});
})
}
})

View File

@@ -1,94 +1,2 @@
@import "tailwindcss";
@import url('https://fonts.googleapis.com/css2?family=Intel+One+Mono:ital,wght@0,300..700;1,300..700&display=swap');
h1,h2,h3,h4,h5,h6,
label,span,input,{
font-family: 'Intel One Mono', monospace;
}
h1 {
font-size: 2rem;
}
h2 {
font-size: 1.5rem;
}
h3 {
font-size: 1rem;
}
label {
font-size: 1rem;
}
input {
background: oklch(21% 0.034 264.665);
color: white;
&::placeholder {
opacity: 0.5;
}
}
.password-toggle-icon {
cursor: pointer;
position: absolute;
right: 12px; /* Adjust as needed */
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
color: #6b7280; /* Tailwind gray-500 */
}
.banke{
background: red;
padding: 0.5rem;
width: 100%;
margin-bottom: 1rem;
display: none;
&.show{
display: block;
}
}
.modal-payment{
background: rgba(0,0,0,0.5);
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
.iframe-container {
background: var(--color-gray-800);
width: 50%;
height: 90%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
iframe {
width: 100%;
height: 100%;
}
}
}
.cgv-content{
width: 50%;
margin-left: auto;
margin-right: auto;
background: var(--color-gray-800);
padding: 0.5rem;
h2 {
text-align: center;
font-weight: bolder;
font-size: 2.5rem;
margin-bottom: 2rem;
}
p {
}
}
.max-h-250 {
max-height: 50vh;
height: 50vh;
}

View File

@@ -1,203 +0,0 @@
export class AutoCustomer extends HTMLButtonElement {
connectedCallback() {
const modalHTML = `
<style>
.modal {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.85);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.modal.hidden {
display: none;
}
.modal-content {
background: #1f2937; /* gray-800 */
border-radius: 0.5rem;
padding: 1.5rem;
max-width: 28rem;
width: 100%;
position: relative;
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.5),
0 4px 6px -2px rgba(0,0,0,0.4);
color: #f9fafb; /* gray-50 */
font-family: system-ui, sans-serif;
}
.close-btn {
position: absolute;
top: 0.5rem;
right: 0.75rem;
background: transparent;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #9ca3af; /* gray-400 */
}
.close-btn:hover {
color: #f9fafb;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: #d1d5db; /* gray-300 */
}
input[type="text"] {
width: 100%;
padding: 0.5rem 0.75rem;
border: 1px solid #374151; /* gray-700 */
border-radius: 0.375rem;
margin-bottom: 1rem;
font-size: 1rem;
background-color: #111827; /* gray-900 */
color: #f9fafb; /* gray-50 */
box-sizing: border-box;
}
input[type="text"]::placeholder {
color: #6b7280; /* gray-500 */
}
button.submit-btn {
background-color: #3b82f6; /* blue-500 */
color: white;
padding: 0.5rem 1rem;
font-weight: 600;
border: none;
border-radius: 0.375rem;
cursor: pointer;
transition: background-color 0.3s ease;
}
button.submit-btn:hover {
background-color: #2563eb; /* blue-600 */
}
.result {
margin-top: 1rem;
background-color: #374151; /* gray-700 */
padding: 1rem;
border-radius: 0.375rem;
white-space: pre-wrap;
font-family: monospace, monospace;
max-height: 200px;
overflow-y: auto;
}
.error {
color: #f87171; /* red-400 */
margin-top: 1rem;
}
</style>
<div class="modal hidden" id="siret-modal">
<div class="modal-content" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<button class="close-btn" aria-label="Fermer la fenêtre modale">&times;</button>
<h2 id="modal-title" style="font-size:1.25rem; font-weight:700; margin-bottom:1rem;">Recherche SIRET</h2>
<form id="siret-form">
<label for="siret-input">Numéro SIRET :</label>
<input type="text" id="siret-input" name="siret" maxlength="14" pattern="\\d{14}" placeholder="Ex: 12345678901234" required />
<button type="submit" class="submit-btn">Rechercher</button>
</form>
<div class="result" id="result-container" aria-live="polite"></div>
</div>
</div>
`;
this.insertAdjacentHTML('afterend', modalHTML);
const modal = document.getElementById('siret-modal');
const closeBtn = modal.querySelector('.close-btn');
const form = modal.querySelector('#siret-form');
const input = modal.querySelector('#siret-input');
const resultContainer = modal.querySelector('#result-container');
this.addEventListener('click', e => {
e.preventDefault();
resultContainer.textContent = ''; // reset résultat
modal.classList.remove('hidden');
input.focus();
});
closeBtn.addEventListener('click', () => {
modal.classList.add('hidden');
});
modal.addEventListener('click', e => {
if (e.target === modal) {
modal.classList.add('hidden');
}
});
form.addEventListener('submit', async e => {
e.preventDefault();
const siret = input.value.trim();
resultContainer.textContent = '';
if (!/^\d{14}$/.test(siret)) {
resultContainer.innerHTML = `<div class="error">Veuillez entrer un numéro SIRET valide à 14 chiffres.</div>`;
return;
}
resultContainer.textContent = 'Recherche en cours...';
try {
const response = await fetch(`/api-interne/intranet/customer/auto/${siret}`, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
if (!response.ok) {
throw new Error(`Erreur API: ${response.status}`);
}
const data = await response.json();
if(data.error != undefined) {
resultContainer.innerHTML = `<div class="error">Erreur lors de la recherche : Aucune information non trouvée</div>`;
input.value = "";
input.setAttribute('input',"")
} else {
if(data.etat) {
let customer_raisonSocial = document.body.querySelector('#customer_raisonSocial');
customer_raisonSocial.setAttribute('value',data.name);
customer_raisonSocial.value = data.name;
let customer_siret = document.body.querySelector('#customer_siret');
customer_siret.setAttribute('value',data.siret);
customer_siret.value = data.siret;
let customer_ape = document.body.querySelector('#customer_ape');
customer_ape.setAttribute('value',data.ape);
customer_ape.value = data.ape;
let customer_rna = document.body.querySelector('#customer_rna');
customer_rna.setAttribute('value',data.rna);
customer_rna.value = data.rna;
let customer_address = document.body.querySelector('#customer_address');
customer_address.setAttribute('value',data.num);
customer_address.value = data.num;
let customer_zipcode = document.body.querySelector('#customer_zipcode');
customer_zipcode.setAttribute('value',data.zipcode);
customer_zipcode.value = data.zipcode;
let customer_city = document.body.querySelector('#customer_city');
customer_city.setAttribute('value',data.comune);
customer_city.value = data.comune;
modal.classList.add('hidden');
} else {
resultContainer.innerHTML = `<div class="error">Erreur lors de la recherche : Entreprise FERMER</div>`;
input.value = "";
input.setAttribute('input',"")
}
}
} catch (error) {
resultContainer.innerHTML = `<div class="error">Erreur lors de la recherche : ${error.message}</div>`;
}
});
}
}

View File

@@ -1,26 +0,0 @@
export class AutoSubmit extends HTMLFormElement{
connectedCallback() {
const form = this; // Reference to the form element
// Get all input elements within this form
// We're interested in text, number, and other common input types
const inputs = form.querySelectorAll('input:not([type="submit"]):not([type="button"]):not([type="reset"]), select, textarea');
// Add an event listener to each input element
inputs.forEach(input => {
input.addEventListener('input', () => {
// Display a message that the form is being submitted
const messageBox = document.getElementById('submissionMessage');
if (messageBox) {
messageBox.style.display = 'block';
messageBox.textContent = 'Form submitted automatically!';
// Optionally hide the message after a short delay
setTimeout(() => {
messageBox.style.display = 'none';
}, 2000);
}
form.submit();
});
});
}
}

View File

@@ -1,123 +0,0 @@
export class ConfirmModal extends HTMLAnchorElement{
connectedCallback() {
let element = this;
element.addEventListener('click',btn=>{
btn.preventDefault();
let modalConfirm = document.createElement('confirm-modal');
modalConfirm.innerHTML = `<div class="confirm-modal-content"></div>`;
if(element.getAttribute('type') == "cp-customer") {
this.copyCustomer(modalConfirm,element.getAttribute('href'));
}
if(element.getAttribute('type') == "delete-customer") {
this.deleteCustomer(modalConfirm,element.getAttribute('href'));
}
if(element.getAttribute('type') == "delete-email") {
this.deleteEmail(modalConfirm,element.getAttribute('href'));
}
if(element.getAttribute('type') == "delete-esyweb-tuto") {
this.deleteEsyWebTuto(modalConfirm,element.getAttribute('href'));
}
document.body.appendChild(modalConfirm);
})
}
deleteEsyWebTuto(modalConfirm,link) {
let message = document.createElement('h2');
message.innerText = "Confirmer la suppression du tutoriel";
modalConfirm.querySelector('.confirm-modal-content').appendChild(message);
let grid = document.createElement('div')
grid.classList = "grid grid-cols-1 gap-4 md:grid-cols-2";
modalConfirm.querySelector('.confirm-modal-content').appendChild(grid);
let buttonOk = document.createElement('button');
buttonOk.classList = "bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded";
buttonOk.innerText = "Oui";
buttonOk.addEventListener('click',()=>{
modalConfirm.remove()
location.href = link;
})
let buttonKo = document.createElement('button');
buttonKo.classList = "bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded";
buttonKo.innerText = "Non";
buttonKo.addEventListener('click',()=>modalConfirm.remove())
grid.appendChild(buttonOk)
grid.appendChild(buttonKo)
}
deleteEmail(modalConfirm,link) {
let message = document.createElement('h2');
message.innerText = "Confirmer la suppression de l'email";
modalConfirm.querySelector('.confirm-modal-content').appendChild(message);
let grid = document.createElement('div')
grid.classList = "grid grid-cols-1 gap-4 md:grid-cols-2";
modalConfirm.querySelector('.confirm-modal-content').appendChild(grid);
let buttonOk = document.createElement('button');
buttonOk.classList = "bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded";
buttonOk.innerText = "Oui";
buttonOk.addEventListener('click',()=>{
modalConfirm.remove()
location.href = link;
})
let buttonKo = document.createElement('button');
buttonKo.classList = "bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded";
buttonKo.innerText = "Non";
buttonKo.addEventListener('click',()=>modalConfirm.remove())
grid.appendChild(buttonOk)
grid.appendChild(buttonKo)
}
deleteCustomer(modalConfirm,link) {
let message = document.createElement('h2');
message.innerText = "Confirmer la suppression du client";
modalConfirm.querySelector('.confirm-modal-content').appendChild(message);
let grid = document.createElement('div')
grid.classList = "grid grid-cols-1 gap-4 md:grid-cols-2";
modalConfirm.querySelector('.confirm-modal-content').appendChild(grid);
let buttonOk = document.createElement('button');
buttonOk.classList = "bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded";
buttonOk.innerText = "Oui";
buttonOk.addEventListener('click',()=>{
modalConfirm.remove()
location.href = link;
})
let buttonKo = document.createElement('button');
buttonKo.classList = "bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded";
buttonKo.innerText = "Non";
buttonKo.addEventListener('click',()=>modalConfirm.remove())
grid.appendChild(buttonOk)
grid.appendChild(buttonKo)
}
copyCustomer(modalConfirm,link) {
let message = document.createElement('h2');
message.innerText = "Confirmer la copie du client";
modalConfirm.querySelector('.confirm-modal-content').appendChild(message);
let grid = document.createElement('div')
grid.classList = "grid grid-cols-1 gap-4 md:grid-cols-2";
modalConfirm.querySelector('.confirm-modal-content').appendChild(grid);
let buttonOk = document.createElement('button');
buttonOk.classList = "bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded";
buttonOk.innerText = "Oui";
buttonOk.addEventListener('click',()=>{
modalConfirm.remove()
location.href = link;
})
let buttonKo = document.createElement('button');
buttonKo.classList = "bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded";
buttonKo.innerText = "Non";
buttonKo.addEventListener('click',()=>modalConfirm.remove())
grid.appendChild(buttonOk)
grid.appendChild(buttonKo)
}
}

View File

@@ -1,14 +0,0 @@
export class IpWall extends HTMLElement {
connectedCallback() {
if (!document.querySelector('security-wall-item')) {
let wall = document.createElement('security-wall-item');
wall.innerHTML = `
<div class="content">
<h2><warn>/!\\ </warn> - Protection MAINFRAME - <warn>/!\\ </warn></h2>
<span>Votre IP n'est pas autorisée par le système !</span>
</div>
`;
document.body.appendChild(wall);
}
}
}

View File

@@ -1,25 +0,0 @@
export class LockdownWall extends HTMLElement {
connectedCallback() {
fetch("/artemis/lockdown")
.then((r) => r.json())
.then((result) => {
if(result.lockdown) {
if (!document.querySelector('lockdown-wall-item')) {
let sound = new Audio("/sound/alert.mp3")
let wall = document.createElement('lockdown-wall-item');
wall.innerHTML = `
<div class="content" style="padding: 20px; background: #ffcccc; color: #900; font-weight: bold; text-align: center; border: 2px solid #900; border-radius: 8px; max-width: 600px; margin: 30px auto; font-family: Arial, sans-serif;">
<h2><warn>/!\\ </warn> - Protection MAINFRAME - <warn>/!\\ </warn></h2>
<p>Verrouillage complet de l'application est en cours, aucune action n'est possible.</p>
</div>
`;
document.body.appendChild(wall);
setInterval(() => {
sound.play();
}, 30000)
}
}
});
}
}

View File

@@ -1,23 +0,0 @@
export class OrderCtrl extends HTMLDivElement{
connectedCallback(){
let element = this;
let selectType = this.querySelector('select[name="type"]');
let inputNum = this.querySelector('input[name="num"]');
fetch("/api-interne/intranet/customer/order/num?type=avis")
.then(response => response.json())
.then(data => {
inputNum.setAttribute('value',data.num)
inputNum.value = data.num;
})
selectType.addEventListener('change', (event)=>{
fetch("/api-interne/intranet/customer/order/num?type="+event.target.value)
.then(response => response.json())
.then(data => {
inputNum.setAttribute('value',data.num)
inputNum.value = data.num;
})
})
}
}

View File

@@ -1,225 +0,0 @@
export class PaymentVirement extends HTMLButtonElement{
connectedCallback(){
let element = this;
element.addEventListener('click', function(e){
e.preventDefault();
let displayModal = document.createElement('div');
displayModal.classList.add('modal-payment');
let iframeContainer = document.createElement('div');
iframeContainer.style.height = "fit-content";
iframeContainer.classList.add(
'iframe-container',
'max-w-md',
'mx-auto',
'bg-white',
'dark:bg-gray-900',
'rounded-xl',
'shadow-md',
'overflow-hidden',
'p-6',
'space-y-4'
);
// Message d'invitation au virement
let infoMsg = document.createElement('div');
infoMsg.className = 'text-xl text-white-700 dark:text-white-300 mb-2';
infoMsg.textContent = "Merci d'effectuer le virement sur ce compte, en notant la référence de l'avis de paiement ! Dés réception du règlement une facture vous sera envoyée";
iframeContainer.appendChild(infoMsg);
let ibanLabel = document.createElement('div');
ibanLabel.className = 'text-gray-700 dark:text-gray-300 text-base font-semibold';
ibanLabel.textContent = 'IBAN';
let ibanValue = document.createElement('div');
ibanValue.className = 'text-gray-900 dark:text-white text-lg font-mono break-all';
ibanValue.textContent = 'FR76 1020 6006 7198 4797 7981 061';
let bicLabel = document.createElement('div');
bicLabel.className = 'text-gray-700 dark:text-gray-300 text-base font-semibold';
bicLabel.textContent = 'BIC';
let bicValue = document.createElement('div');
bicValue.className = 'text-gray-900 dark:text-white text-lg font-mono';
bicValue.textContent = 'AGRIFRPP802';
let btn = document.createElement('a');
btn.setAttribute('href', '/paiement?id='+element.getAttribute('id')+"&type=virement");
btn.classList = "button bg-green-900 w-full text-center text-white p-2";
btn.innerText = "Je confirme le paiement par virement bancaire"
iframeContainer.appendChild(ibanLabel);
iframeContainer.appendChild(ibanValue);
iframeContainer.appendChild(bicLabel);
iframeContainer.appendChild(bicValue);
iframeContainer.appendChild(btn);
document.body.appendChild(iframeContainer);
displayModal.appendChild(iframeContainer);
document.body.appendChild(displayModal);
})
}
}
export class PaymentChaque extends HTMLButtonElement{
connectedCallback(){
let element = this;
element.addEventListener('click', function(e){
e.preventDefault();
let displayModal = document.createElement('div');
displayModal.classList.add('modal-payment');
let iframeContainer = document.createElement('div');
iframeContainer.style.height = "fit-content";
iframeContainer.classList.add(
'iframe-container',
'max-w-md',
'mx-auto',
'bg-white',
'dark:bg-gray-900',
'rounded-xl',
'shadow-md',
'overflow-hidden',
'p-6',
'space-y-4'
);
// Message d'invitation au virement
let infoMsg = document.createElement('div');
infoMsg.className = 'text-xl text-white-700 dark:text-white-300 mb-2';
infoMsg.textContent = "Merci d'envoie le chéque à l'adresse suivant en notant la référence de l'avis de paiement aux dos ! Dés réception du chéque et sont incaisement une facture vous sera envoyée";
iframeContainer.appendChild(infoMsg);
let ibanLabel = document.createElement('div');
ibanLabel.className = 'text-gray-700 dark:text-gray-300 text-base font-semibold';
ibanLabel.textContent = 'Adresse';
let ibanValue = document.createElement('div');
ibanValue.className = 'text-gray-900 dark:text-white text-lg font-mono break-all';
ibanValue.textContent = '27 rue le Sérurier 02100 Saint-Quentin';
let bicLabel = document.createElement('div');
bicLabel.className = 'text-gray-700 dark:text-gray-300 text-base font-semibold';
bicLabel.textContent = 'A l\'ordre de ';
let bicValue = document.createElement('div');
bicValue.className = 'text-gray-900 dark:text-white text-lg font-mono';
bicValue.textContent = 'SARL SITECONSEIL';
let btn = document.createElement('a');
btn.setAttribute('href', '/paiement?id='+element.getAttribute('id')+"&type=bank");
btn.classList = "button bg-green-900 w-full text-center text-white p-2";
btn.innerText = "Je confirme le paiement par chéque"
iframeContainer.appendChild(ibanLabel);
iframeContainer.appendChild(ibanValue);
iframeContainer.appendChild(bicLabel);
iframeContainer.appendChild(bicValue);
iframeContainer.appendChild(btn);
document.body.appendChild(iframeContainer);
displayModal.appendChild(iframeContainer);
document.body.appendChild(displayModal);
})
}
}
export class PaymentPage extends HTMLButtonElement{
connectedCallback(){
let element = this;
element.addEventListener('click', function(){
let banke = document.querySelector('.banke');
banke.classList.remove('show');
let displayModal = document.createElement('div');
displayModal.classList.add('modal-payment');
let iframeContainer = document.createElement('div');
iframeContainer.classList.add('iframe-container');
window.addEventListener('message', function (event) {
if (event.origin !== 'https://payment.stancer.com') {
return;
}
if(event.data.status != undefined) {
if(event.data.status != "init" && event.data.status != "pending" && event.data.status != "secure-auth-start" && event.data.status != "secure-auth-end") {
if (event.data.status == "paid") {
displayModal.remove();
location.href = "/paiement/complete?id=" + element.getAttribute('id');
} else if (event.data.status == "finished") {
displayModal.remove();
location.href = event.data.url;
} else {
fetch("/api-interne/intranet/customer/payment/cancel?id="+element.getAttribute('id'))
displayModal.remove();
banke.classList.add('show');
}
}
}
console.log(event.data);
});
fetch("/api-interne/intranet/customer/payment?id="+element.getAttribute('id'))
.then(r=>r.json())
.then(r=>{
let iframe = document.createElement('iframe');
iframe.src = r.url;
iframeContainer.appendChild(iframe);
window.frame = iframeContainer;
})
displayModal.appendChild(iframeContainer);
document.body.appendChild(displayModal);
})
}
}
export class PaymentSepa extends HTMLButtonElement{
connectedCallback(){
let element = this;
element.addEventListener('click', function(){
let banke = document.querySelector('.banke');
banke.classList.remove('show');
let displayModal = document.createElement('div');
displayModal.classList.add('modal-payment');
let iframeContainer = document.createElement('div');
iframeContainer.classList.add('iframe-container');
window.addEventListener('message', function (event) {
if (event.origin !== 'https://payment.stancer.com') {
return;
}
if(event.data.status != undefined) {
if(event.data.status != "init" && event.data.status != "pending" && event.data.status != "secure-auth-start" && event.data.status != "secure-auth-end") {
if (event.data.status == "paid") {
displayModal.remove();
location.href = "/paiement/complete?id=" + element.getAttribute('id');
} else if (event.data.status == "finished") {
displayModal.remove();
location.href = event.data.url;
} else {
fetch("/api-interne/intranet/customer/payment/cancel?id="+element.getAttribute('id'))
displayModal.remove();
banke.classList.add('show');
}
}
}
console.log(event.data);
});
fetch("/api-interne/intranet/customer/payment?id="+element.getAttribute('id')+"&type=sepa")
.then(r=>r.json())
.then(r=>{
let iframe = document.createElement('iframe');
iframe.src = r.url;
iframeContainer.appendChild(iframe);
window.frame = iframeContainer;
})
displayModal.appendChild(iframeContainer);
document.body.appendChild(displayModal);
})
}
}

View File

@@ -1,223 +0,0 @@
export class RegisterPayment extends HTMLButtonElement {
connectedCallback() {
let element = this;
element.addEventListener('click', (event) => {
event.preventDefault();
const advertId = element.getAttribute('id');
let modal = document.createElement('div');
// Classes de fond du modal Dark Mode
modal.classList.add("modal-payment", "fixed", "inset-0", "bg-gray-900", "bg-opacity-75", "flex", "items-center", "justify-center", "z-50");
modal.innerHTML = `
<div class="modal-payment-content dark:bg-gray-800 bg-white shadow-2xl rounded-lg p-6 relative" style="max-width: 900px; width: 90%; max-height: 90vh; overflow-y: auto;">
<h2 class="text-xl font-bold dark:text-white mb-4">Enregistrer un paiement</h2>
<a class="block dbclose bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded" style="cursor: pointer; position: absolute; top: 10px; right: 10px;">Fermer</a>
<form method="post" class="content mb-6">
<div class="flex space-x-4 w-full">
<fieldset class="form-group form-group--horizontal w-full">
<div class="flex space-x-4">
<div class="flex-1">
<div class="form-field">
<div class="mb-1">
<label for="type" class="block mb-2 text-sm font-medium dark:text-gray-300 text-gray-900">Type</label>
<select name="type" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
<option value="CB">Carte Bancaire</option>
<option value="PREV">Prélèvement</option>
<option value="CH">Chèque</option>
<option value="ESP">Espèce</option>
<option value="VIR">Virement</option>
</select>
</div>
</div>
</div>
<div class="flex-1">
<div class="form-field">
<div class="mb-1">
<label for="date" class="block mb-2 text-sm font-medium dark:text-gray-300 text-gray-900">Date</label>
<input name="date" type="date" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
</div>
</div>
<div class="flex-1">
<div class="form-field">
<div class="mb-1">
<label for="amount" class="block mb-2 text-sm font-medium dark:text-gray-300 text-gray-900">Montant</label>
<input name="amount" type="number" step="0.01" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required />
</div>
</div>
</div>
<div class="flex-1">
<div class="form-field">
<div class="mb-1">
<label for="num_cheque" class="block mb-2 text-sm font-medium dark:text-gray-300 text-gray-900">Numéro de remise de chèque</label>
<input name="num_cheque" type="text" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" />
</div>
</div>
</div>
</div>
</fieldset>
</div>
<button type="submit" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-semibold px-4 py-2 rounded mt-3">Enregistrer</button>
</form>
<h3 class="mt-6 text-lg font-semibold dark:text-white border-t border-gray-700 pt-4">Historique des paiements</h3>
<div class="overflow-x-auto">
<table id="payment-table" class="min-w-full divide-y dark:divide-gray-700 divide-gray-200">
<thead>
<tr>
<th class="px-6 py-3 dark:bg-gray-700 bg-gray-100 text-left text-xs font-medium dark:text-gray-300 text-gray-500 uppercase tracking-wider">Date</th>
<th class="px-6 py-3 dark:bg-gray-700 bg-gray-100 text-left text-xs font-medium dark:text-gray-300 text-gray-500 uppercase tracking-wider">Type</th>
<th class="px-6 py-3 dark:bg-gray-700 bg-gray-100 text-left text-xs font-medium dark:text-gray-300 text-gray-500 uppercase tracking-wider">Montant</th>
<th class="px-6 py-3 dark:bg-gray-700 bg-gray-100 text-left text-xs font-medium dark:text-gray-300 text-gray-500 uppercase tracking-wider">Réf. Chèque</th>
<th class="px-6 py-3 dark:bg-gray-700 bg-gray-100 text-right text-xs font-medium dark:text-gray-300 text-gray-500 uppercase tracking-wider">Action</th>
</tr>
</thead>
<tbody class="dark:bg-gray-800 bg-white divide-y dark:divide-gray-700 divide-gray-200">
<tr id="loading-row"><td colspan="6" class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-400 text-gray-500 text-center">Chargement...</td></tr>
</tbody>
</table>
</div>
</div>
`;
const paymentTableBody = modal.querySelector('#payment-table tbody');
/**
* Fonction pour récupérer et afficher la liste des paiements.
*/
const loadPayments = () => {
paymentTableBody.innerHTML = '<tr id="loading-row"><td colspan="6" class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-400 text-gray-500 text-center">Chargement...</td></tr>';
fetch(`/api-interne/intranet/customer/register?idPayment=${advertId}`)
.then(response => {
if (!response.ok) {
throw new Error('Erreur lors de la récupération des paiements (code: ' + response.status + ')');
}
return response.json();
})
.then((listPayment) => {
paymentTableBody.innerHTML = '';
if (listPayment && listPayment.length > 0) {
listPayment.forEach(payment => {
const tr = document.createElement('tr');
const date = new Date(payment.date).toLocaleDateString();
// Classes pour les lignes (alternance des couleurs en dark mode)
tr.classList.add('hover:bg-gray-700');
tr.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-300 text-gray-500">${date}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-300 text-gray-500">${payment.type}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-bold text-green-400 dark:text-green-400">${parseFloat(payment.amount).toFixed(2)} €</td>
<td class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-300 text-gray-500">${payment.num_cheque || ''}</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button data-payment-id="${payment.id}" class="delete-payment-btn text-red-500 hover:text-red-400 dark:text-red-400 dark:hover:text-red-300">Supprimer</button>
</td>
`;
paymentTableBody.appendChild(tr);
});
modal.querySelectorAll('.delete-payment-btn').forEach(button => {
button.addEventListener('click', (e) => {
const paymentId = e.currentTarget.dataset.paymentId;
deletePayment(paymentId, loadPayments);
});
});
} else {
paymentTableBody.innerHTML = '<tr><td colspan="6" class="px-6 py-4 whitespace-nowrap text-sm dark:text-gray-400 text-gray-500 text-center">Aucun paiement enregistré pour le moment.</td></tr>';
}
})
.catch(error => {
console.error("Erreur de chargement des paiements:", error);
paymentTableBody.innerHTML = `<tr><td colspan="6" class="px-6 py-4 whitespace-nowrap text-sm text-red-500 text-center">Erreur lors du chargement: ${error.message}</td></tr>`;
});
};
/**
* Fonction pour envoyer la requête de suppression de paiement.
*/
const deletePayment = (paymentId, callback) => {
if (!confirm(`Êtes-vous sûr de vouloir supprimer le paiement ?`)) {
return;
}
fetch(`/api-interne/intranet/customer/payment/${paymentId}`, {
method: 'DELETE',
})
.then(response => {
if (!response.ok) {
throw new Error('Échec de la suppression.');
}
return response.json();
})
.then(() => {
alert('Paiement supprimé avec succès.');
callback(); // Recharger la liste des paiements
})
.catch(error => {
console.error("Erreur de suppression:", error);
alert(`Erreur lors de la suppression du paiement: ${error.message}`);
});
};
// 1. Charger les paiements lors de l'ouverture du modal
loadPayments();
// 2. Écouteur pour la fermeture du modal
modal.querySelector('.dbclose').addEventListener('click', () => {
modal.remove();
})
// 3. Écouteur pour l'enregistrement d'un nouveau paiement
modal.querySelector('form').addEventListener('submit', (e) => {
e.preventDefault();
const formData = {};
const formElements = e.target.elements;
for (let i = 0; i < formElements.length; i++) {
const el = formElements[i];
if (el.name) {
formData[el.name] = el.value;
}
}
formData['idAdvert'] = advertId;
let inputs = [];
Object.keys(formData).forEach(key => inputs.push({ name: key, val: formData[key] }));
fetch("/api-interne/intranet/customer/register", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(inputs),
})
.then(response => {
if (!response.ok) {
return response.json().then(err => { throw new Error(err.message || 'Erreur lors de l\'enregistrement'); });
}
return response.json();
})
.then(() => {
loadPayments();
e.target.reset();
})
.catch(error => {
console.error("Erreur lors de l'enregistrement:", error);
alert("Une erreur est survenue lors de l'enregistrement du paiement: " + error.message);
});
})
document.body.appendChild(modal);
})
}
}

View File

@@ -1,127 +0,0 @@
import Sortable from 'sortablejs';
export class RepeatLine extends HTMLDivElement{
connectedCallback(){
this.$props = this.getProps(this, { maxRows: 5 });
this.$refs = this.getRefs(this);
this.rowHTML = this.$refs.rows.children[0].outerHTML;
this.init();
}
// Hook up events for the row.
setUpRow(row) {
const rowRefs = this.getRefs(row);
rowRefs.removeButton.onclick = (e) => {
e.preventDefault();
this.removeRow(row);
};
}
// Enable or disable addButton as necessary.
updateAddButton() {
if (this.$refs.rows.children.length >= this.$props.maxRows) {
this.$refs.addButton.setAttribute('disabled', '');
return;
}
this.$refs.addButton.removeAttribute('disabled');
}
// Update array key values to the row number
updateFieldNames() {
[...this.$refs.rows.children]
.forEach((el, index) => {
el.querySelectorAll('[name]')
.forEach(el => {
const newName = el.getAttribute('name').replace(/\[\d\]/gm, `[${index}]`);
el.setAttribute('name', newName);
});
});
}
addRow() {
if (
!this.rowHTML ||
this.$refs.rows.children.length >= this.$props.maxRows
) return;
let newRow = this.createFromHTML(this.rowHTML);
newRow.removeAttribute('id');
this.setUpRow(newRow);
this.$refs.rows.appendChild(newRow);
newRow.querySelector('input,textarea,select').focus();
newRow.querySelectorAll('input,textarea,select').forEach(el=>{
el.setAttribute('value','');
el.value = "";
})
this.updateFieldNames();
this.updateAddButton();
}
removeRow(row) {
if (this.$refs.rows.children.length <= 1) return;
row.remove();
this.$refs.rows.focus();
this.updateFieldNames();
this.updateFieldNames();
}
init() {
this.setUpRow(this.$refs.rows.children[0]);
this.$refs.addButton.onclick = (e) => {
e.preventDefault();
this.addRow();
}
this.updateFieldNames();
let repeater__rows = this.querySelector('.form-repeater__rows');
new Sortable(repeater__rows,{
});
}
// Return an object that contains references to DOM objects.
getRefs(el) {
let result = {};
[...el.querySelectorAll('[data-ref]')]
.forEach(ref => {
result[ref.dataset.ref] = ref;
});
return result;
}
setDefaults(obj, defaults) {
let results = obj;
for (const prop in defaults) {
if (!obj.hasOwnProperty(prop)) {
results[prop] = defaults[prop];
}
}
return results;
}
getProps(el, defaults={}) {
return this.setDefaults(
JSON.parse(el.dataset.props ?? '{}'),
defaults
);
}
createFromHTML(html='') {
let element = document.createElement(null);
element.innerHTML = html;
return element.firstElementChild;
}
}

View File

@@ -1,10 +0,0 @@
import TomSelect from "tom-select";
export class SearchCustomer extends HTMLSelectElement{
connectedCallback() {
let element = this;
new TomSelect(element,{
create: false
});
}
}

View File

@@ -1,40 +0,0 @@
export class SecurityWall extends HTMLElement {
connectedCallback() {
this.render();
// Ecoute globale pour Alt+P
window.addEventListener('keydown', (event) => {
if (event.altKey && event.key.toLowerCase() === 'p') {
this.toggleWall();
}
});
}
render() {
const isEnabled = localStorage.getItem('mainframe-wallsecurity') === 'true';
if (!isEnabled) {
// Retirer si déjà présent
const existing = document.querySelector('security-wall-item');
if (existing) existing.remove();
return;
}
// Ajouter seulement si pas déjà présent
if (!document.querySelector('security-wall-item')) {
let wall = document.createElement('security-wall-item');
wall.innerHTML = `
<div class="content">
<h2><warn>/!\\ </warn> - Protection MAINFRAME - <warn>/!\\ </warn></h2>
<span>Filtre de confidentialité activée</span>
</div>
`;
document.body.appendChild(wall);
}
}
toggleWall() {
const current = localStorage.getItem('mainframe-wallsecurity') === 'true';
localStorage.setItem('mainframe-wallsecurity', current ? 'false' : 'true');
this.render();
}
}

View File

@@ -1,75 +0,0 @@
export class ServerCard extends HTMLDivElement{
connectedCallback() {
let element = this;
this.s = element.querySelector('.s');
this.cpu = element.querySelector('.cpu');
this.ram = element.querySelector('.ram');
this.hdd = element.querySelector('.hdd');
setInterval(()=>{
this.update()
},5000)
this.update()
}
update() {
let mqttClient = mqtt.connect('wss://wsmqtt.esy-web.dev');
mqttClient.on("connect", () => {
mqttClient.subscribe('server/'+this.getAttribute('id')+'/metric')
mqttClient.subscribe('server/'+this.getAttribute('id')+'/online')
});
mqttClient.on("message", (topic, message) => {
if(topic == "server/"+this.getAttribute('id')+"/online") {
console.log(topic,message.toString());
let json = JSON.parse(message.toString());
if(json.status) {
this.s.classList = "s font-semibold bg-RUNNING";
this.s.innerText = "RUNNING";
} else {
this.s.classList = "s font-semibold bg-STOPPED";
this.s.innerText = "STOPPED";
}
}
if(topic == "server/"+this.getAttribute('id')+"/metric") {
let json = JSON.parse(message.toString());
this.cpu.querySelector('.p').innerText = json.cpu + "%";
this.cpu.querySelector('.gauge >div').style.width = json.cpu + "%";
if (json.cpu <= 70) {
this.cpu.querySelector('.gauge >div').classList = "bg-green-500 h-2 rounded-l-full";
}
if (json.cpu>=71 && json.cpu <=90) {
this.cpu.querySelector('.gauge >div').classList = "bg-orange-500 h-2 rounded-l-full";
}
if (json.cpu>=91) {
this.cpu.querySelector('.gauge >div').classList = "bg-red-500 h-2 rounded-l-full";
}
this.ram.querySelector('.p').innerText = json.memory + "%";
this.ram.querySelector('.gauge >div').style.width = json.memory + "%";
if (json.memory <= 70) {
this.ram.querySelector('.gauge >div').classList = "bg-green-500 h-2 rounded-l-full";
}
if (json.memory>=71 && json.memory <=90) {
this.ram.querySelector('.gauge >div').classList = "bg-orange-500 h-2 rounded-l-full";
}
if (json.ram>=91) {
this.ram.querySelector('.gauge >div').classList = "bg-red-500 h-2 rounded-l-full";
}
this.hdd.querySelector('.p').innerText = json.disk + "%";
this.hdd.querySelector('.gauge >div').style.width = json.disk + "%";
if (json.disk <= 70) {
this.hdd.querySelector('.gauge >div').classList = "bg-green-500 h-2 rounded-l-full";
}
if (json.disk>=71 && json.disk <=90) {
this.hdd.querySelector('.gauge >div').classList = "bg-orange-500 h-2 rounded-l-full";
}
if (json.disk>=91) {
this.hdd.querySelector('.gauge >div').classList = "bg-red-500 h-2 rounded-l-full";
}
}
});
}
}

View File

@@ -1,55 +0,0 @@
Software License Agreement
==========================
**CKEditor&nbsp;5** (https://github.com/ckeditor/ckeditor5)<br>
Copyright (c) 20032025, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
Licensed under a dual-license model, this software is available under:
* the [GNU General Public License Version 2 or later](https://www.gnu.org/licenses/gpl.html) (see COPYING.GPL),
* or commercial license terms from CKSource Holding sp. z o.o.
For more information, see: [https://ckeditor.com/legal/ckeditor-licensing-options](https://ckeditor.com/legal/ckeditor-licensing-options).
If you are using CKEditor under commercial terms, you are free to remove the COPYING.GPL file with the full copy of a GPL license.
Sources of Intellectual Property Included in CKEditor
-----------------------------------------------------
Where not otherwise indicated, all CKEditor content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor will incorporate work done by developers outside of CKSource with their express permission.
The following libraries are included in CKEditor under the [MIT license](https://opensource.org/licenses/MIT):
* @types/color-convert - Copyright (c) DefinitelyTyped.
* blurhash - Copyright (c) Wolt Enterprises.
* color-convert - Copyright (c) 20112016 Heather Arthur <fayearthur@gmail.com>, copyright (c) 20162021 Josh Junon <josh@junon.me>.
* color-parse - Copyright (c) 2015 Dmitry Ivanov.
* emojibase-data - Copyright (c) 2017-2019 Miles Johnson.
* es-toolkit - Copyright (c) 2024 Viva Republica, Inc.
* fuzzysort - Copyright (c) 2018 Stephen Kamenar.
* is-emoji-supported - Copyright (c) 2016-2020 Koala Interactive, Inc.
* vanilla-colorful - Copyright (c) 2020 Serhii Kulykov <iamkulykov@gmail.com>.
* Regular Expression for URL validation - Copyright (c) 2010-2018 Diego Perini.
* @types/hast - Copyright (c) Microsoft Corporation.
* hast-util-to-html - Copyright (c) Titus Wormer <tituswormer@gmail.com>
* hast-util-to-mdast - Copyright (c) Titus Wormer <tituswormer@gmail.com> and Copyright (c) Seth Vincent <sethvincent@gmail.com>
* hastscript - Copyright (c) Titus Wormer <tituswormer@gmail.com>
* rehype-remark - Copyright (c) Titus Wormer <tituswormer@gmail.com>
* remark-breaks - Copyright (c) 2017 Titus Wormer <tituswormer@gmail.com>
* remark-gfm - Copyright (c) Titus Wormer <tituswormer@gmail.com>
* remark-parse - Copyright (c) 2014 Titus Wormer <tituswormer@gmail.com>
* remark-rehype - Copyright (c) Titus Wormer <tituswormer@gmail.com>
* remark-stringify - Copyright (c) 2014 Titus Wormer <tituswormer@gmail.com>
* unified - Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>
* unist-util-visit - Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>
The following libraries are included in CKEditor under the [ISC license](https://opensource.org/license/isc-license-txt):
* hast-util-from-dom - Copyright (c) Keith McKnight <keith@mcknig.ht>
* rehype-dom-parse - Copyright (c) 2018 Keith McKnight <keith@mcknig.ht>
* rehype-dom-stringify - Copyright (c) 2018 Keith McKnight <keith@mcknig.ht>
Trademarks
----------
**CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,409 +0,0 @@
/**
* tom-select.css (v2.4.3)
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at:
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
* ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*
*/
.ts-control {
border: 1px solid #d0d0d0;
padding: 8px 8px;
width: 100%;
overflow: hidden;
position: relative;
z-index: 1;
box-sizing: border-box;
box-shadow: none;
border-radius: 3px;
display: flex;
flex-wrap: wrap;
}
.full .ts-control {
background-color: #fff;
}
.disabled .ts-control, .disabled .ts-control * {
cursor: default !important;
}
.focus .ts-control {
box-shadow: none;
}
.ts-control > * {
vertical-align: baseline;
display: inline-block;
}
.ts-wrapper.multi .ts-control > div {
cursor: pointer;
margin: 0 3px 3px 0;
padding: 2px 6px;
background: #f2f2f2;
color: #303030;
border: 0 solid #d0d0d0;
}
.ts-wrapper.multi .ts-control > div.active {
background: #e8e8e8;
color: #303030;
border: 0 solid #cacaca;
}
.ts-wrapper.multi.disabled .ts-control > div, .ts-wrapper.multi.disabled .ts-control > div.active {
color: rgb(124.5, 124.5, 124.5);
background: white;
border: 0 solid white;
}
.ts-control > input {
flex: 1 1 auto;
min-width: 7rem;
display: inline-block !important;
padding: 0 !important;
min-height: 0 !important;
max-height: none !important;
max-width: 100% !important;
margin: 0 !important;
text-indent: 0 !important;
border: 0 none !important;
background: none !important;
line-height: inherit !important;
-webkit-user-select: auto !important;
-moz-user-select: auto !important;
-ms-user-select: auto !important;
user-select: auto !important;
box-shadow: none !important;
}
.ts-control > input::-ms-clear {
display: none;
}
.ts-control > input:focus {
outline: none !important;
}
.has-items .ts-control > input {
margin: 0 4px !important;
}
.ts-control.rtl {
text-align: right;
}
.ts-control.rtl.single .ts-control:after {
left: 15px;
right: auto;
}
.ts-control.rtl .ts-control > input {
margin: 0 4px 0 -2px !important;
}
.disabled .ts-control {
opacity: 0.5;
background-color: #fafafa;
}
.input-hidden .ts-control > input {
opacity: 0;
position: absolute;
left: -10000px;
}
.ts-dropdown {
position: absolute;
top: 100%;
left: 0;
width: 100%;
z-index: 10;
border: 1px solid #d0d0d0;
background: var(--color-gray-600) !important;
margin: 0.25rem 0 0;
border-top: 0 none;
box-sizing: border-box;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
border-radius: 0 0 3px 3px;
}
.ts-dropdown [data-selectable] {
cursor: pointer;
overflow: hidden;
}
.ts-dropdown [data-selectable] .highlight {
background: rgba(125, 168, 208, 0.2);
border-radius: 1px;
}
.ts-dropdown .option,
.ts-dropdown .optgroup-header,
.ts-dropdown .no-results,
.ts-dropdown .create {
padding: 5px 8px;
}
.ts-dropdown .option, .ts-dropdown [data-disabled], .ts-dropdown [data-disabled] [data-selectable].option {
cursor: inherit;
opacity: 0.5;
}
.ts-dropdown [data-selectable].option {
opacity: 1;
cursor: pointer;
}
.ts-dropdown .optgroup:first-child .optgroup-header {
border-top: 0 none;
}
.ts-dropdown .optgroup-header {
color: #303030;
background: #fff;
cursor: default;
}
.ts-dropdown .active {
background-color: #f5fafd;
color: #495c68;
}
.ts-dropdown .active.create {
color: #495c68;
}
.ts-dropdown .create {
color: rgba(48, 48, 48, 0.5);
}
.ts-dropdown .spinner {
display: inline-block;
width: 30px;
height: 30px;
margin: 5px 8px;
}
.ts-dropdown .spinner::after {
content: " ";
display: block;
width: 24px;
height: 24px;
margin: 3px;
border-radius: 50%;
border: 5px solid #d0d0d0;
border-color: #d0d0d0 transparent #d0d0d0 transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
@keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.ts-dropdown-content {
overflow: hidden auto;
max-height: 200px;
scroll-behavior: smooth;
}
.ts-wrapper.plugin-drag_drop .ts-dragging {
color: transparent !important;
}
.ts-wrapper.plugin-drag_drop .ts-dragging > * {
visibility: hidden !important;
}
.plugin-checkbox_options:not(.rtl) .option input {
margin-right: 0.5rem;
}
.plugin-checkbox_options.rtl .option input {
margin-left: 0.5rem;
}
/* stylelint-disable function-name-case */
.plugin-clear_button {
--ts-pr-clear-button: 1em;
}
.plugin-clear_button .clear-button {
opacity: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: calc(8px - 6px);
margin-right: 0 !important;
background: transparent !important;
transition: opacity 0.5s;
cursor: pointer;
}
.plugin-clear_button.form-select .clear-button, .plugin-clear_button.single .clear-button {
right: max(var(--ts-pr-caret), 8px);
}
.plugin-clear_button.focus.has-items .clear-button, .plugin-clear_button:not(.disabled):hover.has-items .clear-button {
opacity: 1;
}
.ts-wrapper .dropdown-header {
position: relative;
padding: 10px 8px;
border-bottom: 1px solid #d0d0d0;
background: color-mix(#fff, #d0d0d0, 85%);
border-radius: 3px 3px 0 0;
}
.ts-wrapper .dropdown-header-close {
position: absolute;
right: 8px;
top: 50%;
color: #303030;
opacity: 0.4;
margin-top: -12px;
line-height: 20px;
font-size: 20px !important;
}
.ts-wrapper .dropdown-header-close:hover {
color: black;
}
.plugin-dropdown_input.focus.dropdown-active .ts-control {
box-shadow: none;
border: 1px solid #d0d0d0;
}
.plugin-dropdown_input .dropdown-input {
border: 1px solid #d0d0d0;
border-width: 0 0 1px;
display: block;
padding: 8px 8px;
box-shadow: none;
width: 100%;
background: transparent;
}
.plugin-dropdown_input .items-placeholder {
border: 0 none !important;
box-shadow: none !important;
width: 100%;
}
.plugin-dropdown_input.has-items .items-placeholder, .plugin-dropdown_input.dropdown-active .items-placeholder {
display: none !important;
}
.ts-wrapper.plugin-input_autogrow.has-items .ts-control > input {
min-width: 0;
}
.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input {
flex: none;
min-width: 4px;
}
.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input::-ms-input-placeholder {
color: transparent;
}
.ts-wrapper.plugin-input_autogrow.has-items.focus .ts-control > input::placeholder {
color: transparent;
}
.ts-dropdown.plugin-optgroup_columns .ts-dropdown-content {
display: flex;
}
.ts-dropdown.plugin-optgroup_columns .optgroup {
border-right: 1px solid #f2f2f2;
border-top: 0 none;
flex-grow: 1;
flex-basis: 0;
min-width: 0;
}
.ts-dropdown.plugin-optgroup_columns .optgroup:last-child {
border-right: 0 none;
}
.ts-dropdown.plugin-optgroup_columns .optgroup::before {
display: none;
}
.ts-dropdown.plugin-optgroup_columns .optgroup-header {
border-top: 0 none;
}
.ts-wrapper.plugin-remove_button .item {
display: inline-flex;
align-items: center;
}
.ts-wrapper.plugin-remove_button .item .remove {
color: inherit;
text-decoration: none;
vertical-align: middle;
display: inline-block;
padding: 0 6px;
border-radius: 0 2px 2px 0;
box-sizing: border-box;
}
.ts-wrapper.plugin-remove_button .item .remove:hover {
background: rgba(0, 0, 0, 0.05);
}
.ts-wrapper.plugin-remove_button.disabled .item .remove:hover {
background: none;
}
.ts-wrapper.plugin-remove_button .remove-single {
position: absolute;
right: 0;
top: 0;
font-size: 23px;
}
.ts-wrapper.plugin-remove_button:not(.rtl) .item {
padding-right: 0 !important;
}
.ts-wrapper.plugin-remove_button:not(.rtl) .item .remove {
border-left: 1px solid #d0d0d0;
margin-left: 6px;
}
.ts-wrapper.plugin-remove_button:not(.rtl) .item.active .remove {
border-left-color: #cacaca;
}
.ts-wrapper.plugin-remove_button:not(.rtl).disabled .item .remove {
border-left-color: white;
}
.ts-wrapper.plugin-remove_button.rtl .item {
padding-left: 0 !important;
}
.ts-wrapper.plugin-remove_button.rtl .item .remove {
border-right: 1px solid #d0d0d0;
margin-right: 6px;
}
.ts-wrapper.plugin-remove_button.rtl .item.active .remove {
border-right-color: #cacaca;
}
.ts-wrapper.plugin-remove_button.rtl.disabled .item .remove {
border-right-color: white;
}
:root {
--ts-pr-clear-button: 0px;
--ts-pr-caret: 0px;
--ts-pr-min: .75rem;
}
.ts-wrapper.single .ts-control, .ts-wrapper.single .ts-control input {
cursor: pointer;
}
.ts-control:not(.rtl) {
padding-right: max(var(--ts-pr-min), var(--ts-pr-clear-button) + var(--ts-pr-caret)) !important;
}
.ts-control.rtl {
padding-left: max(var(--ts-pr-min), var(--ts-pr-clear-button) + var(--ts-pr-caret)) !important;
}
.ts-wrapper {
position: relative;
}
.ts-dropdown,
.ts-control,
.ts-control input {
color: #303030;
font-family: inherit;
font-size: 13px;
line-height: 18px;
}
.ts-control,
.ts-wrapper.single.input-active .ts-control {
background: var(--color-gray-600);
cursor: text;
}
.ts-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
/*# sourceMappingURL=tom-select.css.map */

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
import type { Translations } from '@ckeditor/ckeditor5-utils';
declare const translations: Translations;
export default translations;

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More