The Content-Range header is missing in the HTTP Response. The simple REST data provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';
import * as cookieParser from 'cookie-parser';
import * as express from 'express';
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(cookieParser());
app.setGlobalPrefix('api')
app.enableCors({
origin: [process.env.CLIENT_URL],
credentials: true,
exposedHeaders: ['set-cookie'],
});
app.use('/uploads', express.static(join(__dirname, '..', 'uploads')));
const config = new DocumentBuilder()
.setTitle('example')
.setDescription('Тесты api проекта')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);
await app.listen(process.env.PORT! || 4200);
}
bootstrap();
import { Controller, Get, Post, Put, Delete, Body, Param } from '@nestjs/common';
import { TestsService } from './tests.service';
@Controller('tests')
export class TestsController {
constructor(private readonly testsService: TestsService) {}
@Get()
async getList() {
return this.testsService.findAll();
}
@Get(':id')
async getOne(@Param('id') id: string) {
return this.testsService.findOne(id);
}
@Post()
async create(@Body() createDTO: any) {
return this.testsService.create(createDTO);
}
@Put(':id')
async update(@Param('id') id: string, @Body() updateDTO: any) {
return this.testsService.update(id, updateDTO);
}
@Delete(':id')
async delete(@Param('id') id: string) {
return this.testsService.delete(id);
}
}
import { Injectable } from '@nestjs/common';
@Injectable()
export class TestsService {
private tests = []; // Example in-memory storage
findAll() {
return this.tests; // Fetch all tests
}
findOne(id: string) {
return this.tests.find(test => test.id === id); // Find a specific test
}
create(createDTO: any) {
const newTest = { id: Date.now().toString(), ...createDTO };
this.tests.push(newTest);
return newTest; // Create a new test
}
update(id: string, updateDTO: any) {
const testIndex = this.tests.findIndex(test => test.id === id);
if (testIndex > -1) {
this.tests[testIndex] = { ...this.tests[testIndex], ...updateDTO };
return this.tests[testIndex]; // Update an existing test
}
}
delete(id: string) {
this.tests = this.tests.filter(test => test.id !== id); // Delete a test
return { deleted: true }; // Return deletion confirmation
}
}
'use client';
import simpleRestProvider from 'ra-data-simple-rest';
import {
Admin,
Resource,
List,
Create,
Edit,
Show,
SimpleList,
SimpleForm,
TextInput,
Datagrid,
TextField,
EditButton,
DeleteButton,
ShowButton,
} from 'react-admin';
import { useUserStore } from '@/store/use-user-store';
import { redirect } from 'next/navigation';
const dataProvider = simpleRestProvider(
`${process.env.NEXT_PUBLIC_SERVER_URL}/api`
);
const AdminsPage = () => {
const { user, isLoading: isUserLoading } = useUserStore();
if (isUserLoading) return null;
if (!user?.isAdmin) return redirect('/');
return (
<Admin dataProvider={dataProvider}>
<Resource
name='tests'
list={TestList}
create={TestCreate}
edit={TestEdit}
show={TestShow}
/>
</Admin>
);
};
const TestList = props => (
<List {...props}>
<Datagrid>
<TextField source='id' />
<TextField source='title' />
<TextField source='author' />
<EditButton />
<DeleteButton />
<ShowButton />
</Datagrid>
</List>
);
const TestCreate = props => (
<Create {...props}>
<SimpleForm>
<TextInput source='title' />
<TextInput source='author' />
</SimpleForm>
</Create>
);
const TestEdit = props => (
<Edit {...props}>
<SimpleForm>
<TextInput source='title' />
<TextInput source='author' />
</SimpleForm>
</Edit>
);
const TestShow = props => (
<Show {...props}>
<SimpleList
primaryText={record => record.title}
secondaryText={record => record.author}
/>
</Show>
);
export default AdminsPage;