Uses a new `URL_SAFE_BASIC` regex constant that checks for characters
that are commonly used in URL path sections: alphanumeric lowercase
characters, dashes and underscores.
This will allow us to re-use this constant in our server-side
validation.
Since we've now added PAT's we really do recommend switching to those,
or for enterprises, we recommend using service accounts.
Admin tokens have an obvious disadvantage in that they're not connected
to any user, so actions performed by them are harder to audit.
This PR adds a killswitch for turning it off, in preparation for
deprecating them and ultimately removing them in the future.
This improves the role resolution in the value of the default root role,
preventing a bug where settings saved
pre-https://github.com/Unleash/unleash/pull/5887 would show an empty
default root role in the dropdown.
Also makes the role update more robust.
This PR adds uuids as ids using a symbol in order to make sure we only
use this to keep internal order in the viritual DOM. This makes us able
to have predictable mutable lists on the frontend, and makes it easy to
not pass this property along to the backend.
This seems to improve the performance in the role form while still
maintaining the same validation logic.
A big factor was the memoization of the categories calculation and
respective elements, which is especially impactful when there are many
environments.
This PR adds undo functionality so you can restore the state of your
constraint if you make a mistake. We also amend the autosave
functionality to only apply when values are changed and you have a valid
value. See demo:
https://www.loom.com/share/da704da8aee94ac18d4caae697426802
[![Mend
Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com)
This PR contains the following updates:
| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [react-router](https://togithub.com/remix-run/react-router)
([source](https://togithub.com/remix-run/react-router/tree/HEAD/packages/react-router))
| [`6.20.1` ->
`6.21.1`](https://renovatebot.com/diffs/npm/react-router/6.20.1/6.21.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-router/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-router/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-router/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-router/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [react-router-dom](https://togithub.com/remix-run/react-router)
([source](https://togithub.com/remix-run/react-router/tree/HEAD/packages/react-router-dom))
| [`6.20.1` ->
`6.21.1`](https://renovatebot.com/diffs/npm/react-router-dom/6.20.1/6.21.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/react-router-dom/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/react-router-dom/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/react-router-dom/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/react-router-dom/6.20.1/6.21.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
---
### Release Notes
<details>
<summary>remix-run/react-router (react-router)</summary>
###
[`v6.21.1`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#6211)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router@6.21.0...react-router@6.21.1)
##### Patch Changes
- Fix bug with `route.lazy` not working correctly on initial SPA load
when `v7_partialHydration` is specified
([#​11121](https://togithub.com/remix-run/react-router/pull/11121))
- Updated dependencies:
- `@remix-run/router@1.14.1`
###
[`v6.21.0`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router/CHANGELOG.md#6210)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router@6.20.1...react-router@6.21.0)
##### Minor Changes
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking
bug fix to relative routing when inside a splat route.
([#​11087](https://togithub.com/remix-run/react-router/pull/11087))
This fix was originally added in
[#​10983](https://togithub.com/remix-run/react-router/issues/10983)
and was later reverted in
[#​11078](https://togithub.com/remix-run/react-router/pull/11078)
because it was determined that a large number of existing applications
were relying on the buggy behavior (see
[#​11052](https://togithub.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when
resolving relative paths is to *ignore* any splat (`*`) portion of the
current route path.
**The Background**
This decision was originally made thinking that it would make the
concept of nested different sections of your apps in `<Routes>` easier
if relative routing would *replace* the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects`
will match the `Dashboard` route. The dashboard component itself can
then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them.
This makes code splitting and compartmentalizing your app really easy.
You could render the `Dashboard` as its own independent app, or embed it
into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot
of other assumptions in React Router - namely that `"."` always means
the current location pathname for that route. When we ignore the splat
portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to
/dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at
/dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our
`DashboardTeam` component around our route hierarchy easily - since it
behaves differently if we're underneath a non-splat route, such as
`/dashboard/:widget`. Now, our `"."` links will, properly point to
ourself *inclusive of the dynamic param value* so behavior will break
from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard`
component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any
`<Form>` should post to it's own route `action` if you the user doesn't
specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the
parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default
location for a `Form` to submit to is itself (`"."`) - and if we ignore
the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the
future flag, move your splat to it's own route, and leverage `../` for
any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all
cases (including static, dynamic, and splat routes) and `..` always
means "my parents pathname".
##### Patch Changes
- Properly handle falsy error values in ErrorBoundary's
([#​11071](https://togithub.com/remix-run/react-router/pull/11071))
- Updated dependencies:
- `@remix-run/router@1.14.0`
</details>
<details>
<summary>remix-run/react-router (react-router-dom)</summary>
###
[`v6.21.1`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#6211)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router-dom@6.21.0...react-router-dom@6.21.1)
##### Patch Changes
- Updated dependencies:
- `react-router@6.21.1`
- `@remix-run/router@1.14.1`
###
[`v6.21.0`](https://togithub.com/remix-run/react-router/blob/HEAD/packages/react-router-dom/CHANGELOG.md#6210)
[Compare
Source](https://togithub.com/remix-run/react-router/compare/react-router-dom@6.20.1...react-router-dom@6.21.0)
##### Minor Changes
- Add a new `future.v7_relativeSplatPath` flag to implement a breaking
bug fix to relative routing when inside a splat route.
([#​11087](https://togithub.com/remix-run/react-router/pull/11087))
This fix was originally added in
[#​10983](https://togithub.com/remix-run/react-router/issues/10983)
and was later reverted in
[#​11078](https://togithub.com/remix-run/react-router/pull/11078)
because it was determined that a large number of existing applications
were relying on the buggy behavior (see
[#​11052](https://togithub.com/remix-run/react-router/issues/11052))
**The Bug**
The buggy behavior is that without this flag, the default behavior when
resolving relative paths is to *ignore* any splat (`*`) portion of the
current route path.
**The Background**
This decision was originally made thinking that it would make the
concept of nested different sections of your apps in `<Routes>` easier
if relative routing would *replace* the current splat:
```jsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="dashboard/*" element={<Dashboard />} />
</Routes>
</BrowserRouter>
```
Any paths like `/dashboard`, `/dashboard/team`, `/dashboard/projects`
will match the `Dashboard` route. The dashboard component itself can
then render nested `<Routes>`:
```jsx
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="/">Dashboard Home</Link>
<Link to="team">Team</Link>
<Link to="projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Routes>
</div>
);
}
```
Now, all links and route paths are relative to the router above them.
This makes code splitting and compartmentalizing your app really easy.
You could render the `Dashboard` as its own independent app, or embed it
into your large app without making any changes to it.
**The Problem**
The problem is that this concept of ignoring part of a path breaks a lot
of other assumptions in React Router - namely that `"."` always means
the current location pathname for that route. When we ignore the splat
portion, we start getting invalid paths when using `"."`:
```jsx
// If we are on URL /dashboard/team, and we want to link to
/dashboard/team:
function DashboardTeam() {
// ❌ This is broken and results in <a href="/dashboard">
return <Link to=".">A broken link to the Current URL</Link>;
// ✅ This is fixed but super unintuitive since we're already at
/dashboard/team!
return <Link to="./team">A broken link to the Current URL</Link>;
}
```
We've also introduced an issue that we can no longer move our
`DashboardTeam` component around our route hierarchy easily - since it
behaves differently if we're underneath a non-splat route, such as
`/dashboard/:widget`. Now, our `"."` links will, properly point to
ourself *inclusive of the dynamic param value* so behavior will break
from it's corresponding usage in a `/dashboard/*` route.
Even worse, consider a nested splat route configuration:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
```
Now, a `<Link to=".">` and a `<Link to="..">` inside the `Dashboard`
component go to the same place! That is definitely not correct!
Another common issue arose in Data Routers (and Remix) where any
`<Form>` should post to it's own route `action` if you the user doesn't
specify a form action:
```jsx
let router = createBrowserRouter({
path: "/dashboard",
children: [
{
path: "*",
action: dashboardAction,
Component() {
// ❌ This form is broken! It throws a 405 error when it submits because
// it tries to submit to /dashboard (without the splat value) and the
parent
// `/dashboard` route doesn't have an action
return <Form method="post">...</Form>;
},
},
],
});
```
This is just a compounded issue from the above because the default
location for a `Form` to submit to is itself (`"."`) - and if we ignore
the splat portion, that now resolves to the parent route.
**The Solution**
If you are leveraging this behavior, it's recommended to enable the
future flag, move your splat to it's own route, and leverage `../` for
any links to "sibling" pages:
```jsx
<BrowserRouter>
<Routes>
<Route path="dashboard">
<Route index path="*" element={<Dashboard />} />
</Route>
</Routes>
</BrowserRouter>
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<nav>
<Link to="..">Dashboard Home</Link>
<Link to="../team">Team</Link>
<Link to="../projects">Projects</Link>
</nav>
<Routes>
<Route path="/" element={<DashboardHome />} />
<Route path="team" element={<DashboardTeam />} />
<Route path="projects" element={<DashboardProjects />} />
</Router>
</div>
);
}
```
This way, `.` means "the full current pathname for my route" in all
cases (including static, dynamic, and splat routes) and `..` always
means "my parents pathname".
##### Patch Changes
- Updated dependencies:
- `@remix-run/router@1.14.0`
- `react-router@6.21.0`
</details>
---
### Configuration
📅 **Schedule**: Branch creation - "after 7pm every weekday,before 5am
every weekday" in timezone Europe/Madrid, Automerge - At any time (no
schedule defined).
🚦 **Automerge**: Enabled.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box
---
This PR has been generated by [Mend
Renovate](https://www.mend.io/free-developer-tools/renovate/). View
repository job log
[here](https://developer.mend.io/github/Unleash/unleash).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4xMjcuMCIsInVwZGF0ZWRJblZlciI6IjM3LjEyNy4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Lots of work here, mostly because I didn't want to turn off the
`noImplicitAnyLet` lint. This PR tries its best to type all the untyped
lets biome complained about (Don't ask me how many hours that took or
how many lints that was >200...), which in the future will force test
authors to actually type their global variables setup in `beforeAll`.
---------
Co-authored-by: Gastón Fournier <gaston@getunleash.io>
This changes the two interfaces IChangeRequest and
IChangeRequestSchedule to be union types instead of interfaces. It also
extracts the constituents of those union types into proper types
themselves (so that they can be used in function type signatures etc).
It also updates the type names.
This turned out to be more work than I had imagined, but I think the end
result pays off, giving us more type safety and control.
I wanted to use just `ChangeRequest` for the IChangeRequest type, but
that caused issues due to naming collisions with the `ChangeRequest`
component that we have, causing tests to fail. I've named it
`ChangeRequestType` as a potential solution, but suggestions are
welcome.
The relevant changes are in
`frontend/src/component/changeRequest/changeRequest.types.ts`.
Everything else is updated references and some necessary refactoring to
respect the new types.
https://linear.app/unleash/issue/2-1817/ui-create-an-incoming-webhooks-configuration-page
This adds an incoming webhooks page with the respective table. We plan
on possibly extending the table with a couple more columns in a future
PR.
This allows us:
- View all configured incoming webhooks;
- Copy their URL to the clipboard;
- Remove them;
For "new" and "edit" operations we still need the incoming webhooks
form/dialog, coming in a future PR.
**Note**: Even though we are showing the full URL in the table for now,
we may end up truncating its start in the future (e.g.
`.../api/incoming-webhook/<webhook-name>` - This decision depends on how
it will look like after the rest of the columns are added.
![image](https://github.com/Unleash/unleash/assets/14320932/1cac3286-818f-4967-8686-43f78aa6bd33)