Skip to content

feat: modernise the UI and bring its screens in line with the API - #1068

Open
blaipr wants to merge 1 commit into
ctrliq:mainfrom
blaipr:feat/modernise-the-ui
Open

blaipr wants to merge 1 commit into
ctrliq:mainfrom
blaipr:feat/modernise-the-ui

Conversation

@blaipr

@blaipr blaipr commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

A modernised UI, in line with the API

Everything this change adds over main, by the part of the product it touches.

After you validate this PR, v25.7.0 can be released.


Scope

This is mostly interface work on top of main, with a small set of API changes the interface needed.

It is one commit over 1,101 files. The regenerated message catalogues account for most of the volume: outside
ui/src/locales the change is 1,083 files, adding 48,657 lines and removing 12,973. The backend part is 34 files,
adding 1,772 lines and removing 582, and is the part that most needs a reviewer who knows the API.


Breaking changes

Two changes affect installations or integrations rather than only the screens.

  • RADIUS and TACACS+ authentication are removed, from the settings screens, the API and the dependencies that
    served them. Old RADIUS and TACACS+ settings addresses in the UI land on Authentication.
  • Screens moved to new addresses: Jobs is Runs (/runs), and the data retention screen is Cleanup Jobs
    (/cleanup_jobs). Every old address, /jobs, /data_retention and /management_jobs included, redirects to its
    new one with whatever followed it, so saved links still land.

Navigation and layout

The rail down the left is the frame everything else sits in, and it was rebuilt first.

  • Eight groups that open and close, each remembering how it was left, with the current item lit while one of its
    own tabs is open.
  • A group that opens below the fold scrolls into view with it, at the speed every other group opens.
  • The machinery a job runs on, the instances, the instance groups, the container groups and the topology, gathers
    under one rail item instead of four. Users who are not administrators, who cannot open Instances or Topology, get
    Instance Groups in the rail with Container Groups as its tab, and no tab that leads to a screen they cannot open.
  • Rows stand off both ends of their line alike, the lines run the width of the sidebar, and the first row sits
    where a row starts rather than eight pixels lower.
  • Page titles say what the rail calls the screen, tooltips open upwards, and every add button says what it adds.
  • Cards carry their outline whether or not their content is padded, and the page keeps its gutter beside the rail.
  • One loading animation per page, over the bare background, rather than one per card and one per form.
  • An unknown address below an object shows Not Found, with no tab highlighted, rather than an empty card under a
    highlighted Back tab. Every object screen has a Not Found page, notification templates, execution environments,
    credential types, applications and roles included.

Buttons and tabs

Every list and tab uses the same toolbar, with words that say what a click does.

  • Add and Delete create and destroy. Associate and Disassociate link and unlink things that exist on their own:
    Access, a user's and a team's Roles, a user's Organizations and Teams, a host's Groups, an instance group's
    Instances, an instance's Peers and Instance Groups. The dialogs, errors and empty messages use the same words.
  • A group's Hosts and Related Groups tabs have Add for a new one and Associate for an existing one, where a menu
    held both.
  • Every tab that can add or remove what it lists has the standard Add and Delete, shown only to whoever the API
    lets use them: an organization's Teams and Execution Environments, every Notifications tab, an application's
    Tokens, and Delete with tick boxes on the Roles and Access tabs.
  • Adding from an organization's tab opens the form in that organization, and Cancel comes back to the tab: teams,
    execution environments and notification templates. A token added from an application returns to the
    application.
  • Every Runs tab has a Run button that runs what the tab belongs to: a template launches, a project or source
    syncs, a cleanup job runs, and an inventory or host opens a Run menu aimed at it. Screens where nothing can be
    run, an instance or an instance group, show no Run button.
  • Tab order is the same everywhere: Back first, then Details, the object's own tabs, and Notifications, Schedules
    and Runs last.
  • Buttons, tabs, titles, columns and field labels are in Title Case, and tooltips name the object ("Edit Host",
    "Associate Role", "Run Job Template").
  • Switches show On or Off as they are, where PatternFly 6 left every switch showing its On label.

Lists and search

The lists read what is there now, keep their ticks to what is on screen, and search the way people type.

  • A list paints what it has at once and always reads again when it opens, so a change made elsewhere shows on the
    way back, and each tab reads its own resource rather than the last one cached.
  • Ticks clear whenever what the list shows changes, so Delete never acts on a row no longer on screen, and a list
    steps back a page when its last page empties.
  • Lists filter as their search box is typed in, including busy lists that keep updating while you type.
  • Live updates reach every row: two jobs changing status in the same moment both show it.
  • Search finds by any part of a name in any case on every list, an inventory's Sources included, and the role
    wizard offers only searches the API accepts.
  • Ticking two statuses or two types means either of them on every runs list, inventory Runs tabs included, and a
    Type combined with a Status narrows the list rather than widening it.
  • Empty lists say something true about where their entries come from.

Runs

The runs list gained a way to start anything, and the launch wizard was rebuilt around what a run is aimed at.

  • A Run button that starts any of the six kinds the list shows: Job, Workflow, Command, Inventory Sync, Project
    Sync and Cleanup Job, in that order wherever they are listed, the type search included.
  • The wizard asks for the template first and for the limit second. What the limit step offers comes from the
    template: whole inventories where it prompts for one, the hosts and groups of its own inventory where it prompts
    for a limit, and nothing at all where it prompts for neither, in which case there is no step.
  • The inventory is asked once. Where the limit step collects it, the prompt that would ask again is dropped.
  • Syncs and cleanup jobs are picked with tick boxes, so several start at once, and the two cleanup jobs that keep a
    number of days of records ask for it once between them. Runs the API refuses are named, with the API's reason,
    after the others start, and a run aimed at several inventories starts on every one it can.
  • Cancel and Delete follow the API: Cancel for whoever may cancel that run, in the states it can be canceled in,
    and Delete once it can be deleted. A run in the new state offers both. Relaunch is not offered where it cannot
    work, such as on a cleanup job.
  • Relaunch, Cancel and Delete name the kind of run they act on, "Cancel Project Sync" or "Delete Workflow Job".
  • A failed workflow job offers relaunch from the failed nodes on its details, as its row and output do.
  • Leaving a workflow's prompted Limit blank no longer replaces the limits set on its nodes, at launch or in a
    schedule, so a node limited to some hosts no longer runs against its whole inventory.
  • The modals forget what their lists were showing when they close, so the next one opens unfiltered.

Job output

The output of a run shows all of it, from its first line.

  • A long run shows every event. Nothing cuts it off at a fixed number of rows, so the last tasks and the recap of a
    large run are always there.
  • Lines are numbered from one, and finished output opens at its top.
  • The end of a run stays on screen when it finishes, instead of reloading to the top half way through.
  • Copy and Download say when they fail rather than reporting success, and a cleanup run's output can be copied
    and downloaded.
  • Moving between the jobs of a workflow waits for each job's output before showing it.

Templates

The templates screen holds two kinds of thing, and says which is which without repeating itself.

  • Tabs for All, Job Templates and Workflow Templates, with the type search and the add menu narrowing to the tab.
  • The Type column shows only on All, where the two kinds are mixed; on the other tabs it was a column of one value
    whose sort put the rows back where it found them.
  • The list a run picks from leaves out what it cannot reach, and says why it is empty rather than telling the
    reader to add a template: what the search matched, the limit a run aimed at hosts needs, or the inventory a
    template has to be able to reach.
  • Each row names the inventory its template is stuck with, since that is where its run will happen.
  • The Playbook Name search on every Job Templates tab works; it sent a filter the API refused.
  • A job template added from any kind of inventory starts with that inventory.
  • A workflow's visualizer says Delete for the nodes and links it deletes, its tools and legend match the rest of
    the UI, cleanup job nodes are marked C, and an approval node shows its timeout action, required approvals and
    context.
  • A workflow template's survey forms hide its tabs, as a job template's do.

Hosts and groups

The four host lists and the three group lists all start runs the same way.

  • One Run menu on each of them, offering a job, a workflow or a command against what is ticked.
  • The button is live whether or not anything is ticked: nothing ticked runs on everything the tab covers, the
    group or host a tab belongs to rather than the whole inventory, and the tooltip says which.
  • A command goes to the hosts ticked, or to all of them, and shows the same Limit line the other two show.
  • The template list a run picks from is filtered to the inventory the ticks are in, so no template from another
    inventory is offered.
  • The toolbar's buttons are one size, and a toolbar's menu toggle is painted as the buttons beside it.
  • A host's groups in a constructed or federated inventory open the right group, and offer no edit that cannot open.
  • Hosts of smart, constructed and federated inventories have Facts and Runs tabs.

Inventories and projects

Both lists sync from the toolbar rather than one row at a time.

  • A Sync button beside Delete. It says Sync All with nothing ticked and Sync once rows are ticked, syncs only what
    the user may sync, follows the list's search across every page, starts five syncs at a time rather than all at
    once, and says what it skipped and why.
  • A click starts the syncs. There is no confirmation step, since a sync is undone by not watching it.
  • A project shows the revision its sync wrote as soon as the sync ends, even when several syncs finish together.
  • An inventory whose sync is running shows the blue Running label the runs list gives it.
  • Projects, inventory sources and cleanup jobs have Runs tabs, and an inventory's details can sync its sources.
  • Cancel Sync is offered to whoever the API lets cancel that sync, in every state a sync can be canceled in.
  • Every kind of inventory lists Groups before Hosts, and keeps the list's filters on its Back tab.

Schedules

The schedules screen lists every schedule there is, and now makes them too.

  • An Add button beside Delete, since a schedule belongs to the thing it starts and only that thing's own tab could
    add one before.
  • The first step asks what the schedule is for, over one list of the templates, projects, inventory sources and
    cleanup jobs a schedule can hang on.
  • What the template prompts for are steps of the same wizard, ending on a preview that shows the schedule above
    what it will run with, where a Prompt button opened a second wizard.
  • Escape closes an open menu inside the wizard before the wizard itself, so nothing typed is lost.
  • A row the API refuses, a manual project or one the account may only read, says so when it is picked.
  • Days of Data to Keep is asked only for the two cleanup jobs that keep history, and takes only whole numbers
    from 0 to 99,999.
  • A template's default credentials must still be replaced with one of the same type in a schedule's prompts.
  • Editing a schedule without opening its prompts keeps its variables.
  • The form and details name each field alike: Start Date/Time, End Date/Time, Repeat Frequency, Exceptions.

Cleanup jobs

Cleanup jobs are a screen of their own, named the way the runs list names them.

  • The screen is Cleanup Jobs at /cleanup_jobs, with tick boxes and a Run button, so several run at once with one
    question about days between them.
  • Each cleanup job has Details, Notifications, Schedules and Runs tabs, and can be run from its details.
  • One days prompt everywhere, which refuses an empty or invalid value rather than running with 0, which would
    delete all history.

Instances and instance groups

The screens for the machinery that runs jobs follow what the API allows.

  • An instance has Instance Groups and Runs tabs. Hop nodes, which can do neither, do not show them.
  • Health Check is for superusers on every screen, reaches every execution node ticked, managed ones included, and
    says why it is off.
  • An instance may leave controlplane unless it is a hybrid node, as the API allows, and the reason is given.
  • Deprovisioning an instance says Delete and names the instances it refuses, managed ones among them.
  • The default and controlplane group forms lock the name and policy percentage the API refuses to change.
  • A plain instance group opened at a container group address moves to its own address, and container groups name
    themselves throughout.
  • Peers and listener addresses read every page, and the capacity slider behaves on details as on the lists.

Notifications

Notification templates are one thing with one name, and every screen names their types alike.

  • One translated list of types, read by the form, the filters, the rows and the details.
  • Details show every custom message, the Changed messages included, and editing keeps each type's defaults
    rather than saving untouched messages as blank.
  • The IRC form's Use SSL box says Use SSL, where it read Disable SSL Verification.
  • A new template added from an organization starts in that organization.

Access, users and tokens

The access screens offer only what the API will do.

  • An Access tab closes only a role held on that resource itself, never one a team inherits from its organization.
  • A user's Organizations and Teams tabs offer Associate and Disassociate to superusers and to admins of the
    organization or team concerned.
  • The system roles work in every language, where they were looked up by their translated name.
  • Removing a user from an organization takes every role they hold there, Admin and Auditor included.
  • Token lists and details offer Delete only to whoever may delete that token, only your own token list offers
    Add, and a token opened from an application returns there.
  • The role wizards finish with Associate, need a role picked, and search each resource by its own fields.
  • A failed association shows which roles were associated anyway.
  • The Users list's Organization column, always empty, is gone, and its Role column is User Type.
  • Labels offer Edit and Delete only to superusers and admins of the label's organization. A label can be deleted
    only once nothing carries it; deleting one still in use is refused with a message saying why.

Roles

Roles became something that can be read rather than a table to scroll.

  • A screen per kind of object, and a page per role saying what it grants and who holds it.
  • The objects a role is held on are listed on a tab of their own.
  • Each kind has its own address, so a reload and the breadcrumb agree, and role kinds are translated.

Settings

Settings became screens rather than one list of links.

  • One screen per subject, each with its own route, and the provider screens under authentication.
  • Tabs within a screen read alphabetically, so a tab is looked for in one place and a new one has somewhere to go.
  • Revert All resets only the settings on the page or tab in front of you. It used to reset the whole category,
    Disable Local Authentication included, from the Session tab.
  • Saving a tab saves that tab's settings only, on every tabbed settings screen, so it cannot overwrite what another
    admin changed on another tab.
  • Every tab has its own address, and Save and Cancel return to the tab that was edited. Old ?tab= links still
    land on their tab.
  • Edit forms are for superusers only, and closing the Disable Local Authentication confirmation undoes the switch.
  • Unset values say Not configured, durations show their units, and choices show their labels.
  • Every signed-in user gets the installation's default theme, language and editor size, which only
    administrators could read before.
  • The editors open at the size of what they hold, up to the fifty lines the setting allows, instead of four.

Authentication

The authentication settings were split up, and two providers were removed.

  • RADIUS and TACACS+ are gone, from the settings screens and from the backend that served them.
  • Providers is the first tab. Tokens, the social auth mapping, the password rules and troubleshooting each have a
    tab of their own.
  • The session settings show their plain fields before their json blocks.
  • The screen names itself in the header, and the tab bar names the view, on every one of its tabs.

Forms and details

Forms save what they hold and check what they declare, and details say what they mean.

  • A required lookup's check is no longer dropped when a form has a field of the same name, so a team, inventory,
    project, application or user can no longer be saved without its organization.
  • Editing an inventory source keeps its limit and timeout.
  • Errors wait for a field to be touched, selects that start empty say what they want, and Cancel and Prompt are
    the same link buttons on every form.
  • Form and details use one name for each field, and options blocks list the same items on both.
  • Detail pages show values the way the lists do: pull policies, job types, launchers and credentials.

Themes

All four themes were touched, and the rules that differed between them were brought together.

  • An editor selection is readable in every theme: the library drew it from its own dark base, which buried the
    text under it in the light themes, and the search extension painted every other copy of the selected text a
    solid green over the text rather than behind it.
  • A button keeps its label the same colour under the pointer, and a green fill carries dark ink at rest and on
    hover alike.
  • An add button that holds a menu is the same button as every other add: the same fill, the same ink and the same
    darkening under the pointer.
  • The masthead's toggles are part of the bar rather than fields on it.
  • The pagination arrows are dark on their green fill in the dark theme.
  • Form controls and the output console take a surface of their own in the light theme.
  • The topology legend draws nodes as the canvas does, and its letters are readable in the dark.
  • The AWX theme is called Classic. A user or installation default saved as AWX opens as Classic.

API

The backend changes are small, and each one serves the interface.

  • Runs report a cancel user capability, computed as the cancel endpoints decide, and workflow approvals report
    can_cancel_workflow. On the runs and approvals lists these are answered once per page, not once per row.
  • Labels can be deleted through DELETE /api/v2/labels/<id>/, by a superuser or an admin of the label's
    organization, and only while nothing carries the label: a label in use answers 409. Labels report edit and
    delete user capabilities.
  • /api/v2/config/ carries the default UI theme, language and editor size for every signed-in user.
  • type__in on unified jobs and templates matches each type it lists, where it matched nothing.
  • A role_level filter a model cannot take answers 400 rather than 500.
  • The workflow approvals list costs a fixed number of queries whatever its size, for every kind of reader, with
    the same permission answers as before. A test holds the batched answers to the per row ones for every kind of
    user and approval.
  • The old AWXModelBackend name only restores sessions made before the rename, instead of checking every failed
    password a second time.
  • RADIUS and TACACS+ are removed, with their settings, migrations and licences.

Translations

Relabelled text keeps its translations, but new text is not translated yet.

  • Renaming labels into Title Case gave each a new message, which dropped its translation; those were carried over
    wherever only the case, spacing or end mark changed.
  • About 420 messages per language are new or reworded text with no translation yet, where main has about 25.
    Until they are translated, those parts show in English in every language.

Under the hood

The work that does not show, but that the rest of it stands on.

  • Tests alongside each change, including stylesheet checks for the rules jsdom cannot see.
  • The message catalogues are regenerated whenever the strings move, and the check that they are in step runs with
    the lint.
  • The modals' variables editors follow the editor rows setting, as the editors on a page do.
  • Every settings page is an ordinary screen rather than a special case of one list.
  • The generated API types are in step with the serializers.
  • The command wizard's launch, its payload and its error paths have tests again.

Verification

Every job the CI workflow runs was run locally on this commit, on top of the current main.

  • API: 4,607 passed and 6 skipped, with the missing migration and settings checks clean.
  • Migrations: the migration tests pass.
  • API lint and the strict type check pass. The advisory type check reports 2,903 diagnostics, the same as main.
  • API types: regenerated from the serializers with no drift.
  • UI: lint, type check and prettier check pass, and 3,854 tests pass.
  • End to end: 21 of 21 Playwright tests pass against a fresh build.
  • Smoke test: a job template launched and ran on the development environment.

What is not here

One thing was deliberately left, and is worth knowing before picking the work up again.

  • The job output fix, which keeps the end of a run on screen, has no unit test: jsdom could not drive the
    websocket and the virtualiser together. It was verified against a running installation instead.

@cigamit cigamit self-assigned this Sep 29, 2026
@cigamit cigamit added the enhancement New feature or request label Sep 29, 2026
@blaipr
blaipr force-pushed the feat/modernise-the-ui branch from 7fa8d47 to 3b4ad07 Compare September 29, 2026 20:43
@cigamit

cigamit commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

I will discuss this one with the Team. While I like a lot of what is done here, there are some things that will need to be debated, such as changing Jobs to Runs, etc... as that's a terminology change for existing users.

@blaipr

blaipr commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

Sure! I understand there are too many changes @cigamit. Let me know if you want something changed/reverted.

I started by fixing UI bugs, added the buttons that a user asked for, added some other new buttons that I was missing myself and saw opportunities here and there and didn't feel like making 100 little PRs.

Thanks for your patience 😄

A rework of the web UI on top of main, with the small set of API changes the
screens needed. The full list is in the pull request.

- Breaking: RADIUS and TACACS+ authentication are removed. Jobs is Runs at
  /runs and data retention is Cleanup Jobs at /cleanup_jobs; every old address
  redirects to its new one.
- A rebuilt navigation rail, one toolbar and one vocabulary on every list and
  tab: Add and Delete create and destroy, Associate and Disassociate link and
  unlink, and every Runs tab runs what it belongs to.
- A Run button and launch wizard for every kind of run, toolbar Sync that
  follows permissions and search, Cancel and Delete that follow the api, and
  job output that shows every event from line one.
- Schedules added from the schedules screen, with template prompts as wizard
  steps; Cleanup Jobs, Roles and Settings as screens of their own; instances,
  instance groups, notifications, access and tokens gated on what the api
  allows.
- Lists that read what is there now, search by any part of a name, deliver
  every live update and keep their ticks to what is on screen; forms that save
  what they hold; Title Case labels, and fixes across all four themes.
- API: a cancel user capability on runs and can_cancel_workflow on approvals,
  UI defaults in /api/v2/config/ for every user, type__in matching each listed
  type, a 400 rather than a 500 for an unusable role_level filter, and an
  approvals list at a fixed number of queries.
- Relabelled text keeps its translations; new text is not translated yet.
@blaipr
blaipr force-pushed the feat/modernise-the-ui branch from 3b4ad07 to c5bdaee Compare October 4, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Development

Successfully merging this pull request may close these issues.

2 participants