Description du programme

Application web de gestion et d'édition de timeway pour installations de traitement de surface (galvanoplastie, phosphatation, etc.).

Version : 2.4.2 — © 2026 VK Vision SA


Description

VKTimeway permet de définir, visualiser et éditer graphiquement les cycles de transfert d'un ou de plusieurs robots sur une ligne de traitement de surface. L'application gère :


Architecture

Application PWA vanilla JS sans framework, fonctionnant entièrement côté client.

App/
├── index.html                  Point d'entrée unique (SPA)
├── manifest.json               Manifeste PWA
├── sw.js                       Service Worker (cache offline)
└── assets/
    ├── js/
    │   ├── VKApp.js            Routeur SPA + logique de toutes les pages
    │   ├── VKModels.js         Constructeurs des modèles de données
    │   ├── VKData.js           Persistance localStorage
    │   ├── VKCloud.js          Client PocketBase (auth, CRUD, partage)
    │   ├── VKStore.js          Façade de persistance (routage Local/Cloud)
    │   ├── VKDiagram.js        Moteur de rendu canvas du timeway
    │   ├── VKMachine.js        Dessin SVG inline de la machine
    │   ├── VKTimewayGen.js     Générateur automatique de timeway
    │   ├── VKReport.js         Génération de rapports PDF (pdfmake)
    │   ├── VKI18n.js           Internationalisation (FR / EN / DE / ZH)
    │   ├── pdfmake.min.js      Librairie PDF (embarquée, offline)
    │   ├── vfs_fonts.min.js    Polices pdfmake (Roboto, embarquées)
    │   └── pocketbase.umd.js   SDK client PocketBase (embarqué)
    ├── css/
    │   └── app.css             Styles spécifiques à l'application
    └── img/
        └── icons/              Icônes PNG de la barre d'outils de l'éditeur

PocketBase/
└── README.md                   Configuration des collections du serveur PocketBase (source "Cloud")

Modules JS

Fichier Rôle
VKApp.js Routeur hash (#/, #/machines, …), rendu des pages, modales d'édition, simulateur
VKModels.js Constructeurs Machine, Version, Position, Hoist, Sequence, Timeway, …
VKData.js Lecture / écriture dans localStorage (source "Local")
VKCloud.js Client PocketBase : authentification email/mot de passe, CRUD Machines/Versions, partage (source "Cloud")
VKStore.js Façade Machines/Versions : route vers VKData ou VKCloud selon la source de données active, transparente pour le reste de l'application
VKDiagram.js Rendu canvas : axes, étapes, aides visuelles, détection collision
VKMachine.js Dessin SVG inline de la machine (cuves, robots) depuis la définition des positions
VKTimewayGen.js Génération automatique d'un timeway depuis une séquence
VKReport.js Rapports PDF via pdfmake : machine, séquence, timeway, diagramme
VKI18n.js Dictionnaire quadrilingue + injection dans le DOM (data-i18n)

Modèle de données

Machine                  Id, Name, Number, Client, Location, Remarks, CreatedAt, UpdatedAt
└── Version[]            Id, Number, Comment, Remarks, CreatedAt, UpdatedAt
    ├── Positions[]      id, name, tag, flag, group, tank, address, branch, lift, lower, distance
    ├── Hoists[]         id, pi, pf, width, front, back, speed1 (mm/s), accdec (ms), lifts[], lowers[]
    ├── Sequences[]      id, name, remarks, steps[]
    ├── Timeways[]       id, name, remarks, cycletime (ms), visible, steps[]
    ├── LiftTypes[]      10 types de montée nommés (id, name, time)
    └── LowerTypes[]     10 types de descente nommés (id, name, time)

En source Local, toutes les données sont stockées en JSON dans localStorage sous les clés tw_machines et tw_versions.

En source Cloud, le même modèle est persisté sur un serveur PocketBase : Machine et Version (métadonnées) deviennent chacune une collection, le contenu imbriqué de Version (Positions, Hoists, Sequences, Timeways, Programs, LiftTypes, LowerTypes) étant conservé tel quel dans un unique champ JSON data — voir PocketBase/README.md.


Fonctionnalités principales

Gestion des machines

Export / Import des données

Source de données Cloud (PocketBase)

Versions

Positions, robots (hoists), séquences

Visualisation de la machine

Types montées / descentes

Génération automatique de timeway

Éditeur graphique de timeway

Simulateur de production

Rapports PDF

Générés côté client via pdfmake (aucun serveur requis, fonctionne offline). Chaque rapport est téléchargé directement en .pdf.

Rapport Déclencheur Contenu
Fiche machine Bouton dans l'onglet Positions Positions · Robots · Types montées/descentes · Remarques
Fiche séquence Bouton par ligne dans l'onglet Séquences Étapes (position, groupe, montée, descente, Tmin/Tmax/Tégouttage) · Remarques
Fiche timeway Bouton par ligne dans l'onglet Timeway Étapes avec tous les temps (Ti, Tf, Tégouttage, Tmontée, Tdescente, Ttransfert) · Remarques
Rapport diagramme Bouton dans la toolbar de l'éditeur Capture du canvas + table des étapes · Remarques (orientation paysage si nécessaire)

Structure commune des rapports :


Internationalisation

Quatre langues supportées : Français (défaut), English, Deutsch, 中文 (chinois simplifié).

La langue est sélectionnable depuis la page d'accueil et persistée dans localStorage. Le changement est instantané sans rechargement de page.

Utilisation dans le HTML : data-i18n="clé" sur n'importe quel élément. Utilisation dans le JS : VKI18n.t('clé').


Installation / Démarrage

Développement

Aucune dépendance serveur pour la source de données "Local" — l'application fonctionne directement depuis un navigateur (la source "Cloud" nécessite un serveur PocketBase, voir plus bas).

  1. Cloner le dépôt
  2. Servir le dossier App/ via un serveur HTTP local (requis pour le Service Worker) :
    npx serve App/
    # ou
    python -m http.server 8080 --directory App/
    
  3. Ouvrir http://localhost:8080 dans un navigateur moderne

Note : L'ouverture directe du fichier index.html (file://) ne fonctionnera pas avec le Service Worker. Un serveur HTTP est nécessaire.

Build de distribution (version minifiée)

Un script de build génère une version optimisée dans Dist/ :

npm install       # une seule fois
npm run build     # génère Dist/

Le build effectue :

Important : le nom du cache du sw.js généré (vktimeway-dist-v*) est dérivé automatiquement de VK_VERSION (tête de VKApp.js) — incrémenter cette constante (et CACHE_NAME dans App/sw.js pour le mode développement) à chaque nouveau déploiement pour forcer la mise à jour du cache chez les utilisateurs.

Pour servir la version de distribution :

npx serve Dist/

Source de données Cloud (optionnel)

La source "Local" (localStorage) fonctionne sans aucune configuration. Pour activer la source "Cloud", un serveur PocketBase est nécessaire :

  1. Configurer les collections machines, versions, machine_shares sur le serveur — voir PocketBase/README.md (champs, règles API à copier-coller)
  2. Renseigner son adresse dans VK_POCKETBASE_URL_DEFAULT (App/assets/js/VKCloud.js), ou directement dans le formulaire de connexion de l'application

Dépendances front-end (embarquées)

Librairie Version Usage
Bootstrap 5.x UI composants, grille, modales
Font Awesome 6.x Icônes vectorielles
pdfmake 0.2.10 Génération de rapports PDF côté client
pocketbase (SDK JS) 0.28.x Client de la source de données Cloud (auth, CRUD, partage)

Toutes les dépendances sont incluses dans App/assets/ — aucune connexion CDN requise.

Dépendances de build (développement uniquement)

Package Usage
terser Minification JavaScript
clean-css Minification CSS
fs-extra Opérations fichiers avancées

Structure des routes

Hash Page
#/ Accueil (sélection de langue, source de données Local/Cloud, export/import données)
#/machines Liste des machines
#/machines/create Nouvelle machine
#/machines/:id Détail machine + liste des versions
#/machines/:id/version/:vid Édition d'une version (positions, robots, séquences, timeway)

Versioning de l'application

La version est définie par la constante VK_VERSION en tête de VKApp.js :

var VK_VERSION = 'ver. 2.4.2';

Elle s'affiche automatiquement dans le footer de l'application et est intégrée dans les métadonnées et les noms de fichiers des rapports PDF générés.

Configuration PocketBase — VKTimeway

Ce dossier documente la configuration à effectuer une seule fois, dans l'interface d'administration de votre serveur PocketBase, pour activer la source de données "Cloud" de l'application (voir App/assets/js/VKCloud.js et App/assets/js/VKStore.js).

Testé avec le SDK client pocketbase v0.28.1 (vendored dans App/assets/js/pocketbase.umd.js) — utilisez une version de serveur PocketBase récente (≥ 0.23) qui expose le même format de règles.

0. Adresse du serveur

Ouvrez App/assets/js/VKCloud.js et remplacez la valeur par défaut :

var VK_POCKETBASE_URL_DEFAULT = 'http://localhost:8090';

par l'URL réelle de votre instance PocketBase. Ce n'est qu'une valeur par défaut : le champ "Adresse du serveur PocketBase" du formulaire de connexion (page d'accueil, source "Cloud") permet de la modifier à tout moment sans retoucher le code — la dernière adresse utilisée est mémorisée dans le navigateur. Changer d'adresse invalide la session en cours (un jeton d'authentification n'a de sens que pour le serveur qui l'a émis).

1. Collection users (déjà fournie par PocketBase)

Rien à créer — PocketBase inclut déjà une collection d'authentification users (email + mot de passe). Il faut seulement assouplir ses règles pour permettre à un utilisateur connecté de retrouver un autre utilisateur par son adresse e-mail (nécessaire pour partager une machine) :

Dans Collections → users → Edit → API Rules, remplacez :

Ceci permet à tout utilisateur connecté de lister/consulter les comptes (uniquement les champs publics : email, id — jamais le mot de passe), mais pas de les modifier ni les supprimer (ces règles restent inchangées).

2. Collection machines

Collections → New collection → Base collection, nom machines.

Champs :

Champ Type Requis Notes
name Text oui
number Text non
client Text non
location Text non
remarks Editor (ou Text) non
owner Relation → users oui Single, cascade delete conseillé
local_id Text non UUID généré côté client, pour réconcilier avec les données locales

API Rules :

List/Search rule :
  owner = @request.auth.id ||
  machine_shares_via_machine.user ?= @request.auth.id

View rule :  (identique au List rule ci-dessus)

Create rule :
  @request.auth.id != "" && @request.body.owner = @request.auth.id

Update rule :
  owner = @request.auth.id ||
  (machine_shares_via_machine.user ?= @request.auth.id &&
   machine_shares_via_machine.permission = "edit")

Delete rule :
  owner = @request.auth.id

3. Collection versions

New collection → Base collection, nom versions.

Champs :

Champ Type Requis Notes
machine Relation → machines oui Single, cascade delete conseillé
number Number oui
comment Text non
remarks Editor (ou Text) non
data JSON oui { Positions, Hoists, Sequences, Timeways, Programs, LiftTypes, LowerTypes }
local_id Text non UUID généré côté client

API Rules :

List/Search rule :
  machine.owner = @request.auth.id ||
  machine.machine_shares_via_machine.user ?= @request.auth.id

View rule :  (identique)

Create rule :
  machine.owner = @request.auth.id ||
  (machine.machine_shares_via_machine.user ?= @request.auth.id &&
   machine.machine_shares_via_machine.permission = "edit")

Update rule :  (identique au Create rule)

Delete rule :
  machine.owner = @request.auth.id

4. Collection machine_shares

New collection → Base collection, nom machine_shares.

Champs :

Champ Type Requis Notes
machine Relation → machines oui Single, cascade delete conseillé
user Relation → users oui Single, cascade delete conseillé
permission Select oui Options : view, edit — défaut view

API Rules :

List/Search rule :
  machine.owner = @request.auth.id || user = @request.auth.id

View rule :  (identique)

Create rule :
  machine.owner = @request.auth.id

Update rule :
  machine.owner = @request.auth.id

Delete rule :
  machine.owner = @request.auth.id || user = @request.auth.id

5. Comptes utilisateurs

Créez les comptes depuis Collections → users → New record (ou activez l'inscription publique si vous le souhaitez — non nécessaire pour ce projet, les comptes peuvent être créés uniquement par l'administrateur).

Notes / limites connues


Revision #7
Created 2026-03-24 09:25:49 UTC by Jean-Noël Voirol
Updated 2026-09-21 17:21:42 UTC by Jean-Noël Voirol