`groupId` parameter because of the change in validation wasn't parsed
correctly. Intent was to fill it when it is empty, when the form is loaded.
By mistake the same logic applies when you manually remove all
characters from the text field.
Adds sticky pagination to the event log:
![image](https://github.com/user-attachments/assets/c426f30d-bb64-44a5-b3b4-8c295207b249)
This PR uses the sticky pagination bar that we use on other tables to
navigate the event search results.
## Decisions / discussion points
The trickiest issue here is how we calculate the next and previous page
offsets. This is tricky because we don't expose the page number to the
API, but the raw offset itself. This abstraction makes it possible to
set an offset that isn't a multiple of the page size.
Say the page size is 25. If you manually set an offset of 30 (through
changing the URL), what do you expect should happen when you:
- load the page? Should you see results 31 to 55? 26 to 50?
- go to the next page? Should your next offset be 55 or 50?
- previous page: should your previous page offset be 5? 25? 0?
The current implementation has taken what I thought would be the easiest
way out: If your offset is between two multiples of the page size, we'll
consider it to be the lower of the two.
- The next page's offset is the next multiple of the page size that is
higher than the current offset (50 in the example above).
- The previous page's offset will be not the nearest lower page size,
but the one below. So if you set offset 35 and page size 25, your next
page will take you back to 0 (as if the offset was 25).
We could instead update the API to accept `page` instead of offset, but
that wouldn't align with how other tables do it.
Comparing to the global flags table, if you set an offset that isn't a
multiple of the page size, we force the offset to 0. We can look at
handling it like that in a follow-up, though I'd argue that forcing it
to be the next lower multiple of the page size would make more sense.
One issue that appears when you can set custom offsets is that the
little "showing x-y items out of z" gets out of whack (because it only
operates on multiples of the page size (seemingly))
![image](https://github.com/user-attachments/assets/ec9df89c-2717-45d9-97dd-5c4e8ebc24cc)
## The Event Log as a table
While we haven't used the HTML `table` element to render the event log,
I would argue that it _is_ actually a table. It displays tabular data.
Each card (row) has an id, a project, etc.
The current implementation forces the event log search to act as a table
state manager, but we could transform the event list into an events
table to better align the pagination handling. The best part? We can
keep the exact same design too. A table doesn't have to _look_ like a
table to be a table.
Fixes a bug where the `handleSelection` function would select the
wrong item under certain conditions.
Because we always sent the unfiltered list of options to the function,
but took the index of the filtered items, the index would be off when
you have filtered the list and items before the selected items were
hidden.
This addresses that and also ports in some improvements I made when
setting up the config buttons for the new dialogs:
1. You can now use the space bar to select items that you have
focused (this is consistent with regular form interactions for
checkboxes)
2. When you have added text to the search field, pressing Enter will
select the top-most item (this is consistent with how these fields
work in linear, for instance) as long as your focus is still in the
search field. If you have moved it to the list, enter will still
select an item on that list as expected.
Potential other addition: if you press "Enter" with an empty search
field, we could close the box but keep your selection the same. Again,
this is how Linear does it, but I don't personally know what I'd
expect to happen there, so I'm happy to leave it as is.
Fixes a bug in the navigation when you create a project. It used to be
that we'd replace the current entry in the browser history when we
took you to a separate form for it. However, now that we instead
use a dialog, we don't want to replace the history.
Before: if you created a project and navigated back, you'd be taken to
the page you were at BEFORE you went to the projects page, whether
that was in Unleash or otherwise.
Now you'll be taken back to the projects page.
Hooks up the new Event search and filtering capabilities to the new
Event Log component. In doing so, it also splits the existing EventLog
component into two: `LegacyEventLog` and `NewEventLog`. The naming is
probably temporary, as the old EventLog isn't really legacy yet. But we
can rename them later.
The other half of #7768 .
This is just the state management part of #7768.
Adds a useEventLogSearch hook.
All the filters work except for the date filters. They don't work
because the query parameters in the API don't match what's here, but an
update to the API is coming in a follow-up.
It's a little tricky to handle this because the three different event
logs should have slightly different filters, which makes making the type
checker happy a bit of a pain. However, I'd like to revisit this in a
follow-up PR.
Adding a link "Read more in [release
notes](https://github.com/Unleash/unleash/releases/tag/v6.1.0)" to
orphaned tokens.
This needs to be added on v6.1, with the following changelog entry:
> **SDK tokens for deleted projects**
>
> In previous versions of Unleash, when a project was deleted, the
associated SDK tokens were not removed. This issue has been addressed in
the current version of Unleash.
>
> Unfortunately, if you deleted a project in the past without manually
removing the associated tokens, these "orphaned" tokens were
automatically converted to “wildcard” tokens, granting access to all
feature flags across all projects.
>
> Our assessment indicates this poses a minor security concern due to
the following reasons:
>
> This issue only affects tokens whose entire project scope has been
deleted.
>
> Access requires knowledge of the token.
>
> SDK tokens have limited read access and must be assigned to a single
environment.
>
> In the SDK tokens overview, orphaned tokens are flagged with a
warning. We recommend discontinuing the use of these tokens and creating
new, dedicated tokens instead.
>
> With the latest version, when a project is deleted, all API tokens
scoped to that project will be removed as well. If you need further
assistance, please contact customer support.
Creates a new useEventSearch hook based on the useFeatureSearch hook.
Moves the old useEventSearch hook into useLegacyEventSearch and updates
references to it.
I don't know yet whether this'll work entirely as expected, but I plan
on making any necessary configurations when I implement the state
management in a follow-up PR.
But because this is pretty much a straight copy-paste from
useFeatureSearch (only adjusting types, I think), I also think it might
be possible to turn this into a generic search template. Not sure if now
is the time, but worth thinking about, I think.
This change primarily adds all flags to the flag filter and restructures
the filters component. Instead of splitting into three smaller
components, we now handle more data in the main component.
We might wanna turn them back to smaller components later, but I think
this'll be easier to work with.
Fixes an issue where the collaborator component would be smooshed
together when you have too many collaborators and too many flag tab
items.
The primary things I have done are:
1. Limit the amount of collaborators we show to 6 instead of 8. I
believe the number 8 was arbitrary, so let's go with 6 for now.
2. Instead of using a fixed gap, use a separator element that grows up
to a certain limit. I've added a `Separator` component, which is an
empty div with flex-grow. It feels like you should be able to do that
with gap too, but I can't think of how right now.
3. Don't allow collaborator component text (or avatars) to wrap. We
don't have a lot of space in this header, so let's keep it tight.
Additionally, I've added the `className` prop to the AvatarGroup
component so that it can be styled externally. I also cleaned up some
naming that was left in while I was at it.
Before:
![image](https://github.com/user-attachments/assets/98525a23-c086-433a-8f60-3e281805409f)
After:
![image](https://github.com/user-attachments/assets/559f8975-9cbe-4260-ba5a-409a303375ed)
Fixes a bug introduced with the new tooltips where the system user was
shown as "User ID n" instead of "System". The "n" in this case is
actually the user's index number in the list of project owners
(including duplicates).
There's a few things happening:
1. Change the object for system owners: use `name` instead of
`description`. At the same time, remove the `description` property
completely because it's not used at the moment.
2. Remove the assignnment of `id: objectId(user)` to the user sent to
the User Avatar component. This was a leftover from when we split out
the AvatarGroup component, and is not something we use anymore.
Before:
![image](https://github.com/user-attachments/assets/bd348daf-c81e-4ea9-b8a9-f10af71a0da7)
After:
![image](https://github.com/user-attachments/assets/d147f7c7-d683-43ac-9ee2-6116f155dad6)
This PR makes some small changes to how we handle strategy deletion in
the demo environment, which has become extra important with the recent
soft limits.
The changes are:
- lower the strategy limit from 30 to 25. The standard limit is 30, so
we want to make sure we're below that.
- when checking whether we should delete a strategy, check whether we're
**at or above** the limit. It used to only check if we were above, but
if soft limits would prevent you from adding more, then you'd never be
able to go above the limit.
- Also delete strategies for step3.
Old versions of Unleash allow for creating "Gradual Rollout" strategies
without `groupId` or `stickiness`. UI will now populate those fields,
not getting stuck when editing strategies without said fields.
Fixes an issue where the filter buttons were both too far down and too
far to the right.
The issue was that the wrapper body imposed a pretty substantial bit
of padding. However, the filter buttons already came with their own
bit of padding. The result of this was alignment issues.
To fix it I have:
- opened the `Filters` component up to be styled with styled components
And conditionally (when isEnterprise and the flag is on):
- set the page body to have no padding.
- added a wrapper with padding around the event search results for
This feels a little messy to me, but I also think that because it's
still in heavy development, it might change later. I'd be happy to have
suggestions forbetter implementations.
What makes this extra tricky is that the top padding differs depending
on whether you have the filters there or not, so I couldn't find a way
to just remove that component and be done with it. I may very well have
missed somehing, though.
Before:
![image](https://github.com/user-attachments/assets/1552d1ec-2c14-450f-9ce8-8e74389f11a1)
After:
![image](https://github.com/user-attachments/assets/d58b6fe5-437f-4488-bf01-cabfef669e2e)
Changes the type used by the useEventSearch hook to be `EventSchema`
from OpenAPI instead. This is more accurate with what we're actually
getting. And crucially for the event log search, it contains the
`createdByUserId` property that we need to filter out events.
It's mostly a straightforward find and replace except for one instance
where we need to do some extra fiddling. There's an inline comment
explaining that.
Extracts the Avatar Group component into a `common` component and adds a
standard tooltip to all avatars.
Relates to linear issue 1-2606
This is a suggestion / proof of concept for how we can solve it. While I
think we can merge this as is, I'd also be happy to take any discussions
on other ways to approach it etc.
## Why are these changes made together?
Because extracting the avatar group without adding the new tooltip data
made the existing tooltip misbehave (it'd show up in the top left of the
screen, not synced to the avatar in any way).
I probably could have (and still can if you think it's prudent) split it
out such that the avatar gets a standardized tooltip first (and disable
it for the group card avatars), and split out the avatars in a
follow-up. Happy to do that if you think it's better.
## What does this mean?
It used to be that we had no consistent way of dealing with avatars and
tooltips. Some places had them, some places didn't. This change makes it
so that all avatars that we can show tooltips for will get the same
tooltip.
Previously, we had at least 4 different ways of dealing with tooltips:
- The HTML tooltip (that would be standardized with this PR) in the
project flags table
![image](https://github.com/user-attachments/assets/91098d31-a5e3-4091-9125-332fe5d106fd)
- The "title" that you'd get on your user avatar
![image](https://github.com/user-attachments/assets/39062b61-db8c-4bd5-9fa3-3ecc9bc192ee)
- The group card list tooltip
![image](https://github.com/user-attachments/assets/0d4a696a-e944-446c-8bff-4dcec02d8afb)
- And sometimes you'd get nothing at all
![image](https://github.com/user-attachments/assets/8975afaf-9ca1-4eb6-b443-9ab94b52bbd8)
with this change, we'll always show the same kind of tooltip if we can:
![image](https://github.com/user-attachments/assets/974c592c-c844-4b65-8a55-05e84d3df130)
## What goes in the tooltip?
We use the `UserAvatar` component for a fair few different things and I
didn't want to extract separate components for all the different use
cases. Instead, I wanted to get an overview over what we use it for and
what is relevant info to show.
I found all the places we used it and tried to form an opinion.
This tooltip will work with a user's email, name, username, and id. If
there is no user (such as for empty avatars and avatars displaying only
"+n" for remaining members), we show no tooltip.
Following the example set by the group card avatars, we'll try to use
email or username (in that order) as the main bit of text. If the user
has an email or a username and also a name, the name will be used as
secondary text.
If the user does not have an email or username, but has a name, we'll
use the name as the main text.
If the user does not have an email, a username, or a name, we'll try to
show "User ID: N" if they have an id.
If they do not have a username, a name, an email, or an ID, we bail out
and show nothing.
## Why can you disable the tooltip?
In some cases, you might want to disable the tooltip because you have
more information to feed into it. An example of that is in the project
flags table, where we want to show more information in cases where the
user is 'unknown':
![image](https://github.com/user-attachments/assets/758b4e86-e934-47e3-91ce-ce900f76bc54)
## Additional fixes
This PR also adds a few lines of CSS to fix a minor avatar layout bug.
Before:
![image](https://github.com/user-attachments/assets/0150efbf-c51a-40bb-898f-7ddd3565ce21)
After:
![image](https://github.com/user-attachments/assets/f337cf68-c572-4610-b1de-a27749325da8)
Adds placeholder filter buttons (that don't work at all) yet to the
three event logs.
Flag logs get to choose to and from dates, created by, and event type.
Project logs get all that flag logs get + a filter for flag.
The global log gets all project log filters + a project filter.
There's still work to be done to add data to createdBy, eventType, to
hook it up to the API, and to finalize the layout, but I wanted to get a
rough outline in to iterate on later. The eventType icon will also need
to be decided on.
![image](https://github.com/user-attachments/assets/06a65301-9cc5-45ed-b753-2b9235d64ea6)