Skip to content

Add global parameter definitions with configurable choice inputs - #1492

Open
LMatt08 wants to merge 6 commits into
Part-DB:masterfrom
LMatt08:feature/parameter-choice
Open

Add global parameter definitions with configurable choice inputs#1492
LMatt08 wants to merge 6 commits into
Part-DB:masterfrom
LMatt08:feature/parameter-choice

Conversation

@LMatt08

@LMatt08 LMatt08 commented Aug 16, 2026

Copy link
Copy Markdown

Summary

This PR adds reusable global parameter definitions to Part-DB.

A parameter definition can define:

  • a canonical name
  • symbol
  • unit
  • input type (Text or Choice)
  • predefined choices for Choice parameters

Definitions are global and are not dependant of categories.

Parts can link their parameters to a global definition while still keeping
the existing parameter fields as snapshots for compatibility and history.

Legacy / ad-hoc parameters are still supported.

Example:

Definition:
    Name: Dielectric
    Input type: Choice
    Choices:
        C0G/NP0
        X7R
        X5R

A part parameter linked to this definition is displayed using the current
definition metadata and use a dropdown for its value.


Main behavior

Global parameter definitions

A new ParameterDefinition entity and administration page are available under:

Tools -> Edit -> Parameters

Definitions have case-insensitive unique names.

Choice definitions store an ordered list of canonical values.

Text definitions continue to use the existing free-text parameter editor.

The goal is to have one global definition for a parameter instead of redefining
again and again the same name/unit/symbol in different places.


Part parameter editor

Existing parameters stay compatible.

When the user selects a known global parameter definition:

  • the parameter is linked using definition_id
  • name, symbol and unit are refreshed from the definition
  • Choice definitions use a dropdown
  • Text definitions use the existing text input
  • empty value remain a valid "nothing selected" state

Unknown parameter names stay normal ad-hoc parameters and do not automatically
create a global definition.

A user allowed to manage parameter definitions can explicitely add a new choice
directly from the Part editor.

The new value is only kept as a pending choice during the form editing.
The global definition is modified only after the complete Part form is valid
and saved.

Server-side validation recheck:

  • definition existence
  • definition type
  • permissions
  • value length
  • duplicate / canonical choice spelling

No DB write is done directly from Javascript.


Compatibility and history

Existing name, symbol and unit fields stay stored on parameters as
snapshots.

Current entities use linked definition metadata when available.

Historical / TimeTravel views keep the snapshots and safely fallback to them
if the definition cannot be resolved anymore.

Deleting a definition currently used by parameters is blocked.

This was important to not break the existing data model too much and to keep
compatibility with old parameters.


Advanced parameter search

The Part search can now filter directly using global parameter definitions.

Example:

Dielectric = X7R

Multiple parameter filters are combined with AND semantic.

For linked parameters, matching primarily use definition_id.

For old/ad-hoc data, a compatibility fallback match by parameter name only
when definition IS NULL.

This avoid a parameter linked to another definition to accidentally match
through an old snapshot name.

Choice parameters use exact canonical values.

Existing text operators continue to work for Text definitions.

Numeric comparison of global parameters is volontary not included in this PR.
I prefered to keep this PR focused before adding unit-aware numeric search.


Changes by commit

6c03f9f1 — Add global parameter definitions with choice inputs

Introduced the first global parameter definition architecture:

  • new ParameterDefinition entity
  • database migration and definition_id relation
  • global definition administration
  • Text / Choice input types
  • predefined choices
  • new permissions and permission schema v5
  • API representation
  • parameter snapshots vs effective metadata
  • legacy/ad-hoc compatibility
  • definition-aware typeahead
  • initial Part editor integration
  • import/export and history integration
  • delete protection for definitions currently in use

The main idea here was to introduce the new model without replacing all the
existing parameter system.


2fc432ac — Improve global choice parameter editing

This commit mainly harden the Part editor and the Choice workflow:

  • fixed empty Choice values (null -> empty string)
  • dedicated TomSelect handling for Choice parameters
  • explicit "Nothing selected" state
  • canonical case handling
  • explicit creation of new choices
  • added new_choice_value pending state
  • added PendingParameterChoiceApplier
  • new choices are applied only after a valid Part save
  • server-side permission and stale-state revalidation
  • prevented generic TomSelect from initializing the same Choice field
  • improved form reset behavior for dynamic parameter collections
  • restored deleted initial rows on reset
  • removed newly created prototype rows on reset
  • improved validation error tab handling
  • fixed TomSelect reset listener cleanup
  • fixed delete + recreate of the same parameter during one Unit Of Work
  • improved TimeTravel fallback behavior
  • added EN/FR validation messages and more tests

An important point is that Javascript never modify directly the global
definition. It only prepare the user intention, and the server apply it after
validation.


5dd48ab2 — Add global parameter filters to part search

Added definition-aware advanced Part filtering.

Main additions:

  • global definition selector in parameter search rows
  • dedicated Choice filter editor
  • exact Choice matching
  • existing Text operators for Text definitions
  • definition_id as the primary identity
  • legacy/ad-hoc fallback only when definition IS NULL
  • multiple parameter filters combined with AND
  • server-side canonicalization of submitted definition names
  • forged definition IDs are rejected
  • forged Choice values are rejected
  • stale numeric fields are cleaned when switching to global definitions
  • renamed definitions stay searchable through their ID
  • dedicated Stimulus controller for the filter UI
  • GET URL round-trip support
  • multiple independant dynamic filter rows
  • no parameter-definition mutation from search

Example:

Dielectric = X7R
Voltage contains "50"

Both filters must match the Part.

For Choice definitions the equality is strict/canonical.
For Text definitions the previous text operators are still usable.


b08fa3b6 — Fix permission schema upgrade during API requests

This commit fix an upgrade-time regression exposed by the new permission
schema v5.

Existing Part-DB installations can contain users/groups still using permission
schema v4.

The automatic permission upgrade subscriber was running at
kernel.request priority 0.

At this priority, API Platform already deserialised the new API entity.

The permission subscriber then called:

EntityManager::flush()

while the new entity was not yet persisted by API Platform.

This could produce errors like:

A new entity was found through the relationship Category#children

The real listener order was:

Firewall / authentication        8
API Platform Read                4
API Platform Deserialize         2
Permission schema upgrade        0

The subscriber is now running at priority 6:

Firewall / authentication        8
Permission schema upgrade        6
API Platform Read                4
API Platform Deserialize         2

So the subscriber still have access to the authenticated user, but execute
before API Platform starts loading/deserializing request entities.

No Doctrine cascade was added and API Platform persistence behavior was not
changed.

A regression test now explicitely:

  • put the API admin user at permission schema v4
  • put its parent group at permission schema v4
  • remove the new parameter_definitions permissions
  • flush this state to the database
  • use the first authenticated request as POST /api/categories
  • check HTTP 201
  • check that the Category was really persisted
  • reload User and Group from DB
  • check both are now schema v5
  • check all parameter_definitions permission values were correctly migrated

This reproduce the real case of an existing Part-DB installation upgraded
from permission schema v4 to v5.


Permission schema v5

The new parameter_definitions permission set is migrated this way:

parameter_definitions.read
    <- existing parts.read

Management operations:

edit
create
delete
show_history
revert_element
import

are inherited from:

config.change_system_settings

So users already allowed to read parts can read the global definitions.

Users who could modify system configuration keep the rights needed to manage
them.


Validation

image

A lot of automated tests were added or extended during the different
checkpoints.

The tests cover in particular:

  • ParameterDefinition entity behavior
  • case-insensitive definition names
  • Choice canonicalization
  • Part parameter forms
  • pending Choice workflow
  • permissions
  • permission schema v4 -> v5 upgrade
  • API endpoints
  • TimeTravel
  • import/export compatibility
  • definition-aware Part search
  • multiple AND parameter filters
  • forged/stale form submissions
  • delete/recreate in the same Unit Of Work
  • legacy ad-hoc parameter fallback

After the permission-upgrade fix:

tests/API/Endpoints
123 tests, 366 assertions
OK

On a clean SQLite test DB:

tests/API + tests/Doctrine
218 tests, 476 assertions
OK

The complete local PHPUnit suite was also ran:

2065 tests

The remaining local failures are only OAuth tests because the local Windows /
OpenSSL setup is currently not able to generate the RSA OAuth test keys.

CI generates these keys before executing the tests, so these failures are not
related to this PR.

PHPStan targeted checks are clean.

git diff --check is clean.

Frontend assets builds correctly.


Backward compatibility

The implementation try to keep the old parameter behavior as much as possible.

  • existing ad-hoc parameters continue to work
  • existing parameters are not automatically converted to definitions
  • parameter snapshot fields stay stored
  • legacy search data is supported through a controlled name fallback
  • existing installations are automatically upgraded from permission schema
    v4 to v5
  • no destructive migration of existing parameter values is done

The definition_id relation is nullable so old data stay valid.


Out of scope

Some things are intentionally not included in this PR to keep the scope
reasonable:

  • numeric global parameter type / unit aware numeric comparisons
  • automatic conversion of old ad-hoc parameters into definitions
  • category specific parameter-definition assignment
  • automatic creation of definitions from unknown parameter names
  • more advanced concurrency handling for simultaneous Choice edition

Numeric filtering is probably the next logical evolution, but I prefered to
not mix it with this first global parameter definition implementation.

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