Skip to content

web: provide dual-list multiselect with pagination#8004

Merged
kensternberg-authentik merged 33 commits intomainfrom
web/issue-4880-multi-select-limitations
Jan 25, 2024
Merged

web: provide dual-list multiselect with pagination#8004
kensternberg-authentik merged 33 commits intomainfrom
web/issue-4880-multi-select-limitations

Conversation

@kensternberg-authentik
Copy link
Copy Markdown
Contributor

@kensternberg-authentik kensternberg-authentik commented Dec 28, 2023

web: provide a “select / select all” tool for the dual list multiselect

This commit

This commit provides the following new features for dual list multiselect:

  • The “available” pane, which has all of the entries that are available to be selected. Items that are already selected will remain, but they’re marked with a checkmark and can neither be selected or moved.
  • The “selected” pane, which has all of the entries that have been selected.
  • The Pagination control, which in this case only sends an event upstream.

Plan:

The plan is to have a master control that marries the available-pane, selected-pane, select-controls, and pagination-controls into a single component that receives the list of “currently visible” available entries and keeps the list of “currently selected” entries, as well as a pass-through for the pagination value that allows it to hide the pagination control if there is only one page.

A master component above that will provide the list of currently visible entries and, at need, read the value of the master control object for the “selected” list. That component will mostly be data-only; it’s render will probably just be <slot></slot>; its duty will be only to map entries to string keys Lit can use, and to provide the lists we want to provide and the pagination ranges we want to show.

Some judicious use of grid will allow me size the controls properly with/without the pagination control.

Status and Title are going to be in the master control.

There is already a planned fallback control; the multi-select experience on mobile is actually excellent, and we should exploit that appropriately.

closes #4880

Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If an API change has been made

  • The API schema has been updated (make gen-build)

If changes to the frontend have been made

  • The code has been formatted (make web)
  • The translation files have been updated (make i18n-extract)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make website)

…dual-entry

Given that the difference Vite/Storybook cares about is whether or not there's a
sigil at the end of the CSS string, it seemed silly to require devs to enter
both the raw and sigiled string; just do an in-line text-and-replace.
**This commit**

Provides one of several of the sub-controls needed to make the multi-list multi-select thing work.
This is the simplest control, and I decided to go with it first because it's all presentation; all
it does is show the buttons and send events from those buttons.

A Storybook component is provided to show how well it works.
**This commit**

This commit provides the following new features for dual list multiselect:

- The "available" pane, which has all of the entries that are available to be selected.  Items that
  are already selected will remain, but they're marked with a checkmark and can neither be selected
  or moved.
- The "selected" pane, which has *all* of the entries that have been selected.
- The Pagination control, which in this case only sends an event upstream.

**Plan**:

The plan is to have a master control that marries the available-pane, selected-pane,
select-controls, and pagination-controls into a single component that receives the list of
"currently visible" available entries and keeps the list of "currently selected" entries, as well as
a pass-through for the pagination value that allows it to hide the pagination control if there is
only one page.

A master component *above that* will provide the list of currently visible entries and, at need,
read the value of the master control object for the "selected" list. That component will mostly be
data-only; it's render will probably just be `<slot></slot>`; its duty will be only to map entries
to string keys Lit can use, and to provide the lists we want to provide and the pagination ranges we
want to show.

Some judicious use of grid will allow me size the controls properly with/without the pagination
control.

Status and Title are going to be in the master control.

A <slot> will be provided for Search, but I have no plans to integrate that into this control as of
yet.

There is already a planned fallback control; the multi-select experience on mobile is actually
excellent, and we should exploit that appropriately.
@netlify
Copy link
Copy Markdown

netlify bot commented Dec 28, 2023

Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit b5fee45
🔍 Latest deploy log https://app.netlify.com/sites/authentik-storybook/deploys/65b29d1624520000082b56aa
😎 Deploy Preview https://deploy-preview-8004--authentik-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@codecov
Copy link
Copy Markdown

codecov bot commented Dec 28, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (dcbfe73) 92.33% compared to head (b5fee45) 92.32%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8004      +/-   ##
==========================================
- Coverage   92.33%   92.32%   -0.01%     
==========================================
  Files         626      626              
  Lines       30922    30922              
==========================================
- Hits        28552    28550       -2     
- Misses       2370     2372       +2     
Flag Coverage Δ
e2e 50.64% <ø> (-0.01%) ⬇️
integration 26.02% <ø> (ø)
unit 89.58% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

**This commit**

1. Re-arrange the contents of the folder so that the sub-components are in their own folder. This
   reduces the clutter and makes it easier to understand where to look for certain things.
2. Re-arranges the contents of the folder so that all the Storybook stories are in their own folder.
   Again, this reduces the clutter; it also helps the compiler understand what not to compile.
3. Strips down the "Available items pane" to a minimal amount of interactivity and annotates the
   passed-in properties as `readonly`, since the purpose of this component is to display those. The
   only internal state kept is the list of items marked-to-move.
4. Does the same thing with the "Selected items pane".
5. Added comments to help guide future maintainers.
6. Restructured the CSS, taking a _lot_ of it into our own hands. Patternfly continues to act as if
   all components are fully available all the time, and that's simply not true in a shadowDOM
   environment. By separating out the global CSS Custom Properties from the grid and style
   definitions of `pf-c-dual-list-selector`, I was able to construct a more simple and
   straightforward grid (with nested grids for the columns inside).
7. Added "Delete ALL Selected" to the controls
8. Added "double-click" as a "move this one NOW" feature.
@netlify
Copy link
Copy Markdown

netlify bot commented Dec 29, 2023

Deploy Preview for authentik ready!

Name Link
🔨 Latest commit de5e35b
🔍 Latest deploy log https://app.netlify.com/sites/authentik/deploys/65b28642e5c2d500088baed3
😎 Deploy Preview https://deploy-preview-8004--authentik.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

**This commit**

- Fixes the bug whereby pagination would leave the 'some moves available' state visible by clearing
  the 'to-move' state when the list of options changes.
- Fixes the bug whereby a change of 'options' in available would also cause an update to
  `selectedKeys`, causing the entire selected field to clear. Fixed by making `selectedKeys` a
  static object updated only when `selected` is generated rather than generating it anew with each
  re-rerender. (Hey, kids, can you say "functional programming and immutability" five time fast? I
  knew you could!)
- Fixes the bug whereby the change of outpost type would not cause an update of the `options`
  collection.
- Fixes the bug whereby the CSS was not creating enough whitespace separation between the whole
  component and its siblings. Host components are coded `span:static` unless otherwise styled to be
  `block`; we want `block` most of the time.
- Fixes the bug whereby the list of existing objects wasn't being passed to the handler correctly.
- Updates the Form Handler to recognize this new input object.
- Fixes the bug whereby changing outpost type doesn't handle the list of selected applications well.
- Fixes the bug whereby the identity of the outpost type's associated `fetch()` function loses
  identity -- necessary to maintain the selected outpost type switch.
- Fixes the CSS bug whereby horizontal scrolling would not enable correctly when the application's
  name overflows the listbox.
- Completes this assignment.  :-)
* main: (30 commits)
  outposts/proxy: better Redis error message (#8044)
  translate: Updates for file web/xliff/en.xlf in fr (#8046)
  web: bump the eslint group in /tests/wdio with 2 updates (#8041)
  web: bump the storybook group in /web with 7 updates (#8042)
  web: bump the eslint group in /web with 2 updates (#8043)
  web: bump @types/guacamole-common-js from 1.3.2 to 1.5.2 in /web (#8030)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#8038)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#8039)
  website: bump clsx from 2.0.0 to 2.1.0 in /website (#8033)
  core: bump golang from 1.21.3-bookworm to 1.21.5-bookworm (#8027)
  web: bump the babel group in /web with 4 updates (#8028)
  web: bump the esbuild group in /web with 2 updates (#8029)
  web: bump rollup from 4.9.1 to 4.9.2 in /web (#8031)
  tests/e2e: fix tests to work without docker network_mode host (#8035)
  website/docs: fix typo (#8015)
  web: bump API Client version (#8025)
  enterprise/providers: Add RAC [AUTH-15] (#7291)
  outposts: disable deployment and secret reconciler for embedded outpost in code instead of in config (#8021)
  providers/proxy: use access token (#8022)
  website/integrations: Add custom Group/Role mapping documentation for Grafana (#7453)
  ...
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 3, 2024

authentik translations instructions

Thanks for your pull request!

authentik translations are handled using Transifex. Please edit translations over there and they'll be included automatically.

@kensternberg-authentik kensternberg-authentik marked this pull request as ready for review January 3, 2024 00:14
@kensternberg-authentik kensternberg-authentik requested a review from a team as a code owner January 3, 2024 00:14
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Jan 3, 2024

authentik PR Installation instructions

Instructions for docker-compose

Add the following block to your .env file:

AUTHENTIK_IMAGE=ghcr.io/goauthentik/dev-server
AUTHENTIK_TAG=gh-web-issue-4880-multi-select-limitations-1706205859-dd55b50
AUTHENTIK_OUTPOSTS__CONTAINER_IMAGE_BASE=ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s

For arm64, use these values:

AUTHENTIK_IMAGE=ghcr.io/goauthentik/dev-server
AUTHENTIK_TAG=gh-web-issue-4880-multi-select-limitations-1706205859-dd55b50-arm64
AUTHENTIK_OUTPOSTS__CONTAINER_IMAGE_BASE=ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s

Afterwards, run the upgrade commands from the latest release notes.

Instructions for Kubernetes

Add the following block to your values.yml file:

authentik:
    outposts:
        container_image_base: ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s
image:
    repository: ghcr.io/goauthentik/dev-server
    tag: gh-web-issue-4880-multi-select-limitations-1706205859-dd55b50

For arm64, use these values:

authentik:
    outposts:
        container_image_base: ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s
image:
    repository: ghcr.io/goauthentik/dev-server
    tag: gh-web-issue-4880-multi-select-limitations-1706205859-dd55b50-arm64

Afterwards, run the upgrade commands from the latest release notes.

kensternberg-authentik and others added 4 commits January 3, 2024 13:28
Modified the display so that if it's a template we display it
correctly opposite the text, and provide classes that can be used
in the display to differentiate between the main label and the
descriptive label.

Added a sort key, so the select can sort the right-hand pane correctly.

Fixed the `this.selected` setters to use Arrays instead of maps.
Theoretically, this is terribly inefficient, as it makes it
theoretically O(n^2) rather than O(1), but in practice even if both
lists were 10,000 elements long a modern desktop could perform the
entire scan in 150ms or so.
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
@BeryJu BeryJu changed the title web: provide dual-list multiselect with pagination to address issue 4880 "multi-select limitations" web: provide dual-list multiselect with pagination Jan 4, 2024
"Available" requires a round-trip to the provider level, so that's next.
…i-select-limitations' into web/issue-4880-multi-select-limitations

* refs/remotes/origin/web/issue-4880-multi-select-limitations:
  start on dark theme support
  update strings slightly
  fix lint error
**This commit**

- Includes a new widget that represents the basic, Patternfly-designed search bar.  It just emits
  events of search request updates.
- Changes the definition of a data provider to take an optional search string.
- Changes the handler in the *independent* layer so that it catches search requests and those
  requests work on the "selected" collection.
- Changes the handler of the `authentik` interface layer so that it catches search requests and
  those requests are sent to the data provider.
- Provides a debounce function for the `authentik` interface layer to not hammer the Django instance
  too much.
- Updates the data providers in the example for `OutpostForm` to handle search requests.
- Provides a property in the `authentik` interface layer so that the debounce can be tuned.
* main:
  website/docs: add link to our example flows (#8052)
  providers/oauth2: offline access (#8026)
  web: bump API Client version (#8059)
  Update index.md (#8056)
  enterprise/providers/rac: add option to limit concurrent connections to endpoint (#8053)
  web: bump API Client version (#8058)
  enterprise/providers/rac: add alert that enterprise is required for RAC (#8057)
  enterprise/providers/rac: create authorize_application event when creating token (#8050)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const displayMessage = (result: any) => {
const doc = new DOMParser().parseFromString(`<p><i>Content</i>: ${result}</p>`, "text/xml");

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML

[DOM text](1) is reinterpreted as HTML without escaping meta-characters.
Copy link
Copy Markdown
Member

@BeryJu BeryJu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a couple bugs left with the dark mode that we should fix before merging

* dev:
  web: Replace  calls to `rootInterface()?.tenant?` with a contextual `this.tenant` object (#7778)
  web: abstract `rootInterface()?.config?.capabilities.includes()` into `.can()` (#7737)
  web: update some locale details (#8090)
  web: bump the eslint group in /web with 2 updates (#8082)
  web: bump rollup from 4.9.2 to 4.9.4 in /web (#8083)
  core: bump github.com/redis/go-redis/v9 from 9.3.1 to 9.4.0 (#8085)
  web: bump the eslint group in /tests/wdio with 2 updates (#8086)
  website: bump @types/react from 18.2.46 to 18.2.47 in /website (#8088)
  stages/user_login: only set last_ip in session if a binding is given (#8074)
  providers/oauth2: fix missing nonce in token endpoint not being saved (#8073)
  core: bump goauthentik.io/api/v3 from 3.2023105.3 to 3.2023105.5 (#8066)
  providers/oauth2: fix missing nonce in id_token (#8072)
  rbac: fix error when looking up permissions for now uninstalled apps (#8068)
  web/flows: fix device picker incorrect foreground color (#8067)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#8061)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#8062)
  website: bump postcss from 8.4.32 to 8.4.33 in /website (#8063)
  web: bump the sentry group in /web with 2 updates (#8064)
  core: bump golang.org/x/sync from 0.5.0 to 0.6.0 (#8065)
@notion-workspace
Copy link
Copy Markdown

* main: (82 commits)
  translate: Updates for file web/xliff/en.xlf in fr (#8212)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#8211)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#8210)
  web/flows: update flow background (#8209)
  web: clear "blanked" placeholder when present (#15) (#5948)
  web: bump prettier from 3.2.3 to 3.2.4 in /web (#8207)
  web: bump prettier from 3.2.2 to 3.2.3 in /tests/wdio (#8200)
  web: bump the wdio group in /tests/wdio with 4 updates (#8199)
  web: bump @formatjs/intl-listformat from 7.5.4 to 7.5.5 in /web (#8203)
  core: bump uvicorn from 0.25.0 to 0.26.0 (#8198)
  web: bump prettier from 3.2.2 to 3.2.3 in /web (#8201)
  web: bump vite-tsconfig-paths from 4.2.3 to 4.3.1 in /web (#8202)
  website: bump prettier from 3.2.2 to 3.2.3 in /website (#8204)
  website: fix styling on pricing page on firefox
  website: update pricing page (#8197)
  website: bump @types/react from 18.2.47 to 18.2.48 in /website (#8184)
  website: bump react-tooltip from 5.25.1 to 5.25.2 in /website (#8185)
  web: bump the eslint group in /tests/wdio with 2 updates (#8186)
  web: bump the eslint group in /web with 2 updates (#8187)
  web: bump mermaid from 10.6.1 to 10.7.0 in /web (#8189)
  ...
There were two issues: the dark mode didn't reach into the "search"
bar, and there were several hover states that weren't handled well.

This commit handles both.  The color scheme mirrors the one we
currently use, but it's a bit backwards from Patternfly 5.  Dunno
how we're gonna reconcile all that.
Copy link
Copy Markdown
Member

@BeryJu BeryJu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, especially with the dark theme changes

We'll have to do a separate PR to replace all the other multiselect occurrences

* main: (76 commits)
  core: compile backend translations (#8311)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#8304)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#8305)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#8300)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#8301)
  events: fix missing labels on prometheus metrics (#8309)
  core: bump goauthentik.io/api/v3 from 3.2023106.4 to 3.2023106.5 (#8302)
  web: bump the wdio group in /tests/wdio with 4 updates (#8303)
  web: restore test anchor tag (#8298)
  translate: Updates for file web/xliff/en.xlf in fr (#8296)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#8295)
  website: update wording (#8290)
  enterrpise: exclude inactive users from license (#8294)
  web: bump API Client version (#8292)
  core: compile backend translations (#8291)
  events: migrate SystemTasks to DB (#8159)
  web/admin: fix footer links not being parsed on settings page (#8289)
  root: fix system check warnings (#8277)
  web: bump API Client version (#8288)
  enterprise: add full audit log [AUTH-458] (#8177)
  ...
* main:
  web: provide a context for checking the status of the enterprise license (#8153)
@kensternberg-authentik kensternberg-authentik merged commit 5f1ba45 into main Jan 25, 2024
@kensternberg-authentik kensternberg-authentik deleted the web/issue-4880-multi-select-limitations branch January 25, 2024 18:08
kensternberg-authentik added a commit that referenced this pull request Jan 25, 2024
* main:
  web: clear out selecteds list after an API event to ensure a fresh copy of the policies-to-delete list (#8125)
  web: provide dual-list multiselect with pagination (#8004)
kensternberg-authentik added a commit that referenced this pull request Jan 25, 2024
* main: (30 commits)
  web: clear out selecteds list after an API event to ensure a fresh copy of the policies-to-delete list (#8125)
  web: provide dual-list multiselect with pagination (#8004)
  web: provide a context for checking the status of the enterprise license (#8153)
  core: compile backend translations (#8311)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#8304)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#8305)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_CN (#8300)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in zh-Hans (#8301)
  events: fix missing labels on prometheus metrics (#8309)
  core: bump goauthentik.io/api/v3 from 3.2023106.4 to 3.2023106.5 (#8302)
  web: bump the wdio group in /tests/wdio with 4 updates (#8303)
  web: restore test anchor tag (#8298)
  translate: Updates for file web/xliff/en.xlf in fr (#8296)
  translate: Updates for file locale/en/LC_MESSAGES/django.po in fr (#8295)
  website: update wording (#8290)
  enterrpise: exclude inactive users from license (#8294)
  web: bump API Client version (#8292)
  core: compile backend translations (#8291)
  events: migrate SystemTasks to DB (#8159)
  web/admin: fix footer links not being parsed on settings page (#8289)
  ...
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.

Outpost is not able to select more than 100 Applications

2 participants