Skip to content

Many enhancements: node/edge editing, formula columns, selection panel, Github check before save, mobile UX & pre-production CI... - #332

Open
JeanGarf wants to merge 340 commits into
gephi:mainfrom
JeanGarf:main_jg
Open

JeanGarf wants to merge 340 commits into
gephi:mainfrom
JeanGarf:main_jg

Conversation

@JeanGarf

@JeanGarf JeanGarf commented Aug 4, 2026

Copy link
Copy Markdown

Pull request type

Check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

Summary of changes (d906a9565d89a9)

This range covers the full set of changes accumulated on this fork since the base commit, spanning many feature/fix branches merged into develop and periodically promoted to main_jg.

Save & session

  • Fix GitHub file being overwritten after creating a new workspace (Critical Bug)
  • Add a save icon next to "Workspace", greyed out until there are unsaved changes
  • Persist session settings (layout & metrics parameters) together with the graph
  • Warn before editing a GitHub file that has become stale, checked as soon as the create/edit popup opens
  • Re-arm the freshness check every ~1 minute (down from 5) and re-check before every save
  • Fix a save deadlock and add an "Overwrite" button to the conflict popup
  • Save-conflict popup: all 3 buttons visible on mobile, "Keep" selected by default
  • Fix a reload loop (the internal reference date wasn't refreshed after Reload)
  • Disable the HTTP cache on gist reads (getFile / getFileContent)
  • Fix a freshness false positive: memorize the open date from the same detail endpoint used by the periodic checks, instead of the list endpoint; add a 1s tolerance to absorb transient GitHub timestamp inconsistencies
  • Stop flagging a remote change that isn't one (real content comparison, not date alone)
  • Fix the two remaining root causes of false "modified on GitHub" alerts: fingerprint mismatch between sent and remote-returned bytes, and an un-persisted "keep my changes" acknowledgment causing repeated re-warnings
  • Open from GitHub: the last opened file is now really preselected (not just visually), so "Open" works immediately
  • Warn before opening another file while the current graph has unsaved changes, from every place a file can be opened - including the welcome modal, previously the one path this guard forgot
  • Survive a page reload and a discarded/restored tab (Firefox Android frees background tabs overnight): the graph, its "unsaved changes" star, and the camera's position/zoom all come back exactly as they were left

Node & Edge editing

  • Avoid Gephi Lite to crash when deleting an Edge [Deleting Edge makes Gephi lite to crash #318] (critical bug)
  • Prevent creation of duplicate nodes/edges
  • Support changing edge extremities (source/target) via updateEdge, add a swap button in the edit form, and an "Invert arrow's direction" menu item [Add button to invert Source and Target of an Edge #321]
  • Pre-fill default attribute values on node/edge creation [Default value for attributes #326]
  • Auto-focus the first empty field in node/edge modals
  • Numeric attributes: cross-platform +/− stepper
  • Add a validation button in the modal header and duplicate the OK button in the modal footer (especially for Android)
  • Fix edge weight resetting to 1 on creation [weight field is reseted to 1 #322]
  • Move ID field to the end of node/edge create/edit forms and data columns; move x/y position fields to the end of the edit form
  • Fix Escape not closing the node/edge create/edit popups
  • Confirm before losing unsaved input when closing the editor (Back button, Escape, click-outside, and both close crosses all go through the same confirmation)
  • When editing an edge, offer to create the typed source/target node on the fly if it doesn't exist yet, with confirmation
  • Fix the node/edge/attribute create/edit popup being too wide on mobile

Formula (scripted) columns & data columns

  • Scripted columns: persisted script, live recompute, editable label, and a "Freeze values" action to materialize computed values into a static attribute
  • Add automatic "Update Date" / "Creation Date" columns, with backfill for graphs already loaded in session
  • GEXF export now materializes formula column values
  • Rename "Delete attribute" → "Delete column"; rename "Identifier" → "ID"
  • Fix the Label caption for scripted attributes: back to a plain fixed "Label" instead of computing it from the current display label (Appearance)

Selection panel & Graph view

  • Add a title and selected-item count to the selection panel
  • Make selected nodes/edges clickable to locate them
  • Click a node's label to locate it
  • Add quick-action icons (locate, select neighbors, edit, invert direction, delete)
  • Add icons to create an edge from a node and select a node's edges
  • Sort selected edges by source, target, then label; show only endpoint labels for a selected edge and refocus dimming on it
  • Improve camera framing when locating an edge; unify multi-edge zoom between table and panel (mobile-aware); fix excessive zoom-out on multi-node framing
  • Scroll the selection panel to top after locating an item
  • Visualize the shortest path between two selected nodes
  • Long-press to add a node or edge to the selection (touch equivalent of Ctrl-click)
  • Mobile: fold the selection panel without losing the selection
  • Selection panel: toggle between alphabetical and size sort, persisted per item type
  • Automatically zoom on the selection whenever it changes (debounced so a just-created edge has time to reach the rendered graph first)

Search

  • Made the main fuzzy search robust to involuntary focus loss on Android
  • Fixed the clear cross not closing the results list on Windows, and made it reappear automatically on Android
  • Touch-friendly fuzzy search, persistent results, browser autocomplete hidden
  • Clear cross: focus returned to the field, and the cross always visible
  • Persistent fuzzy search text and clearable fields in the editor
  • Pre-fill node/edge creation with the text typed in the fuzzy search
  • Close the results dropdown when another panel or popup takes its place (it used to keep floating on top)
  • Move the fuzzy search field between the graph title and the Nodes/Edges counter, so the Android virtual keyboard no longer hides its results list
  • Auto-focus the fuzzy search field whenever its panel is (re)opened on mobile

Data tables

  • Locate a node/edge by clicking from the data tables
  • Add Source/Target label columns [In data view, edge mode, Create column Source Label and Target Label #320] and move ID columns to the end (edge view, then node view)
  • Search edges by source/target labels, not just internal IDs
  • Keyboard navigation between cells, plus a cancel button
  • Align the number field's stepper with the check button, not the cross

Filters

  • Reorder the filters panel and support scripted attributes as filterable
  • Fix the displayed From/To range-filter placeholder values
  • Add a "Based on filtered values" checkbox for size min/max interpolation
  • Left panel: clarify when filters are active
  • Make filtered items readable and consistent everywhere (funnel icon, selection, dimmed rendering)
  • A filtered edge also dims both its endpoints

Color palette

  • Sort the color legend alphabetically and keep existing colors when a new category is added
  • Remove obsolete categories from the palette; sync the palette when data changes, not only when fields change

Mobile & navigation

  • Add mobile header with node/edge creation icons; expand the Workspace toolbar by default on mobile
  • Fix the Layout submenu appearing unexpectedly on mobile
  • Android Back button closes the popup instead of navigating; prevent Back from popping Graph/Data views or exiting the app with unsaved work; warn before leaving the app with unsaved changes
  • Add a "+" button to create a node directly from the bottom bar, between the panel-close button and "Graph"
  • Add an auto-report menu entry, wired to the feedback-widget-js widget
  • On mobile, the bug icon opens a Report / Auto-report menu like on desktop, replacing three separate burger-menu icons
  • Replace the language selector's text label with an icon on mobile, freeing room for the bug icon on small viewports
  • Hide the floating graph controls (zoom, selection mode...) when a side panel is deployed on mobile, so they stop overlapping its footer buttons
  • Fix tooltips/dropdowns staying stuck open on mobile (a tap fires a mouseenter with no matching mouseleave), intercepting taps on the buttons underneath
  • Add a play/stop icon, next to the theme toggle, to relaunch or stop the last used spatialization
  • Keep the English terms "Graph" and "Data" in the French UI instead of translating them

Default labels

  • Use ID as the default label for nodes/edges; don't show the ID when "No label" is selected

Label rendering

  • Replace the label-display size threshold (which defeated itself on zoom) with a per-screen label budget: at every frame, the largest visible nodes are picked and spread across the viewport, with a minimum render size so small neighbors (e.g. around a hovered node) stay legible
  • Adapt the budget to small screens and to the actually visible area (excluding what the header and panels cover)
  • Show exactly the configured number of labels on every device, without silently down-scaling it on phones
  • Make the label-eligibility margins asymmetric (nil on the left, reduced on the right, where the label text extends), then geometry-accurate vertically (based on sigma's own label-line metrics, shared with click detection)
  • Rename the size/zoom/label-density settings in the appearance panel, with all translations updated

Pre-production banner & CI

  • Add CI deployment of pre-production to GitHub Pages from develop; configure GitHub Pages for this fork; grant contents:write permission to the deploy workflow
  • Move the pre-production banner to the top of the graph; detect preprod via URL

Misc / internal

  • Factor the duplicated data-creation menu into a shared constant; add it to the Graph view above Spatialisation [Data Creation Menu also on Graph View #319]
  • Refresh the filtered graph cache on node/edge data changes, not only on fullGraph reference changes
  • Documentation: factoring rule (avoid divergent behavior across call sites) and feature-branch sync rule (merge --no-ff)
  • Show the build commit hash and date below the version number in the About popup, so the running version can be checked at a glance
  • Fix i18n-checker false positives on dynamically-referenced keys
  • Regenerate e2e reference screenshots (Java / Les Misérables / Power Grid), desynced from CI rendering since 2026-08-16

claude and others added 30 commits July 17, 2026 15:22
Sinon leur ordre dans le volet de sélection suit celui, arbitraire, du Set
de sélection, ce qui rend une sélection multiple difficile à parcourir.
…bile)

Le bouton « Show in Graph » du tableau des edges passait par fitViewportToNodes
(cadrage sur tout le canvas), alors que le bouton « Zoom on all selected edges »
du volet passait par notre cadrage conscient de la bande visible (.filler). D'où,
sur mobile, des edges cadrés derrière le volet de sélection, et un niveau de zoom
différent entre les deux entrées.

Les deux chemins passent désormais par focusCameraOnNodes (cadrage band-aware +
surbrillance), réutilisé par focusCameraOnEdges. L'attente runWhenReadyToFrame
combine bande stabilisée et graphe rendu (relit le sigma vivant à chaque frame),
donc le cadrage est correct aussi bien depuis le volet (déjà monté) que depuis le
tableau (navigation puis montage).
Deux corrections dans getCameraStateToFrameNodes :
- La largeur du label (fixe, non scalée) n'est désormais réservée que pour les
  nœuds situés à droite du centre (le label s'affiche à droite du nœud). La
  réserver pour tous, y compris les nœuds à gauche dont le label s'étend vers
  l'intérieur, sur-contraignait le zoom et dézoomait énormément sur une bande
  étroite (mobile) — d'où « on ne voit presque plus le graphe » sur une sélection
  d'edges étalée (un edge seul, 2 nœuds proches, n'était pas affecté). La réserve
  est aussi plafonnée pour qu'un label très long ne puisse pas écraser le zoom.
- Garde-fou : cadrer un sous-ensemble de nœuds ne doit jamais dézoomer au-delà de
  l'affichage du graphe entier. On calcule le zoom qui fait tenir tous les nœuds
  rendus dans la bande et on ne dézoome jamais en deçà.
… facilement, grisee tant qu'il n'y a pas de modification
- Header mobile : la disquette de sauvegarde est regroupée avec le bouton
  Workspace à gauche (espaceur puis thème/langue/logo à droite), au lieu d'être
  poussée à droite près du sélecteur de thème par le flex-grow de Workspace. Elle
  est ainsi proche de Workspace et n'attrape plus les clics du menu thème.
- Header mobile : l'état ouvert/fermé de la barre d'icônes (burger) est persisté
  entre les vues Graphe et Data (chaque page monte son propre Header, un simple
  useState se réinitialisait à chaque changement de vue).
- Bandeau de gauche : ajout d'icônes « + » pour créer un node et un edge, à droite
  des titres Nodes et Edges (composant partagé GraphSummary, donc présent dans les
  vues Graphe et Data). Le clic ouvre la modale de création correspondante.
…le localiser

Dans le volet des edges sélectionnés, seuls les nœuds source/cible d'un edge
étaient cliquables (pour localiser le nœud). Le milieu de l'edge est désormais
cliquable lui aussi et déclenche la localisation de l'edge, via le même hook
partagé useLocateInGraph.locateEdge que celui utilisé dans la vue Data Mode Edges
(seule l'option navigateToGraph diffère, nécessaire depuis le tableau qui est sur
une autre page). Le comportement exécuté est donc identique des deux côtés.
…œud cliquable dans le volet des nœuds sélectionnés

Même bug que celui déjà corrigé sur les edges : dans le volet des nœuds
sélectionnés, le nœud n'était pas cliquable pour se localiser (contrairement au
tableau Data), car ce comportement n'était implémenté que dans NodeComponentById
(en enveloppant NodeComponent dans un bouton depuis l'extérieur), et EdgeComponent
dupliquait la même logique d'enrobage pour ses nœuds source/cible.

Factorisation : NodeComponent (le composant partagé) porte désormais lui-même le
comportement optionnel « rendre le nœud cliquable » via onClick/buttonTitle.
NodeComponentById, EdgeComponent (source/cible) et le volet de sélection
utilisent tous ce même mécanisme unique au lieu de le réimplémenter chacun de
leur côté — plus de risque de comportements divergents pour une même
fonctionnalité.
…ge depuis une fiche

Sur mobile, en particulier avec plusieurs edges sélectionnés : cliquer sur un
nœud (ou un edge) à l'intérieur d'une fiche en bas de la liste remplaçait la
sélection par ce seul élément, mais le volet restait scrollé à son ancienne
position (proche du bas de l'ancienne liste, plus longue), laissant le titre et
la barre d'icônes du nouvel élément hors champ.

Le volet remonte désormais en haut dès que la sélection est totalement remplacée
par une autre sans recouvrement (type différent, ou aucun id en commun avec
l'ancienne sélection) — le cas d'une localisation ou d'un saut vers un nouvel
élément sur le graphe. Une modification partielle de la liste courante
(désélectionner/cocher un seul élément) conserve la position de scroll.
…ion du clic mobile

1) Une étoile apparaît à droite de la disquette dès que le graphe (données,
   apparence ou filtres) a été modifié depuis le dernier enregistrement ; elle
   disparaît automatiquement une fois la sauvegarde effectuée (isDirty repasse à
   false aussi bien pour l'enregistrement GitHub que pour l'export local/Save As).

2) La disquette est désormais toujours visible (plus seulement quand un fichier
   GitHub est ouvert) : si aucun fichier cloud n'est connecté, le clic ouvre la
   modale « Save as... » (enregistrement local ou vers un nouveau fichier
   GitHub) au lieu de ne rien faire.

3) Sur mobile, la disquette et le bouton Workspace étaient collés (aucun espace
   entre les deux dans la barre du menu burger), ce qui faisait qu'un tap
   imprécis sur la disquette pouvait atteindre la zone tactile du bouton
   Workspace et ouvrir son menu. Ajout d'un espacement entre les boutons de la
   barre.
claude and others added 29 commits August 16, 2026 20:57
…ros nœuds de la zone visible, répartis), réglage du nombre de libellés affichés et taille minimale de rendu
Le libellé étant écrit à droite de son nœud, les côtés ne sont pas
équivalents : à gauche, un nœud qui entre dans l'écran a d'emblée tout son
libellé visible, d'où une marge nulle ; à droite, la marge passe de 50 à
25 px, ce qui rend éligibles des nœuds jusque-là écartés sans que leur
libellé devienne illisible pour autant.

Documente également le retour sur `develop` après chaque propagation en
production.
…texte

La marge de 50 px, héritée du côté droit, écartait sans raison des nœuds
proches des bords supérieur et inférieur : seule la hauteur du texte compte
là, et non la longueur du libellé. Elle est donc calculée à partir de la
géométrie de rendu de sigma (ligne de base à un tiers de la taille de police
sous le centre du nœud, jambages descendants jusqu'à 0,3 de plus), pour la
plus grande taille de libellé attendue, soit 16 px.

Les ratios de cette géométrie, jusqu'ici codés en dur dans la détection du
clic sur un libellé, sont partagés entre les deux usages.
Confirmation avant perte de graphe non sauvegardé à l'ouverture
…auvegardé factorisée (y compris depuis la modale d'accueil)
Zoome automatiquement sur la sélection quand elle change
…d), désynchronisées du rendu CI depuis le 2026-08-16
Fiabilise les captures e2e de load-graph.spec.ts (dérive de rendu CI)
…u'elle apparaisse dans le graphe de rendu (débounce de sigmaGraphAtom)
Zoom auto non déclenché après création d'un lien
…n veille

Sur Firefox Android, un onglet laissé de côté une nuit est déchargé pour
libérer de la mémoire, puis restauré au retour. Le navigateur ne rétablit
la sessionStorage de l'onglet que si elle est assez petite pour son
gestionnaire de session : un graphe sérialisé est très loin du compte
(60 Ko pour Les Misérables, dont 39 % pour les colonnes de dates
automatiques ajoutées récemment). L'onglet revenait donc vide, avec la
popup d'accueil, et le graphe était perdu.

L'instantané de l'espace de travail (graphe, filtres, apparence, session)
passe donc en localStorage, que le navigateur restaure quelle que soit sa
taille, sous un espace de noms propre à l'onglet. Seul cet identifiant
reste en sessionStorage — quelques dizaines d'octets, toujours restaurés —
et il est doublé dans history.state, lui aussi restauré, au cas où la
sessionStorage serait perdue entièrement.

Comme le localStorage survit à l'onglet qui l'a écrit, les espaces de noms
sont nettoyés : ceux laissés par des onglets disparus depuis plus de sept
jours sont supprimés au démarrage, et atteindre le quota évince les moins
récemment utilisés. Un graphe trop gros pour être stocké efface désormais
l'instantané précédent, qui aurait sinon été restauré à la place.
Deux oublis du correctif précédent, qui ne restaurait que le contenu de
l'espace de travail :

- L'étoile "modifications non enregistrées" disparaissait : la restauration
  effaçait le drapeau isDirty, parce qu'elle passe forcément par des
  écritures d'atomes qui le remettent à true, sans rapport avec l'état
  réel. Le drapeau est désormais enregistré avec l'instantané, et remis
  tel quel — il faut donc le lire avant de toucher aux atomes, sans quoi
  on ne relit que le "true" que la restauration vient d'écrire.

- La position et le zoom repartaient d'un cadrage complet du graphe. La
  caméra est maintenant enregistrée (à l'arrêt du déplacement) et remise
  en place au chargement. Les coordonnées n'ayant de sens que par rapport
  à la boîte englobante du graphe, la restauration passe toujours par
  resetCamera d'abord, via restoreCamera, appelé aussi bien à la
  restauration de l'espace de travail qu'au montage de sigma, puisque
  l'un ou l'autre peut arriver en dernier.

Le bouton "voir tout le graphe", l'ouverture d'un fichier et les layouts
continuent d'appeler resetCamera : ils recadrent, et le nouveau cadrage
devient à son tour celui que l'on retrouvera.
Focus automatique sur la recherche fuzzy à l'ouverture du volet gauche (mobile)
@JeanGarf

JeanGarf commented Sep 9, 2026

Copy link
Copy Markdown
Author

Bonsoir @sim51,

Si vous avez besoin d'infos supplémentaires, ou si vous souhaitez essayer ma version, n'hésitez pas à me contacter.

Cordialement,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants