Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into release-tooling
Browse files Browse the repository at this point in the history
  • Loading branch information
slax57 committed Feb 21, 2025
2 parents bfda854 + 1c3f9bb commit f8c103e
Show file tree
Hide file tree
Showing 102 changed files with 2,305 additions and 732 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ jobs:

e-commerce:
runs-on: ubuntu-latest
if: github.ref_type != 'tag'
needs: [typecheck]
steps:
- name: Checkout
Expand Down Expand Up @@ -171,7 +170,7 @@ jobs:
runs-on: ubuntu-latest
name: GreenFrame
needs: [e-commerce]
if: github.event_name == 'push' && github.ref_type == 'tag' && github.ref_name == 'refs/tags/v*' && !contains('beta', github.ref_name) && !contains('alpha', github.ref_name)
if: github.event_name == 'push' && github.ref_type == 'tag' && contains(github.ref, 'refs/tags/v') && !contains('beta', github.ref) && !contains('alpha', github.ref)
steps:
# To use this repository's private action,
# you must check out the repository
Expand Down Expand Up @@ -218,15 +217,15 @@ jobs:
- name: Build create-react-admin
run: make build-create-react-admin install
- name: Create new project
run: ./node_modules/.bin/create-react-admin myadmin --data-provider ra-data-fakerest --auth-provider local-auth-provider --install npm
run: ./node_modules/.bin/create-react-admin myadmin --data-provider ra-data-fakerest --auth-provider local-auth-provider --resource posts --resource comments --install npm
- name: Run the tests
working-directory: ./myadmin
run: npm run test

update-sandbox-repository:
runs-on: ubuntu-latest
# Only run on new tags that target a release (not latest nor next) and avoid alpha and beta tags
if: github.event_name == 'push' && github.ref_type == 'tag' && github.ref_name == 'refs/tags/v*' && !contains('beta', github.ref_name) && !contains('alpha', github.ref_name)
if: github.event_name == 'push' && github.ref_type == 'tag' && contains(github.ref, 'refs/tags/v') && !contains('beta', github.ref) && !contains('alpha', github.ref)
needs: [typecheck, simple-example-typecheck, unit-test, e2e-test]
steps:
- name: Checkout
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Changelog

## 5.6.0

* Add `<LoginWithEmail>` to facilitate login with email ([#10518](https://github.com/marmelab/react-admin/pull/10518)) ([fzaninotto](https://github.com/fzaninotto))
* Add B&W Theme ([#10523](https://github.com/marmelab/react-admin/pull/10523)) ([fzaninotto](https://github.com/fzaninotto))
* Make `create-react-admin` non interactive by default and support `ra-supabase` ([#10511](https://github.com/marmelab/react-admin/pull/10511)) ([djhi](https://github.com/djhi))
* Support `<ReferenceOneField emptyContent>` ([#10450](https://github.com/marmelab/react-admin/pull/10450)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* Update `<ArrayInput>` to throw an error when using outdated `disabled` prop ([#10529](https://github.com/marmelab/react-admin/pull/10529)) ([fzaninotto](https://github.com/fzaninotto))
* [Doc] Add `HorizontalMenu` doc ([#10528](https://github.com/marmelab/react-admin/pull/10528)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Doc] Add `<FormFillerButton>` documentation ([#10527](https://github.com/marmelab/react-admin/pull/10527)) ([djhi](https://github.com/djhi))
* [chore] Fix CI jobs that run on new tag ([#10525](https://github.com/marmelab/react-admin/pull/10525)) ([slax57](https://github.com/slax57))

## 5.5.4

* Fix `<FilerLiveForm>` does not allow to clear filters ([#10522](https://github.com/marmelab/react-admin/pull/10522)) ([djhi](https://github.com/djhi))
* Fix `create-react-admin` with `ra-data-fakerest` ignore custom resources ([#10502](https://github.com/marmelab/react-admin/pull/10502)) ([djhi](https://github.com/djhi))
* Remove doc from published `react-admin` package ([#10505](https://github.com/marmelab/react-admin/pull/10505)) ([djhi](https://github.com/djhi))
* [Doc] Backport `<DatagridAG>` and `<DatagridAGClient>` access control's doc ([#10521](https://github.com/marmelab/react-admin/pull/10521)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Doc] Backport `title={null}`'s doc on dialog components ([#10520](https://github.com/marmelab/react-admin/pull/10520)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Doc] Update doc to mention the dependency on `@ag-grid-community/styles` ([#10510](https://github.com/marmelab/react-admin/pull/10510)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Doc] Update `warnWhenUnsavedChanges`'s doc on dialog forms ([#10509](https://github.com/marmelab/react-admin/pull/10509)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Doc] Update docs to mention `format` prop for timezone adjustment ([#10506](https://github.com/marmelab/react-admin/pull/10506)) ([ogroppo](https://github.com/ogroppo))
* [Doc] Add "Guides and Concepts" section ([#10477](https://github.com/marmelab/react-admin/pull/10477)) ([fzaninotto](https://github.com/fzaninotto))
* [Doc] Deprecate mui v6 system props ([#10463](https://github.com/marmelab/react-admin/pull/10463)) ([smeng9](https://github.com/smeng9))
* [Demo] Fix build ([#10499](https://github.com/marmelab/react-admin/pull/10499)) ([djhi](https://github.com/djhi))
* [Chore] Rename directories for local storage data providers ([#10507](https://github.com/marmelab/react-admin/pull/10507)) ([erwanMarmelab](https://github.com/erwanMarmelab))
* [Chore] Bump serialize-javascript from 6.0.1 to 6.0.2 ([#10508](https://github.com/marmelab/react-admin/pull/10508)) ([dependabot[bot]](https://github.com/apps/dependabot))

## 5.5.3

* Fix `useHandleCallback` compatibility with `React.StrictMode` ([#10486](https://github.com/marmelab/react-admin/pull/10486)) ([erwanMarmelab](https://github.com/erwanMarmelab))
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/LoginPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export default url => ({
appLoader: '.app-loader',
username: "input[name='username']",
password: "input[name='password']",
submitButton: 'button',
submitButton: "button[type='submit']",
title: '#react-admin-title',
},

Expand Down
39 changes: 35 additions & 4 deletions docs/AppTheme.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ const App = () => (

## Built-In Themes

React-admin comes with 4 built-in themes, each one having a light and a dark variant. You can use them as a starting point for your custom theme, or use them as-is.
React-admin comes with 5 built-in themes, each one having a light and a dark variant. You can use them as a starting point for your custom theme, or use them as-is.

| :---: | :---: |
| &nbsp;&nbsp; [Default](#default) [![Default light theme](./img/defaultLightTheme1.jpg)]((#default)) | &nbsp;&nbsp; [Nano](#nano) [![Nano light theme](./img/nanoLightTheme1.jpg)](#nano) |
| &nbsp;&nbsp; [Radiant](#radiant) [![Radiant light theme](./img/radiantLightTheme1.jpg)](#radiant) | &nbsp;&nbsp; [House](#house) [![House light theme](./img/houseLightTheme1.jpg)](#house) |
| &nbsp;&nbsp; [Default](#default) [![Default light theme](./img/defaultLightTheme1.jpg)]((#default)) | &nbsp;&nbsp; [B&W](#bw) [![B&W light theme](./img/bwLightTheme1.jpg)](#bw) |
| &nbsp;&nbsp; [Nano](#nano) [![Nano light theme](./img/nanoLightTheme1.jpg)](#nano) | &nbsp;&nbsp; [Radiant](#radiant) [![Radiant light theme](./img/radiantLightTheme1.jpg)](#radiant) |
| &nbsp;&nbsp; [House](#house) [![House light theme](./img/houseLightTheme1.jpg)](#house) |

### Default

Expand All @@ -123,6 +123,37 @@ The default theme is a good fit for every application, and works equally well on

You don't need to configure anything to use the default theme - it comes out of the box with react-admin.

### B&W

A high-contrast theme with a black and white palette, ideal for visually impaired users. Its modern-looking style, reminiscent of shadcn, is suitable for desktop apps.

[![B&W light theme](./img/bwLightTheme1.jpg)](./img/bwLightTheme1.jpg)
[![B&W light theme](./img/bwLightTheme2.jpg)](./img/bwLightTheme2.jpg)
[![B&W dark theme](./img/bwDarkTheme1.jpg)](./img/bwDarkTheme1.jpg)
[![B&W dark theme](./img/bwDarkTheme2.jpg)](./img/bwDarkTheme2.jpg)

To use the B&W theme, import the `bwLightTheme` and `bwDarkTheme` objects, and pass them to the `<Admin>` component:

```jsx
import { Admin, bwLightTheme, bwDarkTheme } from 'react-admin';

export const App = () => (
<Admin
dataProvider={dataProvider}
theme={bwLightTheme}
darkTheme={bwDarkTheme}
>
// ...
</Admin>
);
```

You must also import the Geist font in your `index.html` file:

```html
<link href="https://fonts.googleapis.com/css2?family=Geist:[email protected]&display=swap" rel="stylesheet">
```

### Nano

A dense theme with minimal chrome, ideal for complex apps. It uses a small font size, reduced spacing, text buttons, standard variant inputs, pale colors. Only fit for desktop apps.
Expand Down
26 changes: 25 additions & 1 deletion docs/ArrayInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Check [the `<SimpleFormIterator>` documentation](./SimpleFormIterator.md) for de

## Props

`<ArrayInput>` accepts the [common input props](./Inputs.md#common-input-props) (except `format` and `parse`).
`<ArrayInput>` accepts the [common input props](./Inputs.md#common-input-props) (except `disabled`, `readOnly`, `format` and `parse`).

## Global validation

Expand All @@ -109,3 +109,27 @@ You need to return an errors object shaped like this:
```

**Tip:** You can find a sample `validate` function that handles arrays in the [Form Validation documentation](./Validation.md#global-validation).

## Disabling The Input

`<ArrayInput>` does not support the `disabled` and `readOnly` props.

If you need to disable the input, set the `<SimpleFormIterator disabled>` prop, and make the child inputs `readOnly`:

```jsx
const OrderEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="customer" />
<DateInput source="date" />
<ArrayInput source="items">
<SimpleFormIterator inline disabled>
<TextInput source="name" readOnly/>
<NumberInput source="price" readOnly />
<NumberInput source="quantity" readOnly />
</SimpleFormIterator>
</ArrayInput>
</SimpleForm>
</Edit>
);
```
85 changes: 69 additions & 16 deletions docs/Authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ const App = () => (
);
```

An `authProvider` is an object that handles authentication and authorization logic, similar to a `dataProvider`. It exposes methods that react-admin calls when needed, and you can also call these methods manually through specialized hooks.

Once an admin has an `authProvider`, react-admin will restrict CRUD pages (the `list`, `edit`, `create`, and `show` components of your `Resources`) to authenticated users and redirect anonymous users to the `/login` page, displaying a login form for a username and password.

## Anatomy Of An `authProvider`
![Login form](./img/login-form.png)

An `authProvider` is an object that handles authentication and authorization logic, similar to a `dataProvider`. It exposes methods that react-admin calls when needed, and you can also call these methods manually through specialized hooks. The `authProvider` methods must return a Promise.
React-admin offers several built-in `authProvider` implementations for popular authentication services like **Google Identity**, **Microsoft Entra ID**, **AWS Cognito**, **Auth0**, **Keycloak**, and others. Refer to the [List of Available Auth Providers](./AuthProviderList.md) to find one that suits your requirements.

A typical `authProvider` has the following methods:
If you need to implement a custom authentication strategy, the [Building Your Own Auth Provider](./AuthProviderWriting.md) offers a step-by-step guide. It boils down to implementing a few methods that react-admin calls when needed:

```js
const authProvider = {
Expand All @@ -54,8 +56,6 @@ const authProvider = {
};
```

You can use an existing Auth Provider from the [List of Available Auth Providers](./AuthProviderList.md) or write your own by following the [Building Your Own Auth Provider](./AuthProviderWriting.md) instructions.

## Sending Credentials To The API

The `authProvider` handles authentication logic, but the `dataProvider` must include the user credentials in requests to the API.
Expand Down Expand Up @@ -229,23 +229,74 @@ const App = () => (

## Customizing The Login Component

Using an `authProvider` is enough to secure your app if authentication relies on a username and password. But for cases like using an email instead of a username, Single-Sign-On (SSO), or two-factor authentication, you can implement your own `LoginPage` component to be displayed under the `/login` route.
Using an `authProvider` is enough to secure your app if authentication relies on a username and password. But for cases like using an email instead of a username, Single-Sign-On (SSO), or two-factor authentication, you can use a custom login page by setting the [`<Admin loginPage>`](./Admin.md#loginpage) prop.

Pass this component to the [`<Admin loginPage>`](./Admin.md#loginpage) prop:
For example, to use an email field instead of a username field, use the `LoginWithEmail` component:

```jsx
// in src/App.js
import { Admin } from 'react-admin';

import MyLoginPage from './MyLoginPage';
```tsx
import { Admin, LoginWithEmail } from 'react-admin';
import authProvider from './authProvider';

const App = () => (
<Admin loginPage={MyLoginPage} authProvider={authProvider}>
...
<Admin loginPage={LoginWithEmail} authProvider={authProvider}>
...
</Admin>
);
```

![Login with email](./img/LoginWithEmail.jpg)

The default login page component is the `Login` component, which delegates the rendering of the login form to its child, usually a `LoginForm` component. This means you can create a custom login page by adding your own content to the `Login` component.

For instance, to add a "forgot password" link to the login page:

```jsx
import { Box, Link } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { Login, LoginForm } from 'react-admin';

const MyLogin = () => (
<Login>
<LoginForm />
<Box textAlign="center" mb={1}>
<Link component={RouterLink} to="/forgot-password">
Forgot password?
</Link>
</Box>
</Login>
);
```
![Login with content](./img/LoginWithContent.jpg)
You can also customize the login form fields, by setting the `LoginForm` children:
```jsx
import { Link as RouterLink } from 'react-router-dom';
import { Login, LoginForm, TextInput, PasswordInput, required } from 'react-admin';

const MyLogin = () => (
<Login>
<LoginForm>
<TextInput
autoFocus
source="email"
label="Email"
autoComplete="email"
type="email"
validate={required()}
/>
<PasswordInput
source="password"
label="Password"
autoComplete="current-password"
validate={required()}
/>
</LoginForm>
</Login>
);
```
By default, the login page displays a gradient background. To change it, use the default Login component and pass an image URL as the `backgroundImage` prop.
```jsx
Expand All @@ -257,7 +308,9 @@ const MyLoginPage = () => (
);
```
To build a Login page from scratch, use the [`useLogin` hook](./useLogin.md).
![Custom login page](./img/LoginCustomBackground.jpg)
You can also build your login page from scratch, leveraging the [`useLogin` hook](./useLogin.md) to handle the login form submission.
```jsx
// in src/MyLoginPage.js
Expand Down Expand Up @@ -415,7 +468,7 @@ export const dataProvider = addRefreshAuthToDataProvider(baseDataProvider, refre
## Authorization
Access control and permissions allow you to restrict certain pages to specific users. React-admin provides powerful primitives for implementing authorization logic. For detailed guidance, check out the [Authorization](./Permissions.md) documentation.
Access control and permissions allow you to restrict certain pages and features to specific users. React-admin provides powerful primitives for implementing authorization logic. For detailed guidance, check out the [Authorization](./Permissions.md) documentation.
<video controls autoplay muted loop>
<source src="./img/AccessControl.mp4" type="video/mp4"/>
Expand Down
21 changes: 20 additions & 1 deletion docs/CanAccess.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const LogsPage = () => (
);
```

Use the [`<CustomRoutes>`](./CustomRoutes.md) component to add custom routes to your admin.
Use the [`<CustomRoutes>`](./CustomRoutes.md) component to add custom routes to your admin.

```tsx
import { Admin, CustomRoutes, Authenticated, CanAccess, AccessDenied, Layout } from 'react-admin';
Expand Down Expand Up @@ -98,3 +98,22 @@ export const MyMenu = () => (

**Note**: You don't need to use `<Authenticated>` on custom pages if your admin uses [`requireAuth`](./Admin.md#requireauth).

## Access Denied Message

By default, `<CanAccess>` renders nothing when the user doesn't have access to the resource.

On custom pages, it's preferable to show an error message instead. Set the `accessDenied` prop to render a custom component in case of access denial:

```tsx
import { Authenticated, CanAccess, AccessDenied } from 'react-admin';

export const LogsPage = () => (
<Authenticated>
<CanAccess resource="logs" action="read" accessDenied={<AccessDenied />}>
...
</CanAccess>
</Authenticated>
);
```

![Access Denied](./img/accessDenied.png)
11 changes: 8 additions & 3 deletions docs/ContainerLayout.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ const MyLayout = ({ children }) => (

## `menu`

By default, `<ContainerLayout>` renders one menu item per resource in the admin. To reorder the menu, omit resources, or add custom pages, pass a custom menu element to the `menu` prop. This element should be [a `<HorizontalMenu>` component](#horizontalmenu) with `<HorizontalMenu.Item>` children. Each child should have a `value` corresponding to the [application location](https://react-admin-ee.marmelab.com/documentation/ra-navigation#concepts) of the target, and can have a `to` prop corresponding to the target location if different from the app location.
By default, `<ContainerLayout>` renders one menu item per resource in the admin. To reorder the menu, omit resources, or add custom pages, pass a custom menu element to the `menu` prop.
This element should be [a `<HorizontalMenu>` component](#horizontalmenu) with `<HorizontalMenu.DashboardItem>` or `<HorizontalMenu.Item>` children.
Each child should have a `value` corresponding to the [application location](https://react-admin-ee.marmelab.com/documentation/ra-navigation#concepts) of the target, and can have a `to` prop corresponding to the target location if different from the app location.

```jsx
import {
Expand All @@ -104,10 +106,14 @@ import {

const Menu = () => (
<HorizontalMenu>
<HorizontalMenu.Item label="Dashboard" to="/" value="" />
<HorizontalMenu.DashboardItem label="Dashboard" value="" />
<HorizontalMenu.Item label="Songs" to="/songs" value="songs" />
<HorizontalMenu.Item label="Artists" to="/artists" value="artists" />
<HorizontalMenu.Item label="Custom" to="/custom" value="custom" />
<HorizontalMenu.Item label="Business" value="business">
<HorizontalMenu.Item label="Sales" value="sales" >
<HorizontalMenu.Item label="Customers" value="customers" >
</HorizontalMenu.Item>
</HorizontalMenu>
);

Expand Down Expand Up @@ -225,7 +231,6 @@ export const MyLayout = ({ children }) => (
```
{% endraw %}

## `<HorizontalMenu>`

This component renders a horizontal menu, to be used in the AppBar of the [`<ContainerLayout>`](#containerLayout).

Expand Down
Loading

0 comments on commit f8c103e

Please sign in to comment.