Customizing the Resource in API Platform with a custom Symfony setup - symfony

I am using a custom setup of API Platform (Symfony 5 + api-pack + admin-pack). I am trying to customize the Resource List with the following
const entrypoint = document.getElementById('api-entrypoint').innerText;
const PropertyCreate = props => (
<CreateGuesser {...props}>
...
</CreateGuesser>
);
const PropertyEdit = props => (
<EditGuesser {...props}>
...
</EditGuesser>
);
export default () => (
<HydraAdmin
apiDocumentationParser={apiDocumentationParser}
dataProvider={dataProvider}
authProvider={authProvider}
entrypoint={entrypoint}
>
<Resource name="properties" create={PropertyCreate} edit={PropertyEdit} />
</HydraAdmin>
);
ReactDOM.render(<HydraAdmin entrypoint={entrypoint}/>, document.getElementById('api-platform-admin'));
But for some reason the Admin doesn't pick the changes. It shows the default view for Create and Edit forms.
Thank you.

Well, it looks like it is quite simple:
export const BookingsAdmin =
<HydraAdmin
apiDocumentationParser={apiDocumentationParser}
dataProvider={dataProvider}
entrypoint={entrypoint}
>
<Resource name="properties" create={PropertyCreate} edit={PropertyEdit}/>
<Resource name="bookings" list={BookingsList}/>
</HydraAdmin>;
ReactDOM.render(BookingsAdmin, document.getElementById('api-platform-admin'));

Related

nextjs localStorage getItem

after searching half a day I still not able to getItem from local storage.
the idea is to save some data to local storage and based on that I want to route a user in the Layout component. I am able to save to local storage and delete but not able to get data from it. I get error 'local storage not defined' or 'destroy is not a function'
I have 3 components save, delete and get. save and delete I execute after a client side api call, the get function I need to be working in the Layout as it is the top level for all routes.
I Need a bit help to the right direction please.
---Upadte
I found something that works
export const IsAuth = ()=>{
const [auth, setAuth] = useState();
useEffect(()=>{
if(typeof windows === undefined) return;
const item = localStorage.getItem('ltu');
setAuth(!!item);
},[]);
return auth;
}
now my problem is I have not much understanding of nextjs. I used the Layout to create a theme template, I basically have only 3 pages that can be visited if not logged in and the rest one needs to be logged in. I get so many examples but it seems like I need to verify auth on every single page instead of being able to do this on root/layout level.
all examples I get are without the use of Layout and I am totally stuck.
I want a simple login system just with jwt and check if thats there to show pages.
I could not get the localStorage.getItem() to work in the layout template.
My solution while maybe not perfect is.
in the _app.js I create useState() and pass those along to the menu trough the Layout, in in the menu useEffect() with 'use client' in the useEffect I set the state I need global.
_app.js
export default function App({ Component, pageProps }){
const [isAuth, setAuth] = useState()
const [user, setUser] = useState()
return (
<Layout setAuth={setAuth} isAuth={isAuth} user={user} setUser={setUser}>
<Component user={user} setUser={setUser} isAuth={isAuth} {...pageProps} />
</Layout>
)
}
Layout.js
export default function Layout({ children, setAuth, isAuth, user, setUser }) {
return (
<>
<Headd />
<SideMenu setAuth={setAuth} isAuth={isAuth} user={user} setUser={setUser}/>
<main>
<div className="menu-spacer"></div>
<content>
{children}
</content>
</main>
</>
)
}
menu.js
'use client';
const SideMenu = ({setAuth, isAuth, user, setUser}) => {
useEffect(()=>{
if(typeof windows === undefined) return;
const item = localStorage.getItem('ltu');
setAuth(!!item);
if(item) setUser(JSON.parse(localStorage.getItem('Ud')))
}, [router, router.isReady])
}
Now I can use the {isAuth, user,} on any page and component.
I am pretty sure this is not the right solution, but I could not find any other working solution and no one here yet posted a answer.

change source in list guesser - React-admin

I'm using React Admin, and I have this result :
As you can see, React admin displays /media_objects/:id.
I would like to display the title instead of the id.
Here is my code :
export const MediaAreasList = props => (
<ListGuesser {...props}>
<FieldGuesser label={labelLabel} source="label" />
<FieldGuesser source="title" label={titleLabel} />
<FieldGuesser source="description" />
<FieldGuesser source="mediaObjects" label={mediaObjectsLabel} />
</ListGuesser>
);
Is there a way to display titles instead of id ?
I didn't find anything in the doc
Thank you !
Do not use ListGuesser in production https://marmelab.com/react-admin/Tutorial.html
you’ll have to replace the ListGuesser component in the users
resource by a custom React component. Fortunately, ListGuesser dumps
the code of the list it has guessed to the console
In your case FieldGuesser for mediaObjects should be replaced with ReferenceManyField component:
<ReferenceManyField label={mediaObjectsLabel} reference="mediaObjects" target="...">
<SingleFieldList>
<ChipField source="title" />
</SingleFieldList>
</ReferenceManyField>
docs: https://marmelab.com/react-admin/ReferenceManyField.html

How can I create a layout that applies to all subfolders in a Next.js app?

I am trying to use .mdx files to easily create custom articles with Next.js.
I currently have this structure:
When going over a category, for example: /articles/math, I am able to show a gallery by using this code in my articles/[category]/index.tsx file:
const Category = () => {
const router = useRouter()
const category: string = router.query.category as string
return (
<Gallery type={category} />
)
}
Would there be a way to specify a layout for all my articles? Additionally, where should the index.tsx file be placed in this case, under articles/[category]/[article]? For example, I would like to achieve something like this:
const Article = () => {
return (
<article className="content-panel">
<div className="article-content">
// The current article information goes here
</div>
</article>
);
}

useWrappedStore missing in next-redux-wrapper

I was trying to implement the next-redux-wrapper with redux-toolkit.
As the example suggests in https://github.com/kirill-konshin/next-redux-wrapper/blob/master/packages/demo-redux-toolkit/pages/_app.tsx.
As the example suggests, the store should be wrapper with the useWrappedStore method. Unfortunately, it's not found anywhere in the library.
const MyApp: FC<AppProps> = ({Component, ...rest}) => {
const {store, props} = wrapper.useWrappedStore(rest);
return (
<Provider store={store}>
<Component {...props.pageProps} />
</Provider>
);
};
export default MyApp;
Anyone have any idea how to solve this?

How to implement a theme switcher on an existing React site

I currently have two theme files, theme.js and theme-dark.js. I also have a complex React-based site that has already been set up, and I cannot find a way to implement a way for a user to switch between the two theme files via some switcher on the site.
This is what my index.js render function looks like:
const rootElement = document.getElementById('root')
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
)
And this is what the relevant code in the App.tsx file looks like:
<ThemeProvider theme={theme}>
<CssBaseline />
<SnackbarProvider
.....
</SnackbarProvider>
</ThemeProvider>
The above code from the App.tsx file is nested in some custom Context provider components and contains some data for loading the initial components of the site.
I'm having some trouble implementing a theme switcher with this existing code to switch between theme.js and theme-dark.js. If anyone could give me a push in the right direction I'd greatly appreciate it. Unfortunately this is about all the actual code I can paste due to security reasons for my company, but I believe the main issue here is that the <Provider> element in index.js breaks when a custom theme provider is provided.
A simple state should suffice the job, but you might need to toggle the state deep down your app, where the switch/button is.
You can pass through with Context, but since you're using redux already, why reinvent the wheel.
Create a reducer for your theme type,
// isDarkModeReducer.js
export default function isDarkModeReducer(state = false, action) {
switch (action.type) {
case 'toggleDarkMode': {
return !state;
}
default:
return state;
}
}
Add it on your rootReducer
// rootReducer.js
...
import isDarkModeReducer from '<location of your isDarkModeReducer reducer>';
...
const rootReducer = combineReducers({
...
isDarkMode: isDarkModeReducer
})
...
On your App.tsx access the isDarkMode value from the created store, and use it to conditionally pass theme.js or theme-dark.js file.
// App.tsx
...
import theme from 'theme.js';
import theme-dark from 'theme-dark.js';
import { useSelector } from 'react-redux'
const isDarkMode = useSelector(state => state.isDarkMode);
...
return (
<ThemeProvider theme={isDarkMode ? theme-dark : theme}>
<CssBaseline />
<SnackbarProvider
.....
</SnackbarProvider>
</ThemeProvider>
);
...
For toggling, all you have to do is dispatch the action toggleDarkMode from wherever your switch button is.
// SwitchButton
import { useDispatch } from 'react-redux'
const dispatch = useDispatch();
const toggleTheme = () => {
dispatch({ type: 'toggleDarkMode' });
};
return (
<button onClick={toggleTheme}>Switch Theme</button>
);
You might also want to save the value to localStorage for persisting, which you can easily do as stated in the docs.

Resources